]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from 1.1.x into 1.2 devel.
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 26 Dec 2001 16:52:58 +0000 (16:52 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 26 Dec 2001 16:52:58 +0000 (16:52 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/branches/branch-1.2@1981 7a7537e8-13f0-0310-91df-b6672ffda945

202 files changed:
CHANGES.txt
INSTALL.txt
LICENSE.html
LICENSE.txt
Makedefs.in
Makefile
README.txt
backend/Makefile
backend/ipp.c
backend/lpd.c
backend/parallel.c
backend/serial.c
backend/socket.c
backend/usb.c
berkeley/Makefile
berkeley/lpq.c
berkeley/lpr.c
cgi-bin/Makefile
cgi-bin/admin.c
cgi-bin/template.c
conf/Makefile
conf/cupsd.conf
conf/mime.types
config-scripts/cups-common.m4
config-scripts/cups-compiler.m4
config-scripts/cups-directories.m4
config-scripts/cups-image.m4
config-scripts/cups-libtool.m4
config-scripts/cups-manpages.m4
config-scripts/cups-network.m4
config-scripts/cups-openslp.m4
config-scripts/cups-openssl.m4
config-scripts/cups-opsys.m4
config-scripts/cups-pam.m4
config-scripts/cups-sharedlibs.m4
config.h.in
configure.in
cups-config.in
cups.list [deleted file]
cups.list.in
cups.sh.in
cups.spec
cups/Makefile
cups/cups.h
cups/dest.c
cups/http.c
cups/http.h
cups/ipp.c
cups/ipp.h
cups/language.h
cups/options.c
cups/ppd.c
cups/tempfile.c
cups/testppd.c
cups/util.c
data/Makefile
doc/Makefile
doc/cmp.html
doc/cmp.pdf
doc/idd.html
doc/idd.pdf
doc/ipp.html
doc/ipp.pdf
doc/ipp.shtml
doc/overview.pdf
doc/sam.html
doc/sam.pdf
doc/sam.shtml
doc/sdd.html
doc/sdd.pdf
doc/spm.html
doc/spm.pdf
doc/spm.shtml
doc/sps.html
doc/sps.pdf
doc/ssr.html
doc/ssr.pdf
doc/stp.html
doc/stp.pdf
doc/sum.html
doc/sum.pdf
doc/sum.shtml
doc/svd.html
doc/svd.pdf
filter/Makefile
filter/image-colorspace.c
filter/image-jpeg.c
filter/image.c
filter/imagetops.c
filter/imagetoraster.c
filter/pstops.c
filter/rastertodymo.c
filter/textcommon.c
fonts/Makefile
locale/Makefile
man/Makefile
man/cups-config.man
man/cupsaddsmb.man
man/lp.man
pdftops/Array.cxx
pdftops/Array.h
pdftops/Catalog.cxx
pdftops/Catalog.h
pdftops/CompactFontInfo.h
pdftops/Decrypt.cxx
pdftops/Decrypt.h
pdftops/Dict.cxx
pdftops/Dict.h
pdftops/Error.cxx
pdftops/FontEncoding.cxx
pdftops/FontEncoding.h
pdftops/FontFile.cxx
pdftops/FontFile.h
pdftops/FontInfo.h
pdftops/FormWidget.cxx
pdftops/FormWidget.h
pdftops/Gfx.cxx
pdftops/Gfx.h
pdftops/GfxFont.cxx
pdftops/GfxFont.h
pdftops/GfxState.cxx
pdftops/GfxState.h
pdftops/Lexer.cxx
pdftops/Lexer.h
pdftops/Link.cxx
pdftops/Link.h
pdftops/Makefile
pdftops/Object.cxx
pdftops/Object.h
pdftops/OutputDev.cxx
pdftops/OutputDev.h
pdftops/PDFDoc.cxx
pdftops/PDFDoc.h
pdftops/PSOutputDev.cxx
pdftops/PSOutputDev.h
pdftops/Page.cxx
pdftops/Page.h
pdftops/Params.cxx
pdftops/Params.h
pdftops/Parser.cxx
pdftops/Parser.h
pdftops/README
pdftops/SFont.h
pdftops/StdFontInfo.h
pdftops/Stream.cxx
pdftops/Stream.h
pdftops/T1Font.h
pdftops/TTFont.h
pdftops/XRef.cxx
pdftops/XRef.h
pdftops/config.h
pdftops/configure.in [deleted file]
pdftops/gfile.cxx
pdftops/pdftops.cxx
ppd/Makefile
ppd/deskjet2.ppd
ppd/dymo.ppd
pstoraster/Makefile
pstoraster/gdevcups.c
pstoraster/gscrdp.c
pstoraster/isave.c
pstoraster/pstoraster.c
scheduler/Makefile
scheduler/auth.c
scheduler/auth.h
scheduler/banners.c
scheduler/banners.h
scheduler/cert.c
scheduler/classes.c
scheduler/client.c
scheduler/conf.c
scheduler/conf.h
scheduler/cups-lpd.c
scheduler/cups-polld.c
scheduler/cupsd.h
scheduler/devices.c
scheduler/dirsvc.c
scheduler/dirsvc.h
scheduler/ipp.c
scheduler/job.c
scheduler/listen.c
scheduler/log.c
scheduler/main.c
scheduler/ppds.c
scheduler/printers.c
scheduler/printers.h
scheduler/quotas.c
scheduler/type.c
systemv/Makefile
systemv/accept.c
systemv/cupsaddsmb.c
systemv/lp.c
systemv/lpadmin.c
templates/Makefile
templates/choose-uri.tmpl
templates/jobs.tmpl
templates/option-header.tmpl
templates/printer-accept.tmpl
templates/printer-reject.tmpl
templates/trailer.tmpl
test/Makefile
visualc/config.h

index bafb94a85ca1bd7bb611eaeda02eda1ce5baab88..5fbf7f170a158b4423bb362bc0ac1991e821fdf1 100644 (file)
@@ -1,6 +1,453 @@
-CHANGES.txt - 05/07/2001
+CHANGES.txt - 12/26/2001
 ------------------------
 
+CHANGES IN CUPS V1.2.0a1
+
+
+CHANGES IN CUPS V1.1.13
+
+       - The cups-lpd mini-daemon now supports LPD clients that
+         send multiple control files.
+       - httpConnectEncrypt() now always uses encryption for
+         connections on port 443, since port 443 is reserved
+         for the "https" scheme.
+       - Group authentication via certificates did not work
+         from the web interface for accounts other than
+         "root".       
+       - The serial port backend did not clear the OPOST
+         option, which could cause problems with some printers.
+       - The cups-lpd mini-daemon didn't lookup the client IP
+         address properly.
+       - The parallel backend now identifies the polled and
+         interrupt-driven devices under *BSD.
+       - The scheduler allowed the "always" encryption mode
+         inside a Location, which is not valid.
+       - The CUPS startup script now checks for the timezone
+         information under Linux.
+       - Now also map the sides attribute to the JCLDuplex
+         option (if present) in PPD files.
+       - Updated pdftops to Xpdf 0.93a.
+       - Added support for MD5 passwords under Slackware.
+       - Added new AuthType BasicDigest that does Basic
+         authentication using the MD5 password file managed by
+         the lppasswd command.
+       - The banner page attribute substitution code now
+         retains {name} sequences in banner files when the
+         named attribute is undefined.  Use {?name} to
+         conditionally substitute an IPP attribute.
+       - The scheduler now ensures that the ServerRoot
+         directory and configuration files are owned by and
+         writable by the User and Group in cupsd.conf.
+       - The USB backend now lists all USB printer devices
+         regardless of whether a printer is connected or not. 
+         This allows new USB printers to be connected without
+         restarting cupsd.
+       - Added some more minor performance tweeks to the IPP
+         protocol code to reduce copying and array indexing.
+       - The cupsaddsmb utility now uses the -c option with
+         smbclient and rpcclient to avoid the read length limit
+         for commands on the standard input.
+       - Added an include file to the CRD handling code in
+         pstoraster so that it would compile properly on 64-bit
+         pointer platforms...
+
+
+CHANGES IN CUPS V1.1.12
+
+       - Added "Polish" to the list of known languages for PPD
+         files.
+       - Added missing directory definition to cups-config.
+       - The CUPS-Move-Job operation did not set the
+         destination type for the new destination.
+       - The CUPS-Add-Printer operation did not support the
+         allow=all or deny=none values to clear the per-user
+         printer ACLs.
+       - The SetPrinterAttrs() function did not handle invalid
+         PPD files that were missing the required NickName
+         attribute.  It now looks for NickName, ModelName, and
+         then substitutes the string "Bad PPD File" for the
+         printer-make-and-model attribute.
+
+
+CHANGES IN CUPS V1.1.11
+
+       - Added support for embedded TrueType fonts in PDF
+         files.
+       - Added support for PostScript functions in PDF
+         files.
+       - Added new "cupsaddsmb" utility for exporting
+         CUPS printer drivers to SAMBA/Windows clients.
+       - Added preliminary support for Darwin/MacOS X.
+       - The CUPS-Add-Printer operation no longer allows
+         arbitrary scheme names in device URIs to be used - it
+         now restricts the available schemes to those found in
+         the device list (lpinfo -m).
+       - The ippRead() and ipp_read_file() functions could not
+         handle more than IPP_MAX_VALUES (100) values in a
+         1setOf attribute.  These functions have been updated
+         to dynamically allocate more memory as needed, and the
+         IPP_MAX_VALUES constant now represents the allocation
+         increment.  [this caused some versions of the
+         GIMP-print drivers to fail since the number of media
+         options exceeded 100...]
+       - The scheduler could crash when BrowseShortNames
+         was set to "No".
+       - The scheduler did not prevent MaxClients from being
+         set to 0, which could cause the scheduler to go in an
+         infinite loop when accepting a request.
+       - Made some performance optimizations in the ippRead()
+         functions to make IPP request/response processing
+         faster.
+       - The accept/reject/enable/disable command did not
+         support properly support the "-h" or default
+         server name.
+       - The scheduler did not save the quota configuration
+         when the job-quota-period attribute was set to 0.
+       - The LPDEST and PRINTER environment variables did not
+         support printer instances.
+       - The text filter now handles more types of boldface and
+         underline formatting.
+       - The cupsTempFd() function did not fail if the
+         temporary directory did not exist; this would cause it
+         to loop indefinitely instead of returning an error
+         (-1).
+       - Stopping (disabling) a printer class did not stop jobs
+         from printing to printers in that class.
+       - The cupsGetDests() function was sending the
+         requested-attributes attribute as a name instead of a
+         keyword; this caused a serious performance problem on
+         slower systems since more information had to be
+         transferred from server to client.
+       - The web interfaces did not always quote < and & in
+         things like the job title.  This had the potential for
+         browser-based security violations (on the browser's
+         machine); bug report from SuSE.
+       - The scheduler now treats unauthenticated usernames as
+         case-insensitive when doing quota and allow/deny
+         processing.
+       - The lp command sent the "request ID is ..." message
+         to stderr instead of stdout...
+       - The PostScript filter (pstops) now handles EPS files,
+         adding a showpage command to the files as needed.
+       - The configure script checked for the <stdlib.h> header
+         file before the JPEG libraries; since the JPEG headers
+         can define HAVE_STDLIB_H, the configure check would
+         cause the JPEG check to fail on some systems.
+       - The scheduler now supports localized banner files,
+         using the subdirectory approach, e.g. the "es"
+         subdirectory under /usr/share/cups/banners is used for
+         the Spanish banner files.
+       - Updated the scheduler so it knows the correct
+         language abbreviation to use for all supported
+         PPD LanguageVersion values.  The new code also
+         supports country codes as well, so "English-GB"
+         maps to the "en_GB" locale.
+       - The cups-lpd mini-daemon did not support
+         anonymous printing (no username specified).
+         While the username is REQUIRED by RFC-1179,
+         MacOS clients do not send the REQUIRED username
+         information when printing via LPD.
+       - Added many warning and informational messages
+         to cups-lpd where they were missing.
+       - Added Czech message file contributed by SuSE.
+       - The cups-lpd mini-daemon now returns a non-zero
+         status if an invalid destination or job ID is
+         provided.
+       - The scheduler did not honor the KeepAlive setting in
+         cupsd.conf.
+       - Increased the size of the file read/write buffers to
+         32k.
+       - *BSD static library creation fixes.
+       - Use mkstemps() instead of tmpnam() in pdftops whenever
+         possible.
+       - Added httpGetHostByName() function as a wrapper around
+         gethostbyname() - some implementations of this
+         function do not support IP addresses (e.g. MacOS X.)
+       - Added casts to all printf's of file lengths, since
+         there is currently no standard way of formatting long
+         long values.
+       - The client filename field was not cleared in all
+         instances, resulting in old form data being submitted
+         to CGIs.
+       - The httpConnect*() functions now try all available
+         addresses for a host when connecting for the first
+         time.
+       - The pstoraster filter would "lose" all drawing
+         commands when the PageSize was set but the printer
+         bitmap was  not reallocated.  This was most noticeable
+         with the output from StarOffice 6 beta and would
+         result in a blank page being output...
+       - The IPP backend was sending a PAGE comment even when
+         printing the output from a filter (it should only send
+         page comments when printing files directly...)
+       - The pdftops filter didn't properly map glyph names of
+         embedded Asian TrueType fonts.
+       - Changed the CUPS startup script to look for a program
+         named "cupsd", not just any program with "cupsd" in
+         the name (this caused the apcupsd UPS monitoring
+         daemon to be stopped/restarted...)
+       - The CUPS-Move-Job operation did not change the
+         internal destination name for held jobs, so moved (but
+         held) jobs would still show up as queued on the
+         original destination.
+       - The cups-polld program didn't send the
+         requested-attributes attribute in the
+         CUPS-Get-Printers and CUPS-Get-Classes requests, which
+         made it use more CPU and bandwidth than required.
+       - The scheduler and CUPS API incorrectly added a
+         job-sheets-default attribute for remote printers. This
+         caused banner pages to be omitted from client system
+         prints.
+
+
+CHANGES IN CUPS V1.1.10-1
+
+       - Minor fixes to the filter, systemv, and template
+         makefiles to install files properly.
+
+
+CHANGES IN CUPS V1.1.10
+
+       - Added a driver for DYMO label printers.
+       - Added new ClassifyOverride directive to allow users
+         to override the classification of individual jobs.
+       - Added new BrowseProtocols directive to control which
+         browse protocols are used (currently CUPS and SLP).
+       - Added SLPv2 support (thanks to Matt Peterson for
+         contributing the initial implementation for CUPS.)
+       - Adding a raw printer on a remote CUPS server now
+         correctly redirects PPD file requests to the remote
+         server.
+       - The serial backend now limits writes to 1/10th
+         second worth of data to avoid buffer overflows
+         with some types of flow control.
+       - The scheduler did not properly process PUT requests,
+         so configuration files could not be uploaded to the
+         server.
+       - The scheduler did not strip trailing whitespace on
+         lines in the configuration files.
+       - The httpWrite() function did not transition the PUT
+         request to the HTTP_STATUS state to get the status
+         from the server.
+       - The scheduler did not properly handle trailing null
+         ("-") filters when testing a driver that sent data
+         to the file: pseudo-backend.
+       - The IPP backend now only sends a document-format of
+         "application/vnd.cups-raw" when printing to another
+         CUPS server using a local printer driver or interface
+         script.  Previously the job's document format was
+         used, which was incorrect.
+       - The lpadmin command didn't use the ppd-name attribute
+         with the -m option; this prevented the use of the
+         "raw" model from the command-line.
+       - The pstoraster filter output draft (1-bit) 6-color
+         output in the wrong order; this resulted in yellow
+         being printed instead of black on Stylus Photo
+         printers.
+       - The pdftops filter did not have the Japanese and
+         Chinese text support compiled into it.
+       - The IPP and AppSocket backends did not clear the
+         "waiting for print job to complete" status message,
+         which caused some confusion... :)
+       - The serial backend now opens the port in "no delay"
+         mode to avoid DCD detection problems with some OS's.
+
+
+CHANGES IN CUPS V1.1.9-1
+
+       - The configure script did not substitute the
+         correct user and group names.
+       - The configure script did not use the full path
+         to the install-sh script when it was used.
+       - The pstoraster filter did not correctly support
+         DuplexTumble mode for printers that used flip
+         duplexing.
+       - The cups.list.in file was missing from the
+         distribution.
+       - The New DeskJet series driver did not use the
+         correct OrderDependency for the Duplex option.
+       - Use read() instead of fread() to read piped
+         print files in lpr/lp.  This avoids a bug in the
+         HP-UX 10.20 fread() function.
+       - Updated the pstoraster filter to use the MIPS_FIXADE
+         system call under IRIX to fix bus error problems on
+         R12000 processors (Ghostscript is not 64-bit clean...)
+       - Some Xerox PPD files (most notably the Phaser 790)
+         have illegal whitespace in the option keyword in the
+         OpenUI line.  This caused the PageRegion option to not
+         be recognized properly for the Phaser 790.
+
+
+CHANGES IN CUPS V1.1.9
+
+       - Revamped the configure script to use a modular
+         approach for the various tests.
+       - Added --with-openssl-* options to properly reference
+         the OpenSSL libraries in DSOs.
+       - Added --with-cups-user and --with-cups-group
+         options to specify the default user and group for
+         CUPS.
+       - Added AIX shared library support.
+       - Added AIX device discovery for the serial and
+         parallel ports.
+       - Now use install program or script to install
+         directories, files, and symlinks.
+       - Updated pstops filter to use strict handling of EPS
+         files embedded in a PostScript document.  The %%EOF
+         handling in 1.1.8 caused some dvips files not to
+         print.
+       - Fixed yet another memory allocation bug in pstoraster
+         that would cause it to crash.  This fix also ensures
+         that all memory allocations are done on (at least) a
+         64-bit boundary.
+       - Fixed Digest authentication - httpGetSubField() didn't
+         skip the Digest keyword.
+       - The scheduler did not properly handle Digest
+         authentication with the new multiple-group support.
+       - The scheduler did not allow usernames that were
+         not in the UNIX password file to be used for Digest
+         authentication from passwd.md5.
+       - The scheduler could not scan PPD files that only used
+         a carriage return (i.e. MacOS PPD files); the new code
+         is also about 40% faster, so servers with thousands of
+         PPD files should start much faster now.
+       - The scheduler now stores the PPD file size and
+         modification times in the ppds.dat file, so it can now
+         incrementally update the PPD database from the model
+         directory, resulting in significantly faster startup
+         times.
+       - The lpinfo command did not return a non-zero status
+         code if an error occurred.
+       - Fixed a bug in the scheduler's UpdateJob() function.
+         Basically, all jobs shared the same status buffer, and
+         the "buffer start" pointer could point to 1 byte
+         before the beginning of the buffer.  The new
+         implementation uses a separate buffer for each job and
+         eliminates the buffer start bug.
+       - The IPP backend would send N copies of a document if
+         the receiving device didn't support the copies
+         attribute, even if the upstream driver already added
+         the necessary commands to generate the copies.  This
+         was most noticeable with HP printers where N * N
+         copies would come out instead of N.
+       - The PostScript filter (pstops) did not properly handle
+         duplex printing on inkjet printers that provide this
+         option.  Copies would be put on the front and back
+         sides of the duplexed page, and the filter did not
+         output an even number of pages.
+       - The backends always caught SIGTERM after they
+         connected to the printer.  This prevented raw jobs
+         from being cancelled early.
+       - The cupsSetDests() function now removes any printers,
+         instances, and options that are not defined by the
+         user or server.  This should prevent old system-wide
+         options from being used in individual user accounts.
+       - Updated the EPSON printer driver and added PPDs for
+         the newer EPSON Stylus printers that only support the
+         "ESC i" graphics command.
+       - The lpadmin command didn't allow you to add remote
+         printers to a local class.
+       - The lpadmin command didn't allow you to set the
+         options (quotas, etc.) for a class.
+       - The scheduler did not load or save the
+         job-sheets-default attribute for classes.
+       - The scheduler did not automatically recreate remote
+         printers that were part of a class.
+       - It was possible for a printer class to list the same
+         printer more than once.
+       - The scheduler now makes a backup copy of classes.conf
+         and printers.conf before writing the new file.
+       - The lppasswd program incorrectly asked for a new
+         password when deleting an existing MD5 password
+         account.
+       - The scheduler did not match "/printers/name.ppd"
+         against a location of "/printers/name".
+       - The client code did not always handle HTTP encryption
+         upgrades properly.
+       - The client code now caches the last Digest password so
+         it can retry using a new resource path or nonce value,
+         which are included in the MD5 sum sent to the server. 
+         This should eliminate unnecessary password prompts
+         when using Digest authentication.
+       - The lppasswd command didn't have a man page.
+       - Updated the PJL detection rules to allow the universal
+         escape to occur anywhere in the first 128 bytes of the
+         file.
+       - The cups-polld program would poll servers continuously
+         with no delay if there was an error contacting the
+         server.
+       - The IPP backend would send an empty job-name or
+         requesting-user-name attribute if the corresponding
+         job attribute was an empty string.  While this is
+         allowed by the IPP specification, some HP JetDirect
+         implementations return a client-error-bad-request
+         error if an empty name attribute value is received.
+         The new code only sends these attributes if they are
+         not the empty string.
+       - At least some versions of the HP JetDirect firmware
+         do not correctly implement IPP.  Added additional
+         checks to the IPP backend to eliminate extra,
+         unsupported attributes which should normally be
+         ignored by a compliant IPP device.
+       - The scheduler did not copy the complete list of
+         supported file types into the
+         document-format-supported attribute. This caused
+         clients to not send the local file type (such as
+         application/vnd.cups-raw for raw print files) and the
+         corresponding bad output in some cases.
+       - The scheduler did not fully copy attributes from a
+         set-job-attributes request - string attributes were
+         only referenced, which could cause cupsd to crash
+         or behave irratically.
+       - The lp command didn't send the right value for the
+         job-hold-until attribute when "-H resume" was
+         specified.
+       - The IPP backend now returns as soon as a job is
+         completed or reported as "pending-held".
+       - Added new ImplicitAnyClasses and HideImplicitMembers
+         directives to the cupsd.conf file to make implicit
+         classes more usable/transparent to the user.
+       - Clients can now (with the appropriate authentication)
+         retrieve and update the server configuration files
+         using HTTP GET and PUT requests.
+       - The web interface didn't allow you to modify the
+         location or description of the printer.
+       - The pdftops filter now uses its own temporary file
+         function to work with PDF files using LZW compression
+         (which use the uncompress program or gunzip)
+       - The SystemGroup directive now supports specification of
+         multiple groups.
+       - Added new Include directive to cupsd.conf, a la
+         Apache.
+       - Added new pseudo-driver/PPD called "raw" that can be
+         used to create/convert a raw queue.  This also allows
+         raw queues to be created in the web interface.
+       - The pdftops filter didn't handle image objects that
+         used JPEG and Flate compression together.
+       - The pstops filter counted pages wrong when using the
+         N-up and even/odd printing options.  This prevented
+         the page-ranges option from working properly.
+       - Added another fix to pstoraster for a bus error
+         condition caused by a lack of parenthesis in the
+         Ghostscript code.
+       - Added new "natural-scaling" option which scales the
+         natural size of the image (percent of natural image
+         size instead of percent of page size.)
+       - The lppasswd program is now setuid to the CUPS user
+         instead of root.
+       - The PPD functions did not allow for PPD files that
+         defined the page sizes and margins before the page
+         size options.
+       - The mime.types file now checks for the PJL "LANGUAGE =
+         Postscript" command for PostScript files.
+       - The scheduler did not truncate file: output files.
+       - The PPD file reading code did not handle options with
+         raw quotes (") in the human-readable names.
+       - The pdftops filter now remaps the space character when
+         (bad) PDF files contain a .notdef glyph for the space
+         character.
+
+
 CHANGES IN CUPS V1.1.8
 
        - Updated spec file to generate separate cups-pstoraster
index bcfb5e2654f3219dfe345f9fce9e9295fb8b089b..1a91cdfa905bc3c902cc36c1a8d45b06611dee7a 100644 (file)
@@ -1,4 +1,4 @@
-INSTALL - CUPS v1.1.7 - 05/01/2001
+INSTALL - CUPS v1.2.0 - 12/26/2001
 ----------------------------------
 
 This file describes how to compile and install CUPS from source
@@ -48,11 +48,12 @@ another location:
 
 If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in
 a system default location (typically "/usr/include" and
-"/usr/lib") you'll need to set the CFLAGS, CXXFLAGS, and LDFLAGS
-environment variables prior to running configure:
+"/usr/lib") you'll need to set the CFLAGS, CXXFLAGS, DSOFLAGS,
+and LDFLAGS environment variables prior to running configure:
 
     setenv CFLAGS "-I/some/directory" ENTER
     setenv CXXFLAGS "-I/some/directory" ENTER
+    setenv DSOFLAGS "-L/some/directory" ENTER
     setenv LDFLAGS "-L/some/directory" ENTER
     ./configure ... ENTER
 
@@ -60,6 +61,7 @@ or:
 
     CFLAGS="-I/some/directory"; export CFLAGS ENTER
     CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER
+    DSOFLAGS="-L/some/directory"; export DSOFLAGS ENTER
     LDFLAGS="-L/some/directory"; export LDFLAGS ENTER
     ./configure ... ENTER
 
@@ -72,6 +74,14 @@ SSL and TLS support require the OpenSSL library, available at:
 
     http://www.openssl.org
 
+If the OpenSSL header files and libraries are not in a standard
+location, specify the locations of these files using the
+--with-openssl-includes and --with-openssl-libs directives:
+
+    ./configure --enable-ssl \
+        --with-openssl-includes=/foo/bar/include \
+        --with-openssl-libs=/foo/bar/lib
+
 See the file "ENCRYPTION.txt" for information on using the
 encryption support in CUPS.
 
@@ -79,7 +89,7 @@ Once you have configured things, just type:
 
     make ENTER
 
-or if you have FreeBSD:
+or if you have FreeBSD, NetBSD, or OpenBSD type:
 
     gmake ENTER
 
@@ -94,7 +104,7 @@ your local system:
 
     make install ENTER
 
-or for FreeBSD:
+or for FreeBSD, NetBSD, or OpenBSD:
 
     gmake install ENTER
 
@@ -124,16 +134,19 @@ or
 
     gmake <format> ENTER
 
-for FreeBSD, where <format> is one of the following:
+for FreeBSD, NetBSD, and OpenBSD.  The <format> target is one of
+the following:
 
     epm      - Builds a portable shell script and tar file based
                distribution.  This format will also backup your
               existing printing system if you decide to remove
               CUPS at some future time.
-    rpm      - Builds a RPM binary distribution.
+    aix      - Builds an AIX binary distribution.
+    bsd      - Builds a *BSD binary distribution.
     deb      - Builds a Debian binary distribution.
     depot    - Builds a HP-UX binary distribution.
     pkg      - Builds a Solaris binary distribution.
+    rpm      - Builds a RPM binary distribution.
     tardist  - Builds an IRIX binary distribution.
 
 
index 1bf924e80a4728fcdb9c712abdd0559901780add..da8647fc2a6d52940b265c65433fd8fc820f9b9c 100644 (file)
@@ -24,12 +24,12 @@ licenses follow this introduction.
 
 <P>The GNU LGPL applies to the CUPS API library, located in the "cups"
 subdirectory of the CUPS source distribution and in the
-"/usr/include/cups" directory and "libcups.a", "libcups.sl", or
-"libcups.so" files in the binary distributions.
+"/usr/include/cups" directory and "libcups.a", "libcups_s.a",
+"libcups.sl", or "libcups.so" files in the binary distributions.
 
 <P>The GNU GPL applies to the remainder of the CUPS distribution,
 including the "pstoraster" filter which is based upon GNU Ghostscript
-5.50 and the "pdftops" filter which is based upon Xpdf 0.90.
+5.50 and the "pdftops" filter which is based upon Xpdf 0.93a.
 
 <P>For those not familiar with the GNU GPL, the license basically
 allows you to:
@@ -93,7 +93,7 @@ Fax: +1.415.492.9862<BR>
 EMail: <A HREF="mailto:info@arsoft.com">info@arsoft.com</A>
 </BLOCKQUOTE>
 
-<P>The "pdftops" filter is based on the Xpdf 0.90 software. For binary
+<P>The "pdftops" filter is based on the Xpdf 0.93a software. For binary
 distribution licensing of this software, please contact:
 
 <BLOCKQUOTE>
index e05c0456861809f16c4fb289ca1aae63d9d909a1..a28160c957747e23d68a3a750d18f20e1e0fc1f7 100644 (file)
@@ -17,12 +17,12 @@ General Public License ("GPL") and GNU Library General Public License
 
 The GNU LGPL applies to the CUPS API library, located in the "cups"
 subdirectory of the CUPS source distribution and in the "/usr/include/cups"
-directory and "libcups.a", "libcups.sl", or "libcups.so" files in the binary
-distributions.
+directory and "libcups.a", "libcups_s.a", "libcups.sl", or "libcups.so"
+files in the binary distributions.
 
 The GNU GPL applies to the remainder of the CUPS distribution, including the
 "pstoraster" filter which is based upon GNU Ghostscript 5.50 and the
-"pdftops" filter which is based upon Xpdf 0.90.
+"pdftops" filter which is based upon Xpdf 0.93a.
 
 For those not familiar with the GNU GPL, the license basically allows you
 to:
@@ -75,7 +75,7 @@ contact:
      Fax: +1.415.492.9862
      EMail: info@arsoft.com
 
-The "pdftops" filter is based on the Xpdf 0.90 software. For binary
+The "pdftops" filter is based on the Xpdf 0.93a software. For binary
 distribution licensing of this software, please contact:
 
      Derek B. Noonburg
index 8b5bd4d221bc87b9fbaf15fa4fa5ad457326aac8..731d6ad4ead8bc1d574c5f73c4d6f05c059633c6 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makedefs.in,v 1.36.2.1 2001/05/13 18:37:58 mike Exp $"
+# "$Id: Makedefs.in,v 1.36.2.2 2001/12/26 16:52:05 mike Exp $"
 #
 #   Common makefile definitions for the Common UNIX Printing System (CUPS).
 #
 AR     =       @AR@
 AWK    =       @AWK@
 CC     =       @LIBTOOL@ @CC@
-CHMOD  =       @CHMOD@
-CP     =       @CP@
 CXX    =       @LIBTOOL@ @CXX@
 DSO    =       @DSO@
 HTMLDOC        =       @HTMLDOC@
+INSTALL        =       @INSTALL@
 LIBTOOL        =       @LIBTOOL@
 LN     =       /bin/ln -sf
-MKDIR  =       @MKDIR@ -p
 MV     =       @MV@
 NROFF  =       @NROFF@
 RANLIB =       @RANLIB@
@@ -48,12 +46,19 @@ SHELL       =       /bin/sh
 # Installation programs...
 #
 
-INSTALL_BIN    =       $(LIBTOOL) $(CP)
-INSTALL_DATA   =       $(CP)
-INSTALL_LIB    =       $(LIBTOOL) $(CP)
-INSTALL_MAN    =       $(CP)
-INSTALL_SCRIPT =       $(CP)
-INSTALL_SYSV   =       @INSTALL_SYSV@
+INSTALL_BIN    =       $(LIBTOOL) $(INSTALL) -m 755 -s
+INSTALL_DATA   =       $(INSTALL) -m 644
+INSTALL_DIR    =       $(INSTALL) -d
+INSTALL_LIB    =       $(LIBTOOL) $(INSTALL) -m 755
+INSTALL_MAN    =       $(INSTALL) -m 644
+INSTALL_SCRIPT =       $(INSTALL) -m 755
+
+#
+# Default user and group for the scheduler...
+#
+
+CUPS_USER      =       @CUPS_USER@
+CUPS_GROUP     =       @CUPS_GROUP@
 
 #
 # Libraries...
@@ -64,6 +69,7 @@ LIBCUPSIMAGE =        @LIBCUPSIMAGE@
 LIBJPEG        =       @LIBJPEG@
 LIBMALLOC =    @LIBMALLOC@
 LIBPNG =       @LIBPNG@
+LIBSLP =       @LIBSLP@
 LIBTIFF        =       @LIBTIFF@
 LIBZ   =       @LIBZ@
 
@@ -75,7 +81,7 @@ LIBZ  =       @LIBZ@
 #         extra debug info)
 #
 
-ARFLAGS        =       crvs
+ARFLAGS        =       @ARFLAGS@
 CFLAGS =       @CFLAGS@ -I.. $(OPTIONS)
 CXXFLAGS =     @CXXFLAGS@ -I.. $(OPTIONS)
 DSOFLAGS =     @DSOFLAGS@
@@ -88,6 +94,7 @@ LIBS  =       $(LINKCUPS) $(NETLIBS) @LIBS@
 NETLIBS        =       @NETLIBS@
 OPTIM  =       @OPTIM@
 OPTIONS        =
+PAMLIBS        =       @PAMLIBS@
 SSLLIBS        =       @SSLLIBS@
 
 #
@@ -119,41 +126,44 @@ srcdir            =       @srcdir@
 sysconfdir     =       @sysconfdir@
 top_srcdir     =       @top_srcdir@
 
-AMANDIR                =       @AMANDIR@
-BINDIR         =       @bindir@
-DATADIR                =       @CUPS_DATADIR@
-DOCDIR         =       @CUPS_DOCROOT@
-INCLUDEDIR     =       $(includedir)
+AMANDIR                =       $(BUILDROOT)@AMANDIR@
+BINDIR         =       $(BUILDROOT)@bindir@
+DATADIR                =       $(BUILDROOT)@CUPS_DATADIR@
+DOCDIR         =       $(BUILDROOT)@CUPS_DOCROOT@
+INCLUDEDIR     =       $(BUILDROOT)$(includedir)
 INITDIR                =       @INITDIR@
 INITDDIR       =       @INITDDIR@
-LIBDIR         =       $(libdir)
-LOCALEDIR      =       @CUPS_LOCALEDIR@
-LOGDIR         =       @CUPS_LOGDIR@
-MANDIR         =       @mandir@
-PAMDIR         =       @PAMDIR@
-REQUESTS       =       @CUPS_REQUESTS@
-SBINDIR                =       @sbindir@
-SERVERBIN      =       @CUPS_SERVERBIN@
-SERVERROOT     =       @CUPS_SERVERROOT@
+LIBDIR         =       $(BUILDROOT)$(libdir)
+LOCALEDIR      =       $(BUILDROOT)@CUPS_LOCALEDIR@
+LOGDIR         =       $(BUILDROOT)@CUPS_LOGDIR@
+MANDIR         =       $(BUILDROOT)@mandir@
+PAMDIR         =       $(BUILDROOT)@PAMDIR@
+PMANDIR                =       $(BUILDROOT)@PMANDIR@
+REQUESTS       =       $(BUILDROOT)@CUPS_REQUESTS@
+SBINDIR                =       $(BUILDROOT)@sbindir@
+SERVERBIN      =       $(BUILDROOT)@CUPS_SERVERBIN@
+SERVERROOT     =       $(BUILDROOT)@CUPS_SERVERROOT@
 
 CAT1EXT                =       @CAT1EXT@
+CAT3EXT                =       @CAT3EXT@
 CAT5EXT                =       @CAT5EXT@
 CAT8EXT                =       @CAT8EXT@
 MAN8EXT                =       @MAN8EXT@
+MAN8DIR                =       @MAN8DIR@
 
 #
 # Rules...
 #
 
 .SILENT:
-.SUFFIXES:     .a .c .cxx .h .man .o .0 .1 .1m .5 .8 .z
+.SUFFIXES:     .a .c .cxx .h .man .o .0 .1 .1m .3 .5 .8 .z
 .c.o:
        echo Compiling $<...
        $(CC) $(OPTIM) $(CFLAGS) -c $<
 .cxx.o:
        echo Compiling $<...
        $(CXX) $(OPTIM) $(CXXFLAGS) -c $<
-.man.0 .man.1 .man.1m .man.5 .man.8:
+.man.0 .man.1 .man.1m .man.3 .man.5 .man.8:
        echo Formatting $<...
        $(RM) $@
        $(NROFF) -man $< >$@
@@ -165,5 +175,5 @@ MAN8EXT             =       @MAN8EXT@
        $(MV) t.z $@
 
 #
-# End of "$Id: Makedefs.in,v 1.36.2.1 2001/05/13 18:37:58 mike Exp $"
+# End of "$Id: Makedefs.in,v 1.36.2.2 2001/12/26 16:52:05 mike Exp $"
 #
index db0cfa236b26499eb9b7b3a67773d48c96ec63a3..b40afe2b93c9550eef3d4029b94f370295790113 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.31.2.1 2001/05/13 18:37:58 mike Exp $"
+# "$Id: Makefile,v 1.31.2.2 2001/12/26 16:52:05 mike Exp $"
 #
 #   Top-level Makefile for the Common UNIX Printing System (CUPS).
 #
@@ -74,30 +74,32 @@ install:
        (cd ppd; $(MAKE) $(MFLAGS) install)
        echo Installing in templates...
        (cd templates; $(MAKE) $(MFLAGS) install)
+       echo Installing cups-config script...
+       $(INSTALL_DIR) $(BINDIR)
+       $(INSTALL_SCRIPT) cups-config $(BINDIR)/cups-config
        echo Installing startup script...
        if test "x$(INITDIR)" != "x"; then \
-               $(MKDIR) $(prefix)/$(INITDIR)/init.d; \
-               $(RM) $(prefix)/$(INITDIR)/init.d/cups; \
-               $(INSTALL_SCRIPT) cups.sh $(prefix)/$(INITDIR)/init.d/cups; \
-               $(CHMOD) ugo+rx $(prefix)/$(INITDIR)/init.d/cups; \
-               $(MKDIR) $(prefix)/$(INITDIR)/rc0.d; \
-               $(RM) $(prefix)/$(INITDIR)/rc0.d/K00cups; \
-               ln -s $(INITDDIR)/cups $(prefix)/$(INITDIR)/rc0.d/K00cups; \
-               $(MKDIR) $(prefix)/$(INITDIR)/rc2.d; \
-               $(RM) $(prefix)/$(INITDIR)/rc2.d/S99cups; \
-               ln -s $(INITDDIR)/cups $(prefix)/$(INITDIR)/rc2.d/S99cups; \
-               $(MKDIR) $(prefix)/$(INITDIR)/rc3.d; \
-               $(RM) $(prefix)/$(INITDIR)/rc3.d/S99cups; \
-               ln -s $(INITDDIR)/cups $(prefix)/$(INITDIR)/rc3.d/S99cups; \
-               $(MKDIR) $(prefix)/$(INITDIR)/rc5.d; \
-               $(RM) $(prefix)/$(INITDIR)/rc5.d/S99cups; \
-               ln -s $(INITDDIR)/cups $(prefix)/$(INITDIR)/rc5.d/S99cups; \
+               $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/init.d; \
+               $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/init.d/cups; \
+               $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc0.d; \
+               $(INSTALL_SCRIPT) cups.sh  $(BUILDROOT)$(INITDIR)/rc0.d/K00cups; \
+               $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc2.d; \
+               $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/rc2.d/S99cups; \
+               $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc3.d; \
+               $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/rc3.d/S99cups; \
+               $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc5.d; \
+               $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/rc5.d/S99cups; \
        fi
        if test "x$(INITDIR)" = "x" -a "x$(INITDDIR)" != "x"; then \
-               $(MKDIR) $(prefix)/$(INITDDIR); \
-               $(RM) $(prefix)/$(INITDDIR)/cups; \
-               $(INSTALL_SCRIPT) cups.sh $(prefix)/$(INITDDIR)/cups; \
-               $(CHMOD) ugo+rx $(prefix)/$(INITDDIR)/cups; \
+               $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR); \
+               if test "$(INITDDIR)" = "/System/Library/StartupItems/CUPS"; then \
+                       $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDDIR)/CUPS; \
+                       $(INSTALL_DATA) cups.plist $(BUILDROOT)$(INITDDIR)/StartupParameters.plist; \
+                       $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR)/Resources/English.lproj; \
+                       $(INSTALL_DATA) cups.strings $(BUILDROOT)$(INITDDIR)/Resources/English.lproj/Localizable.strings; \
+               else \
+                       $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDDIR)/cups; \
+               fi \
        fi
 
 
@@ -114,15 +116,13 @@ test:     all
 # Make software distributions using EPM (http://www.easysw.com/epm)...
 #
 
-EPMFLAGS       =       -v \
-                       AMANDIR=$(AMANDIR) \
-                       BINDIR=$(BINDIR) DATADIR=$(DATADIR) \
-                       DOCDIR=$(DOCDIR) INCLUDEDIR=$(INCLUDEDIR) \
-                       LIBDIR=$(LIBDIR) LOCALEDIR=$(LOCALEDIR) \
-                       LOGDIR=$(LOGDIR) MANDIR=$(MANDIR) \
-                       PAMDIR=$(PAMDIR) REQUESTS=$(REQUESTS) \
-                       SBINDIR=$(SBINDIR) SERVERBIN=$(SERVERBIN) \
-                       SERVERROOT=$(SERVERROOT)
+EPMFLAGS       =       -v
+
+aix:
+       epm $(EPMFLAGS) -f aix cups
+
+bsd:
+       epm $(EPMFLAGS) -f bsd cups
 
 epm:
        epm $(EPMFLAGS) cups
@@ -143,5 +143,5 @@ tardist:
        epm $(EPMFLAGS) -f tardist cups
 
 #
-# End of "$Id: Makefile,v 1.31.2.1 2001/05/13 18:37:58 mike Exp $".
+# End of "$Id: Makefile,v 1.31.2.2 2001/12/26 16:52:05 mike Exp $".
 #
index 1dad6ea49960b8da09b2958a6f9e370bce7a8ddc..1a245aeea77796b179a68fdac269c07544cafc10 100644 (file)
@@ -1,4 +1,4 @@
-README - CUPS v1.1.7 - 05/01/2001
+README - CUPS v1.2.0 - 12/26/2001
 ---------------------------------
 
 Looking for compile instructions?  Read the file "INSTALL.txt"
@@ -27,8 +27,8 @@ that are used to support non-PostScript printers.  Sample
 drivers for HP and EPSON printers are included that use these
 filters.
 
-Drivers for over 2300 printers are provided with our ESP Print
-Pro software, available at:
+Drivers for thousands of printers are provided with our ESP
+Print Pro software, available at:
 
        http://www.easysw.com/printpro
 
@@ -55,7 +55,8 @@ SOFTWARE REQUIREMENTS
 The following operating system software is required to install
 one of the binary distributions from Easy Software Products:
 
-    - Digital UNIX (aka OSF1 aka Compaq Tru64 UNIX) 4.0 or higher
+    - AIX 4.3 or higher
+    - Compaq Tru64 UNIX (aka OSF1 aka Digital UNIX) 4.0 or higher
     - HP-UX 10.20 or higher
     - IRIX 5.3 or higher
     - Linux 2.0 with glibc2 or higher
@@ -188,14 +189,20 @@ the following commands:
 
 Similarly, for the other sample drivers you can use:
 
-    Driver                      PPD File
-    --------------------------  ------------
-    HP DeskJet Series           deskjet.ppd
-    HP LaserJet Series          laserjet.ppd
-    EPSON Stylus Color Series   stcolor.ppd
-    EPSON Stylus Photo Series   stphoto.ppd
-    EPSON 9-pin Series          epson9.ppd
-    EPSON 24-pin Series         epson24.ppd
+    Driver                         PPD File
+    -----------------------------  ------------
+    Dymo Label Printers            dymo.ppd
+    EPSON Stylus Color Series      stcolor.ppd
+    EPSON Stylus Photo Series      stphoto.ppd
+    EPSON Stylus New Color Series  stcolor2.ppd
+    EPSON Stylus New Photo Series  stphoto2.ppd
+    EPSON 9-pin Series             epson9.ppd
+    EPSON 24-pin Series            epson24.ppd
+    HP DeskJet Series              deskjet.ppd
+    HP New DeskJet Series          deskjet2.ppd
+    HP LaserJet Series             laserjet.ppd
+    OKIDATA 9-Pin Series           okidata9.ppd
+    OKIDATA 24-Pin Series          okidat24.ppd
 
 These sample drivers provide basic printing capabilities, but
 generally do not exercise the full potential of the printers or
@@ -246,8 +253,8 @@ The PostScript RIP software (pstoraster) is based on the GNU
 Ghostscript 5.50 core, Copyright 1986-1998 by Aladdin
 Enterprises.
 
-The PDF filter (pdftops) is based on the Xpdf 0.90 software,
-Copyright 1996-1999 by Derek B. Noonburg.
+The PDF filter (pdftops) is based on the Xpdf 0.92 software,
+Copyright 1996-2001 by Derek B. Noonburg.
 
 This software is based in part on the work of the Independent
 JPEG Group.
index 6152f31f481c2a7a8ce5f70284f94ba928d99d86..fee32117af79c7f41d9244bed74e5fcf2a93d3b1 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.25.2.1 2001/04/02 19:51:42 mike Exp $"
+# "$Id: Makefile,v 1.25.2.2 2001/12/26 16:52:06 mike Exp $"
 #
 #   Backend makefile for the Common UNIX Printing System (CUPS).
 #
@@ -49,10 +49,10 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(SERVERBIN)/backend
-       $(CHMOD) ugo+rx $(SERVERBIN)
-       $(CHMOD) ugo+rx $(SERVERBIN)/backend
-       $(INSTALL_BIN) $(BACKENDS) $(SERVERBIN)/backend
+       $(INSTALL_DIR) $(SERVERBIN)/backend
+       for file in $(BACKENDS); do \
+               $(INSTALL_BIN) $$file $(SERVERBIN)/backend; \
+       done
        $(RM) $(SERVERBIN)/backend/http
        $(LN) ipp $(SERVERBIN)/backend/http
 
@@ -139,5 +139,5 @@ usb.o:      ../cups/cups.h
 $(OBJS):       ../config.h ../Makedefs
 
 #
-# End of "$Id: Makefile,v 1.25.2.1 2001/04/02 19:51:42 mike Exp $".
+# End of "$Id: Makefile,v 1.25.2.2 2001/12/26 16:52:06 mike Exp $".
 #
index 7c10ea60f8e1766e2ea07822f2e2cbc004c87ec7..6e29cdd2093c22430e55040af66ae31ddfcc8fb7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c,v 1.38.2.1 2001/05/13 18:37:59 mike Exp $"
+ * "$Id: ipp.c,v 1.38.2.2 2001/12/26 16:52:06 mike Exp $"
  *
  *   IPP backend for the Common UNIX Printing System (CUPS).
  *
@@ -408,13 +408,15 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
 
     fprintf(stderr, "DEBUG: printer-uri = \"%s\"\n", uri);
 
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
-                NULL, argv[2]);
+    if (argv[2][0])
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+                  NULL, argv[2]);
 
     fprintf(stderr, "DEBUG: requesting-user-name = \"%s\"\n", argv[2]);
 
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
-                argv[3]);
+    if (argv[3][0])
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+                  argv[3]);
 
     fprintf(stderr, "DEBUG: job-name = \"%s\"\n", argv[3]);
 
@@ -425,7 +427,12 @@ main(int  argc,            /* I - Number of command-line arguments (6 or 7) */
     options     = NULL;
     num_options = cupsParseOptions(argv[5], 0, &options);
 
-    if ((content_type = getenv("CONTENT_TYPE")) != NULL && format_sup != NULL)
+    if (argc > 6)
+      content_type = getenv("CONTENT_TYPE");
+    else
+      content_type = "application/vnd.cups-raw";
+
+    if (content_type != NULL && format_sup != NULL)
     {
       for (i = 0; i < format_sup->num_values; i ++)
         if (strcasecmp(content_type, format_sup->values[i].string.text) == 0)
@@ -436,11 +443,24 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
                                    num_options, &options);
     }
 
-    cupsEncodeOptions(request, num_options, options);
+    if (copies_sup)
+    {
+     /*
+      * Only send options if the destination printer supports the copies
+      * attribute.  This is a hack for the HP JetDirect implementation of
+      * IPP, which does not accept extension attributes and incorrectly
+      * reports a client-error-bad-request error instead of the
+      * successful-ok-unsupported-attributes status.  In short, at least
+      * some HP implementations of IPP are non-compliant.
+      */
+
+      cupsEncodeOptions(request, num_options, options);
+      ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies",
+                    atoi(argv[4]));
+    }
+
     cupsFreeOptions(num_options, options);
 
-    if (copies_sup)
-      ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", atoi(argv[4]));
 
    /*
     * Do the request...
@@ -453,6 +473,8 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
 
     if (ipp_status > IPP_OK_CONFLICT)
     {
+      job_id = 0;
+
       if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
          ipp_status == IPP_PRINTER_BUSY)
       {
@@ -478,7 +500,7 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
     if (response)
       ippDelete(response);
 
-    if (ipp_status <= IPP_OK_CONFLICT)
+    if (ipp_status <= IPP_OK_CONFLICT && argc > 6)
     {
       fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
       copies --;
@@ -558,10 +580,11 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
       else if ((job_state = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL)
       {
        /*
-        * Stop polling if the job is finished...
+        * Stop polling if the job is finished or pending-held...
        */
 
-        if (job_state->values[0].integer > IPP_JOB_PROCESSING)
+        if (job_state->values[0].integer > IPP_JOB_PROCESSING ||
+           job_state->values[0].integer == IPP_JOB_HELD)
        {
          ippDelete(response);
          break;
@@ -600,7 +623,7 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
   */
 
   if (ipp_status <= IPP_OK_CONFLICT)
-    fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+    fputs("INFO: Ready to print.\n", stderr);
 
   return (ipp_status > IPP_OK_CONFLICT);
 }
@@ -620,5 +643,5 @@ password_cb(const char *prompt)     /* I - Prompt (not used) */
 
 
 /*
- * End of "$Id: ipp.c,v 1.38.2.1 2001/05/13 18:37:59 mike Exp $".
+ * End of "$Id: ipp.c,v 1.38.2.2 2001/12/26 16:52:06 mike Exp $".
  */
index 5c4ce282588d2f088d71f69bd7d5d2ab2c91174e..e4f405244f5dbdd26d89298f4212bbe6926c391e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpd.c,v 1.28 2001/03/08 15:13:13 mike Exp $"
+ * "$Id: lpd.c,v 1.28.2.1 2001/12/26 16:52:06 mike Exp $"
  *
  *   Line Printer Daemon backend for the Common UNIX Printing System (CUPS).
  *
@@ -398,7 +398,7 @@ lpd_queue(char *hostname,   /* I - Host to connect to */
   * First try to reserve a port for this connection...
   */
 
-  if ((hostaddr = gethostbyname(hostname)) == NULL)
+  if ((hostaddr = httpGetHostByName(hostname)) == NULL)
   {
     fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s",
             hostname, strerror(errno));
@@ -669,5 +669,5 @@ lpd_write(int  lpd_fd,              /* I - LPD socket */
 
 
 /*
- * End of "$Id: lpd.c,v 1.28 2001/03/08 15:13:13 mike Exp $".
+ * End of "$Id: lpd.c,v 1.28.2.1 2001/12/26 16:52:06 mike Exp $".
  */
index b8474a4cf44ce5d93f23699509e0d368af130a25..a876da9158152199b9b93a95953884f5108fbd15 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: parallel.c,v 1.29 2001/03/23 13:58:17 mike Exp $"
+ * "$Id: parallel.c,v 1.29.2.1 2001/12/26 16:52:07 mike Exp $"
  *
  *   Parallel port backend for the Common UNIX Printing System (CUPS).
  *
@@ -604,11 +604,26 @@ list_devices(void)
     if ((fd = open(device, O_WRONLY)) >= 0)
     {
       close(fd);
-      printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1);
+      printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d (interrupt-driven)\"\n", device, i + 1);
     }
 
     sprintf(device, "/dev/lpa%d", i);
     if ((fd = open(device, O_WRONLY)) >= 0)
+    {
+      close(fd);
+      printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d (polled)\"\n", device, i + 1);
+    }
+  }
+#elif defined(_AIX)
+  int  i;                      /* Looping var */
+  int  fd;                     /* File descriptor */
+  char device[255];            /* Device filename */
+
+
+  for (i = 0; i < 8; i ++)
+  {
+    sprintf(device, "/dev/lp%d", i);
+    if ((fd = open(device, O_WRONLY)) >= 0)
     {
       close(fd);
       printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1);
@@ -619,5 +634,5 @@ list_devices(void)
 
 
 /*
- * End of "$Id: parallel.c,v 1.29 2001/03/23 13:58:17 mike Exp $".
+ * End of "$Id: parallel.c,v 1.29.2.1 2001/12/26 16:52:07 mike Exp $".
  */
index 192bbc2cdd7cfb8db422e75704b28a82a87a3e21..050a1f86288e3e00d80f876db7ccab937435c9f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: serial.c,v 1.32 2001/03/13 14:05:35 mike Exp $"
+ * "$Id: serial.c,v 1.32.2.1 2001/12/26 16:52:07 mike Exp $"
  *
  *   Serial port backend for the Common UNIX Printing System (CUPS).
  *
@@ -189,7 +189,7 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
 
   do
   {
-    if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1)
+    if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL | O_NDELAY)) == -1)
     {
       if (errno == EBUSY)
       {
@@ -212,8 +212,9 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
   tcgetattr(fd, &opts);
 
   opts.c_lflag &= ~(ICANON | ECHO | ISIG);     /* Raw mode */
+  opts.c_oflag &= ~OPOST;                      /* Don't post-process */
 
-  bufsize = 480;       /* 9600 baud / 10 bits/char / 2Hz */
+  bufsize = 96;                /* 9600 baud / 10 bits/char / 10Hz */
   dtrdsr  = 0;         /* No dtr/dsr flow control */
 
   if (options != NULL)
@@ -255,7 +256,7 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
         * Set the baud rate...
        */
 
-        bufsize = atoi(value) / 20;
+        bufsize = atoi(value) / 100;
 
 #if B19200 == 19200
         cfsetispeed(&opts, atoi(value));
@@ -378,6 +379,7 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
     }
 
   tcsetattr(fd, TCSANOW, &opts);
+  fcntl(fd, F_SETFL, 0);
 
  /*
   * Now that we are "connected" to the port, ignore SIGTERM so that we
@@ -476,7 +478,7 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
   }
 
  /*
-  * Close the socket connection and input file and return...
+  * Close the serial port and input file and return...
   */
 
   close(fd);
@@ -852,5 +854,5 @@ list_devices(void)
 
 
 /*
- * End of "$Id: serial.c,v 1.32 2001/03/13 14:05:35 mike Exp $".
+ * End of "$Id: serial.c,v 1.32.2.1 2001/12/26 16:52:07 mike Exp $".
  */
index e48fe08c8668cc2d482292e0f5ed5a935e868c4c..115296bb0a2081054366d692e64b1f0aa0d87c5e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: socket.c,v 1.17.2.1 2001/05/13 18:37:59 mike Exp $"
+ * "$Id: socket.c,v 1.17.2.2 2001/12/26 16:52:07 mike Exp $"
  *
  *   AppSocket backend for the Common UNIX Printing System (CUPS).
  *
@@ -146,7 +146,7 @@ main(int  argc,             /* I - Number of command-line arguments (6 or 7) */
   * Then try to connect to the remote host...
   */
 
-  if ((hostaddr = gethostbyname(hostname)) == NULL)
+  if ((hostaddr = httpGetHostByName(hostname)) == NULL)
   {
     fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n",
             hostname, strerror(errno));
@@ -332,12 +332,12 @@ main(int  argc,           /* I - Number of command-line arguments (6 or 7) */
   if (fp != stdin)
     fclose(fp);
 
-  fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+  fputs("INFO: Ready to print.\n", stderr);
 
   return (0);
 }
 
 
 /*
- * End of "$Id: socket.c,v 1.17.2.1 2001/05/13 18:37:59 mike Exp $".
+ * End of "$Id: socket.c,v 1.17.2.2 2001/12/26 16:52:07 mike Exp $".
  */
index c3ecc700bc71634d861af3907f54528f0d5def28..3d6ea82ae2cef83c52b77f88e4e437a111cfde72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: usb.c,v 1.18 2001/02/08 18:46:00 mike Exp $"
+ * "$Id: usb.c,v 1.18.2.1 2001/12/26 16:52:07 mike Exp $"
  *
  *   USB port backend for the Common UNIX Printing System (CUPS).
  *
@@ -363,35 +363,55 @@ list_devices(void)
     }
 
     fclose(probe);
+
+   /*
+    * Write empty device listings for unused USB devices...
+    */
+
+    for (; i < 16; i ++)
+    {
+      sprintf(device, "/dev/usb/lp%d", i);
+
+      if (access(device, 0))
+      {
+       sprintf(device, "/dev/usb/usblp%d", i);
+
+       if (access(device, 0))
+       {
+         sprintf(device, "/dev/usblp%d", i);
+
+         if (access(device, 0))
+           continue;
+       }
+      }
+
+      printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
+    }
   }
   else
   {
    /*
-    * Just probe manually for USB devices...
+    * Just check manually for USB devices...
     */
 
-    for (i = 0; i < 8; i ++)
+    for (i = 0; i < 16; i ++)
     {
       sprintf(device, "/dev/usb/lp%d", i);
-      if ((fd = open(device, O_WRONLY)) >= 0)
-      {
-       close(fd);
-       printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
-      }
 
-      sprintf(device, "/dev/usb/usblp%d", i);
-      if ((fd = open(device, O_WRONLY)) >= 0)
+      if (access(device, 0))
       {
-       close(fd);
-       printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
-      }
+       sprintf(device, "/dev/usb/usblp%d", i);
 
-      sprintf(device, "/dev/usblp%d", i);
-      if ((fd = open(device, O_WRONLY)) >= 0)
-      {
-       close(fd);
-       printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
+       if (access(device, 0))
+       {
+         sprintf(device, "/dev/usblp%d", i);
+
+         if (access(device, 0))
+           continue;
+       }
       }
+
+      printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
     }
   }
 #elif defined(__sgi)
@@ -400,38 +420,30 @@ list_devices(void)
 #elif defined(__osf)
 #elif defined(__FreeBSD__)
   int   i;                      /* Looping var */
-  int   fd;                     /* File descriptor */
   char  device[255];            /* Device filename */
 
 
   for (i = 0; i < 3; i ++)
   {
     sprintf(device, "/dev/unlpt%d", i);
-    if ((fd = open(device, O_WRONLY)) >= 0)
-    {
-      close(fd);
-      printf("direct usb:%s \"Unknown\" \"USB Port #%d\"\n", device, i + 1);
-    }
+    if (!access(device, 0))
+      printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
   }
 #elif defined(__NetBSD__) || defined(__OpenBSD__)
   int   i;                      /* Looping var */
-  int   fd;                     /* File descriptor */
   char  device[255];            /* Device filename */
 
 
   for (i = 0; i < 3; i ++)
   {
     sprintf(device, "/dev/ulpt%d", i);
-    if ((fd = open(device, O_WRONLY)) >= 0)
-    {
-      close(fd);
-      printf("direct usb:%s \"Unknown\" \"USB Port #%d\"\n", device, i + 1);
-    }
+    if (!access(device, 0))
+      printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
   }
 #endif
 }
 
 
 /*
- * End of "$Id: usb.c,v 1.18 2001/02/08 18:46:00 mike Exp $".
+ * End of "$Id: usb.c,v 1.18.2.1 2001/12/26 16:52:07 mike Exp $".
  */
index ad830e109b6766b2ced9f3323280a2b057e2e036..8ba055ac1aa9c043886f8f4e55d2f98e50f95def 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.13 2001/01/22 15:03:20 mike Exp $"
+# "$Id: Makefile,v 1.13.2.1 2001/12/26 16:52:07 mike Exp $"
 #
 #   Berkeley commands makefile for the Common UNIX Printing System (CUPS).
 #
@@ -48,11 +48,11 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(BINDIR)
-       $(CHMOD) ugo+rx $(BINDIR)
-       $(INSTALL_BIN) lpq lpr lprm $(BINDIR)
-       -$(MKDIR) $(SBINDIR)
-       $(CHMOD) ugo+rx $(SBINDIR)
+       $(INSTALL_DIR) $(BINDIR)
+       $(INSTALL_BIN) lpq $(BINDIR)
+       $(INSTALL_BIN) lpr $(BINDIR)
+       $(INSTALL_BIN) lprm $(BINDIR)
+       $(INSTALL_DIR) $(SBINDIR)
        $(INSTALL_BIN) lpc $(SBINDIR)
 
 
@@ -101,5 +101,5 @@ lprm.o:     ../cups/cups.h ../Makedefs
 
 
 #
-# End of "$Id: Makefile,v 1.13 2001/01/22 15:03:20 mike Exp $".
+# End of "$Id: Makefile,v 1.13.2.1 2001/12/26 16:52:07 mike Exp $".
 #
index cae40a4d31f54e72a0966b81a54c2a87177d7e2b..2de3622177d22e8e4746411a20fb398f7798bf08 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpq.c,v 1.17.2.1 2001/05/13 18:38:00 mike Exp $"
+ * "$Id: lpq.c,v 1.17.2.2 2001/12/26 16:52:08 mike Exp $"
  *
  *   "lpq" command for the Common UNIX Printing System (CUPS).
  *
@@ -72,7 +72,9 @@ main(int  argc,               /* I - Number of command-line arguments */
                longstatus;     /* Show file details */
   int          num_dests;      /* Number of destinations */
   cups_dest_t  *dests;         /* Destinations */
+#ifdef HAVE_LIBSSL
   http_encryption_t encryption;        /* Encryption? */
+#endif /* HAVE_LIBSSL */
 
 
  /*
@@ -536,5 +538,5 @@ show_printer(http_t     *http,      /* I - HTTP connection to server */
 
 
 /*
- * End of "$Id: lpq.c,v 1.17.2.1 2001/05/13 18:38:00 mike Exp $".
+ * End of "$Id: lpq.c,v 1.17.2.2 2001/12/26 16:52:08 mike Exp $".
  */
index 949a9f3cbc6b84ab4311fa1ae53efdc328dbb087..d25b7c35b34f94a621533795ec07ff0740eb99d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpr.c,v 1.20.2.1 2001/05/13 18:38:00 mike Exp $"
+ * "$Id: lpr.c,v 1.20.2.2 2001/12/26 16:52:08 mike Exp $"
  *
  *   "lpr" command for the Common UNIX Printing System (CUPS).
  *
@@ -366,7 +366,7 @@ main(int  argc,             /* I - Number of command-line arguments */
       return (1);
     }
 
-    while ((i = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+    while ((i = read(0, buffer, sizeof(buffer))) > 0)
       write(temp, buffer, i);
 
     i = lseek(temp, 0, SEEK_CUR);
@@ -421,5 +421,5 @@ sighandler(int s)   /* I - Signal number */
 
 
 /*
- * End of "$Id: lpr.c,v 1.20.2.1 2001/05/13 18:38:00 mike Exp $".
+ * End of "$Id: lpr.c,v 1.20.2.2 2001/12/26 16:52:08 mike Exp $".
  */
index 7a4e48729301a3ae6c2aa9b1fdc0fde510076f16..ca74ac487a6212b3f297871f2cfea4d28aee7c9a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.15 2001/02/21 17:01:16 mike Exp $"
+# "$Id: Makefile,v 1.15.2.1 2001/12/26 16:52:08 mike Exp $"
 #
 #   CGI makefile for the Common UNIX Printing System (CUPS).
 #
@@ -50,10 +50,10 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(SERVERBIN)/cgi-bin
-       $(CHMOD) ugo+rx $(SERVERBIN)
-       $(CHMOD) ugo+rx $(SERVERBIN)/cgi-bin
-       $(INSTALL_BIN) $(CGIS) $(SERVERBIN)/cgi-bin
+       $(INSTALL_DIR) $(SERVERBIN)/cgi-bin
+       for file in $(CGIS); do \
+               $(INSTALL_BIN) $$file $(SERVERBIN)/cgi-bin; \
+       done
 
 
 #
@@ -117,5 +117,5 @@ $(OBJS):    ../Makedefs
 
 
 #
-# End of "$Id: Makefile,v 1.15 2001/02/21 17:01:16 mike Exp $".
+# End of "$Id: Makefile,v 1.15.2.1 2001/12/26 16:52:08 mike Exp $".
 #
index bd4fc28eb68b65481a98d22aa073ad50f28072f3..781a800973c48c688973ee080f2175351f041179 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: admin.c,v 1.22.2.1 2001/05/13 18:38:01 mike Exp $"
+ * "$Id: admin.c,v 1.22.2.2 2001/12/26 16:52:08 mike Exp $"
  *
  *   Administration CGI for the Common UNIX Printing System (CUPS).
  *
@@ -549,7 +549,8 @@ do_am_printer(http_t      *http,    /* I - HTTP connection */
   else
     oldinfo = NULL;
 
-  if ((name = cgiGetVariable("PRINTER_NAME")) == NULL)
+  if ((name = cgiGetVariable("PRINTER_NAME")) == NULL ||
+      cgiGetVariable("PRINTER_LOCATION") == NULL)
   {
     if (modify)
     {
@@ -1594,5 +1595,5 @@ get_line(char *buf,       /* I - Line buffer */
 
 
 /*
- * End of "$Id: admin.c,v 1.22.2.1 2001/05/13 18:38:01 mike Exp $".
+ * End of "$Id: admin.c,v 1.22.2.2 2001/12/26 16:52:08 mike Exp $".
  */
index b95e0f356a97fb0341123f4ece33d8f251553a21..088cbb122de9d575b566ab8003a1ba26165cff9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: template.c,v 1.22 2001/01/22 15:03:22 mike Exp $"
+ * "$Id: template.c,v 1.22.2.1 2001/12/26 16:52:09 mike Exp $"
  *
  *   CGI template function.
  *
@@ -480,11 +480,13 @@ cgi_puts(const char *s,
 {
   while (*s)
   {
-    if (s[0] == '<' && s[1] != '/' && !isalpha(s[1]))
+    if (s[0] == '<')
       fputs("&lt;", out);
+    else if (s[0] == '>')
+      fputs("&gt;", out);
     else if (*s == '\"')
       fputs("&quot;", out);
-    else if (s[0] == '&' && isspace(s[1]))
+    else if (s[0] == '&')
       fputs("&amp;", out);
     else
       putc(*s, out);
@@ -495,5 +497,5 @@ cgi_puts(const char *s,
 
 
 /*
- * End of "$Id: template.c,v 1.22 2001/01/22 15:03:22 mike Exp $".
+ * End of "$Id: template.c,v 1.22.2.1 2001/12/26 16:52:09 mike Exp $".
  */
index 47c71ff88beb95a4265803bed7b096d48e8d3cbd..539626579e0d672b6432256b0528154ccd84a18a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.10 2001/01/22 15:03:23 mike Exp $"
+# "$Id: Makefile,v 1.10.2.1 2001/12/26 16:52:09 mike Exp $"
 #
 #   Configuration file makefile for the Common UNIX Printing System (CUPS).
 #
@@ -51,8 +51,7 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(SERVERROOT)
-       $(CHMOD) ugo+rx $(SERVERROOT)
+       $(INSTALL_DIR) $(SERVERROOT)
        for file in $(KEEP); do \
                if test -r $(SERVERROOT)/$$file ; then \
                        $(INSTALL_DATA) $$file $(SERVERROOT)/$$file.N ; \
@@ -69,5 +68,5 @@ install:
 
 
 #
-# End of "$Id: Makefile,v 1.10 2001/01/22 15:03:23 mike Exp $".
+# End of "$Id: Makefile,v 1.10.2.1 2001/12/26 16:52:09 mike Exp $".
 #
index 462abc150280a17014a885f6163dffee13898bc6..e03f97e07981cdeb94e122cb0cb9c7422ae9c482 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: cupsd.conf,v 1.32.2.1 2001/04/02 19:51:42 mike Exp $"
+# "$Id: cupsd.conf,v 1.32.2.2 2001/12/26 16:52:09 mike Exp $"
 #
 #   Sample configuration file for the Common UNIX Printing System (CUPS)
 #   scheduler.
@@ -75,6 +75,7 @@
 # Classification: the classification level of the server.  If set, this
 # classification is displayed on all pages, and raw printing is disabled.
 # The default is the empty string.
+#
 
 #Classification classified
 #Classification confidential
 #Classification topsecret
 #Classification unclassified
 
+#
+# ClassifyOverride: whether to allow users to override the classification
+# on printouts. If enabled, users can limit banner pages to before or
+# after the job, and can change the classification of a job, but cannot
+# completely eliminate the classification or banners.
+#
+# The default is off.
+#
+
+#ClassifyOverride off
+
 #
 # DataDir: the root directory for the CUPS data files.
 # By default /usr/share/cups.
@@ -184,10 +196,10 @@ LogLevel info
 
 #
 # MaxJobs: maximum number of jobs to keep in memory (active and completed.)
-# Default is 0 (no limit.)
+# Default is 500; the value 0 is used for no limit.
 #
 
-#MaxJobs 0
+#MaxJobs 500
 
 #
 # Printcap: the name of the printcap file.  Default is /etc/printcap.
@@ -370,6 +382,25 @@ Port 631
 
 #Browsing On
 
+#
+# BrowseProtocols: which protocols to use for browsing.  Can be
+# any of the following separated by whitespace and/or commas:
+#
+#     all  - Use all supported protocols.
+#     cups - Use the CUPS browse protocol.
+#     slp  - Use the SLPv2 protocol.
+#
+# The default is "cups".
+#
+# NOTE: If you choose to use SLPv2, it is *strongly* recommended that
+#       you have at least one SLP Directory Agent (DA) on your
+#       network.  Otherwise, browse updates can take several seconds,
+#       during which the scheduler will not response to client
+#       requests.
+#
+
+#BrowseProtocols cups
+
 #
 # BrowseAddress: specifies a broadcast address to be used.  By
 # default browsing information is not sent!
@@ -494,6 +525,36 @@ Port 631
 
 #ImplicitClasses On
 
+#
+# ImplicitAnyClasses: whether or not to create "AnyPrinter" implicit
+# classes.
+#
+# When ImplicitAnyClasses is On and a local queue of the same name
+# exists, e.g. "printer", "printer@server1", "printer@server1", then
+# an implicit class called "Anyprinter" is created instead.
+#
+# When ImplicitAnyClasses is Off, implicit classes are not created
+# when there is a local queue of the same name.
+#
+# Disabled by default.
+#
+
+#ImplicitAnyCLasses Off
+
+#
+# HideImplicitMembers: whether or not to show the members of an
+# implicit class.
+#
+# When HideImplicitMembers is On, any remote printers that are
+# part of an implicit class are hidden from the user, who will
+# then only see a single queue even though many queues will be
+# supporting the implicit class.
+#
+# Enabled by default.
+#
+
+#HideImplicitMembers On
+
 
 ########
 ######## Security Options
@@ -654,5 +715,5 @@ Allow From 127.0.0.1
 </Location>
 
 #
-# End of "$Id: cupsd.conf,v 1.32.2.1 2001/04/02 19:51:42 mike Exp $".
+# End of "$Id: cupsd.conf,v 1.32.2.2 2001/12/26 16:52:09 mike Exp $".
 #
index fadc5aad4b4fa7df85319244821cd1c67af7c968..12dc0c7a31e448405aaf00a1893bb4b7fd0d5a6e 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: mime.types,v 1.17.2.1 2001/05/13 18:38:02 mike Exp $"
+# "$Id: mime.types,v 1.17.2.2 2001/12/26 16:52:09 mike Exp $"
 #
 #   MIME types file for the Common UNIX Printing System (CUPS).
 #
@@ -131,6 +131,7 @@ text/plain                  txt printable(0,1024)
 application/vnd.cups-form      string(0,"<CUPSFORM>")
 application/vnd.cups-postscript        string(0,<1B>%-12345X) + \
                                (contains(9,512,"LANGUAGE=POSTSCRIPT") \
+                                contains(9,512,"LANGUAGE = Postscript") \
                                 contains(9,512,"LANGUAGE = POSTSCRIPT"))
 application/vnd.cups-raster    string(0,"RaSt") string(0,"tSaR")
 application/vnd.cups-raw       (string(0,<1B>E) + !string(2,<1B>%0B)) \
@@ -151,5 +152,5 @@ application/vnd.cups-raw    (string(0,<1B>E) + !string(2,<1B>%0B)) \
 #application/octet-stream
 
 #
-# End of "$Id: mime.types,v 1.17.2.1 2001/05/13 18:38:02 mike Exp $".
+# End of "$Id: mime.types,v 1.17.2.2 2001/12/26 16:52:09 mike Exp $".
 #
index e7bf3eec25d9631a754629c1bd4c89e171a8cca0..12e3192529410eaad45914e405bb09c297cb1dfa 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-common.m4,v 1.12 2001/11/02 17:34:54 mike Exp $"
+dnl "$Id: cups-common.m4,v 1.12.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Common configuration stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -150,5 +150,5 @@ esac
 AC_SUBST(ARFLAGS)
 
 dnl
-dnl End of "$Id: cups-common.m4,v 1.12 2001/11/02 17:34:54 mike Exp $".
+dnl End of "$Id: cups-common.m4,v 1.12.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index c5b4a90f3320578a2d1c4e32be32506eebc02899..cdb1c714a5586fb24e4dde43dc9b85b748a43a15 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-compiler.m4,v 1.9 2001/11/02 17:34:54 mike Exp $"
+dnl "$Id: cups-compiler.m4,v 1.9.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Common configuration stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -148,5 +148,5 @@ case $uname in
 esac
 
 dnl
-dnl End of "$Id: cups-compiler.m4,v 1.9 2001/11/02 17:34:54 mike Exp $".
+dnl End of "$Id: cups-compiler.m4,v 1.9.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index dd8cd0ff18eb1f1bfdf0a4f347052f57ecb4e300..b43675641c45a72cc8c50cb8f12ce2fd4a1133bd 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-directories.m4,v 1.5 2001/11/02 17:34:54 mike Exp $"
+dnl "$Id: cups-directories.m4,v 1.5.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Directory stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -232,5 +232,5 @@ dnl Set the CUPS_FONTPATH directory...
 AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$fontpath")
 
 dnl
-dnl End of "$Id: cups-directories.m4,v 1.5 2001/11/02 17:34:54 mike Exp $".
+dnl End of "$Id: cups-directories.m4,v 1.5.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index d861a0d0493bbc6580db0e2bcc14d32ba2a667af..1e6a176fb07ee2bbd4208dc70d4f195ad5a862a5 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-image.m4,v 1.2 2001/10/04 16:50:18 mike Exp $"
+dnl "$Id: cups-image.m4,v 1.2.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Image library stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -68,5 +68,5 @@ LIBS="$SAVELIBS"
 AC_CHECK_HEADER(stdlib.h,AC_DEFINE(HAVE_STDLIB_H))
 
 dnl
-dnl End of "$Id: cups-image.m4,v 1.2 2001/10/04 16:50:18 mike Exp $".
+dnl End of "$Id: cups-image.m4,v 1.2.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index 8329c1d42fa5f2d7b87dacc13df0519f9408b1ea..6904e4bd75b50058b8e86a65558516bab7bdd399 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-libtool.m4,v 1.2 2001/08/06 19:37:09 mike Exp $"
+dnl "$Id: cups-libtool.m4,v 1.2.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Libtool stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -45,5 +45,5 @@ if test x$LIBTOOL != x; then
 fi
 
 dnl
-dnl End of "$Id: cups-libtool.m4,v 1.2 2001/08/06 19:37:09 mike Exp $".
+dnl End of "$Id: cups-libtool.m4,v 1.2.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index 61f0da585e2d98991cce3f6e25e6187a3c150ea3..b418de610aec7068cc62554502d95bbe9f314b00 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-manpages.m4,v 1.5 2001/11/02 17:34:54 mike Exp $"
+dnl "$Id: cups-manpages.m4,v 1.5.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Manpage stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -100,5 +100,5 @@ AC_SUBST(MAN8EXT)
 AC_SUBST(MAN8DIR)
 
 dnl
-dnl End of "$Id: cups-manpages.m4,v 1.5 2001/11/02 17:34:54 mike Exp $".
+dnl End of "$Id: cups-manpages.m4,v 1.5.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index 473996e931b7ae36441a5334a3cd4d57eae400a0..282c13f2871e3c210c7b486a1d416355fab6984f 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-network.m4,v 1.1 2001/06/27 19:06:45 mike Exp $"
+dnl "$Id: cups-network.m4,v 1.1.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Networking stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -32,5 +32,5 @@ fi
 AC_SUBST(NETLIBS)
 
 dnl
-dnl End of "$Id: cups-network.m4,v 1.1 2001/06/27 19:06:45 mike Exp $".
+dnl End of "$Id: cups-network.m4,v 1.1.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index 25a0985e5f9603f76629523c9e335d3f15663444..c077e06eba6488d8aa8fe06659718703d4a06a75 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-openslp.m4,v 1.2 2001/07/24 20:23:03 mike Exp $"
+dnl "$Id: cups-openslp.m4,v 1.2.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   OpenSLP configuration stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -43,5 +43,5 @@ AC_SUBST(LIBSLP)
 
 
 dnl
-dnl End of "$Id: cups-openslp.m4,v 1.2 2001/07/24 20:23:03 mike Exp $".
+dnl End of "$Id: cups-openslp.m4,v 1.2.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index 1177c9b5221f906962de14c039ac0a6496a35bda..7aea86c05ba9b3748d75e06666fc4fa3e7dfb1bf 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-openssl.m4,v 1.4 2001/07/24 20:23:03 mike Exp $"
+dnl "$Id: cups-openssl.m4,v 1.4.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   OpenSSL stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -65,5 +65,5 @@ fi
 AC_SUBST(SSLLIBS)
 
 dnl
-dnl End of "$Id: cups-openssl.m4,v 1.4 2001/07/24 20:23:03 mike Exp $".
+dnl End of "$Id: cups-openssl.m4,v 1.4.2.1 2001/12/26 16:52:10 mike Exp $".
 dnl
index 17b7dea299d9d9c1f3b5165719fdf831531e702e..eef9c8157931b2a38adf80b93009aafedd94aebf 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-opsys.m4,v 1.5 2001/07/24 20:23:03 mike Exp $"
+dnl "$Id: cups-opsys.m4,v 1.5.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
 dnl   Operating system stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -81,5 +81,5 @@ AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USER, "$CUPS_USER")
 AC_DEFINE_UNQUOTED(CUPS_DEFAULT_GROUP, "$CUPS_GROUP")
 
 dnl
-dnl "$Id: cups-opsys.m4,v 1.5 2001/07/24 20:23:03 mike Exp $"
+dnl "$Id: cups-opsys.m4,v 1.5.2.1 2001/12/26 16:52:10 mike Exp $"
 dnl
index 7beeba872599a7e51ceda028d8942afd02b7c249..4cfc2df183216738503ded1babe5cf1d2cbc5f4e 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-pam.m4,v 1.2 2001/07/24 20:23:03 mike Exp $"
+dnl "$Id: cups-pam.m4,v 1.2.2.1 2001/12/26 16:52:11 mike Exp $"
 dnl
 dnl   PAM stuff for the Common UNIX Printing System (CUPS).
 dnl
@@ -55,5 +55,5 @@ AC_SUBST(PAMDIR)
 AC_SUBST(PAMLIBS)
 
 dnl
-dnl End of "$Id: cups-pam.m4,v 1.2 2001/07/24 20:23:03 mike Exp $".
+dnl End of "$Id: cups-pam.m4,v 1.2.2.1 2001/12/26 16:52:11 mike Exp $".
 dnl
index 13bf562cf03f85a1bf8a1fe016985a2455cf8a1e..05a42c7b9ff1bbb14d2ab6de5f302958d82338b9 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: cups-sharedlibs.m4,v 1.6 2001/10/26 03:16:47 mike Exp $"
+dnl "$Id: cups-sharedlibs.m4,v 1.6.2.1 2001/12/26 16:52:11 mike Exp $"
 dnl
 dnl   Shared library support for the Common UNIX Printing System (CUPS).
 dnl
@@ -30,26 +30,26 @@ AC_ARG_ENABLE(shared, [  --enable-shared         turn on shared libraries [defau
 if test x$enable_shared != xno; then
        case "$uname" in
                SunOS* | UNIX_S*)
-                       LIBCUPS="libcups.so.2"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
+                       LIBCUPS="libcups.so.3"
+                       LIBCUPSIMAGE="libcupsimage.so.3"
                        DSO="\$(CC)"
                        DSOFLAGS="$DSOFLAGS -Wl,-h,\$@ -G \$(OPTIM)"
                        ;;
                HP-UX*)
-                       LIBCUPS="libcups.sl.2"
-                       LIBCUPSIMAGE="libcupsimage.sl.2"
+                       LIBCUPS="libcups.sl.3"
+                       LIBCUPSIMAGE="libcupsimage.sl.3"
                        DSO="ld"
                        DSOFLAGS="$DSOFLAGS -b -z +h \$@"
                        ;;
                OSF1* | Linux* | IRIX* | FreeBSD* | NetBSD* | OpenBSD*)
-                       LIBCUPS="libcups.so.2"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
+                       LIBCUPS="libcups.so.3"
+                       LIBCUPSIMAGE="libcupsimage.so.3"
                        DSO="\$(CC)"
                        DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)"
                        ;;
                Darwin*)
-                       LIBCUPS="libcups.2.dylib"
-                       LIBCUPSIMAGE="libcupsimage.2.dylib"
+                       LIBCUPS="libcups.3.dylib"
+                       LIBCUPSIMAGE="libcupsimage.3.dylib"
                        DSO="ld"
                        DSOFLAGS="$DSOFLAGS -dylib /usr/lib/dylib1.o -lc"
                        ;;
@@ -62,8 +62,8 @@ 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"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
+                       LIBCUPS="libcups.so.3"
+                       LIBCUPSIMAGE="libcupsimage.so.3"
                        DSO="\$(CC)"
                        DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)"
                        ;;
@@ -141,5 +141,5 @@ AC_SUBST(DSOLIBS)
 AC_SUBST(IMGLIBS)
 
 dnl
-dnl End of "$Id: cups-sharedlibs.m4,v 1.6 2001/10/26 03:16:47 mike Exp $".
+dnl End of "$Id: cups-sharedlibs.m4,v 1.6.2.1 2001/12/26 16:52:11 mike Exp $".
 dnl
index 369de49c62d0f5ee2b24d59a090709339fe918d2..cc8798850c54553bcf604da5227e94ef8661e016 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: config.h.in,v 1.39.2.2 2001/05/13 18:37:58 mike Exp $"
+ * "$Id: config.h.in,v 1.39.2.3 2001/12/26 16:52:05 mike Exp $"
  *
  *   Configuration file for the Common UNIX Printing System (CUPS).
  *
 
 #define CUPS_SVERSION  "CUPS v1.2.0"
 
+
+/*
+ * Default user and group...
+ */
+
+#define CUPS_DEFAULT_USER      "lp"
+#define CUPS_DEFAULT_GROUP     "sys"
+
+
 /*
  * Where are files stored?
  */
 #define CUPS_DATADIR    "/usr/share/cups"
 #define CUPS_FONTPATH  "/usr/share/cups/fonts"
 
+
 /*
  * What is the format string for strftime?
  */
 
 #define CUPS_STRFTIME_FORMAT   NULL
 
+
 /*
  * Do we have various image libraries?
  */
 #undef HAVE_LIBJPEG
 #undef HAVE_LIBTIFF
 
+
 /*
  * Does this machine store words in big-endian (MSB-first) order?
  */
 
 #undef WORDS_BIGENDIAN
 
+
 /*
  * Which directory functions and headers do we use?
  */
@@ -73,6 +86,7 @@
 #undef HAVE_SYS_NDIR_H
 #undef HAVE_NDIR_H
 
+
 /*
  * Do we have PAM stuff?
  */
 #define HAVE_LIBPAM 0
 #endif /* !HAVE_LIBPAM */
 
+
 /*
  * Do we have <shadow.h>?
  */
 
 #undef HAVE_SHADOW_H
 
+
 /*
  * Do we have <crypt.h>?
  */
 
 #undef HAVE_CRYPT_H
 
+
 /*
  * Use <string.h>, <strings.h>, or both?
  */
 #undef HAVE_STRING_H
 #undef HAVE_STRINGS_H
 
+
 /*
  * Do we have the strXXX() functions?
  */
 #undef HAVE_STRCASECMP
 #undef HAVE_STRNCASECMP
 
+
 /*
  * Do we have the vsyslog() function?
  */
 
 #undef HAVE_VSYSLOG
 
+
 /*
  * Do we have the (v)snprintf() functions?
  */
 #undef HAVE_SNPRINTF
 #undef HAVE_VSNPRINTF
 
+
 /*
  * What signal functions to use?
  */
 #undef HAVE_SIGSET
 #undef HAVE_SIGACTION
 
+
 /*
  * What wait functions to use?
  */
 #undef HAVE_WAITPID
 #undef HAVE_WAIT3
 
+
 /*
  * Do we have the mallinfo function and malloc.h?
  */
 #undef HAVE_MALLINFO
 #undef HAVE_MALLOC_H
 
+
 /*
  * Do we have the OpenSSL library?
  */
 
 #undef HAVE_LIBSSL
 
+
+/*
+ * Do we have the OpenSLP library?
+ */
+
+#undef HAVE_LIBSLP
+
+
 /*
  * Do we have <sys/ioctl.h>?
  */
 
 #undef HAVE_SYS_IOCTL_H
 
+
+/*
+ * Do we have mkstemp() and/or mkstemps()?
+ */
+
+#undef HAVE_MKSTEMP
+#undef HAVE_MKSTEMPS
+
+
+/*
+ * Does the "tm" structure contain the "tm_gmtoff" member?
+ */
+
+#undef HAVE_TM_GMTOFF
+
+
 /*
- * End of "$Id: config.h.in,v 1.39.2.2 2001/05/13 18:37:58 mike Exp $".
+ * End of "$Id: config.h.in,v 1.39.2.3 2001/12/26 16:52:05 mike Exp $".
  */
index 0491dcdf31a8052064dd914652110aee51fd8db0..344d3e63bb175c7052f8bbf103117df006ce2f28 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl "$Id: configure.in,v 1.83.2.2 2001/05/13 18:37:58 mike Exp $"
+dnl "$Id: configure.in,v 1.83.2.3 2001/12/26 16:52:05 mike Exp $"
 dnl
 dnl   Configuration script for the Common UNIX Printing System (CUPS).
 dnl
@@ -23,680 +23,26 @@ dnl         WWW: http://www.cups.org
 dnl
 
 AC_INIT(cups/cups.h)
-AC_CONFIG_HEADER(config.h)
-AC_PREFIX_DEFAULT(/)
 
-dnl Get the operating system and version number...
+sinclude(config-scripts/cups-opsys.m4)
+sinclude(config-scripts/cups-common.m4)
+sinclude(config-scripts/cups-directories.m4)
+sinclude(config-scripts/cups-manpages.m4)
 
-uname=`uname`
-uversion=`uname -r | sed -e '1,$s/[[^0-9]]//g'`
-if test "$uname" = "IRIX64"; then
-    uname="IRIX"
-fi
+sinclude(config-scripts/cups-sharedlibs.m4)
+sinclude(config-scripts/cups-libtool.m4)
+sinclude(config-scripts/cups-compiler.m4)
 
-dnl Clear the debugging and non-shared library options unless the user asks
-dnl for them...
+sinclude(config-scripts/cups-image.m4)
+sinclude(config-scripts/cups-network.m4)
+sinclude(config-scripts/cups-openslp.m4)
+sinclude(config-scripts/cups-openssl.m4)
+sinclude(config-scripts/cups-pam.m4)
 
-OPTIM=""
-AC_SUBST(OPTIM)
-PICFLAG=1
-CFLAGS="${CFLAGS:=}"
-CXXFLAGS="${CXXFLAGS:=}"
-DSOFLAGS="${DSOFLAGS:=}"
-AC_SUBST(DSOFLAGS)
+AC_OUTPUT(Makedefs cups.list cups.sh cups-config)
 
-AC_ARG_ENABLE(debug, [  --enable-debug        turn on debugging [default=no]],[if eval "test x$enable_debug = xyes"; then
-       OPTIM="-g"
-fi])
-AC_ARG_ENABLE(shared, [  --enable-shared        turn on shared libraries [default=yes]])
-AC_ARG_ENABLE(ssl, [  --enable-ssl           turn on SSL/TLS support [default=yes]])
-AC_ARG_ENABLE(libtool_unsupported, [  --enable-libtool-unsupported=LIBTOOL_PATH
-                          turn on building with libtool (UNSUPPORTED!) [default=no]],[if eval "test x$enable_libtool_unsupported != xno"; then
-       LIBTOOL="$enable_libtool_unsupported"
-       enable_shared=no
-       echo "WARNING: libtool is not supported or endorsed by Easy Software Products."
-       echo "         WE DO NOT PROVIDE TECHNICAL SUPPORT FOR LIBTOOL PROBLEMS."
-       echo "         (even if you have a support contract)"
-else
-       LIBTOOL=""
-fi])
-
-if test "$enable_shared" != "no"; then
-       case "$uname" in
-               SunOS* | UNIX_S*)
-                       LIBCUPS="libcups.so.3"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
-                       DSO="\$(CC)"
-                       DSOFLAGS="$DSOFLAGS -Wl,-h,\$@ -G \$(OPTIM)"
-                       ;;
-               HP-UX*)
-                       LIBCUPS="libcups.sl.3"
-                       LIBCUPSIMAGE="libcupsimage.sl.2"
-                       DSO="ld"
-                       DSOFLAGS="$DSOFLAGS -b -z +h \$@"
-                       ;;
-               FreeBSD* | NetBSD* | OpenBSD*)
-                       LIBCUPS="libcups.so.3"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
-                       DSO="\$(CC)"
-                       DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)"
-                       ;;
-               OSF1* | Linux*)
-                       LIBCUPS="libcups.so.3"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
-                       DSO="\$(CC)"
-                       DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)"
-                       ;;
-               IRIX*)
-                       LIBCUPS="libcups.so.3"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
-                       DSO="\$(CC)"
-                       DSOFLAGS="$DSOFLAGS -soname \$@ -shared \$(OPTIM)"
-                       ;;
-               AIX*)
-                       AC_MSG_WARN(Shared library support for AIX not available yet - defaulting to static)
-                       enable_shared=no
-                       PICFLAG=0
-                       LIBCUPS="libcups.a"
-                       LIBCUPSIMAGE="libcupsimage.a"
-                       DSO=":"
-                       ;;
-               *)
-                       echo "Warning: shared libraries may not be supported.  Trying -shared"
-                       echo "         option with compiler."
-                       LIBCUPS="libcups.so.3"
-                       LIBCUPSIMAGE="libcupsimage.so.2"
-                       DSO="\$(CC)"
-                       DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)"
-                       ;;
-       esac
-else
-       PICFLAG=0
-       LIBCUPS="libcups.a"
-       LIBCUPSIMAGE="libcupsimage.a"
-       DSO=":"
-fi
-
-if test "$LIBTOOL" != ""; then
-       LIBCUPS="libcups.la"
-       LIBCUPSIMAGE="libcupsimage.la"
-       LINKCUPS="../cups/\$(LIBCUPS)"
-       LINKCUPSIMAGE="../filter/\$(LIBCUPSIMAGE)"
-       DSO=":"
-       DSOFLAGS=""
-else
-       LINKCUPS="-L../cups -lcups"
-       LINKCUPSIMAGE="-L../filter -lcupsimage"
-fi
-
-AC_ARG_ENABLE(pam, [  --enable-pam        turn on PAM support [default=yes]])
-
-# Don't use PAM with AIX...
-if test $uname = AIX; then
-       enable_pam=no
-fi
-
-AC_ARG_WITH(fontpath, [  --with-fontpath     set font path for pstoraster],fontpath="$withval",fontpath="")
-AC_ARG_WITH(docdir, [  --with-docdir       set path for documentation],docdir="$withval",docdir="")
-AC_ARG_WITH(logdir, [  --with-logdir       set path for log files],logdir="$withval",logdir="")
-
-dnl Checks for programs...
-AC_PROG_AWK
-AC_PROG_CC
-AC_PROG_CXX
-AC_PROG_CPP
-AC_PROG_RANLIB
-AC_PATH_PROG(AR,ar)
-AC_PATH_PROG(CHMOD,chmod)
-AC_PATH_PROG(CHOWN,chown)
-AC_PATH_PROG(CP,cp)
-AC_PATH_PROG(MV,mv)
-AC_PATH_PROG(NROFF,nroff)
-if test "$NROFF" = ""; then
-    AC_PATH_PROG(GROFF,groff)
-    if test "$GROFF" = ""; then
-        NROFF="echo"
-    else
-        NROFF="$GROFF -T ascii"
-    fi
-fi
-AC_PATH_PROG(HTMLDOC,htmldoc)
-AC_PATH_PROG(MKDIR,mkdir)
-AC_PATH_PROG(RM,rm)
-AC_PATH_PROG(SED,sed)
-
-dnl Architecture checks...
-AC_C_BIGENDIAN
-
-dnl Check for libraries...
-AC_CHECK_LIB(c,crypt,LIBS="$LIBS")
-if test "$ac_cv_lib_c_crypt" = "no"; then
-       AC_CHECK_LIB(crypt,crypt)
-fi
-AC_CHECK_LIB(sec,getspent)
-
-LIBMALLOC=""
-AC_CHECK_LIB(c,mallinfo,LIBS="$LIBS"; AC_DEFINE(HAVE_MALLINFO),LIBS="$LIBS")
-if test "$ac_cv_lib_c_mallinfo" = "no"; then
-       AC_CHECK_LIB(malloc,mallinfo,
-                    LIBS="$LIBS"
-                    LIBMALLOC="-lmalloc"
-                    AC_DEFINE(HAVE_MALLINFO),
-                    LIBS="$LIBS")
-fi
-AC_SUBST(LIBMALLOC)
-
-if test "$enable_pam" != "no"; then
-       OLDLIBS="$LIBS"
-       AC_CHECK_LIB(dl,dlopen)
-       AC_CHECK_LIB(pam,pam_start)
-       if test "$ac_cv_lib_pam_pam_start" != "no"; then
-               PAMDIR="/etc/pam.d"
-       else
-               PAMDIR=""
-               LIBS="$OLDLIBS"
-       fi
-       AC_SUBST(PAMDIR)
-fi
-
-NETLIBS=""
-AC_SUBST(NETLIBS)
-AC_CHECK_LIB(socket,socket,
-if test "$uname" != "IRIX"; then
-       NETLIBS="-lsocket"
-else
-       echo "Not using -lsocket since you are running IRIX."
-fi)
-AC_CHECK_LIB(nsl,gethostbyaddr,
-if test "$uname" != "IRIX"; then
-       NETLIBS="$NETLIBS -lnsl"
-else
-       echo "Not using -lnsl since you are running IRIX."
-fi)
-
-dnl Encryption support...
-
-SSLLIBS=""
-AC_SUBST(SSLLIBS)
-
-if test "$enable_ssl" != "no"; then
-       dnl Save the current libraries so the crypto stuff isn't always
-       dnl included...
-       SAVELIBS="$LIBS"
-
-       dnl Some ELF systems can't resolve all the symbols in libcrypto
-       dnl if libcrypto was linked against RSAREF, and fail to link the
-       dnl test program correctly, even though a correct installation
-       dnl of OpenSSL exists.  So we test the linking three times in
-       dnl case the RSAREF libraries are needed.
-
-       for libcrypto in \
-               "-lcrypto" \
-               "-lcrypto -lrsaref" \
-               "-lcrypto -lRSAglue -lrsaref"
-       do
-               AC_CHECK_LIB(ssl,SSL_new,
-                       [SSLLIBS="-lssl $libcrypto"
-                        AC_DEFINE(HAVE_LIBSSL)],,
-                       $libcrypto
-               )
-               if test "x${SSLLIBS}" != "x"; then
-                       break
-               fi
-       done
-
-       LIBS="$SAVELIBS"
-fi
-
-dnl Save the current libraries since we don't want the image libraries
-dnl included with every program...
-SAVELIBS="$LIBS"
-
-dnl Check for image libraries...
-LIBJPEG=""
-LIBPNG=""
-LIBTIFF=""
-LIBZ=""
-
-AC_SUBST(LIBJPEG)
-AC_SUBST(LIBPNG)
-AC_SUBST(LIBTIFF)
-AC_SUBST(LIBZ)
-
-AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
-    AC_DEFINE(HAVE_LIBJPEG)
-    LIBJPEG="-ljpeg"
-    LIBS="$LIBS -ljpeg")
-
-AC_CHECK_LIB(z, gzgets,
-    AC_DEFINE(HAVE_LIBZ)
-    LIBZ="-lz"
-    LIBS="$LIBS -lz")
-
-dnl PNG library uses math library functions...
-AC_CHECK_LIB(m, pow)
-
-AC_CHECK_LIB(png, png_set_tRNS_to_alpha,
-    AC_DEFINE(HAVE_LIBPNG)
-    LIBPNG="-lpng")
-
-AC_CHECK_LIB(tiff, TIFFReadScanline,
-    AC_DEFINE(HAVE_LIBTIFF)
-    LIBTIFF="-ltiff")
-
-dnl Restore original LIBS settings...
-LIBS="$SAVELIBS"
-
-dnl Checks for header files.
-AC_HEADER_STDC
-AC_HEADER_DIRENT
-AC_CHECK_HEADER(crypt.h,AC_DEFINE(HAVE_CRYPT_H))
-AC_CHECK_HEADER(malloc.h,AC_DEFINE(HAVE_MALLOC_H))
-AC_CHECK_HEADER(shadow.h,AC_DEFINE(HAVE_SHADOW_H))
-AC_CHECK_HEADER(stddef.h,AC_DEFINE(HAVE_STDDEF_H))
-AC_CHECK_HEADER(stdlib.h,AC_DEFINE(HAVE_STDLIB_H))
-AC_CHECK_HEADER(string.h,AC_DEFINE(HAVE_STRING_H))
-AC_CHECK_HEADER(strings.h,AC_DEFINE(HAVE_STRINGS_H))
-AC_CHECK_HEADER(usersec.h,AC_DEFINE(HAVE_USERSEC_H))
-AC_CHECK_HEADER(sys/ioctl.h,AC_DEFINE(HAVE_SYS_IOCTL_H))
-
-dnl Checks for string functions.
-AC_CHECK_FUNCS(strdup)
-AC_CHECK_FUNCS(strcasecmp)
-AC_CHECK_FUNCS(strncasecmp)
-if test "$uname" = "HP-UX" -a "$uversion" = "1020"; then
-       echo Forcing snprintf emulation for HP-UX.
-else
-       AC_CHECK_FUNCS(snprintf)
-       AC_CHECK_FUNCS(vsnprintf)
-fi
-
-dnl Check OS version and use appropriate format string for strftime...
-AC_MSG_CHECKING(for correct format string to use with strftime)
-
-case "$uname" in
-       IRIX* | SunOS*)
-               # IRIX and SunOS
-               AC_MSG_RESULT(NULL)
-               AC_DEFINE(CUPS_STRFTIME_FORMAT, NULL)
-               ;;
-       *)
-               # All others
-               AC_MSG_RESULT("%c")
-               AC_DEFINE(CUPS_STRFTIME_FORMAT, "%c")
-               ;;
-esac
-
-dnl Checks for vsyslog function.
-AC_CHECK_FUNCS(vsyslog)
-
-dnl Checks for signal functions.
-if test "$uname" != "Linux"; then
-       AC_CHECK_FUNCS(sigset)
-fi
-
-AC_CHECK_FUNCS(sigaction)
-
-dnl Checks for wait functions.
-AC_CHECK_FUNCS(waitpid)
-AC_CHECK_FUNCS(wait3)
-
-dnl Update compiler options...
-if test -n "$GCC"; then
-       CXX="$CC"
-
-       if test -z "$OPTIM"; then
-               OPTIM="-O2"
-       fi
-       if test $PICFLAG = 1; then
-               OPTIM="-fPIC $OPTIM"
-       fi
-       OPTIM="-Wall $OPTIM"
-else
-       case $uname in
-               AIX*)
-                       if test -z "$OPTIM"; then
-                               OPTIM="-O2 -qmaxmem=6000"
-                       fi
-                       ;;
-               HP-UX*)
-                       if test -z "$OPTIM"; then
-                               OPTIM="+O2"
-                       fi
-                       CFLAGS="-Ae $CFLAGS"
-                       OPTIM="+DAportable $OPTIM"
-                       if test $PICFLAG = 1; then
-                               OPTIM="+z $OPTIM"
-                       fi
-                       ;;
-               IRIX*)
-                       if test -z "$OPTIM"; then
-                               OPTIM="-O2"
-                       fi
-                       if test $uversion -ge 62; then
-                               OPTIM="$OPTIM -n32 -mips3"
-                       fi
-                       OPTIM="-fullwarn $OPTIM"
-                       ;;
-               SunOS*)
-                       # Solaris
-                       if test -z "$OPTIM"; then
-                               OPTIM="-xO4"
-                       fi
-                       OPTIM="$OPTIM -xarch=generic"
-                       if test $PICFLAG = 1; then
-                               OPTIM="-KPIC $OPTIM"
-                       fi
-                       ;;
-               *)
-                       # Running some other operating system; inform the user they
-                       # should contribute the necessary options to
-                       # cups-support@cups.org...
-                       echo "Building CUPS with default compiler optimizations; contact"
-                       echo "cups-support@cups.org with uname and compiler options needed"
-                       echo "for your platform, or set the CFLAGS environment variable"
-                       echo "before running configure."
-                       ;;
-       esac
-fi
-
-if test "$DSO" != ":"; then
-       # When using DSOs the image libraries are linked to libcupsimage.so
-       # rather than to the executables.  This makes things smaller if you
-       # are using any static libraries, and it also allows us to distribute
-       # a single DSO rather than a bunch...
-       DSOLIBS="\$(LIBPNG) \$(LIBTIFF) \$(LIBJPEG) \$(LIBZ)"
-       IMGLIBS=""
-
-       # The *BSD, HP-UX, and Solaris run-time linkers need help when
-       # deciding where to find a DSO.  Add linker options to tell them
-       # where to find the DSO (usually in /usr/lib...  duh!)
-       case $uname in
-                HP-UX*)
-                       # HP-UX
-                       DSOFLAGS="+b $libdir +fb $DSOFLAGS"
-                       LDFLAGS="$LDFLAGS -Wl,+b,$libdir,+fb"
-                       ;;
-                SunOS*)
-                       # Solaris
-                       DSOFLAGS="-R$libdir $DSOFLAGS"
-                       LDFLAGS="$LDFLAGS -R$libdir"
-                       ;;
-                FreeBSD* | NetBSD* | OpenBSD*)
-                        # *BSD
-                       DSOFLAGS="-Wl,-R$libdir $DSOFLAGS"
-                        LDFLAGS="$LDFLAGS -Wl,-R$libdir"
-                        ;;
-       esac
-else
-       DSOLIBS=""
-       IMGLIBS="\$(LIBPNG) \$(LIBTIFF) \$(LIBJPEG) \$(LIBZ)"
-fi
-
-AC_SUBST(DSO)
-AC_SUBST(DSOLIBS)
-AC_SUBST(IMGLIBS)
-AC_SUBST(LIBCUPS)
-AC_SUBST(LIBCUPSIMAGE)
-AC_SUBST(LIBTOOL)
-AC_SUBST(LINKCUPS)
-AC_SUBST(LINKCUPSIMAGE)
-
-dnl Fix "prefix" variable if it hasn't been specified...
-if test "$prefix" = "NONE"; then
-       prefix="/"
-fi
-
-dnl Fix "exec_prefix" variable if it hasn't been specified...
-if test "$exec_prefix" = "NONE"; then
-       if test "$prefix" = "/"; then
-               exec_prefix="/usr"
-       else
-               exec_prefix="$prefix"
-       fi
-fi
-
-dnl Fix "sharedstatedir" variable if it hasn't been specified...
-if test "$sharedstatedir" = "\${prefix}/com" -a "$prefix" = "/"; then
-       sharedstatedir="/usr/com"
-fi
-
-dnl Fix "datadir" variable if it hasn't been specified...
-if test "$datadir" = "\${prefix}/share"; then
-       if test "$prefix" = "/"; then
-               datadir="/usr/share"
-       else
-               datadir="$prefix/share"
-       fi
-fi
-
-dnl Fix "includedir" variable if it hasn't been specified...
-if test "$includedir" = "\${prefix}/include" -a "$prefix" = "/"; then
-       includedir="/usr/include"
-fi
-
-dnl Fix "localstatedir" variable if it hasn't been specified...
-if test "$localstatedir" = "\${prefix}/var"; then
-       if test "$prefix" = "/"; then
-               localstatedir="/var"
-       else
-               localstatedir="$prefix/var"
-       fi
-fi
-
-dnl Fix "sysconfdir" variable if it hasn't been specified...
-if test "$sysconfdir" = "\${prefix}/etc"; then
-       if test "$prefix" = "/"; then
-               sysconfdir="/etc"
-       else
-               sysconfdir="$prefix/etc"
-       fi
-fi
-
-dnl Fix "libdir" variable for IRIX 6.x...
-if test "$uname" = "IRIX" -a $uversion -ge 62; then
-       libdir="$exec_prefix/lib32"
-fi
-
-dnl Fix "mandir" variable...
-if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/"; then
-       case "$uname" in
-               FreeBSD* | NetBSD* | OpenBSD* | AIX*)
-                       # *BSD + AIX
-                       mandir="/usr/share/man"
-                       AMANDIR="/usr/share/man"
-                       ;;
-               IRIX*)
-                       # SGI IRIX
-                       mandir="/usr/share/catman/u_man"
-                       AMANDIR="/usr/share/catman/a_man"
-                       ;;
-               *)
-                       # All others
-                       mandir="/usr/man"
-                       AMANDIR="/usr/man"
-                       ;;
-       esac
-else
-       AMANDIR="$mandir"
-fi
-
-AC_SUBST(AMANDIR)
-
-dnl Fix "fontpath" variable...
-if test "x$fontpath" = "x"; then
-       fontpath="$datadir/cups/fonts"
-fi
-
-dnl Setup manpage extensions...
-case "$uname" in
-       FreeBSD* | NetBSD* | OpenBSD*)
-               # *BSD
-               CAT1EXT=0
-               CAT5EXT=0
-               CAT8EXT=0
-               MAN8EXT=8
-               ;;
-       IRIX*)
-               # SGI IRIX
-               CAT1EXT=z
-               CAT5EXT=z
-               CAT8EXT=z
-               MAN8EXT=1m
-               ;;
-       SunOS* | HP-UX*)
-               # Solaris and HP-UX
-               CAT1EXT=1
-               CAT5EXT=5
-               CAT8EXT=1m
-               MAN8EXT=1m
-               ;;
-       *)
-               # All others
-               CAT1EXT=1
-               CAT5EXT=5
-               CAT8EXT=8
-               MAN8EXT=8
-               ;;
-esac
-
-AC_SUBST(CAT1EXT)
-AC_SUBST(CAT5EXT)
-AC_SUBST(CAT8EXT)
-AC_SUBST(MAN8EXT)
-
-dnl Setup init.d locations...
-case "$uname" in
-       FreeBSD* | OpenBSD*)
-               # FreeBSD and OpenBSD
-               INITDIR=""
-               INITDDIR=""
-               ;;
-
-       NetBSD*)
-               # NetBSD
-               INITDIR=""
-               INITDDIR="/etc/rc.d"
-               ;;
-
-       Linux*)
-               # Linux seems to choose an init.d directory at random...
-               if test -d /sbin/init.d; then
-                       # SuSE
-                       INITDIR="/sbin/init.d"
-                       INITDDIR=".."
-               else
-                       if test -d /etc/rc.d; then
-                               # RedHat
-                               INITDIR="/etc/rc.d"
-                               INITDDIR="../init.d"
-                       else
-                               # Others
-                               INITDIR="/etc"
-                               INITDDIR="../init.d"
-                       fi
-               fi
-               ;;
-
-       OSF1* | HP-UX*)
-               INITDIR="/sbin"
-               INITDDIR="../init.d"
-               ;;
-
-       AIX*)
-               INITDIR="/etc/rc.d"
-               INITDDIR=".."
-               ;;
-
-       *)
-               INITDIR="/etc"
-               INITDDIR="../init.d"
-               ;;
-
-esac
-
-AC_SUBST(INITDIR)
-AC_SUBST(INITDDIR)
-
-dnl Setup default locations...
-CUPS_SERVERROOT='${sysconfdir}/cups'
-CUPS_REQUESTS='${localstatedir}/spool/cups'
-
-AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$sysconfdir/cups")
-AC_DEFINE_UNQUOTED(CUPS_REQUESTS, "$localstatedir/spool/cups")
-
-if test x$logdir = x; then
-       CUPS_LOGDIR='${localstatedir}/log/cups'
-       AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$localstatedir/log/cups")
-else
-       CUPS_LOGDIR="$logdir"
-       AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$logdir")
-fi
-
-dnl See what directory to put server executables...
-case "$uname" in
-       FreeBSD* | NetBSD* | OpenBSD*)
-               # *BSD
-               INSTALL_SYSV=""
-               CUPS_SERVERBIN='${exec_prefix}/libexec/cups'
-               AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$exec_prefix/libexec/cups")
-               ;;
-       *)
-               # All others
-               INSTALL_SYSV="install-sysv"
-               CUPS_SERVERBIN='${exec_prefix}/lib/cups'
-               AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$exec_prefix/lib/cups")
-               ;;
-esac
-
-AC_SUBST(INSTALL_SYSV)
-AC_SUBST(CUPS_SERVERROOT)
-AC_SUBST(CUPS_SERVERBIN)
-AC_SUBST(CUPS_LOGDIR)
-AC_SUBST(CUPS_REQUESTS)
-
-dnl Set the CUPS_LOCALE directory...
-case "$uname" in
-       Linux* | FreeBSD* | NetBSD* | OpenBSD*)
-               CUPS_LOCALEDIR='${datadir}/locale'
-               AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$datadir/locale")
-               ;;
-
-       OSF1* | AIX*)
-               CUPS_LOCALEDIR='${exec_prefix}/lib/nls/msg'
-               AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/nls/msg")
-               ;;
-
-       *)
-               # This is the standard System V location...
-               CUPS_LOCALEDIR='${exec_prefix}/lib/locale'
-               AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/locale")
-               ;;
-esac
-
-AC_SUBST(CUPS_LOCALEDIR)
-
-dnl Set the CUPS_DATADIR directory...
-CUPS_DATADIR='${datadir}/cups'
-AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$datadir/cups")
-AC_SUBST(CUPS_DATADIR)
-
-dnl Set the CUPS_DOCROOT directory...
-if test x$docdir = x; then
-       CUPS_DOCROOT='${datadir}/doc/cups'
-       docdir="$datadir/doc/cups"
-else
-       CUPS_DOCROOT="$docdir"
-fi
-
-AC_DEFINE_UNQUOTED(CUPS_DOCROOT, "$docdir")
-AC_SUBST(CUPS_DOCROOT)
-
-dnl Set the CUPS_FONTPATH directory...
-AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$fontpath")
-
-AC_OUTPUT(Makedefs cups.sh)
+chmod +x cups-config
 
 dnl
-dnl End of "$Id: configure.in,v 1.83.2.2 2001/05/13 18:37:58 mike Exp $".
+dnl End of "$Id: configure.in,v 1.83.2.3 2001/12/26 16:52:05 mike Exp $".
 dnl
index 74e1abfae541969c1192da81f72414bb2525fe84..7d75654881024d26bc49b56e79eb5fc970c7c1a0 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# "$Id: cups-config.in,v 1.3 2001/11/16 18:05:21 mike Exp $"
+# "$Id: cups-config.in,v 1.3.2.1 2001/12/26 16:52:05 mike Exp $"
 # 
 #   CUPS configuration utility.
 #
@@ -129,5 +129,5 @@ while test $# -gt 0; do
 done
 
 #
-# End of "$Id: cups-config.in,v 1.3 2001/11/16 18:05:21 mike Exp $".
+# End of "$Id: cups-config.in,v 1.3.2.1 2001/12/26 16:52:05 mike Exp $".
 #
diff --git a/cups.list b/cups.list
deleted file mode 100644 (file)
index 8d78311..0000000
--- a/cups.list
+++ /dev/null
@@ -1,320 +0,0 @@
-#
-# "$Id: cups.list,v 1.85.2.1 2001/05/13 18:37:58 mike Exp $"
-#
-#   ESP Package Manager (EPM) file list for the Common UNIX Printing
-#   System (CUPS).
-#
-#   Copyright 1997-2001 by Easy Software Products, all rights reserved.
-#
-#   These coded instructions, statements, and computer programs are the
-#   property of Easy Software Products 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 missing or damaged please contact Easy Software Products
-#   at:
-#
-#       Attn: CUPS Licensing Information
-#       Easy Software Products
-#       44141 Airport View Drive, Suite 204
-#       Hollywood, Maryland 20636-3111 USA
-#
-#       Voice: (301) 373-9603
-#       EMail: cups-info@cups.org
-#         WWW: http://www.cups.org
-#
-
-# Product information
-%product Common UNIX Printing System
-%copyright 1993-2001 by Easy Software Products, All Rights Reserved.
-%vendor Easy Software Products
-%license LICENSE.txt
-%readme README.txt
-%version 1.1.7
-%incompat printpro
-
-# Server programs
-%system all
-# Server files
-f 0555 root sys $SBINDIR/cupsd scheduler/cupsd
-
-d 0555 root sys $SERVERBIN -
-d 0555 root sys $SERVERBIN/backend -
-f 0555 root sys $SERVERBIN/backend/ipp backend/ipp
-l 0555 root sys $SERVERBIN/backend/http ipp
-f 0555 root sys $SERVERBIN/backend/lpd backend/lpd
-f 0555 root sys $SERVERBIN/backend/parallel backend/parallel
-f 0555 root sys $SERVERBIN/backend/serial backend/serial
-f 0555 root sys $SERVERBIN/backend/socket backend/socket
-f 0555 root sys $SERVERBIN/backend/usb backend/usb
-d 0555 root sys $SERVERBIN/cgi-bin -
-f 0555 root sys $SERVERBIN/cgi-bin/admin.cgi cgi-bin/admin.cgi
-f 0555 root sys $SERVERBIN/cgi-bin/classes.cgi cgi-bin/classes.cgi
-f 0555 root sys $SERVERBIN/cgi-bin/jobs.cgi cgi-bin/jobs.cgi
-f 0555 root sys $SERVERBIN/cgi-bin/printers.cgi cgi-bin/printers.cgi
-d 0555 root sys $SERVERBIN/daemon -
-f 0555 root sys $SERVERBIN/daemon/cups-lpd scheduler/cups-lpd
-f 0555 root sys $SERVERBIN/daemon/cups-polld scheduler/cups-polld
-d 0555 root sys $SERVERBIN/filter -
-f 0555 root sys $SERVERBIN/filter/pstoraster pstoraster/pstoraster
-f 0555 root sys $SERVERBIN/filter/pdftops pdftops/pdftops
-f 0555 root sys $SERVERBIN/filter/imagetops filter/imagetops
-f 0555 root sys $SERVERBIN/filter/pstops filter/pstops
-f 0555 root sys $SERVERBIN/filter/texttops filter/texttops
-f 0555 root sys $SERVERBIN/filter/rastertoepson filter/rastertoepson
-f 0555 root sys $SERVERBIN/filter/rastertohp filter/rastertohp
-f 0555 root sys $SERVERBIN/filter/hpgltops filter/hpgltops
-f 0555 root sys $SERVERBIN/filter/imagetoraster filter/imagetoraster
-
-# Admin commands
-l 0555 root sys $BINDIR/disable $SBINDIR/accept
-l 0555 root sys $BINDIR/enable $SBINDIR/accept
-l 0555 root sys $LIBDIR/accept $SBINDIR/accept
-l 0555 root sys $LIBDIR/lpadmin $SBINDIR/lpadmin
-l 0555 root sys $LIBDIR/reject accept
-f 0555 root sys $SBINDIR/accept systemv/accept
-f 0555 root sys $SBINDIR/lpadmin systemv/lpadmin
-f 0555 root sys $SBINDIR/lpc berkeley/lpc
-f 0555 root sys $SBINDIR/lpinfo systemv/lpinfo
-f 0555 root sys $SBINDIR/lpmove systemv/lpmove
-l 0555 root sys $SBINDIR/reject accept
-
-%system irix
-l 0555 root sys /usr/etc/lpc $SBINDIR/lpc
-%system all
-
-# User commands
-f 0555 root sys $BINDIR/cancel systemv/cancel
-f 0555 root sys $BINDIR/lp systemv/lp
-f 0555 root sys $BINDIR/lpoptions systemv/lpoptions
-f 4555 root sys $BINDIR/lppasswd systemv/lppasswd
-f 0555 root sys $BINDIR/lpq berkeley/lpq
-f 0555 root sys $BINDIR/lpr berkeley/lpr
-f 0555 root sys $BINDIR/lprm berkeley/lprm
-f 0555 root sys $BINDIR/lpstat systemv/lpstat
-
-%system irix
-l 0555 root sys /usr/bsd/lpq $BINDIR/lpq
-l 0555 root sys /usr/bsd/lpr $BINDIR/lpr
-l 0555 root sys /usr/bsd/lprm $BINDIR/lprm
-%system all
-
-# DSOs
-%system hpux
-f 0555 root sys $LIBDIR/libcups.sl.2 cups/libcups.sl.2
-l 0555 root sys $LIBDIR/libcups.sl libcups.sl.2
-f 0555 root sys $LIBDIR/libcupsimage.sl.2 filter/libcupsimage.sl.2
-l 0555 root sys $LIBDIR/libcupsimage.sl libcupsimage.sl.2
-%system !hpux
-f 0555 root sys $LIBDIR/libcups.so.2 cups/libcups.so.2
-l 0555 root sys $LIBDIR/libcups.so libcups.so.2
-f 0555 root sys $LIBDIR/libcupsimage.so.2 filter/libcupsimage.so.2
-l 0555 root sys $LIBDIR/libcupsimage.so libcupsimage.so.2
-%system all
-
-# Directories
-d 0755 root sys $LOGDIR -
-d 0700 lp sys $REQUESTS -
-d 1700 lp sys $REQUESTS/tmp -
-
-# Data files
-f 0444 root sys $LOCALEDIR/C/cups_C locale/C/cups_C
-f 0444 root sys $LOCALEDIR/de/cups_de locale/de/cups_de
-f 0444 root sys $LOCALEDIR/en/cups_en locale/en/cups_en
-f 0444 root sys $LOCALEDIR/es/cups_es locale/es/cups_es
-f 0444 root sys $LOCALEDIR/fr/cups_fr locale/fr/cups_fr
-f 0444 root sys $LOCALEDIR/it/cups_it locale/it/cups_it
-
-d 0555 root sys $DATADIR -
-
-d 0555 root sys $DATADIR/banners -
-f 0444 root sys $DATADIR/banners/classified data/classified
-f 0444 root sys $DATADIR/banners/confidential data/confidential
-f 0444 root sys $DATADIR/banners/secret data/secret
-f 0444 root sys $DATADIR/banners/standard data/standard
-f 0444 root sys $DATADIR/banners/topsecret data/topsecret
-f 0444 root sys $DATADIR/banners/unclassified data/unclassified
-
-d 0555 root sys $DATADIR/charsets -
-f 0444 root sys $DATADIR/charsets/windows-874 data/windows-874
-f 0444 root sys $DATADIR/charsets/windows-1250 data/windows-1250
-f 0444 root sys $DATADIR/charsets/windows-1251 data/windows-1251
-f 0444 root sys $DATADIR/charsets/windows-1252 data/windows-1252
-f 0444 root sys $DATADIR/charsets/windows-1253 data/windows-1253
-f 0444 root sys $DATADIR/charsets/windows-1254 data/windows-1254
-f 0444 root sys $DATADIR/charsets/windows-1255 data/windows-1255
-f 0444 root sys $DATADIR/charsets/windows-1256 data/windows-1256
-f 0444 root sys $DATADIR/charsets/windows-1257 data/windows-1257
-f 0444 root sys $DATADIR/charsets/windows-1258 data/windows-1258
-f 0444 root sys $DATADIR/charsets/iso-8859-1 data/iso-8859-1
-f 0444 root sys $DATADIR/charsets/iso-8859-14 data/iso-8859-14
-f 0444 root sys $DATADIR/charsets/iso-8859-15 data/iso-8859-15
-f 0444 root sys $DATADIR/charsets/iso-8859-2 data/iso-8859-2
-f 0444 root sys $DATADIR/charsets/iso-8859-3 data/iso-8859-3
-f 0444 root sys $DATADIR/charsets/iso-8859-4 data/iso-8859-4
-f 0444 root sys $DATADIR/charsets/iso-8859-5 data/iso-8859-5
-f 0444 root sys $DATADIR/charsets/iso-8859-6 data/iso-8859-6
-f 0444 root sys $DATADIR/charsets/iso-8859-7 data/iso-8859-7
-f 0444 root sys $DATADIR/charsets/iso-8859-8 data/iso-8859-8
-f 0444 root sys $DATADIR/charsets/iso-8859-9 data/iso-8859-9
-f 0444 root sys $DATADIR/charsets/utf-8 data/utf-8
-
-d 0555 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.ps data/testprint.ps
-
-d 0555 root sys $DATADIR/fonts -
-f 0444 root sys $DATADIR/fonts fonts/*
-
-d 0555 root sys $DATADIR/pstoraster -
-f 0444 root sys $DATADIR/pstoraster/Fontmap pstoraster/Fontmap
-f 0444 root sys $DATADIR/pstoraster pstoraster/gs*.ps
-
-d 0555 root sys $DATADIR/model -
-f 0444 root sys $DATADIR/model ppd/*.ppd
-
-d 0555 root sys $DATADIR/templates -
-f 0444 root sys $DATADIR/templates templates/*.tmpl
-
-# Config files
-d 0555 root sys $SERVERROOT -
-d 0711 root sys $SERVERROOT/certs -
-d 0755 root sys $SERVERROOT/interfaces -
-d 0755 root sys $SERVERROOT/ppd -
-c 0644 root sys $SERVERROOT conf/*.conf
-f 0644 root sys $SERVERROOT/mime.convs conf/mime.convs
-f 0644 root sys $SERVERROOT/mime.types conf/mime.types
-
-%system linux
-d 0555 root sys $PAMDIR -
-c 0644 root sys $PAMDIR/cups data/cups.pam
-c 0644 root sys $PAMDIR/cups.suse data/cups.suse
-%install if test -f /lib/security/pam_unix.so; then
-%install     mv $PAMDIR/cups.suse $PAMDIR/cups
-%install fi
-%system all
-
-# Developer files
-d 0555 root sys $INCLUDEDIR/cups -
-f 0444 root sys $INCLUDEDIR/cups/cups.h cups/cups.h
-f 0444 root sys $INCLUDEDIR/cups/http.h cups/http.h
-f 0444 root sys $INCLUDEDIR/cups/image.h filter/image.h
-f 0444 root sys $INCLUDEDIR/cups/ipp.h cups/ipp.h
-f 0444 root sys $INCLUDEDIR/cups/language.h cups/language.h
-f 0444 root sys $INCLUDEDIR/cups/md5.h cups/md5.h
-f 0444 root sys $INCLUDEDIR/cups/ppd.h cups/ppd.h
-f 0444 root sys $INCLUDEDIR/cups/raster.h filter/raster.h
-
-f 0444 root sys $LIBDIR/libcups.a cups/libcups.a
-
-# Documentation files
-d 0555 root sys $DOCDIR -
-f 0444 root sys $DOCDIR/cups.css doc/cups.css
-f 0444 root sys $DOCDIR doc/*.html
-f 0444 root sys $DOCDIR doc/*.pdf
-d 0555 root sys $DOCDIR/images -
-f 0444 root sys $DOCDIR/images doc/images/*.gif
-
-# Man pages
-%system irix
-d 0555 root sys $AMANDIR -
-d 0555 root sys $AMANDIR/cat1 -
-d 0555 root sys $MANDIR -
-d 0555 root sys $MANDIR/cat1 -
-d 0555 root sys $MANDIR/cat5 -
-
-f 0444 root sys $AMANDIR/cat1/accept.z man/accept.z
-l 0444 root sys $AMANDIR/cat1/reject.z accept.z
-f 0444 root sys $MANDIR/cat1/backend.z man/backend.z
-f 0444 root sys $MANDIR/cat5/classes.conf.z man/classes.conf.z
-f 0444 root sys $AMANDIR/cat1/cups-lpd.z man/cups-lpd.z
-f 0444 root sys $AMANDIR/cat1/cups-polld.z man/cups-polld.z
-f 0444 root sys $MANDIR/cat5/cupsd.conf.z man/cupsd.conf.z
-f 0444 root sys $AMANDIR/cat1/cupsd.z man/cupsd.z
-f 0444 root sys $AMANDIR/cat1/enable.z man/enable.z
-l 0444 root sys $AMANDIR/cat1/disable.z enable.z
-f 0444 root sys $MANDIR/cat1/filter.z man/filter.z
-f 0444 root sys $AMANDIR/cat1/lpadmin.z man/lpadmin.z
-f 0444 root sys $AMANDIR/cat1/lpc.z man/lpc.z
-f 0444 root sys $AMANDIR/cat1/lpinfo.z man/lpinfo.z
-f 0444 root sys $AMANDIR/cat1/lpmove.z man/lpmove.z
-f 0444 root sys $MANDIR/cat1/lpoptions.z man/lpoptions.z
-f 0444 root sys $MANDIR/cat1/lpq.z man/lpq.z
-f 0444 root sys $MANDIR/cat1/lprm.z man/lprm.z
-f 0444 root sys $MANDIR/cat1/lpr.z man/lpr.z
-f 0444 root sys $MANDIR/cat1/lpstat.z man/lpstat.z
-f 0444 root sys $MANDIR/cat1/lp.z man/lp.z
-l 0444 root sys $MANDIR/cat1/cancel.z lp.z
-f 0444 root sys $MANDIR/cat5/mime.convs.z man/mime.convs.z
-f 0444 root sys $MANDIR/cat5/mime.types.z man/mime.types.z
-f 0444 root sys $MANDIR/cat5/printers.conf.z man/printers.conf.z
-
-%system solaris hpux
-d 0555 root sys $MANDIR/man1 -
-d 0555 root sys $MANDIR/man5 -
-d 0555 root sys $MANDIR/man1m -
-
-f 0444 root sys $MANDIR/man1m/accept.1m man/accept.man
-l 0444 root sys $MANDIR/man1m/reject.1m accept.1m
-f 0444 root sys $MANDIR/man1/backend.1 man/backend.man
-f 0444 root sys $MANDIR/man1/classes.conf.5 man/classes.conf.man
-f 0444 root sys $MANDIR/man1m/cups-lpd.1m man/cups-lpd.man
-f 0444 root sys $MANDIR/man1m/cups-polld.1m man/cups-polld.man
-f 0444 root sys $MANDIR/man1m/cupsd.1m man/cupsd.man
-f 0444 root sys $MANDIR/man5/cupsd.conf.5 man/cupsd.conf.man
-f 0444 root sys $MANDIR/man1m/enable.1m man/enable.man
-l 0444 root sys $MANDIR/man1m/disable.1m enable.1m
-f 0444 root sys $MANDIR/man1/filter.1 man/filter.man
-f 0444 root sys $MANDIR/man1m/lpadmin.1m man/lpadmin.man
-f 0444 root sys $MANDIR/man1m/lpc.1m man/lpc.man
-f 0444 root sys $MANDIR/man1m/lpinfo.1m man/lpinfo.man
-f 0444 root sys $MANDIR/man1m/lpmove.1m man/lpmove.man
-f 0444 root sys $MANDIR/man1/lpoptions.1 man/lpoptions.man
-f 0444 root sys $MANDIR/man1/lpq.1 man/lpq.man
-f 0444 root sys $MANDIR/man1/lprm.1 man/lprm.man
-f 0444 root sys $MANDIR/man1/lpr.1 man/lpr.man
-f 0444 root sys $MANDIR/man1/lpstat.1 man/lpstat.man
-f 0444 root sys $MANDIR/man1/lp.1 man/lp.man
-l 0444 root sys $MANDIR/man1/cancel.1 lp.1
-f 0444 root sys $MANDIR/man5/mime.convs.5 man/mime.convs.man
-f 0444 root sys $MANDIR/man5/mime.types.5 man/mime.types.man
-f 0444 root sys $MANDIR/man5/printers.conf.5 man/printers.conf.man
-
-%system !irix !solaris !hpux
-d 0555 root sys $MANDIR/man1 -
-d 0555 root sys $MANDIR/man5 -
-d 0555 root sys $MANDIR/man8 -
-
-f 0444 root sys $MANDIR/man8/accept.8 man/accept.man
-l 0444 root sys $MANDIR/man8/reject.8 accept.8
-f 0444 root sys $MANDIR/man1/backend.1 man/backend.man
-f 0444 root sys $MANDIR/man1/classes.conf.5 man/classes.conf.man
-f 0444 root sys $MANDIR/man8/cups-lpd.8 man/cups-lpd.man
-f 0444 root sys $MANDIR/man8/cups-polld.8 man/cups-polld.man
-f 0444 root sys $MANDIR/man8/cupsd.8 man/cupsd.man
-f 0444 root sys $MANDIR/man5/cupsd.conf.5 man/cupsd.conf.man
-f 0444 root sys $MANDIR/man8/enable.8 man/enable.man
-l 0444 root sys $MANDIR/man8/disable.8 enable.8
-f 0444 root sys $MANDIR/man1/filter.1 man/filter.man
-f 0444 root sys $MANDIR/man8/lpadmin.8 man/lpadmin.man
-f 0444 root sys $MANDIR/man8/lpc.8 man/lpc.man
-f 0444 root sys $MANDIR/man8/lpinfo.8 man/lpinfo.man
-f 0444 root sys $MANDIR/man8/lpmove.8 man/lpmove.man
-f 0444 root sys $MANDIR/man1/lpoptions.1 man/lpoptions.man
-f 0444 root sys $MANDIR/man1/lpq.1 man/lpq.man
-f 0444 root sys $MANDIR/man1/lprm.1 man/lprm.man
-f 0444 root sys $MANDIR/man1/lpr.1 man/lpr.man
-f 0444 root sys $MANDIR/man1/lpstat.1 man/lpstat.man
-f 0444 root sys $MANDIR/man1/lp.1 man/lp.man
-l 0444 root sys $MANDIR/man1/cancel.1 lp.1
-f 0444 root sys $MANDIR/man5/mime.convs.5 man/mime.convs.man
-f 0444 root sys $MANDIR/man5/mime.types.5 man/mime.types.man
-f 0444 root sys $MANDIR/man5/printers.conf.5 man/printers.conf.man
-
-# Startup script
-%system all
-i 0555 root sys cups cups.sh
-
-#
-# End of "$Id: cups.list,v 1.85.2.1 2001/05/13 18:37:58 mike Exp $".
-#
index 0886f401a0e71579e63f0112caa2700d4936cd06..055e12c09161d80a77926f1d83020e83a2e8f44e 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: cups.list.in,v 1.13 2001/12/18 17:34:06 mike Exp $"
+# "$Id: cups.list.in,v 1.13.2.1 2001/12/26 16:52:05 mike Exp $"
 #
 #   ESP Package Manager (EPM) file list for the Common UNIX Printing
 #   System (CUPS).
@@ -369,5 +369,5 @@ f 0444 root sys $AMANDIR/man$MAN8DIR/lpmove.$MAN8EXT man/lpmove.man
 i 0555 root sys cups cups.sh
 
 #
-# End of "$Id: cups.list.in,v 1.13 2001/12/18 17:34:06 mike Exp $".
+# End of "$Id: cups.list.in,v 1.13.2.1 2001/12/26 16:52:05 mike Exp $".
 #
index b310eedbe04332e37245ae1c917689deb3ff0689..2734ffbed10152c961d7a549c9a2585ebc032356 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# "$Id: cups.sh.in,v 1.9.2.1 2001/05/13 18:37:58 mike Exp $"
+# "$Id: cups.sh.in,v 1.9.2.2 2001/12/26 16:52:05 mike Exp $"
 #
 #   Startup/shutdown script for the Common UNIX Printing System (CUPS).
 #
@@ -43,6 +43,7 @@
 
 
 #### OS-Dependent Configuration
+
 case "`uname`" in
        IRIX*)
                IS_ON=/sbin/chkconfig
@@ -52,6 +53,31 @@ case "`uname`" in
                IS_ON=:
                ;;
 
+       Darwin*)
+               . /etc/rc.common
+
+               if test "${CUPS:=-YES-}" = "-NO-"; then
+                       exit 0
+               fi
+
+               IS_ON=:
+               ;;
+
+       Linux*)
+               # Set the timezone, if possible...
+               if test -f /etc/TIMEZONE; then
+                        . /etc/TIMEZONE
+                else
+                       if test -f /etc/sysconfig/clock; then
+                               . /etc/sysconfig/clock
+                               TZ="$ZONE"
+                               export TZ
+                       fi
+                fi
+
+               IS_ON=/bin/true
+               ;;
+
        *)
                IS_ON=/bin/true
                ;;
@@ -65,10 +91,14 @@ esac
 # all but IRIX, which can configure verbose bootup messages.
 #
 
-if $IS_ON verbose; then
-       ECHO=echo
+if test "`uname`" = "Darwin"; then
+       ECHO=ConsoleMessage
 else
-       ECHO=:
+       if $IS_ON verbose; then
+               ECHO=echo
+       else
+               ECHO=:
+       fi
 fi
 
 #
@@ -76,14 +106,22 @@ fi
 #
 
 case "`uname`" in
-       IRIX* | HP-UX* | SunOS* | AIX*)
-               pid=`ps -e | awk '{print $1,$4}' | grep cupsd | awk '{print $1}'`
+<<<<<<< cups.sh.in
+       IRIX* | HP-UX* | AIX* | SINIX*)
+               pid=`ps -e | awk '{if (match($4, ".*/cupsd$") || $4 == "cupsd") print $1}'`
+               ;;
+       SunOS*)
+               pid=`ps -e | nawk '{if (match($4, ".*/cupsd$") || $4 == "cupsd") print $1}'`
+               ;;
+       UnixWare*)
+               pid=`ps -e | awk '{if (match($6, ".*/cupsd$") || $6 == "cupsd") print $1}'`
+               . /etc/TIMEZONE
                ;;
        OSF1*)
-               pid=`ps -e | awk '{print $1,$5}' | grep cupsd | awk '{print $1}'`
+               pid=`ps -e | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'`
                ;;
-       Linux* | NetBSD*)
-               pid=`ps ax | awk '{print $1,$5}' | grep cupsd | awk '{print $1}'`
+       Linux* | *BSD* | Darwin*)
+               pid=`ps ax | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'`
                ;;
        *)
                pid=""
@@ -139,5 +177,5 @@ exit 0
 
 
 #
-# End of "$Id: cups.sh.in,v 1.9.2.1 2001/05/13 18:37:58 mike Exp $".
+# End of "$Id: cups.sh.in,v 1.9.2.2 2001/12/26 16:52:05 mike Exp $".
 #
index 707a39cf156de9ad9a6a2a89b0966cc1e278a0ff..5d321ee6b9f9ca2e8c83f0ecefaca90e2bef42bf 100644 (file)
--- a/cups.spec
+++ b/cups.spec
@@ -1,5 +1,5 @@
 #
-# "$Id: cups.spec,v 1.30.2.1 2001/05/13 18:37:58 mike Exp $"
+# "$Id: cups.spec,v 1.30.2.2 2001/12/26 16:52:05 mike Exp $"
 #
 #   RPM "spec" file for the Common UNIX Printing System (CUPS).
 #
 
 Summary: Common Unix Printing System
 Name: cups
-Version: 1.1.7
-Release: 1
+Version: 1.2
+Release: 0
 Copyright: GPL
 Group: System Environment/Daemons
 Source: ftp://ftp.easysw.com/pub/cups/%{version}/cups-%{version}-source.tar.gz
 Url: http://www.cups.org
 Packager: Michael Sweet <mike@easysw.com>
 Vendor: Easy Software Products
-# use buildroot so as not to disturb the version already installed
+
+# Use buildroot so as not to disturb the version already installed
 BuildRoot: /var/tmp/%{name}-root
+
+# Dependencies...
 Conflicts: lpr, LPRng
 Provides: libcups.so.2
 Provides: libcupsimage.so.2
-Provides: cupsd
+Provides: cups
 
 %package devel
 Summary: Common Unix Printing System - development environment
 Group: Development/Libraries
+Provides: libcups1
 
 %package pstoraster
 Summary: Common Unix Printing System - PostScript RIP
@@ -59,7 +63,7 @@ CUPS provides the System V and Berkeley command-line interfaces.
 %description devel
 The Common UNIX Printing System provides a portable printing layer for 
 UNIX® operating systems. This is the development package for creating
-additional printer drivers, and other CUPS services.
+additional printer drivers and other CUPS services.
 
 %description devel
 The Common UNIX Printing System provides a portable printing layer for 
@@ -70,7 +74,7 @@ supporting non-PostScript printer drivers.
 %setup
 
 %build
-./configure
+CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure
 
 # If we got this far, all prerequisite libraries must be here.
 make
@@ -79,25 +83,11 @@ make
 # Make sure the RPM_BUILD_ROOT directory exists.
 rm -rf $RPM_BUILD_ROOT
 
-make   prefix=$RPM_BUILD_ROOT \
-       exec_prefix=$RPM_BUILD_ROOT/usr \
-       AMANDIR=$RPM_BUILD_ROOT/usr/man \
-       BINDIR=$RPM_BUILD_ROOT/usr/bin \
-       DATADIR=$RPM_BUILD_ROOT/usr/share/cups \
-       DOCDIR=$RPM_BUILD_ROOT/usr/share/doc/cups \
-       INCLUDEDIR=$RPM_BUILD_ROOT/usr/include \
-       LIBDIR=$RPM_BUILD_ROOT/usr/lib \
-       LOGDIR=$RPM_BUILD_ROOT/var/log/cups \
-       LOCALEDIR=$RPM_BUILD_ROOT/usr/share/locale \
-       MANDIR=$RPM_BUILD_ROOT/usr/man \
-       PAMDIR=$RPM_BUILD_ROOT/etc/pam.d \
-       REQUESTS=$RPM_BUILD_ROOT/var/spool/cups \
-       SBINDIR=$RPM_BUILD_ROOT/usr/sbin \
-       SERVERBIN=$RPM_BUILD_ROOT/usr/lib/cups \
-       SERVERROOT=$RPM_BUILD_ROOT/etc/cups \
-       install
+make BUILDROOT=$RPM_BUILD_ROOT install
 
 %post
+ldconfig
+
 if test -x /sbin/chkconfig; then
        /sbin/chkconfig --add cups
        /sbin/chkconfig cups on
@@ -163,7 +153,10 @@ rm -rf $RPM_BUILD_ROOT
 #/sbin/rc.d/rc3.d/*
 #/sbin/rc.d/rc5.d/*
 
-/usr/bin/*
+/usr/bin/cancel
+/usr/bin/disable
+/usr/bin/enable
+/usr/bin/lp*
 /usr/lib/*.so*
 %dir /usr/lib/cups
 %dir /usr/lib/cups/backend
@@ -179,7 +172,6 @@ rm -rf $RPM_BUILD_ROOT
 /usr/lib/cups/filter/rastertoepson
 /usr/lib/cups/filter/rastertohp
 /usr/lib/cups/filter/texttops
-/usr/man/*
 /usr/sbin/*
 %dir /usr/share/cups
 %dir /usr/share/cups/banners
@@ -196,6 +188,19 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/doc/cups/*
 %dir /usr/share/locale
 /usr/share/locale/*
+%dir /usr/share/man/cat1
+/usr/share/man/cat1/*
+%dir /usr/share/man/cat5
+/usr/share/man/cat5/*
+%dir /usr/share/man/cat8
+/usr/share/man/cat8/*
+%dir /usr/share/man/man1
+/usr/share/man/man1/*
+%dir /usr/share/man/man5
+/usr/share/man/man5/*
+%dir /usr/share/man/man8
+/usr/share/man/man8/*
+
 %attr(0700,lp,root) %dir /var/spool/cups
 %attr(1700,lp,root) %dir /var/spool/cups/tmp
 
@@ -203,6 +208,10 @@ rm -rf $RPM_BUILD_ROOT
 %dir /usr/include/cups
 /usr/include/cups/*
 /usr/lib/*.a
+%dir /usr/share/man/cat3
+/usr/share/man/cat3/*
+%dir /usr/share/man/man3
+/usr/share/man/man1/*
 
 %files pstoraster
 %dir /usr/lib/cups/filter
@@ -213,5 +222,5 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/cups/pstoraster/*
 
 #
-# End of "$Id: cups.spec,v 1.30.2.1 2001/05/13 18:37:58 mike Exp $".
+# End of "$Id: cups.spec,v 1.30.2.2 2001/12/26 16:52:05 mike Exp $".
 #
index dfb72083b368200c517f32260c34c34d2a002b1a..9b44b0933547c0c2f5dbcfeb5c567c5d8a97c1b5 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.53.2.1 2001/04/02 19:51:43 mike Exp $"
+# "$Id: Makefile,v 1.53.2.2 2001/12/26 16:52:11 mike Exp $"
 #
 #   Support library Makefile for the Common UNIX Printing System (CUPS).
 #
@@ -68,18 +68,25 @@ clean:
 #
 
 install:       all
-       -$(MKDIR) $(INCLUDEDIR)/cups
-       $(CHMOD) ugo+rx $(INCLUDEDIR)
-       $(CHMOD) ugo+rx $(INCLUDEDIR)/cups
-       $(INSTALL_DATA) $(HEADERS) $(INCLUDEDIR)/cups
-       -$(MKDIR) $(LIBDIR)
-       $(CHMOD) ugo+rx $(LIBDIR)
+       $(INSTALL_DIR) $(INCLUDEDIR)/cups
+       for file in $(HEADERS); do \
+               $(INSTALL_DATA) $$file $(INCLUDEDIR)/cups; \
+       done
+       $(INSTALL_DIR) $(LIBDIR)
        $(INSTALL_LIB) $(LIBCUPS) $(LIBDIR)
-       if test $(LIBCUPS) != "libcups.a" -a $(LIBCUPS) != "libcups.la"; then \
+       if test $(LIBCUPS) = "libcups.so.2" -o $(LIBCUPS) = "libcups.sl.2"; then \
                $(INSTALL_LIB) libcups.a $(LIBDIR); \
                $(RM) $(LIBDIR)/`basename $(LIBCUPS) .3`; \
                $(LN) $(LIBCUPS) $(LIBDIR)/`basename $(LIBCUPS) .3`; \
        fi
+       if test $(LIBCUPS) = "libcups.2.dylib"; then \
+               $(INSTALL_LIB) libcups.a $(LIBDIR); \
+               $(RM) $(LIBDIR)/libcups.dylib; \
+               $(LN) $(LIBCUPS) $(LIBDIR)/libcups.dylib; \
+       fi
+       if test $(LIBCUPS) = "libcups_s.a"; then \
+               $(INSTALL_LIB) libcups.a $(LIBDIR); \
+       fi
 
 
 #
@@ -93,6 +100,30 @@ libcups.so.3 libcups.sl.3:  $(LIBOBJS) ../Makedefs
        $(LN) $@ `basename $@ .3`
 
 
+#
+# libcups.2.dylib
+#
+
+libcups.3.dylib:       $(LIBOBJS) ../Makedefs
+       echo Linking $@...
+       $(DSO) $(DSOFLAGS) -o $@ $(LIBOBJS) $(SSLLIBS)
+       $(RM) libcups.dylib
+       $(LN) $@ libcups.dylib
+
+
+#
+# libcups_s.a
+#
+
+libcups_s.a:   $(LIBOBJS) ../Makedefs
+       echo Creating $@...
+       $(RM) libcups_s.exp
+       (echo _ipp_add_attr; echo _ipp_free_attr) >libcups_s.exp
+       $(DSO) $(DSOFLAGS) -Wl,-bexport:libcups_s.exp -o libcups_s.o $(LIBOBJS) $(SSLLIBS) -lm
+       $(RM) $@
+       $(AR) $(ARFLAGS) $@ libcups_s.o
+
+
 #
 # libcups.la
 #
@@ -167,5 +198,5 @@ $(OBJS):    ../Makedefs ../config.h
 
 
 #
-# End of "$Id: Makefile,v 1.53.2.1 2001/04/02 19:51:43 mike Exp $".
+# End of "$Id: Makefile,v 1.53.2.2 2001/12/26 16:52:11 mike Exp $".
 #
index 94e9adfb36a1d0cf542b10c34c5ffb9ea4268469..b89717a2640c179dcb98e36f991b43eb26fdb93b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cups.h,v 1.32.2.1 2001/05/13 18:38:02 mike Exp $"
+ * "$Id: cups.h,v 1.32.2.2 2001/12/26 16:52:11 mike Exp $"
  *
  *   API definitions for the Common UNIX Printing System (CUPS).
  *
@@ -46,7 +46,7 @@ extern "C" {
  * Constants...
  */
 
-#  define CUPS_VERSION         1.0103
+#  define CUPS_VERSION         1.0200
 #  define CUPS_DATE_ANY                -1
 
 
@@ -171,5 +171,5 @@ extern const char   *cupsUser(void);
 #endif /* !_CUPS_CUPS_H_ */
 
 /*
- * End of "$Id: cups.h,v 1.32.2.1 2001/05/13 18:38:02 mike Exp $".
+ * End of "$Id: cups.h,v 1.32.2.2 2001/12/26 16:52:11 mike Exp $".
  */
index c0e2018b85f16db995e1d170f66544dbc57cfec8..d972d17b8f561371ebcd123aec70a1f2dd764d37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: dest.c,v 1.18 2001/03/30 22:23:00 mike Exp $"
+ * "$Id: dest.c,v 1.18.2.1 2001/12/26 16:52:11 mike Exp $"
  *
  *   User-defined destination (and option) support for the Common UNIX
  *   Printing System (CUPS).
@@ -275,6 +275,15 @@ cupsGetDests(cups_dest_t **dests)  /* O - Destinations */
     if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
       dest->is_default = 1;
   }
+  else
+  {
+   /*
+    * This initialization of "instance" is unnecessary, but avoids a
+    * compiler warning...
+    */
+
+    instance = NULL;
+  }
 
  /*
   * Load the /etc/cups/lpoptions and ~/.lpoptions files...
@@ -294,6 +303,21 @@ cupsGetDests(cups_dest_t **dests)  /* O - Destinations */
     num_dests = cups_get_dests(filename, num_dests, dests);
   }
 
+ /*
+  * Reset the default destination if the LPDEST or PRINTER environment
+  * variables are set...
+  */
+
+  if (getenv("LPDEST") != NULL || getenv("PRINTER") != NULL)
+  {
+   /*
+    * Lookup the printer and instance and make it the default...
+    */
+
+    if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
+      dest->is_default = 1;
+  }
+
  /*
   * Return the number of destinations...
   */
@@ -542,5 +566,147 @@ cups_get_dests(const char  *filename,     /* I - File to read from */
 
 
 /*
- * End of "$Id: dest.c,v 1.18 2001/03/30 22:23:00 mike Exp $".
+ * 'cups_get_sdests()' - Get destinations from a server.
+ */
+
+static int                             /* O - Number of destinations */
+cups_get_sdests(ipp_op_t    op,                /* I - get-printers or get-classes */
+                int         num_dests, /* I - Number of destinations */
+                cups_dest_t **dests)   /* IO - Destinations */
+{
+  cups_dest_t  *dest;                  /* Current destination */
+  http_t       *http;                  /* HTTP connection */
+  ipp_t                *request,               /* IPP Request */
+               *response;              /* IPP Response */
+  ipp_attribute_t *attr;               /* Current attribute */
+  cups_lang_t  *language;              /* Default language */
+  const char   *name;                  /* printer-name attribute */
+  char         job_sheets[1024];       /* job-sheets option */
+  static const char    *pattrs[] =     /* Attributes we're interested in */
+               {
+                 "printer-name",
+                 "job-sheets-default"
+               };
+
+
+ /*
+  * Connect to the CUPS server...
+  */
+
+  if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+    return (num_dests);
+
+ /*
+  * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which require
+  * the following attributes:
+  *
+  *    attributes-charset
+  *    attributes-natural-language
+  */
+
+  request = ippNew();
+
+  request->request.op.operation_id = op;
+  request->request.op.request_id   = 1;
+
+  language = cupsLangDefault();
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+               "attributes-charset", NULL, cupsLangEncoding(language));
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+               "attributes-natural-language", NULL, language->language);
+
+  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+               NULL, pattrs);
+
+ /*
+  * Do the request and get back a response...
+  */
+
+  if ((response = cupsDoRequest(http, request, "/")) != NULL)
+  {
+    for (attr = response->attrs; attr != NULL; attr = attr->next)
+    {
+     /*
+      * Skip leading attributes until we hit a printer...
+      */
+
+      while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+        attr = attr->next;
+
+      if (attr == NULL)
+        break;
+
+     /*
+      * Pull the needed attributes from this job...
+      */
+
+      name = NULL;
+
+      strcpy(job_sheets, "");
+
+      while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+      {
+        if (strcmp(attr->name, "printer-name") == 0 &&
+           attr->value_tag == IPP_TAG_NAME)
+         name = attr->values[0].string.text;
+
+        if (strcmp(attr->name, "job-sheets-default") == 0 &&
+           (attr->value_tag == IPP_TAG_KEYWORD ||
+            attr->value_tag == IPP_TAG_NAME))
+        {
+         if (attr->num_values == 2)
+           snprintf(job_sheets, sizeof(job_sheets), "%s,%s",
+                    attr->values[0].string.text, attr->values[1].string.text);
+         else
+           strcpy(job_sheets, attr->values[0].string.text);
+        }
+
+        attr = attr->next;
+      }
+
+     /*
+      * See if we have everything needed...
+      */
+
+      if (!name)
+      {
+        if (attr == NULL)
+         break;
+       else
+          continue;
+      }
+
+      num_dests = cupsAddDest(name, NULL, num_dests, dests);
+
+      if ((dest = cupsGetDest(name, NULL, num_dests, *dests)) != NULL)
+        if (job_sheets[0])
+          dest->num_options = cupsAddOption("job-sheets", job_sheets, 0,
+                                           &(dest->options));
+
+      if (attr == NULL)
+       break;
+    }
+
+    ippDelete(response);
+  }
+
+ /*
+  * Close the server connection...
+  */
+
+  httpClose(http);
+
+ /*
+  * Return the count...
+  */
+
+  return (num_dests);
+}
+
+
+/*
+ * End of "$Id: dest.c,v 1.18.2.1 2001/12/26 16:52:11 mike Exp $".
  */
index c10e3998e65d19052eb18cd77a44979b72cc05f9..9c7ea32e6ff4e03eefc082fd2e5e4237cde8ad21 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: http.c,v 1.82.2.2 2001/05/13 18:38:03 mike Exp $"
+ * "$Id: http.c,v 1.82.2.3 2001/12/26 16:52:11 mike Exp $"
  *
  *   HTTP routines for the Common UNIX Printing System (CUPS).
  *
@@ -32,6 +32,8 @@
  *   httpConnectEncrypt() - Connect to a HTTP server using encryption.
  *   httpEncryption()     - Set the required encryption on the link.
  *   httpReconnect()      - Reconnect to a HTTP server...
+ *   httpGetHostByName()  - Lookup a hostname or IP address, and return
+ *                          address records for the specified name.
  *   httpSeparate()       - Separate a Universal Resource Identifier into its
  *                          components.
  *   httpSetField()       - Set the value of an HTTP header.
@@ -352,7 +354,7 @@ httpConnectEncrypt(const char *host,        /* I - Host to connect to */
   * Lookup the host...
   */
 
-  if ((hostaddr = gethostbyname(host)) == NULL)
+  if ((hostaddr = httpGetHostByName(host)) == NULL)
   {
    /*
     * This hack to make users that don't have a localhost entry in
@@ -361,7 +363,7 @@ httpConnectEncrypt(const char *host,        /* I - Host to connect to */
 
     if (strcasecmp(host, "localhost") != 0)
       return (NULL);
-    else if ((hostaddr = gethostbyname("127.0.0.1")) == NULL)
+    else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL)
       return (NULL);
   }
 
@@ -396,24 +398,22 @@ httpConnectEncrypt(const char *host,      /* I - Host to connect to */
   */
 
   strncpy(http->hostname, host, sizeof(http->hostname) - 1);
-  memset(&(http->hostaddr), 0, sizeof(http->hostaddr));
 
-  http->hostaddr.addr.sa_family = hostaddr->h_addrtype;
-
-  if (port == 443)
-  {
-   /*
-    * Set the default encryption status...
-    */
-
-    http->encryption = HTTP_ENCRYPT_ALWAYS;
-  }
+  http->hostaddr.sin_family = hostaddr->h_addrtype;
+#ifdef WIN32
+  http->hostaddr.sin_port   = htons((u_short)port);
+#else
+  http->hostaddr.sin_port   = htons(port);
+#endif /* WIN32 */
 
  /*
   * Set the encryption status...
   */
 
-  http->encryption = encrypt;
+  if (port == 443)     /* Always use encryption for https */
+    http->encryption = HTTP_ENCRYPT_ALWAYS;
+  else
+    http->encryption = encrypt;
 
  /*
   * Loop through the addresses we have until one of them connects...
@@ -614,6 +614,69 @@ httpReconnect(http_t *http)        /* I - HTTP data */
 }
 
 
+/*
+ * 'httpGetHostByName()' - Lookup a hostname or IP address, and return
+ *                         address records for the specified name.
+ */
+
+struct hostent *                       /* O - Host entry */
+httpGetHostByName(const char *name)    /* I - Hostname or IP address */
+{
+  unsigned             ip[4];          /* IP address components */
+  static unsigned      packed_ip;      /* Packed IPv4 address */
+  static char          *packed_ptr[2]; /* Pointer to packed address */
+  static struct hostent        host_ip;        /* Host entry for IP address */
+
+
+ /*
+  * This function is needed because some operating systems have a
+  * buggy implementation of httpGetHostByName() that does not support
+  * IP addresses.  If the first character of the name string is a
+  * number, then sscanf() is used to extract the IP components.
+  * We then pack the components into an IPv4 address manually,
+  * since the inet_aton() function is deprecated.  We use the
+  * htonl() macro to get the right byte order for the address.
+  */
+
+  if (isdigit(name[0]))
+  {
+   /*
+    * We have an IP address; break it up and provide the host entry
+    * to the caller.  Currently only supports IPv4 addresses, although
+    * it should be trivial to support IPv6 in CUPS 1.2.
+    */
+
+    if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4)
+      return (NULL); /* Must have 4 numbers */
+
+    packed_ip = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3]));
+
+   /*
+    * Fill in the host entry and return it...
+    */
+
+    host_ip.h_name      = (char *)name;
+    host_ip.h_aliases   = NULL;
+    host_ip.h_addrtype  = AF_INET;
+    host_ip.h_length    = 4;
+    host_ip.h_addr_list = packed_ptr;
+    packed_ptr[0]       = (char *)(&packed_ip);
+    packed_ptr[1]       = NULL;
+
+    return (&host_ip);
+  }
+  else
+  {
+   /*
+    * Use the gethostbyname() function to get the IP address for
+    * the name...
+    */
+
+    return (gethostbyname(name));
+  }
+}
+
+
 /*
  * 'httpSeparate()' - Separate a Universal Resource Identifier into its
  *                    components.
@@ -1115,6 +1178,47 @@ httpRead(http_t *http,                   /* I - HTTP data */
   else if (length > http->data_remaining)
     length = http->data_remaining;
 
+  if (http->used == 0 && length <= 256)
+  {
+   /*
+    * Buffer small reads for better performance...
+    */
+
+    if (http->data_remaining > sizeof(http->buffer))
+      bytes = sizeof(http->buffer);
+    else
+      bytes = http->data_remaining;
+
+#ifdef HAVE_LIBSSL
+    if (http->tls)
+      bytes = SSL_read((SSL *)(http->tls), http->buffer, bytes);
+    else
+#endif /* HAVE_LIBSSL */
+    {
+      DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n",
+                    bytes));
+
+      bytes = recv(http->fd, http->buffer, bytes, 0);
+
+      DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n",
+                    bytes));
+    }
+
+    if (bytes > 0)
+      http->used = bytes;
+    else if (bytes < 0)
+    {
+#if defined(WIN32) || defined(__EMX__)
+      http->error = WSAGetLastError();
+#else
+      http->error = errno;
+#endif /* WIN32 || __EMX__ */
+      return (-1);
+    }
+    else
+      return (0);
+  }
+
   if (http->used > 0)
   {
     if (length > http->used)
@@ -1202,6 +1306,8 @@ httpWrite(http_t     *http,               /* I - HTTP data */
 
       if (http->state == HTTP_POST_RECV)
        http->state ++;
+      else if (http->state == HTTP_PUT_RECV)
+        http->state = HTTP_STATUS;
       else
        http->state = HTTP_WAITING;
 
@@ -2096,5 +2202,5 @@ http_upgrade(http_t *http)        /* I - HTTP data */
 
 
 /*
- * End of "$Id: http.c,v 1.82.2.2 2001/05/13 18:38:03 mike Exp $".
+ * End of "$Id: http.c,v 1.82.2.3 2001/12/26 16:52:11 mike Exp $".
  */
index a6f7cdcddcbac60e4b0e21e2bdeff70d58107bee..32f90d8af02a8da0033c96b8f1d571b3d770a246 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: http.h,v 1.33.2.2 2001/05/13 18:38:03 mike Exp $"
+ * "$Id: http.h,v 1.33.2.3 2001/12/26 16:52:12 mike Exp $"
  *
  *   Hyper-Text Transport Protocol definitions for the Common UNIX Printing
  *   System (CUPS).
@@ -315,6 +315,7 @@ extern char         *httpGets(char *line, int length, http_t *http);
 extern const char      *httpGetDateString(time_t t);
 extern time_t          httpGetDateTime(const char *s);
 #  define              httpGetField(http,field)        (http)->fields[field]
+extern struct hostent  *httpGetHostByName(const char *name);
 extern char            *httpGetSubField(http_t *http, http_field_t field,
                                         const char *name, char *value);
 extern int             httpHead(http_t *http, const char *uri);
@@ -364,5 +365,5 @@ extern char         *httpAddrString(const http_addr_t *addr,
 #endif /* !_CUPS_HTTP_H_ */
 
 /*
- * End of "$Id: http.h,v 1.33.2.2 2001/05/13 18:38:03 mike Exp $".
+ * End of "$Id: http.h,v 1.33.2.3 2001/12/26 16:52:12 mike Exp $".
  */
index 1e268d47ed96fdb2134a059f46c866cb4728666d..f2d0fc5e64b01c2b9cfcab217d93887b56ad3846 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c,v 1.55.2.2 2001/05/13 18:38:03 mike Exp $"
+ * "$Id: ipp.c,v 1.55.2.3 2001/12/26 16:52:12 mike Exp $"
  *
  *   Internet Printing Protocol support functions for the Common UNIX
  *   Printing System (CUPS).
@@ -125,6 +125,7 @@ ippAddBooleans(ipp_t      *ipp,             /* I - IPP request */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
+  ipp_value_t          *value;         /* Current value */
 
 
   DEBUG_printf(("ippAddBooleans(%p, %02x, \'%s\', %d, %p)\n", ipp,
@@ -141,8 +142,10 @@ ippAddBooleans(ipp_t      *ipp,            /* I - IPP request */
   attr->value_tag = IPP_TAG_BOOLEAN;
 
   if (values != NULL)
-    for (i = 0; i < num_values; i ++)
-      attr->values[i].boolean = values[i];
+    for (i = 0, value = attr->values;
+        i < num_values;
+        i ++, value ++)
+      value->boolean = values[i];
 
   return (attr);
 }
@@ -225,6 +228,7 @@ ippAddIntegers(ipp_t      *ipp,             /* I - IPP request */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
+  ipp_value_t          *value;         /* Current value */
 
 
   if (ipp == NULL || name == NULL)
@@ -238,8 +242,10 @@ ippAddIntegers(ipp_t      *ipp,            /* I - IPP request */
   attr->value_tag = type;
 
   if (values != NULL)
-    for (i = 0; i < num_values; i ++)
-      attr->values[i].integer = values[i];
+    for (i = 0, value = attr->values;
+        i < num_values;
+        i ++, value ++)
+      value->integer = values[i];
 
   return (attr);
 }
@@ -269,8 +275,10 @@ ippAddString(ipp_t      *ipp,              /* I - IPP request */
   attr->name                      = strdup(name);
   attr->group_tag                 = group;
   attr->value_tag                 = type;
-  attr->values[0].string.charset  = charset ? strdup(charset) : NULL;
-  attr->values[0].string.text     = value ? strdup(value) : NULL;
+  attr->values[0].string.charset  = ((int)type & IPP_TAG_COPY) ? (char *)charset :
+                                    charset ? strdup(charset) : NULL;
+  attr->values[0].string.text     = ((int)type & IPP_TAG_COPY) ? (char *)value :
+                                    value ? strdup(value) : NULL;
 
   if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) &&
       attr->values[0].string.text)
@@ -308,6 +316,7 @@ ippAddStrings(ipp_t      *ipp,              /* I - IPP request */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
+  ipp_value_t          *value;         /* Current value */
 
 
   if (ipp == NULL || name == NULL)
@@ -320,16 +329,20 @@ ippAddStrings(ipp_t      *ipp,            /* I - IPP request */
   attr->group_tag = group;
   attr->value_tag = type;
 
-  if (values != NULL)
-    for (i = 0; i < num_values; i ++)
-    {
-      if (i == 0)
-       attr->values[0].string.charset = charset ? strdup(charset) : NULL;
-      else
-       attr->values[i].string.charset = attr->values[0].string.charset;
-
-      attr->values[i].string.text = strdup(values[i]);
-    }
+  for (i = 0, value = attr->values;
+       i < num_values;
+       i ++, value ++)
+  {
+    if (i == 0)
+      value->string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset :
+                                   charset ? strdup(charset) : NULL;
+    else
+      value->string.charset = attr->values[0].string.charset;
+
+    if (values != NULL)
+      value->string.text = ((int)type & IPP_TAG_COPY) ? (char *)values[i] :
+                                    strdup(values[i]);
+  }
 
   return (attr);
 }
@@ -379,6 +392,7 @@ ippAddRanges(ipp_t      *ipp,               /* I - IPP request */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
+  ipp_value_t          *value;         /* Current value */
 
 
   if (ipp == NULL || name == NULL)
@@ -392,10 +406,12 @@ ippAddRanges(ipp_t      *ipp,             /* I - IPP request */
   attr->value_tag             = IPP_TAG_RANGE;
 
   if (lower != NULL && upper != NULL)
-    for (i = 0; i < num_values; i ++)
+    for (i = 0, value = attr->values;
+        i < num_values;
+        i ++, value ++)
     {
-      attr->values[i].range.lower = lower[i];
-      attr->values[i].range.upper = upper[i];
+      value->range.lower = lower[i];
+      value->range.upper = upper[i];
     }
 
   return (attr);
@@ -449,6 +465,7 @@ ippAddResolutions(ipp_t      *ipp,  /* I - IPP request */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
+  ipp_value_t          *value;         /* Current value */
 
 
   if (ipp == NULL || name == NULL)
@@ -462,11 +479,13 @@ ippAddResolutions(ipp_t      *ipp,        /* I - IPP request */
   attr->value_tag                  = IPP_TAG_RESOLUTION;
 
   if (xres != NULL && yres != NULL)
-    for (i = 0; i < num_values; i ++)
+    for (i = 0, value = attr->values;
+        i < num_values;
+        i ++, value ++)
     {
-      attr->values[i].resolution.xres  = xres[i];
-      attr->values[i].resolution.yres  = yres[i];
-      attr->values[i].resolution.units = units;
+      value->resolution.xres  = xres[i];
+      value->resolution.yres  = yres[i];
+      value->resolution.units = units;
     }
 
   return (attr);
@@ -558,7 +577,7 @@ ippDelete(ipp_t *ipp)               /* I - IPP request */
                        *next;  /* Next attribute */
 
 
-  DEBUG_printf(("ippNew(): %p\n", ipp));
+  DEBUG_printf(("ippDelete(): %p\n", ipp));
 
   if (ipp == NULL)
     return;
@@ -704,6 +723,7 @@ ippLength(ipp_t *ipp)               /* I - IPP request */
   int                  bytes;  /* Number of bytes */
   ipp_attribute_t      *attr;  /* Current attribute */
   ipp_tag_t            group;  /* Current group */
+  ipp_value_t          *value; /* Current value */
 
 
   if (ipp == NULL)
@@ -760,8 +780,10 @@ ippLength(ipp_t *ipp)              /* I - IPP request */
       case IPP_TAG_CHARSET :
       case IPP_TAG_LANGUAGE :
       case IPP_TAG_MIMETYPE :
-          for (i = 0; i < attr->num_values; i ++)
-           bytes += strlen(attr->values[i].string.text);
+         for (i = 0, value = attr->values;
+              i < attr->num_values;
+              i ++, value ++)
+           bytes += strlen(value->string.text);
          break;
 
       case IPP_TAG_DATE :
@@ -779,13 +801,17 @@ ippLength(ipp_t *ipp)             /* I - IPP request */
       case IPP_TAG_TEXTLANG :
       case IPP_TAG_NAMELANG :
           bytes += 4 * attr->num_values;/* Charset + text length */
-          for (i = 0; i < attr->num_values; i ++)
-           bytes += strlen(attr->values[i].string.charset) +
-                    strlen(attr->values[i].string.text);
+         for (i = 0, value = attr->values;
+              i < attr->num_values;
+              i ++, value ++)
+           bytes += strlen(value->string.charset) +
+                    strlen(value->string.text);
          break;
 
       default :
-          for (i = 0; i < attr->num_values; i ++)
+         for (i = 0, value = attr->values;
+              i < attr->num_values;
+              i ++, value ++)
             bytes += attr->values[0].unknown.length;
          break;
     }
@@ -840,6 +866,7 @@ ippRead(http_t *http,               /* I - HTTP data */
                        *bufptr;        /* Pointer into buffer */
   ipp_attribute_t      *attr;          /* Current attribute */
   ipp_tag_t            tag;            /* Current tag */
+  ipp_value_t          *value;         /* Current value */
 
 
   DEBUG_printf(("ippRead(%p, %p)\n", http, ipp));
@@ -983,12 +1010,37 @@ ippRead(http_t *http,            /* I - HTTP data */
              return (IPP_ERROR);
 
            /*
-           * Finally, make sure we don't have too many elements in the
-           * attribute array...
+           * Finally, reallocate the attribute array as needed...
            */
 
-           if (attr->num_values >= IPP_MAX_VALUES)
-             return (IPP_ERROR);
+           if ((attr->num_values % IPP_MAX_VALUES) == 0)
+           {
+             ipp_attribute_t   *temp,  /* Pointer to new buffer */
+                               *ptr;   /* Pointer in attribute list */
+
+
+             /*
+             * Reallocate memory...
+             */
+
+              if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
+                                       (attr->num_values + IPP_MAX_VALUES - 1) *
+                                       sizeof(ipp_value_t))) == NULL)
+               return (IPP_ERROR);
+
+             /*
+             * Reset pointers in the list...
+             */
+
+             for (ptr = ipp->attrs; ptr && ptr->next != attr; ptr = ptr->next);
+
+              if (ptr)
+               ptr->next = temp;
+             else
+               ipp->attrs = temp;
+
+              attr = ipp->current = ipp->last = temp;
+           }
          }
          else
          {
@@ -1013,6 +1065,8 @@ ippRead(http_t *http,             /* I - HTTP data */
            attr->num_values = 0;
          }
 
+          value = attr->values + attr->num_values;
+
          if (ipp_read(http, buffer, 2) < 2)
          {
            DEBUG_puts("ippRead: unable to read value length!");
@@ -1032,13 +1086,13 @@ ippRead(http_t *http,           /* I - HTTP data */
                n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
                    buffer[3];
 
-                attr->values[attr->num_values].integer = n;
+                value->integer = n;
                break;
            case IPP_TAG_BOOLEAN :
                if (ipp_read(http, buffer, 1) < 1)
                  return (IPP_ERROR);
 
-                attr->values[attr->num_values].boolean = buffer[0];
+                value->boolean = buffer[0];
                break;
            case IPP_TAG_TEXT :
            case IPP_TAG_NAME :
@@ -1049,41 +1103,39 @@ ippRead(http_t *http,           /* I - HTTP data */
            case IPP_TAG_CHARSET :
            case IPP_TAG_LANGUAGE :
            case IPP_TAG_MIMETYPE :
-               if (ipp_read(http, buffer, n) < n)
-                 return (IPP_ERROR);
+                value->string.text = calloc(n + 1, 1);
 
-                buffer[n] = '\0';
-               DEBUG_printf(("ippRead: value = \'%s\'\n", buffer));
+               if (ipp_read(http, value->string.text, n) < n)
+                 return (IPP_ERROR);
 
-                attr->values[attr->num_values].string.text = strdup((char *)buffer);
+               DEBUG_printf(("ippRead: value = \'%s\'\n",
+                             value->string.text));
                break;
            case IPP_TAG_DATE :
-               if (ipp_read(http, buffer, 11) < 11)
+               if (ipp_read(http, value->date, 11) < 11)
                  return (IPP_ERROR);
-
-                memcpy(attr->values[attr->num_values].date, buffer, 11);
                break;
            case IPP_TAG_RESOLUTION :
                if (ipp_read(http, buffer, 9) < 9)
                  return (IPP_ERROR);
 
-                attr->values[attr->num_values].resolution.xres =
+                value->resolution.xres =
                    (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
                    buffer[3];
-                attr->values[attr->num_values].resolution.yres =
+                value->resolution.yres =
                    (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
                    buffer[7];
-                attr->values[attr->num_values].resolution.units =
+                value->resolution.units =
                    (ipp_res_t)buffer[8];
                break;
            case IPP_TAG_RANGE :
                if (ipp_read(http, buffer, 8) < 8)
                  return (IPP_ERROR);
 
-                attr->values[attr->num_values].range.lower =
+                value->range.lower =
                    (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
                    buffer[3];
-                attr->values[attr->num_values].range.upper =
+                value->range.upper =
                    (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
                    buffer[7];
                break;
@@ -1106,31 +1158,30 @@ ippRead(http_t *http,           /* I - HTTP data */
 
                n = (bufptr[0] << 8) | bufptr[1];
 
-                attr->values[attr->num_values].string.charset = calloc(n + 1, 1);
+                value->string.charset = calloc(n + 1, 1);
 
-               memcpy(attr->values[attr->num_values].string.charset,
+               memcpy(value->string.charset,
                       bufptr + 2, n);
 
                 bufptr += 2 + n;
                n = (bufptr[0] << 8) | bufptr[1];
 
-                attr->values[attr->num_values].string.text = calloc(n + 1, 1);
+                value->string.text = calloc(n + 1, 1);
 
-               memcpy(attr->values[attr->num_values].string.text,
+               memcpy(value->string.text,
                       bufptr + 2, n);
-
                break;
 
             default : /* Other unsupported values */
-                attr->values[attr->num_values].unknown.length = n;
+                value->unknown.length = n;
                if (n > 0)
                {
-                 attr->values[attr->num_values].unknown.data = malloc(n);
-                 if (ipp_read(http, attr->values[attr->num_values].unknown.data, n) < n)
+                 value->unknown.data = malloc(n);
+                 if (ipp_read(http, value->unknown.data, n) < n)
                    return (IPP_ERROR);
                }
                else
-                 attr->values[attr->num_values].unknown.data = NULL;
+                 value->unknown.data = NULL;
                break;
          }
 
@@ -2158,7 +2209,9 @@ ippWriteFile(int   fd,            /* I - File to write to */
                break;
 
            case IPP_TAG_BOOLEAN :
-               for (i = 0; i < attr->num_values; i ++)
+               for (i = 0, value = attr->values;
+                    i < attr->num_values;
+                    i ++, value ++)
                {
                   if ((sizeof(buffer) - (bufptr - buffer)) < 6)
                  {
@@ -2185,7 +2238,7 @@ ippWriteFile(int   fd,            /* I - File to write to */
 
                  *bufptr++ = 0;
                  *bufptr++ = 1;
-                 *bufptr++ = attr->values[i].boolean;
+                 *bufptr++ = value->boolean;
                }
                break;
 
@@ -2198,7 +2251,9 @@ ippWriteFile(int   fd,            /* I - File to write to */
            case IPP_TAG_CHARSET :
            case IPP_TAG_LANGUAGE :
            case IPP_TAG_MIMETYPE :
-               for (i = 0; i < attr->num_values; i ++)
+               for (i = 0, value = attr->values;
+                    i < attr->num_values;
+                    i ++, value ++)
                {
                  if (i)
                  {
@@ -2227,7 +2282,7 @@ ippWriteFile(int   fd,            /* I - File to write to */
                    *bufptr++ = 0;
                  }
 
-                  n = strlen(attr->values[i].string.text);
+                  n = strlen(value->string.text);
 
                   if (n > sizeof(buffer))
                    return (IPP_ERROR);
@@ -2248,13 +2303,15 @@ ippWriteFile(int   fd,          /* I - File to write to */
 
                  *bufptr++ = n >> 8;
                  *bufptr++ = n;
-                 memcpy(bufptr, attr->values[i].string.text, n);
+                 memcpy(bufptr, value->string.text, n);
                  bufptr += n;
                }
                break;
 
            case IPP_TAG_DATE :
-               for (i = 0; i < attr->num_values; i ++)
+               for (i = 0, value = attr->values;
+                    i < attr->num_values;
+                    i ++, value ++)
                {
                   if ((sizeof(buffer) - (bufptr - buffer)) < 16)
                  {
@@ -2281,13 +2338,15 @@ ippWriteFile(int   fd,          /* I - File to write to */
 
                  *bufptr++ = 0;
                  *bufptr++ = 11;
-                 memcpy(bufptr, attr->values[i].date, 11);
+                 memcpy(bufptr, value->date, 11);
                  bufptr += 11;
                }
                break;
 
            case IPP_TAG_RESOLUTION :
-               for (i = 0; i < attr->num_values; i ++)
+               for (i = 0, value = attr->values;
+                    i < attr->num_values;
+                    i ++, value ++)
                {
                   if ((sizeof(buffer) - (bufptr - buffer)) < 14)
                  {
@@ -2314,20 +2373,22 @@ ippWriteFile(int   fd,          /* I - File to write to */
 
                  *bufptr++ = 0;
                  *bufptr++ = 9;
-                 *bufptr++ = attr->values[i].resolution.xres >> 24;
-                 *bufptr++ = attr->values[i].resolution.xres >> 16;
-                 *bufptr++ = attr->values[i].resolution.xres >> 8;
-                 *bufptr++ = attr->values[i].resolution.xres;
-                 *bufptr++ = attr->values[i].resolution.yres >> 24;
-                 *bufptr++ = attr->values[i].resolution.yres >> 16;
-                 *bufptr++ = attr->values[i].resolution.yres >> 8;
-                 *bufptr++ = attr->values[i].resolution.yres;
-                 *bufptr++ = attr->values[i].resolution.units;
+                 *bufptr++ = value->resolution.xres >> 24;
+                 *bufptr++ = value->resolution.xres >> 16;
+                 *bufptr++ = value->resolution.xres >> 8;
+                 *bufptr++ = value->resolution.xres;
+                 *bufptr++ = value->resolution.yres >> 24;
+                 *bufptr++ = value->resolution.yres >> 16;
+                 *bufptr++ = value->resolution.yres >> 8;
+                 *bufptr++ = value->resolution.yres;
+                 *bufptr++ = value->resolution.units;
                }
                break;
 
            case IPP_TAG_RANGE :
-               for (i = 0; i < attr->num_values; i ++)
+               for (i = 0, value = attr->values;
+                    i < attr->num_values;
+                    i ++, value ++)
                {
                   if ((sizeof(buffer) - (bufptr - buffer)) < 13)
                  {
@@ -2354,20 +2415,22 @@ ippWriteFile(int   fd,          /* I - File to write to */
 
                  *bufptr++ = 0;
                  *bufptr++ = 8;
-                 *bufptr++ = attr->values[i].range.lower >> 24;
-                 *bufptr++ = attr->values[i].range.lower >> 16;
-                 *bufptr++ = attr->values[i].range.lower >> 8;
-                 *bufptr++ = attr->values[i].range.lower;
-                 *bufptr++ = attr->values[i].range.upper >> 24;
-                 *bufptr++ = attr->values[i].range.upper >> 16;
-                 *bufptr++ = attr->values[i].range.upper >> 8;
-                 *bufptr++ = attr->values[i].range.upper;
+                 *bufptr++ = value->range.lower >> 24;
+                 *bufptr++ = value->range.lower >> 16;
+                 *bufptr++ = value->range.lower >> 8;
+                 *bufptr++ = value->range.lower;
+                 *bufptr++ = value->range.upper >> 24;
+                 *bufptr++ = value->range.upper >> 16;
+                 *bufptr++ = value->range.upper >> 8;
+                 *bufptr++ = value->range.upper;
                }
                break;
 
            case IPP_TAG_TEXTLANG :
            case IPP_TAG_NAMELANG :
-               for (i = 0; i < attr->num_values; i ++)
+               for (i = 0, value = attr->values;
+                    i < attr->num_values;
+                    i ++, value ++)
                {
                  if (i)
                  {
@@ -2392,8 +2455,8 @@ ippWriteFile(int   fd,            /* I - File to write to */
                    *bufptr++ = 0;
                  }
 
-                  n = strlen(attr->values[i].string.charset) +
-                     strlen(attr->values[i].string.text) +
+                  n = strlen(value->string.charset) +
+                     strlen(value->string.text) +
                      4;
 
                   if (n > sizeof(buffer))
@@ -2415,27 +2478,29 @@ ippWriteFile(int   fd,          /* I - File to write to */
                  *bufptr++ = n;
 
                  /* Length of charset */
-                  n = strlen(attr->values[i].string.charset);
+                  n = strlen(value->string.charset);
                  *bufptr++ = n >> 8;
                  *bufptr++ = n;
 
                  /* Charset */
-                 memcpy(bufptr, attr->values[i].string.charset, n);
+                 memcpy(bufptr, value->string.charset, n);
                  bufptr += n;
 
                  /* Length of text */
-                  n = strlen(attr->values[i].string.text);
+                  n = strlen(value->string.text);
                  *bufptr++ = n >> 8;
                  *bufptr++ = n;
 
                  /* Text */
-                 memcpy(bufptr, attr->values[i].string.text, n);
+                 memcpy(bufptr, value->string.text, n);
                  bufptr += n;
                }
                break;
 
             default :
-               for (i = 0; i < attr->num_values; i ++)
+               for (i = 0, value = attr->values;
+                    i < attr->num_values;
+                    i ++, value ++)
                {
                  if (i)
                  {
@@ -2460,7 +2525,7 @@ ippWriteFile(int   fd,            /* I - File to write to */
                    *bufptr++ = 0;
                  }
 
-                  n = attr->values[i].unknown.length;
+                  n = value->unknown.length;
 
                   if (n > sizeof(buffer))
                    return (IPP_ERROR);
@@ -2483,7 +2548,7 @@ ippWriteFile(int   fd,            /* I - File to write to */
                  /* Value */
                  if (n > 0)
                  {
-                   memcpy(bufptr, attr->values[i].unknown.data, n);
+                   memcpy(bufptr, value->unknown.data, n);
                    bufptr += n;
                  }
                }
@@ -2609,7 +2674,8 @@ _ipp_add_attr(ipp_t *ipp, /* I - IPP request */
 void
 _ipp_free_attr(ipp_attribute_t *attr)  /* I - Attribute to free */
 {
-  int  i;                              /* Looping var */
+  int          i;                      /* Looping var */
+  ipp_value_t  *value;                 /* Current value */
 
 
   DEBUG_printf(("_ipp_free_attr(): %p\n", attr));
@@ -2625,17 +2691,21 @@ _ipp_free_attr(ipp_attribute_t *attr)   /* I - Attribute to free */
     case IPP_TAG_CHARSET :
     case IPP_TAG_LANGUAGE :
     case IPP_TAG_MIMETYPE :
-        for (i = 0; i < attr->num_values; i ++)
-         free(attr->values[i].string.text);
+       for (i = 0, value = attr->values;
+            i < attr->num_values;
+            i ++, value ++)
+         free(value->string.text);
        break;
 
     case IPP_TAG_TEXTLANG :
     case IPP_TAG_NAMELANG :
-        for (i = 0; i < attr->num_values; i ++)
+       for (i = 0, value = attr->values;
+            i < attr->num_values;
+            i ++, value ++)
        {
-         if (attr->values[i].string.charset && i == 0)
-           free(attr->values[i].string.charset);
-         free(attr->values[i].string.text);
+         if (value->string.charset && i == 0)
+           free(value->string.charset);
+         free(value->string.text);
        }
        break;
 
@@ -2661,6 +2731,7 @@ ipp_read(http_t        *http,     /* I - Client connection */
 {
   int  tbytes,                 /* Total bytes read */
        bytes;                  /* Bytes read this pass */
+  char len[32];                /* Length string */
 
 
  /*
@@ -2668,8 +2739,46 @@ ipp_read(http_t        *http,    /* I - Client connection */
   */
 
   for (tbytes = 0, bytes = 0; tbytes < length; tbytes += bytes, buffer += bytes)
-    if ((bytes = httpRead(http, (char *)buffer, length - tbytes)) <= 0)
+  {
+    if (http->used > 0)
+    {
+     /*
+      * Do "fast read" from HTTP buffer directly...
+      */
+
+      if (http->used > (length - tbytes))
+        bytes = length - tbytes;
+      else
+        bytes = http->used;
+
+      if (bytes == 1)
+       buffer[0] = http->buffer[0];
+      else
+       memcpy(buffer, http->buffer, bytes);
+
+      http->used           -= bytes;
+      http->data_remaining -= bytes;
+
+      if (http->used > 0)
+       memcpy(http->buffer, http->buffer + bytes, http->used);
+
+      if (http->data_remaining == 0)
+      {
+       if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+         httpGets(len, sizeof(len), http);
+
+       if (http->data_encoding != HTTP_ENCODE_CHUNKED)
+       {
+         if (http->state == HTTP_POST_RECV)
+           http->state ++;
+         else
+           http->state = HTTP_WAITING;
+       }
+      }
+    }
+    else if ((bytes = httpRead(http, (char *)buffer, length - tbytes)) <= 0)
       break;
+  }
 
  /*
   * Return the number of bytes read...
@@ -2683,5 +2792,5 @@ ipp_read(http_t        *http,     /* I - Client connection */
 
 
 /*
- * End of "$Id: ipp.c,v 1.55.2.2 2001/05/13 18:38:03 mike Exp $".
+ * End of "$Id: ipp.c,v 1.55.2.3 2001/12/26 16:52:12 mike Exp $".
  */
index fa00ad172f7833dcf733d45cbad64362544ba621..3ed98c3211e1c3b1e29270965a33f25f5b24a09b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.h,v 1.36.2.2 2001/05/13 18:38:04 mike Exp $"
+ * "$Id: ipp.h,v 1.36.2.3 2001/12/26 16:52:12 mike Exp $"
  *
  *   Internet Printing Protocol definitions for the Common UNIX Printing
  *   System (CUPS).
@@ -61,7 +61,7 @@ extern "C" {
  */
 
 #  define IPP_MAX_NAME         256
-#  define IPP_MAX_VALUES       100
+#  define IPP_MAX_VALUES       10      /* Now just an allocation increment */
 
 
 /*
@@ -364,8 +364,7 @@ typedef union                       /**** Attribute Value ****/
 
 typedef struct ipp_attribute_s /**** Attribute ****/
 {
-  struct ipp_attribute_s       *next;
-                               /* Next atrtribute in list */
+  struct ipp_attribute_s *next;        /* Next attribute in list */
   ipp_tag_t    group_tag,      /* Job/Printer/Operation group tag */
                value_tag;      /* What type of value is it? */
   char         *name;          /* Name of attribute */
@@ -428,5 +427,5 @@ extern void         _ipp_free_attr(ipp_attribute_t *);
 #endif /* !_CUPS_IPP_H_ */
 
 /*
- * End of "$Id: ipp.h,v 1.36.2.2 2001/05/13 18:38:04 mike Exp $".
+ * End of "$Id: ipp.h,v 1.36.2.3 2001/12/26 16:52:12 mike Exp $".
  */
index 6e64f7966e8bfe669f737ac96f92dce0785fae07..eb429a8b894b2171f73e36a0ea86948a9cdafdc1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: language.h,v 1.18 2001/01/22 15:03:26 mike Exp $"
+ * "$Id: language.h,v 1.18.2.1 2001/12/26 16:52:13 mike Exp $"
  *
  *   Multi-language support for the Common UNIX Printing System (CUPS).
  *
@@ -201,8 +201,8 @@ typedef struct cups_lang_str        /**** Language Cache Structure ****/
 
 #  ifdef WIN32
 #    define            cupsLangDefault() cupsLangGet(setlocale(LC_ALL, ""))
-#  else /* This fix works around bugs in the Linux and HP-UX setlocale() */
-#    define            cupsLangDefault() cupsLangGet(getenv("LANG"))
+#  else
+#    define            cupsLangDefault() cupsLangGet(setlocale(LC_MESSAGES, ""))
 #  endif /* WIN32 */
 
 extern char            *cupsLangEncoding(cups_lang_t *lang);
@@ -218,5 +218,5 @@ extern cups_lang_t  *cupsLangGet(const char *language);
 #endif /* !_CUPS_LANGUAGE_H_ */
 
 /*
- * End of "$Id: language.h,v 1.18 2001/01/22 15:03:26 mike Exp $".
+ * End of "$Id: language.h,v 1.18.2.1 2001/12/26 16:52:13 mike Exp $".
  */
index e2caef283e9a51ba2f45a7dddc5824b41bb39425..4f8ac77c7d1065616005414d7d5814091b311a6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: options.c,v 1.21.2.1 2001/05/13 18:38:04 mike Exp $"
+ * "$Id: options.c,v 1.21.2.2 2001/12/26 16:52:13 mike Exp $"
  *
  *   Option routines for the Common UNIX Printing System (CUPS).
  *
@@ -366,6 +366,8 @@ cupsMarkOptions(ppd_file_t    *ppd,         /* I - PPD file */
       {
         if (ppdMarkOption(ppd, "Duplex", "None"))
          conflict = 1;
+        if (ppdMarkOption(ppd, "JCLDuplex", "None"))   /* Samsung */
+         conflict = 1;
         if (ppdMarkOption(ppd, "EFDuplex", "None"))    /* EFI */
          conflict = 1;
         if (ppdMarkOption(ppd, "KD03Duplex", "None"))  /* Kodak */
@@ -375,6 +377,8 @@ cupsMarkOptions(ppd_file_t    *ppd,         /* I - PPD file */
       {
         if (ppdMarkOption(ppd, "Duplex", "DuplexNoTumble"))
          conflict = 1;
+        if (ppdMarkOption(ppd, "JCLDuplex", "DuplexNoTumble")) /* Samsung */
+         conflict = 1;
         if (ppdMarkOption(ppd, "EFDuplex", "DuplexNoTumble"))  /* EFI */
          conflict = 1;
         if (ppdMarkOption(ppd, "KD03Duplex", "DuplexNoTumble"))        /* Kodak */
@@ -384,6 +388,8 @@ cupsMarkOptions(ppd_file_t    *ppd,         /* I - PPD file */
       {
         if (ppdMarkOption(ppd, "Duplex", "DuplexTumble"))
          conflict = 1;
+        if (ppdMarkOption(ppd, "JCLDuplex", "DuplexTumble"))   /* Samsung */
+         conflict = 1;
         if (ppdMarkOption(ppd, "EFDuplex", "DuplexTumble"))    /* EFI */
          conflict = 1;
         if (ppdMarkOption(ppd, "KD03Duplex", "DuplexTumble"))  /* Kodak */
@@ -416,5 +422,5 @@ cupsMarkOptions(ppd_file_t    *ppd,         /* I - PPD file */
 
 
 /*
- * End of "$Id: options.c,v 1.21.2.1 2001/05/13 18:38:04 mike Exp $".
+ * End of "$Id: options.c,v 1.21.2.2 2001/12/26 16:52:13 mike Exp $".
  */
index 0e8c20fb881611aec99ccebf123ea501b071bef6..988016875209530c33692ce3c9545e6b3a6c9af9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $"
+ * "$Id: ppd.c,v 1.51.2.3 2001/12/26 16:52:13 mike Exp $"
  *
  *   PPD file routines for the Common UNIX Printing System (CUPS).
  *
@@ -284,12 +284,16 @@ ppd_get_group(ppd_file_t *ppd,    /* I - PPD file */
   ppd_group_t  *group;         /* Group */
 
 
+  DEBUG_printf(("ppd_get_group(%p, \"%s\")\n", ppd, name));
+
   for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
     if (strcmp(group->text, name) == 0)
       break;
 
   if (i == 0)
   {
+    DEBUG_printf(("Adding group %s...\n", name));
+
     if (ppd->num_groups == 0)
       group = malloc(sizeof(ppd_group_t));
     else
@@ -525,6 +529,21 @@ ppdOpen(FILE *fp)          /* I - File to read from */
     puts("");
 #endif /* DEBUG */
 
+    if (strcmp(keyword, "CloseUI") != 0 &&
+        strcmp(keyword, "JCLCloseUI") != 0 &&
+        strcmp(keyword, "CloseGroup") != 0 &&
+       strcmp(keyword, "CloseSubGroup") != 0 &&
+       strncmp(keyword, "Default", 7) != 0 &&
+       string == NULL)
+    {
+     /*
+      * Need a string value!
+      */
+
+      ppdClose(ppd);
+      return (NULL);
+    }
+
     if (strcmp(keyword, "LanguageLevel") == 0)
       ppd->language_level = atoi(string);
     else if (strcmp(keyword, "LanguageEncoding") == 0)
@@ -916,13 +935,13 @@ ppdOpen(FILE *fp)         /* I - File to read from */
       */
 
       if (name[0] == '*')
-        strcpy(name, name + 1);
+        strcpy(name, name + 1); /* Eliminate leading asterisk */
 
-      if (string == NULL)
-      {
-        ppdClose(ppd);
-       return (NULL);
-      }
+      for (i = strlen(name) - 1; i > 0 && isspace(name[i]); i --)
+        name[i] = '\0'; /* Eliminate trailing spaces */
+
+      DEBUG_printf(("OpenUI of %s in group %s...\n", name,
+                    group ? group->text : "(null)"));
 
       if (subgroup != NULL)
         option = ppd_get_option(subgroup, name);
@@ -951,6 +970,7 @@ ppdOpen(FILE *fp)           /* I - File to read from */
          return (NULL);
        }
 
+        DEBUG_printf(("Adding to group %s...\n", group->text));
         option = ppd_get_option(group, name);
        group  = NULL;
       }
@@ -1245,14 +1265,40 @@ ppdOpen(FILE *fp)               /* I - File to read from */
     }
     else if (strcmp(keyword, "PaperDimension") == 0)
     {
-      if ((size = ppdPageSize(ppd, name)) != NULL)
-        sscanf(string, "%f%f", &(size->width), &(size->length));
+      if ((size = ppdPageSize(ppd, name)) == NULL)
+       size = ppd_add_size(ppd, name);
+
+      if (size == NULL)
+      {
+       /*
+        * Unable to add or find size!
+       */
+
+        ppdClose(ppd);
+       safe_free(string);
+       return (NULL);
+      }
+
+      sscanf(string, "%f%f", &(size->width), &(size->length));
     }
     else if (strcmp(keyword, "ImageableArea") == 0)
     {
-      if ((size = ppdPageSize(ppd, name)) != NULL)
-       sscanf(string, "%f%f%f%f", &(size->left), &(size->bottom),
-              &(size->right), &(size->top));
+      if ((size = ppdPageSize(ppd, name)) == NULL)
+       size = ppd_add_size(ppd, name);
+
+      if (size == NULL)
+      {
+       /*
+        * Unable to add or find size!
+       */
+
+        ppdClose(ppd);
+       safe_free(string);
+       return (NULL);
+      }
+
+      sscanf(string, "%f%f%f%f", &(size->left), &(size->bottom),
+            &(size->right), &(size->top));
     }
     else if (option != NULL &&
              (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
@@ -1266,7 +1312,8 @@ ppdOpen(FILE *fp)         /* I - File to read from */
         * Add a page size...
        */
 
-       ppd_add_size(ppd, name);
+        if (ppdPageSize(ppd, name) == NULL)
+         ppd_add_size(ppd, name);
       }
 
      /*
@@ -1584,6 +1631,7 @@ ppd_read(FILE *fp,                /* I - File to read from */
         char **string)         /* O - Code/string data */
 {
   int          ch,             /* Character from file */
+               colon,          /* Colon seen? */
                endquote,       /* Waiting for an end quote */
                mask;           /* Mask to be returned */
   char         *keyptr,        /* Keyword pointer */
@@ -1616,6 +1664,7 @@ ppd_read(FILE *fp,                /* I - File to read from */
 
     lineptr  = line;
     endquote = 0;
+    colon    = 0;
 
     while ((ch = getc(fp)) != EOF &&
            (lineptr - line) < (sizeof(line) - 1))
@@ -1656,7 +1705,10 @@ ppd_read(FILE *fp,               /* I - File to read from */
 
        *lineptr++ = ch;
 
-       if (ch == '\"')
+       if (ch == ':')
+         colon = 1;
+
+       if (ch == '\"' && colon)
         {
          endquote = !endquote;
 
@@ -1728,6 +1780,8 @@ ppd_read(FILE *fp,                /* I - File to read from */
 
     *lineptr = '\0';
 
+/*    DEBUG_printf(("LINE = \"%s\"\n", line));*/
+
     if (ch == EOF && lineptr == line)
       return (0);
 
@@ -1746,7 +1800,8 @@ ppd_read(FILE *fp,                /* I - File to read from */
     if (line[0] != '*')                        /* All lines start with an asterisk */
       continue;
 
-    if (strncmp(line, "*%", 2) == 0 || /* Comment line */
+    if (strcmp(line, "*") == 0 ||      /* (Bad) comment line */
+        strncmp(line, "*%", 2) == 0 || /* Comment line */
         strncmp(line, "*?", 2) == 0 || /* Query line */
         strcmp(line, "*End") == 0)     /* End of multi-line string */
       continue;
@@ -1762,15 +1817,21 @@ ppd_read(FILE *fp,              /* I - File to read from */
       *keyptr++ = *lineptr++;
 
     *keyptr = '\0';
+
+    if (strcmp(keyword, "End") == 0)
+      continue;
+
     mask |= PPD_KEYWORD;
 
-    if (*lineptr == ' ' || *lineptr == '\t')
+/*    DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/
+
+    if (isspace(*lineptr))
     {
      /*
       * Get an option name...
       */
 
-      while (*lineptr == ' ' || *lineptr == '\t')
+      while (isspace(*lineptr))
         lineptr ++;
 
       optptr = option;
@@ -1782,6 +1843,8 @@ ppd_read(FILE *fp,                /* I - File to read from */
       *optptr = '\0';
       mask |= PPD_OPTION;
 
+/*      DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/
+
       if (*lineptr == '/')
       {
        /*
@@ -1801,6 +1864,8 @@ ppd_read(FILE *fp,                /* I - File to read from */
 
        mask |= PPD_TEXT;
       }
+
+/*      DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/
     }
 
     if (*lineptr == ':')
@@ -1826,6 +1891,8 @@ ppd_read(FILE *fp,                /* I - File to read from */
 
       *strptr = '\0';
 
+/*      DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/
+
       mask |= PPD_STRING;
     }
   }
@@ -1940,5 +2007,5 @@ ppd_fix(char *string)             /* IO - String to fix */
 
 
 /*
- * End of "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $".
+ * End of "$Id: ppd.c,v 1.51.2.3 2001/12/26 16:52:13 mike Exp $".
  */
index 3f10352106ae5f290a6faa24c5c4d900ac93d994..d76eff3062bd693408ffcc8ef7400eec9fb3a118 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: tempfile.c,v 1.1 2001/03/09 20:06:07 mike Exp $"
+ * "$Id: tempfile.c,v 1.1.2.1 2001/12/26 16:52:13 mike Exp $"
  *
  *   Temp file utilities for the Common UNIX Printing System (CUPS).
  *
@@ -139,8 +139,8 @@ cupsTempFd(char *filename,          /* I - Pointer to buffer */
     fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
 #endif /* O_NOFOLLOW */
 
-    if (fd < 0 && errno == EPERM)
-      break; /* Stop immediately if permission denied! */
+    if (fd < 0 && (errno == EPERM || errno == ENOENT))
+      break; /* Stop immediately if permission denied or the dir doesn't exist! */
   }
   while (fd < 0);
 
@@ -196,5 +196,5 @@ cupsTempFile(char *filename,                /* I - Pointer to buffer */
 
 
 /*
- * End of "$Id: tempfile.c,v 1.1 2001/03/09 20:06:07 mike Exp $".
+ * End of "$Id: tempfile.c,v 1.1.2.1 2001/12/26 16:52:13 mike Exp $".
  */
index 46e2ccec319e51211a811b73857771176d4f6def..5c5d2b125803e69970aa4525a929364361b90d60 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: testppd.c,v 1.18 2001/01/22 15:03:31 mike Exp $"
+ * "$Id: testppd.c,v 1.18.2.1 2001/12/26 16:52:13 mike Exp $"
  *
  *   PPD test program for the Common UNIX Printing System (CUPS).
  *
@@ -56,6 +56,8 @@ main(int  argc,                       /* I - Number of command-line arguments */
                                 "JCL", "PAGE", "PROLOG" };
 
 
+  setbuf(stdout, NULL);
+
  /*
   * Display PPD files for each file listed on the command-line...
   */
@@ -127,9 +129,10 @@ main(int  argc,                    /* I - Number of command-line arguments */
 
       for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
       {
-       printf("            options[%d] = %s (%s) %s %s %.0f\n", k,
+       printf("            options[%d] = %s (%s) %s %s %.0f (%d choices)\n", k,
               option->keyword, option->text, uis[option->ui],
-              sections[option->section], option->order);
+              sections[option->section], option->order,
+              option->num_choices);
 
         if (strcmp(option->keyword, "PageSize") == 0 ||
             strcmp(option->keyword, "PageRegion") == 0)
@@ -194,5 +197,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: testppd.c,v 1.18 2001/01/22 15:03:31 mike Exp $".
+ * End of "$Id: testppd.c,v 1.18.2.1 2001/12/26 16:52:13 mike Exp $".
  */
index 210c4d61b293a07d6987dfeafdc6d85c4d0ad048..083cd5a64383a545c73049b431b984464d2329be 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: util.c,v 1.81.2.2 2001/05/13 18:38:05 mike Exp $"
+ * "$Id: util.c,v 1.81.2.3 2001/12/26 16:52:13 mike Exp $"
  *
  *   Printing utilities for the Common UNIX Printing System (CUPS).
  *
@@ -172,7 +172,7 @@ cupsDoFileRequest(http_t     *http, /* I - HTTP connection to server */
   FILE         *file;                  /* File to send */
   struct stat  fileinfo;               /* File information */
   int          bytes;                  /* Number of bytes read/written */
-  char         buffer[8192];           /* Output buffer */
+  char         buffer[32768];          /* Output buffer */
   const char   *password;              /* Password string */
   char         realm[HTTP_MAX_VALUE],  /* realm="xyz" string */
                nonce[HTTP_MAX_VALUE],  /* nonce="xyz" string */
@@ -240,9 +240,10 @@ cupsDoFileRequest(http_t     *http,        /* I - HTTP connection to server */
     */
 
     if (filename != NULL)
-      sprintf(length, "%u", ippLength(request) + (size_t)fileinfo.st_size);
+      sprintf(length, "%lu", (unsigned long)(ippLength(request) +
+                                             (size_t)fileinfo.st_size));
     else
-      sprintf(length, "%u", ippLength(request));
+      sprintf(length, "%lu", (unsigned long)ippLength(request));
 
     httpClearFields(http);
     httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length);
@@ -1677,5 +1678,5 @@ cups_local_auth(http_t *http)     /* I - Connection */
 
 
 /*
- * End of "$Id: util.c,v 1.81.2.2 2001/05/13 18:38:05 mike Exp $".
+ * End of "$Id: util.c,v 1.81.2.3 2001/12/26 16:52:13 mike Exp $".
  */
index 9b4b1e4b30c54c59b65f390d074308de35eae6d6..f7e3767caec570a728fc870773b80d25cf817f4d 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.12 2001/01/22 15:03:32 mike Exp $"
+# "$Id: Makefile,v 1.12.2.1 2001/12/26 16:52:14 mike Exp $"
 #
 #   Datafile makefile for the Common UNIX Printing System (CUPS).
 #
@@ -81,19 +81,20 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(DATADIR)/banners
-       $(CHMOD) ugo+rx $(DATADIR)
-       $(CHMOD) ugo+rx $(DATADIR)/banners
-       $(INSTALL_DATA) $(BANNERS) $(DATADIR)/banners
-       -$(MKDIR) $(DATADIR)/charsets
-       $(CHMOD) ugo+rx $(DATADIR)/charsets
-       $(INSTALL_DATA) $(CHARSETS) $(DATADIR)/charsets
-       -$(MKDIR) $(DATADIR)/data
-       $(CHMOD) ugo+rx $(DATADIR)/data
-       $(INSTALL_DATA) $(DATAFILES) $(DATADIR)/data
-       -if test "$(PAMDIR)" != ""; then \
-               $(MKDIR) $(PAMDIR); \
-               $(CHMOD) ugo+rx $(PAMDIR); \
+       $(INSTALL_DIR) $(DATADIR)/banners
+       for file in $(BANNERS); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/banners; \
+       done
+       $(INSTALL_DIR) $(DATADIR)/charsets
+       for file in $(CHARSETS); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/charsets; \
+       done
+       $(INSTALL_DIR) $(DATADIR)/data
+       for file in $(DATAFILES); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/data; \
+       done
+       -if test x$(PAMDIR) != x; then \
+               $(INSTALL_DIR) $(PAMDIR); \
                if test -f /lib/security/pam_unix.so; then \
                        $(INSTALL_DATA) cups.suse $(PAMDIR)/cups; \
                else \
@@ -103,5 +104,5 @@ install:
 
 
 #
-# End of "$Id: Makefile,v 1.12 2001/01/22 15:03:32 mike Exp $".
+# End of "$Id: Makefile,v 1.12.2.1 2001/12/26 16:52:14 mike Exp $".
 #
index f0ff35cec3fd5bf70518cf2c116049e4c0397ac3..c293368c86d868dbdb9d4adcba369016d2091a68 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.33 2001/03/02 03:45:34 andy Exp $"
+# "$Id: Makefile,v 1.33.2.1 2001/12/26 16:52:14 mike Exp $"
 #
 #   Documentation makefile for the Common UNIX Printing System (CUPS).
 #
@@ -118,16 +118,22 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(DOCDIR)
-       $(CHMOD) ugo+rx $(DOCDIR)
-       $(INSTALL_MAN) $(WEBPAGES) $(DOCDIR)
-       $(INSTALL_MAN) overview.html overview.pdf $(DOCDIR)
-       $(INSTALL_MAN) $(DOCUMENTS:.shtml=.html) $(DOCDIR)
-       $(INSTALL_MAN) $(DOCUMENTS:.shtml=.pdf) $(DOCDIR)
-       -$(MKDIR) $(DOCDIR)/images
-       $(CHMOD) ugo+rx $(DOCDIR)/images
-       $(INSTALL_MAN) $(WEBIMAGES) $(DOCDIR)/images
-       $(INSTALL_MAN) $(DOCIMAGES) $(DOCDIR)/images
+       $(INSTALL_DIR) $(DOCDIR)
+       for file in $(WEBPAGES); do \
+               $(INSTALL_MAN) $$file $(DOCDIR); \
+       done
+       $(INSTALL_MAN) overview.html $(DOCDIR)
+       $(INSTALL_MAN) overview.pdf $(DOCDIR)
+       for file in $(DOCUMENTS:.shtml=.html); do \
+               $(INSTALL_MAN) $$file $(DOCDIR); \
+       done
+       for file in $(DOCUMENTS:.shtml=.pdf); do \
+               $(INSTALL_MAN) $$file $(DOCDIR); \
+       done
+       $(INSTALL_DIR) $(DOCDIR)/images
+       for file in $(WEBIMAGES) $(DOCIMAGES); do \
+               $(INSTALL_MAN) $$file $(DOCDIR)/images; \
+       done
 
 
 #
index a950f872b8bb64694827d519ac4817469bb86b4c..022fb4702246a19f357c5dc039ce01454264fe9f 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Configuration Management Plan</TITLE>
+<TITLE>CUPS Configuration Management Plan</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-CMP-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Configuration Management Plan</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Configuration Management Plan</H1></A><BR>
 CUPS-CMP-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -116,28 +116,28 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <B><A HREF="#8">C Software Trouble Report Form</A></B><HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
- This configuration management plan document provides the guidelines 
-for development and maintenance of the Common UNIX Printing System 
-(&quot;CUPS&quot;) Version 1.1 software. 
+ This configuration management plan document provides the guidelines for
+ development and maintenance of the Common UNIX Printing System (&quot;CUPS&quot;)
+ Version 1.1 software.
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
- This configuration management document is organized into the following 
-sections: 
+ This configuration management document is organized into the following
+ sections:
 <UL>
 <LI>1 - Scope</LI>
 <LI>2 - References</LI>
@@ -149,74 +149,74 @@ sections:
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
-<UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 File Management</A></H1>
 <H2><A NAME="3_1">3.1 Directory Structure</A></H2>
- Each source file shall be placed a sub-directory corresponding to the 
-software sub-system it belongs to (&quot;scheduler&quot;, &quot;cups&quot;, etc.) To remain 
-compatible with older UNIX filesystems, directory names shall not 
-exceed 16 characters in length. 
+ Each source file shall be placed a sub-directory corresponding to the
+ software sub-system it belongs to (&quot;scheduler&quot;, &quot;cups&quot;, etc.) To remain
+ compatible with older UNIX filesystems, directory names shall not
+ exceed 16 characters in length.
 <H2><A NAME="3_2">3.2 Source Files</A></H2>
- Source files shall be documented and formatted as described in 
-Appendix B, Coding Requirements. 
+ Source files shall be documented and formatted as described in Appendix
+ B, Coding Requirements.
 <H2><A NAME="3_3">3.3 Configuration Management</A></H2>
- Source files shall be placed under the control of the Concurrent 
-Versions System (&quot;CVS&quot;) software. Source files shall be &quot;checked in&quot; 
-with each change so that modifications can be tracked. 
-<P>Documentation on the CVS software is included with the whitepaper, 
-&quot;CVS II: Parallelizing Software Development&quot;. </P>
+ Source files shall be placed under the control of the Concurrent
+ Versions System (&quot;CVS&quot;) software. Source files shall be &quot;checked in&quot;
+ with each change so that modifications can be tracked.
+<P>Documentation on the CVS software is included with the whitepaper,
+ &quot;CVS II: Parallelizing Software Development&quot;.</P>
 <H1><A NAME="4">4 Trouble Report Processing</A></H1>
- A Software Trouble Report (&quot;STR&quot;) shall be submitted every time a user 
-or vendor experiences a problem with the CUPS software. Trouble reports 
-are maintained in a database with one of the following states: 
+ A Software Trouble Report (&quot;STR&quot;) shall be submitted every time a user
+ or vendor experiences a problem with the CUPS software. Trouble reports
+ are maintained in a database with one of the following states:
 <OL>
 <LI>STR is closed with complete resolution</LI>
 <LI>STR is closed without resolution</LI>
 <LI>STR is active</LI>
 <LI>STR is pending (new STR or additional information available)</LI>
 </OL>
- Trouble reports shall be processed using the following steps. 
+ Trouble reports shall be processed using the following steps.
 <H2><A NAME="4_1">4.1 Classification</A></H2>
- When a trouble report is received it must be classified at one of the 
-following levels: 
+ When a trouble report is received it must be classified at one of the
+ following levels:
 <OL>
 <LI>Request for enhancement</LI>
 <LI>Documentation error</LI>
@@ -224,61 +224,61 @@ following levels:
 <LI>Unable to print to a printer</LI>
 <LI>Unable to print at all</LI>
 </OL>
- The scope of the problem should also be determined as: 
+ The scope of the problem should also be determined as:
 <OL>
 <LI>Specific to a machine</LI>
 <LI>Specific to an operating system</LI>
 <LI>Applies to all machines and operating systems</LI>
 </OL>
 <H2><A NAME="4_2">4.2 Identification</A></H2>
- Once the level and scope of the trouble report is determined the 
-software sub-system(s) involved with the problem are determined. This 
-may involve additional communication with the user or vendor to isolate 
-the problem to a specific cause. 
-<P>When the sub-system(s) involved have been identified, an engineer 
-will then determine the change(s) needed and estimate the time required 
-for the change(s). </P>
+ Once the level and scope of the trouble report is determined the
+ software sub-system(s) involved with the problem are determined. This
+ may involve additional communication with the user or vendor to isolate
+ the problem to a specific cause.
+<P>When the sub-system(s) involved have been identified, an engineer
+ will then determine the change(s) needed and estimate the time required
+ for the change(s).</P>
 <H2><A NAME="4_3">4.3 Correction</A></H2>
- Corrections are scheduled based upon the severity and complexity of 
-the problem. Once all changes have been made, documented, and tested 
-successfully a new software release snapshot is generated. Additional 
-tests are added as necessary for proper testing of the changes. 
+ Corrections are scheduled based upon the severity and complexity of the
+ problem. Once all changes have been made, documented, and tested
+ successfully a new software release snapshot is generated. Additional
+ tests are added as necessary for proper testing of the changes.
 <H2><A NAME="4_4">4.4 Notification</A></H2>
- The user or vendor is notified when the fix is available or if the 
-problem was caused by user error. 
+ The user or vendor is notified when the fix is available or if the
+ problem was caused by user error.
 <H1><A NAME="5">5 Software Releases</A></H1>
 <H2><A NAME="5_1">5.1 Version Numbering</A></H2>
- CUPS uses a three-part version number separated by periods to 
-represent the major, minor, and patch release numbers: 
+ CUPS uses a three-part version number separated by periods to represent
+ the major, minor, and patch release numbers:
 <UL>
 <PRE>
 major.minor.patch
 1.1.0
 </PRE>
 </UL>
- Beta-test releases are indentified by appending the letter B followed 
-by the build number: 
+ Beta-test releases are indentified by appending the letter B followed
+ by the build number:
 <UL>
 <PRE>
 major.minor.patchbbuild
 1.1.0b1
 </PRE>
 </UL>
- A CVS snapshot is generated for every beta and final release and uses 
-the version number preceded by the letter &quot;v&quot; and with the decimal 
-points replaced by underscores: 
+ A CVS snapshot is generated for every beta and final release and uses
+ the version number preceded by the letter &quot;v&quot; and with the decimal
+ points replaced by underscores:
 <UL>
 <PRE>
 v1_0_0b1
 v1_0_0
 </PRE>
 </UL>
- Each change that corrects a fault in a software sub-system increments 
-the patch release number. If a change affects the software design of 
-CUPS then the minor release number will be incremented and the patch 
-release number reset to 0. If CUPS is completely redesigned the major 
-release number will be incremented and the minor and patch release 
-numbers reset to 0: 
+ Each change that corrects a fault in a software sub-system increments
+ the patch release number. If a change affects the software design of
+ CUPS then the minor release number will be incremented and the patch
+ release number reset to 0. If CUPS is completely redesigned the major
+ release number will be incremented and the minor and patch release
+ numbers reset to 0:
 <UL>
 <PRE>
 1.1.0b1    First beta release
@@ -293,82 +293,82 @@ numbers reset to 0:
 </PRE>
 </UL>
 <H2><A NAME="5_2">5.2 Generation</A></H2>
- Software releases shall be generated for each successfully completed 
-software trouble report. All object and executable files shall be 
-deleted prior to performing a full build to ensure that source files 
-are recompiled. 
+ Software releases shall be generated for each successfully completed
+ software trouble report. All object and executable files shall be
+ deleted prior to performing a full build to ensure that source files
+ are recompiled.
 <H2><A NAME="5_3">5.3 Testing</A></H2>
- Software testing shall be conducted according to the CUPS Software 
-Test Plan, CUPS-STP-1.1. Failed tests cause STRs to be generated to 
-correct the problems found. 
+ Software testing shall be conducted according to the CUPS Software Test
+ Plan, CUPS-STP-1.1. Failed tests cause STRs to be generated to correct
+ the problems found.
 <H2><A NAME="5_4">5.4 Release</A></H2>
- When testing has been completed successfully a new distribution image 
-is created from the current CVS code &quot;snapshot&quot;. No production release 
-shall contain software that has not passed the appropriate software 
-tests. 
+ When testing has been completed successfully a new distribution image
+ is created from the current CVS code &quot;snapshot&quot;. No production release
+ shall contain software that has not passed the appropriate software
+ tests.
 <H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
 <H2><A NAME="6_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="6_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 <H1><A NAME="7">B Coding Requirements</A></H1>
- These coding requirements provide detailed information on source file 
-formatting and documentation content. These guidelines shall be applied 
-to all C and C++ source files provided with CUPS. 
+ These coding requirements provide detailed information on source file
+ formatting and documentation content. These guidelines shall be applied
+ to all C and C++ source files provided with CUPS.
 <H2><A NAME="7_1">B.1 Source Files</A></H2>
 <H3><A NAME="7_1_1">B.1.1 Naming</A></H3>
- All source files names shall be 16 characters or less in length to 
-ensure compatibility with older UNIX filesystems. Source files 
-containing functions shall have an extension of &quot;.c&quot; for ANSI C and 
-&quot;.cxx&quot; for C++ source files. All other &quot;include&quot; files shall have an 
-extension of &quot;.h&quot;. 
+ All source files names shall be 16 characters or less in length to
+ ensure compatibility with older UNIX filesystems. Source files
+ containing functions shall have an extension of &quot;.c&quot; for ANSI C and
+ &quot;.cxx&quot; for C++ source files. All other &quot;include&quot; files shall have an
+ extension of &quot;.h&quot;.
 <H3><A NAME="7_1_2">B.1.2 Documentation</A></H3>
- The top of each source file shall contain a header giving the name of 
-the file, the purpose or nature of the source file, the copyright and 
-licensing notice, and the functions contained in the file.  The file 
-name and revision information is provided by the CVS &quot;$Id$&quot; tag: 
+ The top of each source file shall contain a header giving the name of
+ the file, the purpose or nature of the source file, the copyright and
+ licensing notice, and the functions contained in the file. The file
+ name and revision information is provided by the CVS &quot;$Id$&quot; tag:
 <UL>
 <PRE>
 /*
@@ -403,10 +403,10 @@ name and revision information is provided by the CVS &quot;$Id$&quot; tag:
  */
 </PRE>
 </UL>
- The bottom of each source file shall contain a trailer giving the name 
-of the file using the CVS &quot;$Id$&quot; tag. The primary purpose of this is to 
-mark the end of a source file; if the trailer is missing it is possible 
-that code has been lost near the end of the file: 
+ The bottom of each source file shall contain a trailer giving the name
+ of the file using the CVS &quot;$Id$&quot; tag. The primary purpose of this is to
+ mark the end of a source file; if the trailer is missing it is possible
+ that code has been lost near the end of the file:
 <UL>
 <PRE>
 /*
@@ -416,17 +416,17 @@ that code has been lost near the end of the file:
 </UL>
 <H2><A NAME="7_2">B.2 Functions</A></H2>
 <H3><A NAME="7_2_1">B.2.1 Naming</A></H3>
- Functions with a global scope shall be capitalized (&quot;DoThis&quot;, 
-&quot;DoThat&quot;, &quot;DoSomethingElse&quot;, etc.) The only exception to this rule 
-shall be the CUPS interface library functions which may begin with a 
-prefix word in lowercase (&quot;cupsDoThis&quot;, &quot;cupsDoThat&quot;, etc.) 
-<P>Functions with a local scope shall be declared &quot;static&quot; and be 
-lowercase with underscores between words (&quot;do_this&quot;, &quot;do_that&quot;, 
-&quot;do_something_else&quot;, etc.) </P>
+ Functions with a global scope shall be capitalized (&quot;DoThis&quot;, &quot;DoThat&quot;,
+ &quot;DoSomethingElse&quot;, etc.) The only exception to this rule shall be the
+ CUPS interface library functions which may begin with a prefix word in
+ lowercase (&quot;cupsDoThis&quot;, &quot;cupsDoThat&quot;, etc.)
+<P>Functions with a local scope shall be declared &quot;static&quot; and be
+ lowercase with underscores between words (&quot;do_this&quot;, &quot;do_that&quot;,
+ &quot;do_something_else&quot;, etc.)</P>
 <H3><A NAME="7_2_2">B.2.2 Documentation</A></H3>
- Each function shall begin with a comment header describing what the 
-function does, the possible input limits (if any), and the possible 
-output values (if any), and any special information needed: 
+ Each function shall begin with a comment header describing what the
+ function does, the possible input limits (if any), and the possible
+ output values (if any), and any special information needed:
 <UL>
 <PRE>
 /*
@@ -445,12 +445,12 @@ do_this(float x) /* I - Power value (0.0 &lt;= x &lt;= 1.1) */
 </UL>
 <H2><A NAME="7_3">B.3 Methods</A></H2>
 <H3><A NAME="7_3_1">B.3.1 Naming</A></H3>
- Methods shall be in lowercase with underscores between words 
-(&quot;do_this&quot;, &quot;do_that&quot;, &quot;do_something_else&quot;, etc.) 
+ Methods shall be in lowercase with underscores between words
+ (&quot;do_this&quot;, &quot;do_that&quot;, &quot;do_something_else&quot;, etc.)
 <H3><A NAME="7_3_2">B.3.2 Documentation</A></H3>
- Each method shall begin with a comment header describing what the 
-method does, the possible input limits (if any), and the possible 
-output values (if any), and any special information needed: 
+ Each method shall begin with a comment header describing what the
+ method does, the possible input limits (if any), and the possible
+ output values (if any), and any special information needed:
 <UL>
 <PRE>
 /*
@@ -469,19 +469,19 @@ class::do_this(float x) /* I - Power value (0.0 &lt;= x &lt;= 1.0) */
 </UL>
 <H2><A NAME="7_4">B.4 Variables</A></H2>
 <H3><A NAME="7_4_1">B.4.1 Naming</A></H3>
- Variables with a global scope shall be capitalized (&quot;ThisVariable&quot;, 
-&quot;ThatVariable&quot;, &quot;ThisStateVariable&quot;, etc.) The only exception to this 
-rule shall be the CUPS interface library global variables which must 
-begin with the prefix &quot;cups&quot; (&quot;cupsThisVariable&quot;, &quot;cupsThatVariable&quot;, 
-etc.) Global variables shall be replaced by function arguments whenever 
-possible. 
-<P>Variables with a local scope shall be lowercase with underscores 
-between words (&quot;this_variable&quot;, &quot;that_variable&quot;, etc.) Any local 
-variables shared by functions within a source file shall be declared 
-&quot;static&quot;. </P>
+ Variables with a global scope shall be capitalized (&quot;ThisVariable&quot;,
+ &quot;ThatVariable&quot;, &quot;ThisStateVariable&quot;, etc.) The only exception to this
+ rule shall be the CUPS interface library global variables which must
+ begin with the prefix &quot;cups&quot; (&quot;cupsThisVariable&quot;, &quot;cupsThatVariable&quot;,
+ etc.) Global variables shall be replaced by function arguments whenever
+ possible.
+<P>Variables with a local scope shall be lowercase with underscores
+ between words (&quot;this_variable&quot;, &quot;that_variable&quot;, etc.) Any local
+ variables shared by functions within a source file shall be declared
+ &quot;static&quot;.</P>
 <H3><A NAME="7_4_2">B.4.2 Documentation</A></H3>
- Each variable shall be declared on a separate line and shall be 
-immediately followed by a comment block describing the variable: 
+ Each variable shall be declared on a separate line and shall be
+ immediately followed by a comment block describing the variable:
 <UL>
 <PRE>
 int this_variable;   /* The current state of this */
@@ -490,11 +490,11 @@ int that_variable;   /* The current state of that */
 </UL>
 <H2><A NAME="7_5">B.5 Types</A></H2>
 <H3><A NAME="7_5_1">B.5.1 Naming</A></H3>
- All type names shall be lowercase with underscores between words and 
-&quot;_t&quot; appended to the end of the name (&quot;this_type_t&quot;, &quot;that_type_t&quot;, 
-etc.) 
+ All type names shall be lowercase with underscores between words and
+ &quot;_t&quot; appended to the end of the name (&quot;this_type_t&quot;, &quot;that_type_t&quot;,
+ etc.)
 <H3><A NAME="7_5_2">B.5.2 Documentation</A></H3>
- Each type shall have a comment block immediately before the typedef: 
+ Each type shall have a comment block immediately before the typedef:
 <UL>
 <PRE>
 /*
@@ -505,13 +505,13 @@ typedef int cups_this_type_t;
 </UL>
 <H2><A NAME="7_6">B.6 Structures</A></H2>
 <H3><A NAME="7_6_1">B.6.1 Naming</A></H3>
- All structure names shall be lowercase with underscores between words 
-and &quot;_str&quot; appended to the end of the name (&quot;this_struct_str&quot;, 
-&quot;that_struct_str&quot;, etc.) 
+ All structure names shall be lowercase with underscores between words
+ and &quot;_str&quot; appended to the end of the name (&quot;this_struct_str&quot;,
+ &quot;that_struct_str&quot;, etc.)
 <H3><A NAME="7_6_2">B.6.2 Documentation</A></H3>
- Each structure shall have a comment block immediately before the 
-struct and each member shall be documented in accordance with the 
-variable naming policy above: 
+ Each structure shall have a comment block immediately before the struct
+ and each member shall be documented in accordance with the variable
+ naming policy above:
 <UL>
 <PRE>
 /*
@@ -526,12 +526,12 @@ struct cups_this_struct_str
 </UL>
 <H2><A NAME="7_7">B.7 Classes</A></H2>
 <H3><A NAME="7_7_1">B.7.1 Naming</A></H3>
- All class names shall be lowercase with underscores between words 
-(&quot;this_class&quot;, &quot;that_class&quot;, etc.) 
+ All class names shall be lowercase with underscores between words
+ (&quot;this_class&quot;, &quot;that_class&quot;, etc.)
 <H3><A NAME="7_7_2">B.7.2 Documentation</A></H3>
- Each class shall have a comment block immediately before the class and 
-each member shall be documented in accordance with the variable naming 
-policy above: 
+ Each class shall have a comment block immediately before the class and
+ each member shall be documented in accordance with the variable naming
+ policy above:
 <UL>
 <PRE>
 /*
@@ -546,14 +546,14 @@ class cups_this_class
 </UL>
 <H2><A NAME="7_8">B.8 Constants</A></H2>
 <H3><A NAME="7_8_1">B.8.1 Naming</A></H3>
- All constant names shall be uppercase with underscored between words 
-(&quot;THIS_CONSTANT&quot;, &quot;THAT_CONSTANT&quot;, etc.) Constants defined for the CUPS 
-interface library must begin with an uppercase prefix 
-(&quot;CUPS_THIS_CONSTANT&quot;, &quot;CUPS_THAT_CONSTANT&quot;, etc.) 
-<P>Typed enumerations shall be used whenever possible to allow for type 
-checking by the compiler. </P>
+ All constant names shall be uppercase with underscored between words
+ (&quot;THIS_CONSTANT&quot;, &quot;THAT_CONSTANT&quot;, etc.) Constants defined for the CUPS
+ interface library must begin with an uppercase prefix
+ (&quot;CUPS_THIS_CONSTANT&quot;, &quot;CUPS_THAT_CONSTANT&quot;, etc.)
+<P>Typed enumerations shall be used whenever possible to allow for type
+ checking by the compiler.</P>
 <H3><A NAME="7_8_2">B.8.2 Documentation</A></H3>
- Comment blocks shall immediately follow each constant: 
+ Comment blocks shall immediately follow each constant:
 <UL>
 <PRE>
 enum
@@ -565,8 +565,8 @@ enum
 </UL>
 <H2><A NAME="7_9">B.9 Code</A></H2>
 <H3><A NAME="7_9_1">B.9.1 Documentation</A></H3>
- All source code shall utilize block comments within functions to 
-describe the operations being performed by a group of statements: 
+ All source code shall utilize block comments within functions to
+ describe the operations being performed by a group of statements:
 <UL>
 <PRE>
 /*
@@ -593,10 +593,10 @@ do
 </UL>
 <H3><A NAME="7_9_2">B.9.2 Style</A></H3>
 <H4 TYPE="a">B.9.2.a Indentation</H4>
- All code blocks enclosed by brackets shall begin with the opening 
-brace on a new line. The code then follows starting on a new line after 
-the brace and is indented 2 spaces. The closing brace is then placed on 
-a new line following the code at the original indentation: 
+ All code blocks enclosed by brackets shall begin with the opening brace
+ on a new line. The code then follows starting on a new line after the
+ brace and is indented 2 spaces. The closing brace is then placed on a
+ new line following the code at the original indentation:
 <UL>
 <PRE>
 {
@@ -614,10 +614,9 @@ a new line following the code at the original indentation:
 }
 </PRE>
 </UL>
- Single-line statements following &quot;do&quot;, &quot;else&quot;, &quot;for&quot;, &quot;if&quot;, and 
-&quot;while&quot; shall be indented 2 spaces as well. Blocks of code in a 
-&quot;switch&quot; block shall be indented 4 spaces after each &quot;case&quot; and 
-&quot;default&quot; case: 
+ Single-line statements following &quot;do&quot;, &quot;else&quot;, &quot;for&quot;, &quot;if&quot;, and &quot;while&quot;
+ shall be indented 2 spaces as well. Blocks of code in a &quot;switch&quot; block
+ shall be indented 4 spaces after each &quot;case&quot; and &quot;default&quot; case:
 <UL>
 <PRE>
 switch (array[i])
@@ -633,20 +632,20 @@ switch (array[i])
 </PRE>
 </UL>
 <H4>B.9.2.b Spacing</H4>
- A space shall follow each reserved word (&quot;if&quot;, &quot;while&quot;, etc.) Spaces 
-shall not be inserted between a function name and the arguments in 
-parenthesis. 
+ A space shall follow each reserved word (&quot;if&quot;, &quot;while&quot;, etc.) Spaces
+ shall not be inserted between a function name and the arguments in
+ parenthesis.
 <H4>B.9.2.c Return Values</H4>
- Parenthesis shall surround values returned from a function using 
-&quot;return&quot;: 
+ Parenthesis shall surround values returned from a function using
+ &quot;return&quot;:
 <UL>
 <PRE>
 return (STATE_IDLE);
 </PRE>
 </UL>
 <H4>B.9.2.d Loops</H4>
- Whenever convenient loops should count downward to zero to improve 
-program performance: 
+ Whenever convenient loops should count downward to zero to improve
+ program performance:
 <UL>
 <PRE>
 for (i = sizeof(array) / sizeof(array[0]) - 1; i &gt;= 0; i --)
@@ -658,19 +657,19 @@ for (i = sizeof(array) / sizeof(array[0]) - 1; i &gt;= 0; i --)
 <TABLE WIDTH="80%">
 <TR><TH ALIGN="RIGHT">Summary of Problem:</TH><TD ALIGN="LEFT">
 ________________________________________</TD></TR>
-<TR><TH ALIGN="RIGHT">Problem Severity:</TH><TD ALIGN="LEFT">__1=RFE 
-<BR> __2=Documentation-Error 
-<BR> __3=Unable-to-Print-a-File 
-<BR> __4=Unable-to-Print-to-a-Printer 
+<TR><TH ALIGN="RIGHT">Problem Severity:</TH><TD ALIGN="LEFT">__1=RFE
+<BR> __2=Documentation-Error
+<BR> __3=Unable-to-Print-a-File
+<BR> __4=Unable-to-Print-to-a-Printer
 <BR> __5=Unable-to-Print-at-All</TD></TR>
-<TR><TH ALIGN="RIGHT">Problem Scope:</TH><TD ALIGN="LEFT">__1=Machine 
-__2=Operating-System __3=All</TD></TR>
+<TR><TH ALIGN="RIGHT">Problem Scope:</TH><TD ALIGN="LEFT">__1=Machine
+ __2=Operating-System __3=All</TD></TR>
 <TR><TH ALIGN="RIGHT" VALIGN="TOP">Detailed Description of Problem:</TH><TD
-ALIGN="LEFT">________________________________________ 
-<BR> ________________________________________ 
-<BR> ________________________________________ 
-<BR> ________________________________________ 
-<BR> ________________________________________ 
+ALIGN="LEFT">________________________________________
+<BR> ________________________________________
+<BR> ________________________________________
+<BR> ________________________________________
+<BR> ________________________________________
 <BR> ________________________________________</TD></TR>
 </TABLE>
 </CENTER>
index 990f61b9662a1860145875e093aa1b4f6032abc7..81a8f32eb14d1162c2f1f8a6facdb2db1091866d 100644 (file)
Binary files a/doc/cmp.pdf and b/doc/cmp.pdf differ
index e8505391a0b8c841facd71403488bbcabf33ef48..dba4fa674dd87f282c53f99cdc7012a7466a75ee 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Interface Design Description</TITLE>
+<TITLE>CUPS Interface Design Description</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-IDD-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Interface Design Description</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Interface Design Description</H1></A><BR>
 CUPS-IDD-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -91,197 +91,197 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
-<P>This interface design description document provides detailed file 
-formats, message formats, and program conventions for the Common UNIX 
-Printing System (&quot;CUPS&quot;) Version 1.1. </P>
+<P>This interface design description document provides detailed file
+ formats, message formats, and program conventions for the Common UNIX
+ Printing System (&quot;CUPS&quot;) Version 1.1.</P>
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
-<P>This interface design description document is organized into the 
-following sections: </P>
+<P>This interface design description document is organized into the
+ following sections:</P>
 <UL>
-<LI>1 - Scope </LI>
-<LI>2 - References </LI>
-<LI>3 - Internal Interfaces </LI>
-<LI>4 - External Interfaces </LI>
-<LI>5 - Directories </LI>
-<LI>A - Glossary </LI>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Internal Interfaces</LI>
+<LI>4 - External Interfaces</LI>
+<LI>5 - Directories</LI>
+<LI>A - Glossary</LI>
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
+<P>The following CUPS documentation is referenced by this document:</P>
 <UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 Internal Interfaces</A></H1>
 <H2><A NAME="3_1">3.1 Character Set Files</A></H2>
-<P>The character set files define a mapping between 8-bit characters 
-and the Unicode character set, or between Unicode and printer fonts. 
-They are named using the IETF charset names defined in RFCnnnn.  These 
-files are ASCII text, the content of which is described below. Comments 
-can be included by using the <TT>#</TT> character in the first column 
-of a line. </P>
+<P>The character set files define a mapping between 8-bit characters and
+ the Unicode character set, or between Unicode and printer fonts. They
+ are named using the IETF charset names defined in RFCnnnn. These files
+ are ASCII text, the content of which is described below. Comments can
+ be included by using the <TT>#</TT> character in the first column of a
+ line.</P>
 <H3><A NAME="3_1_1">3.1.1 8-Bit Character Set Files</A></H3>
-<P>8-bit character set files start with a line reading: </P>
+<P>8-bit character set files start with a line reading:</P>
 <UL>
 <PRE>
 charset 8bit
 </PRE>
 </UL>
-<P>Following this are lines that define the font information: </P>
+<P>Following this are lines that define the font information:</P>
 <UL>
 <PRE>
 first last direction width normal bold italic bold-italic
 </PRE>
 </UL>
-<P><VAR>First</VAR> and <VAR>last</VAR> are the first and last glyphs 
-in the font mapping that correspond to that font; a maximum of 256 
-characters can be mapped within each group, with a maximum of 256 
-mappings (this is a PostScript limitation.) The glyph values are 
-hexadecimal. </P>
-<P><VAR>Direction</VAR> is the string &quot;ltor&quot;, &quot;rtol&quot;, or &quot;rtola&quot; 
-indicating left-to-right, right-to-left, or right-to-left Arabic text. </P>
-<P><VAR>Width</VAR> is the string &quot;single&quot; or &quot;double&quot;; double means 
-that the glyphs are twice as wide as ASCII characters in the Courier 
-typeface. </P>
-<P><VAR>Normal, bold, italic</VAR>, and <VAR>bold-italic</VAR> are the 
-typefaces to use for each presentation.  If characters are only 
-available in a single style then only one typeface should be listed 
-(e.g. &quot;Symbol&quot;.) Each font that is listed will be used (and downloaded 
-if needed) when printing. </P>
-<P>The remaining lines define a character to Unicode glyph mapping for 
-the character set. The character and glyph values are hexadecimal: </P>
+<P><VAR>First</VAR> and<VAR> last</VAR> are the first and last glyphs in
+ the font mapping that correspond to that font; a maximum of 256
+ characters can be mapped within each group, with a maximum of 256
+ mappings (this is a PostScript limitation.) The glyph values are
+ hexadecimal.</P>
+<P><VAR>Direction</VAR> is the string &quot;ltor&quot;, &quot;rtol&quot;, or &quot;rtola&quot;
+ indicating left-to-right, right-to-left, or right-to-left Arabic text.</P>
+<P><VAR>Width</VAR> is the string &quot;single&quot; or &quot;double&quot;; double means
+ that the glyphs are twice as wide as ASCII characters in the Courier
+ typeface.</P>
+<P><VAR>Normal, bold, italic</VAR>, and<VAR> bold-italic</VAR> are the
+ typefaces to use for each presentation. If characters are only
+ available in a single style then only one typeface should be listed
+ (e.g. &quot;Symbol&quot;.) Each font that is listed will be used (and downloaded
+ if needed) when printing.</P>
+<P>The remaining lines define a character to Unicode glyph mapping for
+ the character set. The character and glyph values are hexadecimal:</P>
 <UL>
 <PRE>
 xx yyyy
 </PRE>
 </UL>
 <H3><A NAME="3_1_2">3.1.2 Unicode Character Set Files</A></H3>
-<P>Unicode character set files start with a line reading: </P>
+<P>Unicode character set files start with a line reading:</P>
 <UL>
 <PRE>
 charset encoding
 </PRE>
 </UL>
-<P><VAR>Encoding</VAR> is the encoding to use for the text; currently 
-only the string &quot;utf8&quot; is supported. </P>
-<P>Following this are lines defining the font information: </P>
+<P><VAR>Encoding</VAR> is the encoding to use for the text; currently
+ only the string &quot;utf8&quot; is supported.</P>
+<P>Following this are lines defining the font information:</P>
 <UL>
 <PRE>
 first last direction width normal bold italic bold-italic
 </PRE>
 </UL>
-<P><VAR>First</VAR> and <VAR>last</VAR> are the first and last glyphs 
-in the font mapping that correspond to that font; a maximum of 256 
-characters can be mapped within each group, with a maximum of 256 
-mappings (this is a PostScript limitation.) The glyph values are 
-hexadecimal. </P>
-<P><VAR>Direction</VAR> is the string &quot;ltor&quot;, &quot;rtol&quot;, or &quot;rtola&quot; 
-indicating left-to-right, right-to-left, or right-to-left Arabic text. </P>
-<P><VAR>Width</VAR> is the string &quot;single&quot; or &quot;double&quot;; double means 
-that the glyphs are twice as wide as ASCII characters in the Courier 
-typeface. </P>
-<P><VAR>Normal, bold, italic</VAR>, and <VAR>bold-italic</VAR> are the 
-typefaces to use for each presentation.  If characters are only 
-available in a single style then only one typeface should be listed 
-(e.g. &quot;Symbol&quot;.) Each font that is listed will be used (and downloaded 
-if needed) when printing. </P>
+<P><VAR>First</VAR> and<VAR> last</VAR> are the first and last glyphs in
+ the font mapping that correspond to that font; a maximum of 256
+ characters can be mapped within each group, with a maximum of 256
+ mappings (this is a PostScript limitation.) The glyph values are
+ hexadecimal.</P>
+<P><VAR>Direction</VAR> is the string &quot;ltor&quot;, &quot;rtol&quot;, or &quot;rtola&quot;
+ indicating left-to-right, right-to-left, or right-to-left Arabic text.</P>
+<P><VAR>Width</VAR> is the string &quot;single&quot; or &quot;double&quot;; double means
+ that the glyphs are twice as wide as ASCII characters in the Courier
+ typeface.</P>
+<P><VAR>Normal, bold, italic</VAR>, and<VAR> bold-italic</VAR> are the
+ typefaces to use for each presentation. If characters are only
+ available in a single style then only one typeface should be listed
+ (e.g. &quot;Symbol&quot;.) Each font that is listed will be used (and downloaded
+ if needed) when printing.</P>
 <H2><A NAME="3_2">3.2 Language Files</A></H2>
-<P>The language files define the default character set and a collection 
-of text messages in that language. They are named by prefixing the 
-string &quot;cups_&quot; to the front of the language specifier (e.g. &quot;cups_en&quot;, 
-&quot;cups_fr&quot;, etc.) Each file consists of two or more lines of ASCII text. </P>
-<P>The first line identifies the character set to be used for the 
-messages. The currently recognized values are: </P>
+<P>The language files define the default character set and a collection
+ of text messages in that language. They are named by prefixing the
+ string &quot;cups_&quot; to the front of the language specifier (e.g. &quot;cups_en&quot;,
+ &quot;cups_fr&quot;, etc.) Each file consists of two or more lines of ASCII text.</P>
+<P>The first line identifies the character set to be used for the
+ messages. The currently recognized values are:</P>
 <UL>
-<LI>iso-8859-1 </LI>
-<LI>iso-8859-2 </LI>
-<LI>iso-8859-3 </LI>
-<LI>iso-8859-4 </LI>
-<LI>iso-8859-5 </LI>
-<LI>iso-8859-6 </LI>
-<LI>iso-8859-7 </LI>
-<LI>iso-8859-8 </LI>
-<LI>iso-8859-9 </LI>
-<LI>iso-8859-10 </LI>
-<LI>iso-8859-13 </LI>
-<LI>iso-8859-14 </LI>
-<LI>iso-8859-15 </LI>
-<LI>us-ascii </LI>
-<LI>utf-8 </LI>
-<LI>windows-874 </LI>
-<LI>windows-1250 </LI>
-<LI>windows-1251 </LI>
-<LI>windows-1252 </LI>
-<LI>windows-1253 </LI>
-<LI>windows-1254 </LI>
-<LI>windows-1255 </LI>
-<LI>windows-1256 </LI>
-<LI>windows-1257 </LI>
-<LI>windows-1258 </LI>
+<LI>iso-8859-1</LI>
+<LI>iso-8859-2</LI>
+<LI>iso-8859-3</LI>
+<LI>iso-8859-4</LI>
+<LI>iso-8859-5</LI>
+<LI>iso-8859-6</LI>
+<LI>iso-8859-7</LI>
+<LI>iso-8859-8</LI>
+<LI>iso-8859-9</LI>
+<LI>iso-8859-10</LI>
+<LI>iso-8859-13</LI>
+<LI>iso-8859-14</LI>
+<LI>iso-8859-15</LI>
+<LI>us-ascii</LI>
+<LI>utf-8</LI>
+<LI>windows-874</LI>
+<LI>windows-1250</LI>
+<LI>windows-1251</LI>
+<LI>windows-1252</LI>
+<LI>windows-1253</LI>
+<LI>windows-1254</LI>
+<LI>windows-1255</LI>
+<LI>windows-1256</LI>
+<LI>windows-1257</LI>
+<LI>windows-1258</LI>
 </UL>
-<P>The second and succeeding lines define text messages. If the message 
-text is preceded by a number, then the current message number is 
-updated and the text after the number is used. </P>
+<P>The second and succeeding lines define text messages. If the message
+ text is preceded by a number, then the current message number is
+ updated and the text after the number is used.</P>
 <H2><A NAME="3_3">3.3 MIME Files</A></H2>
-<P>CUPS uses two MIME files in its standard configuration. </P>
+<P>CUPS uses two MIME files in its standard configuration.</P>
 <H3><A NAME="3_3_1">3.3.1 mime.types</A></H3>
-<P>The mime.types file defines the recognized file types and consists 
-of 1 or more lines of ASCII text. Comment lines start with the pound 
-(&quot;#&quot;) character. The backslash (&quot;\&quot;) character can be used at the end 
-of a line to continue that line to the next. </P>
-<P>Each non-blank line starts with a MIME type identifier 
-(&quot;super/type&quot;) as registered with the IANA. All text following the MIME 
-type is treated as a series of type recognition rules: </P>
+<P>The mime.types file defines the recognized file types and consists of
+ 1 or more lines of ASCII text. Comment lines start with the pound (&quot;#&quot;)
+ character. The backslash (&quot;\&quot;) character can be used at the end of a
+ line to continue that line to the next.</P>
+<P>Each non-blank line starts with a MIME type identifier (&quot;super/type&quot;)
+ as registered with the IANA. All text following the MIME type is
+ treated as a series of type recognition rules:</P>
 <UL>
 <PRE>
 mime-type := super &quot;/&quot; type { SP rule }*
@@ -303,31 +303,31 @@ operator := &quot;+&quot; |       [ logical AND ]
            &quot;!&quot;         [ unary NOT ]
 </PRE>
 </UL>
-<P>The <CODE>int</CODE> and <CODE>short</CODE> rules match look for 
-integers in network byte order (a.k.a. big-endian) with the 
-most-significant byte first. </P>
+<P>The <CODE>int</CODE> and <CODE>short</CODE> rules match look for
+ integers in network byte order (a.k.a. big-endian) with the
+ most-significant byte first.</P>
 <H3><A NAME="3_3_2">3.3.2 mime.convs</A></H3>
-<P>The mime.types file defines the recognized file filters and consists 
-of 1 or more lines of ASCII text. Comment lines start with the pound 
-(&quot;#&quot;) character. </P>
-<P>Each non-blank line starts with two MIME type identifiers 
-(&quot;super/type&quot;) representing the source and destination types. Following 
-the MIME types are a cost value (0 to 100) and the filter program to 
-use. If the filter program is not specified using the full path then it 
-must reside in the CUPS filter directory: </P>
+<P>The mime.types file defines the recognized file filters and consists
+ of 1 or more lines of ASCII text. Comment lines start with the pound
+ (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with two MIME type identifiers
+ (&quot;super/type&quot;) representing the source and destination types. Following
+ the MIME types are a cost value (0 to 100) and the filter program to
+ use. If the filter program is not specified using the full path then it
+ must reside in the CUPS filter directory:</P>
 <UL>
 <PRE>
 super/type SP super/type2 SP cost SP program
 </PRE>
 </UL>
 <H2><A NAME="3_4">3.4 Option Files</A></H2>
-<P>CUPS maintains user-defined printer and option files for each 
-printer and user on the system. The printers and options defined in the 
-system option file (<CODE>/etc/cups/lpoptions</CODE>) are loaded first, 
-followed by the user option file (<CODE>$HOME/.lpoptions</CODE>). 
-Options in the user file replace those defined in the system file for 
-the same destination. Each line in the files can be one of the 
-following: </P>
+<P>CUPS maintains user-defined printer and option files for each printer
+ and user on the system. The printers and options defined in the system
+ option file (<CODE>/etc/cups/lpoptions</CODE>) are loaded first,
+ followed by the user option file (<CODE>$HOME/.lpoptions</CODE>).
+ Options in the user file replace those defined in the system file for
+ the same destination. Each line in the files can be one of the
+ following:</P>
 <UL>
 <PRE>
 Dest name option=value option=value ... option=value
@@ -336,300 +336,295 @@ Default name option=value option=value ... option=value
 Default name/instance option=value option=value ... option=value
 </PRE>
 </UL>
-<P>The line beginning with &quot;Default&quot; indicates the default destination 
-for print jobs; a default line in the user option file overrides the 
-default defined in the system option file. </P>
-<P><VAR>Name</VAR> is the name of a printer known to the local server. </P>
-<P><VAR>Instance</VAR> can be any string of letters, numbers, and the 
-underscore up to 127 characters in length. </P>
-<P>The remainder of the line contains a list of space-separated options 
-and their values. </P>
+<P>The line beginning with &quot;Default&quot; indicates the default destination
+ for print jobs; a default line in the user option file overrides the
+ default defined in the system option file.</P>
+<P><VAR>Name</VAR> is the name of a printer known to the local server.</P>
+<P><VAR>Instance</VAR> can be any string of letters, numbers, and the
+ underscore up to 127 characters in length.</P>
+<P>The remainder of the line contains a list of space-separated options
+ and their values.</P>
 <H2><A NAME="3_5">3.5 PostScript Printer Description Files</A></H2>
-<P>PostScript Printer Description (&quot;PPD&quot;) files describe the 
-capabilities of each printer and are used by CUPS to support 
-printer-specific features and intelligent filtering. </P>
+<P>PostScript Printer Description (&quot;PPD&quot;) files describe the
+ capabilities of each printer and are used by CUPS to support
+ printer-specific features and intelligent filtering.</P>
 <H3><A NAME="3_5_1">3.5.1 PPD Specification</A></H3>
-<P>The PPD file format is described in <A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
- Adobe TechNote #5003: PostScript Printer Description File Format 
-Specification Version 4.3</A>. </P>
+<P>The PPD file format is described in<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+ Adobe TechNote #5003: PostScript Printer Description File Format
+ Specification Version 4.3</A>.</P>
 <H3><A NAME="3_5_2">3.5.2 CUPS Extensions to PPD Files</A></H3>
-<P>CUPS adds several new attributes that are described below. </P>
+<P>CUPS adds several new attributes that are described below.</P>
 <H4>3.5.2.1 cupsFilter</H4>
-<P>This string attribute provides a conversion rule of the form: </P>
+<P>This string attribute provides a conversion rule of the form:</P>
 <UL>
 <PRE>
 source/type cost program
 </PRE>
 </UL>
-<P>The destination type is assumed to the printer's type. If a printer 
-supports the source type directly the special filter program &quot;-&quot; may be 
-specified. </P>
+<P>The destination type is assumed to the printer's type. If a printer
+ supports the source type directly the special filter program &quot;-&quot; may be
+ specified.</P>
 <H4>3.5.2.2 cupsManualCopies</H4>
-<P>This boolean attribute notifies the RIP filters that the destination 
-printer does not support copy generation in hardware. The default value 
-is false. </P>
+<P>This boolean attribute notifies the RIP filters that the destination
+ printer does not support copy generation in hardware. The default value
+ is false.</P>
 <H4>3.5.2.3 cupsModelNumber</H4>
-<P>This integer attribute specifies a printer-specific model number. 
-This number can be used by a filter program to adjust the output for a 
-specific model of printer. </P>
+<P>This integer attribute specifies a printer-specific model number.
+ This number can be used by a filter program to adjust the output for a
+ specific model of printer.</P>
 <H4>3.5.2.4 cupsProfile</H4>
-<P>This string attribute specifies a color profile of the form: </P>
+<P>This string attribute specifies a color profile of the form:</P>
 <UL>
 <PRE>
 resolution/type density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22
 </PRE>
 </UL>
-<P>The <I>resolution</I> and <I>type</I> values may be &quot;-&quot; to act as a 
-wildcard. Otherwise they must match one of the <CODE>Resolution</CODE>
- or <CODE>MediaType</CODE> attributes defined in the PPD file. </P>
-<P>The <I>density</I> and <I>gamma</I> values define gamma and density 
-adjustment function such that: </P>
+<P>The<I> resolution</I> and<I> type</I> values may be &quot;-&quot; to act as a
+ wildcard. Otherwise they must match one of the <CODE>Resolution</CODE>
+ or <CODE>MediaType</CODE> attributes defined in the PPD file.</P>
+<P>The<I> density</I> and<I> gamma</I> values define gamma and density
+ adjustment function such that:</P>
 <UL>
 <PRE>
 f(x) = density * x<SUP>gamma</SUP>
 </PRE>
 </UL>
-<P>The <I>m00</I> through <I>m22</I> values define a 3x3 transformation 
-matrix for the CMY color values. The density function is applied <I>
-after</I> the CMY transformation. </P>
+<P>The<I> m00</I> through<I> m22</I> values define a 3x3 transformation
+ matrix for the CMY color values. The density function is applied<I>
+ after</I> the CMY transformation.</P>
 <H4>3.5.2.5 cupsVersion</H4>
-<P>This required attribute describes which version of the CUPS IDD was 
-used for the PPD file extensions. Currently it must be the string &quot;1.0&quot; 
-or &quot;1.1&quot;. </P>
+<P>This required attribute describes which version of the CUPS IDD was
+ used for the PPD file extensions. Currently it must be the string &quot;1.0&quot;
+ or &quot;1.1&quot;.</P>
 <H2><A NAME="3_6">3.6 Scheduler Configuration Files</A></H2>
-<P>The scheduler reads three configuration files that define the 
-available printers, classes, and services: </P>
+<P>The scheduler reads three configuration files that define the
+ available printers, classes, and services:</P>
 <DL>
-<DT>classes.conf </DT>
-<DD>This file defines all of the printer classes known to the  system. </DD>
-<DT>cupsd.conf </DT>
-<DD>This file defines the files, directories, passwords, etc.  used by 
-the scheduler. </DD>
-<DT>printers.conf </DT>
-<DD>This file defines all of the printers known to the system. </DD>
+<DT>classes.conf</DT>
+<DD>This file defines all of the printer classes known to the system.</DD>
+<DT>cupsd.conf</DT>
+<DD>This file defines the files, directories, passwords, etc. used by
+ the scheduler.</DD>
+<DT>printers.conf</DT>
+<DD>This file defines all of the printers known to the system.</DD>
 </DL>
 <H3><A NAME="3_6_1">3.6.1 classes.conf</A></H3>
-<P>The classes.conf file consists of 1 or more lines of ASCII text. 
- Comment lines start with the pound (&quot;#&quot;) character. </P>
-<P>Each non-blank line starts with the name of a configuration 
-directive followed by its value. The following directives are 
-understood: 
+<P>The classes.conf file consists of 1 or more lines of ASCII text.
+ Comment lines start with the pound (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with the name of a configuration directive
+ followed by its value. The following directives are understood:
 <CENTER>
 <TABLE BORDER="1" WIDTH="90%">
 <TR><TH WIDTH="25%">Directive</TH><TH>Description</TH></TR>
 <TR><TD>&lt;Class name&gt;
 <BR> &lt;/Class&gt;</TD><TD>Surrounds a class definition.</TD></TR>
 <TR><TD>&lt;DefaultClass name&gt;
-<BR> &lt;/Class&gt;</TD><TD>Surrounds a class definition for the default 
-destination.</TD></TR>
-<TR><TD>Accepting</TD><TD>Specifies whether the class is accepting new 
-jobs. May be  the names &quot;Yes&quot; or &quot;No&quot;.</TD></TR>
-<TR><TD>AllowUsers</TD><TD>Specifies a list of users that are allowed 
-to access the class.</TD></TR>
-<TR><TD>BannerStart</TD><TD>Specifies the banner that is printed before 
-other files in a  job.</TD></TR>
-<TR><TD>BannerEnd</TD><TD>Specifies the banner that is printed after 
-other files in a  job.</TD></TR>
-<TR><TD>DenyUsers</TD><TD>Specifies a list of users that are not 
-allowed to access the  class.</TD></TR>
+<BR> &lt;/Class&gt;</TD><TD>Surrounds a class definition for the default
+ destination.</TD></TR>
+<TR><TD>Accepting</TD><TD>Specifies whether the class is accepting new
+ jobs. May be the names &quot;Yes&quot; or &quot;No&quot;.</TD></TR>
+<TR><TD>AllowUsers</TD><TD>Specifies a list of users that are allowed to
+ access the class.</TD></TR>
+<TR><TD>BannerStart</TD><TD>Specifies the banner that is printed before
+ other files in a job.</TD></TR>
+<TR><TD>BannerEnd</TD><TD>Specifies the banner that is printed after
+ other files in a job.</TD></TR>
+<TR><TD>DenyUsers</TD><TD>Specifies a list of users that are not allowed
+ to access the class.</TD></TR>
 <TR><TD>Info</TD><TD>A textual description of the class.</TD></TR>
 <TR><TD>Location</TD><TD>A textual location of the class.</TD></TR>
-<TR><TD>Printer</TD><TD>Specifies a printer that is a member of the 
-class.</TD></TR>
-<TR><TD>State</TD><TD>Specifies the initial state of the class; can be 
-&quot;Idle&quot; or  &quot;Stopped&quot;.</TD></TR>
-<TR><TD>StateMessage</TD><TD>Specifies a textual message for the 
-current class state.</TD></TR>
+<TR><TD>Printer</TD><TD>Specifies a printer that is a member of the
+ class.</TD></TR>
+<TR><TD>State</TD><TD>Specifies the initial state of the class; can be
+ &quot;Idle&quot; or &quot;Stopped&quot;.</TD></TR>
+<TR><TD>StateMessage</TD><TD>Specifies a textual message for the current
+ class state.</TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H3><A NAME="3_6_2">3.6.2 cupsd.conf</A></H3>
-<P>The cupsd.conf file consists of 1 or more lines of ASCII text. 
- Comment lines start with the pound (&quot;#&quot;) character. </P>
-<P>Each non-blank line starts with the name of a configuration 
-directive followed by its value. The following directives are 
-understood: 
+<P>The cupsd.conf file consists of 1 or more lines of ASCII text.
+ Comment lines start with the pound (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with the name of a configuration directive
+ followed by its value. The following directives are understood:
 <CENTER>
 <TABLE BORDER="1" WIDTH="90%">
 <TR><TH WIDTH="25%">Directive</TH><TH>Default</TH><TH>Description</TH></TR>
-<TR><TD>AccessLog</TD><TD>access_log</TD><TD>Specifies the location of 
-the access log file. The special name  &quot;syslog&quot; can be used to send 
-access log information to the system  log.</TD></TR>
-<TR><TD>Allow</TD><TD>-</TD><TD>Allows connections from the specified 
-host, network, or  domain.</TD></TR>
-<TR><TD>AuthClass</TD><TD>-</TD><TD>Specifies what level of 
-authentication is required; may be  &quot;User&quot;, &quot;System&quot;, or &quot;Group&quot;.</TD></TR>
-<TR><TD>AuthType</TD><TD>None</TD><TD>Specifies the type of 
-authentication to perform; may be  &quot;None&quot;, &quot;Basic&quot;, or &quot;Digest&quot;.</TD></TR>
-<TR><TD>BrowseAddress</TD><TD>255.255.255.255</TD><TD>Specifies a 
-broadcast address to send CUPS browsing packets to.</TD></TR>
-<TR><TD>BrowseAllow</TD><TD>-</TD><TD>Specifies hosts or addresses from 
-which browsing information  should be used.</TD></TR>
-<TR><TD>BrowseDeny</TD><TD>-</TD><TD>Specifies hosts or addresses from 
-which browsing information  should not be used.</TD></TR>
-<TR><TD>BrowseInterval</TD><TD>30</TD><TD>Specifies the number of 
-seconds between browsing updates. A  browse interval of 0 seconds 
-disables outgoing packets.</TD></TR>
-<TR><TD>BrowseOrder</TD><TD>Allow,Deny</TD><TD>Specifies the order of 
-BrowseAllow and BrowseDeny directive  processing; can be &quot;Deny,Allow&quot; 
-to implicitly deny hosts unless  they are allowed by a BrowseAllow 
-line, or &quot;Allow,Deny&quot; to  implicitly allow hosts unless they are denied 
-by a BrowseDeny  line.</TD></TR>
-<TR><TD>BrowsePoll</TD><TD>-</TD><TD>Specifies a server to poll for 
-available printers and classes.</TD></TR>
-<TR><TD>BrowsePort</TD><TD>631</TD><TD>Specifies the UDP port number to 
-use for browse packets.</TD></TR>
-<TR><TD>BrowseRelay</TD><TD>-</TD><TD>Specifies a source and 
-destination address for relaying browser  information from one subnet 
-to another.</TD></TR>
-<TR><TD>BrowseShortNames</TD><TD>yes</TD><TD>Specifies whether or not 
-to provide short names (without the  &quot;@server&quot; part) for remote 
-printers.</TD></TR>
-<TR><TD>BrowseTimeout</TD><TD>300</TD><TD>Specifies the number of 
-seconds to wait until remote destinations  are removed from the local 
-destination list.</TD></TR>
-<TR><TD>Browsing</TD><TD>On</TD><TD>Specifies whether or not printer 
-and class browsing is enabled; can  be &quot;On&quot; or &quot;Off&quot;.</TD></TR>
-<TR><TD>DataDir</TD><TD>/usr/share/cups</TD><TD>Specifies the directory 
-where CUPS data files are stored.</TD></TR>
-<TR><TD>DefaultCharset</TD><TD>iso-8859-1</TD><TD>Specifies the default 
-character set.</TD></TR>
-<TR><TD>DefaultLanguage</TD><TD>current locale</TD><TD>Specifies the 
-default language.</TD></TR>
-<TR><TD>Deny</TD><TD>-</TD><TD>Refuses connections from the specified 
-host, network, or  domain.</TD></TR>
-<TR><TD>DocumentRoot</TD><TD>/usr/share/doc/cups</TD><TD>Specifies the 
-document data root directory.</TD></TR>
-<TR><TD>ErrorLog</TD><TD>error_log</TD><TD>Specifies the error log file 
-location. The special name  &quot;syslog&quot; can be used to send error log 
-information to the system  log.</TD></TR>
-<TR><TD>Group</TD><TD>root, sys, system</TD><TD>Specifies the group 
-name or ID that is used when running  external programs.</TD></TR>
-<TR><TD>HostNameLookups</TD><TD>Off</TD><TD>Specifies whether or not to 
-perform reverse IP address lookups to  get the actual hostname; may be 
-&quot;On&quot; or &quot;Off&quot;. Hostname lookups can  significantly degrade the 
-performance of the CUPS server if one or  more DNS servers is not 
-functioning properly.</TD></TR>
-<TR><TD>ImplicitClasses</TD><TD>On</TD><TD>Specifies whether or not to 
-automatically create printer classes  when more than one printer or 
-class of the same name is detected on  the network; may be &quot;On&quot; or 
-&quot;Off&quot;.</TD></TR>
-<TR><TD>KeepAlive</TD><TD>On</TD><TD>Specifies whether or not to use 
-the HTTP Keep-Alive feature; may  be &quot;On&quot; or &quot;Off&quot;.</TD></TR>
-<TR><TD>KeepAliveTimeout</TD><TD>30</TD><TD>Specifies the amount of 
-time to keep the HTTP connection alive  before closing it.</TD></TR>
+<TR><TD>AccessLog</TD><TD>access_log</TD><TD>Specifies the location of
+ the access log file. The special name &quot;syslog&quot; can be used to send
+ access log information to the system log.</TD></TR>
+<TR><TD>Allow</TD><TD>-</TD><TD>Allows connections from the specified
+ host, network, or domain.</TD></TR>
+<TR><TD>AuthClass</TD><TD>-</TD><TD>Specifies what level of
+ authentication is required; may be &quot;User&quot;, &quot;System&quot;, or &quot;Group&quot;.</TD></TR>
+<TR><TD>AuthType</TD><TD>None</TD><TD>Specifies the type of
+ authentication to perform; may be &quot;None&quot;, &quot;Basic&quot;, or &quot;Digest&quot;.</TD></TR>
+<TR><TD>BrowseAddress</TD><TD>255.255.255.255</TD><TD>Specifies a
+ broadcast address to send CUPS browsing packets to.</TD></TR>
+<TR><TD>BrowseAllow</TD><TD>-</TD><TD>Specifies hosts or addresses from
+ which browsing information should be used.</TD></TR>
+<TR><TD>BrowseDeny</TD><TD>-</TD><TD>Specifies hosts or addresses from
+ which browsing information should not be used.</TD></TR>
+<TR><TD>BrowseInterval</TD><TD>30</TD><TD>Specifies the number of
+ seconds between browsing updates. A browse interval of 0 seconds
+ disables outgoing packets.</TD></TR>
+<TR><TD>BrowseOrder</TD><TD>Allow,Deny</TD><TD>Specifies the order of
+ BrowseAllow and BrowseDeny directive processing; can be &quot;Deny,Allow&quot; to
+ implicitly deny hosts unless they are allowed by a BrowseAllow line, or
+ &quot;Allow,Deny&quot; to implicitly allow hosts unless they are denied by a
+ BrowseDeny line.</TD></TR>
+<TR><TD>BrowsePoll</TD><TD>-</TD><TD>Specifies a server to poll for
+ available printers and classes.</TD></TR>
+<TR><TD>BrowsePort</TD><TD>631</TD><TD>Specifies the UDP port number to
+ use for browse packets.</TD></TR>
+<TR><TD>BrowseRelay</TD><TD>-</TD><TD>Specifies a source and destination
+ address for relaying browser information from one subnet to another.</TD>
+</TR>
+<TR><TD>BrowseShortNames</TD><TD>yes</TD><TD>Specifies whether or not to
+ provide short names (without the &quot;@server&quot; part) for remote printers.</TD>
+</TR>
+<TR><TD>BrowseTimeout</TD><TD>300</TD><TD>Specifies the number of
+ seconds to wait until remote destinations are removed from the local
+ destination list.</TD></TR>
+<TR><TD>Browsing</TD><TD>On</TD><TD>Specifies whether or not printer and
+ class browsing is enabled; can be &quot;On&quot; or &quot;Off&quot;.</TD></TR>
+<TR><TD>DataDir</TD><TD>/usr/share/cups</TD><TD>Specifies the directory
+ where CUPS data files are stored.</TD></TR>
+<TR><TD>DefaultCharset</TD><TD>iso-8859-1</TD><TD>Specifies the default
+ character set.</TD></TR>
+<TR><TD>DefaultLanguage</TD><TD>current locale</TD><TD>Specifies the
+ default language.</TD></TR>
+<TR><TD>Deny</TD><TD>-</TD><TD>Refuses connections from the specified
+ host, network, or domain.</TD></TR>
+<TR><TD>DocumentRoot</TD><TD>/usr/share/doc/cups</TD><TD>Specifies the
+ document data root directory.</TD></TR>
+<TR><TD>ErrorLog</TD><TD>error_log</TD><TD>Specifies the error log file
+ location. The special name &quot;syslog&quot; can be used to send error log
+ information to the system log.</TD></TR>
+<TR><TD>Group</TD><TD>root, sys, system</TD><TD>Specifies the group name
+ or ID that is used when running external programs.</TD></TR>
+<TR><TD>HostNameLookups</TD><TD>Off</TD><TD>Specifies whether or not to
+ perform reverse IP address lookups to get the actual hostname; may be
+ &quot;On&quot; or &quot;Off&quot;. Hostname lookups can significantly degrade the
+ performance of the CUPS server if one or more DNS servers is not
+ functioning properly.</TD></TR>
+<TR><TD>ImplicitClasses</TD><TD>On</TD><TD>Specifies whether or not to
+ automatically create printer classes when more than one printer or
+ class of the same name is detected on the network; may be &quot;On&quot; or
+ &quot;Off&quot;.</TD></TR>
+<TR><TD>KeepAlive</TD><TD>On</TD><TD>Specifies whether or not to use the
+ HTTP Keep-Alive feature; may be &quot;On&quot; or &quot;Off&quot;.</TD></TR>
+<TR><TD>KeepAliveTimeout</TD><TD>30</TD><TD>Specifies the amount of time
+ to keep the HTTP connection alive before closing it.</TD></TR>
 <TR><TD>&lt;Location path&gt;
-<BR> &lt;/Location&gt;</TD><TD>-</TD><TD>Specifies a location to restrict 
-access to.</TD></TR>
-<TR><TD>LogLevel</TD><TD>info</TD><TD>Controls the amount of 
-information that is logged in the  error log file. Can be one of 
-&quot;debug&quot;, &quot;info&quot;, &quot;warn&quot;, &quot;error&quot;,  or &quot;none&quot;, in decreasing order or 
-verbosity.</TD></TR>
-<TR><TD>MaxClients</TD><TD>100</TD><TD>Specifies the maximum number of 
-simultaneous active clients.  This value is internally limited to 1/3 
-of the total number of  available file descriptors.</TD></TR>
-<TR><TD>MaxLogSize</TD><TD>0</TD><TD>Specifies the maximum size of the 
-access, error, and page  log files in bytes. If set to 0 then no 
-maximum size is set.  Log files are rotated automatically when this 
-size is  exceeded.</TD></TR>
-<TR><TD>MaxRequestSize</TD><TD>0</TD><TD>Specifies the maximum size of 
-HTTP requests in bytes. If set to 0  then there is no maximum.</TD></TR>
-<TR><TD>Order</TD><TD>Allow,Deny</TD><TD>Specifies the order of Allow 
-and Deny directive processing; can  be &quot;Deny,Allow&quot; to implicitly deny 
-hosts unless they are allowed by  an Allow line, or &quot;Allow,Deny&quot; to 
-implicitly allow hosts unless they  are denied by a Deny line.</TD></TR>
-<TR><TD>PageLog</TD><TD>page_log</TD><TD>Specifies the location of the 
-page log file. The special name  &quot;syslog&quot; can be used to send page log 
-information to the system  log.</TD></TR>
-<TR><TD>Port</TD><TD>631</TD><TD>Specifies a port number to listen to 
-for HTTP connections.</TD></TR>
-<TR><TD>Printcap</TD><TD>/etc/printcap</TD><TD>Specifies the location 
-of a Berkeley printcap file to update  with a list of current printers 
-and classes. If no filename is  supplied then this automatic generation 
-is disabled.</TD></TR>
-<TR><TD>RequestRoot</TD><TD>/var/spool/cups</TD><TD>Specifies the 
-location of request files.</TD></TR>
-<TR><TD>RIPCache</TD><TD>8m</TD><TD>Specifies the size of the memory 
-cache in bytes that is used by  RIP filters.</TD></TR>
-<TR><TD>ServerAdmin</TD><TD>root@ServerName</TD><TD>Specifies the 
-person to contact with problems.</TD></TR>
-<TR><TD>ServerName</TD><TD>hostname</TD><TD>Specifies the hostname that 
-is supplied to HTTP clients. This  is also used to determine the 
-default CUPS server for the CUPS IPP  client applications.</TD></TR>
-<TR><TD>ServerRoot</TD><TD>/etc/cups</TD><TD>Specifies the root 
-directory for server configuration files.</TD></TR>
-<TR><TD>SystemGroup</TD><TD>root, sys, system</TD><TD>Specifies the 
-group name used for System class authentication.</TD></TR>
-<TR><TD>TempDir</TD><TD>/var/tmp</TD><TD>Specifies the temporary 
-directory to use.</TD></TR>
-<TR><TD>Timeout</TD><TD>300</TD><TD>The timeout in seconds before 
-client connections are closed  in the middle of a request.</TD></TR>
-<TR><TD>User</TD><TD>lp</TD><TD>Specifies the user that is used when 
-running external programs.</TD></TR>
+<BR> &lt;/Location&gt;</TD><TD>-</TD><TD>Specifies a location to restrict
+ access to.</TD></TR>
+<TR><TD>LogLevel</TD><TD>info</TD><TD>Controls the amount of information
+ that is logged in the error log file. Can be one of &quot;debug&quot;, &quot;info&quot;,
+ &quot;warn&quot;, &quot;error&quot;, or &quot;none&quot;, in decreasing order or verbosity.</TD></TR>
+<TR><TD>MaxClients</TD><TD>100</TD><TD>Specifies the maximum number of
+ simultaneous active clients. This value is internally limited to 1/3 of
+ the total number of available file descriptors.</TD></TR>
+<TR><TD>MaxLogSize</TD><TD>0</TD><TD>Specifies the maximum size of the
+ access, error, and page log files in bytes. If set to 0 then no maximum
+ size is set. Log files are rotated automatically when this size is
+ exceeded.</TD></TR>
+<TR><TD>MaxRequestSize</TD><TD>0</TD><TD>Specifies the maximum size of
+ HTTP requests in bytes. If set to 0 then there is no maximum.</TD></TR>
+<TR><TD>Order</TD><TD>Allow,Deny</TD><TD>Specifies the order of Allow
+ and Deny directive processing; can be &quot;Deny,Allow&quot; to implicitly deny
+ hosts unless they are allowed by an Allow line, or &quot;Allow,Deny&quot; to
+ implicitly allow hosts unless they are denied by a Deny line.</TD></TR>
+<TR><TD>PageLog</TD><TD>page_log</TD><TD>Specifies the location of the
+ page log file. The special name &quot;syslog&quot; can be used to send page log
+ information to the system log.</TD></TR>
+<TR><TD>Port</TD><TD>631</TD><TD>Specifies a port number to listen to
+ for HTTP connections.</TD></TR>
+<TR><TD>Printcap</TD><TD>/etc/printcap</TD><TD>Specifies the location of
+ a Berkeley printcap file to update with a list of current printers and
+ classes. If no filename is supplied then this automatic generation is
+ disabled.</TD></TR>
+<TR><TD>RequestRoot</TD><TD>/var/spool/cups</TD><TD>Specifies the
+ location of request files.</TD></TR>
+<TR><TD>RIPCache</TD><TD>8m</TD><TD>Specifies the size of the memory
+ cache in bytes that is used by RIP filters.</TD></TR>
+<TR><TD>ServerAdmin</TD><TD>root@ServerName</TD><TD>Specifies the person
+ to contact with problems.</TD></TR>
+<TR><TD>ServerName</TD><TD>hostname</TD><TD>Specifies the hostname that
+ is supplied to HTTP clients. This is also used to determine the default
+ CUPS server for the CUPS IPP client applications.</TD></TR>
+<TR><TD>ServerRoot</TD><TD>/etc/cups</TD><TD>Specifies the root
+ directory for server configuration files.</TD></TR>
+<TR><TD>SystemGroup</TD><TD>root, sys, system</TD><TD>Specifies the
+ group name used for System class authentication.</TD></TR>
+<TR><TD>TempDir</TD><TD>/var/tmp</TD><TD>Specifies the temporary
+ directory to use.</TD></TR>
+<TR><TD>Timeout</TD><TD>300</TD><TD>The timeout in seconds before client
+ connections are closed in the middle of a request.</TD></TR>
+<TR><TD>User</TD><TD>lp</TD><TD>Specifies the user that is used when
+ running external programs.</TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H3><A NAME="3_6_3">3.6.3 printers.conf</A></H3>
-<P>The printers.conf file consists of 1 or more lines of ASCII text. 
- Comment lines start with the pound (&quot;#&quot;) character. </P>
-<P>Each non-blank line starts with the name of a configuration 
-directive followed by its value. The following directives are 
-understood: 
+<P>The printers.conf file consists of 1 or more lines of ASCII text.
+ Comment lines start with the pound (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with the name of a configuration directive
+ followed by its value. The following directives are understood:
 <CENTER>
 <TABLE BORDER="1" WIDTH="90%">
 <TR><TH WIDTH="25%">Directive</TH><TH>Description</TH></TR>
-<TR><TD>Accepting</TD><TD>Specifies whether the printer is accepting 
-new jobs. May be  the names &quot;Yes&quot; or &quot;No&quot;.</TD></TR>
+<TR><TD>Accepting</TD><TD>Specifies whether the printer is accepting new
+ jobs. May be the names &quot;Yes&quot; or &quot;No&quot;.</TD></TR>
 <TR><TD>&lt;DefaultPrinter name&gt;
-<BR> &lt;/Printer&gt;</TD><TD>Surrounds the printer definition for a default 
-destination.</TD></TR>
-<TR><TD>AllowUsers</TD><TD>Specifies a list of users that are allowed 
-to access the printer.</TD></TR>
-<TR><TD>BannerStart</TD><TD>Specifies the banner that is printed before 
-other files in a  job.</TD></TR>
-<TR><TD>BannerEnd</TD><TD>Specifies the banner that is printed after 
-other files in a  job.</TD></TR>
-<TR><TD>DenyUsers</TD><TD>Specifies a list of users that are not 
-allowed to access the  printer.</TD></TR>
-<TR><TD>DeviceURI</TD><TD>Specifies the device-uri attribute for the 
-printer.</TD></TR>
+<BR> &lt;/Printer&gt;</TD><TD>Surrounds the printer definition for a default
+ destination.</TD></TR>
+<TR><TD>AllowUsers</TD><TD>Specifies a list of users that are allowed to
+ access the printer.</TD></TR>
+<TR><TD>BannerStart</TD><TD>Specifies the banner that is printed before
+ other files in a job.</TD></TR>
+<TR><TD>BannerEnd</TD><TD>Specifies the banner that is printed after
+ other files in a job.</TD></TR>
+<TR><TD>DenyUsers</TD><TD>Specifies a list of users that are not allowed
+ to access the printer.</TD></TR>
+<TR><TD>DeviceURI</TD><TD>Specifies the device-uri attribute for the
+ printer.</TD></TR>
 <TR><TD>Info</TD><TD>A textual description of the printer.</TD></TR>
 <TR><TD>Location</TD><TD>A textual location of the printer.</TD></TR>
 <TR><TD>&lt;Printer name&gt;
 <BR> &lt;/Printer&gt;</TD><TD>Surrounds the printer definition.</TD></TR>
-<TR><TD>State</TD><TD>Specifies the initial state of the printer; can 
-be &quot;Idle&quot; or  &quot;Stopped&quot;.</TD></TR>
-<TR><TD>StateMessage</TD><TD>Specifies a textual message for the 
-current printer state.</TD></TR>
+<TR><TD>State</TD><TD>Specifies the initial state of the printer; can be
+ &quot;Idle&quot; or &quot;Stopped&quot;.</TD></TR>
+<TR><TD>StateMessage</TD><TD>Specifies a textual message for the current
+ printer state.</TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H1><A NAME="4">4 External Interfaces</A></H1>
 <H2><A NAME="4_1">4.1 AppSocket Protocol</A></H2>
-<P>The AppSocket protocol is an 8-bit clean TCP/IP socket connection. 
-The default IP service port is 9100. The URI method name is &quot;socket&quot;. </P>
-<P>The AppSocket protocol is used by the Hewlett Packard JetDirect 
-network interfaces and print servers, as well as many other vendors' 
-products. See the CUPS Software Administrators Manual for a list of 
-supported products. </P>
+<P>The AppSocket protocol is an 8-bit clean TCP/IP socket connection.
+ The default IP service port is 9100. The URI method name is &quot;socket&quot;.</P>
+<P>The AppSocket protocol is used by the Hewlett Packard JetDirect
+ network interfaces and print servers, as well as many other vendors'
+ products. See the CUPS Software Administrators Manual for a list of
+ supported products.</P>
 <H2><A NAME="4_2">4.2 CUPS Browsing Protocol</A></H2>
-<P>The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By 
-default this service operates on IP service port 631. </P>
-<P>Each broadcast packet describes the state of a single printer or 
-class and is an ASCII text string of up to 1450 bytes ending with a 
-newline (0x0a). The string is formatted as follows: </P>
+<P>The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By
+ default this service operates on IP service port 631.</P>
+<P>Each broadcast packet describes the state of a single printer or
+ class and is an ASCII text string of up to 1450 bytes ending with a
+ newline (0x0a). The string is formatted as follows:</P>
 <UL>
 <PRE>
 type SP state SP uri SP &quot;location&quot; SP &quot;info&quot; SP &quot;make-and-model&quot; NL
 </PRE>
 </UL>
-<P><VAR>State, uri, location, info</VAR>, and <VAR>make-and-model</VAR>
-, correspond to the IPP <CODE>printer-state</CODE>, <CODE>
+<P><VAR>State, uri, location, info</VAR>, and<VAR> make-and-model</VAR>,
+ correspond to the IPP <CODE>printer-state</CODE>, <CODE>
 printer-uri-supported</CODE>, <CODE>printer-location</CODE>, <CODE>
-printer-info</CODE>, and <CODE>printer-make-and-model</CODE>
- attributes. </P>
-<P><VAR>Type</VAR> is a hexadecimal number string representing 
-capability/type bits: 
+printer-info</CODE>, and <CODE>printer-make-and-model</CODE> attributes.</P>
+<P><VAR>Type</VAR> is a hexadecimal number string representing
+ capability/type bits:
 <CENTER>
 <TABLE BORDER="1" WIDTH="40%">
 <TR><TH WIDTH="8%">Bit</TH><TH>Description</TH></TR>
@@ -657,12 +652,12 @@ capability/type bits:
 </P>
 <H2><A NAME="4_3">4.3 CUPS Form File</A></H2>
 <P>CUPS Form files are XML files used by the CUPS <CODE>formtops</CODE>
- filter to produce dynamic banner pages and support preprinted forms. </P>
+ filter to produce dynamic banner pages and support preprinted forms.</P>
 <P>The MIME type for CUPS Form files is <CODE>application/vnd.cups-form</CODE>
-. </P>
+.</P>
 <H3><A NAME="4_3_1">4.3.1 CUPS Form DTD</A></H3>
-<P>The following DTD describes the available elements and attributes in 
-a CUPS Form file: 
+<P>The following DTD describes the available elements and attributes in
+ a CUPS Form file:
 <CENTER>
 <TABLE BORDER>
 <TR><TD>
@@ -840,27 +835,27 @@ a CUPS Form file:
 </CENTER>
 </P>
 <H2><A NAME="4_4">4.4 CUPS PostScript File</A></H2>
-<P>CUPS PostScript files are device-dependent Adobe PostScript program 
-files. The PostScript language is described in the <A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
- Adobe PostScript Language Reference Manual, Third Edition</A>. </P>
+<P>CUPS PostScript files are device-dependent Adobe PostScript program
+ files. The PostScript language is described in the<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+ Adobe PostScript Language Reference Manual, Third Edition</A>.</P>
 <P>The MIME type for CUPS PostScript files is <CODE>
-application/vnd.cups-postscript</CODE>. </P>
+application/vnd.cups-postscript</CODE>.</P>
 <H2><A NAME="4_5">4.5 CUPS Raster File</A></H2>
-<P>CUPS raster files are device-dependent raster image files that 
-contain a PostScript page device dictionary and device-dependent raster 
-imagery for each page in the document. These files are used to transfer 
-raster data from the PostScript and image file RIPs to device-dependent 
-filters that convert the raster data to a printable format. </P>
-<P>A raster file begins with a four byte synchronization word: 
-0x52615374 (&quot;RaSt&quot;) for big-endian architectures and 0x74536152 
-(&quot;tSaR&quot;) for little-endian architectures.  The writer of the raster 
-file will use the native word order, and the reader is responsible for 
-detecting a reversed word order file and swapping bytes as needed. The 
-CUPS Image Library raster functions perform this function 
-automatically. </P>
-<P>Following the synchronization word are a series of raster pages. 
- Each page starts with a page device dictionary header and is followed 
-immediately by the raster data for that page. 
+<P>CUPS raster files are device-dependent raster image files that
+ contain a PostScript page device dictionary and device-dependent raster
+ imagery for each page in the document. These files are used to transfer
+ raster data from the PostScript and image file RIPs to device-dependent
+ filters that convert the raster data to a printable format.</P>
+<P>A raster file begins with a four byte synchronization word:
+ 0x52615374 (&quot;RaSt&quot;) for big-endian architectures and 0x74536152
+ (&quot;tSaR&quot;) for little-endian architectures. The writer of the raster file
+ will use the native word order, and the reader is responsible for
+ detecting a reversed word order file and swapping bytes as needed. The
+ CUPS Image Library raster functions perform this function
+ automatically.</P>
+<P>Following the synchronization word are a series of raster pages. Each
+ page starts with a page device dictionary header and is followed
+ immediately by the raster data for that page.
 <CENTER>
 <TABLE BORDER="1" WIDTH="80%">
 <TR><TH WIDTH="10%">Bytes</TH><TH WIDTH="20%">Description</TH><TH>Values</TH>
@@ -872,8 +867,8 @@ immediately by the raster data for that page.
 </TR>
 <TR><TD>192-255</TD><TD>OutputType</TD><TD>Nul-terminated ASCII string</TD>
 </TR>
-<TR><TD>256-259</TD><TD>AdvanceDistance</TD><TD>0 to 2<SUP>32</SUP> - 1 
-points</TD></TR>
+<TR><TD>256-259</TD><TD>AdvanceDistance</TD><TD>0 to 2<SUP>32</SUP> - 1
+ points</TD></TR>
 <TR><TD>260-263</TD><TD>AdvanceMedia</TD><TD>0 = Never advance roll
 <BR> 1 = Advance roll after file
 <BR> 2 = Advance roll after job
@@ -888,13 +883,13 @@ points</TD></TR>
 <BR> 4 = Cut roll after page</TD></TR>
 <TR><TD>272-275</TD><TD>Duplex</TD><TD>0 = Print single-sided
 <BR> 1 = Print double-sided</TD></TR>
-<TR><TD>276-283</TD><TD>HWResolution</TD><TD>Horizontal and vertical 
-resolution in dots-per-inch.</TD></TR>
-<TR><TD>284-299</TD><TD>ImagingBoundingBox</TD><TD>Four integers giving 
-the left, bottom, right, and top positions  of the page bounding box in 
-points</TD></TR>
-<TR><TD>300-303</TD><TD>InsertSheet</TD><TD>0 = Do not insert separator 
-sheets
+<TR><TD>276-283</TD><TD>HWResolution</TD><TD>Horizontal and vertical
+ resolution in dots-per-inch.</TD></TR>
+<TR><TD>284-299</TD><TD>ImagingBoundingBox</TD><TD>Four integers giving
+ the left, bottom, right, and top positions of the page bounding box in
+ points</TD></TR>
+<TR><TD>300-303</TD><TD>InsertSheet</TD><TD>0 = Do not insert separator
+ sheets
 <BR> 1 = Insert separator sheets</TD></TR>
 <TR><TD>304-307</TD><TD>Jog</TD><TD>0 = Do no jog pages
 <BR> 1 = Jog pages after file
@@ -904,15 +899,15 @@ sheets
 <BR> 1 = Right edge is first
 <BR> 2 = Bottom edge is first
 <BR> 3 = Left edge is first</TD></TR>
-<TR><TD>312-319</TD><TD>Margins</TD><TD>Left and bottom origin of image 
-in points</TD></TR>
-<TR><TD>320-323</TD><TD>ManualFeed</TD><TD>0 = Do not manually feed 
-media
+<TR><TD>312-319</TD><TD>Margins</TD><TD>Left and bottom origin of image
+ in points</TD></TR>
+<TR><TD>320-323</TD><TD>ManualFeed</TD><TD>0 = Do not manually feed
+ media
 <BR> 1 = Manually feed media</TD></TR>
-<TR><TD>324-327</TD><TD>MediaPosition</TD><TD>Input slot position from 
-0 to N</TD></TR>
-<TR><TD>328-331</TD><TD>MediaWeight</TD><TD>Media weight in grams per 
-meter squared</TD></TR>
+<TR><TD>324-327</TD><TD>MediaPosition</TD><TD>Input slot position from 0
+ to N</TD></TR>
+<TR><TD>328-331</TD><TD>MediaWeight</TD><TD>Media weight in grams per
+ meter squared</TD></TR>
 <TR><TD>332-335</TD><TD>MirrorPrint</TD><TD>0 = Do not mirror prints
 <BR> 1 = Mirror prints</TD></TR>
 <TR><TD>336-339</TD><TD>NegativePrint</TD><TD>0 = Do not invert prints
@@ -927,24 +922,24 @@ meter squared</TD></TR>
 <TR><TD>352-359</TD><TD>PageSize</TD><TD>Width and length in points</TD></TR>
 <TR><TD>360-363</TD><TD>Separations</TD><TD>0 = Print composite image
 <BR> 1 = Print color separations</TD></TR>
-<TR><TD>364-367</TD><TD>TraySwitch</TD><TD>0 = Do not change trays if 
-selected tray is empty
+<TR><TD>364-367</TD><TD>TraySwitch</TD><TD>0 = Do not change trays if
+ selected tray is empty
 <BR> 1 = Change trays if selected tray is empty</TD></TR>
-<TR><TD>368-371</TD><TD>Tumble</TD><TD>0 = Do not rotate even pages 
-when duplexing
+<TR><TD>368-371</TD><TD>Tumble</TD><TD>0 = Do not rotate even pages when
+ duplexing
 <BR> 1 = Rotate even pages when duplexing</TD></TR>
 <TR><TD>372-375</TD><TD>cupsWidth</TD><TD>Width of page image in pixels</TD>
 </TR>
-<TR><TD>376-379</TD><TD>cupsHeight</TD><TD>Height of page image in 
-pixels</TD></TR>
+<TR><TD>376-379</TD><TD>cupsHeight</TD><TD>Height of page image in
+ pixels</TD></TR>
 <TR><TD>380-383</TD><TD>cupsMediaType</TD><TD>Driver-specific 0 to 2<SUP>
 32</SUP> - 1</TD></TR>
 <TR><TD>384-387</TD><TD>cupsBitsPerColor</TD><TD>1, 2, 4, 8 bits</TD></TR>
 <TR><TD>388-391</TD><TD>cupsBitsPerPixel</TD><TD>1 to 32 bits</TD></TR>
-<TR><TD>392-395</TD><TD>cupsBytesPerLine</TD><TD>1 to 2<SUP>32</SUP> - 
-1 bytes</TD></TR>
-<TR><TD>396-399</TD><TD>cupsColorOrder</TD><TD>0 = chunky pixels (CMYK 
-CMYK CMYK)
+<TR><TD>392-395</TD><TD>cupsBytesPerLine</TD><TD>1 to 2<SUP>32</SUP> - 1
+ bytes</TD></TR>
+<TR><TD>396-399</TD><TD>cupsColorOrder</TD><TD>0 = chunky pixels (CMYK
+ CMYK CMYK)
 <BR> 1 = banded pixels (CCC MMM YYY KKK)
 <BR> 2 = planar pixels (CCC... MMM... YYY... KKK...)</TD></TR>
 <TR><TD>400-403</TD><TD>cupsColorSpace</TD><TD>0 = white
@@ -969,118 +964,118 @@ CMYK CMYK)
 </CENTER>
 </P>
 <P>The MIME type for CUPS Raster files is <CODE>
-application/vnd.cups-raster</CODE>. </P>
+application/vnd.cups-raster</CODE>.</P>
 <H2><A NAME="4_6">4.6 CUPS Raw Files</A></H2>
-<P>Raw files are printer-dependent print files that are in a format 
-suitable to the destination printer (e.g. HP-PCL, HP-RTL, etc.) The 
-MIME type for CUPS Raw files is <CODE>application/vnd.cups-raw</CODE>. </P>
+<P>Raw files are printer-dependent print files that are in a format
+ suitable to the destination printer (e.g. HP-PCL, HP-RTL, etc.) The
+ MIME type for CUPS Raw files is <CODE>application/vnd.cups-raw</CODE>.</P>
 <H2><A NAME="4_7">4.7 Internet Printing Protocol</A></H2>
-<P>The Internet Printing Protocol and the CUPS extensions to it are 
-described in the CUPS Implementation of IPP document. </P>
+<P>The Internet Printing Protocol and the CUPS extensions to it are
+ described in the CUPS Implementation of IPP document.</P>
 <H2><A NAME="4_8">4.8 Line Printer Daemon Protocol</A></H2>
-<P>The Line Printer Daemon (LPD) protocol is described by <A HREF="http://www.ietf.org/rfc/rfc1179.txt">
-RFC 1179: Line Printer Daemon Protocol</A>. </P>
-<P>The URI method name for LPD is &quot;lpd&quot;. </P>
+<P>The Line Printer Daemon (LPD) protocol is described by<A HREF="http://www.ietf.org/rfc/rfc1179.txt">
+ RFC 1179: Line Printer Daemon Protocol</A>.</P>
+<P>The URI method name for LPD is &quot;lpd&quot;.</P>
 <H2><A NAME="4_9">4.9 Server Message Block Protocol</A></H2>
-<P>The Server Message Block (SMB) and related Common Internet File 
-System (CIFS) protocols are described at <A HREF="http://anu.samba.org/cifs">
-http://anu.samba.org/cifs</A>. </P>
-<P>The URI method name for SMB is &quot;smb&quot;. Support for this protocol is 
-provided via the SAMBA <CODE>smbspool(1)</CODE> program provided with 
-SAMBA 2.0.6 and higher. </P>
+<P>The Server Message Block (SMB) and related Common Internet File
+ System (CIFS) protocols are described at<A HREF="http://anu.samba.org/cifs">
+ http://anu.samba.org/cifs</A>.</P>
+<P>The URI method name for SMB is &quot;smb&quot;. Support for this protocol is
+ provided via the SAMBA <CODE>smbspool(1)</CODE> program provided with
+ SAMBA 2.0.6 and higher.</P>
 <H1><A NAME="5">5 Directories</A></H1>
 <DL>
-<DT>/etc/cups </DT>
-<DD>The scheduler configuration and MIME files reside here. </DD>
-<DT>/etc/cups/certs </DT>
-<DD>The authentication certificates reside here. </DD>
-<DT>/etc/cups/interfaces </DT>
-<DD>System V interface scripts reside here. </DD>
-<DT>/etc/cups/ppd </DT>
-<DD>This directory contains PPD files for each printer. </DD>
-<DT>/usr/bin </DT>
+<DT>/etc/cups</DT>
+<DD>The scheduler configuration and MIME files reside here.</DD>
+<DT>/etc/cups/certs</DT>
+<DD>The authentication certificates reside here.</DD>
+<DT>/etc/cups/interfaces</DT>
+<DD>System V interface scripts reside here.</DD>
+<DT>/etc/cups/ppd</DT>
+<DD>This directory contains PPD files for each printer.</DD>
+<DT>/usr/bin</DT>
 <DD>The <CODE>cancel</CODE>, <CODE>lp</CODE>, <CODE>lpq</CODE>, <CODE>
- lpr</CODE>, <CODE>lprm</CODE>, and <CODE>lpstat</CODE> commands 
reside here. </DD>
-<DT>/usr/lib, /usr/lib32 </DT>
-<DD>The shared libraries (DSOs) reside here. </DD>
-<DT>/usr/lib/cups/backend </DT>
-<DD>The backend filters reside here. </DD>
-<DT>/usr/lib/cups/cgi-bin </DT>
-<DD>The CGI programs reside here. </DD>
-<DT>/usr/lib/cups/daemon </DT>
-<DD>The polling and LPD daemons reside here. </DD>
-<DT>/usr/lib/cups/filter </DT>
-<DD>The file filters reside here. </DD>
-<DT>/usr/sbin </DT>
-<DD>The <CODE>accept</CODE>, <CODE>cupsd</CODE>, <CODE> lpadmin</CODE>, <CODE>
-lpc</CODE>, and <CODE>reject</CODE> commands reside here. </DD>
-<DT>/usr/share/cups </DT>
-<DD>This is the root directory of the CUPS static data. </DD>
-<DT>/usr/share/cups/charsets </DT>
-<DD>The character set files reside here. </DD>
-<DT>/usr/share/cups/data </DT>
-<DD>The filter data files reside here. </DD>
-<DT>/usr/share/cups/fonts </DT>
-<DD>The <CODE>pstoraster</CODE> font files reside here. </DD>
-<DT>/usr/share/cups/model </DT>
-<DD>The sample PPD files reside here. </DD>
-<DT>/usr/share/cups/pstoraster </DT>
-<DD>The <CODE>pstoraster</CODE> data files reside here. </DD>
-<DT>/usr/share/doc/cups </DT>
-<DD>The scheduler documentation files reside here. </DD>
-<DT>/var/log/cups </DT>
+lpr</CODE>, <CODE>lprm</CODE>, and <CODE>lpstat</CODE> commands reside
here.</DD>
+<DT>/usr/lib, /usr/lib32</DT>
+<DD>The shared libraries (DSOs) reside here.</DD>
+<DT>/usr/lib/cups/backend</DT>
+<DD>The backend filters reside here.</DD>
+<DT>/usr/lib/cups/cgi-bin</DT>
+<DD>The CGI programs reside here.</DD>
+<DT>/usr/lib/cups/daemon</DT>
+<DD>The polling and LPD daemons reside here.</DD>
+<DT>/usr/lib/cups/filter</DT>
+<DD>The file filters reside here.</DD>
+<DT>/usr/sbin</DT>
+<DD>The <CODE>accept</CODE>, <CODE>cupsd</CODE>, <CODE>lpadmin</CODE>, <CODE>
+lpc</CODE>, and <CODE>reject</CODE> commands reside here.</DD>
+<DT>/usr/share/cups</DT>
+<DD>This is the root directory of the CUPS static data.</DD>
+<DT>/usr/share/cups/charsets</DT>
+<DD>The character set files reside here.</DD>
+<DT>/usr/share/cups/data</DT>
+<DD>The filter data files reside here.</DD>
+<DT>/usr/share/cups/fonts</DT>
+<DD>The <CODE>pstoraster</CODE> font files reside here.</DD>
+<DT>/usr/share/cups/model</DT>
+<DD>The sample PPD files reside here.</DD>
+<DT>/usr/share/cups/pstoraster</DT>
+<DD>The <CODE>pstoraster</CODE> data files reside here.</DD>
+<DT>/usr/share/doc/cups</DT>
+<DD>The scheduler documentation files reside here.</DD>
+<DT>/var/log/cups</DT>
 <DD>The <CODE>access_log</CODE>, <CODE>error_log</CODE>, and <CODE>
- page_log</CODE> files reside here. </DD>
-<DT>/var/spool/cups </DT>
-<DD>This directory contains print job files. </DD>
+page_log</CODE> files reside here.</DD>
+<DT>/var/spool/cups</DT>
+<DD>This directory contains print job files.</DD>
 </DL>
 <H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
 <H2><A NAME="6_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="6_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 </BODY>
 </HTML>
index 8857c0288f6f6766f4a03250e278099006d430ce..6b174d49a8e5fa40ac94e27f284c9cc45ab2afcf 100644 (file)
Binary files a/doc/idd.pdf and b/doc/idd.pdf differ
index 6a468e4f9be437d67186f7ae1e20c22a5a619850..c27b5fb43879d857b91bd3ed8ba3eb63eea761c1 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Implementation of IPP</TITLE>
+<TITLE>CUPS Implementation of IPP</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001 All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-IPP-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Implementation of IPP</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Implementation of IPP</H1></A><BR>
 CUPS-IPP-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001 All Rights Reserved<BR>
@@ -148,23 +148,24 @@ Copyright 1997-2001 All Rights Reserved<BR>
 <LI><A HREF="#5_2_7">5.2.7 hue (integer(-180:180))</A></LI>
 <LI><A HREF="#5_2_8">5.2.8 job-billing (text(MAX))</A></LI>
 <LI><A HREF="#5_2_9">5.2.9 job-hold-until (keyword | name(MAX))</A></LI>
-<LI><A HREF="#5_2_10">5.2.10 job-sheets (1setof type3 keyword | 
-name(MAX))</A></LI>
+<LI><A HREF="#5_2_10">5.2.10 job-sheets (1setof type3 keyword |
+ name(MAX))</A></LI>
 <LI><A HREF="#5_2_11">5.2.11 job-originating-host-name (name(MAX))</A></LI>
 <LI><A HREF="#5_2_12">5.2.12 lpi (type2 enum)</A></LI>
-<LI><A HREF="#5_2_13">5.2.13 page-bottom (integer(0:MAX))</A></LI>
-<LI><A HREF="#5_2_14">5.2.14 page-label (text(MAX))</A></LI>
-<LI><A HREF="#5_2_15">5.2.15 page-left (integer(0:MAX))</A></LI>
-<LI><A HREF="#5_2_16">5.2.16 page-right (integer(0:MAX))</A></LI>
-<LI><A HREF="#5_2_17">5.2.17 page-set (type2 keyword)</A></LI>
-<LI><A HREF="#5_2_18">5.2.18 page-top (integer(0:MAX))</A></LI>
-<LI><A HREF="#5_2_19">5.2.19 penwidth (integer(0:MAX))</A></LI>
-<LI><A HREF="#5_2_20">5.2.20 position (type2 keyword)</A></LI>
-<LI><A HREF="#5_2_21">5.2.21 ppi (integer(1:MAX))</A></LI>
-<LI><A HREF="#5_2_22">5.2.22 prettyprint (boolean)</A></LI>
-<LI><A HREF="#5_2_23">5.2.23 saturation (integer(0:200))</A></LI>
-<LI><A HREF="#5_2_24">5.2.24 scaling (integer(1:1000))</A></LI>
-<LI><A HREF="#5_2_25">5.2.25 wrap (boolean)</A></LI>
+<LI><A HREF="#5_2_13">5.2.13 natural-scaling (integer(1:1000))</A></LI>
+<LI><A HREF="#5_2_14">5.2.14 page-bottom (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_15">5.2.15 page-label (text(MAX))</A></LI>
+<LI><A HREF="#5_2_16">5.2.16 page-left (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_17">5.2.17 page-right (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_18">5.2.18 page-set (type2 keyword)</A></LI>
+<LI><A HREF="#5_2_19">5.2.19 page-top (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_20">5.2.20 penwidth (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_21">5.2.21 position (type2 keyword)</A></LI>
+<LI><A HREF="#5_2_22">5.2.22 ppi (integer(1:MAX))</A></LI>
+<LI><A HREF="#5_2_23">5.2.23 prettyprint (boolean)</A></LI>
+<LI><A HREF="#5_2_24">5.2.24 saturation (integer(0:200))</A></LI>
+<LI><A HREF="#5_2_25">5.2.25 scaling (integer(1:1000))</A></LI>
+<LI><A HREF="#5_2_26">5.2.26 wrap (boolean)</A></LI>
 </UL>
 <LI><A HREF="#5_3">5.3 PPD Attributes</A></LI>
 <UL>
@@ -178,14 +179,14 @@ name(MAX))</A></LI>
 <LI><A HREF="#5_4_1">5.4.1 job-k-limit (integer)</A></LI>
 <LI><A HREF="#5_4_2">5.4.2 job-page-limit (integer)</A></LI>
 <LI><A HREF="#5_4_3">5.4.3 job-quota-period (integer)</A></LI>
-<LI><A HREF="#5_4_4">5.4.4 job-sheets-supported (1setof type3 keyword | 
-name(MAX))</A></LI>
+<LI><A HREF="#5_4_4">5.4.4 job-sheets-supported (1setof type3 keyword |
+ name(MAX))</A></LI>
 <LI><A HREF="#5_4_5">5.4.5 printer-type (type2 enum)</A></LI>
 <LI><A HREF="#5_4_6">5.4.6 printer-type-mask (type2 enum)</A></LI>
-<LI><A HREF="#5_4_7">5.4.7 requesting-user-name-allowed (1setof 
-name(127))</A></LI>
-<LI><A HREF="#5_4_8">5.4.8 requesting-user-name-denied (1setof 
-name(127))</A></LI>
+<LI><A HREF="#5_4_7">5.4.7 requesting-user-name-allowed (1setof
+ name(127))</A></LI>
+<LI><A HREF="#5_4_8">5.4.8 requesting-user-name-denied (1setof
+ name(127))</A></LI>
 </UL>
 <LI><A HREF="#5_5">5.5 Printer Class Attributes</A></LI>
 <UL>
@@ -201,27 +202,27 @@ name(127))</A></LI>
 <HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
-<P>This document provides an overview of the Internet Printing Protocol 
-(&quot;IPP&quot;) version 1.1 as implemented in the Common UNIX Printing System 
-(&quot;CUPS&quot;) version 1.1. </P>
+<P>This document provides an overview of the Internet Printing Protocol
+ (&quot;IPP&quot;) version 1.1 as implemented in the Common UNIX Printing System
+ (&quot;CUPS&quot;) version 1.1.</P>
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
-<P>This document is organized into the following sections: </P>
+<P>This document is organized into the following sections:</P>
 <UL>
 <LI><A HREF="#1">1 - Scope</A></LI>
 <LI><A HREF="#2">2 - References</A></LI>
@@ -232,76 +233,76 @@ EPSON printers are included that use these filters. </P>
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
-<UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 Overview</A></H1>
-<P>CUPS 1.1 implements IPP/1.1 and the operations and attributes 
-defined in the &quot;IPP: Job and Printer Set Operations&quot;, &quot;IPP/1.1: 
-Output-bin Attribute Extension&quot;, and &quot;IPP/1.1: finishings 'fold',' 
-trim', and 'bale' attribute values extension&quot; specifications. </P>
-<P>CUPS also provides 13 new operations and many new attributes to 
-support multiple IPP printers and printer classes on a single host. </P>
+<P>CUPS 1.1 implements IPP/1.1 and the operations and attributes defined
+ in the &quot;IPP: Job and Printer Set Operations&quot;, &quot;IPP/1.1: Output-bin
+ Attribute Extension&quot;, and &quot;IPP/1.1: finishings 'fold',' trim', and
+ 'bale' attribute values extension&quot; specifications.</P>
+<P>CUPS also provides 13 new operations and many new attributes to
+ support multiple IPP printers and printer classes on a single host.</P>
 <H2><A NAME="3_1">3.1 IPP URIs</A></H2>
-<P>CUPS supports both the &quot;http&quot; and &quot;ipp&quot; methods. The following 
-resource names are used: </P>
+<P>CUPS supports both the &quot;http&quot; and &quot;ipp&quot; methods. The following
+ resource names are used:</P>
 <DL>
-<DT>method://hostname:port/ </DT>
-<DD>Can be used for all &quot;get&quot; operations. </DD>
-<DT>method://hostname:port/admin </DT>
-<DD>Used for all administrative operations. </DD>
-<DT>method://hostname:port/classes/name </DT>
-<DD>Specifies a printer class. </DD>
-<DT>method://hostname:port/jobs/id </DT>
-<DD>Specifies a job. </DD>
-<DT>method://hostname:port/printers/name </DT>
-<DD>Specifies a printer. </DD>
+<DT>method://hostname:port/</DT>
+<DD>Can be used for all &quot;get&quot; operations.</DD>
+<DT>method://hostname:port/admin</DT>
+<DD>Used for all administrative operations.</DD>
+<DT>method://hostname:port/classes/name</DT>
+<DD>Specifies a printer class.</DD>
+<DT>method://hostname:port/jobs/id</DT>
+<DD>Specifies a job.</DD>
+<DT>method://hostname:port/printers/name</DT>
+<DD>Specifies a printer.</DD>
 </DL>
-<P>So a typical printer URI would be 
-&quot;ipp://foo.bar.com/printers/LaserJet&quot;. </P>
-<P>In addition, the CUPS server also supports normal browser access to 
-&quot;method://hostname:port/admin/&quot;, &quot;method://hostname:port/classes/&quot;, 
-&quot;method://hostname:port/jobs/&quot;, and &quot;method://hostname:port/printers/&quot; 
-to view and manage resources on the server dynamically. </P>
+<P>So a typical printer URI would be
+ &quot;ipp://foo.bar.com/printers/LaserJet&quot;.</P>
+<P>In addition, the CUPS server also supports normal browser access to
+ &quot;method://hostname:port/admin/&quot;, &quot;method://hostname:port/classes/&quot;,
+ &quot;method://hostname:port/jobs/&quot;, and &quot;method://hostname:port/printers/&quot;
+ to view and manage resources on the server dynamically.</P>
 <H2><A NAME="3_2">3.2 CUPS IPP Operations</A></H2>
-<P>CUPS provides 13 extension operations in addition to most of the 
-standard IPP and registered extension operations: 
+<P>CUPS provides 13 extension operations in addition to most of the
+ standard IPP and registered extension operations:
 <CENTER>
 <TABLE BORDER WIDTH="80%">
 <TR><TH VALIGN="TOP">Operation Name</TH><TH VALIGN="TOP">CUPS</TH><TH VALIGN="TOP">
@@ -368,971 +369,978 @@ VALIGN="TOP">0x4004</TD><TD VALIGN="TOP">Delete a printer.</TD></TR>
 </CENTER>
 </P>
 <H1><A NAME="4">4 Operations</A></H1>
-<P>The following sections describe the operations supported by CUPS. In 
-the interest of brevity, operations which use only the standard IPP 
-attributes are not described. </P>
+<P>The following sections describe the operations supported by CUPS. In
+ the interest of brevity, operations which use only the standard IPP
+ attributes are not described.</P>
 <H2><A NAME="4_1">4.1 Print-Job Operation</A></H2>
-<P>The Print-Job operation (0x0002) prints a file. </P>
+<P>The Print-Job operation (0x0002) prints a file.</P>
 <H3><A NAME="4_1_1">4.1.1 Print-Job Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-Print-Job request: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are supplied as part of the
+ Print-Job request:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer. </P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
 </UL>
-<P>Group 2: Job Template Attributes </P>
+<P>Group 2: Job Template Attributes</P>
 <UL>
-<P>&quot;job-billing&quot; (text(MAX)): </P>
+<P>&quot;job-billing&quot; (text(MAX)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a billing string that is logged  with 
-the page accounting information. </P>
-<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)): </P>
+<P>The client OPTIONALLY supplies a billing string that is logged with
+ the page accounting information.</P>
+<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies one or two banner pages that  are 
-printed before and after any files in the print job. The  name of 
-&quot;none&quot; is reserved to indicate that no banner page  should be printed. 
-If the client does not specify this  attribute then the value of the 
-&quot;job-sheets-default&quot; printer  object attribute is used. </P>
-<P><B>Note:</B> Standard IPP only allows specification of a single 
- job-sheets attribute value. </P>
-<P>&quot;media&quot; (1setof type3 keyword | name(MAX)): </P>
-<P>The client OPTIONALLY supplies one or more media attributes 
- specifying the size, type, source, and color of the output  media. If 
-the client does not specify this attribute then the  value of the 
-&quot;media-default&quot; printer object attribute is used. </P>
-<P><B>Note:</B> Standard IPP only allows specification of a single 
media attribute value. </P>
-<P>Other Job Template Attributes </P>
-</UL>
-<P>The Print-Job request is followed by a file to be printed. </P>
+<P>The client OPTIONALLY supplies one or two banner pages that are
+ printed before and after any files in the print job. The name of &quot;none&quot;
+ is reserved to indicate that no banner page should be printed. If the
+ client does not specify this attribute then the value of the
+ &quot;job-sheets-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.</P>
+<P>&quot;media&quot; (1setof type3 keyword | name(MAX)):</P>
+<P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output media. If
+ the client does not specify this attribute then the value of the
+ &quot;media-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single media
attribute value.</P>
+<P>Other Job Template Attributes</P>
+</UL>
+<P>The Print-Job request is followed by a file to be printed.</P>
 <H3><A NAME="4_1_2">4.1.2 Print-Job Response</A></H3>
-<P>The following groups of attributes are send as part of the Print-Job 
-Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the Print-Job
+ Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
-<P>Group 2: Job Attributes </P>
+<P>Group 2: Job Attributes</P>
 <UL>
-<P>Standard Job Attributes </P>
+<P>Standard Job Attributes</P>
 </UL>
 <H2><A NAME="4_2">4.2 Create-Job Operation</A></H2>
-<P>The Create-Job operation (0x0005) creates a new, empty print job. </P>
+<P>The Create-Job operation (0x0005) creates a new, empty print job.</P>
 <H3><A NAME="4_2_1">4.2.1 Create-Job Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-Create-Job request: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are supplied as part of the
+ Create-Job request:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer. </P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
 </UL>
-<P>Group 2: Job Template Attributes </P>
+<P>Group 2: Job Template Attributes</P>
 <UL>
-<P>&quot;job-billing&quot; (text(MAX)): </P>
+<P>&quot;job-billing&quot; (text(MAX)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a billing string that is logged  with 
-the page accounting information. </P>
-<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)): </P>
+<P>The client OPTIONALLY supplies a billing string that is logged with
+ the page accounting information.</P>
+<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies one or two banner pages that  are 
-printed before and after any files in the print job. The  name of 
-&quot;none&quot; is reserved to indicate that no banner page  should be printed. 
-If the client does not specify this  attribute then the value of the 
-&quot;job-sheets-default&quot; printer  object attribute is used. </P>
-<P><B>Note:</B> Standard IPP only allows specification of a single 
- job-sheets attribute value. </P>
-<P>&quot;media&quot; (1setof type3 keyword | name(MAX)): </P>
-<P>The client OPTIONALLY supplies one or more media attributes 
- specifying the size, type, source, and color of the output  media. If 
-the client does not specify this attribute then the  value of the 
-&quot;media-default&quot; printer object attribute is used. </P>
-<P><B>Note:</B> Standard IPP only allows specification of a single 
media attribute value. </P>
-<P>Standard Job Template Attributes </P>
+<P>The client OPTIONALLY supplies one or two banner pages that are
+ printed before and after any files in the print job. The name of &quot;none&quot;
+ is reserved to indicate that no banner page should be printed. If the
+ client does not specify this attribute then the value of the
+ &quot;job-sheets-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.</P>
+<P>&quot;media&quot; (1setof type3 keyword | name(MAX)):</P>
+<P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output media. If
+ the client does not specify this attribute then the value of the
+ &quot;media-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single media
attribute value.</P>
+<P>Standard Job Template Attributes</P>
 </UL>
 <H3><A NAME="4_2_2">4.2.2 Create-Job Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-Create-Job Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the Create-Job
+ Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
-<P>Group 2: Job Attributes </P>
+<P>Group 2: Job Attributes</P>
 <UL>
-<P>Standard Job Attributes </P>
+<P>Standard Job Attributes</P>
 </UL>
 <H2><A NAME="4_3">4.3 Set-Job-Attributes Operation</A></H2>
-<P>The Set-Job-Attributes operation (0x0014) changes the attributes of 
-an active (not completed) job. </P>
+<P>The Set-Job-Attributes operation (0x0014) changes the attributes of
+ an active (not completed) job.</P>
 <H3><A NAME="4_3_1">4.3.1 Set-Job-Attributes Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-Set-Job-Attributes request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri) and &quot;job-id&quot; (integer) </P>
+<P>The following groups of attributes are supplied as part of the
+ Set-Job-Attributes request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri) and &quot;job-id&quot; (integer)</P>
 <P><I>OR</I></P>
-<P>&quot;job-uri&quot;: </P>
-<P>The client MUST supply a URI for the specified printer and  a job ID 
-number, or the job URI. </P>
+<P>&quot;job-uri&quot;:</P>
+<P>The client MUST supply a URI for the specified printer and a job ID
+ number, or the job URI.</P>
 </UL>
-<P>Group 2: Job Template Attributes </P>
+<P>Group 2: Job Template Attributes</P>
 <UL>
-<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)): </P>
+<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies one or two banner pages that  are 
-printed before and after any files in the print job. The  name of 
-&quot;none&quot; is reserved to indicate that no banner page  should be printed. 
-If the client does not specify this  attribute then the value of the 
-&quot;job-sheets-default&quot; printer  object attribute is used. </P>
-<P><B>Note:</B> Standard IPP only allows specification of a single 
- job-sheets attribute value. </P>
-<P>&quot;media&quot; (1setof type3 keyword | name(MAX)): </P>
-<P>The client OPTIONALLY supplies one or more media attributes 
- specifying the size, type, source, and color of the output  media. If 
-the client does not specify this attribute then the  value of the 
-&quot;media-default&quot; printer object attribute is used. </P>
-<P><B>Note:</B> Standard IPP only allows specification of a single 
media attribute value. </P>
-<P>Other Job Template Attributes </P>
+<P>The client OPTIONALLY supplies one or two banner pages that are
+ printed before and after any files in the print job. The name of &quot;none&quot;
+ is reserved to indicate that no banner page should be printed. If the
+ client does not specify this attribute then the value of the
+ &quot;job-sheets-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.</P>
+<P>&quot;media&quot; (1setof type3 keyword | name(MAX)):</P>
+<P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output media. If
+ the client does not specify this attribute then the value of the
+ &quot;media-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single media
attribute value.</P>
+<P>Other Job Template Attributes</P>
 </UL>
 <H3><A NAME="4_3_2">4.3.2 Set-Job-Attributes Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-Set-Job-Attributes Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ Set-Job-Attributes Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_4">4.4 CUPS-Get-Default Operation</A></H2>
-<P>The CUPS-Get-Default operation (0x4001) returns the default printer 
-URI and attributes. </P>
+<P>The CUPS-Get-Default operation (0x4001) returns the default printer
+ URI and attributes.</P>
 <H3><A NAME="4_4_1">4.4.1 CUPS-Get-Default Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Get-Default request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;requested-attributes&quot; (1setOf keyword) : </P>
-<P>The client OPTIONALLY supplies a set of attribute names  and/or 
-attribute group names in whose values the requester is  interested. If 
-the client omits this attribute, the server  responds as if this 
-attribute had been supplied with a value of  'all'. </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Default request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
 </UL>
 <H3><A NAME="4_4_2">4.4.2 CUPS-Get-Default Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Get-Default Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Default Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
-<P>Group 2: Printer Object Attributes </P>
+<P>Group 2: Printer Object Attributes</P>
 <UL>
-<P>The set of requested attributes and their current values. </P>
+<P>The set of requested attributes and their current values.</P>
 </UL>
 <H2><A NAME="4_5">4.5 CUPS-Get-Printers Operation</A></H2>
-<P>The CUPS-Get-Printers operation (0x4002) returns the printer 
-attributes for every printer known to the system. This may include 
-printers that are not served directly by the server. </P>
+<P>The CUPS-Get-Printers operation (0x4002) returns the printer
+ attributes for every printer known to the system. This may include
+ printers that are not served directly by the server.</P>
 <H3><A NAME="4_5_1">4.5.1 CUPS-Get-Printers Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Get-Printers request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;limit&quot; (integer (1:MAX)): </P>
-<P>The client OPTIONALLY supplies this attribute limiting the  number 
-of printers that are returned. </P>
-<P>&quot;printer-info&quot; (text(127)): </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Printers request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ printers that are returned.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies this attribute to  select which 
-printers are returned. </P>
-<P>&quot;printer-location&quot; (text(127)): </P>
+<P>The client OPTIONALLY supplies this attribute to select which
+ printers are returned.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies this attribute to  select which 
-printers are returned. </P>
-<P>&quot;printer-type&quot; (type2 enum): </P>
+<P>The client OPTIONALLY supplies this attribute to select which
+ printers are returned.</P>
+<P>&quot;printer-type&quot; (type2 enum):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a printer type enumeration to  select 
-which printers are returned. </P>
-<P>&quot;printer-type-mask&quot; (type2 enum): </P>
+<P>The client OPTIONALLY supplies a printer type enumeration to select
+ which printers are returned.</P>
+<P>&quot;printer-type-mask&quot; (type2 enum):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a printer type mask  enumeration to 
-select which bits are used in the &quot;printer-type&quot;  attribute. </P>
-<P>&quot;requested-attributes&quot; (1setOf keyword) : </P>
-<P>The client OPTIONALLY supplies a set of attribute names  and/or 
-attribute group names in whose values the requester is  interested. If 
-the client omits this attribute, the server  responds as if this 
-attribute had been supplied with a value of  'all'. </P>
+<P>The client OPTIONALLY supplies a printer type mask enumeration to
+ select which bits are used in the &quot;printer-type&quot; attribute.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
 </UL>
 <H3><A NAME="4_5_2">4.5.2 CUPS-Get-Printers Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Get-Printers Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Printers Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
-<P>Group 2: Printer Object Attributes </P>
+<P>Group 2: Printer Object Attributes</P>
 <UL>
-<P>The set of requested attributes and their current values for  each 
-printer. </P>
+<P>The set of requested attributes and their current values for each
+ printer.</P>
 </UL>
 <H2><A NAME="4_6">4.6 CUPS-Add-Printer Operation</A></H2>
-<P>The CUPS-Add-Printer operation (0x4003) adds a new printer or 
-modifies an existing printer on the system. </P>
+<P>The CUPS-Add-Printer operation (0x4003) adds a new printer or
+ modifies an existing printer on the system.</P>
 <H3><A NAME="4_6_1">4.6.1 CUPS-Add-Printer Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Add-Printer request: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Add-Printer request:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer. </P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
 </UL>
-<P>Group 2: Printer Object Attributes </P>
+<P>Group 2: Printer Object Attributes</P>
 <UL>
-<P>&quot;banner-end-default&quot; (name(127)): </P>
+<P>&quot;banner-end-default&quot; (name(127)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a banner page name that is  printed 
-after files in a job. The reserved name &quot;none&quot; is used to  specify that 
-no banner page should be printed. </P>
-<P>&quot;banner-start-default&quot; (name(127)): </P>
+<P>The client OPTIONALLY supplies a banner page name that is printed
+ after files in a job. The reserved name &quot;none&quot; is used to specify that
+ no banner page should be printed.</P>
+<P>&quot;banner-start-default&quot; (name(127)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a banner page name that is  printed 
-before files in a job. The reserved name &quot;none&quot; is used to  specify 
-that no banner page should be printed. </P>
-<P>&quot;device-uri&quot; (uri): </P>
-<P>The client OPTIONALLY supplies a device URI for the  specified 
-printer. </P>
-<P>&quot;ppd-name&quot; (name(127)): </P>
-<P>The client OPTIONALLY supplies a PPD name for the specified 
- printer. </P>
-<P>&quot;printer-is-accepting-jobs&quot; (boolean): </P>
-<P>The client OPTIONALLY supplies this boolean attribute  indicating 
-whether or not the printer object should accept new jobs. </P>
-<P>&quot;printer-info&quot; (text(127)): </P>
-<P>The client OPTIONALLY supplies this attribute indicating the 
- printer information string. </P>
-<P>&quot;printer-location&quot; (text(127)): </P>
-<P>The client OPTIONALLY supplies this attribute indicating a  textual 
-location of the printer. </P>
-<P>&quot;printer-more-info&quot; (uri): </P>
-<P>The client OPTIONALLY supplies this attribute indicating a  URI for 
-additional printer information. </P>
-<P>&quot;printer-state&quot; (type2 enum): </P>
-<P>The client OPTIONALLY supplies this attribute indicating the 
- initial/current state of the printer. Only the &quot;idle&quot; and &quot;stopped&quot; 
- enumerations are recognized. </P>
-<P>&quot;printer-state-message&quot; (text(MAX)): </P>
-<P>The client OPTIONALLY supplies this attribute indicating a  textual 
-reason for the current printer state. </P>
-<P>&quot;requesting-user-name-allowed&quot; (1setof name(127) | delete) </P>
+<P>The client OPTIONALLY supplies a banner page name that is printed
+ before files in a job. The reserved name &quot;none&quot; is used to specify that
+ no banner page should be printed.</P>
+<P>&quot;device-uri&quot; (uri):</P>
+<P>The client OPTIONALLY supplies a device URI for the specified
+ printer.</P>
+<P>&quot;ppd-name&quot; (name(127)):</P>
+<P>The client OPTIONALLY supplies a PPD name for the specified printer.</P>
+<P>&quot;printer-is-accepting-jobs&quot; (boolean):</P>
+<P>The client OPTIONALLY supplies this boolean attribute indicating
+ whether or not the printer object should accept new jobs.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the printer
+ information string.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ location of the printer.</P>
+<P>&quot;printer-more-info&quot; (uri):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a URI for
+ additional printer information.</P>
+<P>&quot;printer-state&quot; (type2 enum):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the
+ initial/current state of the printer. Only the &quot;idle&quot; and &quot;stopped&quot;
+ enumerations are recognized.</P>
+<P>&quot;printer-state-message&quot; (text(MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ reason for the current printer state.</P>
+<P>&quot;requesting-user-name-allowed&quot; (1setof name(127) | delete)</P>
 <P><I>OR</I></P>
-<P>&quot;requesting-user-name-denied&quot; (1setof name(127) | delete): </P>
-<P>The client OPTIONALLY supplies one of these attributes to  specify 
-an access control list for incoming print jobs. To allow  all users 
-access to a printer, use the delete tag for the  attribute value. </P>
-</UL>
-<P>The CUPS-Add-Printer request can optionally be followed by a PPD 
-file or System V interface script to be used for the printer. The 
-&quot;ppd-name&quot; attribute overrides any file that is attached to the end of 
-the request with a local CUPS PPD file. </P>
+<P>&quot;requesting-user-name-denied&quot; (1setof name(127) | delete):</P>
+<P>The client OPTIONALLY supplies one of these attributes to specify an
+ access control list for incoming print jobs. To allow all users access
+ to a printer, use the delete tag for the attribute value.</P>
+</UL>
+<P>The CUPS-Add-Printer request can optionally be followed by a PPD file
+ or System V interface script to be used for the printer. The &quot;ppd-name&quot;
+ attribute overrides any file that is attached to the end of the request
+ with a local CUPS PPD file.</P>
 <H3><A NAME="4_6_2">4.6.2 CUPS-Add-Printer Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Add-Printer Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Add-Printer Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_7">4.7 CUPS-Delete-Printer Operation</A></H2>
-<P>The CUPS-Delete-Printer operation (0x4004) removes an existing 
-printer from the system. </P>
+<P>The CUPS-Delete-Printer operation (0x4004) removes an existing
+ printer from the system.</P>
 <H3><A NAME="4_7_1">4.7.1 CUPS-Delete-Printer Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Delete-Printer request: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Delete-Printer request:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer. </P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
 </UL>
 <H3><A NAME="4_7_2">4.7.2 CUPS-Delete-Printer Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Delete-Printer Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Delete-Printer Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_8">4.8 CUPS-Get-Classes Operation</A></H2>
-<P>The CUPS-Get-Classes operation (0x4005) returns the printer 
-attributes for every printer class known to the system. This may 
-include printer classes that are not served directly by the server. </P>
+<P>The CUPS-Get-Classes operation (0x4005) returns the printer
+ attributes for every printer class known to the system. This may
+ include printer classes that are not served directly by the server.</P>
 <H3><A NAME="4_8_1">4.8.1 CUPS-Get-Classes Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Get-Classes request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;limit&quot; (integer (1:MAX)): </P>
-<P>The client OPTIONALLY supplies this attribute limiting the  number 
-of printer classes that are returned. </P>
-<P>&quot;printer-info&quot; (text(127)): </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Classes request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ printer classes that are returned.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies this attribute to  select which 
-printer classes are returned. </P>
-<P>&quot;printer-location&quot; (text(127)): </P>
+<P>The client OPTIONALLY supplies this attribute to select which printer
+ classes are returned.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies this attribute to  select which 
-printer classes are returned. </P>
-<P>&quot;printer-type&quot; (type2 enum): </P>
+<P>The client OPTIONALLY supplies this attribute to select which printer
+ classes are returned.</P>
+<P>&quot;printer-type&quot; (type2 enum):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a printer type enumeration to  select 
-which printer classes are returned. </P>
-<P>&quot;printer-type-mask&quot; (type2 enum): </P>
+<P>The client OPTIONALLY supplies a printer type enumeration to select
+ which printer classes are returned.</P>
+<P>&quot;printer-type-mask&quot; (type2 enum):</P>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The client OPTIONALLY supplies a printer type mask  enumeration to 
-select which bits are used in the &quot;printer-type&quot;  attribute. </P>
-<P>&quot;requested-attributes&quot; (1setOf keyword) : </P>
-<P>The client OPTIONALLY supplies a set of attribute names  and/or 
-attribute group names in whose values the requester is  interested. If 
-the client omits this attribute, the server responds as  if this 
-attribute had been supplied with a value of 'all'. </P>
+<P>The client OPTIONALLY supplies a printer type mask enumeration to
+ select which bits are used in the &quot;printer-type&quot; attribute.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
 </UL>
 <H3><A NAME="4_8_2">4.8.2 CUPS-Get-Classes Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Get-Classes Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Classes Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
-<P>Group 2: Printer Class Object Attributes </P>
+<P>Group 2: Printer Class Object Attributes</P>
 <UL>
-<P>The set of requested attributes and their current values for  each 
-printer class. </P>
+<P>The set of requested attributes and their current values for each
+ printer class.</P>
 </UL>
 <H2><A NAME="4_9">4.9 CUPS-Add-Class Operation</A></H2>
-<P>The CUPS-Add-Class operation (0x4006) adds a new printer class or 
-modifies and existing printer class on the system. </P>
+<P>The CUPS-Add-Class operation (0x4006) adds a new printer class or
+ modifies and existing printer class on the system.</P>
 <H3><A NAME="4_9_1">4.9.1 CUPS-Add-Class Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Add-Class request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer class. </P>
-</UL>
-<P>Group 2: Printer Object Attributes </P>
-<UL>
-<P>&quot;member-uris&quot; (1setof uri): </P>
-<P>The client OPTIONALLY supplies the &quot;member-uris&quot; set  specifying the 
-printers and printer classes that are part of the class. </P>
-<P>&quot;printer-is-accepting-jobs&quot; (boolean): </P>
-<P>The client OPTIONALLY supplies this boolean attribute  indicating 
-whether or not the class object should accept new jobs. </P>
-<P>&quot;printer-info&quot; (text(127)): </P>
-<P>The client OPTIONALLY supplies this attribute indicating the 
printer information string. </P>
-<P>&quot;printer-location&quot; (text(127)): </P>
-<P>The client OPTIONALLY supplies this attribute indicating a  textual 
-location of the class. </P>
-<P>&quot;printer-more-info&quot; (uri): </P>
-<P>The client OPTIONALLY supplies this attribute indicating a  URI for 
-additional class information. </P>
-<P>&quot;printer-state&quot; (type2 enum): </P>
-<P>The client OPTIONALLY supplies this attribute indicating the 
- initial/current state of the class. Only the &quot;idle&quot; and &quot;stopped&quot; 
- enumerations are recognized. </P>
-<P>&quot;printer-state-message&quot; (text(MAX)): </P>
-<P>The client OPTIONALLY supplies this attribute indicating a  textual 
-reason for the current class state. </P>
-<P>&quot;requesting-user-name-allowed&quot; (1setof name(127)) </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Add-Class request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer class.</P>
+</UL>
+<P>Group 2: Printer Object Attributes</P>
+<UL>
+<P>&quot;member-uris&quot; (1setof uri):</P>
+<P>The client OPTIONALLY supplies the &quot;member-uris&quot; set specifying the
+ printers and printer classes that are part of the class.</P>
+<P>&quot;printer-is-accepting-jobs&quot; (boolean):</P>
+<P>The client OPTIONALLY supplies this boolean attribute indicating
+ whether or not the class object should accept new jobs.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the printer
information string.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ location of the class.</P>
+<P>&quot;printer-more-info&quot; (uri):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a URI for
+ additional class information.</P>
+<P>&quot;printer-state&quot; (type2 enum):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the
+ initial/current state of the class. Only the &quot;idle&quot; and &quot;stopped&quot;
+ enumerations are recognized.</P>
+<P>&quot;printer-state-message&quot; (text(MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ reason for the current class state.</P>
+<P>&quot;requesting-user-name-allowed&quot; (1setof name(127))</P>
 <P><I>OR</I></P>
-<P>&quot;requesting-user-name-denied&quot; (1setof name(127)): </P>
-<P>The client OPTIONALLY supplies one of these attributes to  specify 
-an access control list for incoming print jobs. To allow  all users 
-access to a class, use the delete tag for the  attribute value. </P>
+<P>&quot;requesting-user-name-denied&quot; (1setof name(127)):</P>
+<P>The client OPTIONALLY supplies one of these attributes to specify an
+ access control list for incoming print jobs. To allow all users access
+ to a class, use the delete tag for the attribute value.</P>
 </UL>
 <H3><A NAME="4_9_2">4.9.2 CUPS-Add-Class Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Add-Class Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Add-Class Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_10">4.10 CUPS-Delete-Class Operation</A></H2>
-<P>The CUPS-Delete-Class operation (0x4007) removes an existing printer 
-class from the system. </P>
+<P>The CUPS-Delete-Class operation (0x4007) removes an existing printer
+ class from the system.</P>
 <H3><A NAME="4_10_1">4.10.1 CUPS-Delete-Class Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Delete-Class request: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Delete-Class request:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer class. </P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer class.</P>
 </UL>
 <H3><A NAME="4_10_2">4.10.2 CUPS-Delete-Class Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Delete-Class Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Delete-Class Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_11">4.11 CUPS-Accept-Jobs Operation</A></H2>
-<P>The CUPS-Accept-Jobs operation (0x4008) sets the 
-&quot;printer-is-accepting-jobs&quot; attribute to true for the specified printer 
-or printer class. </P>
+<P>The CUPS-Accept-Jobs operation (0x4008) sets the
+ &quot;printer-is-accepting-jobs&quot; attribute to true for the specified printer
+ or printer class.</P>
 <H3><A NAME="4_11_1">4.11.1 CUPS-Accept-Jobs Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Accept-Jobs request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer or printer 
-class. </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Accept-Jobs request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer or printer
+ class.</P>
 </UL>
 <H3><A NAME="4_11_2">4.11.2 CUPS-Accept-Jobs Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Accept-Jobs Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Accept-Jobs Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_12">4.12 CUPS-Reject-Jobs Operation</A></H2>
-<P>The CUPS-Reject-Jobs operation (0x4009) sets 
-the&quot;printer-is-accepting-jobs&quot; attribute to false for the specified 
-printer or printer class. </P>
+<P>The CUPS-Reject-Jobs operation (0x4009) sets
+ the&quot;printer-is-accepting-jobs&quot; attribute to false for the specified
+ printer or printer class.</P>
 <H3><A NAME="4_12_1">4.12.1 CUPS-Reject-Jobs Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Reject-Jobs request: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Reject-Jobs request:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer or printer 
-class. </P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer or printer
+ class.</P>
 </UL>
-<P>Group 2: Printer Object Attributes </P>
+<P>Group 2: Printer Object Attributes</P>
 <UL>
-<P>&quot;printer-state-message&quot; (text(MAX)): </P>
-<P>The client OPTIONALLY supplies this attribute indicating a  textual 
-reason for the current printer state. </P>
+<P>&quot;printer-state-message&quot; (text(MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ reason for the current printer state.</P>
 </UL>
 <H3><A NAME="4_12_2">4.12.2 CUPS-Reject-Jobs Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Reject-Jobs Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Reject-Jobs Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_13">4.13 CUPS-Set-Default Operation</A></H2>
-<P>The CUPS-Set-Default operation (0x400A) sets the default printer 
-destination for all clients when a resource name of &quot;/printers&quot; is 
-specified. </P>
+<P>The CUPS-Set-Default operation (0x400A) sets the default printer
+ destination for all clients when a resource name of &quot;/printers&quot; is
+ specified.</P>
 <H3><A NAME="4_13_1">4.13.1 CUPS-Set-Default Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Set-Default request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri): </P>
-<P>The client MUST supply a URI for the specified printer or  printer 
-class. </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Set-Default request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer or printer
+ class.</P>
 </UL>
 <H3><A NAME="4_13_2">4.13.2 CUPS-Set-Default Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Set-Default Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Set-Default Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H2><A NAME="4_14">4.14 CUPS-Get-Devices Operation</A></H2>
-<P>The CUPS-Get-Devices operation (0x400B) returns all of the supported 
-device-uri's for the server (CUPS 1.1 and higher). </P>
+<P>The CUPS-Get-Devices operation (0x400B) returns all of the supported
+ device-uri's for the server (CUPS 1.1 and higher).</P>
 <H3><A NAME="4_14_1">4.14.1 CUPS-Get-Devices Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Get-Devices request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;device-class&quot; (type1 keyword): </P>
-<P>The client OPTIONALLY supplies a device class keyword to select 
which devices are returned. </P>
-<P>&quot;limit&quot; (integer (1:MAX)): </P>
-<P>The client OPTIONALLY supplies this attribute limiting the number of 
- devices that are returned. </P>
-<P>&quot;requested-attributes&quot; (1setOf keyword) : </P>
-<P>The client OPTIONALLY supplies a set of attribute names and/or 
- attribute group names in whose values the requester is interested. If 
- the client omits this attribute, the server responds as if this 
- attribute had been supplied with a value of 'all'. </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Devices request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;device-class&quot; (type1 keyword):</P>
+<P>The client OPTIONALLY supplies a device class keyword to select which
devices are returned.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ devices that are returned.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
 </UL>
 <H3><A NAME="4_14_2">4.14.2 CUPS-Get-Devices Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Get-Devices Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Devices Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
-<P>Group 2: Device Object Attributes </P>
+<P>Group 2: Device Object Attributes</P>
 <UL>
-<P>The set of requested attributes and their current values for  each 
-device. </P>
+<P>The set of requested attributes and their current values for each
+ device.</P>
 </UL>
 <H2><A NAME="4_15">4.15 CUPS-Get-PPDs Operation</A></H2>
-<P>The CUPS-Get-PPDs operation (0x400C) returns all of the locally 
-available PPD files on the system (CUPS 1.1 and higher). </P>
+<P>The CUPS-Get-PPDs operation (0x400C) returns all of the locally
+ available PPD files on the system (CUPS 1.1 and higher).</P>
 <H3><A NAME="4_15_1">4.15.1 CUPS-Get-PPDs Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Get-PPDs request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;limit&quot; (integer (1:MAX)): </P>
-<P>The client OPTIONALLY supplies this attribute limiting the number of 
- PPDs that are returned. </P>
-<P>&quot;ppd-make&quot; (text(127)): </P>
-<P>The client OPTIONALLY supplies a printer manufacturer to select 
which PPDs are returned. </P>
-<P>&quot;requested-attributes&quot; (1setOf keyword) : </P>
-<P>The client OPTIONALLY supplies a set of attribute names and/or 
- attribute group names in whose values the requester is interested. If 
- the client omits this attribute, the server responds as if this 
- attribute had been supplied with a value of 'all'. </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-PPDs request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ PPDs that are returned.</P>
+<P>&quot;ppd-make&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies a printer manufacturer to select which
PPDs are returned.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
 </UL>
 <H3><A NAME="4_15_2">4.15.2 CUPS-Get-PPDs Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Get-PPDs Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-PPDs Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
-<P>Group 2: PPD Attributes </P>
+<P>Group 2: PPD Attributes</P>
 <UL>
-<P>The set of requested attributes and their current values for each 
PPD file. </P>
+<P>The set of requested attributes and their current values for each PPD
file.</P>
 </UL>
 <H2><A NAME="4_16">4.16 CUPS-Move-Job Operation</A></H2>
-<P>The CUPS-Move-Job operation (0x400D) moves an active print job to a 
-different printer (CUPS 1.1 and higher). </P>
+<P>The CUPS-Move-Job operation (0x400D) moves an active print job to a
+ different printer (CUPS 1.1 and higher).</P>
 <H3><A NAME="4_16_1">4.16.1 CUPS-Move-Job Request</A></H3>
-<P>The following groups of attributes are supplied as part of the 
-CUPS-Move-Job request: </P>
-<P>Group 1: Operation Attributes </P>
-<UL>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.1 of the IPP Model and 
Semantics document. </P>
-<P>&quot;printer-uri&quot; (uri) and &quot;job-id&quot; (integer) </P>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Move-Job request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
document.</P>
+<P>&quot;printer-uri&quot; (uri) and &quot;job-id&quot; (integer)</P>
 <P><I>OR</I></P>
-<P>&quot;job-uri&quot;: </P>
-<P>The client MUST supply a URI for the specified printer and  a job ID 
-number, or the job URI. </P>
+<P>&quot;job-uri&quot;:</P>
+<P>The client MUST supply a URI for the specified printer and a job ID
+ number, or the job URI.</P>
 </UL>
-<P>Group 2: Job Template Attributes </P>
+<P>Group 2: Job Template Attributes</P>
 <UL>
-<P>&quot;job-printer-uri&quot; (uri) </P>
-<P>The client MUST supply a URI for a printer on the same server. </P>
+<P>&quot;job-printer-uri&quot; (uri)</P>
+<P>The client MUST supply a URI for a printer on the same server.</P>
 </UL>
 <H3><A NAME="4_16_2">4.16.2 CUPS-Move-Job Response</A></H3>
-<P>The following groups of attributes are send as part of the 
-CUPS-Move-Job Response: </P>
-<P>Group 1: Operation Attributes </P>
+<P>The following groups of attributes are send as part of the
+ CUPS-Move-Job Response:</P>
+<P>Group 1: Operation Attributes</P>
 <UL>
-<P>Status Message: </P>
-<P>The standard response status message. </P>
-<P>Natural Language and Character Set: </P>
-<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; 
- attributes as described in section 3.1.4.2 of the IPP Model and 
Semantics document. </P>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
document.</P>
 </UL>
 <H1><A NAME="5">5 Attributes</A></H1>
-<P>CUPS provides many extension attributes to support multiple devices, 
-PPD files, standard job filters, printers, and printer classes. </P>
+<P>CUPS provides many extension attributes to support multiple devices,
+ PPD files, standard job filters, printers, and printer classes.</P>
 <H2><A NAME="5_1">5.1 Device Attributes</A></H2>
-<P>Device attributes are returned by the CUPS-Get-Devices operation and 
-enumerate all of the available hardware devices and network protocols 
-that are supported by the server. </P>
+<P>Device attributes are returned by the CUPS-Get-Devices operation and
+ enumerate all of the available hardware devices and network protocols
+ that are supported by the server.</P>
 <H3><A NAME="5_1_1">5.1.1 device-class (type2 keyword)</A></H3>
-<P>The device-class attribute specifies the class of device and can be 
-one of the following: </P>
+<P>The device-class attribute specifies the class of device and can be
+ one of the following:</P>
 <UL>
-<LI>&quot;file&quot; - a disk file. </LI>
-<LI>&quot;direct&quot; - a parallel or fixed-rate serial data port,  currently 
-used for Centronics, IEEE-1284, and USB printer  ports. </LI>
-<LI>&quot;serial&quot; - a variable-rate serial port. </LI>
-<LI>&quot;network&quot; - a network connection, typically via AppSocket,  HTTP, 
-IPP, LPD, or SMB/CIFS protocols. </LI>
+<LI>&quot;file&quot; - a disk file.</LI>
+<LI>&quot;direct&quot; - a parallel or fixed-rate serial data port, currently used
+ for Centronics, IEEE-1284, and USB printer ports.</LI>
+<LI>&quot;serial&quot; - a variable-rate serial port.</LI>
+<LI>&quot;network&quot; - a network connection, typically via AppSocket, HTTP,
+ IPP, LPD, or SMB/CIFS protocols.</LI>
 </UL>
 <H3><A NAME="5_1_2">5.1.2 device-info (text(127))</A></H3>
-<P>The device-info attribute specifies a human-readable string 
-describing the device, e.g. &quot;Parallel Port #1&quot;. </P>
+<P>The device-info attribute specifies a human-readable string
+ describing the device, e.g. &quot;Parallel Port #1&quot;.</P>
 <H3><A NAME="5_1_3">5.1.3 device-make-and-model (text(127))</A></H3>
-<P>The device-makr-and-model attribute specifies a device 
-identification string provided by the printer connected to the device. 
-If the device or printer does not support identification then this 
-attribute contains the string &quot;unknown&quot;. </P>
+<P>The device-makr-and-model attribute specifies a device identification
+ string provided by the printer connected to the device. If the device
+ or printer does not support identification then this attribute contains
+ the string &quot;unknown&quot;.</P>
 <H3><A NAME="5_1_4">5.1.4 device-uri (uri)</A></H3>
-<P>The device-uri attribute specifies a unique identifier for the 
-device. The actual format of the device-uri string depends on the value 
-of the device-class attribute: </P>
-<UL>
-<LI>&quot;file&quot; - The device-uri will be of the form 
- &quot;file:/path/to/filename&quot;. </LI>
-<LI>&quot;direct&quot; - The device-uri will be of the form 
- &quot;method:/dev/filename&quot;, where method may be &quot;parallel&quot; or &quot;usb&quot;  in 
-the current implementation. </LI>
-<LI>&quot;serial&quot; - The device-uri will be of the form 
- &quot;serial:/dev/filename?baud=value+parity=value+flow=value&quot;.  The baud 
-value is the data rate in bits per second; the  supported values depend 
-on the underlying hardware.  The parity value can be one of &quot;none&quot;, 
-&quot;even&quot;, or &quot;odd&quot;.  The flow value can be one of &quot;none&quot;, &quot;soft&quot; 
-(XON/XOFF  handshaking), &quot;hard&quot; or &quot;rts/cts&quot; (RTS/CTS handshaking),  or 
-&quot;dtrdsr&quot; (DTR/DSR handshaking). </LI>
-<P>The URI returned by CUPS-Get-Devices will contain the  maximum baud 
-rate supported by the device and the best  type of flow control 
-available (&quot;soft&quot; or &quot;hard&quot;). </P>
-<LI>&quot;network&quot; - The device-uri will be of the form 
- &quot;method://[username:password@]hostname[:port]/[resource]&quot;,  where 
-method may be &quot;http&quot;, &quot;ipp&quot;, &quot;lpd&quot;, &quot;smb&quot;, or  &quot;socket&quot; in the current 
-implementation. </LI>
-<P>The URI returned by CUPS-Get-Devices will only contain  the method 
-name followed by two slashes (&quot;method://&quot;).  It is up to the client 
-application to add the appropriate  host and other information when 
-adding a new printer. </P>
-<P>The URI returned by Get-Printer-Attributes and  CUPS-Get-Printers 
-has any username and password information  stripped; the information is 
-still stored and used by the  server internally to perform any needed 
-authentication. </P>
+<P>The device-uri attribute specifies a unique identifier for the
+ device. The actual format of the device-uri string depends on the value
+ of the device-class attribute:</P>
+<UL>
+<LI>&quot;file&quot; - The device-uri will be of the form
+ &quot;file:/path/to/filename&quot;.</LI>
+<LI>&quot;direct&quot; - The device-uri will be of the form
+ &quot;method:/dev/filename&quot;, where method may be &quot;parallel&quot; or &quot;usb&quot; in the
+ current implementation.</LI>
+<LI>&quot;serial&quot; - The device-uri will be of the form
+ &quot;serial:/dev/filename?baud=value+parity=value+flow=value&quot;. The baud
+ value is the data rate in bits per second; the supported values depend
+ on the underlying hardware. The parity value can be one of &quot;none&quot;,
+ &quot;even&quot;, or &quot;odd&quot;. The flow value can be one of &quot;none&quot;, &quot;soft&quot; (XON/XOFF
+ handshaking), &quot;hard&quot; or &quot;rts/cts&quot; (RTS/CTS handshaking), or &quot;dtrdsr&quot;
+ (DTR/DSR handshaking).</LI>
+<P>The URI returned by CUPS-Get-Devices will contain the maximum baud
+ rate supported by the device and the best type of flow control
+ available (&quot;soft&quot; or &quot;hard&quot;).</P>
+<LI>&quot;network&quot; - The device-uri will be of the form
+ &quot;method://[username:password@]hostname[:port]/[resource]&quot;, where method
+ may be &quot;http&quot;, &quot;ipp&quot;, &quot;lpd&quot;, &quot;smb&quot;, or &quot;socket&quot; in the current
+ implementation.</LI>
+<P>The URI returned by CUPS-Get-Devices will only contain the method
+ name followed by two slashes (&quot;method://&quot;). It is up to the client
+ application to add the appropriate host and other information when
+ adding a new printer.</P>
+<P>The URI returned by Get-Printer-Attributes and CUPS-Get-Printers has
+ any username and password information stripped; the information is
+ still stored and used by the server internally to perform any needed
+ authentication.</P>
 </UL>
 <H2><A NAME="5_2">5.2 Job Template Attributes</A></H2>
 <H3><A NAME="5_2_1">5.2.1 blackplot (boolean)</A></H3>
-<P>The blackplot attribute specifies whether HP-GL/2 plot files should 
-be rendered entirely in black ink (blackplot=true) or using the colors 
-and shades specified in the file (blackplot=false). The default value 
-is false. </P>
+<P>The blackplot attribute specifies whether HP-GL/2 plot files should
+ be rendered entirely in black ink (blackplot=true) or using the colors
+ and shades specified in the file (blackplot=false). The default value
+ is false.</P>
 <H3><A NAME="5_2_2">5.2.2 brightness (integer(0:200))</A></H3>
-<P>The brightness attribute specifies the overall brightness of the 
-printed output in percent. A brightness of 100 is normal, while 200 is 
-twice as bright and 50 is half as bright. The default value is 100. </P>
-<P>Brightness is applied to the Cyan, Magenta, Yellow, and Black values 
-using the function &quot;f(x) = brightness / 100 * x&quot;. </P>
+<P>The brightness attribute specifies the overall brightness of the
+ printed output in percent. A brightness of 100 is normal, while 200 is
+ twice as bright and 50 is half as bright. The default value is 100.</P>
+<P>Brightness is applied to the Cyan, Magenta, Yellow, and Black values
+ using the function &quot;f(x) = brightness / 100 * x&quot;.</P>
 <H3><A NAME="5_2_3">5.2.3 columns (integer(1:4))</A></H3>
-<P>The columns attribute specifies the number of columns to generate 
-when printing text files. The default value is 1. </P>
+<P>The columns attribute specifies the number of columns to generate
+ when printing text files. The default value is 1.</P>
 <H3><A NAME="5_2_4">5.2.4 cpi (type2 enum)</A></H3>
-<P>The cpi attribute specifies the number of characters per inch when 
-printing text files. Only the values 10, 12, and 17 are currently 
-supported. The default value is 10. </P>
+<P>The cpi attribute specifies the number of characters per inch when
+ printing text files. Only the values 10, 12, and 17 are currently
+ supported. The default value is 10.</P>
 <H3><A NAME="5_2_5">5.2.5 fitplot (boolean)</A></H3>
-<P>The fitplot attribute specifies whether to scale HP-GL/2 plot files 
-to fit on the selected media (fitplot=true) or use the physical scale 
-specified in the plot file (fitplot=false). The default value is false. </P>
+<P>The fitplot attribute specifies whether to scale HP-GL/2 plot files
+ to fit on the selected media (fitplot=true) or use the physical scale
+ specified in the plot file (fitplot=false). The default value is false.</P>
 <H3><A NAME="5_2_6">5.2.6 gamma (integer(1:10000))</A></H3>
-<P>The gamma attribute specifies the luminance correction for the 
-output. A value of 1000 specifies no correction, while values of 2000 
-and 500 will generate lighter and darker output, respectively. The 
-default value is 1000. </P>
-<P>Gamma is applied to the Red, Green, and Blue values (or luminance 
-for grayscale output) using the function &quot;f(x) = x<SUP>(1000/gamma)</SUP>
-&quot;. </P>
+<P>The gamma attribute specifies the luminance correction for the
+ output. A value of 1000 specifies no correction, while values of 2000
+ and 500 will generate lighter and darker output, respectively. The
+ default value is 1000.</P>
+<P>Gamma is applied to the Red, Green, and Blue values (or luminance for
+ grayscale output) using the function &quot;f(x) = x<SUP>(1000/gamma)</SUP>&quot;.</P>
 <H3><A NAME="5_2_7">5.2.7 hue (integer(-180:180))</A></H3>
-<P>The hue attribute specifies a color hue rotation when printing image 
-files. The default value is 0. </P>
+<P>The hue attribute specifies a color hue rotation when printing image
+ files. The default value is 0.</P>
 <H3><A NAME="5_2_8">5.2.8 job-billing (text(MAX))</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The job-billing attribute provides a text value to associate with a 
-job for billing purposes. </P>
+<P>The job-billing attribute provides a text value to associate with a
+ job for billing purposes.</P>
 <H3><A NAME="5_2_9">5.2.9 job-hold-until (keyword | name(MAX))</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The job-hold-until attribute specifies a hold time. In addition to 
-the standard IPP/1.1 keyword names, CUPS supports name values of the 
-form &quot;HH:MM&quot; and &quot;HH:MM:SS&quot; that specify a hold time. The hold time is 
-in Greenwich Mean Time (GMT) and <I>not</I> in the local time zone. If 
-the specified time is less than the current time, the job is held until 
-the next day. </P>
-<H3><A NAME="5_2_10">5.2.10 job-sheets (1setof type3 keyword | 
-name(MAX))</A></H3>
+<P>The job-hold-until attribute specifies a hold time. In addition to
+ the standard IPP/1.1 keyword names, CUPS supports name values of the
+ form &quot;HH:MM&quot; and &quot;HH:MM:SS&quot; that specify a hold time. The hold time is
+ in Greenwich Mean Time (GMT) and<I> not</I> in the local time zone. If
+ the specified time is less than the current time, the job is held until
+ the next day.</P>
+<H3><A NAME="5_2_10">5.2.10 job-sheets (1setof type3 keyword |
+ name(MAX))</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The job-sheets attribute specifies one or two banner files that are 
-printed before and after a job. The reserved value of &quot;none&quot; disables 
-banner printing. The default value is stored in the job-sheets-default 
-attribute. </P>
-<P>If only one value is supplied, the banner file is printed before the 
-job. If two values are supplied, the first value is used as the 
-starting banner file and the second as the ending banner file. </P>
+<P>The job-sheets attribute specifies one or two banner files that are
+ printed before and after a job. The reserved value of &quot;none&quot; disables
+ banner printing. The default value is stored in the job-sheets-default
+ attribute.</P>
+<P>If only one value is supplied, the banner file is printed before the
+ job. If two values are supplied, the first value is used as the
+ starting banner file and the second as the ending banner file.</P>
 <H3><A NAME="5_2_11">5.2.11 job-originating-host-name (name(MAX))</A></H3>
 <P><I>(CUPS 1.1.5 and higher)</I></P>
-<P>The job-originating-host-name attribute specifies the host from 
-which the job was queued. The value will be the hostname or IP address 
-of the client depending on whether hostname resolution is enabled.  The 
-localhost address (127.0.0.1) is <B>always</B> resolved to the name 
-&quot;localhost&quot;. </P>
-<P>This attribute is read-only. </P>
+<P>The job-originating-host-name attribute specifies the host from which
+ the job was queued. The value will be the hostname or IP address of the
+ client depending on whether hostname resolution is enabled. The
+ localhost address (127.0.0.1) is<B> always</B> resolved to the name
+ &quot;localhost&quot;.</P>
+<P>This attribute is read-only.</P>
 <H3><A NAME="5_2_12">5.2.12 lpi (type2 enum)</A></H3>
-<P>The lpi attribute specifies the number of lines per inch when 
-printing text files. Only the values 6 and 8 are currently supported. 
-The default value is 6. </P>
-<H3><A NAME="5_2_13">5.2.13 page-bottom (integer(0:MAX))</A></H3>
-<P>The page-bottom attribute specifies the bottom margin in points (72 
-points equals 1 inch). The default value is the device physical margin. </P>
-<H3><A NAME="5_2_14">5.2.14 page-label (text(MAX))</A></H3>
+<P>The lpi attribute specifies the number of lines per inch when
+ printing text files. Only the values 6 and 8 are currently supported.
+ The default value is 6.</P>
+<H3><A NAME="5_2_13">5.2.13 natural-scaling (integer(1:1000))</A></H3>
+<P><I>(CUPS 1.1.9 and higher)</I></P>
+<P>The natural-scaling attribute specifies the scaling of image files
+ with respect to the natural image size. A value of 100 specifies that
+ the image file should exactly the natural size, while 50 is half the
+ natural size and 200 is twice the natural size. The default value is
+ 100.</P>
+<P>The ppi option can be used to override the natural resolution of the
+ image, which controls the natural size.</P>
+<H3><A NAME="5_2_14">5.2.14 page-bottom (integer(0:MAX))</A></H3>
+<P>The page-bottom attribute specifies the bottom margin in points (72
+ points equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_15">5.2.15 page-label (text(MAX))</A></H3>
 <P><I>(CUPS 1.1.7 and higher)</I></P>
-<P>The page-label attribute provides a text value to place in the 
-header and footer on each page. If a classification level is set on the 
-server, then this classification is printed before the page label. </P>
-<H3><A NAME="5_2_15">5.2.15 page-left (integer(0:MAX))</A></H3>
-<P>The page-left attribute specifies the left margin in points (72 
-points equals 1 inch). The default value is the device physical margin. </P>
-<H3><A NAME="5_2_16">5.2.16 page-right (integer(0:MAX))</A></H3>
-<P>The page-right attribute specifies the right margin in points (72 
-points equals 1 inch). The default value is the device physical margin. </P>
-<H3><A NAME="5_2_17">5.2.17 page-set (type2 keyword)</A></H3>
-<P>The page-set attribute specifies which pages to print in a file. The 
-supported keywords are &quot;all&quot;, &quot;even&quot;, and &quot;odd&quot;. The default value is 
-&quot;all&quot;. </P>
-<H3><A NAME="5_2_18">5.2.18 page-top (integer(0:MAX))</A></H3>
-<P>The page-top attribute specifies the top margin in points (72 points 
-equals 1 inch). The default value is the device physical margin. </P>
-<H3><A NAME="5_2_19">5.2.19 penwidth (integer(0:MAX))</A></H3>
-<P>The penwidth attribute specifies the default pen width in 
-micrometers when printing HP-GL/2 plot files. The default value is 1000 
-(1 millimeter). </P>
-<H3><A NAME="5_2_20">5.2.20 position (type2 keyword)</A></H3>
-<P>The position attribute specifies the location of image files on the 
-media. The following keyword values are recognized: </P>
-<UL>
-<LI><CODE>center</CODE> - Center the image on the page (default) </LI>
-<LI><CODE>top</CODE> - Print the image centered at the top of the page </LI>
-<LI><CODE>left</CODE> - Print the image centered on the left of page </LI>
-<LI><CODE>right</CODE> - Print the image centered on the right of the 
-page </LI>
-<LI><CODE>top-left</CODE> - Print the image at the top left corner of 
- the page </LI>
-<LI><CODE>top-right</CODE> - Print the image at the top right corner of 
- the page </LI>
-<LI><CODE>bottom</CODE> - Print the image centered at the bottom of 
the page </LI>
-<LI><CODE>bottom-left</CODE> - Print the image at the bottom left 
corner of the page </LI>
-<LI><CODE>bottom-right</CODE> - Print the image at the bottom right 
- corner of the page </LI>
-</UL>
-<H3><A NAME="5_2_21">5.2.21 ppi (integer(1:MAX))</A></H3>
-<P>The ppi attribute specifies the resolution of an image file in 
-pixels per inch. The default value is the resolution included with the 
-file or 128 if no resolution information is available. </P>
-<H3><A NAME="5_2_22">5.2.22 prettyprint (boolean)</A></H3>
-<P>The prettyprint attribute specifies whether text files should be 
-printed with a shaded header and keyword highlighting 
-(prettyprint=true) or without additional formatting 
-(prettyprint=false). The default value is false. </P>
-<H3><A NAME="5_2_23">5.2.23 saturation (integer(0:200))</A></H3>
-<P>The saturation attribute specifies the color saturation when 
-printing image files. A saturation of 100 is normal, while values of 50 
-and 200 will be half and twice as colorful, respectively. The default 
-value is 100. </P>
-<H3><A NAME="5_2_24">5.2.24 scaling (integer(1:1000))</A></H3>
-<P>The scaling attribute specifies the scaling of image files with 
-respect to the selected media. A value of 100 specifies that the image 
-file should fit 100% of the page, or as much as possible given the 
-image dimensions. The default value is unspecified. </P>
-<P>The scaling attribute overrides the ppi attribute if specified. </P>
-<H3><A NAME="5_2_25">5.2.25 wrap (boolean)</A></H3>
-<P>The wrap attribute specifies whether long lines should be wrapped 
-(wrap=true) or not (wrap=false) when printing text files. The default 
-value is true. </P>
+<P>The page-label attribute provides a text value to place in the header
+ and footer on each page. If a classification level is set on the
+ server, then this classification is printed before the page label.</P>
+<H3><A NAME="5_2_16">5.2.16 page-left (integer(0:MAX))</A></H3>
+<P>The page-left attribute specifies the left margin in points (72
+ points equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_17">5.2.17 page-right (integer(0:MAX))</A></H3>
+<P>The page-right attribute specifies the right margin in points (72
+ points equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_18">5.2.18 page-set (type2 keyword)</A></H3>
+<P>The page-set attribute specifies which pages to print in a file. The
+ supported keywords are &quot;all&quot;, &quot;even&quot;, and &quot;odd&quot;. The default value is
+ &quot;all&quot;.</P>
+<H3><A NAME="5_2_19">5.2.19 page-top (integer(0:MAX))</A></H3>
+<P>The page-top attribute specifies the top margin in points (72 points
+ equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_20">5.2.20 penwidth (integer(0:MAX))</A></H3>
+<P>The penwidth attribute specifies the default pen width in micrometers
+ when printing HP-GL/2 plot files. The default value is 1000 (1
+ millimeter).</P>
+<H3><A NAME="5_2_21">5.2.21 position (type2 keyword)</A></H3>
+<P>The position attribute specifies the location of image files on the
+ media. The following keyword values are recognized:</P>
+<UL>
+<LI><CODE>center</CODE> - Center the image on the page (default)</LI>
+<LI><CODE>top</CODE> - Print the image centered at the top of the page</LI>
+<LI><CODE>left</CODE> - Print the image centered on the left of page</LI>
+<LI><CODE>right</CODE> - Print the image centered on the right of the
+ page</LI>
+<LI><CODE>top-left</CODE> - Print the image at the top left corner of
+ the page</LI>
+<LI><CODE>top-right</CODE> - Print the image at the top right corner of
+ the page</LI>
+<LI><CODE>bottom</CODE> - Print the image centered at the bottom of the
page</LI>
+<LI><CODE>bottom-left</CODE> - Print the image at the bottom left corner
of the page</LI>
+<LI><CODE>bottom-right</CODE> - Print the image at the bottom right
+ corner of the page</LI>
+</UL>
+<H3><A NAME="5_2_22">5.2.22 ppi (integer(1:MAX))</A></H3>
+<P>The ppi attribute specifies the resolution of an image file in pixels
+ per inch. The default value is the resolution included with the file or
+ 128 if no resolution information is available.</P>
+<H3><A NAME="5_2_23">5.2.23 prettyprint (boolean)</A></H3>
+<P>The prettyprint attribute specifies whether text files should be
+ printed with a shaded header and keyword highlighting
+ (prettyprint=true) or without additional formatting
+ (prettyprint=false). The default value is false.</P>
+<H3><A NAME="5_2_24">5.2.24 saturation (integer(0:200))</A></H3>
+<P>The saturation attribute specifies the color saturation when printing
+ image files. A saturation of 100 is normal, while values of 50 and 200
+ will be half and twice as colorful, respectively. The default value is
+ 100.</P>
+<H3><A NAME="5_2_25">5.2.25 scaling (integer(1:1000))</A></H3>
+<P>The scaling attribute specifies the scaling of image files with
+ respect to the selected media. A value of 100 specifies that the image
+ file should fit 100% of the page, or as much as possible given the
+ image dimensions. The default value is unspecified.</P>
+<P>The scaling attribute overrides the ppi attribute if specified.</P>
+<H3><A NAME="5_2_26">5.2.26 wrap (boolean)</A></H3>
+<P>The wrap attribute specifies whether long lines should be wrapped
+ (wrap=true) or not (wrap=false) when printing text files. The default
+ value is true.</P>
 <H2><A NAME="5_3">5.3 PPD Attributes</A></H2>
 <H3><A NAME="5_3_1">5.3.1 ppd-natural-language (naturalLanguage)</A></H3>
-<P>The ppd-natural-language attribute specifies the language encoding 
-of the PPD file (the LanguageVersion attribute in the PPD file). If the 
-language is unknown or undefined then &quot;en&quot; (English) is assumed. </P>
+<P>The ppd-natural-language attribute specifies the language encoding of
+ the PPD file (the LanguageVersion attribute in the PPD file). If the
+ language is unknown or undefined then &quot;en&quot; (English) is assumed.</P>
 <H3><A NAME="5_3_2">5.3.2 ppd-make (text(127))</A></H3>
-<P>The ppd-make attribute specifies the manufacturer of the printer 
-(the Manufacturer attribute in the PPD file). If the manufacturer is 
-not specified in the PPD file then an educated guess is made using the 
-NickName attribute in the PPD file. </P>
+<P>The ppd-make attribute specifies the manufacturer of the printer (the
+ Manufacturer attribute in the PPD file). If the manufacturer is not
+ specified in the PPD file then an educated guess is made using the
+ NickName attribute in the PPD file.</P>
 <H3><A NAME="5_3_3">5.3.3 ppd-make-and-model (text(127))</A></H3>
-<P>The ppd-make-and-model attribute specifies the manufacturer and 
-model name of the PPD file (the NickName attribute in the PPD file). If 
-the make and model is not specified in the PPD file then the ModelName 
-or ShortNickName attributes are used instead. </P>
+<P>The ppd-make-and-model attribute specifies the manufacturer and model
+ name of the PPD file (the NickName attribute in the PPD file). If the
+ make and model is not specified in the PPD file then the ModelName or
+ ShortNickName attributes are used instead.</P>
 <H3><A NAME="5_3_4">5.3.4 ppd-name (name(255))</A></H3>
-<P>The ppd-name attribute specifies the PPD filename on the server 
-relative to the model directory. The forward slash (/) is used to 
-delineate directories. </P>
+<P>The ppd-name attribute specifies the PPD filename on the server
+ relative to the model directory. The forward slash (/) is used to
+ delineate directories.</P>
 <H2><A NAME="5_4">5.4 Printer Attributes</A></H2>
 <H3><A NAME="5_4_1">5.4.1 job-k-limit (integer)</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The job-k-limit attribute specifies the maximum number of kilobytes 
-that may be printed by a user, including banner files. The default 
-value of 0 specifies that there is no limit. </P>
+<P>The job-k-limit attribute specifies the maximum number of kilobytes
+ that may be printed by a user, including banner files. The default
+ value of 0 specifies that there is no limit.</P>
 <H3><A NAME="5_4_2">5.4.2 job-page-limit (integer)</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The job-page-limit attribute specifies the maximum number of pages 
-that may be printed by a user, including banner files. The default 
-value of 0 specifies that there is no limit. </P>
+<P>The job-page-limit attribute specifies the maximum number of pages
+ that may be printed by a user, including banner files. The default
+ value of 0 specifies that there is no limit.</P>
 <H3><A NAME="5_4_3">5.4.3 job-quota-period (integer)</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The job-quota-period attribute specifies the time period used for 
-quota calculations, in seconds. The default value of 0 specifies that 
-the limits apply to all jobs that have been printed by a user that are 
-still known to the system. </P>
-<H3><A NAME="5_4_4">5.4.4 job-sheets-supported (1setof type3 keyword | 
-name(MAX))</A></H3>
+<P>The job-quota-period attribute specifies the time period used for
+ quota calculations, in seconds. The default value of 0 specifies that
+ the limits apply to all jobs that have been printed by a user that are
+ still known to the system.</P>
+<H3><A NAME="5_4_4">5.4.4 job-sheets-supported (1setof type3 keyword |
+ name(MAX))</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The job-sheets-supported attribute specifies the available banner 
-files. There will always be at least one banner file available called 
-&quot;none&quot;. </P>
+<P>The job-sheets-supported attribute specifies the available banner
+ files. There will always be at least one banner file available called
+ &quot;none&quot;.</P>
 <H3><A NAME="5_4_5">5.4.5 printer-type (type2 enum)</A></H3>
-<P>The printer-type attribute specifies printer type and capability 
-bits for the printer or class. The default value is computed from 
-internal state information and the PPD file for the printer. The 
-following bits are defined: 
+<P>The printer-type attribute specifies printer type and capability bits
+ for the printer or class. The default value is computed from internal
+ state information and the PPD file for the printer. The following bits
+ are defined:
 <CENTER>
 <TABLE BORDER WIDTH="80%">
 <TR><TH>Bit</TH><TH>Description</TH></TR>
 <TR><TD VALIGN="TOP">0x00000001</TD><TD VALIGN="TOP">Is a printer class.</TD>
 </TR>
-<TR><TD VALIGN="TOP">0x00000002</TD><TD VALIGN="TOP">Is a remote 
-destination.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000002</TD><TD VALIGN="TOP">Is a remote
+ destination.</TD></TR>
 <TR><TD VALIGN="TOP">0x00000004</TD><TD VALIGN="TOP">Can print in black.</TD>
 </TR>
 <TR><TD VALIGN="TOP">0x00000008</TD><TD VALIGN="TOP">Can print in color.</TD>
 </TR>
-<TR><TD VALIGN="TOP">0x00000010</TD><TD VALIGN="TOP">Can print on both 
-sides of the page in hardware.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000010</TD><TD VALIGN="TOP">Can print on both
+ sides of the page in hardware.</TD></TR>
 <TR><TD VALIGN="TOP">0x00000020</TD><TD VALIGN="TOP">Can staple output.</TD>
 </TR>
-<TR><TD VALIGN="TOP">0x00000040</TD><TD VALIGN="TOP">Can do fast copies 
-in hardware.</TD></TR>
-<TR><TD VALIGN="TOP">0x00000080</TD><TD VALIGN="TOP">Can do fast copy 
-collation in hardware.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000040</TD><TD VALIGN="TOP">Can do fast copies
+ in hardware.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000080</TD><TD VALIGN="TOP">Can do fast copy
+ collation in hardware.</TD></TR>
 <TR><TD VALIGN="TOP">0x00000100</TD><TD VALIGN="TOP">Can punch output.</TD>
 </TR>
 <TR><TD VALIGN="TOP">0x00000200</TD><TD VALIGN="TOP">Can cover output.</TD>
@@ -1341,94 +1349,94 @@ collation in hardware.</TD></TR>
 </TR>
 <TR><TD VALIGN="TOP">0x00000800</TD><TD VALIGN="TOP">Can sort output.</TD>
 </TR>
-<TR><TD VALIGN="TOP">0x00001000</TD><TD VALIGN="TOP">Can handle media 
-up to US-Legal/A4.</TD></TR>
-<TR><TD VALIGN="TOP">0x00002000</TD><TD VALIGN="TOP">Can handle media 
-from US-Legal/A4 to ISO-C/A2.</TD></TR>
-<TR><TD VALIGN="TOP">0x00004000</TD><TD VALIGN="TOP">Can handle media 
-larger than ISO-C/A2.</TD></TR>
-<TR><TD VALIGN="TOP">0x00008000</TD><TD VALIGN="TOP">Can handle 
-user-defined media sizes.</TD></TR>
-<TR><TD VALIGN="TOP">0x00010000</TD><TD VALIGN="TOP">Is an implicit 
-(server-generated) class.</TD></TR>
+<TR><TD VALIGN="TOP">0x00001000</TD><TD VALIGN="TOP">Can handle media up
+ to US-Legal/A4.</TD></TR>
+<TR><TD VALIGN="TOP">0x00002000</TD><TD VALIGN="TOP">Can handle media
+ from US-Legal/A4 to ISO-C/A2.</TD></TR>
+<TR><TD VALIGN="TOP">0x00004000</TD><TD VALIGN="TOP">Can handle media
+ larger than ISO-C/A2.</TD></TR>
+<TR><TD VALIGN="TOP">0x00008000</TD><TD VALIGN="TOP">Can handle
+ user-defined media sizes.</TD></TR>
+<TR><TD VALIGN="TOP">0x00010000</TD><TD VALIGN="TOP">Is an implicit
+ (server-generated) class.</TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H3><A NAME="5_4_6">5.4.6 printer-type-mask (type2 enum)</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The printer-type-mask attribute is used to choose printers or 
-classes with the CUPS-Get-Printers and CUPS-Get-Classes operations. The 
-bits are defined identically to the printer-type attribute and default 
-to all 1's. </P>
-<H3><A NAME="5_4_7">5.4.7 requesting-user-name-allowed (1setof 
-name(127))</A></H3>
+<P>The printer-type-mask attribute is used to choose printers or classes
+ with the CUPS-Get-Printers and CUPS-Get-Classes operations. The bits
+ are defined identically to the printer-type attribute and default to
+ all 1's.</P>
+<H3><A NAME="5_4_7">5.4.7 requesting-user-name-allowed (1setof
+ name(127))</A></H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The requesting-user-name-allowed attribute lists all of the users 
-that are allowed to access a printer or class. Either this attribute or 
-the requesting-user-name-denied attribute will be defined, but not 
-both. </P>
+<P>The requesting-user-name-allowed attribute lists all of the users
+ that are allowed to access a printer or class. Either this attribute or
+ the requesting-user-name-denied attribute will be defined, but not
+ both.</P>
 <H3><A NAME="5_4_8">5.4.8 requesting-user-name-denied (1setof name(127))</A>
 </H3>
 <P><I>(CUPS 1.1 and higher)</I></P>
-<P>The requesting-user-name-denied attribute lists all of the users 
-that are not allowed to access a printer or class. Either this 
-attribute or the requesting-user-name-allowed attribute will be 
-defined, but not both. </P>
+<P>The requesting-user-name-denied attribute lists all of the users that
+ are not allowed to access a printer or class. Either this attribute or
+ the requesting-user-name-allowed attribute will be defined, but not
+ both.</P>
 <H2><A NAME="5_5">5.5 Printer Class Attributes</A></H2>
 <H3><A NAME="5_5_1">5.5.1 member-names (1setof name(127))</A></H3>
-<P>The member-names attribute specifies each of the printer-name 
-attributes of the member printers and classes. Each name corresponds to 
-the same element of the member-uris attribute. </P>
+<P>The member-names attribute specifies each of the printer-name
+ attributes of the member printers and classes. Each name corresponds to
+ the same element of the member-uris attribute.</P>
 <H3><A NAME="5_5_2">5.5.2 member-uris (1setof uri)</A></H3>
-<P>The member-uris attribute specifies each of the printer-uri 
-attributes of the member printers and classes. Each URI corresponds to 
-the same element of the member-names attribute. </P>
+<P>The member-uris attribute specifies each of the printer-uri
+ attributes of the member printers and classes. Each URI corresponds to
+ the same element of the member-names attribute.</P>
 <H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
 <H2><A NAME="6_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="6_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 </BODY>
 </HTML>
index 4036884ec97dd1a5f37b14c61561eaebb59657d4..c41d324c40dc5e37d793f6ddae077beb5e4babd7 100644 (file)
Binary files a/doc/ipp.pdf and b/doc/ipp.pdf differ
index a08063b0bbd07803b189d9f0c1e882940d2a9492..f7fc33d04e64a1de394c4cebbeb29389467d127f 100644 (file)
@@ -1633,6 +1633,18 @@ resolution is enabled.  The localhost address (127.0.0.1) is
 printing text files. Only the values 6 and 8 are currently supported.
 The default value is 6.
 
+<H3>natural-scaling (integer(1:1000))</H3>
+
+<P><I>(CUPS 1.1.9 and higher)</I>
+
+<P>The natural-scaling attribute specifies the scaling of image files with
+respect to the natural image size. A value of 100 specifies that the image
+file should exactly the natural size, while 50 is half the natural size
+and 200 is twice the natural size. The default value is 100.
+
+<P>The ppi option can be used to override the natural resolution of the
+image, which controls the natural size.
+
 <H3>page-bottom (integer(0:MAX))</H3>
 
 <P>The page-bottom attribute specifies the bottom margin in points (72 points
index 20259176fab75ef8c435b1a8458c4a99fb305781..37fb88810b0b97401a5a33fc418a7a66d751e062 100644 (file)
Binary files a/doc/overview.pdf and b/doc/overview.pdf differ
index 5a45b1dacef4e7774d4f2d622b9b4d53c26ebfc1..1f133b40c7b9396f775d499887a32160cd18a5fa 100644 (file)
@@ -119,11 +119,13 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <LI><A HREF="#BrowseInterval">BrowseInterval</A></LI>
 <LI><A HREF="#BrowsePoll">BrowsePoll</A></LI>
 <LI><A HREF="#BrowsePort">BrowsePort</A></LI>
+<LI><A HREF="#BrowseProtocols">BrowseProtocols</A></LI>
 <LI><A HREF="#BrowseRelay">BrowseRelay</A></LI>
 <LI><A HREF="#BrowseShortNames">BrowseShortNames</A></LI>
 <LI><A HREF="#BrowseTimeout">BrowseTimeout</A></LI>
 <LI><A HREF="#Browsing">Browsing</A></LI>
 <LI><A HREF="#Classification">Classification</A></LI>
+<LI><A HREF="#ClassifyOverride">ClassifyOverride</A></LI>
 <LI><A HREF="#DataDir">DataDir</A></LI>
 <LI><A HREF="#DefaultCharset">DefaultCharset</A></LI>
 <LI><A HREF="#DefaultLanguage">DefaultLanguage</A></LI>
@@ -134,8 +136,11 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <LI><A HREF="#FilterLimit">FilterLimit</A></LI>
 <LI><A HREF="#FontPath">FontPath</A></LI>
 <LI><A HREF="#Group">Group</A></LI>
+<LI><A HREF="#HideImplicitMembers">HideImplicitMembers</A></LI>
 <LI><A HREF="#HostNameLookups">HostNameLookups</A></LI>
 <LI><A HREF="#ImplicitClasses">ImplicitClasses</A></LI>
+<LI><A HREF="#ImplicitAnyClasses">ImplicitAnyClasses</A></LI>
+<LI><A HREF="#Include">Include</A></LI>
 <LI><A HREF="#KeepAlive">KeepAlive</A></LI>
 <LI><A HREF="#KeepAliveTimeout">KeepAliveTimeout</A></LI>
 <LI><A HREF="#Limit">Limit</A></LI>
@@ -252,8 +257,8 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <UL>
 <LI><A HREF="#13_1">My Applications Don't See the Available Printers</A></LI>
 <LI><A HREF="#13_2">CUPS Doesn't Recognize My Username or Password!</A></LI>
-<LI><A HREF="#13_3">I Can't Do Administration Tasks from Another 
-Machine!</A></LI>
+<LI><A HREF="#13_3">I Can't Do Administration Tasks from Another
+ Machine!</A></LI>
 <LI><A HREF="#13_4">I Can't Do Administration Tasks from My Web Browser!</A>
 </LI>
 <LI><A HREF="#13_5">Connection Refused Messages</A></LI>
@@ -261,30 +266,31 @@ Machine!</A></LI>
 </UL>
 <HR>
 <H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
-<P>This software administrators manual provides printer administration 
-information for the Common UNIX Printing System<SUP>TM</SUP> (&quot;CUPS<SUP>
-TM</SUP>&quot;), version 1.1.7. </P>
+<P>This software administrators manual provides printer administration
+ information for the Common UNIX Printing System<SUP>TM</SUP> &lt;&lt;&lt;&lt;&lt;&lt;&lt;
+ sam.shtml (&quot;CUPS<SUP>TM</SUP>&quot;), version 1.1.7. ======= (&quot;CUPS<SUP>TM</SUP>
+&quot;), version 1.1.13. &gt;&gt;&gt;&gt;&gt;&gt;&gt; 1.48</P>
 <H2><A NAME="1_1">System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 
 <!-- NEED 3in -->
 <H2><A NAME="1_2">Document Overview</A></H2>
-<P>This software administrators manual is organized into the following 
-sections:</P>
+<P>This software administrators manual is organized into the following
+ sections:</P>
 <UL>
 <LI><A HREF="#OVERVIEW">1 - Printing System Overview</A></LI>
 <LI><A HREF="#BUILDING_INSTALLING">2 - Building and Installing CUPS</A></LI>
@@ -300,16 +306,16 @@ sections:</P>
 <LI><A HREF="#FAQ">E - Troubleshooting Common Problems</A></LI>
 </UL>
 <H2><A NAME="1_3">Notation Conventions</A></H2>
-<P>Various font and syntax conventions are used in this guide. Examples 
-and their meanings and uses are explained below: 
+<P>Various font and syntax conventions are used in this guide. Examples
+ and their meanings and uses are explained below:
 <CENTER>
 <TABLE WIDTH="80%">
 <TR><TH>Example</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
-<BR><CODE> lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands; 
-the first mention of a command or  function in a chapter is followed by 
-a manual page section  number.</TD></TR>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands;
+ the first mention of a command or function in a chapter is followed by
+ a manual page section number.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD><VAR>/var</VAR>
 <BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
@@ -319,204 +325,206 @@ File and directory names.</TD></TR>
 &nbsp;&nbsp;&nbsp;</TD><TD>Screen output.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD><TD>
-&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are 
+&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are
  in ALL CAPS.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
-<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are 
-written using the period (.) to indicate  the decimal point.</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are
+ written using the period (.) to indicate the decimal point.</TD></TR>
 </TABLE>
 </CENTER>
 
 <!-- NEED 3in -->
 </P>
 <H2><A NAME="1_4">Abbreviations</A></H2>
- The following abbreviations are used throughout this manual: 
+ The following abbreviations are used throughout this manual:
 <UL>
 <DL>
-<DT>kb </DT>
+<DT>kb</DT>
 <DD>Kilobytes, or 1024 bytes
-<BR>&nbsp; </DD>
-<DT>Mb </DT>
+<BR>&nbsp;</DD>
+<DT>Mb</DT>
 <DD>Megabytes, or 1048576 bytes
-<BR>&nbsp; </DD>
-<DT>Gb </DT>
+<BR>&nbsp;</DD>
+<DT>Gb</DT>
 <DD>Gigabytes, or 1073741824 bytes
-<BR>&nbsp; </DD>
+<BR>&nbsp;</DD>
 </DL>
 </UL>
 <H2><A NAME="1_5">Other References</A></H2>
 <UL>
 <DL>
-<DT>CUPS Software Programmers Manual </DT>
-<DD>A programmer guide for interfacing with and/or extending the CUPS 
+<DT>CUPS Software Programmers Manual</DT>
+<DD>A programmer guide for interfacing with and/or extending the CUPS
  software.
-<BR>&nbsp; </DD>
-<DT>CUPS Software Users Manual </DT>
+<BR>&nbsp;</DD>
+<DT>CUPS Software Users Manual</DT>
 <DD>An end-user guide for using the CUPS software.
-<BR>&nbsp; </DD>
+<BR>&nbsp;</DD>
 </DL>
 </UL>
 <H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
-<P>This chapter provides an overview of how the Common UNIX Printing 
-System works. </P>
+<P>This chapter provides an overview of how the Common UNIX Printing
+ System works.</P>
 <H2><A NAME="2_1">The Printing Problem</A></H2>
-<P>For years <I>the printing problem</I> has plagued UNIX. Unlike 
-Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system 
-in place for supporting printers. Among the solutions currently 
-available, the Berkeley and System V printing systems are the most 
-prevalent. </P>
-<P>These printing systems support line printers (text only) or 
-PostScript printers (text and graphics), and with some coaxing they can 
-be made to support a full range of printers and file formats. However, 
-because each varient of the UNIX operating system uses a different 
-printing system than the next developing printer drivers for a wide 
-range of printers and operating systems is extremely difficult. That 
-combined with the limited volume of customers for each UNIX varient has 
-forced most printer vendors to give up supporting UNIX entirely. </P>
-<P>CUPS is designed to eliminate <I>the printing problem</I>. One 
-common printing system can be used by all UNIX varients to support the 
-printing needs of users. Printer vendors can use its modular filter 
-interface to develop a single driver program that supports a wide range 
-of file formats with little or no effort.  Since CUPS provides both the 
-System V and Berkeley printing commands, users (and applications) can 
-reap the benefits of this new technology with no changes. </P>
+<P>For years<I> the printing problem</I> has plagued UNIX. Unlike
+ Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system
+ in place for supporting printers. Among the solutions currently
+ available, the Berkeley and System V printing systems are the most
+ prevalent.</P>
+<P>These printing systems support line printers (text only) or
+ PostScript printers (text and graphics), and with some coaxing they can
+ be made to support a full range of printers and file formats. However,
+ because each varient of the UNIX operating system uses a different
+ printing system than the next developing printer drivers for a wide
+ range of printers and operating systems is extremely difficult. That
+ combined with the limited volume of customers for each UNIX varient has
+ forced most printer vendors to give up supporting UNIX entirely.</P>
+<P>CUPS is designed to eliminate<I> the printing problem</I>. One common
+ printing system can be used by all UNIX varients to support the
+ printing needs of users. Printer vendors can use its modular filter
+ interface to develop a single driver program that supports a wide range
+ of file formats with little or no effort. Since CUPS provides both the
+ System V and Berkeley printing commands, users (and applications) can
+ reap the benefits of this new technology with no changes.</P>
 <H2><A NAME="2_2">The Technology</A></H2>
-<P>CUPS is based upon an emerging Internet standard called the Internet 
-Printing Protocol. IPP has been embraced by dozens of printer and 
-printer server manufacturers and is supported by Microsoft Windows 
-2000. </P>
-<P>IPP defines a standard protocol for printing as well as managing 
-print jobs and printer options like media size, resolution, and so 
-forth. Like all IP-based protocols, IPP can be used locally or over the 
-Internet to printers hundreds or thousands of miles away. Unlike other 
-protocols, however, IPP also supports access control, authentication, 
-and encryption, making it a much more capable and secure printing 
-solution than older ones. </P>
-<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;) 
-which is the basis of web servers on the Internet. This allows users to 
-view documentation, check status information on a printer or server, 
-and manage their printers, classes, and jobs using their web browser. </P>
-<P>CUPS provides a complete IPP/1.1 based printing system that provides 
-Basic, Digest, and local certificate authentication and user, domain, 
-or IP-based access control. TLS encryption will be available in future 
-versions of CUPS. </P>
+<P>CUPS is based upon an emerging Internet standard called the Internet
+ Printing Protocol. IPP has been embraced by dozens of printer and
+ printer server manufacturers and is supported by Microsoft Windows
+ 2000.</P>
+<P>IPP defines a standard protocol for printing as well as managing
+ print jobs and printer options like media size, resolution, and so
+ forth. Like all IP-based protocols, IPP can be used locally or over the
+ Internet to printers hundreds or thousands of miles away. Unlike other
+ protocols, however, IPP also supports access control, authentication,
+ and encryption, making it a much more capable and secure printing
+ solution than older ones.</P>
+<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;)
+ which is the basis of web servers on the Internet. This allows users to
+ view documentation, check status information on a printer or server,
+ and manage their printers, classes, and jobs using their web browser.</P>
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+ Basic, Digest, and local certificate authentication and user, domain,
+ or IP-based access control. TLS encryption will be available in future
+ versions of CUPS.</P>
 <H2><A NAME="2_3">Jobs</A></H2>
-<P>Each file or set of files that is submitted for printing is called a <I>
-job</I>. Jobs are identified by a unique number starting at 1 and are 
-assigned to a particular destination, usually a printer. Jobs can also 
-have options associated with them such as media size, number of copies, 
-and priority. </P>
+<P>Each file or set of files that is submitted for printing is called a<I>
+ job</I>. Jobs are identified by a unique number starting at 1 and are
+ assigned to a particular destination, usually a printer. Jobs can also
+ have options associated with them such as media size, number of copies,
+ and priority.</P>
 <H2><A NAME="2_4">Classes</A></H2>
-<P>CUPS supports collections of printers known as <I>classes</I>. Jobs 
-sent to a class are forwarded to the first available printer in the 
-class. </P>
+<P>CUPS supports collections of printers known as<I> classes</I>. Jobs
+ sent to a class are forwarded to the first available printer in the
+ class.</P>
 <H2><A NAME="2_5">Filters</A></H2>
-<P>Filters allow a user or application to print many types of files 
-without extra effort. Print jobs sent to a CUPS server are filtered 
-before sending them to a printer. Some filters convert job files to 
-different formats that the printer can understand. Others perform page 
-selection and ordering tasks. </P>
-<P>CUPS provides filters for printing many types of image files, 
-HP-GL/2 files, PDF files, and text files. CUPS also supplies PostScript 
-and image file Raster Image Processor (&quot;RIP&quot;) filters that convert 
-PostScript or image files into bitmaps that can be sent to a raster 
-printer. </P>
+<P>Filters allow a user or application to print many types of files
+ without extra effort. Print jobs sent to a CUPS server are filtered
+ before sending them to a printer. Some filters convert job files to
+ different formats that the printer can understand. Others perform page
+ selection and ordering tasks.</P>
+<P>CUPS provides filters for printing many types of image files, HP-GL/2
+ files, PDF files, and text files. CUPS also supplies PostScript and
+ image file Raster Image Processor (&quot;RIP&quot;) filters that convert
+ PostScript or image files into bitmaps that can be sent to a raster
+ printer.</P>
 <H2><A NAME="2_6">Backends</A></H2>
-<P>Backends perform the most important task of all - they send the 
-filtered print data to the printer. </P>
-<P>CUPS provides backends for printing over parallel, serial, and USB 
-ports, and over the network via the IPP, JetDirect (AppSocket), and 
-Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are 
-available in network service packages such as the SMB backend included 
-with the popular SAMBA software. </P>
-<P>Backends are also used to determine the available devices. On 
-startup each backend is asked for a list of devices it supports, and 
-any information that is available. This allows the parallel backend to 
-tell CUPS that an EPSON Stylus Color 600 printer is attached to 
-parallel port 1, for example. </P>
+<P>Backends perform the most important task of all - they send the
+ filtered print data to the printer.</P>
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ ports, and over the network via the IPP, JetDirect (AppSocket), and
+ Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are
+ available in network service packages such as the SMB backend included
+ with the popular SAMBA software.</P>
+<P>Backends are also used to determine the available devices. On startup
+ each backend is asked for a list of devices it supports, and any
+ information that is available. This allows the parallel backend to tell
+ CUPS that an EPSON Stylus Color 600 printer is attached to parallel
+ port 1, for example.</P>
 <H2><A NAME="2_7">Printer Drivers</A></H2>
-<P>Printer drivers in CUPS consist of one of more filters specific to a 
-printer. CUPS includes sample printer drivers for Hewlett-Packard 
-LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color, 
-and Stylus Photo printers. While these drivers do not generate optimal 
-output for the different printer models, they do provide basic printing 
-and demonstrate how you can write your own printer drivers and 
-incorporate them into CUPS. </P>
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+ printer. CUPS includes sample printer drivers for Hewlett-Packard
+ LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+ and Stylus Photo printers. While these drivers do not generate optimal
+ output for the different printer models, they do provide basic printing
+ and demonstrate how you can write your own printer drivers and
+ incorporate them into CUPS.</P>
 <H2><A NAME="2_8">Networking</A></H2>
-<P>Printers and classes on the local system are automatically shared 
-with other systems on the network. This allows you to setup one system 
-to print to a printer and use this system as a printer server or spool 
-host for all of the others. Users may then select a local printer by 
-name or a remote printer using &quot;name@server&quot;. </P>
-<P>CUPS also provides <I>implicit classes</I>, which are collections of 
-printers and/or classes with the same name. This allows you to setup 
-multiple servers pointing to the same physical network printer, for 
-example, so that you aren't relying on a single system for printing. 
-Because this also works with printer classes, you can setup multiple 
-servers and printers and never worry about a single point of failure 
-unless all of the printers and servers go down! </P>
-<H1 ALIGN="RIGHT"><A NAME="BUILDING_INSTALLING">2 - Building and 
-Installing CUPS</A></H1>
-<P>This chapter shows how to build and install the Common UNIX Printing 
-System. If you are installing a binary distribution from the CUPS web 
-site, proceed to the section titled, <A HREF="#BINARY">Installing a 
-Binary Distribution</A>. </P>
+<P>Printers and classes on the local system are automatically shared
+ with other systems on the network. This allows you to setup one system
+ to print to a printer and use this system as a printer server or spool
+ host for all of the others. Users may then select a local printer by
+ name or a remote printer using &quot;name@server&quot;.</P>
+<P>CUPS also provides<I> implicit classes</I>, which are collections of
+ printers and/or classes with the same name. This allows you to setup
+ multiple servers pointing to the same physical network printer, for
+ example, so that you aren't relying on a single system for printing.
+ Because this also works with printer classes, you can setup multiple
+ servers and printers and never worry about a single point of failure
+ unless all of the printers and servers go down!</P>
+<H1 ALIGN="RIGHT"><A NAME="BUILDING_INSTALLING">2 - Building and
+ Installing CUPS</A></H1>
+<P>This chapter shows how to build and install the Common UNIX Printing
+ System. If you are installing a binary distribution from the CUPS web
+ site, proceed to the section titled,<A HREF="#BINARY"> Installing a
+ Binary Distribution</A>.</P>
 <H2><A NAME="3_1">Installing a Source Distribution</A></H2>
-<P>This section describes how to compile and install CUPS on your 
-system from the source code. </P>
+<P>This section describes how to compile and install CUPS on your system
+ from the source code.</P>
 <H3><A NAME="REQUIREMENTS">Requirements</A></H3>
-<P>You'll need ANSI-compliant C and C++ compilers to build CUPS on your 
-system. As its name implies, CUPS is designed to run on the UNIX 
-operating system, however the CUPS interface library and most of the 
-filters and backends supplied with CUPS should also compile and run 
-under Microsoft Windows. </P>
-<P>For the image file filters and PostScript RIP, you'll need the JPEG, 
-PNG, TIFF, and ZLIB libraries. CUPS will build without these, but with 
-significantly reduced functionality. Easy Software Products maintains a 
-mirror of the current versions of these libraries at: </P>
+<P>You'll need ANSI-compliant C and C++ compilers to build CUPS on your
+ system. As its name implies, CUPS is designed to run on the UNIX
+ operating system, however the CUPS interface library and most of the
+ filters and backends supplied with CUPS should also compile and run
+ under Microsoft Windows.</P>
+<P>For the image file filters and PostScript RIP, you'll need the JPEG,
+ PNG, TIFF, and ZLIB libraries. CUPS will build without these, but with
+ significantly reduced functionality. Easy Software Products maintains a
+ mirror of the current versions of these libraries at:</P>
 <UL>
 <PRE>
 <A HREF="ftp://ftp.easysw.com/pub/libraries">ftp://ftp.easysw.com/pub/libraries</A>
 </PRE>
 </UL>
-<P>If you make changes to the man pages you'll need GNU groff or 
-another nroff-like package. GNU groff is available from: </P>
+<P>If you make changes to the man pages you'll need GNU groff or another
+ nroff-like package. GNU groff is available from:</P>
 <UL>
 <PRE>
 <A HREF="ftp://ftp.gnu.org/pub/groff">ftp://ftp.gnu.org/pub/groff</A>
 </PRE>
 </UL>
-<P>The documentation is formatted using the HTMLDOC software. If you 
-need to make changes you can get the HTMLDOC software from: </P>
+<P>The documentation is formatted using the HTMLDOC software. If you
+ need to make changes you can get the HTMLDOC software from:</P>
 <UL>
 <PRE>
 <A HREF="http://www.easysw.com/htmldoc">http://www.easysw.com/htmldoc</A>
 </PRE>
 </UL>
+<P>Finally, you'll need a <CODE>make</CODE> program that understands the
+ <CODE>include</CODE> directive - FreeBSD, NetBSD, and OpenBSD
+ developers should use the <CODE>gmake</CODE> program.</P>
 <H3><A NAME="COMPILING">Compiling CUPS</A></H3>
-<P>CUPS uses GNU autoconf to configure the makefiles and source code 
-for your system. Type the following command to configure CUPS for your 
-system: </P>
+<P>CUPS uses GNU autoconf to configure the makefiles and source code for
+ your system. Type the following command to configure CUPS for your
+ system:</P>
 <UL>
 <PRE>
 <B>./configure ENTER</B>
 </PRE>
 </UL>
-<P>The default installation will put the CUPS software in the <VAR>/etc</VAR>
-, <VAR>/usr</VAR>, and <VAR>/var</VAR> directories on your system, 
-which will overwrite any existing printing commands on your system. Use 
-the <CODE>--prefix</CODE> option to install the CUPS software in 
-another location: </P>
+<P>The default installation will put the CUPS software in the<VAR> /etc</VAR>
+,<VAR> /usr</VAR>, and<VAR> /var</VAR> directories on your system, which
+ will overwrite any existing printing commands on your system. Use the <CODE>
+--prefix</CODE> option to install the CUPS software in another location:</P>
 <UL>
 <PRE>
 <B>./configure --prefix=/some/directory ENTER</B>
 </PRE>
 </UL>
-<P>If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in a 
-system default location (typically <VAR>/usr/include</VAR> and <VAR>
-/usr/lib</VAR>) you'll need to set the <CODE>CFLAGS</CODE>, <CODE>
-CXXFLAGS</CODE>, and <CODE>LDFLAGS</CODE> environment variables prior 
-to running configure: </P>
+<P>If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in a
+ system default location (typically<VAR> /usr/include</VAR> and<VAR>
+ /usr/lib</VAR>) you'll need to set the <CODE>CFLAGS</CODE>, <CODE>
+CXXFLAGS</CODE>, and <CODE>LDFLAGS</CODE> environment variables prior to
+ running configure:</P>
 <UL>
 <PRE>
 <B>setenv CFLAGS &quot;-I/some/directory&quot; ENTER</B>
@@ -526,7 +534,7 @@ to running configure: </P>
 <B>./configure ... ENTER</B>
 </PRE>
 </UL>
-<P>or: </P>
+<P>or:</P>
 <UL>
 <PRE>
 <B>CFLAGS=&quot;-I/some/directory&quot;; export CFLAGS ENTER</B>
@@ -536,30 +544,40 @@ to running configure: </P>
 <B>./configure ... ENTER</B>
 </PRE>
 </UL>
-<P>To enable support for encryption, you'll also want to add the 
-&quot;--enable-ssl&quot; option: </P>
+<P>To enable support for encryption, you'll also want to add the
+ &quot;--enable-ssl&quot; option:</P>
 <UL>
 <PRE>
 ./configure --enable-ssl
 </PRE>
 </UL>
-<P>SSL and TLS support require the OpenSSL library, available at: </P>
+<P>SSL and TLS support require the OpenSSL library, available at:</P>
 <UL>
 <PRE>
 <A HREF="http://www.openssl.org">http://www.openssl.org</A>
 </PRE>
 </UL>
-<P>Once you have configured things, just type: </P>
+<P>If the OpenSSL headers and libraries are not installed in the
+ standard directories, use the <CODE>--with-openssl-includes</CODE> and <CODE>
+--with-openssl-libs</CODE> options:</P>
+<UL>
+<PRE>
+./configure --enable-ssl \
+    --with-openssl-includes=/foo/bar/include \
+    --with-openssl-libs=/foo/bar/lib
+</PRE>
+</UL>
+<P>Once you have configured things, just type:</P>
 <UL>
 <PRE>
 <B>make ENTER</B>
 </PRE>
 </UL>
-<P>to build the software. 
+<P>to build the software.
 <!-- NEED 4in -->
 </P>
 <H3><A NAME="INSTALLING">Installing the Software</A></H3>
-<P>Use the &quot;install&quot; target to install the software: </P>
+<P>Use the &quot;install&quot; target to install the software:</P>
 <UL>
 <PRE>
 <B>make install ENTER</B>
@@ -568,16 +586,16 @@ to running configure: </P>
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> WARNING:</B>
-<P>Installing CUPS will overwrite your existing printing  system. If 
-you experience difficulties with the CUPS software  and need to go back 
-to your old printing system, you will need  to reinstall the old 
-printing system from your operating system CDs. </P>
+<P>Installing CUPS will overwrite your existing printing system. If you
+ experience difficulties with the CUPS software and need to go back to
+ your old printing system, you will need to reinstall the old printing
+ system from your operating system CDs.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="RUNNING">Running the Software</A></H3>
-<P>Once you have installed the software you can start the CUPS server 
-by typing: </P>
+<P>Once you have installed the software you can start the CUPS server by
+ typing:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/cupsd ENTER</B>
@@ -586,79 +604,79 @@ by typing: </P>
 
 <!-- NEED 4in -->
 <H2><A NAME="BINARY">Installing a Binary Distribution</A></H2>
-<P>CUPS comes in a variety of binary distribution formats. Easy 
-Software Products provides binaries in TAR format with installation and 
-removal scripts (&quot;portable&quot; distributions), and in RPM and DPKG formats 
-for Red Hat and Debian-based distributions.  Portable distributions are 
-available for all platforms, while the RPM and DPKG distributions are 
-only available for Linux. 
+<P>CUPS comes in a variety of binary distribution formats. Easy Software
+ Products provides binaries in TAR format with installation and removal
+ scripts (&quot;portable&quot; distributions), and in RPM and DPKG formats for Red
+ Hat and Debian-based distributions. Portable distributions are
+ available for all platforms, while the RPM and DPKG distributions are
+ only available for Linux.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> WARNING:</B>
-<P>Installing CUPS will overwrite your existing printing  system. If 
-you experience difficulties with the CUPS software  and need to go back 
-to your old printing system, you will need  to remove the CUPS software 
-with the provided script and/or  reinstall the old printing system from 
-your operating system CDs. </P>
+<P>Installing CUPS will overwrite your existing printing system. If you
+ experience difficulties with the CUPS software and need to go back to
+ your old printing system, you will need to remove the CUPS software
+ with the provided script and/or reinstall the old printing system from
+ your operating system CDs.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H3><A NAME="PORTABLE-BINARY">Installing a Portable Distribution</A></H3>
-<P>To install the CUPS software from a portable distribution you will 
-need to be logged in as root; doing an <CODE>su</CODE> is good enough. 
-Once you are the root user, run the installation script with: </P>
+<P>To install the CUPS software from a portable distribution you will
+ need to be logged in as root; doing an <CODE>su</CODE> is good enough.
+ Once you are the root user, run the installation script with:</P>
 <UL>
 <PRE>
 <B>./cups.install ENTER</B>
 </PRE>
 </UL>
-<P>After asking you a few yes/no questions the CUPS software will be 
-installed and the scheduler will be started automatically. 
+<P>After asking you a few yes/no questions the CUPS software will be
+ installed and the scheduler will be started automatically.
 <!-- NEED 2in -->
 </P>
 <H3><A NAME="RPM-BINARY">Installing an RPM Distribution</A></H3>
-<P>To install the CUPS software from an RPM distribution you will need 
-to be logged in as root; doing an <CODE>su</CODE> is good enough. Once 
-you are the root user, run RPM with: </P>
+<P>To install the CUPS software from an RPM distribution you will need
+ to be logged in as root; doing an <CODE>su</CODE> is good enough. Once
+ you are the root user, run RPM with:</P>
 <UL>
 <PRE>
 <B>rpm -e lpr</B>
 <B>rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTER</B>
 </PRE>
 </UL>
-<P>After a short delay the CUPS software will be installed and the 
-scheduler will be started automatically. </P>
+<P>After a short delay the CUPS software will be installed and the
+ scheduler will be started automatically.</P>
 <H3><A NAME="DPKG-BINARY">Installing an Debian Distribution</A></H3>
-<P>To install the CUPS software from a Debian distribution you will 
-need to be logged in as root; doing an <CODE>su</CODE> is good enough. 
-Once you are the root user, run dpkg with: </P>
+<P>To install the CUPS software from a Debian distribution you will need
+ to be logged in as root; doing an <CODE>su</CODE> is good enough. Once
+ you are the root user, run dpkg with:</P>
 <UL>
 <PRE>
 <B>dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTER</B>
 </PRE>
 </UL>
-<P>After a short delay the CUPS software will be installed and the 
-scheduler will be started automatically. </P>
+<P>After a short delay the CUPS software will be installed and the
+ scheduler will be started automatically.</P>
 <H1 ALIGN="RIGHT"><A NAME="PRINTER_MANAGEMENT">3 - Printer Management</A>
 </H1>
-<P>This chapter describes how to add your first printer and how to 
-manage your printers. </P>
+<P>This chapter describes how to add your first printer and how to
+ manage your printers.</P>
 <H2><A NAME="4_1">The Basics</A></H2>
-<P>Each printer queue has a name associated with it; the printer name 
-must start with a letter and can contain up to 127 letters, numbers, 
-and the underscore (_). Case is not significant, e.g. &quot;PRINTER&quot;, 
-&quot;Printer&quot;, and &quot;printer&quot; are considered to be the same name. </P>
-<P>Printer queues also have a device associated with them. The device 
-can be a parallel port, a network interface, and so forth. Devices 
-within CUPS use Uniform Resource Identifiers (&quot;URIs&quot;) which are a more 
-general form of Uniform Resource Locators (&quot;URLs&quot;) that are used in 
-your web browser. For example, the first parallel port in Linux usually 
-uses a device URI of <CODE>parallel:/dev/lp1</CODE>. 
+<P>Each printer queue has a name associated with it; the printer name
+ must start with a letter and can contain up to 127 letters, numbers,
+ and the underscore (_). Case is not significant, e.g. &quot;PRINTER&quot;,
+ &quot;Printer&quot;, and &quot;printer&quot; are considered to be the same name.</P>
+<P>Printer queues also have a device associated with them. The device
+ can be a parallel port, a network interface, and so forth. Devices
+ within CUPS use Uniform Resource Identifiers (&quot;URIs&quot;) which are a more
+ general form of Uniform Resource Locators (&quot;URLs&quot;) that are used in
+ your web browser. For example, the first parallel port in Linux usually
+ uses a device URI of <CODE>parallel:/dev/lp1</CODE>.
 <!-- NEED 2.5in -->
 </P>
 <P>You can see a complete list of supported devices by running the <CODE>
-lpinfo(8)</CODE> command: </P>
+lpinfo(8)</CODE> command:</P>
 <UL>
 <PRE>
 <B>lpinfo -v ENTER</B>
@@ -674,240 +692,249 @@ direct usb:/dev/usb/lp0
 network smb
 </PRE>
 </UL>
-<P>The <CODE>-v</CODE> option specifies that you want a list of 
-available devices. The first word in each line is the type of device 
-(direct, file, network, or serial) and is followed by the device URI or 
-method name for that device. File devices have device URIs of the form <CODE>
-file:/directory/filename</CODE> while network devices use the more 
-familiar <CODE>method://server</CODE> or <CODE>method://server/path</CODE>
- format. </P>
-<P>Finally, printer queues usually have a PostScript Printer 
-Description (&quot;PPD&quot;) file associated with them. PPD files describe the 
-capabilities of each printer, the page sizes supported, etc., and are 
-used for PostScript and non-PostScript printers. CUPS includes PPD 
-files for HP LaserJet, HP DeskJet, EPSON 9-pin, EPSON 24-pin, and EPSON 
-Stylus printers. </P>
+<P>The <CODE>-v</CODE> option specifies that you want a list of
+ available devices. The first word in each line is the type of device
+ (direct, file, network, or serial) and is followed by the device URI or
+ method name for that device. File devices have device URIs of the form <CODE>
+file:/directory/filename</CODE> while network devices use the more
+ familiar <CODE>method://server</CODE> or <CODE>method://server/path</CODE>
+ format.</P>
+<P>Finally, printer queues usually have a PostScript Printer Description
+ (&quot;PPD&quot;) file associated with them. PPD files describe the capabilities
+ of each printer, the page sizes supported, etc., and are used for
+ PostScript and non-PostScript printers. CUPS includes PPD files for HP
+ LaserJet, HP DeskJet, EPSON 9-pin, EPSON 24-pin, and EPSON Stylus
+ printers.</P>
 <H2><A NAME="4_2">Adding Your First Printer</A></H2>
-<P>CUPS provides two methods for adding printers: a command-line 
-program called <CODE>lpadmin(8)</CODE> and a Web interface. The <CODE>
-lpadmin</CODE> command allows you to perform most printer 
-administration tasks from the command-line and is located in <VAR>
-/usr/sbin</VAR>. The Web interface is located at: </P>
+<P>CUPS provides two methods for adding printers: a command-line program
+ called <CODE>lpadmin(8)</CODE> and a Web interface. The <CODE>lpadmin</CODE>
+ command allows you to perform most printer administration tasks from
+ the command-line and is located in<VAR> /usr/sbin</VAR>. The Web
+ interface is located at:</P>
 <UL>
 <PRE>
 <A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
 </PRE>
 </UL>
-<P>and steps you through printer configuration. If you don't like 
-command-line interfaces, try the <A HREF="#ADD_WEB">Web interface</A>
- instead. </P>
+<P>and steps you through printer configuration. If you don't like
+ command-line interfaces, try the<A HREF="#ADD_WEB"> Web interface</A>
+ instead.</P>
 <H3><A NAME="4_2_1">Adding Your First Printer from the Command-Line</A></H3>
-<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option 
-to add a printer to CUPS: </P>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option
+ to add a printer to CUPS:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -p <I>printer</I> -E -v <I>device</I> -m <I>ppd</I> ENTER</B>
 </PRE>
 </UL>
-<P>For an HP DeskJet printer connected to the parallel port this would 
-look like: </P>
+<P>For an HP DeskJet printer connected to the parallel port this would
+ look like:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTER</B>
 </PRE>
 </UL>
-<P>Similarly, an HP LaserJet printer using a JetDirect network 
-interface at IP address 11.22.33.44 would be added with the command: </P>
+<P>Similarly, an HP LaserJet printer using a JetDirect network interface
+ at IP address 11.22.33.44 would be added with the command:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTER</B>
 </PRE>
 </UL>
 <P>As you can see, <CODE>deskjet.ppd</CODE> and <CODE>laserjet.ppd</CODE>
- are the PPD files for the HP DeskJet and HP LaserJet drivers included 
-with CUPS. You'll find a complete list of PPD files and the printers 
-they will work with in <A HREF="#PRINTER_DRIVERS">Appendix C, &quot;Printer 
-Drivers&quot;</A>. </P>
+ are the PPD files for the HP DeskJet and HP LaserJet drivers included
+ with CUPS. You'll find a complete list of PPD files and the printers
+ they will work with in<A HREF="#PRINTER_DRIVERS"> Appendix C, &quot;Printer
+ Drivers&quot;</A>.</P>
+<P>For a dot matrix printer connected to the serial port this would
+ might look like:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTER</B>
+</PRE>
+</UL>
+<P>Here you specify the serial port (e.g. S0,S1, d0, d1), baud rate
+ (e.g. 9600, 19200, 38400, 115200, etc.), number of bits, parity, and
+ flow control. If you do not need flow control, delete the &quot;+flow=soft&quot;
+ portion.</P>
 <H3><A NAME="ADD_WEB">Adding Your First Printer from the Web</A></H3>
-<P>The CUPS web server provides a user-friendly &quot;wizard&quot; interface for 
-adding your printers. Rather than figuring out which device URI and PPD 
-file to use, you can instead click on the appropriate listings and fill 
-in some simple information. Enter the following URL in your web browser 
-to begin: </P>
+<P>The CUPS web server provides a user-friendly &quot;wizard&quot; interface for
+ adding your printers. Rather than figuring out which device URI and PPD
+ file to use, you can instead click on the appropriate listings and fill
+ in some simple information. Enter the following URL in your web browser
+ to begin:</P>
 <UL>
 <PRE>
 <A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
 </PRE>
 </UL>
-<P>Click on the <VAR>Add Printer</VAR> button to add a printer. </P>
+<P>Click on the<VAR> Add Printer</VAR> button to add a printer.</P>
 <H2><A NAME="4_3">Managing Printers from the Command-Line</A></H2>
-<P>The <CODE>lpadmin</CODE> command enables you to perform most printer 
-administration tasks from the command-line. You'll find <CODE>lpadmin</CODE>
- in the <VAR>/usr/sbin</VAR> directory. </P>
+<P>The <CODE>lpadmin</CODE> command enables you to perform most printer
+ administration tasks from the command-line. You'll find <CODE>lpadmin</CODE>
+ in the<VAR> /usr/sbin</VAR> directory.</P>
 <H3><A NAME="4_3_1">Adding and Modifying Printers</A></H3>
-<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option 
-to add or modify a printer: </P>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option
+ to add or modify a printer:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -p <I>printer</I> <I>options</I> ENTER</B>
 </PRE>
 </UL>
-<P>The <I>options</I> arguments can be any of the following: </P>
+<P>The<I> options</I> arguments can be any of the following:</P>
 <UL>
 <DL>
-<DT>-c <I>class</I></DT>
-<DD>Adds the named printer to printer class <VAR>class</VAR>.  If the 
-class does not exist then it is created. </DD>
-<DT>-i <I>interface</I></DT>
-<DD>Copies the named <VAR>interface</VAR> script to the printer. 
- Interface scripts are used by System V printer drivers. Since  all 
-filtering is disabled when using an interface script, scripts 
- generally should not be used unless there is no other driver for  a 
-printer. </DD>
-<DT>-m <I>model</I></DT>
-<DD>Specifies a standard printer driver which is usually a PPD  file. A 
-list of all available models can be displayed using the <CODE> lpinfo</CODE>
- command with the <CODE>-m</CODE> option. A  list of printer drivers 
-included with CUPS can be found in <A HREF="#PRINTER_DRIVERS"> Appendix 
-C, &quot;Printer Drivers&quot;</A>. </DD>
-<DT>-r <I>class</I></DT>
-<DD>Removes the named printer from printer class <VAR>class.  If the 
-resulting class becomes empty then it is removed. </VAR></DD>
-<DT>-v <I>device-uri</I></DT>
-<DD>Sets the device for communicating with the printer. If a  job is 
-currently printing on the named printer then the job  will be restarted 
-and sent to the new device. </DD>
-<DT>-D <I>info</I></DT>
-<DD>Provides a textual description of the printer, e.g.  &quot;John's 
-Personal Printer&quot;. </DD>
-<DT>-E </DT>
-<DD>Enables the printer and accepts job. This option is  equivalent to 
-running the <CODE>enable(1)</CODE> and <CODE> accept(8)</CODE> commands 
-on the printer. </DD>
-<DT>-L <I>location</I></DT>
-<DD>Provides a textual location for the printer, e.g.  &quot;Computer Lab 
-5&quot;. </DD>
-<DT>-P <I>ppd-file</I></DT>
-<DD>Specifies a local PPD file for the printer driver. </DD>
+<DT>-c<I> class</I></DT>
+<DD>Adds the named printer to printer class<VAR> class</VAR>. If the
+ class does not exist then it is created.</DD>
+<DT>-i<I> interface</I></DT>
+<DD>Copies the named<VAR> interface</VAR> script to the printer.
+ Interface scripts are used by System V printer drivers. Since all
+ filtering is disabled when using an interface script, scripts generally
+ should not be used unless there is no other driver for a printer.</DD>
+<DT>-m<I> model</I></DT>
+<DD>Specifies a standard printer driver which is usually a PPD file. A
+ list of all available models can be displayed using the <CODE>lpinfo</CODE>
+ command with the <CODE>-m</CODE> option. A list of printer drivers
+ included with CUPS can be found in<A HREF="#PRINTER_DRIVERS"> Appendix
+ C, &quot;Printer Drivers&quot;</A>.</DD>
+<DT>-r<I> class</I></DT>
+<DD>Removes the named printer from printer class<VAR> class. If the
+ resulting class becomes empty then it is removed.</VAR></DD>
+<DT>-v<I> device-uri</I></DT>
+<DD>Sets the device for communicating with the printer. If a job is
+ currently printing on the named printer then the job will be restarted
+ and sent to the new device.</DD>
+<DT>-D<I> info</I></DT>
+<DD>Provides a textual description of the printer, e.g. &quot;John's Personal
+ Printer&quot;.</DD>
+<DT>-E</DT>
+<DD>Enables the printer and accepts job. This option is equivalent to
+ running the <CODE>enable(1)</CODE> and <CODE>accept(8)</CODE> commands
+ on the printer.</DD>
+<DT>-L<I> location</I></DT>
+<DD>Provides a textual location for the printer, e.g. &quot;Computer Lab 5&quot;.</DD>
+<DT>-P<I> ppd-file</I></DT>
+<DD>Specifies a local PPD file for the printer driver.</DD>
 </DL>
 </UL>
 <H3><A NAME="4_3_2">Deleting Printers</A></H3>
-<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-x</CODE> option 
-to delete a printer: </P>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-x</CODE> option
+ to delete a printer:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -x <I>printer</I> ENTER</B>
 </PRE>
 </UL>
 <H3><A NAME="4_3_3">Setting the Default Printer</A></H3>
-<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-d</CODE> option 
-to set a default printer: </P>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-d</CODE> option
+ to set a default printer:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -d <I>printer</I> ENTER</B>
 </PRE>
 </UL>
 <P>The default printer can be overridden by the user using the <CODE>
-lpoptions(1)</CODE> command. </P>
+lpoptions(1)</CODE> command.</P>
 <H3><A NAME="4_3_4">Starting and Stopping Printers</A></H3>
-<P>The <CODE>enable</CODE> and <CODE>disable</CODE> commands start and 
-stop printer queues, respectively: </P>
+<P>The <CODE>enable</CODE> and <CODE>disable</CODE> commands start and
+ stop printer queues, respectively:</P>
 <UL>
 <PRE>
 <B>/usr/bin/enable <I>printer</I> ENTER</B>
 <B>/usr/bin/disable <I>printer</I> ENTER</B>
 </PRE>
 </UL>
-<P>Printers that are disabled may still accept jobs for printing, but 
-won't actually print any files until they are restarted. This is useful 
-if the printer malfunctions and you need time to correct the problem. 
-Any queued jobs are printed after the printer is enabled (started). </P>
+<P>Printers that are disabled may still accept jobs for printing, but
+ won't actually print any files until they are restarted. This is useful
+ if the printer malfunctions and you need time to correct the problem.
+ Any queued jobs are printed after the printer is enabled (started).</P>
 <H3><A NAME="4_3_5">Accepting and Rejecting Print Jobs</A></H3>
-<P>The <CODE>accept</CODE> and <CODE>reject</CODE> commands accept and 
-reject print jobs for the named printer, respectively: </P>
+<P>The <CODE>accept</CODE> and <CODE>reject</CODE> commands accept and
+ reject print jobs for the named printer, respectively:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/accept <I>printer</I> ENTER</B>
 <B>/usr/sbin/reject <I>printer</I> ENTER</B>
 </PRE>
 </UL>
-<P>As noted above, a printer can be stopped but accepting new print 
-jobs. A printer can also be rejecting new print jobs while it finishes 
-those that have been queued. This is useful for when you must perform 
-maintenance on the printer and will not have it available to users for 
-a long period of time. </P>
+<P>As noted above, a printer can be stopped but accepting new print
+ jobs. A printer can also be rejecting new print jobs while it finishes
+ those that have been queued. This is useful for when you must perform
+ maintenance on the printer and will not have it available to users for
+ a long period of time.</P>
 <H2><A NAME="4_4">Managing Printers from the Web</A></H2>
-<P>The Web interface is located at: </P>
+<P>The Web interface is located at:</P>
 <UL>
 <PRE>
 <A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
 </PRE>
 </UL>
-<P>From there you can perform all printer management tasks with a few 
-simple mouse clicks. </P>
+<P>From there you can perform all printer management tasks with a few
+ simple mouse clicks.</P>
 <H1 ALIGN="RIGHT"><A NAME="PRINTER_CLASSES">4 - Printer Classes</A></H1>
-<P>This chapter describes what printer classes are and how to manage 
-them. </P>
+<P>This chapter describes what printer classes are and how to manage
+ them.</P>
 <H2><A NAME="5_1">The Basics</A></H2>
-<P>CUPS provides collections of printers called <I>printer classes</I>. 
-Jobs sent to a class are forwarded to the first available printer in 
-the class. Classes can themselves be members of other classes, so it is 
-possible for you to define very large, distributed printer classes for 
-high-availability printing. </P>
-<P>CUPS also supports <I>implicit classes</I>. Implicit classes work 
-just like printer classes, but they are created automatically based 
-upon the available printers and classes on the network. This allows you 
-to setup multiple print servers with identical printer configurations 
-and have the client machines send their print jobs to the first 
-available server. If one or more servers go down, the jobs are 
-automatically redirected to the servers that are running, providing 
-fail-safe printing. </P>
+<P>CUPS provides collections of printers called<I> printer classes</I>.
+ Jobs sent to a class are forwarded to the first available printer in
+ the class. Classes can themselves be members of other classes, so it is
+ possible for you to define very large, distributed printer classes for
+ high-availability printing.</P>
+<P>CUPS also supports<I> implicit classes</I>. Implicit classes work
+ just like printer classes, but they are created automatically based
+ upon the available printers and classes on the network. This allows you
+ to setup multiple print servers with identical printer configurations
+ and have the client machines send their print jobs to the first
+ available server. If one or more servers go down, the jobs are
+ automatically redirected to the servers that are running, providing
+ fail-safe printing.</P>
 <H2><A NAME="5_2">Managing Printer Classes from the Command-Line</A></H2>
 <P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> and <CODE>
--c</CODE> options to add a printer to a class: </P>
+-c</CODE> options to add a printer to a class:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -p <I>printer</I> -c <I>class</I> ENTER</B>
 </PRE>
 </UL>
-<P>The <I>class</I> is created automatically if it doesn't exist. To 
-remove a printer from a class use the <CODE>-r</CODE> option: </P>
+<P>The<I> class</I> is created automatically if it doesn't exist. To
+ remove a printer from a class use the <CODE>-r</CODE> option:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -p <I>printer</I> -r <I>class</I> ENTER</B>
 </PRE>
 </UL>
-<P>To remove the entire class just use the <CODE>-x</CODE> option: </P>
+<P>To remove the entire class just use the <CODE>-x</CODE> option:</P>
 <UL>
 <PRE>
 <B>/usr/sbin/lpadmin -x <I>class</I> ENTER</B>
 </PRE>
 </UL>
 <H2><A NAME="5_3">Managing Printer Classes from the Web Interface</A></H2>
-<P>The Web interface is located at: </P>
+<P>The Web interface is located at:</P>
 <UL>
 <PRE>
 <A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
 </PRE>
 </UL>
-<P>The <VAR>Add Class</VAR> and <VAR>Modify Class</VAR> interfaces 
-provide a list of available printers; click on the printers of interest 
-to add them to the class. </P>
+<P>The<VAR> Add Class</VAR> and<VAR> Modify Class</VAR> interfaces
+ provide a list of available printers; click on the printers of interest
+ to add them to the class.</P>
 <H2><A NAME="5_4">Implicit Classes</A></H2>
-<P>A noted earlier, implicit classes are created automatically from the 
-available network printers and classes. To disable this functionality, 
-set the <A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
- directive to <CODE>Off</CODE> in the <CODE>cupsd.conf</CODE> file. You 
-will find more information on doing this in <A HREF="#PRINTING_MANAGEMENT">
-Chapter 6, &quot;Printing System Management&quot;</A>. </P>
+<P>A noted earlier, implicit classes are created automatically from the
+ available network printers and classes. To disable this functionality,
+ set the<A HREF="#ImplicitClasses"> <CODE>ImplicitClasses</CODE></A>
+ directive to <CODE>Off</CODE> in the <CODE>cupsd.conf</CODE> file. You
+ will find more information on doing this in<A HREF="#PRINTING_MANAGEMENT">
+ Chapter 6, &quot;Printing System Management&quot;</A>.</P>
 <H1 ALIGN="RIGHT"><A NAME="CLIENT_SETUP">5 - Client Setup</A></H1>
-<P>This chapter discusses several ways to configure CUPS clients for 
-printing. </P>
+<P>This chapter discusses several ways to configure CUPS clients for
+ printing.</P>
 <H2><A NAME="6_1">The Basics</A></H2>
-<P>A client is any machine that sends print jobs to another machine for 
-final printing. Clients can also be servers if they communicate 
-directly with any printers of their own. </P>
-<P>CUPS supports several methods of configuring client machines: </P>
+<P>A client is any machine that sends print jobs to another machine for
+ final printing. Clients can also be servers if they communicate
+ directly with any printers of their own.</P>
+<P>CUPS supports several methods of configuring client machines:</P>
 <UL>
 <LI><A HREF="#CLIENT_MANUAL">Manual configuration of print queues.</A></LI>
 <LI><A HREF="#CLIENT_SERVER">Specifying a single server for printing.</A>
@@ -916,116 +943,116 @@ directly with any printers of their own. </P>
 <LI><A HREF="#CLIENT_POLL">Specifying multiple servers for printing.</A></LI>
 </UL>
 <H3><A NAME="CLIENT_MANUAL">Manual Configuration of Print Queues</A></H3>
-<P>The most tedious method of configuring client machines is to 
-configure each remote queue by hand using the <CODE>lpadmin</CODE>
- command: </P>
+<P>The most tedious method of configuring client machines is to
+ configure each remote queue by hand using the <CODE>lpadmin</CODE>
+ command:</P>
 <UL>
 <PRE>
 <B>lpadmin -p <I>printer</I> -E -v ipp://<I>server</I>/printers/<I>printer</I> ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>printer</CODE> name is the name of the printer on the 
-server machine. The <CODE>server</CODE> name is the hostname or IP 
-address of the server machine. Repeat the <CODE>lpadmin</CODE> command 
-for each remote printer you wish to use. </P>
+<P>The <CODE>printer</CODE> name is the name of the printer on the
+ server machine. The <CODE>server</CODE> name is the hostname or IP
+ address of the server machine. Repeat the <CODE>lpadmin</CODE> command
+ for each remote printer you wish to use.</P>
 <H3><A NAME="CLIENT_SERVER">Specifying a Single Server for Printing</A></H3>
-<P>CUPS can be configured to run without a local spooler and send all 
-jobs to a single server. However, if that server goes down then all 
-printing will be disabled. Use this configuration only as absolutely 
-needed. </P>
-<P>The default server is normally &quot;localhost&quot;. To override the default 
-server create a file named <VAR>/etc/cups/client.conf</VAR> and add a 
-line reading: </P>
+<P>CUPS can be configured to run without a local spooler and send all
+ jobs to a single server. However, if that server goes down then all
+ printing will be disabled. Use this configuration only as absolutely
+ needed.</P>
+<P>The default server is normally &quot;localhost&quot;. To override the default
+ server create a file named<VAR> /etc/cups/client.conf</VAR> and add a
+ line reading:</P>
 <UL>
 <PRE>
 ServerName <I>server</I>
 </PRE>
 </UL>
-<P>to the file. The <VAR>server</VAR> name can be the hostname or IP 
-address of the default server. </P>
-<P>The default server can also be customized on a per-user basis. To 
-set a user-specific server create a file named <VAR>~/.cupsrc</VAR> and 
-add a line reading: </P>
+<P>to the file. The<VAR> server</VAR> name can be the hostname or IP
+ address of the default server.</P>
+<P>The default server can also be customized on a per-user basis. To set
+ a user-specific server create a file named<VAR> ~/.cupsrc</VAR> and add
+ a line reading:</P>
 <UL>
 <PRE>
 ServerName <I>server</I>
 </PRE>
 </UL>
-<P>to the file. The <VAR>server</VAR> name can be the hostname or IP 
-address of the default server. </P>
+<P>to the file. The<VAR> server</VAR> name can be the hostname or IP
+ address of the default server.</P>
 <H3><A NAME="CLIENT_AUTO">Automatic Configuration of Print Queues</A></H3>
-<P>CUPS supports automatic client configuration of printers on the same 
-subnet. To configure printers on the same subnet, <I>do nothing</I>. 
-Each client should see the available printers within 30 seconds 
-automatically. The printer and class lists are updated automatically as 
-printers and servers are added or removed. </P>
-<P>If you want to see printers on other subnets as well, use the <A HREF="#BrowsePoll">
-<CODE>BrowsePoll</CODE></A> directive as described next. </P>
+<P>CUPS supports automatic client configuration of printers on the same
+ subnet. To configure printers on the same subnet,<I> do nothing</I>.
+ Each client should see the available printers within 30 seconds
+ automatically. The printer and class lists are updated automatically as
+ printers and servers are added or removed.</P>
+<P>If you want to see printers on other subnets as well, use the<A HREF="#BrowsePoll">
+ <CODE>BrowsePoll</CODE></A> directive as described next.</P>
 <H3><A NAME="CLIENT_POLL">Specifying Multiple Servers for Printing</A></H3>
-<P>If you have CUPS servers on different subnets, then you should 
-configure CUPS to poll those servers. Polling provides the benefits of 
-automatic configuration without significant configuration on the 
-clients, and multiple clients on the same subnet can share the same 
-configuration information. </P>
-<P>Polling is enabled by specifying one or more <A HREF="#BrowsePoll"><CODE>
-BrowsePoll</CODE></A> directives in the <VAR>/etc/cups/cupsd.conf</VAR>
- file. For information on making these changes, see <A HREF="PRINTING_MANAGEMENT">
-Chapter 6, &quot;Printing System Management&quot;</A>. </P>
-<H1 ALIGN="RIGHT"><A NAME="PRINTING_MANAGEMENT">6 - Printing System 
-Management</A></H1>
-<P>This chapter shows how you can configure the CUPS server. </P>
+<P>If you have CUPS servers on different subnets, then you should
+ configure CUPS to poll those servers. Polling provides the benefits of
+ automatic configuration without significant configuration on the
+ clients, and multiple clients on the same subnet can share the same
+ configuration information.</P>
+<P>Polling is enabled by specifying one or more<A HREF="#BrowsePoll"> <CODE>
+BrowsePoll</CODE></A> directives in the<VAR> /etc/cups/cupsd.conf</VAR>
+ file. For information on making these changes, see<A HREF="PRINTING_MANAGEMENT">
+ Chapter 6, &quot;Printing System Management&quot;</A>.</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_MANAGEMENT">6 - Printing System
+ Management</A></H1>
+<P>This chapter shows how you can configure the CUPS server.</P>
 <H2><A NAME="7_1">The Basics</A></H2>
-<P>Several text files are used to configure CUPS. All of the server 
-configuration files are located in the <VAR>/etc/cups</VAR> directory: </P>
+<P>Several text files are used to configure CUPS. All of the server
+ configuration files are located in the<VAR> /etc/cups</VAR> directory:</P>
 <UL>
 <DL>
 <!-- NEED 1in -->
 
-<DT>classes.conf </DT>
-<DD>This file contains information on each printer class.  Normally you 
-manipulate this file using the <CODE> lpadmin</CODE> command or the Web 
-interface.
-<BR>&nbsp; 
+<DT>classes.conf</DT>
+<DD>This file contains information on each printer class. Normally you
+ manipulate this file using the <CODE>lpadmin</CODE> command or the Web
+ interface.
+<BR>&nbsp;
 <!-- NEED 1in -->
 </DD>
-<DT>client.conf </DT>
-<DD>This file provides the default server name for client  machines. 
-See <A HREF="#CLIENT_SETUP">Chapter 5, &quot;Client  Setup&quot;</A> for more 
-information.
-<BR>&nbsp; 
+<DT>client.conf</DT>
+<DD>This file provides the default server name for client machines. See<A
+HREF="#CLIENT_SETUP"> Chapter 5, &quot;Client Setup&quot;</A> for more
+ information.
+<BR>&nbsp;
 <!-- NEED 1in -->
 </DD>
-<DT>cupsd.conf </DT>
-<DD>This file controls how the CUPS server  (<VAR>/usr/sbin/cupsd</VAR>
-) operates and is normally edited by  hand.
-<BR>&nbsp; 
+<DT>cupsd.conf</DT>
+<DD>This file controls how the CUPS server (<VAR>/usr/sbin/cupsd</VAR>)
+ operates and is normally edited by hand.
+<BR>&nbsp;
 <!-- NEED 1in -->
 </DD>
-<DT>mime.convs </DT>
-<DD>This file contains a list of standard file conversion filters  and 
-their costs. You normally do not edit this file.
-<BR>&nbsp; 
+<DT>mime.convs</DT>
+<DD>This file contains a list of standard file conversion filters and
+ their costs. You normally do not edit this file.
+<BR>&nbsp;
 <!-- NEED 1in -->
 </DD>
-<DT>mime.types </DT>
-<DD>This file contains a list of standard file formats and how to 
+<DT>mime.types</DT>
+<DD>This file contains a list of standard file formats and how to
  recognize them. You normally do not edit this file.
-<BR>&nbsp; 
+<BR>&nbsp;
 <!-- NEED 1in -->
 </DD>
-<DT>printers.conf </DT>
-<DD>This file contains information on each printer. Normally  you 
-manipulate this file using the <CODE>lpadmin</CODE> command  or the Web 
-Interface.
-<BR>&nbsp; </DD>
+<DT>printers.conf</DT>
+<DD>This file contains information on each printer. Normally you
+ manipulate this file using the <CODE>lpadmin</CODE> command or the Web
+ Interface.
+<BR>&nbsp;</DD>
 </DL>
 </UL>
 <H2><A NAME="RESTARTING">Restarting the CUPS Server</A></H2>
-<P>Once you have made a change to a configuration file you need to 
-restart the CUPS server by sending it a <CODE>HUP</CODE> signal or 
-using the supplied initialization script. The CUPS distributions 
-install the script in the <VAR>init.d</VAR> directory with the name <VAR>
-cups</VAR>. The location varies based upon the operating system: </P>
+<P>Once you have made a change to a configuration file you need to
+ restart the CUPS server by sending it a <CODE>HUP</CODE> signal or
+ using the supplied initialization script. The CUPS distributions
+ install the script in the<VAR> init.d</VAR> directory with the name<VAR>
+ cups</VAR>. The location varies based upon the operating system:</P>
 <UL>
 <PRE>
 <B>/etc/rc.d/init.d/cups restart ENTER</B>
@@ -1034,17 +1061,17 @@ cups</VAR>. The location varies based upon the operating system: </P>
 </PRE>
 </UL>
 <H2><A NAME="7_3">Changing the Server Configuration</A></H2>
-<P>The <VAR>/etc/cups/cupsd.conf</VAR> file contains configuration <I>
-directives</I> that control how the server functions. Each directive is 
-listed on a line by itself followed by its value. Comments are 
-introduced using the number sign (&quot;#&quot;) character at the beginning of a 
-line. Since the server configuration file consists of plain text, you 
-can use your favorite text editor to make changes to it. 
+<P>The<VAR> /etc/cups/cupsd.conf</VAR> file contains configuration<I>
+ directives</I> that control how the server functions. Each directive is
+ listed on a line by itself followed by its value. Comments are
+ introduced using the number sign (&quot;#&quot;) character at the beginning of a
+ line. Since the server configuration file consists of plain text, you
+ can use your favorite text editor to make changes to it.
 <!-- NEED 4in -->
 </P>
 <H2><A NAME="7_4">Server Directives</A></H2>
-<P>The <VAR>cupsd.conf</VAR> file contains many directives that 
-determine how the server operates: </P>
+<P>The<VAR> cupsd.conf</VAR> file contains many directives that
+ determine how the server operates:</P>
 <UL>
 <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
 <TR><TD VALIGN="TOP">
@@ -1061,24 +1088,29 @@ determine how the server operates: </P>
 <LI><A HREF="#BrowseOrder"><CODE>BrowseOrder</CODE></A></LI>
 <LI><A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A></LI>
 <LI><A HREF="#BrowsePort"><CODE>BrowsePort</CODE></A></LI>
+<LI><A HREF="#BrowseProtocols"><CODE>BrowseProtocols</CODE></A></LI>
 <LI><A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A></LI>
 <LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A></LI>
 <LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A></LI>
 <LI><A HREF="#Browsing"><CODE>Browsing</CODE></A></LI>
 <LI><A HREF="#Classification"><CODE>Classification</CODE></A></LI>
+<LI><A HREF="#ClassifyOverride"><CODE>ClassifyOverride</CODE></A></LI>
 <LI><A HREF="#DataDir"><CODE>DataDir</CODE></A></LI>
 <LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A></LI>
 <LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A></LI>
 <LI><A HREF="#Deny"><CODE>Deny</CODE></A></LI>
 <LI><A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A></LI>
-</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp; </TD><TD VALIGN="TOP">
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
 <LI><A HREF="#Encryption"><CODE>Encryption</CODE></A></LI>
 <LI><A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A></LI>
 <LI><A HREF="#FilterLimit"><CODE>FilterLimit</CODE></A></LI>
 <LI><A HREF="#FontPath"><CODE>FontPath</CODE></A></LI>
 <LI><A HREF="#Group"><CODE>Group</CODE></A></LI>
+<LI><A HREF="#HideImplicitMembers"><CODE>HideImplicitMembers</CODE></A></LI>
 <LI><A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A></LI>
 <LI><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A></LI>
+<LI><A HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A></LI>
+<LI><A HREF="#Include"><CODE>Include</CODE></A></LI>
 <LI><A HREF="#KeepAliveTimeout"><CODE>KeepAliveTimeout</CODE></A></LI>
 <LI><A HREF="#KeepAlive"><CODE>KeepAlive</CODE></A></LI>
 <LI><A HREF="#Limit"><CODE>Limit</CODE></A></LI>
@@ -1094,8 +1126,8 @@ determine how the server operates: </P>
 <LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A></LI>
 <LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A></LI>
 <LI><A HREF="#Order"><CODE>Order</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
 <LI><A HREF="#PageLog"><CODE>PageLog</CODE></A></LI>
-</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp; </TD><TD VALIGN="TOP">
 <LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
 <LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A></LI>
 <LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A></LI>
@@ -1135,16 +1167,16 @@ AccessLog syslog
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>AccessLog</CODE> directive sets the name of the access log 
-file. If the filename is not absolute then it is assumed to be relative 
-to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The 
-access log file is stored in &quot;common log format&quot; and can be used by any 
-web access reporting tool to generate a report on CUPS server activity. </P>
+<P>The <CODE>AccessLog</CODE> directive sets the name of the access log
+ file. If the filename is not absolute then it is assumed to be relative
+ to the<A HREF="#ServerRoot"> <CODE>ServerRoot</CODE></A> directory. The
+ access log file is stored in &quot;common log format&quot; and can be used by any
+ web access reporting tool to generate a report on CUPS server activity.</P>
 <P>The server name can be included in the filename by using <CODE>%s</CODE>
- in the name. </P>
-<P>The special name &quot;syslog&quot; can be used to send the access information 
-to the system log instead of a plain file. </P>
-<P>The default access log file is <VAR>/var/log/cups/access_log</VAR>. 
+ in the name.</P>
+<P>The special name &quot;syslog&quot; can be used to send the access information
+ to the system log instead of a plain file.</P>
+<P>The default access log file is<VAR> /var/log/cups/access_log</VAR>.
 <!-- NEED 6in -->
 </P>
 <H3><A NAME="Allow">Allow</A></H3>
@@ -1166,11 +1198,11 @@ Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Allow</CODE> directive specifies a hostname, IP address, 
-or network that is allowed access to the server. <CODE> Allow</CODE>
- directives are cummulative, so multiple <CODE>Allow</CODE> directives 
-can be used to allow access for multiple hosts or networks.  The <CODE>
-/mm</CODE> notation specifies a CIDR netmask: 
+<P>The <CODE>Allow</CODE> directive specifies a hostname, IP address, or
+ network that is allowed access to the server. <CODE>Allow</CODE>
+ directives are cummulative, so multiple <CODE>Allow</CODE> directives
+ can be used to allow access for multiple hosts or networks. The <CODE>
+/mm</CODE> notation specifies a CIDR netmask:
 <CENTER>
 <TABLE BORDER="1">
 <TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
@@ -1186,8 +1218,8 @@ mm</TH><TH WIDTH="20%">netmask</TH></TR>
 </TABLE>
 </CENTER>
 </P>
-<P>The <CODE>Allow</CODE> directive must appear inside a <A HREF="#Location">
-<CODE>Location</CODE></A> directive. 
+<P>The <CODE>Allow</CODE> directive must appear inside a<A HREF="#Location">
+ <CODE>Location</CODE></A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="AuthClass">AuthClass</A></H3>
@@ -1202,22 +1234,21 @@ AuthClass Group
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>AuthClass</CODE> directive defines what level of 
-authentication is required: </P>
-<UL>
-<LI><CODE>Anonymous</CODE> - No authentication should be performed 
- (default.) </LI>
-<LI><CODE>User</CODE> - A valid username and password is required. </LI>
-<LI><CODE>System</CODE> - A valid username and password is  required, 
-and the username must belong to the &quot;sys&quot; group; this  can be changed 
-using the <A HREF="#SystemGroup"><CODE> SystemGroup</CODE></A>
- directive. </LI>
-<LI><CODE>Group</CODE> - A valid username and password is  required, 
-and the username must belong to the group named by  the <CODE>
-AuthGroupName</CODE> directive. </LI>
-</UL>
-<P>The <CODE>AuthClass</CODE> directive must appear inside a <A HREF="#Location">
-<CODE>Location</CODE></A> directive. 
+<P>The <CODE>AuthClass</CODE> directive defines what level of
+ authentication is required:</P>
+<UL>
+<LI><CODE>Anonymous</CODE> - No authentication should be performed
+ (default.)</LI>
+<LI><CODE>User</CODE> - A valid username and password is required.</LI>
+<LI><CODE>System</CODE> - A valid username and password is required, and
+ the username must belong to the &quot;sys&quot; group; this can be changed using
+ the<A HREF="#SystemGroup"> <CODE>SystemGroup</CODE></A> directive.</LI>
+<LI><CODE>Group</CODE> - A valid username and password is required, and
+ the username must belong to the group named by the <CODE>AuthGroupName</CODE>
+ directive.</LI>
+</UL>
+<P>The <CODE>AuthClass</CODE> directive must appear inside a<A HREF="#Location">
+ <CODE>Location</CODE></A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="AuthGroupName">AuthGroupName</A></H3>
@@ -1231,9 +1262,9 @@ AuthGroupName lp
 </UL>
 <H4>Description</H4>
 <P>The <CODE>AuthGroupName</CODE> directive sets the group to use for <CODE>
-Group</CODE> authentication. </P>
-<P>The <CODE>AuthGroupName</CODE> directive must appear inside a <A HREF="#Location">
-<CODE>Location</CODE></A> directive. 
+Group</CODE> authentication.</P>
+<P>The <CODE>AuthGroupName</CODE> directive must appear inside a<A HREF="#Location">
+ <CODE>Location</CODE></A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="AuthType">AuthType</A></H3>
@@ -1244,24 +1275,27 @@ Group</CODE> authentication. </P>
 AuthType None
 AuthType Basic
 AuthType Digest
+AuthType BasicDigest
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>AuthType</CODE> directive defines the type of 
-authentication to perform: </P>
-<UL>
-<LI><CODE>None</CODE> - No authentication should be performed 
- (default.) </LI>
-<LI><CODE>Basic</CODE> - Basic authentication should be  performed 
-using the UNIX password and group files. </LI>
-<LI><CODE>Digest</CODE> - Digest authentication should be  performed 
-using the <VAR>/etc/cups/passwd.md5</VAR> file. </LI>
-</UL>
-<P>When using <CODE>Basic</CODE> or <CODE>Digest</CODE> authentication, 
-clients connecting through the <CODE>localhost</CODE> interface can 
-also authenticate using <A HREF="#CERTIFICATES">certificates</A>. </P>
-<P>The <CODE>AuthType</CODE> directive must appear inside a <A HREF="#Location">
-<CODE>Location</CODE></A> directive. 
+<P>The <CODE>AuthType</CODE> directive defines the type of
+ authentication to perform:</P>
+<UL>
+<LI><CODE>None</CODE> - No authentication should be performed (default.)</LI>
+<LI><CODE>Basic</CODE> - Basic authentication should be performed using
+ the UNIX password and group files.</LI>
+<LI><CODE>Digest</CODE> - Digest authentication should be performed
+ using the<VAR> /etc/cups/passwd.md5</VAR> file.</LI>
+<LI><CODE>BasicDigest</CODE> - Basic authentication should be performed
+ using the<VAR> /etc/cups/passwd.md5</VAR> file.</LI>
+</UL>
+<P>When using <CODE>Basic</CODE>, <CODE>Digest</CODE>, or <CODE>
+BasicDigest</CODE> authentication, clients connecting through the <CODE>
+localhost</CODE> interface can also authenticate using<A HREF="#CERTIFICATES">
+ certificates</A>.</P>
+<P>The <CODE>AuthType</CODE> directive must appear inside a<A HREF="#Location">
+ <CODE>Location</CODE></A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="AutoPurgeJobs">AutoPurgeJobs</A></H3>
@@ -1274,10 +1308,10 @@ AutoPurgeJobs No
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>AutoPurgeJobs</CODE> directive specifies whether or not to 
-purge completed jobs once they are no longer required for quotas. This 
-option has no effect if quotas are not enabled. The default setting is <CODE>
-No</CODE>. 
+<P>The <CODE>AutoPurgeJobs</CODE> directive specifies whether or not to
+ purge completed jobs once they are no longer required for quotas. This
+ option has no effect if quotas are not enabled. The default setting is <CODE>
+No</CODE>.
 <!-- NEED 5in -->
 </P>
 <H3><A NAME="BrowseAddress">BrowseAddress</A></H3>
@@ -1291,18 +1325,18 @@ BrowseAddress host.domain.com:631
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseAddress</CODE> directive specifies an address to 
-send browsing information to. Multiple <CODE>BrowseAddress</CODE>
- directives can be specified to send browsing information to different 
-networks or systems. </P>
-<P>The default address is <CODE>255.255.255.255:631</CODE> which will 
-broadcast the information to all networks the server is connected to. 
+<P>The <CODE>BrowseAddress</CODE> directive specifies an address to send
+ browsing information to. Multiple <CODE>BrowseAddress</CODE> directives
+ can be specified to send browsing information to different networks or
+ systems.</P>
+<P>The default address is <CODE>255.255.255.255:631</CODE> which will
+ broadcast the information to all networks the server is connected to.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>If you are using HP-UX 10.20 and a subnet that is not 24,  16, or 8 
-bits, printer browsing (and in fact all broadcast  reception) will not 
-work. This problem appears to be fixed in  HP-UX 11.0. </P>
+<P>If you are using HP-UX 10.20 and a subnet that is not 24, 16, or 8
+ bits, printer browsing (and in fact all broadcast reception) will not
+ work. This problem appears to be fixed in HP-UX 11.0.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
@@ -1323,15 +1357,15 @@ BrowseAllow from *.domain.com
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseAllow</CODE> directive specifies a system or network 
-to accept browse packets from. The default is to accept browse packets 
-from all hosts. </P>
-<P>Host and domain name matching require that you enable the <A HREF="#HostNameLookups">
-<CODE>HostNameLookups</CODE></A> directive. </P>
-<P>IP address matching supports exact matches, partial addresses that 
-match networks using netmasks of 255.0.0.0, 255.255.0.0, and 
-255.255.255.0, or network addresses using the specified netmask or bit 
-count. 
+<P>The <CODE>BrowseAllow</CODE> directive specifies a system or network
+ to accept browse packets from. The default is to accept browse packets
+ from all hosts.</P>
+<P>Host and domain name matching require that you enable the<A HREF="#HostNameLookups">
+ <CODE>HostNameLookups</CODE></A> directive.</P>
+<P>IP address matching supports exact matches, partial addresses that
+ match networks using netmasks of 255.0.0.0, 255.255.0.0, and
+ 255.255.255.0, or network addresses using the specified netmask or bit
+ count.
 <!-- NEED 4in -->
 </P>
 <H3><A NAME="BrowseDeny">BrowseDeny</A></H3>
@@ -1348,15 +1382,15 @@ BrowseDeny from *.domain.com
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseDeny</CODE> directive specifies a system or network 
-to reject browse packets from. The default is to deny browse packets 
-from no hosts. </P>
-<P>Host and domain name matching require that you enable the <A HREF="#HostNameLookups">
-<CODE>HostNameLookups</CODE></A> directive. </P>
-<P>IP address matching supports exact matches, partial addresses that 
-match networks using netmasks of 255.0.0.0, 255.255.0.0, and 
-255.255.255.0, or network addresses using the specified netmask or bit 
-count. 
+<P>The <CODE>BrowseDeny</CODE> directive specifies a system or network
+ to reject browse packets from. The default is to deny browse packets
+ from no hosts.</P>
+<P>Host and domain name matching require that you enable the<A HREF="#HostNameLookups">
+ <CODE>HostNameLookups</CODE></A> directive.</P>
+<P>IP address matching supports exact matches, partial addresses that
+ match networks using netmasks of 255.0.0.0, 255.255.0.0, and
+ 255.255.255.0, or network addresses using the specified netmask or bit
+ count.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="BrowseOrder">BrowseOrder</A></H3>
@@ -1369,13 +1403,13 @@ BrowseOrder deny,allow
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseOrder</CODE> directive specifies the order of 
-allow/deny processing. The default order is <CODE>deny,allow</CODE>: </P>
+<P>The <CODE>BrowseOrder</CODE> directive specifies the order of
+ allow/deny processing. The default order is <CODE>deny,allow</CODE>:</P>
 <UL>
-<LI><CODE>allow,deny</CODE> - Browse packets are accepted unless 
- specifically denied. </LI>
-<LI><CODE>deny,allow</CODE> - Browse packets are rejected unless 
- specifically allowed. </LI>
+<LI><CODE>allow,deny</CODE> - Browse packets are accepted unless
+ specifically denied.</LI>
+<LI><CODE>deny,allow</CODE> - Browse packets are rejected unless
+ specifically allowed.</LI>
 </UL>
 
 <!-- NEED 3in -->
@@ -1389,14 +1423,14 @@ BrowseInterval 30
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseInterval</CODE> directive specifies the maximum 
-amount of time between browsing updates. Specifying a value of 0 
-seconds disables outgoing browse updates but allows a server to receive 
-printer information from other hosts. </P>
-<P>The <CODE>BrowseInterval</CODE> value should always be less than the <A
-HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A> value. Otherwise 
-printers and classes will disappear from client systems between 
-updates. 
+<P>The <CODE>BrowseInterval</CODE> directive specifies the maximum
+ amount of time between browsing updates. Specifying a value of 0
+ seconds disables outgoing browse updates but allows a server to receive
+ printer information from other hosts.</P>
+<P>The <CODE>BrowseInterval</CODE> value should always be less than the<A
+HREF="#BrowseTimeout"> <CODE>BrowseTimeout</CODE></A> value. Otherwise
+ printers and classes will disappear from client systems between
+ updates.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="BrowsePoll">BrowsePoll</A></H3>
@@ -1409,12 +1443,12 @@ BrowsePoll host.domain.com:631
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowsePoll</CODE> directive polls a server for available 
-printers once every <A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE>
-</A> seconds. Multiple <CODE>BrowsePoll</CODE> directives can be 
-specified to poll multiple servers. </P>
-<P>If <CODE>BrowseInterval</CODE> is set to 0 then the server is polled 
-once every 30 seconds. 
+<P>The <CODE>BrowsePoll</CODE> directive polls a server for available
+ printers once every<A HREF="#BrowseInterval"> <CODE>BrowseInterval</CODE>
+</A> seconds. Multiple <CODE>BrowsePoll</CODE> directives can be
+ specified to poll multiple servers.</P>
+<P>If <CODE>BrowseInterval</CODE> is set to 0 then the server is polled
+ once every 30 seconds.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="BrowsePort">BrowsePort</A></H3>
@@ -1427,13 +1461,42 @@ BrowsePort 9999
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowsePort</CODE> directive specifies the UDP port number 
-used for browse packets. The default port number is 631. 
+<P>The <CODE>BrowsePort</CODE> directive specifies the UDP port number
+ used for browse packets. The default port number is 631.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>You must set the <CODE>BrowsePort</CODE> to the same value on all of
+ the systems that you want to see.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseProtocols">BrowseProtocols</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseProtocols CUPS
+BrowseProtocols SLP
+BrowseProtocols CUPS SLP
+BrowseProtocols all
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseProtocols</CODE> directive specifies the protocols to
+ use when collecting and distributing shared printers on the local
+ network. The default protocol is <CODE>CUPS</CODE>, which is a
+ broadcast-based protocol.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>You must set the <CODE>BrowsePort</CODE> to the same value  on all 
-of the systems that you want to see. </P>
+<P>When using the <CODE>SLP</CODE> protocol, you must have at least one
+ Directory Agent (DA) server on your network. Otherwise the CUPS
+ scheduler (<CODE>cupsd</CODE>) will not respond to client requests for
+ several seconds while polling the network.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
@@ -1453,20 +1516,20 @@ BrowseRelay host.domain.com 192.0.2.255
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseRelay</CODE> directive specifies source and 
-destination addresses for relaying browsing information from one host 
-or network to another. Multiple <CODE>BrowseRelay</CODE> directives can 
-be specified as needed. </P>
-<P><CODE>BrowseRelay</CODE> is typically used on systems that bridge 
-multiple subnets using one or more network interfaces. It can also be 
-used to relay printer information from polled servers with the line: </P>
+<P>The <CODE>BrowseRelay</CODE> directive specifies source and
+ destination addresses for relaying browsing information from one host
+ or network to another. Multiple <CODE>BrowseRelay</CODE> directives can
+ be specified as needed.</P>
+<P><CODE>BrowseRelay</CODE> is typically used on systems that bridge
+ multiple subnets using one or more network interfaces. It can also be
+ used to relay printer information from polled servers with the line:</P>
 <UL>
 <PRE>
 BrowseRelay 127.0.0.1 255.255.255.255
 </PRE>
 </UL>
-<P>This effectively provides access to printers on a WAN for all 
-clients on the LAN(s). 
+<P>This effectively provides access to printers on a WAN for all clients
+ on the LAN(s).
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="BrowseShortNames">BrowseShortNames</A></H3>
@@ -1479,12 +1542,12 @@ BrowseShortNames No
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseShortNames</CODE> directive specifies whether or not 
-short names are used for remote printers when possible. Short names are 
-just the remote printer name, without the server (&quot;printer&quot;). If more 
-than one remote printer is detected with the same name, the printers 
-will have long names (&quot;printer@server1&quot;, &quot;printer@server2&quot;.) </P>
-<P>The default value for this option is <CODE>Yes</CODE>. 
+<P>The <CODE>BrowseShortNames</CODE> directive specifies whether or not
+ short names are used for remote printers when possible. Short names are
+ just the remote printer name, without the server (&quot;printer&quot;). If more
+ than one remote printer is detected with the same name, the printers
+ will have long names (&quot;printer@server1&quot;, &quot;printer@server2&quot;.)</P>
+<P>The default value for this option is <CODE>Yes</CODE>.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="BrowseTimeout">BrowseTimeout</A></H3>
@@ -1497,14 +1560,14 @@ BrowseTimeout 60
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>BrowseTimeout</CODE> directive sets the timeout for 
-printer or class information that is received in browse packets. Once a 
-printer or class times out it is removed from the list of available 
-destinations. </P>
-<P>The <CODE>BrowseTimeout</CODE> value should always be greater than 
-the <A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> value. 
-Otherwise printers and classes will disappear from client systems 
-between updates. 
+<P>The <CODE>BrowseTimeout</CODE> directive sets the timeout for printer
+ or class information that is received in browse packets. Once a printer
+ or class times out it is removed from the list of available
+ destinations.</P>
+<P>The <CODE>BrowseTimeout</CODE> value should always be greater than
+ the<A HREF="#BrowseInterval"> <CODE>BrowseInterval</CODE></A> value.
+ Otherwise printers and classes will disappear from client systems
+ between updates.
 <!-- NEED 4in -->
 </P>
 <H3><A NAME="Browsing">Browsing</A></H3>
@@ -1517,14 +1580,14 @@ Browsing Off
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Browsing</CODE> directive controls whether or not network 
-printer browsing is enabled. The default setting is <CODE>On</CODE>. 
+<P>The <CODE>Browsing</CODE> directive controls whether or not network
+ printer browsing is enabled. The default setting is <CODE>On</CODE>.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>If you are using HP-UX 10.20 and a subnet that is not 24,  16, or 8 
-bits, printer browsing (and in fact all broadcast  reception) will not 
-work. This problem appears to be fixed in  HP-UX 11.0. </P>
+<P>If you are using HP-UX 10.20 and a subnet that is not 24, 16, or 8
+ bits, printer browsing (and in fact all broadcast reception) will not
+ work. This problem appears to be fixed in HP-UX 11.0.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
@@ -1545,11 +1608,31 @@ Classification unclassified
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Classification</CODE> directive sets the classification 
-level on the server. When this option is set, at least one of the 
-banner pages is forced to the classification level, and the 
-classification is placed on each page of output. The default is no 
-classification level. 
+<P>The <CODE>Classification</CODE> directive sets the classification
+ level on the server. When this option is set, at least one of the
+ banner pages is forced to the classification level, and the
+ classification is placed on each page of output. The default is no
+ classification level.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassifyOverride">ClassifyOverride</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ClassifyOverride Yes
+ClassifyOverride No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ClassifyOverride</CODE> directive specifies whether users
+ can override the default classification level on the server. When the
+ server classification is set, users can change the classification using
+ the <CODE>job-sheets</CODE> option and can choose to only print one
+ security banner before or after the job. If the <CODE>job-sheets</CODE>
+ option is set to <CODE>none</CODE> then the server default
+ classification is used.</P>
+<P>The default is to not allow classification overrides.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="DataDir">DataDir</A></H3>
@@ -1561,8 +1644,8 @@ DataDir /usr/share/cups
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>DataDir</CODE> directive sets the directory to use for 
-data files. 
+<P>The <CODE>DataDir</CODE> directive sets the directory to use for data
+ files.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="DefaultCharset">DefaultCharset</A></H3>
@@ -1576,10 +1659,10 @@ DefaultCharset windows-1251
 </PRE>
 </UL>
 <H4>Description</H4>
-<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>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.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="DefaultLanguage">DefaultLanguage</A></H3>
@@ -1595,10 +1678,10 @@ DefaultLanguage it
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>DefaultLanguage</CODE> directive specifies the default 
-language to use for client connections. Setting the default language 
-also sets the default character set if a language localization file 
-exists for it.  The default language is &quot;en&quot; for English. 
+<P>The <CODE>DefaultLanguage</CODE> directive specifies the default
+ language to use for client connections. Setting the default language
+ also sets the default character set if a language localization file
+ exists for it. The default language is &quot;en&quot; for English.
 <!-- NEED 5in -->
 </P>
 <H3><A NAME="Deny">Deny</A></H3>
@@ -1620,11 +1703,11 @@ Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Deny</CODE> directive specifies a hostname, IP address, or 
-network that is allowed access to the server. <CODE>Deny</CODE>
- directives are cummulative, so multiple <CODE>Deny</CODE> directives 
-can be used to allow access for multiple hosts or networks. The <CODE>
-/mm</CODE> notation specifies a CIDR netmask: 
+<P>The <CODE>Deny</CODE> directive specifies a hostname, IP address, or
+ network that is allowed access to the server. <CODE>Deny</CODE>
+ directives are cummulative, so multiple <CODE>Deny</CODE> directives
+ can be used to allow access for multiple hosts or networks. The <CODE>
+/mm</CODE> notation specifies a CIDR netmask:
 <CENTER>
 <TABLE BORDER="1">
 <TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
@@ -1640,8 +1723,8 @@ mm</TH><TH WIDTH="20%">netmask</TH></TR>
 </TABLE>
 </CENTER>
 </P>
-<P>The <CODE>Deny</CODE> directive must appear inside a <A HREF="#Location">
-<CODE>Location</CODE></A> directive. 
+<P>The <CODE>Deny</CODE> directive must appear inside a<A HREF="#Location">
+ <CODE>Location</CODE></A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="DocumentRoot">DocumentRoot</A></H3>
@@ -1654,16 +1737,16 @@ DocumentRoot /foo/bar/doc/cups
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>DocumentRoot</CODE> directive specifies the location of 
-web content for the HTTP server in CUPS. If an absolute path is not 
-specified then it is assumed to be relative to the <A HREF="#ServerRoot">
-<CODE>ServerRoot</CODE></A> directory. The default directory is <VAR>
-/usr/share/doc/cups</VAR>. </P>
-<P>Documents are first looked up in a sub-directory for the primary 
-language requested by the client (e.g. <VAR>/usr/share/doc/cups/fr/...</VAR>
-) and then directly under the <CODE>DocumentRoot</CODE> directory (e.g. <VAR>
-/usr/share/doc/cups/...</VAR>), so it is possible to localize the web 
-content by providing subdirectories for each language needed. 
+<P>The <CODE>DocumentRoot</CODE> directive specifies the location of web
+ content for the HTTP server in CUPS. If an absolute path is not
+ specified then it is assumed to be relative to the<A HREF="#ServerRoot">
+ <CODE>ServerRoot</CODE></A> directory. The default directory is<VAR>
+ /usr/share/doc/cups</VAR>.</P>
+<P>Documents are first looked up in a sub-directory for the primary
+ language requested by the client (e.g.<VAR> /usr/share/doc/cups/fr/...</VAR>
+) and then directly under the <CODE>DocumentRoot</CODE> directory (e.g.<VAR>
+ /usr/share/doc/cups/...</VAR>), so it is possible to localize the web
+ content by providing subdirectories for each language needed.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Encryption">Encryption</A></H3>
@@ -1678,10 +1761,10 @@ Encryption Always
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Encryption</CODE> directive must appear instead a <A HREF="#Location">
-<CODE>Location</CODE></A> section and specifies the encryption settings 
-for that location. The default setting is <CODE>IfRequested</CODE> for 
-all locations. 
+<P>The <CODE>Encryption</CODE> directive must appear instead a<A HREF="#Location">
+ <CODE>Location</CODE></A> section and specifies the encryption settings
+ for that location. The default setting is <CODE>IfRequested</CODE> for
+ all locations.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ErrorLog">ErrorLog</A></H3>
@@ -1695,14 +1778,14 @@ ErrorLog syslog
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ErrorLog</CODE> directive sets the name of the error log 
-file. If the filename is not absolute then it is assumed to be relative 
-to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The 
-default error log file is <VAR>/var/log/cups/error_log</VAR>. </P>
+<P>The <CODE>ErrorLog</CODE> directive sets the name of the error log
+ file. If the filename is not absolute then it is assumed to be relative
+ to the<A HREF="#ServerRoot"> <CODE>ServerRoot</CODE></A> directory. The
+ default error log file is<VAR> /var/log/cups/error_log</VAR>.</P>
 <P>The server name can be included in the filename by using <CODE>%s</CODE>
- in the name. </P>
-<P>The special name &quot;syslog&quot; can be used to send the error information 
-to the system log instead of a plain file. 
+ in the name.</P>
+<P>The special name &quot;syslog&quot; can be used to send the error information
+ to the system log instead of a plain file.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="FilterLimit">FilterLimit</A></H3>
@@ -1716,15 +1799,15 @@ FilterLimit 1000
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>FilterLimit</CODE> directive sets the maximum cost of all 
-running job filters. It can be used to limit the number of filter 
-programs that are run on a server to minimize disk, memory, and CPU 
-resource problems. A limit of 0 disables filter limiting. </P>
-<P>An average print to a non-PostScript printer needs a filter limit of 
-about 200. A PostScript printer needs about half that (100). Setting 
-the limit below these thresholds will effectively limit the scheduler 
-to printing a single job at any time. </P>
-<P>The default limit is 0. 
+<P>The <CODE>FilterLimit</CODE> directive sets the maximum cost of all
+ running job filters. It can be used to limit the number of filter
+ programs that are run on a server to minimize disk, memory, and CPU
+ resource problems. A limit of 0 disables filter limiting.</P>
+<P>An average print to a non-PostScript printer needs a filter limit of
+ about 200. A PostScript printer needs about half that (100). Setting
+ the limit below these thresholds will effectively limit the scheduler
+ to printing a single job at any time.</P>
+<P>The default limit is 0.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="FontPath">FontPath</A></H3>
@@ -1737,9 +1820,9 @@ FontPath /usr/share/cups/fonts:/foo/bar/fonts
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>FontPath</CODE> directive specifies the font path to use 
-when searching for fonts. The default font path is <CODE>
-/usr/share/cups/fonts</CODE>. 
+<P>The <CODE>FontPath</CODE> directive specifies the font path to use
+ when searching for fonts. The default font path is <CODE>
+/usr/share/cups/fonts</CODE>.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Group">Group</A></H3>
@@ -1753,11 +1836,28 @@ Group root
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Group</CODE> directive specifies the UNIX group that 
-filter and CGI programs run as. The default group is <CODE>sys</CODE>, <CODE>
-system</CODE>, or <CODE>root</CODE> depending on the operating system. 
+<P>The <CODE>Group</CODE> directive specifies the UNIX group that filter
+ and CGI programs run as. The default group is <CODE>sys</CODE>, <CODE>
+system</CODE>, or <CODE>root</CODE> depending on the operating system.
 <!-- NEED 3in -->
 </P>
+<H3><A NAME="HideImplicitMembers">HideImplicitMembers</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+HideImplicitMembers Yes
+HideImplicitMembers No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>HideImplicitMembers</CODE> directive controls whether the
+ individual printers in an implicit class are shown to the user. The
+ default is <CODE>No</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> must be
+ enabled for this directive to have any effect.</P>
+
+<!-- NEED 3in -->
 <H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
 <HR>
 <H4>Examples</H4>
@@ -1769,15 +1869,15 @@ HostNameLookups Double
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>HostNameLookups</CODE> directive controls whether or not 
-CUPS looks up the hostname for connecting clients. The <CODE>Double</CODE>
- setting causes CUPS to verify that the hostname resolved from the 
-address matches one of the addresses returned for that hostname. <CODE>
-Double</CODE> lookups also prevent clients with unregistered addresses 
-from connecting to your server.  The default is <CODE>Off</CODE> to 
-avoid the potential server performance problems with hostname lookups. 
-Set this option to <CODE>On</CODE> or <CODE>Double</CODE> only if 
-absolutely required. 
+<P>The <CODE>HostNameLookups</CODE> directive controls whether or not
+ CUPS looks up the hostname for connecting clients. The <CODE>Double</CODE>
+ setting causes CUPS to verify that the hostname resolved from the
+ address matches one of the addresses returned for that hostname. <CODE>
+Double</CODE> lookups also prevent clients with unregistered addresses
+ from connecting to your server. The default is <CODE>Off</CODE> to
+ avoid the potential server performance problems with hostname lookups.
+ Set this option to <CODE>On</CODE> or <CODE>Double</CODE> only if
+ absolutely required.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ImplicitClasses">ImplicitClasses</A></H3>
@@ -1790,13 +1890,46 @@ ImplicitClasses Off
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ImplicitClasses</CODE> directive controls whether implicit 
-classes are created based upon the available network printers and 
-classes. The default setting is <CODE>On</CODE> but is automatically 
-turned <CODE>Off</CODE> if <A HREF="#Browsing"><CODE>Browsing</CODE></A>
- is turned <CODE>Off</CODE>. 
+<P>The <CODE>ImplicitClasses</CODE> directive controls whether implicit
+ classes are created based upon the available network printers and
+ classes. The default setting is <CODE>On</CODE> but is automatically
+ turned <CODE>Off</CODE> if<A HREF="#Browsing"> <CODE>Browsing</CODE></A>
+ is turned <CODE>Off</CODE>.
 <!-- NEED 3in -->
 </P>
+<H3><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ImplicitAnyClasses On
+ImplicitAnyClasses Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ImplicitAnyClasses</CODE> directive controls whether
+ implicit classes for local and remote printers are created with the
+ name <CODE>AnyPrinter</CODE>. The default setting is <CODE>Off</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> must be
+ enabled for this directive to have any effect.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="Include">Include</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Include filename
+Include /foo/bar/filename
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Include</CODE> directive includes the named file in the <CODE>
+cupsd.conf</CODE> file. If no leading path is provided, the file is
+ assumed to be relative to the<A HREF="#ServerRoot"> <CODE>ServerRoot</CODE>
+</A> directory.</P>
+
+<!-- NEED 3in -->
 <H3><A NAME="KeepAlive">KeepAlive</A></H3>
 <HR>
 <H4>Examples</H4>
@@ -1807,12 +1940,12 @@ KeepAlive Off
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>KeepAlive</CODE> directive controls whether or not to 
-support persistent HTTP connections. The default is <CODE>On</CODE>. </P>
-<P>HTTP/1.1 clients automatically support persistent connections, while 
-HTTP/1.0 clients must specifically request them using the <CODE>
-Keep-Alive</CODE> attribute in the <CODE>Connection:</CODE> field of 
-each request. 
+<P>The <CODE>KeepAlive</CODE> directive controls whether or not to
+ support persistent HTTP connections. The default is <CODE>On</CODE>.</P>
+<P>HTTP/1.1 clients automatically support persistent connections, while
+ HTTP/1.0 clients must specifically request them using the <CODE>
+Keep-Alive</CODE> attribute in the <CODE>Connection:</CODE> field of
+ each request.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="KeepAliveTimeout">KeepAliveTimeout</A></H3>
@@ -1825,9 +1958,9 @@ KeepAliveTimeout 30
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>KeepAliveTimeout</CODE> directive controls how long a 
-persistent HTTP connection will remain open after the last request. The 
-default is 60 seconds. 
+<P>The <CODE>KeepAliveTimeout</CODE> directive controls how long a
+ persistent HTTP connection will remain open after the last request. The
+ default is 60 seconds.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Limit">Limit</A></H3>
@@ -1845,13 +1978,13 @@ default is 60 seconds.
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Limit</CODE> directive groups access control directives 
-for specific types of HTTP requests and must appear inside a <A HREF="#Location">
-<CODE>Location</CODE></A> section. Access can be limited for individual 
-request types (<CODE>DELETE</CODE>, <CODE>GET</CODE>, <CODE>HEAD</CODE>
+<P>The <CODE>Limit</CODE> directive groups access control directives for
+ specific types of HTTP requests and must appear inside a<A HREF="#Location">
+ <CODE>Location</CODE></A> section. Access can be limited for individual
+ request types (<CODE>DELETE</CODE>, <CODE>GET</CODE>, <CODE>HEAD</CODE>
 , <CODE>OPTIONS</CODE>, <CODE>POST</CODE>, <CODE>PUT</CODE>, and <CODE>
-TRACE</CODE>) or for all request types (<CODE>ALL</CODE>). The request 
-type names are case-sensitive for compatibility with Apache. 
+TRACE</CODE>) or for all request types (<CODE>ALL</CODE>). The request
+ type names are case-sensitive for compatibility with Apache.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="LimitExcept">LimitExcept</A></H3>
@@ -1865,12 +1998,12 @@ type names are case-sensitive for compatibility with Apache.
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>LimitExcept</CODE> directive groups access control 
-directives for specific types of HTTP requests and must appear inside a <A
-HREF="#Location"><CODE>Location</CODE></A> section. Unlike the <A HREF="#Limit">
-<CODE>Limit</CODE></A> directive, <CODE>LimitExcept</CODE> restricts 
-access for all requests <I>except</I> those listed on the <CODE>
-LimitExcept</CODE> line. 
+<P>The <CODE>LimitExcept</CODE> directive groups access control
+ directives for specific types of HTTP requests and must appear inside a<A
+HREF="#Location"> <CODE>Location</CODE></A> section. Unlike the<A HREF="#Limit">
+ <CODE>Limit</CODE></A> directive, <CODE>LimitExcept</CODE> restricts
+ access for all requests<I> except</I> those listed on the <CODE>
+LimitExcept</CODE> line.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="LimitRequestBody">LimitRequestBody</A></H3>
@@ -1884,11 +2017,11 @@ LimitRequestBody 0
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>LimitRequestBody</CODE> directive controls the maximum 
-size of print files, IPP requests, and HTML form data in HTTP POST 
-requests. The default limit is 0 which disables the limit check. </P>
-<P>Also see the identical <A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE>
-</A> directive. 
+<P>The <CODE>LimitRequestBody</CODE> directive controls the maximum size
+ of print files, IPP requests, and HTML form data in HTTP POST requests.
+ The default limit is 0 which disables the limit check.</P>
+<P>Also see the identical<A HREF="#MaxRequestSize"> <CODE>MaxRequestSize</CODE>
+</A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Listen">Listen</A></H3>
@@ -1901,12 +2034,12 @@ Listen 192.0.2.1:631
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Listen</CODE> directive specifies a network address and 
-port to listen for connections. Multiple <CODE>Listen</CODE> directives 
-can be provided to listen on multiple addresses. </P>
-<P>The <CODE>Listen</CODE> directive is similar to the <A HREF="#Port"><CODE>
-Port</CODE></A> directive but allows you to restrict access to specific 
-interfaces or networks. 
+<P>The <CODE>Listen</CODE> directive specifies a network address and
+ port to listen for connections. Multiple <CODE>Listen</CODE> directives
+ can be provided to listen on multiple addresses.</P>
+<P>The <CODE>Listen</CODE> directive is similar to the<A HREF="#Port"> <CODE>
+Port</CODE></A> directive but allows you to restrict access to specific
+ interfaces or networks.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Location">Location</A></H3>
@@ -1928,10 +2061,10 @@ interfaces or networks.
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Location</CODE> directive specifies access control and 
-authentication options for the specified HTTP resource or path. More 
-information can be found later in this chapter in <A HREF="#PRINTING_SECURITY">
-&quot;Printing System Security&quot;</A>. 
+<P>The <CODE>Location</CODE> directive specifies access control and
+ authentication options for the specified HTTP resource or path. More
+ information can be found later in this chapter in<A HREF="#PRINTING_SECURITY">
+ &quot;Printing System Security&quot;</A>.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="LogLevel">LogLevel</A></H3>
@@ -1952,23 +2085,23 @@ LogLevel debug2
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>LogLevel</CODE> directive specifies the level of logging 
-for the <A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A> file. The 
-following values are recognized (each level logs everything under the 
-preceding levels): </P>
-<UL>
-<LI><CODE>none</CODE> - Log nothing. </LI>
-<LI><CODE>emerg</CODE> - Log emergency conditions that prevent the 
- server from running. </LI>
-<LI><CODE>alert</CODE> - Log alerts that must be handled immediately. </LI>
-<LI><CODE>crit</CODE> - Log critical errors that don't prevent  the 
-server from running. </LI>
-<LI><CODE>error</CODE> - Log general errors. </LI>
-<LI><CODE>warn</CODE> - Log errors and warnings. </LI>
-<LI><CODE>notice</CODE> - Log temporary error conditions. </LI>
-<LI><CODE>info</CODE> - Log all requests and state changes (default). </LI>
-<LI><CODE>debug</CODE> - Log basic debugging information. </LI>
-<LI><CODE>debug2</CODE> - Log all debugging information. </LI>
+<P>The <CODE>LogLevel</CODE> directive specifies the level of logging
+ for the<A HREF="#ErrorLog"> <CODE>ErrorLog</CODE></A> file. The
+ following values are recognized (each level logs everything under the
+ preceding levels):</P>
+<UL>
+<LI><CODE>none</CODE> - Log nothing.</LI>
+<LI><CODE>emerg</CODE> - Log emergency conditions that prevent the
+ server from running.</LI>
+<LI><CODE>alert</CODE> - Log alerts that must be handled immediately.</LI>
+<LI><CODE>crit</CODE> - Log critical errors that don't prevent the
+ server from running.</LI>
+<LI><CODE>error</CODE> - Log general errors.</LI>
+<LI><CODE>warn</CODE> - Log errors and warnings.</LI>
+<LI><CODE>notice</CODE> - Log temporary error conditions.</LI>
+<LI><CODE>info</CODE> - Log all requests and state changes (default).</LI>
+<LI><CODE>debug</CODE> - Log basic debugging information.</LI>
+<LI><CODE>debug2</CODE> - Log all debugging information.</LI>
 </UL>
 
 <!-- NEED 3in -->
@@ -1982,16 +2115,16 @@ MaxClients 1024
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>MaxClients</CODE> directive controls the maximum number of 
-simultaneous clients that will be allowed by the server. The default is 
-100 clients. 
+<P>The <CODE>MaxClients</CODE> directive controls the maximum number of
+ simultaneous clients that will be allowed by the server. The default is
+ 100 clients.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>Since each print job requires a file descriptor for the  status 
-pipe, the CUPS server internally limits the <CODE> MaxClients</CODE>
- value to 1/3 of the available file descriptors  to avoid possible 
-problems when printing large numbers of jobs. </P>
+<P>Since each print job requires a file descriptor for the status pipe,
+ the CUPS server internally limits the <CODE>MaxClients</CODE> value to
+ 1/3 of the available file descriptors to avoid possible problems when
+ printing large numbers of jobs.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
@@ -2009,13 +2142,13 @@ MaxJobs 0
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>MaxJobs</CODE> directive controls the maximum number of 
-jobs that are kept in memory. Once the number of jobs reaches the 
-limit, the oldest completed job is automatically purged from the system 
-to make room for the new one. If all of the known jobs are still 
-pending or active then the new job will be rejected. </P>
-<P>Setting the maximum to 0 disables this functionality. The default 
-setting is 0. 
+<P>The <CODE>MaxJobs</CODE> directive controls the maximum number of
+ jobs that are kept in memory. Once the number of jobs reaches the
+ limit, the oldest completed job is automatically purged from the system
+ to make room for the new one. If all of the known jobs are still
+ pending or active then the new job will be rejected.</P>
+<P>Setting the maximum to 0 disables this functionality. The default
+ setting is 0.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="MaxJobsPerPrinter">MaxJobsPerPrinter</A></H3>
@@ -2029,12 +2162,12 @@ MaxJobsPerPrinter 0
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>MaxJobsPerPrinter</CODE> directive controls the maximum 
-number of active jobs that are allowed for each printer or class. Once 
-a printer or class reaches the limit, new jobs will be rejected until 
-one of the active jobs is completed, stopped, aborted, or cancelled. </P>
-<P>Setting the maximum to 0 disables this functionality. The default 
-setting is 0. 
+<P>The <CODE>MaxJobsPerPrinter</CODE> directive controls the maximum
+ number of active jobs that are allowed for each printer or class. Once
+ a printer or class reaches the limit, new jobs will be rejected until
+ one of the active jobs is completed, stopped, aborted, or cancelled.</P>
+<P>Setting the maximum to 0 disables this functionality. The default
+ setting is 0.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="MaxJobsPerUser">MaxJobsPerUser</A></H3>
@@ -2048,12 +2181,12 @@ MaxJobsPerUser 0
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>MaxJobsPerUser</CODE> directive controls the maximum 
-number of active jobs that are allowed for each user. Once a user 
-reaches the limit, new jobs will be rejected until one of the active 
-jobs is completed, stopped, aborted, or cancelled. </P>
-<P>Setting the maximum to 0 disables this functionality. The default 
-setting is 0. 
+<P>The <CODE>MaxJobsPerUser</CODE> directive controls the maximum number
+ of active jobs that are allowed for each user. Once a user reaches the
+ limit, new jobs will be rejected until one of the active jobs is
+ completed, stopped, aborted, or cancelled.</P>
+<P>Setting the maximum to 0 disables this functionality. The default
+ setting is 0.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="MaxLogSize">MaxLogSize</A></H3>
@@ -2067,11 +2200,11 @@ MaxLogSize 0
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>MaxLogSize</CODE> directive controls the maximum size of 
-each log file. Once a log file reaches or exceeds the maximum size it 
-is closed and renamed to <VAR>filename.O</VAR>. This allows you to 
-rotate the logs automatically. The default size is 1048576 bytes (1MB). </P>
-<P>Setting the maximum size to 0 disables log rotation. 
+<P>The <CODE>MaxLogSize</CODE> directive controls the maximum size of
+ each log file. Once a log file reaches or exceeds the maximum size it
+ is closed and renamed to<VAR> filename.O</VAR>. This allows you to
+ rotate the logs automatically. The default size is 1048576 bytes (1MB).</P>
+<P>Setting the maximum size to 0 disables log rotation.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="MaxRequestSize">MaxRequestSize</A></H3>
@@ -2085,11 +2218,11 @@ MaxRequestSize 0
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>MaxRequestSize</CODE> directive controls the maximum size 
-of print files, IPP requests, and HTML form data in HTTP POST requests. 
-The default limit is 0 which disables the limit check. </P>
-<P>Also see the identical <A HREF="#LimitRequestBody"><CODE>
-LimitRequestBody</CODE></A> directive. 
+<P>The <CODE>MaxRequestSize</CODE> directive controls the maximum size
+ of print files, IPP requests, and HTML form data in HTTP POST requests.
+ The default limit is 0 which disables the limit check.</P>
+<P>Also see the identical<A HREF="#LimitRequestBody"> <CODE>
+LimitRequestBody</CODE></A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Order">Order</A></H3>
@@ -2102,16 +2235,16 @@ Order Deny,Allow
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Order</CODE> directive defines the default access control. 
-The following values are supported: </P>
+<P>The <CODE>Order</CODE> directive defines the default access control.
+ The following values are supported:</P>
 <UL>
-<LI><CODE>Allow,Deny</CODE> - Allow requests from all  systems <I>except</I>
- for those listed in a <CODE>Deny</CODE> directive. </LI>
-<LI><CODE>Deny,Allow</CODE> - Allow requests only from  those listed in 
-an <CODE>Allow</CODE> directive. </LI>
+<LI><CODE>Allow,Deny</CODE> - Allow requests from all systems<I> except</I>
+ for those listed in a <CODE>Deny</CODE> directive.</LI>
+<LI><CODE>Deny,Allow</CODE> - Allow requests only from those listed in
+ an <CODE>Allow</CODE> directive.</LI>
 </UL>
-<P>The <CODE>Order</CODE> directive must appear inside a <A HREF="#Location">
-<CODE>Location</CODE></A> directive. 
+<P>The <CODE>Order</CODE> directive must appear inside a<A HREF="#Location">
+ <CODE>Location</CODE></A> directive.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="PageLog">PageLog</A></H3>
@@ -2125,14 +2258,14 @@ PageLog syslog
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>PageLog</CODE> directive sets the name of the page log 
-file. If the filename is not absolute then it is assumed to be relative 
-to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The 
-default page log file is <VAR>/var/log/cups/page_log</VAR>. </P>
+<P>The <CODE>PageLog</CODE> directive sets the name of the page log
+ file. If the filename is not absolute then it is assumed to be relative
+ to the<A HREF="#ServerRoot"> <CODE>ServerRoot</CODE></A> directory. The
+ default page log file is<VAR> /var/log/cups/page_log</VAR>.</P>
 <P>The server name can be included in the filename by using <CODE>%s</CODE>
- in the name. </P>
-<P>The special name &quot;syslog&quot; can be used to send the page information 
-to the system log instead of a plain file. 
+ in the name.</P>
+<P>The special name &quot;syslog&quot; can be used to send the page information to
+ the system log instead of a plain file.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Port">Port</A></H3>
@@ -2145,9 +2278,9 @@ Port 80
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Port</CODE> directive specifies a port to listen on. 
-Multiple <CODE>Port</CODE> lines can be specified to listen on multiple 
-ports. The default port is 631. 
+<P>The <CODE>Port</CODE> directive specifies a port to listen on.
+ Multiple <CODE>Port</CODE> lines can be specified to listen on multiple
+ ports. The default port is 631.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="PreserveJobHistory">PreserveJobHistory</A></H3>
@@ -2160,13 +2293,13 @@ PreserveJobHistory Off
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>PreserveJobHistory</CODE> directive controls whether the 
-history of completed, cancelled, or aborted print jobs is stored on 
-disk. </P>
-<P>A value of <CODE>On</CODE> (the default) preserves job information 
-until the administrator purges it with the <CODE>cancel</CODE> command. </P>
-<P>A value of <CODE>Off</CODE> removes the job information as soon as 
-each job is completed, cancelled, or aborted. 
+<P>The <CODE>PreserveJobHistory</CODE> directive controls whether the
+ history of completed, cancelled, or aborted print jobs is stored on
+ disk.</P>
+<P>A value of <CODE>On</CODE> (the default) preserves job information
+ until the administrator purges it with the <CODE>cancel</CODE> command.</P>
+<P>A value of <CODE>Off</CODE> removes the job information as soon as
+ each job is completed, cancelled, or aborted.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="PreserveJobFiles">PreserveJobFiles</A></H3>
@@ -2179,14 +2312,14 @@ PreserveJobFiles Off
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>PreserveJobFiles</CODE> directive controls whether the 
-document files of completed, cancelled, or aborted print jobs are 
-stored on disk. </P>
-<P>A value of <CODE>On</CODE> preserves job files until the 
-administrator purges them with the <CODE>cancel</CODE> command. Jobs 
-can be restarted (and reprinted) as desired until they are purged. </P>
-<P>A value of <CODE>Off</CODE> (the default) removes the job files as 
-soon as each job is completed, cancelled, or aborted. 
+<P>The <CODE>PreserveJobFiles</CODE> directive controls whether the
+ document files of completed, cancelled, or aborted print jobs are
+ stored on disk.</P>
+<P>A value of <CODE>On</CODE> preserves job files until the
+ administrator purges them with the <CODE>cancel</CODE> command. Jobs
+ can be restarted (and reprinted) as desired until they are purged.</P>
+<P>A value of <CODE>Off</CODE> (the default) removes the job files as
+ soon as each job is completed, cancelled, or aborted.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Printcap">Printcap</A></H3>
@@ -2200,15 +2333,15 @@ Printcap /etc/printers.conf
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Printcap</CODE> directive controls whether or not a 
-printcap file is automatically generated and updated with a list of 
-available printers. If specified with no value, then no printcap file 
-will be generated. The default is to generate a file named <VAR>
-/etc/printcap</VAR>. </P>
-<P>When a filename is specified (e.g. <VAR>/etc/printcap</VAR>), the 
-printcap file is written whenever a printer is added or removed. The 
-printcap file can then be used by applications that are hardcoded to 
-look at the printcap file for the available printers. 
+<P>The <CODE>Printcap</CODE> directive controls whether or not a
+ printcap file is automatically generated and updated with a list of
+ available printers. If specified with no value, then no printcap file
+ will be generated. The default is to generate a file named<VAR>
+ /etc/printcap</VAR>.</P>
+<P>When a filename is specified (e.g.<VAR> /etc/printcap</VAR>), the
+ printcap file is written whenever a printer is added or removed. The
+ printcap file can then be used by applications that are hardcoded to
+ look at the printcap file for the available printers.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="Printcap">PrintcapFormat</A></H3>
@@ -2221,8 +2354,8 @@ PrintcapFormat Solaris
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>PrintcapFormat</CODE> directive controls the output format 
-of the printcap file. The default is to generate a BSD printcap file. 
+<P>The <CODE>PrintcapFormat</CODE> directive controls the output format
+ of the printcap file. The default is to generate a BSD printcap file.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="RemoteRoot">RemoteRoot</A></H3>
@@ -2235,10 +2368,10 @@ RemoteRoot root
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>RemoteRoot</CODE> directive sets the username for 
-unauthenticated root requests from remote hosts. The default username 
-is <VAR>remroot</VAR>. Setting <CODE>RemoteRoot</CODE> to <VAR>root</VAR>
- effectively disables this security mechanism. 
+<P>The <CODE>RemoteRoot</CODE> directive sets the username for
+ unauthenticated root requests from remote hosts. The default username
+ is<VAR> remroot</VAR>. Setting <CODE>RemoteRoot</CODE> to<VAR> root</VAR>
+ effectively disables this security mechanism.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="RequestRoot">RequestRoot</A></H3>
@@ -2251,11 +2384,11 @@ RequestRoot /foo/bar/spool/cups
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>RequestRoot</CODE> directive sets the directory for 
-incoming IPP requests and HTML forms. If an absolute path is not 
-provided then it is assumed to be relative to the <A HREF="#ServerRoot"><CODE>
-ServerRoot</CODE></A> directory. The default request directory is <VAR>
-/var/spool/cups</VAR>. 
+<P>The <CODE>RequestRoot</CODE> directive sets the directory for
+ incoming IPP requests and HTML forms. If an absolute path is not
+ provided then it is assumed to be relative to the<A HREF="#ServerRoot">
+ <CODE>ServerRoot</CODE></A> directory. The default request directory is<VAR>
+ /var/spool/cups</VAR>.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="RIPCache">RIPCache</A></H3>
@@ -2269,11 +2402,11 @@ RIPCache 2048k
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>RIPCache</CODE> directive sets the size of the memory 
-cache used by Raster Image Processor (&quot;RIP&quot;) filters such as <CODE>
-imagetoraster</CODE> and <CODE>pstoraster</CODE>. The size can be 
-suffixed with a &quot;k&quot; for kilobytes, &quot;m&quot; for megabytes, or &quot;g&quot; for 
-gigabytes. The default cache size is &quot;8m&quot;, or 8 megabytes. 
+<P>The <CODE>RIPCache</CODE> directive sets the size of the memory cache
+ used by Raster Image Processor (&quot;RIP&quot;) filters such as <CODE>
+imagetoraster</CODE> and <CODE>pstoraster</CODE>. The size can be
+ suffixed with a &quot;k&quot; for kilobytes, &quot;m&quot; for megabytes, or &quot;g&quot; for
+ gigabytes. The default cache size is &quot;8m&quot;, or 8 megabytes.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="RunAsUser">RunAsUser</A></H3>
@@ -2286,16 +2419,16 @@ RunAsUser No
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>RunAsUser</CODE> directive controls whether the scheduler 
-runs as the unpriviledged user account (usually <CODE>lp</CODE>). The 
-default is <CODE>No</CODE> which leaves the scheduler running as the <CODE>
-root</CODE> user. </P>
-<P><B>Note:</B> Running as a non-priviledged user may prevent LPD and 
-locally connected printers from working due to permission problems. The <CODE>
-lpd</CODE> backend will automatically use a non-priviledged mode that 
-is not 100% compliant with RFC 1179. The <CODE>parallel</CODE>, <CODE>
-serial</CODE>, and <CODE>usb</CODE> backends will need write access to 
-the corresponding device files. 
+<P>The <CODE>RunAsUser</CODE> directive controls whether the scheduler
+ runs as the unpriviledged user account (usually <CODE>lp</CODE>). The
+ default is <CODE>No</CODE> which leaves the scheduler running as the <CODE>
+root</CODE> user.</P>
+<P><B>Note:</B> Running as a non-priviledged user may prevent LPD and
+ locally connected printers from working due to permission problems. The
+ <CODE>lpd</CODE> backend will automatically use a non-priviledged mode
+ that is not 100% compliant with RFC 1179. The <CODE>parallel</CODE>, <CODE>
+serial</CODE>, and <CODE>usb</CODE> backends will need write access to
+ the corresponding device files.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ServerAdmin">ServerAdmin</A></H3>
@@ -2308,10 +2441,10 @@ ServerAdmin root@foo.bar.com
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ServerAdmin</CODE> directive identifies the email address 
-for the administrator on the system. By default the administrator email 
-address is <CODE>root@server</CODE>, where <CODE>server</CODE> is the 
-server name. 
+<P>The <CODE>ServerAdmin</CODE> directive identifies the email address
+ for the administrator on the system. By default the administrator email
+ address is <CODE>root@server</CODE>, where <CODE>server</CODE> is the
+ server name.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ServerBin">ServerBin</A></H3>
@@ -2324,11 +2457,11 @@ ServerBin /foo/bar/lib/cups
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ServerBin</CODE> directive sets the directory for 
-server-run executables. If an absolute path is not provided then it is 
-assumed to be relative to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE>
-</A> directory. The default executable directory is <VAR>/usr/lib/cups</VAR>
- or <VAR>/usr/lib32/cups</VAR> (IRIX 6.5). 
+<P>The <CODE>ServerBin</CODE> directive sets the directory for
+ server-run executables. If an absolute path is not provided then it is
+ assumed to be relative to the<A HREF="#ServerRoot"> <CODE>ServerRoot</CODE>
+</A> directory. The default executable directory is<VAR> /usr/lib/cups</VAR>
+ or<VAR> /usr/lib32/cups</VAR> (IRIX 6.5).
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ServerCertificate">ServerCertificate</A></H3>
@@ -2340,12 +2473,12 @@ ServerCertificate /etc/cups/ssl/server.crt
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ServerCertificate</CODE> directive specifies the location 
-of the SSL certificate file used by the server when negotiating 
-encrypted connections. The certificate must not be encrypted (password 
-protected) since the scheduler normally runs in the background and will 
-be unable to ask for a password. The default certificate file is <VAR>
-/etc/cups/ssl/server.crt</VAR>. 
+<P>The <CODE>ServerCertificate</CODE> directive specifies the location
+ of the SSL certificate file used by the server when negotiating
+ encrypted connections. The certificate must not be encrypted (password
+ protected) since the scheduler normally runs in the background and will
+ be unable to ask for a password. The default certificate file is<VAR>
+ /etc/cups/ssl/server.crt</VAR>.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ServerKey">ServerKey</A></H3>
@@ -2357,10 +2490,10 @@ ServerKey /etc/cups/ssl/server.key
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ServerKey</CODE> directive specifies the location of the 
-SSL private key file used by the server when negotiating encrypted 
-connections. The default key file is <VAR>/etc/cups/ssl/server.crt</VAR>
-. 
+<P>The <CODE>ServerKey</CODE> directive specifies the location of the
+ SSL private key file used by the server when negotiating encrypted
+ connections. The default key file is<VAR> /etc/cups/ssl/server.crt</VAR>
+.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ServerName"></A>ServerName</H3>
@@ -2373,8 +2506,8 @@ ServerName myserver.domain.com
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ServerName</CODE> directive specifies the hostname that is 
-reported to clients. By default the server name is the hostname. 
+<P>The <CODE>ServerName</CODE> directive specifies the hostname that is
+ reported to clients. By default the server name is the hostname.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="ServerRoot">ServerRoot</A></H3>
@@ -2387,10 +2520,10 @@ ServerRoot /foo/bar/cups
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>ServerRoot</CODE> directive specifies the absolute path to 
-the server configuration and state files. It is also used to resolve 
-relative paths in the <VAR>cupsd.conf</VAR> file. The default server 
-directory is <VAR>/etc/cups</VAR>. 
+<P>The <CODE>ServerRoot</CODE> directive specifies the absolute path to
+ the server configuration and state files. It is also used to resolve
+ relative paths in the<VAR> cupsd.conf</VAR> file. The default server
+ directory is<VAR> /etc/cups</VAR>.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="SSLListen">SSLListen</A></H3>
@@ -2403,12 +2536,12 @@ SSLListen 192.0.2.1:443
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>SSLListen</CODE> directive specifies a network address and 
-port to listen for secure connections. Multiple <CODE>SSLListen</CODE>
- directives can be provided to listen on multiple addresses. </P>
-<P>The <CODE>SSLListen</CODE> directive is similar to the <A HREF="#SSLPort">
-<CODE>SSLPort</CODE></A> directive but allows you to restrict access to 
-specific interfaces or networks. 
+<P>The <CODE>SSLListen</CODE> directive specifies a network address and
+ port to listen for secure connections. Multiple <CODE>SSLListen</CODE>
+ directives can be provided to listen on multiple addresses.</P>
+<P>The <CODE>SSLListen</CODE> directive is similar to the<A HREF="#SSLPort">
+ <CODE>SSLPort</CODE></A> directive but allows you to restrict access to
+ specific interfaces or networks.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="SSLPort">SSLPort</A></H3>
@@ -2420,9 +2553,9 @@ SSLPort 443
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>SSLPort</CODE> directive specifies a port to listen on for 
-secure connections. Multiple <CODE>SSLPort</CODE> lines can be 
-specified to listen on multiple ports. 
+<P>The <CODE>SSLPort</CODE> directive specifies a port to listen on for
+ secure connections. Multiple <CODE>SSLPort</CODE> lines can be
+ specified to listen on multiple ports.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="SystemGroup">SystemGroup</A></H3>
@@ -2436,10 +2569,10 @@ SystemGroup root
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>SystemGroup</CODE> directive specifies the system 
-administration group for <CODE>System</CODE> authentication. More 
-information can be found later in this chapter in <A HREF="#PRINTING_SECURITY">
-&quot;Printing System Security&quot;</A>. 
+<P>The <CODE>SystemGroup</CODE> directive specifies the system
+ administration group for <CODE>System</CODE> authentication. More
+ information can be found later in this chapter in<A HREF="#PRINTING_SECURITY">
+ &quot;Printing System Security&quot;</A>.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="TempDir">TempDir</A></H3>
@@ -2452,13 +2585,13 @@ TempDir /foo/bar/tmp
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>TempDir</CODE> directive specifies an absolute path for 
-the directory to use for temporary files. The default directory is <VAR>
-/var/tmp</VAR>. </P>
-<P>Temporary directories must be world-writable and should have the 
-&quot;sticky&quot; permission bit enabled so that other users cannot delete 
-filter temporary files. The following commands will create an 
-appropriate temporary directory called <VAR>/foo/bar/tmp</VAR>: </P>
+<P>The <CODE>TempDir</CODE> directive specifies an absolute path for the
+ directory to use for temporary files. The default directory is<VAR>
+ /var/tmp</VAR>.</P>
+<P>Temporary directories must be world-writable and should have the
+ &quot;sticky&quot; permission bit enabled so that other users cannot delete
+ filter temporary files. The following commands will create an
+ appropriate temporary directory called<VAR> /foo/bar/tmp</VAR>:</P>
 <UL>
 <PRE>
 <B>mkdir /foo/bar/tmp ENTER</B>
@@ -2477,9 +2610,9 @@ Timeout 90
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>Timeout</CODE> directive controls the amount of time to 
-wait before an active HTTP or IPP request times out. The default 
-timeout is 300 seconds. 
+<P>The <CODE>Timeout</CODE> directive controls the amount of time to
+ wait before an active HTTP or IPP request times out. The default
+ timeout is 300 seconds.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="User">User</A></H3>
@@ -2492,22 +2625,22 @@ User guest
 </PRE>
 </UL>
 <H4>Description</H4>
-<P>The <CODE>User</CODE> directive specifies the UNIX user that filter 
-and CGI programs run as. The default user is <CODE>lp</CODE>. 
+<P>The <CODE>User</CODE> directive specifies the UNIX user that filter
+ and CGI programs run as. The default user is <CODE>lp</CODE>.
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="PRINTING_SECURITY">Printing System Security</A></H2>
-<P>CUPS provides support for address, certificate, and password (Basic 
-and Digest) based authentication and access control. Certificate and 
-password authentication provide ways to limit access to individual 
-people or groups. </P>
-<P>Address based access control allows you to limit access to specific 
-systems, networks, or domains. While this does not provide 
-authentication, it does allow you to limit the potential users of your 
-system efficiently. </P>
-<P>CUPS maintains a list of locations that have access control and/or 
-authentication enabled. Locations are specified using the <A HREF="#Location">
-<CODE>Location</CODE></A> directive: </P>
+<P>CUPS provides support for address, certificate, and password (Basic
+ and Digest) based authentication and access control. Certificate and
+ password authentication provide ways to limit access to individual
+ people or groups.</P>
+<P>Address based access control allows you to limit access to specific
+ systems, networks, or domains. While this does not provide
+ authentication, it does allow you to limit the potential users of your
+ system efficiently.</P>
+<P>CUPS maintains a list of locations that have access control and/or
+ authentication enabled. Locations are specified using the<A HREF="#Location">
+ <CODE>Location</CODE></A> directive:</P>
 <UL>
 <PRE>
 &lt;Location /resource&gt;
@@ -2521,9 +2654,9 @@ authentication enabled. Locations are specified using the <A HREF="#Location">
 &lt;/Location&gt;
 </PRE>
 </UL>
-<P>Locations generally follow the directory structure of the <A HREF="#DocumentRoot">
-<CODE>DocumentRoot</CODE></A> directory, however CUPS does have several 
-virtual locations for administration, classes, jobs, and printers: 
+<P>Locations generally follow the directory structure of the<A HREF="#DocumentRoot">
+ <CODE>DocumentRoot</CODE></A> directory, however CUPS does have several
+ virtual locations for administration, classes, jobs, and printers:
 <CENTER>
 <TABLE BORDER="1">
 <TR><TH>Location</TH><TH>Description</TH></TR>
@@ -2542,69 +2675,68 @@ name</CODE>.</TD></TR>
 </CENTER>
 </P>
 <H3><A NAME="CERTIFICATES">Authentication Using Certificates</A></H3>
-<P>CUPS supports a local certificate-based authentication scheme that 
-can be used in place of <CODE>Basic</CODE> or <CODE>Digest</CODE>
+<P>CUPS supports a local certificate-based authentication scheme that
+ can be used in place of <CODE>Basic</CODE> or <CODE>Digest</CODE>
  authentication by clients connecting through the <CODE>localhost</CODE>
- interface. Certificate authentication is not supported or allowed from 
-clients on any other interface. </P>
-<P>Certificates are 128-bit random numbers that refer to an internal 
-authentication record in the server. A client connecting via the <CODE>
-localhost</CODE> interface sends a request with an authorization header 
-of: </P>
+ interface. Certificate authentication is not supported or allowed from
+ clients on any other interface.</P>
+<P>Certificates are 128-bit random numbers that refer to an internal
+ authentication record in the server. A client connecting via the <CODE>
+localhost</CODE> interface sends a request with an authorization header
+ of:</P>
 <UL>
 <PRE>
 Authorization: Local 0123456789ABCDEF0123456789ABCDEF
 </PRE>
 </UL>
-<P>The server then looks up the local certificate and authenticates 
-using the username associated with it. </P>
-<P>Certificates are generated by the server automatically and stored in 
-the <VAR>/etc/cups/certs</VAR> directory using the process ID of the 
-CGI program started by the server. Certificate files are only readable 
-by the <A HREF="#User"><CODE>User</CODE></A> and <A HREF="#Group"><CODE>
-Group</CODE></A> defined in the <VAR>cupsd.conf</VAR> file. When the 
-CGI program ends the certificate is removed and invalidated 
-automatically. </P>
-<P>The special file <VAR>/etc/cups/certs/0</VAR> defines the <I>root 
-certificate</I> which can be used by any client running as the 
-super-user or another user that is part of the group defined by the <A HREF="#SystemGroup">
-<CODE>SystemGroup</CODE></A> directive. The root certificate is 
-automatically regenerated every 5 minutes. </P>
+<P>The server then looks up the local certificate and authenticates
+ using the username associated with it.</P>
+<P>Certificates are generated by the server automatically and stored in
+ the<VAR> /etc/cups/certs</VAR> directory using the process ID of the
+ CGI program started by the server. Certificate files are only readable
+ by the<A HREF="#User"> <CODE>User</CODE></A> and<A HREF="#Group"> <CODE>
+Group</CODE></A> defined in the<VAR> cupsd.conf</VAR> file. When the CGI
+ program ends the certificate is removed and invalidated automatically.</P>
+<P>The special file<VAR> /etc/cups/certs/0</VAR> defines the<I> root
+ certificate</I> which can be used by any client running as the
+ super-user or another user that is part of the group defined by the<A HREF="#SystemGroup">
+ <CODE>SystemGroup</CODE></A> directive. The root certificate is
+ automatically regenerated every 5 minutes.</P>
 <H3><A NAME="7_5_2">Using Basic Authentication</A></H3>
-<P>Basic authentication uses UNIX users and passwords to authenticate 
-access to resources such as printers and classes, and to limit access 
-to administrative functions. 
+<P>Basic authentication uses UNIX users and passwords to authenticate
+ access to resources such as printers and classes, and to limit access
+ to administrative functions.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>Basic authentication sends the username and password Base64  encoded 
-from the client to the server, so it offers no  protection against 
-eavesdropping. This means that a malicious  user can monitor network 
-packets and discover valid users and  passwords that could result in a 
-serious compromise in network  security. Use Basic authentication with 
-extreme care. </P>
+<P>Basic authentication sends the username and password Base64 encoded
+ from the client to the server, so it offers no protection against
+ eavesdropping. This means that a malicious user can monitor network
+ packets and discover valid users and passwords that could result in a
+ serious compromise in network security. Use Basic authentication with
+ extreme care.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 </P>
-<P>The CUPS implementation of Basic authentication does not allow 
-access through user accounts without a password. If you try to 
-authenticate using an account without a password, your access will be 
-immediately blocked. </P>
-<P>Once a valid username and password is authenticated by CUPS, any 
-additional group membership requirements are checked. 
+<P>The CUPS implementation of Basic authentication does not allow access
+ through user accounts without a password. If you try to authenticate
+ using an account without a password, your access will be immediately
+ blocked.</P>
+<P>Once a valid username and password is authenticated by CUPS, any
+ additional group membership requirements are checked.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>The root user is considered by CUPS to be a member of every  group. </P>
+<P>The root user is considered by CUPS to be a member of every group.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 
 <!-- NEED 1in -->
 </P>
-<P>Use the <CODE>AuthType</CODE> directive to enable Basic 
-authentication: </P>
+<P>Use the <CODE>AuthType</CODE> directive to enable Basic
+ authentication:</P>
 <UL>
 <PRE>
 AuthType Basic
@@ -2613,42 +2745,41 @@ AuthType Basic
 
 <!-- NEED 7in -->
 <H3><A NAME="7_5_3">Using Digest Authentication</A></H3>
-<P>Digest authentication uses users and passwords defined in the <VAR>
-/etc/cups/passwd.md5</VAR> file to authenticate access to resources 
-such as printers and classes, and to limit access to administrative 
-functions. 
+<P>Digest authentication uses users and passwords defined in the<VAR>
+ /etc/cups/passwd.md5</VAR> file to authenticate access to resources
+ such as printers and classes, and to limit access to administrative
+ functions.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>Unlike Basic authentication, Digest passes the MD5 sum  (basically a 
-complicated checksum) of the username and password  instead of the 
-strings themselves. Also, Digest authentication  does not use the UNIX 
-password file, so if an attacker does  discover the original password 
-it is less likely to result in a  serious security problem so long as 
-you use a different UNIX  password than the corresponding Digest 
-password. </P>
-<P>The current CUPS implementation of Digest authentication  uses the 
-client's hostname or IP address for the &quot;nonce&quot; value.  The nonce value 
-is an additional string added to the username  and password to make 
-guessing the password more difficult. The  server checks that the nonce 
-value matches the client's hostname  or address and rejects the MD5 sum 
-if it doesn't.  Future versions  of CUPS will support Digest &quot;session&quot; 
-authentication which adds  the request data to the MD5 sum, providing 
-even better  authentication and security. </P>
-<P>Digest authentication does not guarantee that an attacker  cannot 
-gain unauthorized access, but it is safer than Basic  authentication 
-and should be used in place of Basic  authentication whenever possible. <B>
-Support for Digest  authentication in web browsers is not yet 
-universally  available.</B></P>
+<P>Unlike Basic authentication, Digest passes the MD5 sum (basically a
+ complicated checksum) of the username and password instead of the
+ strings themselves. Also, Digest authentication does not use the UNIX
+ password file, so if an attacker does discover the original password it
+ is less likely to result in a serious security problem so long as you
+ use a different UNIX password than the corresponding Digest password.</P>
+<P>The current CUPS implementation of Digest authentication uses the
+ client's hostname or IP address for the &quot;nonce&quot; value. The nonce value
+ is an additional string added to the username and password to make
+ guessing the password more difficult. The server checks that the nonce
+ value matches the client's hostname or address and rejects the MD5 sum
+ if it doesn't. Future versions of CUPS will support Digest &quot;session&quot;
+ authentication which adds the request data to the MD5 sum, providing
+ even better authentication and security.</P>
+<P>Digest authentication does not guarantee that an attacker cannot gain
+ unauthorized access, but it is safer than Basic authentication and
+ should be used in place of Basic authentication whenever possible.<B>
+ Support for Digest authentication in web browsers is not yet
+ universally available.</B></P>
 </TD></TR>
 </TABLE>
 </CENTER>
 
 <!-- NEED 2in -->
 </P>
-<P>The <CODE>lppasswd(1)</CODE> command is used to add, change, or 
-remove accounts from the <VAR>passwd.md5</VAR> file. To add a user to 
-the default system group, type: </P>
+<P>The <CODE>lppasswd(1)</CODE> command is used to add, change, or
+ remove accounts from the<VAR> passwd.md5</VAR> file. To add a user to
+ the default system group, type:</P>
 <UL>
 <PRE>
 <B>lppasswd -a user ENTER</B>
@@ -2658,7 +2789,7 @@ Password again: <B>(password) ENTER</B> [password is not echoed]
 </UL>
 
 <!-- NEED 2in -->
-<P>Once added, a user can change his/her password by typing: </P>
+<P>Once added, a user can change his/her password by typing:</P>
 <UL>
 <PRE>
 <B>lppasswd ENTER</B>
@@ -2669,40 +2800,40 @@ Password again: <B>(password) ENTER</B> [password is not echoed]
 </UL>
 
 <!-- NEED 1in -->
-<P>To remove a user from the password file, type: </P>
+<P>To remove a user from the password file, type:</P>
 <UL>
 <PRE>
 <B>lppasswd -x user ENTER</B>
 </PRE>
 </UL>
-<P>Once a valid username and password is authenticated by CUPS, any 
-additional group membership requirements are checked. 
+<P>Once a valid username and password is authenticated by CUPS, any
+ additional group membership requirements are checked.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>The root user is considered by CUPS to be a member of every  group. </P>
+<P>The root user is considered by CUPS to be a member of every group.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 </P>
-<P>Use the <CODE>AuthType</CODE> directive to enable Digest 
-authentication: </P>
+<P>Use the <CODE>AuthType</CODE> directive to enable Digest
+ authentication:</P>
 <UL>
 <PRE>
 AuthType Digest
 </PRE>
 </UL>
 <H3><A NAME="7_5_4">System and Group Authentication</A></H3>
-<P>The <A HREF="#AuthClass"><CODE>AuthClass</CODE></A> directive 
-controls the level of authentication to perform. <CODE>System</CODE>
- and <CODE>Group</CODE> authentication extend the normal user-based 
-authentication to require membership in a UNIX group. For <CODE>System</CODE>
+<P>The<A HREF="#AuthClass"> <CODE>AuthClass</CODE></A> directive
+ controls the level of authentication to perform. <CODE>System</CODE>
+ and <CODE>Group</CODE> authentication extend the normal user-based
+ authentication to require membership in a UNIX group. For <CODE>System</CODE>
  authentication each user must belong to the <CODE>sys</CODE>, <CODE>
-system</CODE>, or <CODE>root</CODE> group; the actual group depends on 
-the operating system. </P>
-<P>For <CODE>Group</CODE> authentication each user must belong to the 
-group named by the <A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A>
- directive: </P>
+system</CODE>, or <CODE>root</CODE> group; the actual group depends on
+ the operating system.</P>
+<P>For <CODE>Group</CODE> authentication each user must belong to the
+ group named by the<A HREF="#AuthGroupName"> <CODE>AuthGroupName</CODE></A>
+ directive:</P>
 <UL>
 <PRE>
 &lt;Location /path&gt;
@@ -2712,10 +2843,10 @@ AuthGroupName mygroup
 &lt;/Location&gt;
 </PRE>
 </UL>
-<P>The named group must be a valid UNIX user group, usually defined in 
-the <VAR>/etc/group</VAR> or <VAR>/etc/netgroup</VAR> files. 
-Additionally, when using Digest authentication you need to create user 
-accounts with the named group: </P>
+<P>The named group must be a valid UNIX user group, usually defined in
+ the<VAR> /etc/group</VAR> or<VAR> /etc/netgroup</VAR> files.
+ Additionally, when using Digest authentication you need to create user
+ accounts with the named group:</P>
 <UL>
 <PRE>
 <B>lppasswd -g mygroup -a user ENTER</B>
@@ -2726,15 +2857,15 @@ Password again: <B>(password) ENTER</B> [password is not echoed]
 
 <!-- NEW PAGE -->
 <H2><A NAME="PRINTER_ACCOUNTING">Printer Accounting</A></H2>
-<P>ESP Print Pro maintains a log of all accesses, errors, and pages 
-that are printed. The log files are normally stored in the <VAR>
-/var/log/cups</VAR> directory. You can change this by editing the <VAR>
-/etc/cups/cupsd.conf</VAR> configuration file. </P>
+<P>ESP Print Pro maintains a log of all accesses, errors, and pages that
+ are printed. The log files are normally stored in the<VAR>
+ /var/log/cups</VAR> directory. You can change this by editing the<VAR>
+ /etc/cups/cupsd.conf</VAR> configuration file.</P>
 <H3><A NAME="7_6_1">The access_log File</A></H3>
-<P>The <VAR>access_log</VAR> file lists each HTTP resource that is 
-accessed by a web browser or CUPS/IPP client. Each line is in the 
-so-called &quot;Common Log Format&quot; used by many web servers and web 
-reporting tools: </P>
+<P>The<VAR> access_log</VAR> file lists each HTTP resource that is
+ accessed by a web browser or CUPS/IPP client. Each line is in the
+ so-called &quot;Common Log Format&quot; used by many web servers and web
+ reporting tools:</P>
 <UL>
 <PRE>
 host group user date-time \&quot;method resource version\&quot; status bytes
@@ -2743,37 +2874,37 @@ host group user date-time \&quot;method resource version\&quot; status bytes
 127.0.0.1 - mike [20/May/1999:19:20:31 +0000] &quot;POST /admin/ HTTP/1.1&quot; 200 0
 </PRE>
 </UL>
-<P>The <I>host</I> field will normally only be an IP address unless you 
-have enabled the <A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>
- directive in the <VAR>cupsd.conf</VAR> file. </P>
-<P>The <I>group</I> field always contains &quot;-&quot; in CUPS. </P>
-<P>The <I>user</I> field is the authenticated username of the 
-requesting user. If no username and password is supplied for the 
-request then this field contains &quot;-&quot;. </P>
-<P>The <I>date-time</I> field is the date and time of the request in 
-local time and is in the format: </P>
+<P>The<I> host</I> field will normally only be an IP address unless you
+ have enabled the<A HREF="#HostNameLookups"> <CODE>HostNameLookups</CODE>
+</A> directive in the<VAR> cupsd.conf</VAR> file.</P>
+<P>The<I> group</I> field always contains &quot;-&quot; in CUPS.</P>
+<P>The<I> user</I> field is the authenticated username of the requesting
+ user. If no username and password is supplied for the request then this
+ field contains &quot;-&quot;.</P>
+<P>The<I> date-time</I> field is the date and time of the request in
+ local time and is in the format:</P>
 <UL>
 <PRE>
 [DD/MON/YYYY:HH:MM:SS +ZZZZ]
 </PRE>
 </UL>
-<P>where <I>ZZZZ</I> is the timezone offset in hours and minutes from 
-Greenwich Mean Time (a.k.a. GMT a.k.a. ZULU.) </P>
-<P>The <I>method</I> field is the HTTP method used (&quot;GET&quot;, &quot;PUT&quot;, 
-&quot;POST&quot;, etc.) </P>
-<P>The <I>resource</I> field is the filename of the requested resource. </P>
-<P>The <I>version</I> field is the HTTP specification version used by 
-the client. For CUPS clients this will always be &quot;HTTP/1.1&quot;. </P>
-<P>The <I>status</I> field contains the HTTP result status of the 
-request. Usually it is &quot;200&quot;, but other HTTP status codes are possible. 
-For example, 401 is the &quot;unauthorized access&quot; status in the example 
-above. </P>
-<P>The <I>bytes</I> field contains the number of bytes in the request. 
-For POST requests the <I>bytes</I> field contains the number of bytes 
-that was received from the client. </P>
+<P>where<I> ZZZZ</I> is the timezone offset in hours and minutes from
+ Greenwich Mean Time (a.k.a. GMT a.k.a. ZULU.)</P>
+<P>The<I> method</I> field is the HTTP method used (&quot;GET&quot;, &quot;PUT&quot;,
+ &quot;POST&quot;, etc.)</P>
+<P>The<I> resource</I> field is the filename of the requested resource.</P>
+<P>The<I> version</I> field is the HTTP specification version used by
+ the client. For CUPS clients this will always be &quot;HTTP/1.1&quot;.</P>
+<P>The<I> status</I> field contains the HTTP result status of the
+ request. Usually it is &quot;200&quot;, but other HTTP status codes are possible.
+ For example, 401 is the &quot;unauthorized access&quot; status in the example
+ above.</P>
+<P>The<I> bytes</I> field contains the number of bytes in the request.
+ For POST requests the<I> bytes</I> field contains the number of bytes
+ that was received from the client.</P>
 <H3><A NAME="7_6_2">The error_log File</A></H3>
-<P>The <VAR>error_log</VAR> file lists messages from the scheduler 
-(errors, warnings, etc.): </P>
+<P>The<VAR> error_log</VAR> file lists messages from the scheduler
+ (errors, warnings, etc.):</P>
 <UL>
 <PRE>
 level date-time message
@@ -2783,20 +2914,20 @@ I [20/May/1999:19:21:02 +0000] Job 2 queued on 'DeskJet' by 'mike'.
 I [20/May/1999:19:22:24 +0000] Job 2 was cancelled by 'mike'.
 </PRE>
 </UL>
-<P>The <I>level</I> field contains the type of message: </P>
+<P>The<I> level</I> field contains the type of message:</P>
 <UL>
-<LI><CODE>E</CODE> - An error occurred. </LI>
-<LI><CODE>W</CODE> - The server was unable to perform some action. </LI>
-<LI><CODE>I</CODE> - Informational message. </LI>
-<LI><CODE>D</CODE> - Debugging message. </LI>
+<LI><CODE>E</CODE> - An error occurred.</LI>
+<LI><CODE>W</CODE> - The server was unable to perform some action.</LI>
+<LI><CODE>I</CODE> - Informational message.</LI>
+<LI><CODE>D</CODE> - Debugging message.</LI>
 </UL>
-<P>The <I>date-time</I> field contains the date and time of when 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>message</I> fields contains a free-form textual message. </P>
+<P>The<I> date-time</I> field contains the date and time of when 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> message</I> fields contains a free-form textual message.</P>
 <H3><A NAME="7_6_3">The page_log File</A></H3>
-<P>The <VAR>page_log</VAR> file lists each page that is sent to a 
-printer. Each line contains the following information: </P>
+<P>The<VAR> page_log</VAR> file lists each page that is sent to a
+ printer. Each line contains the following information:</P>
 <UL>
 <PRE>
 printer user job-id date-time page-number num-copies job-billing
@@ -2804,42 +2935,42 @@ printer user job-id date-time page-number num-copies job-billing
 DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123
 </PRE>
 </UL>
-<P>The <I>printer</I> field contains the name of the printer that 
-printed the page. If you send a job to a printer class, this field will 
-contain the name of the printer that was assigned the job. </P>
-<P>The <I>user</I> field contains the name of the user (the IPP <CODE>
-requesting-user-name</CODE> attribute) that submitted this file for 
-printing. </P>
-<P>The <I>job-id</I> field contains the job number of the page being 
-printed. Job numbers are reset to 1 whenever the CUPS server is 
-started, so don't depend on this number being unique! </P>
-<P>The <I>date-time</I> field contains the date and time of when 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 page 
-number and number of copies being printed of that page. For printer 
-that can not produce copies on their own, the <I>num-pages</I> field 
-will always be 1. </P>
-<P>The <I>job-billing</I> field contains a copy of the <CODE>job-billing</CODE>
+<P>The<I> printer</I> field contains the name of the printer that
+ printed the page. If you send a job to a printer class, this field will
+ contain the name of the printer that was assigned the job.</P>
+<P>The<I> user</I> field contains the name of the user (the IPP <CODE>
+requesting-user-name</CODE> attribute) that submitted this file for
+ printing.</P>
+<P>The<I> job-id</I> field contains the job number of the page being
+ printed. Job numbers are reset to 1 whenever the CUPS server is
+ started, so don't depend on this number being unique!</P>
+<P>The<I> date-time</I> field contains the date and time of when 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 page
+ number and number of copies being printed of that page. For printer
+ that can not produce copies on their own, the<I> num-pages</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 <CODE>create-job</CODE> or <CODE>
-print-job</CODE> requests or &quot;-&quot; if none was provided. 
+print-job</CODE> requests or &quot;-&quot; if none was provided.
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="FILE_TYPING_FILTERING">File Typing and Filtering</A></H2>
-<P>CUPS provides a MIME-based file typing and filtering mechanism to 
-convert files to a printable format for each printer. On startup the 
-CUPS server reads MIME database files from the <VAR>/etc/cups</VAR>
- directory (or a directory specified by the <A HREF="#ServerRoot"><CODE>
-ServerRoot</CODE></A> directive) to build a file type and conversion 
-database in memory. These database files are plain ASCII text and can 
-be edited with your favorite text editor. </P>
-<P>The <VAR>mime.types</VAR> and <VAR>mime.convs</VAR> files define the 
-standard file types and filters that are available on the system. </P>
+<P>CUPS provides a MIME-based file typing and filtering mechanism to
+ convert files to a printable format for each printer. On startup the
+ CUPS server reads MIME database files from the<VAR> /etc/cups</VAR>
+ directory (or a directory specified by the<A HREF="#ServerRoot"> <CODE>
+ServerRoot</CODE></A> directive) to build a file type and conversion
+ database in memory. These database files are plain ASCII text and can
+ be edited with your favorite text editor.</P>
+<P>The<VAR> mime.types</VAR> and<VAR> mime.convs</VAR> files define the
+ standard file types and filters that are available on the system.</P>
 <H3><A NAME="7_7_1">mime.types</A></H3>
-<P>The <VAR>mime.types</VAR> file defines the known file types. Each 
-line of the file starts with the MIME type and may be followed by one 
-or more file type recognition rules. For example, the <CODE>text/html</CODE>
- file type is defined as: </P>
+<P>The<VAR> mime.types</VAR> file defines the known file types. Each
+ line of the file starts with the MIME type and may be followed by one
+ or more file type recognition rules. For example, the <CODE>text/html</CODE>
+ file type is defined as:</P>
 <UL>
 <PRE>
 text/html       html htm \
@@ -2847,46 +2978,46 @@ text/html       html htm \
                 (string(0,&quot;&lt;HTML&gt;&quot;) string(0,&quot;&lt;!DOCTYPE&quot;))
 </PRE>
 </UL>
-<P>The first two rules say that any file with an extension of <VAR>.html</VAR>
- or <VAR>.htm</VAR> is a HTML file. The third rule says that any file 
-whose first 1024 characters are printable text and starts with the 
-strings <CODE>&lt;HTML&gt;</CODE> or <CODE>&lt;!DOCTYPE</CODE> is a HTML file as 
-well. </P>
-<P>The first two rules deal solely with the name of the file being 
-typed. This is useful when the original filename is known, however for 
-print files the server doesn't have a filename to work with. The third 
-rule takes care of this possibility and automatically figures out the 
-file type based upon the contents of the file instead. </P>
-<P>The available tests are: </P>
-<UL>
-<LI><CODE>( expr )</CODE> - Parenthesis for expression grouping </LI>
-<LI><CODE>+</CODE> - Logical AND </LI>
-<LI><CODE>,</CODE> or whitespace - Logical OR </LI>
-<LI><CODE>!</CODE> - Logical NOT </LI>
-<LI><CODE>match(&quot;pattern&quot;)</CODE> - Pattern match on filename </LI>
-<LI><CODE>extension</CODE> - Pattern match on &quot;*.extension&quot; </LI>
-<LI><CODE>ascii(offset,length)</CODE> - True if bytes are valid 
- printable ASCII (CR, NL, TAB, BS, 32-126) </LI>
-<LI><CODE>printable(offset,length)</CODE> - True if bytes are 
printable 8-bit chars (CR, NL, TAB, BS, 32-126, 160-254) </LI>
-<LI><CODE>string(offset,&quot;string&quot;)</CODE> - True if bytes are  identical 
-to string </LI>
-<LI><CODE>contains(offset,range,&quot;string&quot;)</CODE> - True if the  range 
-of bytes contains the string </LI>
-<LI><CODE>char(offset,value)</CODE> - True if byte is identical </LI>
-<LI><CODE>short(offset,value)</CODE> - True if 16-bit integer  is 
-identical (network or &quot;big-endian&quot; byte order) </LI>
-<LI><CODE>int(offset,value)</CODE> - True if 32-bit integer is 
identical (network or &quot;big-endian&quot; byte order) </LI>
-<LI><CODE>locale(&quot;string&quot;)</CODE> - True if current locale  matches 
-string </LI>
-</UL>
-<P>All numeric values can be in decimal (123), octal (0123), or 
-hexadecimal (0x123) as desired. 
+<P>The first two rules say that any file with an extension of<VAR> .html</VAR>
+ or<VAR> .htm</VAR> is a HTML file. The third rule says that any file
+ whose first 1024 characters are printable text and starts with the
+ strings <CODE>&lt;HTML&gt;</CODE> or <CODE>&lt;!DOCTYPE</CODE> is a HTML file as
+ well.</P>
+<P>The first two rules deal solely with the name of the file being
+ typed. This is useful when the original filename is known, however for
+ print files the server doesn't have a filename to work with. The third
+ rule takes care of this possibility and automatically figures out the
+ file type based upon the contents of the file instead.</P>
+<P>The available tests are:</P>
+<UL>
+<LI><CODE>( expr )</CODE> - Parenthesis for expression grouping</LI>
+<LI><CODE>+</CODE> - Logical AND</LI>
+<LI><CODE>,</CODE> or whitespace - Logical OR</LI>
+<LI><CODE>!</CODE> - Logical NOT</LI>
+<LI><CODE>match(&quot;pattern&quot;)</CODE> - Pattern match on filename</LI>
+<LI><CODE>extension</CODE> - Pattern match on &quot;*.extension&quot;</LI>
+<LI><CODE>ascii(offset,length)</CODE> - True if bytes are valid
+ printable ASCII (CR, NL, TAB, BS, 32-126)</LI>
+<LI><CODE>printable(offset,length)</CODE> - True if bytes are printable
8-bit chars (CR, NL, TAB, BS, 32-126, 160-254)</LI>
+<LI><CODE>string(offset,&quot;string&quot;)</CODE> - True if bytes are identical
+ to string</LI>
+<LI><CODE>contains(offset,range,&quot;string&quot;)</CODE> - True if the range of
+ bytes contains the string</LI>
+<LI><CODE>char(offset,value)</CODE> - True if byte is identical</LI>
+<LI><CODE>short(offset,value)</CODE> - True if 16-bit integer is
+ identical (network or &quot;big-endian&quot; byte order)</LI>
+<LI><CODE>int(offset,value)</CODE> - True if 32-bit integer is identical
(network or &quot;big-endian&quot; byte order)</LI>
+<LI><CODE>locale(&quot;string&quot;)</CODE> - True if current locale matches
+ string</LI>
+</UL>
+<P>All numeric values can be in decimal (123), octal (0123), or
+ hexadecimal (0x123) as desired.
 <!-- NEED 2.5in -->
 </P>
-<P>Strings can be in quotes, all by themselves, as a string of 
-hexadecimal values, or some combination: </P>
+<P>Strings can be in quotes, all by themselves, as a string of
+ hexadecimal values, or some combination:</P>
 <UL>
 <PRE>
 &quot;string&quot;
@@ -2896,9 +3027,9 @@ string
 &lt;7374&gt;ring
 </PRE>
 </UL>
-<P>As shown in the <CODE>text/html</CODE> example, rules can continue 
-on multiple lines using the backslash (\) character. A more complex 
-example is the <CODE>image/jpeg</CODE> rules: </P>
+<P>As shown in the <CODE>text/html</CODE> example, rules can continue on
+ multiple lines using the backslash (\) character. A more complex
+ example is the <CODE>image/jpeg</CODE> rules:</P>
 <UL>
 <PRE>
 image/jpeg      jpeg jpg jpe string(0,&lt;FFD8FF&gt;) &amp;&amp;\
@@ -2908,14 +3039,15 @@ image/jpeg      jpeg jpg jpe string(0,&lt;FFD8FF&gt;) &amp;&amp;\
                  char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
 </PRE>
 </UL>
-<P>This rule states that any file with an extension of <VAR>.jpeg</VAR>
-, <VAR>.jpg</VAR>, or <VAR>.jpe</VAR> is a JPEG file. In addition, any 
-file starting with the hexadecimal string <CODE>&lt;FFD8FF&gt;</CODE> (JPEG 
-Start-Of-Image) followed by a character between and including <CODE>0xe0</CODE>
- and <CODE>0xef</CODE> (JPEG APPn markers) is also a JPEG file. </P>
+<P>This rule states that any file with an extension of<VAR> .jpeg</VAR>,<VAR>
+ .jpg</VAR>, or<VAR> .jpe</VAR> is a JPEG file. In addition, any file
+ starting with the hexadecimal string <CODE>&lt;FFD8FF&gt;</CODE> (JPEG
+ Start-Of-Image) followed by a character between and including <CODE>
+0xe0</CODE> and <CODE>0xef</CODE> (JPEG APPn markers) is also a JPEG
+ file.</P>
 <H3><A NAME="7_7_2">mime.convs</A></H3>
-<P>The <VAR>mime.convs</VAR> file defines all of the filter programs 
-that are known to the system. Each line consists of: </P>
+<P>The<VAR> mime.convs</VAR> file defines all of the filter programs
+ that are known to the system. Each line consists of:</P>
 <UL>
 <PRE>
 source destination cost program
@@ -2926,107 +3058,107 @@ image/* application/vnd.cups-postscript 50 imagetops
 image/* application/vnd.cups-raster 50 imagetoraster
 </PRE>
 </UL>
-<P>The <I>source</I> field is a MIME type, optionally using a wildcard 
-for the super-type or sub-type (e.g. &quot;text/plain&quot;, &quot;image/*&quot;, 
-&quot;*/postscript&quot;). </P>
-<P>The <I>destination</I> field is a MIME type defined in the <VAR>
-mime.types</VAR> file. </P>
-<P>The <I>cost</I> field defines a relative cost for the filtering 
-operation from 1 to 100. The cost is used to choose between two 
-different sets of filters when converting a file. For example, to 
-convert from <CODE>image/jpeg</CODE> to <CODE>
+<P>The<I> source</I> field is a MIME type, optionally using a wildcard
+ for the super-type or sub-type (e.g. &quot;text/plain&quot;, &quot;image/*&quot;,
+ &quot;*/postscript&quot;).</P>
+<P>The<I> destination</I> field is a MIME type defined in the<VAR>
+ mime.types</VAR> file.</P>
+<P>The<I> cost</I> field defines a relative cost for the filtering
+ operation from 1 to 100. The cost is used to choose between two
+ different sets of filters when converting a file. For example, to
+ convert from <CODE>image/jpeg</CODE> to <CODE>
 application/vnd.cups-raster</CODE>, you could use the <CODE>imagetops</CODE>
  and <CODE>pstoraster</CODE> filters for a total cost of 100, or the <CODE>
-imagetoraster</CODE> filter for a total cost of 50. </P>
-<P>The <I>program</I> field defines the filter program to run; the 
-special program &quot;-&quot; can be used to make two file types equivalent. The 
-program must accept the standard filter arguments and environment 
-variables described in the CUPS Interface Design Description and CUPS 
-Software Programmers Manual: </P>
+imagetoraster</CODE> filter for a total cost of 50.</P>
+<P>The<I> program</I> field defines the filter program to run; the
+ special program &quot;-&quot; can be used to make two file types equivalent. The
+ program must accept the standard filter arguments and environment
+ variables described in the CUPS Interface Design Description and CUPS
+ Software Programmers Manual:</P>
 <UL>
 <PRE>
 program job user title options [filename]
 </PRE>
 </UL>
-<P>If specified, the <I>filename</I> argument defines a file to read 
-when filtering, otherwise the filter must read from the standard input. 
-All filtered output must go to the standard output. 
+<P>If specified, the<I> filename</I> argument defines a file to read
+ when filtering, otherwise the filter must read from the standard input.
+ All filtered output must go to the standard output.
 <!-- NEED 4in -->
 </P>
 <H3><A NAME="7_7_3">Adding Filetypes and Filters</A></H3>
-<P>Adding a new file type or filter is fairly straight-forward. Rather 
-than adding the new type and filter to the <VAR>mime.types</VAR> and <VAR>
-mime.convs</VAR> files which are overwritten when you upgrade to a new 
-version of CUPS, you simple need to create new files with <VAR>.types</VAR>
- and <VAR>.convs</VAR> extensions in the <VAR>/etc/cups</VAR>
directory. We recommend that you use the product or format name, e.g.: </P>
+<P>Adding a new file type or filter is fairly straight-forward. Rather
+ than adding the new type and filter to the<VAR> mime.types</VAR> and<VAR>
+ mime.convs</VAR> files which are overwritten when you upgrade to a new
+ version of CUPS, you simple need to create new files with<VAR> .types</VAR>
+ and<VAR> .convs</VAR> extensions in the<VAR> /etc/cups</VAR> directory.
We recommend that you use the product or format name, e.g.:</P>
 <UL>
 <PRE>
 myproduct.types
 myproduct.convs
 </PRE>
 </UL>
-<P>If you are providing a filter for a common file format or printer, 
-add the company or author name: </P>
+<P>If you are providing a filter for a common file format or printer,
+ add the company or author name:</P>
 <UL>
 <PRE>
 acme-msword.types
 acme.msword.convs
 </PRE>
 </UL>
-<P>This will help to prevent name collisions if you install many 
-different file types and filters. </P>
-<P>Once you choose the names for these files, create them using your 
-favorite text editor as described earlier in this chapter.  Once you 
-have created the files, restart the <CODE>cupsd</CODE> process as 
-described earlier in <A HREF="#RESTARTING">&quot;Restarting the CUPS Server&quot;</A>
-. </P>
+<P>This will help to prevent name collisions if you install many
+ different file types and filters.</P>
+<P>Once you choose the names for these files, create them using your
+ favorite text editor as described earlier in this chapter. Once you
+ have created the files, restart the <CODE>cupsd</CODE> process as
+ described earlier in<A HREF="#RESTARTING"> &quot;Restarting the CUPS Server&quot;</A>
+.</P>
 <H3><A NAME="7_7_4">Printer Drivers and PPD Files</A></H3>
-<P>Most CUPS printer drivers utilize one or more printer-specific 
-filters and a PPD file for each printer model. Printer driver filters 
-are registered via the PPD file using <CODE>cupsFilter</CODE>
- attributes: </P>
+<P>Most CUPS printer drivers utilize one or more printer-specific
+ filters and a PPD file for each printer model. Printer driver filters
+ are registered via the PPD file using <CODE>cupsFilter</CODE>
+ attributes:</P>
 <UL>
 <PRE>
 *cupsFilter: &quot;application/vnd.cups-raster 0 rastertohp&quot;
 </PRE>
 </UL>
-<P>The filter is specified using the source file type only; the 
-destination file type is assumed to be <CODE>printer/name</CODE> - 
-suitable for sending to the printer. </P>
+<P>The filter is specified using the source file type only; the
+ destination file type is assumed to be <CODE>printer/name</CODE> -
+ suitable for sending to the printer.</P>
 <H3><A NAME="7_7_5">Writing Your Own Filter or Printer Driver</A></H3>
-<P>CUPS supports an unlimited number of file formats and filters, and 
-can handle any printer. If you'd like to write a filter or printer 
-driver for your favorite file format or printer, consult the CUPS 
-Software Programmers Manual for step-by-step instructions. </P>
-<H1 ALIGN="RIGHT"><A NAME="PRINTING_OTHER">7 - Printing with Other 
-Systems</A></H1>
-<P>This chapter describes how to print from client systems that use the 
-LPD, Mac OS, or Windows printing protocols. </P>
+<P>CUPS supports an unlimited number of file formats and filters, and
+ can handle any printer. If you'd like to write a filter or printer
+ driver for your favorite file format or printer, consult the CUPS
+ Software Programmers Manual for step-by-step instructions.</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_OTHER">7 - Printing with Other
+ Systems</A></H1>
+<P>This chapter describes how to print from client systems that use the
+ LPD, Mac OS, or Windows printing protocols.</P>
 <H2><A NAME="8_1">The Basics</A></H2>
-<P>CUPS is based on the IPP protocol, so any system that supports IPP 
-can send jobs to and receive jobs from CUPS automatically. However, not 
-all systems support IPP yet. This chapter will show you how to connect 
-these systems to your CUPS server, either to accept jobs from your 
-server for printing, or to send jobs to your server. </P>
+<P>CUPS is based on the IPP protocol, so any system that supports IPP
+ can send jobs to and receive jobs from CUPS automatically. However, not
+ all systems support IPP yet. This chapter will show you how to connect
+ these systems to your CUPS server, either to accept jobs from your
+ server for printing, or to send jobs to your server.</P>
 <H2><A NAME="8_2">Printing from LPD Clients</A></H2>
-<P>CUPS supports limited functionality for LPD-based clients. With LPD 
-you can print files to specific printers, list the queue status, and so 
-forth. However, the automatic client configuration and printer options 
-are not supported by the LPD protocol, so you must manually configure 
-each client for the printers it needs to access. </P>
-<P>The <CODE>cups-lpd(8)</CODE> program provides support for LPD 
-clients. To enable LPD support on your server, edit the <VAR>
-/etc/inetd.conf</VAR> file and add a line reading: </P>
+<P>CUPS supports limited functionality for LPD-based clients. With LPD
+ you can print files to specific printers, list the queue status, and so
+ forth. However, the automatic client configuration and printer options
+ are not supported by the LPD protocol, so you must manually configure
+ each client for the printers it needs to access.</P>
+<P>The <CODE>cups-lpd(8)</CODE> program provides support for LPD
+ clients. To enable LPD support on your server, edit the<VAR>
+ /etc/inetd.conf</VAR> file and add a line reading:</P>
 <UL>
 <PRE>
 printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
 </PRE>
 </UL>
-<P>The path to the <CODE>cups-lpd</CODE> may vary depending on your 
-installation. </P>
-<P>Once you have added this line, send the <CODE>inetd(8)</CODE>
process a <CODE>HUP</CODE> signal or reboot the system: </P>
+<P>The path to the <CODE>cups-lpd</CODE> may vary depending on your
+ installation.</P>
+<P>Once you have added this line, send the <CODE>inetd(8)</CODE> process
a <CODE>HUP</CODE> signal or reboot the system:</P>
 <UL>
 <PRE>
 <B>killall -HUP inetd ENTER</B> [IRIX and some versions of Linux]
@@ -3035,39 +3167,39 @@ installation. </P>
 </PRE>
 </UL>
 <H2><A NAME="8_3">Printing to LPD Servers</A></H2>
-<P>CUPS provides the <CODE>lpd</CODE> backend for printing to LPD-based 
-servers and printers. Use a device URI of <CODE>lpd://server/name</CODE>
- to print to a printer on an LPD server, where <CODE>server</CODE> is 
-the hostname or IP address of the server and <CODE>name</CODE> is the 
-queue name. </P>
-<P>Microsoft Windows NT provides an LPD service under the name &quot;TCP/IP 
-Printing Services&quot;. To enable LPD printing on NT, open the &quot;Services&quot; 
-control panel, select the &quot;TCP/IP Printing Services&quot; service, and click 
-on the &quot;Start&quot; button. Any shared printer will then be available via 
-the LPD protocol. </P>
+<P>CUPS provides the <CODE>lpd</CODE> backend for printing to LPD-based
+ servers and printers. Use a device URI of <CODE>lpd://server/name</CODE>
+ to print to a printer on an LPD server, where <CODE>server</CODE> is
+ the hostname or IP address of the server and <CODE>name</CODE> is the
+ queue name.</P>
+<P>Microsoft Windows NT provides an LPD service under the name &quot;TCP/IP
+ Printing Services&quot;. To enable LPD printing on NT, open the &quot;Services&quot;
+ control panel, select the &quot;TCP/IP Printing Services&quot; service, and click
+ on the &quot;Start&quot; button. Any shared printer will then be available via
+ the LPD protocol.</P>
 <H2><A NAME="8_4">Printing from Mac OS Clients</A></H2>
-<P>CUPS does not provide Mac OS support directly. However, there are 
-several free and commercial software packages that do. </P>
+<P>CUPS does not provide Mac OS support directly. However, there are
+ several free and commercial software packages that do.</P>
 <H3><A NAME="8_4_1">Columbia Appletalk Package (CAP)</A></H3>
-<P>Because the CAP LaserWriter server (<CODE>lwsrv(8)</CODE>) does not 
-support specification of PPD files, we do not recommend that you use 
-CAP with CUPS. However, you can run the <CODE>lpsrv</CODE> program for 
-limited printing with the command: </P>
+<P>Because the CAP LaserWriter server (<CODE>lwsrv(8)</CODE>) does not
+ support specification of PPD files, we do not recommend that you use
+ CAP with CUPS. However, you can run the <CODE>lpsrv</CODE> program for
+ limited printing with the command:</P>
 <UL>
 <PRE>
 lwsrv -n &quot;<I>Name</I>&quot; -p <I>printer</I> -a /usr/lib/adicts -f /usr/lib/LW+Fonts
 </PRE>
 </UL>
-<P>where <CODE>Name</CODE> is the name you want to use when sharing the 
-printer, and <CODE>printer</CODE> is the name of the CUPS print queue. 
+<P>where <CODE>Name</CODE> is the name you want to use when sharing the
+ printer, and <CODE>printer</CODE> is the name of the CUPS print queue.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="8_4_2">XINET KA/Spool</A></H3>
-<P>To use your system as a print server for Mac OS clients, configure 
-each printer using a <CODE>papserver(8)</CODE> in the <VAR>
-/usr/adm/appletalk/services</VAR> file, specifying the corresponding 
-PPD file in the <VAR>/etc/cups/ppd</VAR> directory for each printer. 
- For a printer named <CODE>MyPrinter</CODE> the entry would look like: </P>
+<P>To use your system as a print server for Mac OS clients, configure
+ each printer using a <CODE>papserver(8)</CODE> in the<VAR>
+ /usr/adm/appletalk/services</VAR> file, specifying the corresponding
+ PPD file in the<VAR> /etc/cups/ppd</VAR> directory for each printer.
+ For a printer named <CODE>MyPrinter</CODE> the entry would look like:</P>
 <UL>
 <PRE>
 /usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/MyPrinter.ppd \
@@ -3077,17 +3209,17 @@ PPD file in the <VAR>/etc/cups/ppd</VAR> directory for each printer.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>Enter the text above on a single line without the backslash (\) 
- character. </P>
+<P>Enter the text above on a single line without the backslash (\)
+ character.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="8_4_3">NetATalk</A></H3>
-<P>To use your system as a print server for Mac OS clients, configure 
-each printer in the <VAR>papd.conf</VAR> file, specifying the 
-corresponding PPD file in the <VAR>/etc/cups/ppd</VAR> directory for 
-each printer. For a printer named <CODE>MyPrinter</CODE> the entry 
-would look like: </P>
+<P>To use your system as a print server for Mac OS clients, configure
+ each printer in the<VAR> papd.conf</VAR> file, specifying the
+ corresponding PPD file in the<VAR> /etc/cups/ppd</VAR> directory for
+ each printer. For a printer named <CODE>MyPrinter</CODE> the entry
+ would look like:</P>
 <UL>
 <PRE>
 Printer Description:MyPrinter@MyServer:\
@@ -3099,14 +3231,14 @@ Printer Description:MyPrinter@MyServer:\
 
 <!-- NEED 2in -->
 <H2><A NAME="8_5">Printing to Mac OS Servers</A></H2>
-<P>CUPS currently does not provide a backend to communicate with a Mac 
-OS server. However, you can write and install a short shell script in 
-the <VAR>/usr/lib/cups/backend</VAR> directory that sends a print file 
-using the appropriate command. The following is a short script that 
-will run the <CODE>papif</CODE> command provided with CAP. </P>
-<P>After copying this script to <VAR>/usr/lib/cups/backend/cap</VAR>, 
-specify a device URI of <CODE>cap://server/printer</CODE> to use this 
-backend with a print queue. 
+<P>CUPS currently does not provide a backend to communicate with a Mac
+ OS server. However, you can write and install a short shell script in
+ the<VAR> /usr/lib/cups/backend</VAR> directory that sends a print file
+ using the appropriate command. The following is a short script that
+ will run the <CODE>papif</CODE> command provided with CAP.</P>
+<P>After copying this script to<VAR> /usr/lib/cups/backend/cap</VAR>,
+ specify a device URI of <CODE>cap://server/printer</CODE> to use this
+ backend with a print queue.
 <!-- NEED 8in -->
 </P>
 <UL>
@@ -3169,46 +3301,46 @@ exit 0
 
 <!-- NEED 2in -->
 <H2><A NAME="8_6">Printing from Windows Clients</A></H2>
-<P>While CUPS does not provide Windows support directly, the free SAMBA 
-software package does. SAMBA version 2.0.6 is the first release of 
-SAMBA that supports CUPS. You can download SAMBA from: </P>
+<P>While CUPS does not provide Windows support directly, the free SAMBA
+ software package does. SAMBA version 2.0.6 is the first release of
+ SAMBA that supports CUPS. You can download SAMBA from:</P>
 <UL>
 <PRE>
 <A HREF="http://www.samba.org">http://www.samba.org</A>
 </PRE>
 </UL>
-<P>To configure SAMBA for CUPS, edit the <VAR>smb.conf</VAR> file and 
-replace the existing printing commands and options with the line: </P>
+<P>To configure SAMBA for CUPS, edit the<VAR> smb.conf</VAR> file and
+ replace the existing printing commands and options with the line:</P>
 <UL>
 <PRE>
 printing = cups
 </PRE>
 </UL>
-<P>That's all there is to it!  Remote users will now be able to browse 
-and print to printers on your system. </P>
+<P>That's all there is to it! Remote users will now be able to browse
+ and print to printers on your system.</P>
 <H2><A NAME="8_7">Printing to Windows Servers</A></H2>
-<P>CUPS can print to Windows servers in one of two ways. The first way 
-uses the LPD protocol on the CUPS system and the &quot;TCP/IP Printing 
-Services&quot; on the Windows system. You can find out more about this 
-configuration in the <A HREF="#LPD">LPD</A> section earlier in this 
-chapter. </P>
-<P>The second way is through the Microsoft Server Message Block (&quot;SMB&quot;) 
-protocol. Support for this protocol is provided with the free SAMBA 
-software package. You can download SAMBA from: </P>
+<P>CUPS can print to Windows servers in one of two ways. The first way
+ uses the LPD protocol on the CUPS system and the &quot;TCP/IP Printing
+ Services&quot; on the Windows system. You can find out more about this
+ configuration in the<A HREF="#LPD"> LPD</A> section earlier in this
+ chapter.</P>
+<P>The second way is through the Microsoft Server Message Block (&quot;SMB&quot;)
+ protocol. Support for this protocol is provided with the free SAMBA
+ software package. You can download SAMBA from:</P>
 <UL>
 <PRE>
 <A HREF="http://www.samba.org">http://www.samba.org</A>
 </PRE>
 </UL>
-<P>To configure CUPS for SAMBA, run the following command: </P>
+<P>To configure CUPS for SAMBA, run the following command:</P>
 <UL>
 <PRE>
 <B>ln -s `which smbspool` /usr/lib/cups/backend/smb ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>smbspool(1)</CODE> program is provided with SAMBA starting 
-with SAMBA 2.0.6. Once you have made the link you can configure your 
-printers with one of the following device URIs: </P>
+<P>The <CODE>smbspool(1)</CODE> program is provided with SAMBA starting
+ with SAMBA 2.0.6. Once you have made the link you can configure your
+ printers with one of the following device URIs:</P>
 <UL>
 <PRE>
 smb://workgroup/server/sharename
@@ -3217,87 +3349,86 @@ smb://user:pass@workgroup/server/sharename
 smb://user:pass@server/sharename
 </PRE>
 </UL>
-<P>The <CODE>workgroup</CODE> name need only be specified if your 
-system is using a different workgroup. The <CODE>user:pass</CODE>
- strings are required when printing to Windows NT servers or to shares 
-with passwords enabled under Windows 95 and 98. </P>
+<P>The <CODE>workgroup</CODE> name need only be specified if your system
+ is using a different workgroup. The <CODE>user:pass</CODE> strings are
+ required when printing to Windows NT servers or to shares with
+ passwords enabled under Windows 95 and 98.</P>
 <H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
-<H2 ALIGN="CENTER"><A NAME="9_1">Common UNIX Printing System License 
-Agreement</A></H2>
+<H2 ALIGN="CENTER"><A NAME="9_1">Common UNIX Printing System License
+ Agreement</A></H2>
 <P ALIGN="CENTER">Copyright 1997-2001 by Easy Software Products
 <BR> 44141 AIRPORT VIEW DR STE 204
 <BR> HOLLYWOOD, MARYLAND 20636-3111 USA
 <BR>
 <BR> Voice: +1.301.373.9600
-<BR> Email: <A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
-<BR> WWW: <A HREF="http://www.cups.org">http://www.cups.org</A></P>
+<BR> Email:<A HREF="mailto:cups-info@cups.org"> cups-info@cups.org</A>
+<BR> WWW:<A HREF="http://www.cups.org"> http://www.cups.org</A></P>
 <H3><A NAME="9_1_1">Introduction</A></H3>
-<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;), 
-is provided under the GNU General Public License (&quot;GPL&quot;) and GNU 
-Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these 
-licenses follow this introduction. </P>
-<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot; 
-subdirectory of the CUPS source distribution and in the 
-&quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups.sl&quot;, or 
-&quot;libcups.so&quot; files in the binary distributions. </P>
-<P>The GNU GPL applies to the remainder of the CUPS distribution, 
-including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript 
-5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.90. </P>
-<P>For those not familiar with the GNU GPL, the license basically 
-allows you to: </P>
-<UL>
-<LI>Use the CUPS software at no charge. </LI>
-<LI>Distribute verbatim copies of the software in source or  binary 
-form. </LI>
-<LI>Sell verbatim copies of the software for a media fee, or  sell 
-support for the software. </LI>
-<LI>Distribute or sell printer drivers and filters that use  CUPS so 
-long as source code is made available under the GPL. </LI>
-</UL>
-<P>What this license <B>does not</B> allow you to do is make changes or 
-add features to CUPS and then sell a binary distribution without source 
-code. You must provide source for any new drivers, changes, or 
-additions to the software, and all code must be provided under the GPL 
-or LGPL as appropriate. </P>
-<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to 
-develop applications that use the CUPS API library under other licenses 
-and/or conditions as appropriate for your application. </P>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these
+ licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the
+ &quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups_s.a&quot;,
+ &quot;libcups.sl&quot;, or &quot;libcups.so&quot; files in the binary distributions.</P>
+<P>The GNU GPL applies to the remainder of the CUPS distribution,
+ including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript
+ 5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.93a.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
 <H3><A NAME="9_1_2">Trademarks</A></H3>
-<P>Easy Software Products has trademarked the Common UNIX Printing 
-System, CUPS, and CUPS logo. These names and logos may be used freely 
-in any direct port or binary distribution of CUPS. To use them in 
-derivative products, please contract Easy Software Products for written 
-permission. Our intention is to protect the value of these trademarks 
-and ensure that any derivative product meets the same high-quality 
-standards as the original. </P>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. These names and logos may be used freely
+ in any direct port or binary distribution of CUPS. To use them in
+ derivative products, please contract Easy Software Products for written
+ permission. Our intention is to protect the value of these trademarks
+ and ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
 <H3><A NAME="9_1_3">Binary Distribution Rights</A></H3>
-<P>Easy Software Products also sells rights to the CUPS source code 
-under a binary distribution license for vendors that are unable to 
-release source code for their drivers, additions, and modifications to 
-CUPS under the GNU GPL and LGPL. For information please contact us at 
-the address shown above. </P>
-<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that 
-utilizes the GNU GhostScript 5.50 core to convert PostScript files into 
-a stream of raster images. For binary distribution licensing of this 
-software, please contact: <BLOCKQUOTE> Miles Jones
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that
+ utilizes the GNU GhostScript 5.50 core to convert PostScript files into
+ a stream of raster images. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Miles Jones
 <BR> Director of Marketing
 <BR> Artifex Software Inc.
 <BR> 454 Las Gallinas Ave., Suite 108
 <BR> San Rafael, CA 94903 USA
 <BR> Voice: +1.415.492.9861
 <BR> Fax: +1.415.492.9862
-<BR> EMail: <A HREF="mailto:info@arsoft.com">info@arsoft.com</A></BLOCKQUOTE>
+<BR> EMail:<A HREF="mailto:info@arsoft.com"> info@arsoft.com</A></BLOCKQUOTE>
 </P>
-<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.90 software. For binary 
-distribution licensing of this software, please contact: <BLOCKQUOTE>
+<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.93a software. For binary
+ distribution licensing of this software, please contact:<BLOCKQUOTE>
  Derek B. Noonburg
-<BR> Email: <A HREF="mailto:derekn@foolabs.com">derekn@foolabs.com</A>
-<BR> WWW: <A HREF="http://www.foolabs.com/xpdf/">
-http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<BR> Email:<A HREF="mailto:derekn@foolabs.com"> derekn@foolabs.com</A>
+<BR> WWW:<A HREF="http://www.foolabs.com/xpdf/">
+ http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
 <H3><A NAME="9_1_4">Support</A></H3>
-<P>Easy Software Products sells software support for CUPS as well as a 
-commercial printing product based on CUPS called ESP Print Pro. You can 
-find out more at our web site: </P>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
 <UL>
 <PRE>
 <A HREF="http://www.easysw.com">http://www.easysw.com</A>
@@ -3306,7 +3437,7 @@ find out more at our web site: </P>
 
 <!-- NEW PAGE -->
 <H2><A NAME="9_2">GNU GENERAL PUBLIC LICENSE</A></H2>
-<P>Version 2, June 1991 </P>
+<P>Version 2, June 1991</P>
 <PRE>
 Copyright 1989, 1991 Free Software Foundation, Inc.
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -3318,252 +3449,250 @@ copies of this license document, but changing it is not allowed.
 
 </PRE>
 <H4>Preamble</H4>
-<P>The licenses for most software are designed to take away your 
-freedom to share and change it.  By contrast, the GNU General Public 
-License is intended to guarantee your freedom to share and change free 
-software--to make sure the software is free for all its users.  This 
-General Public License applies to most of the Free Software 
-Foundation's software and to any other program whose authors commit to 
-using it.  (Some other Free Software Foundation software is covered by 
-the GNU Library General Public License instead.)  You can apply it to 
-your programs, too. </P>
-<P>When we speak of free software, we are referring to freedom, not 
-price.  Our General Public Licenses are designed to make sure that you 
-have the freedom to distribute copies of free software (and charge for 
-this service if you wish), that you receive source code or can get it 
-if you want it, that you can change the software or use pieces of it in 
-new free programs; and that you know you can do these things. </P>
-<P>To protect your rights, we need to make restrictions that forbid 
-anyone to deny you these rights or to ask you to surrender the rights. 
-These restrictions translate to certain responsibilities for you if you 
-distribute copies of the software, or if you modify it. </P>
-<P>For example, if you distribute copies of such a program, whether 
-gratis or for a fee, you must give the recipients all the rights that 
-you have.  You must make sure that they, too, receive or can get the 
-source code.  And you must show them these terms so they know their 
-rights. </P>
-<P>We protect your rights with two steps: (1) copyright the software, 
-and (2) offer you this license which gives you legal permission to 
-copy, distribute and/or modify the software. </P>
-<P>Also, for each author's protection and ours, we want to make certain 
-that everyone understands that there is no warranty for this free 
-software.  If the software is modified by someone else and passed on, 
-we want its recipients to know that what they have is not the original, 
-so that any problems introduced by others will not reflect on the 
-original authors' reputations. </P>
-<P>Finally, any free program is threatened constantly by software 
-patents.  We wish to avoid the danger that redistributors of a free 
-program will individually obtain patent licenses, in effect making the 
-program proprietary.  To prevent this, we have made it clear that any 
-patent must be licensed for everyone's free use or not licensed at all. </P>
-<P>The precise terms and conditions for copying, distribution and 
-modification follow. </P>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
 <H4>GNU GENERAL PUBLIC LICENSE
 <BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
 <OL START="0">
-<LI>This License applies to any program or other work which contains a 
-notice placed by the copyright holder saying it may be distributed 
-under the terms of this General Public License.  The &quot;Program&quot;, below, 
-refers to any such program or work, and a &quot;work based on the Program&quot; 
-means either the Program or any derivative work under copyright law: 
-that is to say, a work containing the Program or a portion of it, 
-either verbatim or with modifications and/or translated into another 
-language.  (Hereinafter, translation is included without limitation in 
-the term &quot;modification&quot;.)  Each licensee is addressed as &quot;you&quot;. </LI>
-<P>Activities other than copying, distribution and modification are not 
-covered by this License; they are outside its scope.  The act of 
-running the Program is not restricted, and the output from the Program 
-is covered only if its contents constitute a work based on the Program 
-(independent of having been made by running the Program). Whether that 
-is true depends on what the Program does. </P>
-<LI>You may copy and distribute verbatim copies of the Program's source 
-code as you receive it, in any medium, provided that you conspicuously 
-and appropriately publish on each copy an appropriate copyright notice 
-and disclaimer of warranty; keep intact all the notices that refer to 
-this License and to the absence of any warranty; and give any other 
-recipients of the Program a copy of this License along with the 
-Program. </LI>
-<P>You may charge a fee for the physical act of transferring a copy, 
-and you may at your option offer warranty protection in exchange for a 
-fee. </P>
-<LI>You may modify your copy or copies of the Program or any portion of 
-it, thus forming a work based on the Program, and copy and distribute 
-such modifications or work under the terms of Section 1 above, provided 
-that you also meet all of these conditions: 
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.</LI>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.</LI>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
 <OL TYPE="a">
-<LI>You must cause the modified files to carry prominent notices 
-stating that you changed the files and the date of any change. </LI>
-<LI>You must cause any work that you distribute or publish, that in 
-whole or in part contains or is derived from the Program or any part 
-thereof, to be licensed as a whole at no charge to all third parties 
-under the terms of this License. </LI>
-<LI>if the modified program normally reads commands interactively when 
-run, you must cause it, when started running for such interactive use 
-in the most ordinary way, to print or display an announcement including 
-an appropriate copyright notice and a notice that there is no warranty 
-(or else, saying that you provide a warranty) and that users may 
-redistribute the program under these conditions, and telling the user 
-how to view a copy of this License.  (Exception: if the Program itself 
-is interactive but does not normally print such an announcement, your 
-work based on the Program is not required to print an announcement.) </LI>
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
 </OL>
 </LI>
-<P>These requirements apply to the modified work as a whole.  If 
-identifiable sections of that work are not derived from the Program, 
-and can be reasonably considered independent and separate works in 
-themselves, then this License, and its terms, do not apply to those 
-sections when you distribute them as separate works.  But when you 
-distribute the same sections as part of a whole which is a work based 
-on the Program, the distribution of the whole must be on the terms of 
-this License, whose permissions for other licensees extend to the 
-entire whole, and thus to each and every part regardless of who wrote 
-it. </P>
-<P>Thus, it is not the intent of this section to claim rights or 
-contest your rights to work written entirely by you; rather, the intent 
-is to exercise the right to control the distribution of derivative or 
-collective works based on the Program. </P>
-<P>In addition, mere aggregation of another work not based on the 
-Program with the Program (or with a work based on the Program) on a 
-volume of a storage or distribution medium does not bring the other 
-work under the scope of this License. </P>
-<LI>You may copy and distribute the Program (or a work based on it, 
-under Section 2) in object code or executable form under the terms of 
-Sections 1 and 2 above provided that you also do one of the following: 
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
 <OL TYPE="a">
-<LI>Accompany it with the complete corresponding machine-readable 
-source code, which must be distributed under the terms of Sections 1 
-and 2 above on a medium customarily used for software interchange; or, </LI>
-<LI>Accompany it with a written offer, valid for at least three years, 
-to give any third party, for a charge no more than your cost of 
-physically performing source distribution, a complete machine-readable 
-copy of the corresponding source code, to be distributed under the 
-terms of Sections 1 and 2 above on a medium customarily used for 
-software interchange; or, </LI>
-<LI>Accompany it with the information you received as to the offer to 
-distribute corresponding source code.  (This alternative is allowed 
-only for noncommercial distribution and only if you received the 
-program in object code or executable form with such an offer, in accord 
-with Subsection b above.) </LI>
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
 </OL>
 </LI>
-<P>The source code for a work means the preferred form of the work for 
-making modifications to it.  For an executable work, complete source 
-code means all the source code for all modules it contains, plus any 
-associated interface definition files, plus the scripts used to control 
-compilation and installation of the executable.  However, as a special 
-exception, the source code distributed need not include anything that 
-is normally distributed (in either source or binary form) with the 
-major components (compiler, kernel, and so on) of the operating system 
-on which the executable runs, unless that component itself accompanies 
-the executable. </P>
-<P>If distribution of executable or object code is made by offering 
-access to copy from a designated place, then offering equivalent access 
-to copy the source code from the same place counts as distribution of 
-the source code, even though third parties are not compelled to copy 
-the source along with the object code. </P>
-<LI>You may not copy, modify, sublicense, or distribute the Program 
-except as expressly provided under this License.  Any attempt otherwise 
-to copy, modify, sublicense or distribute the Program is void, and will 
-automatically terminate your rights under this License. However, 
-parties who have received copies, or rights, from you under this 
-License will not have their licenses terminated so long as such parties 
-remain in full compliance. </LI>
-<LI>You are not required to accept this License, since you have not 
-signed it.  However, nothing else grants you permission to modify or 
-distribute the Program or its derivative works.  These actions are 
-prohibited by law if you do not accept this License.  Therefore, by 
-modifying or distributing the Program (or any work based on the 
-Program), you indicate your acceptance of this License to do so, and 
-all its terms and conditions for copying, distributing or modifying the 
-Program or works based on it. </LI>
-<LI>Each time you redistribute the Program (or any work based on the 
-Program), the recipient automatically receives a license from the 
-original licensor to copy, distribute or modify the Program subject to 
-these terms and conditions.  You may not impose any further 
-restrictions on the recipients' exercise of the rights granted herein. 
-You are not responsible for enforcing compliance by third parties to 
-this License. </LI>
-<LI>If, as a consequence of a court judgment or allegation of patent 
-infringement or for any other reason (not limited to patent issues), 
-conditions are imposed on you (whether by court order, agreement or 
-otherwise) that contradict the conditions of this License, they do not 
-excuse you from the conditions of this License.  If you cannot 
-distribute so as to satisfy simultaneously your obligations under this 
-License and any other pertinent obligations, then as a consequence you 
-may not distribute the Program at all.  For example, if a patent 
-license would not permit royalty-free redistribution of the Program by 
-all those who receive copies directly or indirectly through you, then 
-the only way you could satisfy both it and this License would be to 
-refrain entirely from distribution of the Program. </LI>
-<P>If any portion of this section is held invalid or unenforceable 
-under any particular circumstance, the balance of the section is 
-intended to apply and the section as a whole is intended to apply in 
-other circumstances. </P>
-<P>It is not the purpose of this section to induce you to infringe any 
-patents or other property right claims or to contest validity of any 
-such claims; this section has the sole purpose of protecting the 
-integrity of the free software distribution system, which is 
-implemented by public license practices.  Many people have made 
-generous contributions to the wide range of software distributed 
-through that system in reliance on consistent application of that 
-system; it is up to the author/donor to decide if he or she is willing 
-to distribute software through any other system and a licensee cannot 
-impose that choice. </P>
-<P>This section is intended to make thoroughly clear what is believed 
-to be a consequence of the rest of this License. </P>
-<LI>If the distribution and/or use of the Program is restricted in 
-certain countries either by patents or by copyrighted interfaces, the 
-original copyright holder who places the Program under this License may 
-add an explicit geographical distribution limitation excluding those 
-countries, so that distribution is permitted only in or among countries 
-not thus excluded.  In such case, this License incorporates the 
-limitation as if written in the body of this License. </LI>
-<LI>The Free Software Foundation may publish revised and/or new 
-versions of the General Public License from time to time.  Such new 
-versions will be similar in spirit to the present version, but may 
-differ in detail to address new problems or concerns. </LI>
-<P>Each version is given a distinguishing version number.  If the 
-Program specifies a version number of this License which applies to it 
-and &quot;any later version&quot;, you have the option of following the terms and 
-conditions either of that version or of any later version published by 
-the Free Software Foundation.  If the Program does not specify a 
-version number of this License, you may choose any version ever 
-published by the Free Software Foundation. </P>
-<LI>If you wish to incorporate parts of the Program into other free 
-programs whose distribution conditions are different, write to the 
-author to ask for permission.  For software which is copyrighted by the 
-Free Software Foundation, write to the Free Software Foundation; we 
-sometimes make exceptions for this.  Our decision will be guided by the 
-two goals of preserving the free status of all derivatives of our free 
-software and of promoting the sharing and reuse of software generally. </LI>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.</LI>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.</LI>
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
 </OL>
 <H4>NO WARRANTY</H4>
 <OL START="11">
-<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO 
-WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
- EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
-OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, 
-EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
- THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS 
-WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </LI>
-<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 
-AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU 
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 
-PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 
-FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF 
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
-DAMAGES. </LI>
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
 </OL>
 <H4>END OF TERMS AND CONDITIONS</H4>
 
 <!-- NEW PAGE -->
 <H2><A NAME="9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
-<P>Version 2, June 1991 </P>
+<P>Version 2, June 1991</P>
 <PRE>
 Copyright (C) 1991 Free Software Foundation, Inc.
 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
@@ -3574,400 +3703,396 @@ of this license document, but changing it is not allowed.
  numbered 2 because it goes with version 2 of the ordinary GPL.]
 </PRE>
 <H4>Preamble</H4>
-<P>The licenses for most software are designed to take away your 
-freedom to share and change it.  By contrast, the GNU General Public 
-Licenses are intended to guarantee your freedom to share and change 
-free software--to make sure the software is free for all its users. </P>
-<P>This license, the Library General Public License, applies to some 
-specially designated Free Software Foundation software, and to any 
-other libraries whose authors decide to use it.  You can use it for 
-your libraries, too. </P>
-<P>When we speak of free software, we are referring to freedom, not 
-price.  Our General Public Licenses are designed to make sure that you 
-have the freedom to distribute copies of free software (and charge for 
-this service if you wish), that you receive source code or can get it 
-if you want it, that you can change the software or use pieces of it in 
-new free programs; and that you know you can do these things. </P>
-<P>To protect your rights, we need to make restrictions that forbid 
-anyone to deny you these rights or to ask you to surrender the rights. 
-These restrictions translate to certain responsibilities for you if you 
-distribute copies of the library, or if you modify it. </P>
-<P>For example, if you distribute copies of the library, whether gratis 
-or for a fee, you must give the recipients all the rights that we gave 
-you.  You must make sure that they, too, receive or can get the source 
-code.  If you link a program with the library, you must provide 
-complete object files to the recipients so that they can relink them 
-with the library, after making changes to the library and recompiling 
-it.  And you must show them these terms so they know their rights. </P>
-<P>Our method of protecting your rights has two steps: (1) copyright 
-the library, and (2) offer you this license which gives you legal 
-permission to copy, distribute and/or modify the library. </P>
-<P>Also, for each distributor's protection, we want to make certain 
-that everyone understands that there is no warranty for this free 
-library.  If the library is modified by someone else and passed on, we 
-want its recipients to know that what they have is not the original 
-version, so that any problems introduced by others will not reflect on 
-the original authors' reputations. </P>
-<P>Finally, any free program is threatened constantly by software 
-patents.  We wish to avoid the danger that companies distributing free 
-software will individually obtain patent licenses, thus in effect 
-transforming the program into proprietary software.  To prevent this, 
-we have made it clear that any patent must be licensed for everyone's 
-free use or not licensed at all. </P>
-<P>Most GNU software, including some libraries, is covered by the 
-ordinary GNU General Public License, which was designed for utility 
-programs.  This license, the GNU Library General Public License, 
-applies to certain designated libraries.  This license is quite 
-different from the ordinary one; be sure to read it in full, and don't 
-assume that anything in it is the same as in the ordinary license. </P>
-<P>The reason we have a separate public license for some libraries is 
-that they blur the distinction we usually make between modifying or 
-adding to a program and simply using it.  Linking a program with a 
-library, without changing the library, is in some sense simply using 
-the library, and is analogous to running a utility program or 
-application program.  However, in a textual and legal sense, the linked 
-executable is a combined work, a derivative of the original library, 
-and the ordinary General Public License treats it as such. </P>
-<P>Because of this blurred distinction, using the ordinary General 
-Public License for libraries did not effectively promote software 
-sharing, because most developers did not use the libraries.  We 
-concluded that weaker conditions might promote sharing better. </P>
-<P>However, unrestricted linking of non-free programs would deprive the 
-users of those programs of all benefit from the free status of the 
-libraries themselves.  This Library General Public License is intended 
-to permit developers of non-free programs to use free libraries, while 
-preserving your freedom as a user of such programs to change the free 
-libraries that are incorporated in them.  (We have not seen how to 
-achieve this as regards changes in header files, but we have achieved 
-it as regards changes in the actual functions of the Library.)  The 
-hope is that this will lead to faster development of free libraries. </P>
-<P>The precise terms and conditions for copying, distribution and 
-modification follow.  Pay close attention to the difference between a 
-&quot;work based on the library&quot; and a &quot;work that uses the library&quot;.  The 
-former contains code derived from the library, while the latter only 
-works together with the library. </P>
-<P>Note that it is possible for a library to be covered by the ordinary 
-General Public License rather than by this special one. </P>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
 <H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
-<P><STRONG>0.</STRONG> This License Agreement applies to any software 
-library which contains a notice placed by the copyright holder or other 
-authorized party saying it may be distributed under the terms of this 
-Library General Public License (also called &quot;this License&quot;).  Each 
-licensee is addressed as &quot;you&quot;. </P>
-<P>A &quot;library&quot; means a collection of software functions and/or data 
-prepared so as to be conveniently linked with application programs 
-(which use some of those functions and data) to form executables. </P>
-<P>The &quot;Library&quot;, below, refers to any such software library or work 
-which has been distributed under these terms.  A &quot;work based on the 
-Library&quot; means either the Library or any derivative work under 
-copyright law: that is to say, a work containing the Library or a 
-portion of it, either verbatim or with modifications and/or translated 
-straightforwardly into another language.  (Hereinafter, translation is 
-included without limitation in the term &quot;modification&quot;.) </P>
-<P>&quot;Source code&quot; for a work means the preferred form of the work for 
-making modifications to it.  For a library, complete source code means 
-all the source code for all modules it contains, plus any associated 
-interface definition files, plus the scripts used to control 
-compilation and installation of the library. </P>
-<P>Activities other than copying, distribution and modification are not 
-covered by this License; they are outside its scope.  The act of 
-running a program using the Library is not restricted, and output from 
-such a program is covered only if its contents constitute a work based 
-on the Library (independent of the use of the Library in a tool for 
-writing it).  Whether that is true depends on what the Library does and 
-what the program that uses the Library does. </P>
-<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of 
-the Library's complete source code as you receive it, in any medium, 
-provided that you conspicuously and appropriately publish on each copy 
-an appropriate copyright notice and disclaimer of warranty; keep intact 
-all the notices that refer to this License and to the absence of any 
-warranty; and distribute a copy of this License along with the Library. </P>
-<P>You may charge a fee for the physical act of transferring a copy, 
-and you may at your option offer warranty protection in exchange for a 
-fee. </P>
-<P><STRONG>2.</STRONG> You may modify your copy or copies of the 
-Library or any portion of it, thus forming a work based on the Library, 
-and copy and distribute such modifications or work under the terms of 
-Section 1 above, provided that you also meet all of these conditions: </P>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
 <OL TYPE="a">
-<LI>The modified work must itself be a software library. </LI>
+<LI>The modified work must itself be a software library.</LI>
 <P></P>
-<LI>You must cause the files modified to carry prominent notices 
stating that you changed the files and the date of any change. </LI>
+<LI>You must cause the files modified to carry prominent notices stating
that you changed the files and the date of any change.</LI>
 <P></P>
-<LI>You must cause the whole of the work to be licensed at no  charge 
-to all third parties under the terms of this License. </LI>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.</LI>
 <P></P>
-<LI>If a facility in the modified Library refers to a function or a 
- table of data to be supplied by an application program that uses  the 
-facility, other than as an argument passed when the facility  is 
-invoked, then you must make a good faith effort to ensure that,  in the 
-event an application does not supply such function or  table, the 
-facility still operates, and performs whatever part of  its purpose 
-remains meaningful. </LI>
-<P>(For example, a function in a library to compute square roots has  a 
-purpose that is entirely well-defined independent of the  application. 
- Therefore, Subsection 2d requires that any  application-supplied 
-function or table used by this function must  be optional: if the 
-application does not supply it, the square  root function must still 
-compute square roots.) </P>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.</LI>
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
 </OL>
-<P>These requirements apply to the modified work as a whole.  If 
-identifiable sections of that work are not derived from the Library, 
-and can be reasonably considered independent and separate works in 
-themselves, then this License, and its terms, do not apply to those 
-sections when you distribute them as separate works.  But when you 
-distribute the same sections as part of a whole which is a work based 
-on the Library, the distribution of the whole must be on the terms of 
-this License, whose permissions for other licensees extend to the 
-entire whole, and thus to each and every part regardless of who wrote 
-it. </P>
-<P>Thus, it is not the intent of this section to claim rights or 
-contest your rights to work written entirely by you; rather, the intent 
-is to exercise the right to control the distribution of derivative or 
-collective works based on the Library. </P>
-<P>In addition, mere aggregation of another work not based on the 
-Library with the Library (or with a work based on the Library) on a 
-volume of a storage or distribution medium does not bring the other 
-work under the scope of this License. </P>
-<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary 
-GNU General Public License instead of this License to a given copy of 
-the Library.  To do this, you must alter all the notices that refer to 
-this License, so that they refer to the ordinary GNU General Public 
-License, version 2, instead of to this License.  (If a newer version 
-than version 2 of the ordinary GNU General Public License has appeared, 
-then you can specify that version instead if you wish.)  Do not make 
-any other change in these notices. </P>
-<P>Once this change is made in a given copy, it is irreversible for 
-that copy, so the ordinary GNU General Public License applies to all 
-subsequent copies and derivative works made from that copy. </P>
-<P>This option is useful when you wish to copy part of the code of the 
-Library into a program that is not a library. </P>
-<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a 
-portion or derivative of it, under Section 2) in object code or 
-executable form under the terms of Sections 1 and 2 above provided that 
-you accompany it with the complete corresponding machine-readable 
-source code, which must be distributed under the terms of Sections 1 
-and 2 above on a medium customarily used for software interchange. </P>
-<P>If distribution of object code is made by offering access to copy 
-from a designated place, then offering equivalent access to copy the 
-source code from the same place satisfies the requirement to distribute 
-the source code, even though third parties are not compelled to copy 
-the source along with the object code. </P>
-<P><STRONG>5.</STRONG> A program that contains no derivative of any 
-portion of the Library, but is designed to work with the Library by 
-being compiled or linked with it, is called a &quot;work that uses the 
-Library&quot;.  Such a work, in isolation, is not a derivative work of the 
-Library, and therefore falls outside the scope of this License. </P>
-<P>However, linking a &quot;work that uses the Library&quot; with the Library 
-creates an executable that is a derivative of the Library (because it 
-contains portions of the Library), rather than a &quot;work that uses the 
-library&quot;.  The executable is therefore covered by this License. Section 
-6 states terms for distribution of such executables. </P>
-<P>When a &quot;work that uses the Library&quot; uses material from a header file 
-that is part of the Library, the object code for the work may be a 
-derivative work of the Library even though the source code is not. 
-Whether this is true is especially significant if the work can be 
-linked without the Library, or if the work is itself a library.  The 
-threshold for this to be true is not precisely defined by law. </P>
-<P>If such an object file uses only numerical parameters, data 
-structure layouts and accessors, and small macros and small inline 
-functions (ten lines or less in length), then the use of the object 
-file is unrestricted, regardless of whether it is legally a derivative 
-work.  (Executables containing this object code plus portions of the 
-Library will still fall under Section 6.) </P>
-<P>Otherwise, if the work is a derivative of the Library, you may 
-distribute the object code for the work under the terms of Section 6. 
-Any executables containing that work also fall under Section 6, whether 
-or not they are linked directly with the Library itself. </P>
-<P><STRONG>6.</STRONG> As an exception to the Sections above, you may 
-also compile or link a &quot;work that uses the Library&quot; with the Library to 
-produce a work containing portions of the Library, and distribute that 
-work under terms of your choice, provided that the terms permit 
-modification of the work for the customer's own use and reverse 
-engineering for debugging such modifications. </P>
-<P>You must give prominent notice with each copy of the work that the 
-Library is used in it and that the Library and its use are covered by 
-this License.  You must supply a copy of this License.  If the work 
-during execution displays copyright notices, you must include the 
-copyright notice for the Library among them, as well as a reference 
-directing the user to the copy of this License.  Also, you must do one 
-of these things: </P>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
 <OL TYPE="a">
-<LI>Accompany the work with the complete corresponding 
- machine-readable source code for the Library including whatever 
- changes were used in the work (which must be distributed under 
- Sections 1 and 2 above); and, if the work is an executable linked 
- with the Library, with the complete machine-readable &quot;work that  uses 
-the Library&quot;, as object code and/or source code, so that the  user can 
-modify the Library and then relink to produce a modified  executable 
-containing the modified Library.  (It is understood  that the user who 
-changes the contents of definitions files in the  Library will not 
-necessarily be able to recompile the application  to use the modified 
-definitions.) </LI>
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)</LI>
 <P></P>
-<LI>Accompany the work with a written offer, valid for at  least three 
-years, to give the same user the materials  specified in Subsection 6a, 
-above, for a charge no more  than the cost of performing this 
-distribution. </LI>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.</LI>
 <P></P>
-<LI>If distribution of the work is made by offering access to copy 
- from a designated place, offer equivalent access to copy the above 
specified materials from the same place. </LI>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
materials from the same place.</LI>
 <P></P>
-<LI>Verify that the user has already received a copy of these 
materials or that you have already sent this user a copy. </LI>
+<LI>Verify that the user has already received a copy of these materials
or that you have already sent this user a copy.</LI>
 </OL>
-<P>For an executable, the required form of the &quot;work that uses the 
-Library&quot; must include any data and utility programs needed for 
-reproducing the executable from it.  However, as a special exception, 
-the source code distributed need not include anything that is normally 
-distributed (in either source or binary form) with the major components 
-(compiler, kernel, and so on) of the operating system on which the 
-executable runs, unless that component itself accompanies the 
-executable. </P>
-<P>It may happen that this requirement contradicts the license 
-restrictions of other proprietary libraries that do not normally 
-accompany the operating system.  Such a contradiction means you cannot 
-use both them and the Library together in an executable that you 
-distribute. </P>
-<P><STRONG>7.</STRONG> You may place library facilities that are a work 
-based on the Library side-by-side in a single library together with 
-other library facilities not covered by this License, and distribute 
-such a combined library, provided that the separate distribution of the 
-work based on the Library and of the other library facilities is 
-otherwise permitted, and provided that you do these two things: </P>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
 <OL TYPE="a">
-<LI>Accompany the combined library with a copy of the same work  based 
-on the Library, uncombined with any other library  facilities.  This 
-must be distributed under the terms of the  Sections above. </LI>
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.</LI>
 <P></P>
-<LI>Give prominent notice with the combined library of the fact  that 
-part of it is a work based on the Library, and explaining  where to 
-find the accompanying uncombined form of the same work. </LI>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
 </OL>
-<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with, 
-or distribute the Library except as expressly provided under this 
-License.  Any attempt otherwise to copy, modify, sublicense, link with, 
-or distribute the Library is void, and will automatically terminate 
-your rights under this License.  However, parties who have received 
-copies, or rights, from you under this License will not have their 
-licenses terminated so long as such parties remain in full compliance. </P>
-<P><STRONG>9.</STRONG> You are not required to accept this License, 
-since you have not signed it.  However, nothing else grants you 
-permission to modify or distribute the Library or its derivative works. 
- These actions are prohibited by law if you do not accept this License. 
- Therefore, by modifying or distributing the Library (or any work based 
-on the Library), you indicate your acceptance of this License to do so, 
-and all its terms and conditions for copying, distributing or modifying 
-the Library or works based on it. </P>
-<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any 
-work based on the Library), the recipient automatically receives a 
-license from the original licensor to copy, distribute, link with or 
-modify the Library subject to these terms and conditions.  You may not 
-impose any further restrictions on the recipients' exercise of the 
-rights granted herein. You are not responsible for enforcing compliance 
-by third parties to this License. </P>
-<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or 
-allegation of patent infringement or for any other reason (not limited 
-to patent issues), conditions are imposed on you (whether by court 
-order, agreement or otherwise) that contradict the conditions of this 
-License, they do not excuse you from the conditions of this License. 
- If you cannot distribute so as to satisfy simultaneously your 
-obligations under this License and any other pertinent obligations, 
-then as a consequence you may not distribute the Library at all.  For 
-example, if a patent license would not permit royalty-free 
-redistribution of the Library by all those who receive copies directly 
-or indirectly through you, then the only way you could satisfy both it 
-and this License would be to refrain entirely from distribution of the 
-Library. </P>
-<P>If any portion of this section is held invalid or unenforceable 
-under any particular circumstance, the balance of the section is 
-intended to apply, and the section as a whole is intended to apply in 
-other circumstances. </P>
-<P>It is not the purpose of this section to induce you to infringe any 
-patents or other property right claims or to contest validity of any 
-such claims; this section has the sole purpose of protecting the 
-integrity of the free software distribution system which is implemented 
-by public license practices.  Many people have made generous 
-contributions to the wide range of software distributed through that 
-system in reliance on consistent application of that system; it is up 
-to the author/donor to decide if he or she is willing to distribute 
-software through any other system and a licensee cannot impose that 
-choice. </P>
-<P>This section is intended to make thoroughly clear what is believed 
-to be a consequence of the rest of this License. </P>
-<P><STRONG>12.</STRONG> If the distribution and/or use of the Library 
-is restricted in certain countries either by patents or by copyrighted 
-interfaces, the original copyright holder who places the Library under 
-this License may add an explicit geographical distribution limitation 
-excluding those countries, so that distribution is permitted only in or 
-among countries not thus excluded.  In such case, this License 
-incorporates the limitation as if written in the body of this License. </P>
-<P><STRONG>13.</STRONG> The Free Software Foundation may publish 
-revised and/or new versions of the Library General Public License from 
-time to time. Such new versions will be similar in spirit to the 
-present version, but may differ in detail to address new problems or 
-concerns. </P>
-<P>Each version is given a distinguishing version number.  If the 
-Library specifies a version number of this License which applies to it 
-and &quot;any later version&quot;, you have the option of following the terms and 
-conditions either of that version or of any later version published by 
-the Free Software Foundation.  If the Library does not specify a 
-license version number, you may choose any version ever published by 
-the Free Software Foundation. </P>
-<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library 
-into other free programs whose distribution conditions are incompatible 
-with these, write to the author to ask for permission.  For software 
-which is copyrighted by the Free Software Foundation, write to the Free 
-Software Foundation; we sometimes make exceptions for this.  Our 
-decision will be guided by the two goals of preserving the free status 
-of all derivatives of our free software and of promoting the sharing 
-and reuse of software generally. </P>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
 <P><STRONG>NO WARRANTY</STRONG></P>
-<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, 
-THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY 
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT 
-WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT 
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
-PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE 
-OF THE LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU 
-ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </P>
-<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW 
-OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY 
-WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE 
-LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL 
-OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
-DAMAGES. </P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
 <H4>END OF TERMS AND CONDITIONS</H4>
 <H1 ALIGN="RIGHT"><A NAME="COMMON_NETWORK">B - Common Network Settings</A>
 </H1>
-<P>This appendix covers many of the popular TCP/IP network interfaces 
-and printer servers available on the market today. </P>
+<P>This appendix covers many of the popular TCP/IP network interfaces
+ and printer servers available on the market today.</P>
 <H2><A NAME="10_1">Configuring a Network Interface</A></H2>
-<P>When you first install a network printer or print server on your 
-LAN, you need to set the Internet Protocol (&quot;IP&quot;) address. On most 
-higher-end &quot;workgroup&quot; printers, you can set the address through the 
-printer control panel. However, in most cases you will want to assign 
-the addresses remotely from your workstation. This makes administration 
-a bit easier and avoids assigning duplicate addresses accidentally. </P>
-<P>To setup your printer or print server for remote address assignment, 
-you'll need the Ethernet Media Access Control (&quot;MAC&quot;) address, also 
-sometimes called a node address, and the IP address you want to use for 
-the device. The Ethernet MAC address can often be found on the printer 
-test page or bottom of the print server. 
+<P>When you first install a network printer or print server on your LAN,
+ you need to set the Internet Protocol (&quot;IP&quot;) address. On most
+ higher-end &quot;workgroup&quot; printers, you can set the address through the
+ printer control panel. However, in most cases you will want to assign
+ the addresses remotely from your workstation. This makes administration
+ a bit easier and avoids assigning duplicate addresses accidentally.</P>
+<P>To setup your printer or print server for remote address assignment,
+ you'll need the Ethernet Media Access Control (&quot;MAC&quot;) address, also
+ sometimes called a node address, and the IP address you want to use for
+ the device. The Ethernet MAC address can often be found on the printer
+ test page or bottom of the print server.
 <!-- NEED 3in -->
 </P>
 <H3><A NAME="10_1_1">Configuring the IP Address Using ARP</A></H3>
-<P>The easiest way to set the IP address of a network device is to use 
-the <CODE>arp(8)</CODE> command.  The <CODE>arp</CODE> sends an Address 
-Resolution Protocol (&quot;ARP&quot;) packet to the specified Ethernet MAC 
-address, setting the network device's IP address: </P>
+<P>The easiest way to set the IP address of a network device is to use
+ the <CODE>arp(8)</CODE> command. The <CODE>arp</CODE> sends an Address
+ Resolution Protocol (&quot;ARP&quot;) packet to the specified Ethernet MAC
+ address, setting the network device's IP address:</P>
 <UL>
 <PRE>
 <B>arp -s ip-address ethernet-address ENTER</B>
@@ -3976,50 +4101,50 @@ address, setting the network device's IP address: </P>
 </PRE>
 </UL>
 <H3><A NAME="10_1_2">Configuring the IP Address Using RARP</A></H3>
-<P>The most flexible way to remotely assign IP addresses under UNIX is 
-through the Reverse Address Resolution Protocol (&quot;RARP&quot;). RARP allows a 
-network device to request an IP address using its Ethernet MAC address, 
-and one or more RARP servers on the network will respond with an ARP 
-packet with the IP address the device can use. </P>
-<P>RARP should be used when you have to manage many printers or print 
-servers, or when you have a network device that does not remember its 
-IP address after a power cycle. If you just have a single printer or 
-print server, the <CODE>arp</CODE> command is the way to go. </P>
+<P>The most flexible way to remotely assign IP addresses under UNIX is
+ through the Reverse Address Resolution Protocol (&quot;RARP&quot;). RARP allows a
+ network device to request an IP address using its Ethernet MAC address,
+ and one or more RARP servers on the network will respond with an ARP
+ packet with the IP address the device can use.</P>
+<P>RARP should be used when you have to manage many printers or print
+ servers, or when you have a network device that does not remember its
+ IP address after a power cycle. If you just have a single printer or
+ print server, the <CODE>arp</CODE> command is the way to go.</P>
 <P>Some UNIX operating systems use a program called <CODE>rarpd(8)</CODE>
- to manage RARP. Others, like Linux, support this protocol in the 
-kernel. For systems that provide the <CODE>rarpd</CODE> program you 
-will need to start it before RARP lookups will work: </P>
+ to manage RARP. Others, like Linux, support this protocol in the
+ kernel. For systems that provide the <CODE>rarpd</CODE> program you
+ will need to start it before RARP lookups will work:</P>
 <UL>
 <PRE>
 <B>rarpd ENTER</B>
 </PRE>
 </UL>
-<P>Under IRIX you can enable this functionality by default using: </P>
+<P>Under IRIX you can enable this functionality by default using:</P>
 <UL>
 <PRE>
 <B>chkconfig rarpd on ENTER</B>
 </PRE>
 </UL>
-<P>Both the <CODE>rarpd</CODE> program and kernel RARP support read a 
-list of Ethernet and IP addresses from the file <VAR>/etc/ethers</VAR>. 
-Each line contains the Ethernet address (colon delimited) followed by 
-an IP address or hostname like: </P>
+<P>Both the <CODE>rarpd</CODE> program and kernel RARP support read a
+ list of Ethernet and IP addresses from the file<VAR> /etc/ethers</VAR>.
+ Each line contains the Ethernet address (colon delimited) followed by
+ an IP address or hostname like:</P>
 <UL>
 <PRE>
 08:00:69:00:12:34 myprinter.mydomain.com
 08:00:69:00:12:34 192.0.2.2
 </PRE>
 </UL>
-<P>Add a line to this file and cycle the power on the printer or print 
-server to set its address. 
+<P>Add a line to this file and cycle the power on the printer or print
+ server to set its address.
 <!-- NEED 2in -->
 </P>
 <H3><A NAME="10_1_3">Configuring the IP Address Using BOOTP</A></H3>
-<P>The BOOTP protocol is used when you need to provide additional 
-information such as the location of a configuration file to the network 
-interface. Using the standard <CODE>bootpd(8)</CODE> program supplied 
-with UNIX you simply need to add a line to the <VAR>/etc/bootptab</VAR>
- file; for IRIX: </P>
+<P>The BOOTP protocol is used when you need to provide additional
+ information such as the location of a configuration file to the network
+ interface. Using the standard <CODE>bootpd(8)</CODE> program supplied
+ with UNIX you simply need to add a line to the<VAR> /etc/bootptab</VAR>
+ file; for IRIX:</P>
 <UL>
 <PRE>
 myprinter 08:00:69:00:12:34 192.0.2.2 <VAR>myprinter.boot</VAR>
@@ -4027,36 +4152,36 @@ myprinter 08:00:69:00:12:34 192.0.2.2 <VAR>myprinter.boot</VAR>
 </UL>
 
 <!-- NEED 1in -->
-<P>Newer versions of <CODE>bootpd</CODE> use a different format: </P>
+<P>Newer versions of <CODE>bootpd</CODE> use a different format:</P>
 <UL>
 <PRE>
 myprinter:ha=080069001234:ip=192.0.2.2:<VAR>t144=myprinter.boot</VAR>
 </PRE>
 </UL>
-<P>The <VAR>myprinter.boot</VAR> file resides in the <VAR>
-/usr/local/boot</VAR> directory by default. If you do not need to 
-provide a boot file you may leave the last part of the line blank. 
+<P>The<VAR> myprinter.boot</VAR> file resides in the<VAR>
+ /usr/local/boot</VAR> directory by default. If you do not need to
+ provide a boot file you may leave the last part of the line blank.
 <!-- NEED 2in -->
 
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>Some versions of UNIX do not enable the BOOTP service by  default. 
-The <VAR>/etc/inetd.conf</VAR> usually contains a  line for the BOOTP 
-service that can be uncommented if  needed. </P>
+<P>Some versions of UNIX do not enable the BOOTP service by default. The<VAR>
+ /etc/inetd.conf</VAR> usually contains a line for the BOOTP service
+ that can be uncommented if needed.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H2><A NAME="10_2">Verifying the Printer Connection</A></H2>
-<P>To test that the IP address has been successfully assigned and that 
-the printer is properly connected to your LAN, type: </P>
+<P>To test that the IP address has been successfully assigned and that
+ the printer is properly connected to your LAN, type:</P>
 <UL>
 <PRE>
 <B>ping ip-address ENTER</B>
 </PRE>
 </UL>
-<P>If the connection is working properly you will see something like: </P>
+<P>If the connection is working properly you will see something like:</P>
 <UL>
 <PRE>
 <B>ping myprinter ENTER</B>
@@ -4067,21 +4192,21 @@ PING myprinter (192.0.2.2): 56 data bytes
 64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
 </PRE>
 </UL>
-<P>If not, verify that the printer or print server is connected to the 
-LAN, it is powered on, the LAN cabling is good, and the IP address is 
-set correctly. You can usually see the current IP address and network 
-status by printing a configuration or test page on the device. 
+<P>If not, verify that the printer or print server is connected to the
+ LAN, it is powered on, the LAN cabling is good, and the IP address is
+ set correctly. You can usually see the current IP address and network
+ status by printing a configuration or test page on the device.
 <!-- NEED 4in -->
 </P>
 <H2><A NAME="10_3">Common Network Interface Settings</A></H2>
-<P>Once you have set the IP address you can access the printer or print 
-server using the <CODE>ipp</CODE>, <CODE>lpd</CODE>, or <CODE>socket</CODE>
- backends. The following is a list of common network interfaces and 
-printer servers and the settings you should use with CUPS: 
+<P>Once you have set the IP address you can access the printer or print
+ server using the <CODE>ipp</CODE>, <CODE>lpd</CODE>, or <CODE>socket</CODE>
+ backends. The following is a list of common network interfaces and
+ printer servers and the settings you should use with CUPS:
 <CENTER>
 <TABLE BORDER="1">
-<TR ALIGN="LEFT" VALIGN="TOP"><TH>Model/Manufacturer</TH><TH>Device 
-URI(s)</TH></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TH>Model/Manufacturer</TH><TH>Device
+ URI(s)</TH></TR>
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Apple LaserWriter</TD><TD>lpd://<I>
 address</I>/PASSTHRU</TD></TR>
 
@@ -4111,8 +4236,8 @@ lpd://<I>address</I>/pr1
 <BR> lpd://<I>address</I>/pr3</TD></TR>
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>EFI&reg; Fiery&reg; RIP</TD><TD>lpd://<I>
 address</I>/print</TD></TR>
-<TR ALIGN="LEFT" VALIGN="TOP"><TD>EPSON&reg; Multiprotocol Ethernet 
-Interface Board</TD><TD>socket://<I>address</I></TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>EPSON&reg; Multiprotocol Ethernet
+ Interface Board</TD><TD>socket://<I>address</I></TD></TR>
 
 <!-- NEED 1in -->
 <TR ALIGN="LEFT" VALIGN="TOP"><TD>Extended System ExtendNET</TD><TD>
@@ -4163,16 +4288,16 @@ address</I>:5503</TD></TR>
 </CENTER>
 </P>
 <H2><A NAME="AXIS">Configuring Axis Print Servers</A></H2>
-<P>The Axis print servers can be configured using ARP, RARP, or BOOTP. 
-However, on models that do not provide IPP support an additional step 
-must be performed to configure the TCP/IP portion of the print server 
-for use with CUPS. 
+<P>The Axis print servers can be configured using ARP, RARP, or BOOTP.
+ However, on models that do not provide IPP support an additional step
+ must be performed to configure the TCP/IP portion of the print server
+ for use with CUPS.
 <!-- NEED 3in -->
 </P>
-<P>Each print server contains a configuration file named <VAR>config</VAR>
- that contains a list of network parameters used by the server. To 
-modify this file you must first download it from the print server using 
-the <CODE>ftp(1)</CODE> program: </P>
+<P>Each print server contains a configuration file named<VAR> config</VAR>
+ that contains a list of network parameters used by the server. To
+ modify this file you must first download it from the print server using
+ the <CODE>ftp(1)</CODE> program:</P>
 <UL>
 <PRE>
 <B>ftp ip-address ENTER</B>
@@ -4195,8 +4320,8 @@ ftp&gt; <B>quit ENTER</B>
 </UL>
 
 <!-- NEED 2in -->
-<P>Next, edit the file with your favorite text editor and locate the 
-lines beginning with: </P>
+<P>Next, edit the file with your favorite text editor and locate the
+ lines beginning with:</P>
 <UL>
 <PRE>
 RTN_OPT.     : YES
@@ -4212,7 +4337,7 @@ RTEL_PR8.    : 0
 </UL>
 
 <!-- NEED 1in -->
- Change the <CODE>RTN_OPT</CODE> line to read: 
+ Change the <CODE>RTN_OPT</CODE> line to read:
 <UL>
 <PRE>
 RTN_OPT.     : <B>NO</B>
@@ -4220,9 +4345,9 @@ RTN_OPT.     : <B>NO</B>
 </UL>
 
 <!-- NEED 2in -->
-<P>This disables the Reverse TELNET protocol and enables the standard 
-TELNET protocol on the print server. Next, assign a port number for 
-each parallel and serial port on the server as follows: </P>
+<P>This disables the Reverse TELNET protocol and enables the standard
+ TELNET protocol on the print server. Next, assign a port number for
+ each parallel and serial port on the server as follows:</P>
 <UL>
 <PRE>
 RTEL_PR1.    : <B>9100</B>
@@ -4237,9 +4362,9 @@ RTEL_PR8.    : <B>9107</B>
 </UL>
 
 <!-- NEED 4in -->
-<P>This essentially makes the Axis print server look like a Hewlett 
-Packard JetDirect EX print server. Save the file and then upload the 
-new <VAR>config</VAR> file using the <CODE>ftp</CODE> command: </P>
+<P>This essentially makes the Axis print server look like a Hewlett
+ Packard JetDirect EX print server. Save the file and then upload the
+ new<VAR> config</VAR> file using the <CODE>ftp</CODE> command:</P>
 <UL>
 <PRE>
 <B>ftp ip-address ENTER</B>
@@ -4263,18 +4388,18 @@ ftp&gt; <B>quit ENTER</B>
 221 Goodbye.
 </PRE>
 </UL>
-<P>Your Axis print server is now ready for use! </P>
+<P>Your Axis print server is now ready for use!</P>
 <H2><A NAME="LINKSYS">Configuring Linksys Print Servers</A></H2>
-<P>The Linksys print servers can be configured using ARP, RARP, or 
-BOOTP. Like older Axis print servers, an additional step must be 
-performed to configure the TCP/IP portion of the print server for use 
-with CUPS. 
+<P>The Linksys print servers can be configured using ARP, RARP, or
+ BOOTP. Like older Axis print servers, an additional step must be
+ performed to configure the TCP/IP portion of the print server for use
+ with CUPS.
 <!-- NEED 3in -->
 </P>
-<P>Each print server contains a configuration file named <VAR>CONFIG</VAR>
- that contains a list of network parameters used by the server. To 
-modify this file you must first download it from the print server using 
-the <CODE>ftp(1)</CODE> program: </P>
+<P>Each print server contains a configuration file named<VAR> CONFIG</VAR>
+ that contains a list of network parameters used by the server. To
+ modify this file you must first download it from the print server using
+ the <CODE>ftp(1)</CODE> program:</P>
 <UL>
 <PRE>
 <B>ftp -n ip-address ENTER</B>
@@ -4295,8 +4420,8 @@ ftp&gt; <B>quit ENTER</B>
 </UL>
 
 <!-- NEED 2in -->
-<P>Next, edit the file with your favorite text editor and locate the 
-lines beginning with: </P>
+<P>Next, edit the file with your favorite text editor and locate the
+ lines beginning with:</P>
 <UL>
 <PRE>
 0100 L1_PROUT:P1
@@ -4304,8 +4429,8 @@ lines beginning with: </P>
 0140 L3_PROUT:P1
 </PRE>
 </UL>
-<P>Change the port number for each parallel and serial port on the 
-server as follows: </P>
+<P>Change the port number for each parallel and serial port on the
+ server as follows:</P>
 <UL>
 <PRE>
 0100 L1_PROUT:<B>P1</B>
@@ -4315,9 +4440,9 @@ server as follows: </P>
 </UL>
 
 <!-- NEED 4in -->
-<P>This maps each virtual printer with a physical port. Save the file 
-and then upload the new <VAR>CONFIG</VAR> file using the <CODE>ftp</CODE>
- command: </P>
+<P>This maps each virtual printer with a physical port. Save the file
+ and then upload the new<VAR> CONFIG</VAR> file using the <CODE>ftp</CODE>
+ command:</P>
 <UL>
 <PRE>
 <B>ftp -n ip-address ENTER</B>
@@ -4334,96 +4459,95 @@ ftp&gt; <B>quit ENTER</B>
 221 Goodbye.
 </PRE>
 </UL>
-<P>Your Linksys print server is now ready for use! </P>
+<P>Your Linksys print server is now ready for use!</P>
 <H1 ALIGN="RIGHT"><A NAME="PRINTER_DRIVERS">C - Printer Drivers</A></H1>
-<P>This appendix lists the printer drivers that are provided with CUPS. </P>
+<P>This appendix lists the printer drivers that are provided with CUPS.</P>
 <H2><A NAME="11_1">Printer Drivers</A></H2>
-<P>CUPS includes the following printer drivers: </P>
+<P>CUPS includes the following printer drivers:</P>
 <UL>
-<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A>, <VAR>epson9.ppd</VAR></LI>
-<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A>, <VAR>epson24.ppd</VAR>
+<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A>,<VAR> epson9.ppd</VAR></LI>
+<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A>,<VAR> epson24.ppd</VAR>
 </LI>
-<LI><A HREF="#STCOLOR">EPSON Stylus Color</A>, <VAR>stcolor.ppd</VAR></LI>
-<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A>, <VAR>stphoto.ppd</VAR></LI>
-<LI><A HREF="#DESKJET">HP DeskJet</A>, <VAR>deskjet.ppd</VAR></LI>
-<LI><A HREF="#LASERJET">HP LaserJet</A>, <VAR>laserjet.ppd</VAR></LI>
+<LI><A HREF="#STCOLOR">EPSON Stylus Color</A>,<VAR> stcolor.ppd</VAR></LI>
+<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A>,<VAR> stphoto.ppd</VAR></LI>
+<LI><A HREF="#DESKJET">HP DeskJet</A>,<VAR> deskjet.ppd</VAR></LI>
+<LI><A HREF="#LASERJET">HP LaserJet</A>,<VAR> laserjet.ppd</VAR></LI>
 </UL>
 <H2><A NAME="EPSON9">EPSON 9-pin Dot Matrix</A></H2>
-<P>The EPSON 9-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports 
-9-pin dot matrix printers that implement the ESC/P command set. It 
-provides 60x72, 120x72, and 240x72 DPI output in black only. </P>
+<P>The EPSON 9-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports
+ 9-pin dot matrix printers that implement the ESC/P command set. It
+ provides 60x72, 120x72, and 240x72 DPI output in black only.</P>
 <H2><A NAME="EPSON24">EPSON 24-pin Dot Matrix</A></H2>
-<P>The EPSON 24-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports 
-24-pin dot matrix printers that implement the ESC/P command set. It 
-provides 120x180, 180x180, 360x180, and 360x360 DPI output in black 
-only. </P>
+<P>The EPSON 24-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports
+ 24-pin dot matrix printers that implement the ESC/P command set. It
+ provides 120x180, 180x180, 360x180, and 360x360 DPI output in black
+ only.</P>
 <H2><A NAME="STCOLOR">EPSON Stylus Color</A></H2>
-<P>The EPSON Stylus Color driver (<VAR>stcolor.ppd</VAR>) supports 
-EPSON Stylus Color printers that implement the ESC/P2 command set. It 
-provides 180, 360, and 720 DPI output in black and color (CMYK). </P>
+<P>The EPSON Stylus Color driver (<VAR>stcolor.ppd</VAR>) supports EPSON
+ Stylus Color printers that implement the ESC/P2 command set. It
+ provides 180, 360, and 720 DPI output in black and color (CMYK).</P>
 <H2><A NAME="STPHOTO">EPSON Stylus Photo</A></H2>
-<P>The EPSON Stylus Photo driver (<VAR>stphoto.ppd</VAR>) supports 
-EPSON Stylus Photo printers that implement the ESC/P2 command set. It 
-provides 180, 360, and 720 DPI output in black and color (CMYKcm). </P>
+<P>The EPSON Stylus Photo driver (<VAR>stphoto.ppd</VAR>) supports EPSON
+ Stylus Photo printers that implement the ESC/P2 command set. It
+ provides 180, 360, and 720 DPI output in black and color (CMYKcm).</P>
 <H2><A NAME="DESKJET">HP DeskJet</A></H2>
-<P>The HP DeskJet driver (<VAR>deskjet.ppd</VAR>) supports HP DeskJet 
-printers that implement the PCL command set. It provides 150, 300, and 
-600 DPI output in black and color (CMYK). </P>
-<P>The DeskJet printers that implement the HP-PPA command set (720C, 
-722C, 820C, and 1100C) are <B>not</B> supported due to a complete lack 
-of documentation and support from Hewlett Packard. </P>
-<P>The duplexer provided with the HP DeskJet 900 series printers is 
-also not supported for similar reasons. </P>
+<P>The HP DeskJet driver (<VAR>deskjet.ppd</VAR>) supports HP DeskJet
+ printers that implement the PCL command set. It provides 150, 300, and
+ 600 DPI output in black and color (CMYK).</P>
+<P>The DeskJet printers that implement the HP-PPA command set (720C,
+ 722C, 820C, and 1100C) are<B> not</B> supported due to a complete lack
+ of documentation and support from Hewlett Packard.</P>
+<P>The duplexer provided with the HP DeskJet 900 series printers is also
+ not supported for similar reasons.</P>
 <H2><A NAME="LASERJET">HP LaserJet</A></H2>
-<P>The HP LaserJet driver (<VAR>laserjet.ppd</VAR>) supports HP 
-LaserJet printers that implement the PCL command set. It provides 150, 
-300, and 600 DPI output in black only and supports the duplexer if 
-installed. </P>
-<P>LaserJet printers that do not implement PCL (3100, 3150) are not 
-supported due to a complete lack of documentation and support from 
-Hewlett Packard. </P>
+<P>The HP LaserJet driver (<VAR>laserjet.ppd</VAR>) supports HP LaserJet
+ printers that implement the PCL command set. It provides 150, 300, and
+ 600 DPI output in black only and supports the duplexer if installed.</P>
+<P>LaserJet printers that do not implement PCL (3100, 3150) are not
+ supported due to a complete lack of documentation and support from
+ Hewlett Packard.</P>
 <H1 ALIGN="RIGHT"><A NAME="FILES">D - List of Files</A></H1>
-<P>This appendix lists the files and directories that are installed for 
-the Common UNIX Printing System. 
+<P>This appendix lists the files and directories that are installed for
+ the Common UNIX Printing System.
 <CENTER>
 <TABLE BORDER="1" WIDTH="80%">
 <TR VALIGN="TOP"><TH>Pathname</TH><TH>Description</TH></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/certs/</TD><TD>The location of 
-authentication certificate files for local  HTTP clients.</TD></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/classes.conf</TD><TD>The printer classes 
-configuration file for the scheduler.</TD></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/cupsd.conf</TD><TD>The scheduler 
-configuration file.</TD></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/interfaces/</TD><TD>The location of 
-System V interface scripts for printers.</TD></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/mime.convs</TD><TD>The list of standard 
-file filters included with ESP Print Pro.</TD></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/mime.types</TD><TD>The list of 
-recognized file types for ESP Print Pro.</TD></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/ppd/</TD><TD>The location of PostScript 
-Printer Description (&quot;PPD&quot;) files for  printers.</TD></TR>
-<TR VALIGN="TOP"><TD>/etc/cups/printers.conf</TD><TD>The printer 
-configuration file for the scheduler.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/bin/cancel</TD><TD>The System V cancel job(s) 
-command.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/bin/disable</TD><TD>The System V disable 
-printer command.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/bin/enable</TD><TD>The System V enable 
-printer command.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/certs/</TD><TD>The location of
+ authentication certificate files for local HTTP clients.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/classes.conf</TD><TD>The printer classes
+ configuration file for the scheduler.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/cupsd.conf</TD><TD>The scheduler
+ configuration file.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/interfaces/</TD><TD>The location of
+ System V interface scripts for printers.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/mime.convs</TD><TD>The list of standard
+ file filters included with ESP Print Pro.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/mime.types</TD><TD>The list of recognized
+ file types for ESP Print Pro.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/ppd/</TD><TD>The location of PostScript
+ Printer Description (&quot;PPD&quot;) files for printers.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/printers.conf</TD><TD>The printer
+ configuration file for the scheduler.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/cancel</TD><TD>The System V cancel job(s)
+ command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/disable</TD><TD>The System V disable
+ printer command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/enable</TD><TD>The System V enable printer
+ command.</TD></TR>
 <TR VALIGN="TOP"><TD>/usr/bin/lp</TD><TD>The System V print command.</TD>
 </TR>
-<TR VALIGN="TOP"><TD>/usr/bin/lpoptions</TD><TD>Sets user-defined 
-printing options and defaults.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/bin/lppasswd</TD><TD>Adds, changes, or 
-removes Digest password accounts.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpoptions</TD><TD>Sets user-defined
+ printing options and defaults.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lppasswd</TD><TD>Adds, changes, or removes
+ Digest password accounts.</TD></TR>
 <TR VALIGN="TOP"><TD>/usr/bin/lpq</TD><TD>The Berkeley status command.</TD>
 </TR>
 <TR VALIGN="TOP"><TD>/usr/bin/lpr</TD><TD>The Berkeley print command.</TD>
 </TR>
-<TR VALIGN="TOP"><TD>/usr/bin/lprm</TD><TD>The Berkeley cancel job(s) 
-command.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/bin/lpstat</TD><TD>The System V status 
-command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lprm</TD><TD>The Berkeley cancel job(s)
+ command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpstat</TD><TD>The System V status
+ command.</TD></TR>
 <TR VALIGN="TOP"><TD>/usr/include/cups/</TD><TD>CUPS API header files.</TD>
 </TR>
 <TR VALIGN="TOP"><TD>/usr/lib32/libcups.a
@@ -4438,118 +4562,118 @@ command.</TD></TR>
 <TR VALIGN="TOP"><TD>/usr/lib/libcups.so.2
 <BR> /usr/lib/libcupsimage.so.2</TD><TD>Shared libraries (all others)</TD>
 </TR>
-<TR VALIGN="TOP"><TD>/usr/lib/cups/backend/</TD><TD>Backends for 
-various types of printer connections.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/lib/cups/cgi-bin/</TD><TD>CGI programs for 
-the scheduler.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/lib/cups/daemon/</TD><TD>Daemons for polling 
-and LPD support.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/lib/cups/filter/</TD><TD>Filters for various 
-types of files.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/lib/locale/</TD><TD>The location of 
-language-specific message files. (System V)</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/lib/nls/msg/</TD><TD>The location of 
-language-specific message files. (Compaq Tru64 UNIX)</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/locale/</TD><TD>The location of 
-language-specific message files. (Linux, *BSD)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/backend/</TD><TD>Backends for various
+ types of printer connections.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/cgi-bin/</TD><TD>CGI programs for the
+ scheduler.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/daemon/</TD><TD>Daemons for polling
+ and LPD support.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/filter/</TD><TD>Filters for various
+ types of files.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/locale/</TD><TD>The location of
+ language-specific message files. (System V)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/nls/msg/</TD><TD>The location of
+ language-specific message files. (Compaq Tru64 UNIX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/locale/</TD><TD>The location of
+ language-specific message files. (Linux, *BSD)</TD></TR>
 <TR VALIGN="TOP"><TD>/usr/sbin/accept</TD><TD>The accept-jobs command.</TD>
 </TR>
 <TR VALIGN="TOP"><TD>/usr/sbin/cupsd</TD><TD>The CUPS print scheduler.</TD>
 </TR>
-<TR VALIGN="TOP"><TD>/usr/sbin/lpadmin</TD><TD>The System V printer 
-administration tool.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/sbin/lpc</TD><TD>The Berkeley printer 
-administration tool.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/sbin/lpinfo</TD><TD>The get-devices and 
-get-ppds command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpadmin</TD><TD>The System V printer
+ administration tool.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpc</TD><TD>The Berkeley printer
+ administration tool.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpinfo</TD><TD>The get-devices and
+ get-ppds command.</TD></TR>
 <TR VALIGN="TOP"><TD>/usr/sbin/lpmove</TD><TD>The move-jobs command.</TD>
 </TR>
 <TR VALIGN="TOP"><TD>/usr/sbin/reject</TD><TD>The reject-jobs command.</TD>
 </TR>
 <TR VALIGN="TOP"><TD>/usr/share/catman/a_man/
 <BR> /usr/share/catman/u_man/</TD><TD>Man pages (IRIX)</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/man/</TD><TD>Man pages (Compaq Tru64 
-UNIX, HP-UX, Solaris)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/man/</TD><TD>Man pages (Compaq Tru64
+ UNIX, HP-UX, Solaris)</TD></TR>
 <TR VALIGN="TOP"><TD>/usr/man/</TD><TD>Man pages (all others)</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/cups/data/</TD><TD>The location of 
-filter data files.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/cups/data/testprint.ps</TD><TD>The 
-PostScript test page file.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/cups/fonts/</TD><TD>The location of 
-PostScript fonts for the PostScript RIP.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/cups/model/</TD><TD>The location of 
-PostScript Printer Description (&quot;PPD&quot;) files and  interface scripts 
-that may be used to setup a printer queue.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/</TD><TD>Other 
-PostScript RIP initialization files.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/Fontmap</TD><TD>The 
-font mapping file (converts filenames to fontnames)</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/cups/templates/</TD><TD>The location of 
-HTML template files for the web interfaces.</TD></TR>
-<TR VALIGN="TOP"><TD>/usr/share/doc/cups/</TD><TD>Documentation and web 
-page data for the scheduler.</TD></TR>
-<TR VALIGN="TOP"><TD>/var/log/cups/</TD><TD>The location of scheduler 
-log files.</TD></TR>
-<TR VALIGN="TOP"><TD>/var/spool/cups/</TD><TD>The location of print 
-files waiting to be printed.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/</TD><TD>The location of
+ filter data files.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/testprint.ps</TD><TD>The
+ PostScript test page file.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/fonts/</TD><TD>The location of
+ PostScript fonts for the PostScript RIP.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/model/</TD><TD>The location of
+ PostScript Printer Description (&quot;PPD&quot;) files and interface scripts that
+ may be used to setup a printer queue.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/</TD><TD>Other
+ PostScript RIP initialization files.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/Fontmap</TD><TD>The font
+ mapping file (converts filenames to fontnames)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/templates/</TD><TD>The location of
+ HTML template files for the web interfaces.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/doc/cups/</TD><TD>Documentation and web
+ page data for the scheduler.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/log/cups/</TD><TD>The location of scheduler
+ log files.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/spool/cups/</TD><TD>The location of print
+ files waiting to be printed.</TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H1 ALIGN="RIGHT"><A NAME="FAQ">E - Troubleshooting Common Problems</A></H1>
-<P>This appendix covers some of the common problems first-time users 
-encounter when installing and configuring CUPS. </P>
-<P>Commercial support for CUPS is available from Easy Software 
-Products. For more information please contact us at: </P>
+<P>This appendix covers some of the common problems first-time users
+ encounter when installing and configuring CUPS.</P>
+<P>Commercial support for CUPS is available from Easy Software Products.
+ For more information please contact us at:</P>
 <UL>
-<LI>WWW: <A HREF="http://www.easysw.com"><CODE> http://www.easysw.com</CODE>
+<LI>WWW:<A HREF="http://www.easysw.com"> <CODE>http://www.easysw.com</CODE>
 </A></LI>
-<LI>EMail: <A HREF="mailto:info@easysw.com">info@easysw.com</A></LI>
-<LI>Telephone (M-F, 9-5 EST): +1.301.373.9600 </LI>
+<LI>EMail:<A HREF="mailto:info@easysw.com"> info@easysw.com</A></LI>
+<LI>Telephone (M-F, 9-5 EST): +1.301.373.9600</LI>
 </UL>
 <H2><A NAME="13_1">My Applications Don't See the Available Printers</A></H2>
-<P>Many applications read the <VAR>/etc/printcap</VAR> file to get a 
-list of available printers. </P>
-<P>The default CUPS configuration does not create the <VAR>/etc/printcap</VAR>
- file automatically. To enable automatic creation and updating of this 
-file, use the <A HREF="#Printcap"><CODE>Printcap</CODE></A> directive 
-described in <A HREF="#PRINTING_MANAGEMENT">Chapter 6, &quot;Printing System 
-Management&quot;</A>. </P>
+<P>Many applications read the<VAR> /etc/printcap</VAR> file to get a
+ list of available printers.</P>
+<P>The default CUPS configuration does not create the<VAR> /etc/printcap</VAR>
+ file automatically. To enable automatic creation and updating of this
+ file, use the<A HREF="#Printcap"> <CODE>Printcap</CODE></A> directive
+ described in<A HREF="#PRINTING_MANAGEMENT"> Chapter 6, &quot;Printing System
+ Management&quot;</A>.</P>
 <H2><A NAME="13_2">CUPS Doesn't Recognize My Username or Password!</A></H2>
-<P>CUPS will ask you for a UNIX username and password when you perform 
-printer administration tasks remotely or via a web browser. The default 
-configuration requires that you use the <CODE>root</CODE> username and 
-the corresponding password to authenticate the request. </P>
-<P>CUPS does not allow you to authenticate an administration request 
-with an account that has no password for security reasons. If you do 
-not have a password on your <CODE>root</CODE> account then you won't be 
-able to add printers remotely or via the web interface! 
+<P>CUPS will ask you for a UNIX username and password when you perform
+ printer administration tasks remotely or via a web browser. The default
+ configuration requires that you use the <CODE>root</CODE> username and
+ the corresponding password to authenticate the request.</P>
+<P>CUPS does not allow you to authenticate an administration request
+ with an account that has no password for security reasons. If you do
+ not have a password on your <CODE>root</CODE> account then you won't be
+ able to add printers remotely or via the web interface!
 <!-- NEED 2in -->
 </P>
-<P>To disable password authentication you need to edit the <VAR>
-/etc/cups/cupsd.conf</VAR> file and comment out the lines reading: </P>
+<P>To disable password authentication you need to edit the<VAR>
+ /etc/cups/cupsd.conf</VAR> file and comment out the lines reading:</P>
 <UL>
 <PRE>
 AuthType Basic
 AuthClass System
 </PRE>
 </UL>
- for the <VAR>/admin</VAR> location. Then restart the CUPS server as 
-described in <A HREF="PRINTING_MANAGEMENT">Chapter 8, &quot;Printing System 
-Management&quot;</A>. 
+ for the<VAR> /admin</VAR> location. Then restart the CUPS server as
+ described in<A HREF="PRINTING_MANAGEMENT"> Chapter 8, &quot;Printing System
+ Management&quot;</A>.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>Disabling password checks will allow any local user to  change your 
-printer and class configuration, but remote  administration from 
-another machine will still not be allowed. </P>
+<P>Disabling password checks will allow any local user to change your
+ printer and class configuration, but remote administration from another
+ machine will still not be allowed.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 <H2><A NAME="13_3">I Can't Do Administration Tasks from Another Machine!</A>
 </H2>
-<P>The default CUPS configuration limits administration to the local 
-machine. To open up access, edit the <VAR>/etc/cups/cupsd.conf</VAR>
- and comment out the lines reading: </P>
+<P>The default CUPS configuration limits administration to the local
+ machine. To open up access, edit the<VAR> /etc/cups/cupsd.conf</VAR>
+ and comment out the lines reading:</P>
 <UL>
 <PRE>
 Order deny,allow
@@ -4557,16 +4681,16 @@ Deny from all
 Allow from 127.0.0.1
 </PRE>
 </UL>
- for the <VAR>/admin</VAR> location. Then restart the CUPS server as 
-described in <A HREF="PRINTING_MANAGEMENT">Chapter 8, &quot;Printing System 
-Management&quot;</A>. 
+ for the<VAR> /admin</VAR> location. Then restart the CUPS server as
+ described in<A HREF="PRINTING_MANAGEMENT"> Chapter 8, &quot;Printing System
+ Management&quot;</A>.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>Allowing administration access from all hosts is a potential 
- security risk. Please read <A HREF="PRINTING_SECURITY">Chapter  6, 
-&quot;Printing System Management&quot;</A> for a description of these  risks and 
-ways to minimize them. </P>
+<P>Allowing administration access from all hosts is a potential security
+ risk. Please read<A HREF="PRINTING_SECURITY"> Chapter 6, &quot;Printing
+ System Management&quot;</A> for a description of these risks and ways to
+ minimize them.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
@@ -4574,48 +4698,48 @@ ways to minimize them. </P>
 <!-- NEED 4in -->
 <H2><A NAME="13_4">I Can't Do Administration Tasks from My Web Browser!</A>
 </H2>
-<P>This problem is usually caused by: </P>
+<P>This problem is usually caused by:</P>
 <OL>
-<LI>not specifying the correct password for the  root account. </LI>
-<LI>accessing the CUPS server using the hostname or IP  address of the 
-server without enabling remote access for  administration functions. 
-This can be corrected by following  the instructions in the <A HREF="#ALLOW_REMOTE">
-&quot;I Can't Do  Administration Tasks from Another Machine!&quot;</A> section 
-earlier  in this appendix. </LI>
-<LI>not setting a password on the root account. CUPS will not 
- authenticate a user account that does not have a password for 
security reasons. </LI>
-<LI>authenticating using an account other than root, but the  account 
-you are using is not a member of the system group. </LI>
-<LI>configuring CUPS to use Digest authentication, but  your web 
-browser does not support Digest authentication. </LI>
+<LI>not specifying the correct password for the root account.</LI>
+<LI>accessing the CUPS server using the hostname or IP address of the
+ server without enabling remote access for administration functions.
+ This can be corrected by following the instructions in the<A HREF="#ALLOW_REMOTE">
+ &quot;I Can't Do Administration Tasks from Another Machine!&quot;</A> section
+ earlier in this appendix.</LI>
+<LI>not setting a password on the root account. CUPS will not
+ authenticate a user account that does not have a password for security
reasons.</LI>
+<LI>authenticating using an account other than root, but the account you
+ are using is not a member of the system group.</LI>
+<LI>configuring CUPS to use Digest authentication, but your web browser
+ does not support Digest authentication.</LI>
 </OL>
 <H2><A NAME="13_5">Connection Refused Messages</A></H2>
-<P>Under normal circumstances, &quot;connection refused&quot; messages for a 
-networked printer should be expected from time to time. Most network 
-interfaces only allow a single connection to be made at any given time 
-(one job at a time) and will refuse access to all other systems while 
-the first connection is active. CUPS automatically retries the 
-connection once every 30 seconds. </P>
-<P>If the problem persists and you are unable to print any jobs to the 
-printer, verify that another machine is not maintaining a connection 
-with the printer, and that you have selected the proper port or printer 
-name for the printer. </P>
-<P>Also, most external print servers will refuse connections if the 
-connected printer is turned off or is off-line. Verify that the 
-affected printer is turned on and is online. </P>
+<P>Under normal circumstances, &quot;connection refused&quot; messages for a
+ networked printer should be expected from time to time. Most network
+ interfaces only allow a single connection to be made at any given time
+ (one job at a time) and will refuse access to all other systems while
+ the first connection is active. CUPS automatically retries the
+ connection once every 30 seconds.</P>
+<P>If the problem persists and you are unable to print any jobs to the
+ printer, verify that another machine is not maintaining a connection
+ with the printer, and that you have selected the proper port or printer
+ name for the printer.</P>
+<P>Also, most external print servers will refuse connections if the
+ connected printer is turned off or is off-line. Verify that the
+ affected printer is turned on and is online.</P>
 <H2><A NAME="13_6">Write Error Messages</A></H2>
-<P>If you get &quot;write error&quot; messages on a printer queue the printer 
-interface (usually a Hewlett Packard JetDirect interface) has timed out 
-and reset the network connection from your workstation. </P>
-<P>The error is caused by that startup delay between the initial setup 
-of the printer or plotter and the first page of print data that is 
-sent. 
+<P>If you get &quot;write error&quot; messages on a printer queue the printer
+ interface (usually a Hewlett Packard JetDirect interface) has timed out
+ and reset the network connection from your workstation.</P>
+<P>The error is caused by that startup delay between the initial setup
+ of the printer or plotter and the first page of print data that is
+ sent.
 <!-- NEED 3in -->
 </P>
-<P>To correct the problem, change the idle timeout on the interface to 
-at least 180 seconds or 3 minutes. To change the timeout on a Hewlett 
-Packard JetDirect interface, type: </P>
+<P>To correct the problem, change the idle timeout on the interface to
+ at least 180 seconds or 3 minutes. To change the timeout on a Hewlett
+ Packard JetDirect interface, type:</P>
 <UL>
 <PRE>
 <B>telnet ip-address ENTER</B>
index fc3fa1a4ee4b72a08830fd6577aa9318164d6c11..f97f6d5275f3bc784420af263f3149f90fa5bbb2 100644 (file)
Binary files a/doc/sam.pdf and b/doc/sam.pdf differ
index ca928643e88b2db5de594db2f25f2b70f72a8dc1..18cf426fd2eaf5e0050e6f5c9a2c1ff672212f9f 100644 (file)
@@ -1,7 +1,7 @@
 <HTML>
 <HEAD>
        <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2001, All Rights Reserved">
-       <META NAME="DOCNUMBER" CONTENT="CUPS-SAM-1.1.7">
+       <META NAME="DOCNUMBER" CONTENT="CUPS-SAM-1.2.0">
        <META NAME="Author" CONTENT="Easy Software Products">
        <TITLE>CUPS Software Administrators Manual</TITLE>
 </HEAD>
@@ -11,7 +11,7 @@
 
 <P>This software administrators manual provides printer administration
 information for the Common UNIX Printing System<SUP>TM</SUP>
-("CUPS<SUP>TM</SUP>"), version 1.1.7.
+("CUPS<SUP>TM</SUP>"), version 1.2.0.
 
 <EMBED SRC="system-overview.shtml">
 
@@ -177,6 +177,11 @@ make changes you can get the HTMLDOC software from:
 <A HREF="http://www.easysw.com/htmldoc">http://www.easysw.com/htmldoc</A>
 </PRE></UL>
 
+<P>Finally, you'll need a <CODE>make</CODE> program that
+understands the <CODE>include</CODE> directive - FreeBSD,
+NetBSD, and OpenBSD developers should use the <CODE>gmake</CODE>
+program.
+
 <H3><A NAME="COMPILING">Compiling CUPS</A></H3>
 
 <P>CUPS uses GNU autoconf to configure the makefiles and source code
@@ -234,6 +239,16 @@ prior to running configure:
 <A HREF="http://www.openssl.org">http://www.openssl.org</A>
 </PRE></UL>
 
+<P>If the OpenSSL headers and libraries are not installed in the
+standard directories, use the <CODE>--with-openssl-includes</CODE>
+and <CODE>--with-openssl-libs</CODE> options:</P>
+
+<UL><PRE>
+./configure --enable-ssl \
+    --with-openssl-includes=/foo/bar/include \
+    --with-openssl-libs=/foo/bar/lib
+</PRE></UL>
+
 <P>Once you have configured things, just type:
 
 <UL><PRE>
@@ -434,6 +449,18 @@ the PPD files for the HP DeskJet and HP LaserJet drivers included with CUPS.
 You'll find a complete list of PPD files and the printers they will work with
 in <A HREF="#PRINTER_DRIVERS">Appendix C, "Printer Drivers"</A>.
 
+
+<P>For a dot matrix printer connected to the serial port this would might look like:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTER</B>
+</PRE></UL>
+
+<P>Here you specify the serial port (e.g. S0,S1, d0, d1), baud rate 
+(e.g. 9600, 19200, 38400, 115200, etc.), number of bits, parity, and flow control.
+If you do not need flow control, delete the "+flow=soft" portion.
+
+
 <H3><A NAME="ADD_WEB">Adding Your First Printer from the Web</A></H3>
 
 <P>The CUPS web server provides a user-friendly "wizard" interface for
@@ -829,7 +856,6 @@ can use your favorite text editor to make changes to it.
 determine how the server operates:
 
 <UL>
-
 <TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0">
 <TR>
 <TD VALIGN="TOP">
@@ -847,11 +873,13 @@ determine how the server operates:
        <LI><A HREF="#BrowseOrder"><CODE>BrowseOrder</CODE></A>
        <LI><A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A>
        <LI><A HREF="#BrowsePort"><CODE>BrowsePort</CODE></A>
+       <LI><A HREF="#BrowseProtocols"><CODE>BrowseProtocols</CODE></A>
        <LI><A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A>
        <LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A>
        <LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A>
        <LI><A HREF="#Browsing"><CODE>Browsing</CODE></A>
        <LI><A HREF="#Classification"><CODE>Classification</CODE></A>
+       <LI><A HREF="#ClassifyOverride"><CODE>ClassifyOverride</CODE></A>
        <LI><A HREF="#DataDir"><CODE>DataDir</CODE></A>
        <LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A>
        <LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A>
@@ -869,8 +897,11 @@ determine how the server operates:
        <LI><A HREF="#FilterLimit"><CODE>FilterLimit</CODE></A>
        <LI><A HREF="#FontPath"><CODE>FontPath</CODE></A>
        <LI><A HREF="#Group"><CODE>Group</CODE></A>
+       <LI><A HREF="#HideImplicitMembers"><CODE>HideImplicitMembers</CODE></A>
        <LI><A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>
        <LI><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+       <LI><A HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A>
+       <LI><A HREF="#Include"><CODE>Include</CODE></A>
        <LI><A HREF="#KeepAliveTimeout"><CODE>KeepAliveTimeout</CODE></A>
        <LI><A HREF="#KeepAlive"><CODE>KeepAlive</CODE></A>
        <LI><A HREF="#Limit"><CODE>Limit</CODE></A>
@@ -886,7 +917,6 @@ determine how the server operates:
        <LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A>
        <LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A>
        <LI><A HREF="#Order"><CODE>Order</CODE></A>
-       <LI><A HREF="#PageLog"><CODE>PageLog</CODE></A>
 
 </TD>
 <TD VALIGN="TOP">
@@ -894,6 +924,7 @@ determine how the server operates:
 </TD>
 <TD VALIGN="TOP">
 
+       <LI><A HREF="#PageLog"><CODE>PageLog</CODE></A>
        <LI><A HREF="#Port"><CODE>Port</CODE></A>
        <LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A>
        <LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A>
@@ -1083,6 +1114,7 @@ AuthGroupName lp
 AuthType None
 AuthType Basic
 AuthType Digest
+AuthType BasicDigest
 </PRE></UL>
 
 <H4>Description</H4>
@@ -1101,10 +1133,14 @@ perform:
        <LI><CODE>Digest</CODE> - Digest authentication should be
        performed using the <VAR>/etc/cups/passwd.md5</VAR> file.
 
+       <LI><CODE>BasicDigest</CODE> - Basic authentication should be
+       performed using the <VAR>/etc/cups/passwd.md5</VAR> file.
+
 </UL>
 
-<P>When using <CODE>Basic</CODE> or <CODE>Digest</CODE> authentication,
-clients connecting through the <CODE>localhost</CODE> interface can also
+<P>When using <CODE>Basic</CODE>, <CODE>Digest</CODE>, or
+<CODE>BasicDigest</CODE> authentication, clients connecting
+through the <CODE>localhost</CODE> interface can also
 authenticate using <A HREF="#CERTIFICATES">certificates</A>.
 
 <P>The <CODE>AuthType</CODE> directive must appear inside a
@@ -1315,6 +1351,39 @@ used for browse packets. The default port number is 631.
 </TR>
 </TABLE></CENTER>
 
+<!-- NEED 3in -->
+<H3><A NAME="BrowseProtocols">BrowseProtocols</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseProtocols CUPS
+BrowseProtocols SLP
+BrowseProtocols CUPS SLP
+BrowseProtocols all
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseProtocols</CODE> directive specifies the protocols to
+use when collecting and distributing shared printers on the local network.
+The default protocol is <CODE>CUPS</CODE>, which is a broadcast-based
+protocol.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+       <TD>
+       <B>NOTE:</B>
+
+       <P>When using the <CODE>SLP</CODE> protocol, you must have at least
+       one Directory Agent (DA) server on your network. Otherwise the
+       CUPS scheduler (<CODE>cupsd</CODE>) will not respond to client
+       requests for several seconds while polling the network.
+       </TD>
+</TR>
+</TABLE></CENTER>
+
 <!-- NEED 4in -->
 <H3><A NAME="BrowseRelay">BrowseRelay</A></H3>
 <HR>
@@ -1441,6 +1510,29 @@ on the server. When this option is set, at least one of the banner pages
 is forced to the classification level, and the classification is placed
 on each page of output. The default is no classification level.
 
+<!-- NEED 3in -->
+<H3><A NAME="ClassifyOverride">ClassifyOverride</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ClassifyOverride Yes
+ClassifyOverride No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ClassifyOverride</CODE> directive specifies whether users
+can override the default classification level on the server. When the
+server classification is set, users can change the classification using
+the <CODE>job-sheets</CODE> option and can choose to only print one
+security banner before or after the job. If the <CODE>job-sheets</CODE>
+option is set to <CODE>none</CODE> then the server default classification
+is used.
+
+<P>The default is to not allow classification overrides.
+
 <!-- NEED 3in -->
 <H3><A NAME="DataDir">DataDir</A></H3>
 <HR>
@@ -1693,6 +1785,26 @@ filter and CGI programs run as. The default group is <CODE>sys</CODE>,
 <CODE>system</CODE>, or <CODE>root</CODE> depending on the operating
 system.
 
+<!-- NEED 3in -->
+<H3><A NAME="HideImplicitMembers">HideImplicitMembers</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+HideImplicitMembers Yes
+HideImplicitMembers No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>HideImplicitMembers</CODE> directive controls
+whether the individual printers in an implicit class are shown
+to the user. The default is <CODE>No</CODE>.</P>
+
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+must be enabled for this directive to have any effect.</P>
+
 <!-- NEED 3in -->
 <H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
 <HR>
@@ -1739,6 +1851,45 @@ The default setting is <CODE>On</CODE> but is automatically turned
 <CODE>Off</CODE> if <A HREF="#Browsing"><CODE>Browsing</CODE></A> is
 turned <CODE>Off</CODE>.
 
+<!-- NEED 3in -->
+<H3><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ImplicitAnyClasses On
+ImplicitAnyClasses Off
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ImplicitAnyClasses</CODE> directive controls
+whether implicit classes for local and remote printers are
+created with the name <CODE>AnyPrinter</CODE>. The default
+setting is <CODE>Off</CODE>.</P>
+
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+must be enabled for this directive to have any effect.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="Include">Include</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Include filename
+Include /foo/bar/filename
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Include</CODE> directive includes the named file in
+the <CODE>cupsd.conf</CODE> file. If no leading path is
+provided, the file is assumed to be relative to the
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory.</P>
+
 <!-- NEED 3in -->
 <H3><A NAME="KeepAlive">KeepAlive</A></H3>
 <HR>
index 2c9f95bf4026a5155b19d050366abbbdcda78242..5a665fb6be0ffa59654f81ab6968d40367ee1ef3 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Design Description</TITLE>
+<TITLE>CUPS Software Design Description</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-SDD-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Design Description</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Design Description</H1></A><BR>
 CUPS-SDD-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -138,459 +138,454 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
- This software design description document provides general information 
- on the architecture and coding of the Common UNIX Printing System 
- (&quot;CUPS&quot;) Version 1.1. 
+ This software design description document provides general information
+ on the architecture and coding of the Common UNIX Printing System
+ (&quot;CUPS&quot;) Version 1.1.
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
- This software design description document is organized into the 
- following sections: 
+ This software design description document is organized into the
+ following sections:
 <UL>
-<LI>1 - Scope </LI>
-<LI>2 - References </LI>
-<LI>3 - Design Overview </LI>
-<LI>A - Glossary </LI>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Design Overview</LI>
+<LI>A - Glossary</LI>
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
+<P>The following CUPS documentation is referenced by this document:</P>
 <UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 Design Overview</A></H1>
- CUPS is composed of 9 software sub-systems that operate together to 
- perform common printing tasks: 
+ CUPS is composed of 9 software sub-systems that operate together to
+ perform common printing tasks:
 <UL>
-<LI>Backends </LI>
-<LI>Berkeley Commands </LI>
-<LI>CGI </LI>
-<LI>CUPS Application Programmers Interface </LI>
-<LI>CUPS Imaging Library </LI>
-<LI>Daemons </LI>
-<LI>Filters </LI>
-<LI>Scheduler </LI>
-<LI>System V Commands </LI>
+<LI>Backends</LI>
+<LI>Berkeley Commands</LI>
+<LI>CGI</LI>
+<LI>CUPS Application Programmers Interface</LI>
+<LI>CUPS Imaging Library</LI>
+<LI>Daemons</LI>
+<LI>Filters</LI>
+<LI>Scheduler</LI>
+<LI>System V Commands</LI>
 </UL>
 <H2><A NAME="3_1">3.1 Backends</A></H2>
- The backends implement communications over a number of different 
-interfaces. All backends are called with a common set of arguments: 
+ The backends implement communications over a number of different
+ interfaces. All backends are called with a common set of arguments:
 <UL>
-<LI>Device URI - the Uniform Resource Identifier for the output device 
- (e.g. <CODE>parallel:/dev/plp</CODE>, <CODE> ipp://hostname/resource</CODE>
-). </LI>
-<LI>Job Identifier - the job identifier for this job (integer). </LI>
-<LI>User Name - the user associated with this job (name string). </LI>
-<LI>Title - the title/job-name associated with this job (name string). </LI>
-<LI>Copies - the number of copies required (integer). </LI>
-<LI>Options - the options associated with this job (space separated 
- option strings). </LI>
-<LI>Filename (optional) - the file to print; if this option is not 
- specified, the backend must read the print file from the standard 
- input. </LI>
+<LI>Device URI - the Uniform Resource Identifier for the output device
+ (e.g. <CODE>parallel:/dev/plp</CODE>, <CODE>ipp://hostname/resource</CODE>
+).</LI>
+<LI>Job Identifier - the job identifier for this job (integer).</LI>
+<LI>User Name - the user associated with this job (name string).</LI>
+<LI>Title - the title/job-name associated with this job (name string).</LI>
+<LI>Copies - the number of copies required (integer).</LI>
+<LI>Options - the options associated with this job (space separated
+ option strings).</LI>
+<LI>Filename (optional) - the file to print; if this option is not
+ specified, the backend must read the print file from the standard
+ input.</LI>
 </UL>
-<P>Backends are named using the scheme of the URI, so a URI of 
-&quot;ipp://hostname/resource&quot; would be processed by the &quot;ipp&quot; backend. </P>
+<P>Backends are named using the scheme of the URI, so a URI of
+ &quot;ipp://hostname/resource&quot; would be processed by the &quot;ipp&quot; backend.</P>
 <H3><A NAME="3_1_1">3.1.1 ipp</A></H3>
-<P>The ipp backend sends the specified job to a network printer or host 
-using the Internet Printing Protocol.  The URI is as specified by the <CODE>
-printer-uri-supported</CODE> attribute from the printer or host. </P>
+<P>The ipp backend sends the specified job to a network printer or host
+ using the Internet Printing Protocol. The URI is as specified by the <CODE>
+printer-uri-supported</CODE> attribute from the printer or host.</P>
 <H3><A NAME="3_1_2">3.1.2 lpd</A></H3>
-<P>The lpd backend sends the specified job to a network printer or host 
-using the Line Printer Daemon protocol.  The URI is of the form: </P>
+<P>The lpd backend sends the specified job to a network printer or host
+ using the Line Printer Daemon protocol. The URI is of the form:</P>
 <UL>
 <PRE>lpd://hostname/queue
 </PRE>
 </UL>
 <H3><A NAME="3_1_3">3.1.3 parallel</A></H3>
-<P>The parallel backend sends the specified job to a local printer 
-connected via the specified parallel port device.  The URI is of the 
-form: </P>
+<P>The parallel backend sends the specified job to a local printer
+ connected via the specified parallel port device. The URI is of the
+ form:</P>
 <UL>
 <PRE>parallel:/dev/file
 </PRE>
 </UL>
 <H3><A NAME="3_1_4">3.1.4 serial</A></H3>
-<P>The serial backend sends the specified job to a local printer 
-connected via the specified serial port device.  The URI is of the 
-form: </P>
+<P>The serial backend sends the specified job to a local printer
+ connected via the specified serial port device. The URI is of the form:</P>
 <UL>
 <PRE>serial:/dev/file?option[+option+...]
 </PRE>
 </UL>
- The options can be any combination of the following: 
+ The options can be any combination of the following:
 <UL>
-<LI><CODE>baud=<I>rate</I></CODE> - Sets the baud rate for the device. </LI>
-<LI><CODE>bits=<I>7 or 8</I></CODE> - Sets the number of data bits. </LI>
-<LI><CODE>parity=<I>even</I></CODE> - Sets even parity checking. </LI>
-<LI><CODE>parity=<I>odd</I></CODE> - Sets odd parity checking. </LI>
-<LI><CODE>parity=<I>none</I></CODE> - Turns parity checking off. </LI>
-<LI><CODE>flow=dtrdsr<I></I></CODE> - Turns DTR/DSR (hardware) flow 
- control on. </LI>
-<LI><CODE>flow=hard<I></I></CODE> - Turns RTS/CTS  (hardware) flow 
-control on. </LI>
-<LI><CODE>flow=none<I></I></CODE> - Turns flow control off. </LI>
-<LI><CODE>flow=rtscts<I></I></CODE> - Turns RTS/CTS  (hardware) flow 
-control on. </LI>
-<LI><CODE>flow=xonxoff<I></I></CODE> - Turns XON/XOFF  (software) flow 
-control on. </LI>
+<LI><CODE>baud=<I>rate</I></CODE> - Sets the baud rate for the device.</LI>
+<LI><CODE>bits=<I>7 or 8</I></CODE> - Sets the number of data bits.</LI>
+<LI><CODE>parity=<I>even</I></CODE> - Sets even parity checking.</LI>
+<LI><CODE>parity=<I>odd</I></CODE> - Sets odd parity checking.</LI>
+<LI><CODE>parity=<I>none</I></CODE> - Turns parity checking off.</LI>
+<LI><CODE>flow=dtrdsr<I></I></CODE> - Turns DTR/DSR (hardware) flow
+ control on.</LI>
+<LI><CODE>flow=hard<I></I></CODE> - Turns RTS/CTS (hardware) flow
+ control on.</LI>
+<LI><CODE>flow=none<I></I></CODE> - Turns flow control off.</LI>
+<LI><CODE>flow=rtscts<I></I></CODE> - Turns RTS/CTS (hardware) flow
+ control on.</LI>
+<LI><CODE>flow=xonxoff<I></I></CODE> - Turns XON/XOFF (software) flow
+ control on.</LI>
 </UL>
 <H3><A NAME="3_1_5">3.1.5 socket</A></H3>
-<P>The socket backend sends the specified job to a network host using 
-the AppSocket protocol commonly used by Hewlett-Packard and Tektronix 
-printers.  The URI is of the form: </P>
+<P>The socket backend sends the specified job to a network host using
+ the AppSocket protocol commonly used by Hewlett-Packard and Tektronix
+ printers. The URI is of the form:</P>
 <UL>
 <PRE>socket://hostname[:port]
 </PRE>
 </UL>
- The default port number is 9100. 
+ The default port number is 9100.
 <H3><A NAME="3_1_6">3.1.6 usb</A></H3>
-<P>The usb backend sends the specified job to a local printer connected 
-via the specified usb port device.  The URI is of the form: </P>
+<P>The usb backend sends the specified job to a local printer connected
+ via the specified usb port device. The URI is of the form:</P>
 <UL>
 <PRE>usb:/dev/file
 </PRE>
 </UL>
 <H2><A NAME="3_2">3.2 Berkeley Commands</A></H2>
-<P>The Berkeley commands provide a simple command-line interface to 
-CUPS to submit and control print jobs. It is provided for compatibility 
-with existing software that is hardcoded to use the Berkeley commands. </P>
+<P>The Berkeley commands provide a simple command-line interface to CUPS
+ to submit and control print jobs. It is provided for compatibility with
+ existing software that is hardcoded to use the Berkeley commands.</P>
 <H3><A NAME="3_2_1">3.2.1 lpc</A></H3>
- The lpc command allows users and administrators to check the status 
-and control print queues.  The version provided with CUPS supports the 
-following commands: 
+ The lpc command allows users and administrators to check the status and
+ control print queues. The version provided with CUPS supports the
+ following commands:
 <UL>
-<LI>quit - Quits the lpc command. </LI>
-<LI>status - Shows the status of printers and jobs in the queue. </LI>
+<LI>quit - Quits the lpc command.</LI>
+<LI>status - Shows the status of printers and jobs in the queue.</LI>
 </UL>
 <H3><A NAME="3_2_2">3.2.2 lpq</A></H3>
-<P>The lpq command shows the current queue status. </P>
+<P>The lpq command shows the current queue status.</P>
 <H3><A NAME="3_2_3">3.2.3 lpr</A></H3>
-<P>The lpr command submits a job for printing.  The CUPS version of lpr 
-silently ignores the &quot;i&quot;, &quot;t&quot;, &quot;m&quot;, &quot;h&quot;, and &quot;s&quot; options. </P>
+<P>The lpr command submits a job for printing. The CUPS version of lpr
+ silently ignores the &quot;i&quot;, &quot;t&quot;, &quot;m&quot;, &quot;h&quot;, and &quot;s&quot; options.</P>
 <H3><A NAME="3_2_4">3.2.4 lprm</A></H3>
-<P>The lprm removes one or more print jobs. </P>
+<P>The lprm removes one or more print jobs.</P>
 <H2><A NAME="3_3">3.3 CGI</A></H2>
-<P>The Common Gateway Interface (CGI) programs provide a web-based 
-status interface to monitor the status of printers, classes, and jobs. 
-Each of the CGIs utilize HTML template files that can be customized to 
-provide alternate appearances. </P>
+<P>The Common Gateway Interface (CGI) programs provide a web-based
+ status interface to monitor the status of printers, classes, and jobs.
+ Each of the CGIs utilize HTML template files that can be customized to
+ provide alternate appearances.</P>
 <H3><A NAME="3_3_1">3.3.1 admin.cgi</A></H3>
-<P>The admin CGI provides administration interfaces for printers and 
-classes. The user can add, modify, delete, start, stop, and configure 
-printers and classes using &quot;wizard&quot; interfaces. </P>
+<P>The admin CGI provides administration interfaces for printers and
+ classes. The user can add, modify, delete, start, stop, and configure
+ printers and classes using &quot;wizard&quot; interfaces.</P>
 <H3><A NAME="3_3_2">3.3.2 classes.cgi</A></H3>
-<P>The classes CGI lists the available printer classes and any pending 
-jobs for the class.  The user can click on individual classes to limit 
-the display and click on jobs to see the job status. </P>
+<P>The classes CGI lists the available printer classes and any pending
+ jobs for the class. The user can click on individual classes to limit
+ the display and click on jobs to see the job status.</P>
 <H3><A NAME="3_3_3">3.3.3 jobs.cgi</A></H3>
-<P>The jobs CGI lists the queued print jobs in order of priority.  The 
-list can be limited by printer or job. </P>
+<P>The jobs CGI lists the queued print jobs in order of priority. The
+ list can be limited by printer or job.</P>
 <H3><A NAME="3_3_4">3.3.4 printers.cgi</A></H3>
-<P>The printers CGI lists the available printer queues and any pending 
-jobs for the printer.  The user can click on individual printers to 
-limit the display and click on jobs to see the job status. </P>
+<P>The printers CGI lists the available printer queues and any pending
+ jobs for the printer. The user can click on individual printers to
+ limit the display and click on jobs to see the job status.</P>
 <H2><A NAME="3_4">3.4 CUPS Application Programmers Interface</A></H2>
-<P>The CUPS Application Programmers Interface (&quot;API&quot;) provides common 
-convenience, HTTP, IPP, language, and PPD functions used by the CUPS 
-software. </P>
+<P>The CUPS Application Programmers Interface (&quot;API&quot;) provides common
+ convenience, HTTP, IPP, language, and PPD functions used by the CUPS
+ software.</P>
 <H3><A NAME="3_4_1">3.4.1 Convenience Functions</A></H3>
-<P>Convenience functions are provided to submit an IPP request, send a 
-print file, cancel a job, get a list of available printers, get a list 
-of available classes, get the default printer or class, get the default 
-server name, get the local username, and get a password string. </P>
+<P>Convenience functions are provided to submit an IPP request, send a
+ print file, cancel a job, get a list of available printers, get a list
+ of available classes, get the default printer or class, get the default
+ server name, get the local username, and get a password string.</P>
 <H3><A NAME="3_4_2">3.4.2 HTTP Functions</A></H3>
-<P>The HTTP functions provide functions to connect to HTTP servers, 
-issue requests, read data from a server, and write data to a server. </P>
+<P>The HTTP functions provide functions to connect to HTTP servers,
+ issue requests, read data from a server, and write data to a server.</P>
 <H3><A NAME="3_4_3">3.4.3 IPP Functions</A></H3>
-<P>The IPP function provide functions to manage IPP request data and 
-attributes, read IPP responses from a server, and write IPP requests to 
-a server. </P>
+<P>The IPP function provide functions to manage IPP request data and
+ attributes, read IPP responses from a server, and write IPP requests to
+ a server.</P>
 <H3><A NAME="3_4_4">3.4.4 Language Functions</A></H3>
-<P>The language functions provide a standard interface for retrieving 
-common textual messages for a particular locale and determining the 
-correct encoding (e.g. US ASCII, UTF-8, ISO-8859-1, etc.) </P>
+<P>The language functions provide a standard interface for retrieving
+ common textual messages for a particular locale and determining the
+ correct encoding (e.g. US ASCII, UTF-8, ISO-8859-1, etc.)</P>
 <H3><A NAME="3_4_5">3.4.5 PPD Functions</A></H3>
-<P>The PostScript Printer Description functions manage PPD files, 
-select options, check for option conflicts, and emit selected options 
-in the correct order. </P>
+<P>The PostScript Printer Description functions manage PPD files, select
+ options, check for option conflicts, and emit selected options in the
+ correct order.</P>
 <H2><A NAME="3_5">3.5 CUPS Imaging Library</A></H2>
-<P>The CUPS imaging library provides colorspace conversion, color 
-management, image management, scaling, image file, and raster functions 
-used by the CUPS raster filters. </P>
+<P>The CUPS imaging library provides colorspace conversion, color
+ management, image management, scaling, image file, and raster functions
+ used by the CUPS raster filters.</P>
 <H3><A NAME="3_5_1">3.5.1 Colorspace Conversion Functions</A></H3>
-<P>The colorspace conversion functions handle conversion of grayscale 
-and RGB colors to grayscale, RGB, K, CMY, CMYK, and CMYKcm colorspaces. </P>
+<P>The colorspace conversion functions handle conversion of grayscale
+ and RGB colors to grayscale, RGB, K, CMY, CMYK, and CMYKcm colorspaces.</P>
 <H3><A NAME="3_5_2">3.5.2 Color Management Functions</A></H3>
-<P>The color management functions handle gamut mapping and density 
-correction. These are integrated with the colorspace conversion 
-functions so that colorspace conversion and color management are 
-processed in a single step. </P>
+<P>The color management functions handle gamut mapping and density
+ correction. These are integrated with the colorspace conversion
+ functions so that colorspace conversion and color management are
+ processed in a single step.</P>
 <H3><A NAME="3_5_3">3.5.3 Image Management Functions</A></H3>
-<P>The image management functions manage a tiled image database that is 
-swapped to/from disk as needed. </P>
+<P>The image management functions manage a tiled image database that is
+ swapped to/from disk as needed.</P>
 <H3><A NAME="3_5_4">3.5.4 Scaling Functions</A></H3>
-<P>The scaling functions provide image scaling services using 
-nearest-neighbor sampling and bilinear interpolation as appropriate. </P>
+<P>The scaling functions provide image scaling services using
+ nearest-neighbor sampling and bilinear interpolation as appropriate.</P>
 <H3><A NAME="3_5_5">3.5.5 Image File Functions</A></H3>
-<P>The image file functions handle loading of all image file formats. </P>
+<P>The image file functions handle loading of all image file formats.</P>
 <H3><A NAME="3_5_6">3.5.6 Raster Functions</A></H3>
-<P>The raster functions manage streams of CUPS raster data (described 
-in the Interface Design Document) used by non-PostScript printer 
-drivers and raster filters. </P>
+<P>The raster functions manage streams of CUPS raster data (described in
+ the Interface Design Document) used by non-PostScript printer drivers
+ and raster filters.</P>
 <H2><A NAME="3_6">3.6 Daemons</A></H2>
-<P>The daemons provide additional network functions for the scheduler. 
-Currently only two daemons are provided with CUPS. </P>
+<P>The daemons provide additional network functions for the scheduler.
+ Currently only two daemons are provided with CUPS.</P>
 <H3><A NAME="3_6_1">3.6.1 Line Printer Daemon</A></H3>
-<P>The line printer daemon provides remote LPD client support and is 
-run by the <CODE>inetd(8)</CODE> daemon as needed. </P>
+<P>The line printer daemon provides remote LPD client support and is run
+ by the <CODE>inetd(8)</CODE> daemon as needed.</P>
 <H3><A NAME="3_6_2">3.6.2 Polling Daemon</A></H3>
-<P>The polling daemon is used to poll a remote server for a list of 
-available printers and provide it to the scheduler for addition. A 
-separate polling daemon is run by the scheduler for every remote system 
-listed for polling in the scheduler configuration file. </P>
+<P>The polling daemon is used to poll a remote server for a list of
+ available printers and provide it to the scheduler for addition. A
+ separate polling daemon is run by the scheduler for every remote system
+ listed for polling in the scheduler configuration file.</P>
 <H2><A NAME="3_7">3.7 Filters</A></H2>
-<P>The filters implement file conversion services for CUPS. All filters 
-are called with a common set of arguments: </P>
+<P>The filters implement file conversion services for CUPS. All filters
+ are called with a common set of arguments:</P>
 <UL>
-<LI>Printer name - the name of the destination printer (name string). </LI>
-<LI>Job Identifier - the job identifier for this job (integer). </LI>
-<LI>User Name - the user associated with this job (name string). </LI>
-<LI>Title - the title/job-name associated with this job (name string). </LI>
-<LI>Copies - the number of copies required (integer). </LI>
-<LI>Options - the options associated with this job (space separated 
- option strings). </LI>
-<LI>Filename (optional) - the file to print; if this option is not 
- specified, the filter must read the input file from the standard 
- input. </LI>
+<LI>Printer name - the name of the destination printer (name string).</LI>
+<LI>Job Identifier - the job identifier for this job (integer).</LI>
+<LI>User Name - the user associated with this job (name string).</LI>
+<LI>Title - the title/job-name associated with this job (name string).</LI>
+<LI>Copies - the number of copies required (integer).</LI>
+<LI>Options - the options associated with this job (space separated
+ option strings).</LI>
+<LI>Filename (optional) - the file to print; if this option is not
+ specified, the filter must read the input file from the standard input.</LI>
 </UL>
-<P>Filters are added to the MIME conversion data file and implement all 
-necessary conversions from one file type to another. </P>
+<P>Filters are added to the MIME conversion data file and implement all
+ necessary conversions from one file type to another.</P>
 <H3><A NAME="3_7_1">3.7.1 hpgltops</A></H3>
-<P>The hpgltops filter converts HP-GL/2 files into PostScript. </P>
+<P>The hpgltops filter converts HP-GL/2 files into PostScript.</P>
 <H3><A NAME="3_7_2">3.7.2 imagetops</A></H3>
-<P>The imagetops filter converts image files into PostScript. </P>
+<P>The imagetops filter converts image files into PostScript.</P>
 <H3><A NAME="3_7_3">3.7.3 imagetoraster</A></H3>
-<P>The imagetoraster filter converts image files into CUPS raster data. </P>
+<P>The imagetoraster filter converts image files into CUPS raster data.</P>
 <H3><A NAME="3_7_4">3.7.4 pdftops</A></H3>
-<P>The pdftops filter converts PDF files into PostScript. </P>
+<P>The pdftops filter converts PDF files into PostScript.</P>
 <H3><A NAME="3_7_5">3.7.5 pstops</A></H3>
-<P>The pstops filter inserts printer-specific commands from PPD files 
-and performs page filtering as requested by the user. </P>
+<P>The pstops filter inserts printer-specific commands from PPD files
+ and performs page filtering as requested by the user.</P>
 <H3><A NAME="3_7_6">3.7.6 pstoraster</A></H3>
-<P>The pstoraster filter converts PostScript program data into CUPS 
-raster data. </P>
+<P>The pstoraster filter converts PostScript program data into CUPS
+ raster data.</P>
 <H3><A NAME="3_7_7">3.7.7 rastertoepson</A></H3>
-<P>The rastertoepson filter handles converting CUPS raster data to 
-ESC/P and supports both color and black-and-white printers. </P>
+<P>The rastertoepson filter handles converting CUPS raster data to ESC/P
+ and supports both color and black-and-white printers.</P>
 <H3><A NAME="3_7_8">3.7.8 rastertohp</A></H3>
-<P>The rastertohp filter handles converting CUPS raster data to HP-PCL 
-and supports both color and black-and-white printers. </P>
+<P>The rastertohp filter handles converting CUPS raster data to HP-PCL
+ and supports both color and black-and-white printers.</P>
 <H3><A NAME="3_7_9">3.7.9 texttops</A></H3>
-<P>The texttops filter converts text files into PostScript. </P>
+<P>The texttops filter converts text files into PostScript.</P>
 <H2><A NAME="3_8">3.8 Scheduler</A></H2>
-<P>The scheduler is a fully-functional HTTP/1.1 and IPP/1.1 server that 
-manages the printers, classes, and jobs in the system.  It also handles 
-a simple broadcast-based directory service so that remote print queues 
-and classes can be accessed transparently from the local system. </P>
+<P>The scheduler is a fully-functional HTTP/1.1 and IPP/1.1 server that
+ manages the printers, classes, and jobs in the system. It also handles
+ a simple broadcast-based directory service so that remote print queues
+ and classes can be accessed transparently from the local system.</P>
 <H3><A NAME="3_8_1">3.8.1 Authorization</A></H3>
-<P>The authorization module is responsible for performing access 
-control and authentication for all HTTP and IPP requests entering the 
-system. </P>
+<P>The authorization module is responsible for performing access control
+ and authentication for all HTTP and IPP requests entering the system.</P>
 <H3><A NAME="3_8_2">3.8.2 Classes</A></H3>
-<P>The classes module is responsible for managing printer classes in 
-the system. Each class is a collection of local and/or remote printers. 
- The classes module also reads and writes the classes configuration 
-file. </P>
+<P>The classes module is responsible for managing printer classes in the
+ system. Each class is a collection of local and/or remote printers. The
+ classes module also reads and writes the classes configuration file.</P>
 <H3><A NAME="3_8_3">3.8.3 Client</A></H3>
-<P>The client module is responsible for all HTTP client communications. 
- It handles listening on selected interfaces, accepting connections 
-from prospective clients, processing incoming HTTP requests, and 
-sending HTTP responses to those requests.  The client module also is 
-responsible for executing the external CGI programs as needed to 
-support web-based printer, class, and job status monitoring and 
-administration. </P>
-<P>Once authorized, all IPP requests are sent to the IPP module. </P>
+<P>The client module is responsible for all HTTP client communications.
+ It handles listening on selected interfaces, accepting connections from
+ prospective clients, processing incoming HTTP requests, and sending
+ HTTP responses to those requests. The client module also is responsible
+ for executing the external CGI programs as needed to support web-based
+ printer, class, and job status monitoring and administration.</P>
+<P>Once authorized, all IPP requests are sent to the IPP module.</P>
 <H3><A NAME="3_8_4">3.8.4 Configuration</A></H3>
-<P>The configuration module is responsible for reading the CUPS 
-configuration file and initializing the appropriate data structures and 
-values.  The configuration module also stops CUPS services before 
-reading the configuration file and restarts them after the 
-configuration file has been read. </P>
+<P>The configuration module is responsible for reading the CUPS
+ configuration file and initializing the appropriate data structures and
+ values. The configuration module also stops CUPS services before
+ reading the configuration file and restarts them after the
+ configuration file has been read.</P>
 <H3><A NAME="3_8_5">3.8.5 Devices</A></H3>
-<P>The devices module is responsible for managing the list of available 
-devices for the CUPS-Get-Devices operation. </P>
+<P>The devices module is responsible for managing the list of available
+ devices for the CUPS-Get-Devices operation.</P>
 <H3><A NAME="3_8_6">3.8.6 Directory Services</A></H3>
-<P>The directory services module sends and recieves printer state 
-information over a broadcast socket.  Remote printers and classes are 
-automatically added to or removed from the local printer and class 
-lists as needed. </P>
-<P>The directory services module can only recieve printer state 
-information over a single UDP port, however it can broadcast to 
-multiple addresses and ports as needed. </P>
+<P>The directory services module sends and recieves printer state
+ information over a broadcast socket. Remote printers and classes are
+ automatically added to or removed from the local printer and class
+ lists as needed.</P>
+<P>The directory services module can only recieve printer state
+ information over a single UDP port, however it can broadcast to
+ multiple addresses and ports as needed.</P>
 <H3><A NAME="3_8_7">3.8.7 IPP</A></H3>
-<P>The IPP module handles IPP requests and acts accordingly.  URI 
-validation is also performed here, as a client can post IPP data to any 
-URI on the server which might sidestep the access control or 
-authentication of the HTTP server. </P>
+<P>The IPP module handles IPP requests and acts accordingly. URI
+ validation is also performed here, as a client can post IPP data to any
+ URI on the server which might sidestep the access control or
+ authentication of the HTTP server.</P>
 <H3><A NAME="3_8_8">3.8.8 Jobs</A></H3>
-<P>The jobs module manages print jobs, starts filter and backend 
-processes for jobs to be printed, and monitors status messages from 
-those filters and backends. </P>
+<P>The jobs module manages print jobs, starts filter and backend
+ processes for jobs to be printed, and monitors status messages from
+ those filters and backends.</P>
 <H3><A NAME="3_8_9">3.8.9 Logging</A></H3>
-<P>The logging module manages the access, error, and page log files 
-that are generated by the scheduler. </P>
+<P>The logging module manages the access, error, and page log files that
+ are generated by the scheduler.</P>
 <H3><A NAME="3_8_10">3.8.10 Main</A></H3>
-<P>The main module is responsible for timing out and dispatching input 
-and output for client connections.  It also watches for incoming <CODE>
-SIGHUP</CODE> and <CODE>SIGCHLD</CODE> signals, reloads the server 
-configuration files as needed, and handles child process errors and 
-exits. </P>
+<P>The main module is responsible for timing out and dispatching input
+ and output for client connections. It also watches for incoming <CODE>
+SIGHUP</CODE> and <CODE>SIGCHLD</CODE> signals, reloads the server
+ configuration files as needed, and handles child process errors and
+ exits.</P>
 <H3><A NAME="3_8_11">3.8.11 MIME</A></H3>
-<P>The Multimedia Internet Mail Exchange module manages a MIME type and 
-conversion database that supports file typing by extension and content 
-and least-cost file filtering from a source to a destination file type. </P>
+<P>The Multimedia Internet Mail Exchange module manages a MIME type and
+ conversion database that supports file typing by extension and content
+ and least-cost file filtering from a source to a destination file type.</P>
 <H3><A NAME="3_8_12">3.8.12 PPDs</A></H3>
-<P>The PPDs module is responsible for managing the list of available 
-PPD files for the CUPS-Get-PPDs operation. </P>
+<P>The PPDs module is responsible for managing the list of available PPD
+ files for the CUPS-Get-PPDs operation.</P>
 <H3><A NAME="3_8_13">3.8.13 Printers</A></H3>
-<P>The printers module is responsible for managing printers and PPD 
-files in the system. The printers module also reads and writes the 
-printers configuration file. </P>
+<P>The printers module is responsible for managing printers and PPD
+ files in the system. The printers module also reads and writes the
+ printers configuration file.</P>
 <H2><A NAME="3_9">3.9 System V Commands</A></H2>
-<P>The System V commands provide a robust command-line interface to 
-CUPS to submit and control printers and jobs. </P>
+<P>The System V commands provide a robust command-line interface to CUPS
+ to submit and control printers and jobs.</P>
 <H3><A NAME="3_9_1">3.9.1 accept</A></H3>
-<P>The accept command tells the scheduler to accept new jobs for 
-specific printers. </P>
+<P>The accept command tells the scheduler to accept new jobs for
+ specific printers.</P>
 <H3><A NAME="3_9_2">3.9.2 cancel</A></H3>
-<P>The cancel command tells the scheduler to cancel one or more jobs 
-that are queued for printing. </P>
+<P>The cancel command tells the scheduler to cancel one or more jobs
+ that are queued for printing.</P>
 <H3><A NAME="3_9_3">3.9.3 disable</A></H3>
-<P>The disable command tells the scheduler to stop printing jobs on the 
-specified printers. </P>
+<P>The disable command tells the scheduler to stop printing jobs on the
+ specified printers.</P>
 <H3><A NAME="3_9_4">3.9.4 enable</A></H3>
-<P>The enable command tells the scheduler to start printing jobs on the 
-specified printers. </P>
+<P>The enable command tells the scheduler to start printing jobs on the
+ specified printers.</P>
 <H3><A NAME="3_9_5">3.9.5 lp</A></H3>
-<P>The lp command submits submits files for printing.  Unlike the 
-standard System V lp command, a single CUPS lp command will generate a 
-separate job ID for each file that is printed. Also, the Solaris &quot;f&quot;, 
-&quot;H&quot;, &quot;P&quot;, &quot;S&quot;, and &quot;y&quot; options are silently ignored. </P>
+<P>The lp command submits submits files for printing. Unlike the
+ standard System V lp command, a single CUPS lp command will generate a
+ separate job ID for each file that is printed. Also, the Solaris &quot;f&quot;,
+ &quot;H&quot;, &quot;P&quot;, &quot;S&quot;, and &quot;y&quot; options are silently ignored.</P>
 <H3><A NAME="3_9_6">3.9.6 lpadmin</A></H3>
-<P>The lpadmin command manages printer queues and classes.  The Solaris 
-&quot;A&quot;, &quot;F&quot;, &quot;I&quot;, &quot;M&quot;, &quot;P&quot;, &quot;Q&quot;, &quot;S&quot;, &quot;T&quot;, &quot;U&quot;, &quot;W&quot;, &quot;f&quot;, &quot;l&quot;, &quot;m&quot;, &quot;o&quot;, 
-&quot;s&quot;, &quot;t&quot;, and &quot;u&quot; options are not supported, and new options &quot;P&quot; (PPD 
-file) and &quot;E&quot; (enable and accept) are provided to configure 
-CUPS-specific features. </P>
+<P>The lpadmin command manages printer queues and classes. The Solaris
+ &quot;A&quot;, &quot;F&quot;, &quot;I&quot;, &quot;M&quot;, &quot;P&quot;, &quot;Q&quot;, &quot;S&quot;, &quot;T&quot;, &quot;U&quot;, &quot;W&quot;, &quot;f&quot;, &quot;l&quot;, &quot;m&quot;, &quot;o&quot;,
+ &quot;s&quot;, &quot;t&quot;, and &quot;u&quot; options are not supported, and new options &quot;P&quot; (PPD
+ file) and &quot;E&quot; (enable and accept) are provided to configure
+ CUPS-specific features.</P>
 <H3><A NAME="3_9_7">3.9.7 lpinfo</A></H3>
-<P>The lpinfo command lists the available PPD files or devices as 
-selected by the user. </P>
+<P>The lpinfo command lists the available PPD files or devices as
+ selected by the user.</P>
 <H3><A NAME="3_9_8">3.9.8 lpmove</A></H3>
-<P>The lpmove command moves a print job to a new destination. </P>
+<P>The lpmove command moves a print job to a new destination.</P>
 <H3><A NAME="3_9_9">3.9.9 lpoptions</A></H3>
-<P>The lpoptions command manages user-defined printers and options. </P>
+<P>The lpoptions command manages user-defined printers and options.</P>
 <H3><A NAME="3_9_10">3.9.10 lpstat</A></H3>
-<P>The lpstat command lists printers, classes, and jobs as requested by 
-the user. </P>
+<P>The lpstat command lists printers, classes, and jobs as requested by
+ the user.</P>
 <H3><A NAME="3_9_11">3.9.11 reject</A></H3>
-<P>The reject command tells the scheduler not to accept new jobs for 
-specific printers. </P>
+<P>The reject command tells the scheduler not to accept new jobs for
+ specific printers.</P>
 <H1 TYPE="A" VALUE="1"><A NAME="4">A Glossary</A></H1>
 <H2><A NAME="4_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="4_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 </BODY>
 </HTML>
index b801309fdb0b903df252f5a9d3d08411e38e3c48..49fe27d6d01f5e0d2e6a72bf9eef315f77b69cbe 100644 (file)
Binary files a/doc/sdd.pdf and b/doc/sdd.pdf differ
index 724a715b5702bc2e4862a77f73af7323272cad02..fa926bd57cba4372fb66838ed6954930f4a378f2 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Programmers Manual</TITLE>
+<TITLE>CUPS Software Programmers Manual</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-SPM-1.1.7">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
-<STYLE><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 19.0pt }
-H2 { font-family: sans-serif; font-size: 15.8pt }
-H3 { font-family: sans-serif; font-size: 13.2pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.2pt }
-H6 { font-family: sans-serif; font-size: 7.6pt }
-SUB { font-size: 7.6pt }
-SUP { font-size: 7.6pt }
-PRE { font-size: 9.2pt }
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY BGCOLOR="#ffffff">
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Programmers Manual</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Programmers Manual</H1></A><BR>
 CUPS-SPM-1.1.7<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -1072,30 +1072,30 @@ Copyright 1997-2001, All Rights Reserved<BR>
 </UL>
 <HR>
 <H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
-<P>This software programmers manual provides software programming 
-information for the Common UNIX Printing System (&quot;CUPS&quot;) Version 1.1.7. </P>
+<P>This software programmers manual provides software programming
+ information for the Common UNIX Printing System &lt;&lt;&lt;&lt;&lt;&lt;&lt; spm.shtml
+ (&quot;CUPS&quot;) Version 1.1.7. ======= (&quot;CUPS&quot;) Version 1.1.13. &gt;&gt;&gt;&gt;&gt;&gt;&gt; 1.21</P>
 <H2><A NAME="1_1">System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 
 <!-- NEED 2in -->
-
 <H2><A NAME="1_2">Document Overview</A></H2>
-<P>This software programmers manual is organized into the following 
-sections: </P>
+<P>This software programmers manual is organized into the following
+ sections:</P>
 <UL>
 <LI><A HREF="#OVERVIEW">1 - Printing System Overview</A></LI>
 <LI><A HREF="#CUPS_API">2 - The CUPS API</A></LI>
@@ -1108,16 +1108,16 @@ sections: </P>
 <LI><A HREF="#FUNCTIONS">D - Functions</A></LI>
 </UL>
 <H2><A NAME="1_3">Notation Conventions</A></H2>
-<P>Various font and syntax conventions are used in this guide. Examples 
-and their meanings and uses are explained below: 
+<P>Various font and syntax conventions are used in this guide. Examples
+ and their meanings and uses are explained below:
 <CENTER>
 <TABLE WIDTH="80%">
 <TR><TH>Example</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
-<BR><CODE> lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of 
-commands; the first mention of a command or  function in a chapter is 
-followed by a manual page section  number.</TD></TR>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands;
+ the first mention of a command or function in a chapter is followed by
+ a manual page section number.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD><VAR>/var</VAR>
 <BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
@@ -1127,153 +1127,153 @@ File and directory names.</TD></TR>
 &nbsp;&nbsp;&nbsp;</TD><TD>Screen output.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD><TD>
-&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are 
+&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are
  in ALL CAPS.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
-<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are 
-written using the period (.) to indicate  the decimal point.</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are
+ written using the period (.) to indicate the decimal point.</TD></TR>
 </TABLE>
 </CENTER>
 
 <!-- NEED 3in -->
 </P>
 <H2><A NAME="1_4">Abbreviations</A></H2>
- The following abbreviations are used throughout this manual: 
+ The following abbreviations are used throughout this manual:
 <UL>
 <DL>
-<DT>kb </DT>
+<DT>kb</DT>
 <DD>Kilobytes, or 1024 bytes
-<BR>&nbsp; </DD>
-<DT>Mb </DT>
+<BR>&nbsp;</DD>
+<DT>Mb</DT>
 <DD>Megabytes, or 1048576 bytes
-<BR>&nbsp; </DD>
-<DT>Gb </DT>
+<BR>&nbsp;</DD>
+<DT>Gb</DT>
 <DD>Gigabytes, or 1073741824 bytes
-<BR>&nbsp; </DD>
+<BR>&nbsp;</DD>
 </DL>
 </UL>
 <H2><A NAME="1_5">Other References</A></H2>
 <UL>
 <DL>
-<DT>CUPS Software Administrators Manual </DT>
+<DT>CUPS Software Administrators Manual</DT>
 <DD>An administration guide for the CUPS software.
-<BR>&nbsp; </DD>
-<DT>CUPS Software Users Manual </DT>
+<BR>&nbsp;</DD>
+<DT>CUPS Software Users Manual</DT>
 <DD>An end-user guide for using the CUPS software.
-<BR>&nbsp; </DD>
+<BR>&nbsp;</DD>
 </DL>
 </UL>
 <H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
-<P>This chapter provides an overview of how the Common UNIX Printing 
-System works. </P>
+<P>This chapter provides an overview of how the Common UNIX Printing
+ System works.</P>
 <H2><A NAME="2_1">The Printing Problem</A></H2>
-<P>For years <I>the printing problem</I> has plagued UNIX. Unlike 
-Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system 
-in place for supporting printers. Among the solutions currently 
-available, the Berkeley and System V printing systems are the most 
-prevalent. </P>
-<P>These printing systems support line printers (text only) or 
-PostScript printers (text and graphics), and with some coaxing they can 
-be made to support a full range of printers and file formats. However, 
-because each varient of the UNIX operating system uses a different 
-printing system than the next developing printer drivers for a wide 
-range of printers and operating systems is extremely difficult. That 
-combined with the limited volume of customers for each UNIX varient has 
-forced most printer vendors to give up supporting UNIX entirely. </P>
-<P>CUPS is designed to eliminate <I>the printing problem</I>. One 
-common printing system can be used by all UNIX varients to support the 
-printing needs of users. Printer vendors can use its modular filter 
-interface to develop a single driver program that supports a wide range 
-of file formats with little or no effort.  Since CUPS provides both the 
-System V and Berkeley printing commands, users (and applications) can 
-reap the benefits of this new technology with no changes. </P>
+<P>For years<I> the printing problem</I> has plagued UNIX. Unlike
+ Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system
+ in place for supporting printers. Among the solutions currently
+ available, the Berkeley and System V printing systems are the most
+ prevalent.</P>
+<P>These printing systems support line printers (text only) or
+ PostScript printers (text and graphics), and with some coaxing they can
+ be made to support a full range of printers and file formats. However,
+ because each varient of the UNIX operating system uses a different
+ printing system than the next developing printer drivers for a wide
+ range of printers and operating systems is extremely difficult. That
+ combined with the limited volume of customers for each UNIX varient has
+ forced most printer vendors to give up supporting UNIX entirely.</P>
+<P>CUPS is designed to eliminate<I> the printing problem</I>. One common
+ printing system can be used by all UNIX varients to support the
+ printing needs of users. Printer vendors can use its modular filter
+ interface to develop a single driver program that supports a wide range
+ of file formats with little or no effort. Since CUPS provides both the
+ System V and Berkeley printing commands, users (and applications) can
+ reap the benefits of this new technology with no changes.</P>
 <H2><A NAME="2_2">The Technology</A></H2>
-<P>CUPS is based upon an emerging Internet standard called the Internet 
-Printing Protocol. IPP has been embraced by dozens of printer and 
-printer server manufacturers and is supported by Microsoft Windows 
-2000. </P>
-<P>IPP defines a standard protocol for printing as well as managing 
-print jobs and printer options like media size, resolution, and so 
-forth. Like all IP-based protocols, IPP can be used locally or over the 
-Internet to printers hundreds or thousands of miles away. Unlike other 
-protocols, however, IPP also supports access control, authentication, 
-and encryption, making it a much more capable and secure printing 
-solution than older ones. </P>
-<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;) 
-which is the basis of web servers on the Internet. This allows users to 
-view documentation, check status information on a printer or server, 
-and manage their printers, classes, and jobs using their web browser. </P>
-<P>CUPS provides a complete IPP/1.1 based printing system that provides 
-Basic, Digest, and local certificate authentication and user, domain, 
-or IP-based access control. TLS encryption will be available in future 
-versions of CUPS. </P>
+<P>CUPS is based upon an emerging Internet standard called the Internet
+ Printing Protocol. IPP has been embraced by dozens of printer and
+ printer server manufacturers and is supported by Microsoft Windows
+ 2000.</P>
+<P>IPP defines a standard protocol for printing as well as managing
+ print jobs and printer options like media size, resolution, and so
+ forth. Like all IP-based protocols, IPP can be used locally or over the
+ Internet to printers hundreds or thousands of miles away. Unlike other
+ protocols, however, IPP also supports access control, authentication,
+ and encryption, making it a much more capable and secure printing
+ solution than older ones.</P>
+<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;)
+ which is the basis of web servers on the Internet. This allows users to
+ view documentation, check status information on a printer or server,
+ and manage their printers, classes, and jobs using their web browser.</P>
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+ Basic, Digest, and local certificate authentication and user, domain,
+ or IP-based access control. TLS encryption will be available in future
+ versions of CUPS.</P>
 <H2><A NAME="2_3">Jobs</A></H2>
-<P>Each file or set of files that is submitted for printing is called a <I>
-job</I>. Jobs are identified by a unique number starting at 1 and are 
-assigned to a particular destination, usually a printer. Jobs can also 
-have options associated with them such as media size, number of copies, 
-and priority. </P>
+<P>Each file or set of files that is submitted for printing is called a<I>
+ job</I>. Jobs are identified by a unique number starting at 1 and are
+ assigned to a particular destination, usually a printer. Jobs can also
+ have options associated with them such as media size, number of copies,
+ and priority.</P>
 <H2><A NAME="2_4">Classes</A></H2>
-<P>CUPS supports collections of printers known as <I>classes</I>. Jobs 
-sent to a class are forwarded to the first available printer in the 
-class. </P>
+<P>CUPS supports collections of printers known as<I> classes</I>. Jobs
+ sent to a class are forwarded to the first available printer in the
+ class.</P>
 <H2><A NAME="2_5">Filters</A></H2>
-<P>Filters allow a user or application to print many types of files 
-without extra effort. Print jobs sent to a CUPS server are filtered 
-before sending them to a printer. Some filters convert job files to 
-different formats that the printer can understand. Others perform page 
-selection and ordering tasks. </P>
-<P>CUPS provides filters for printing many types of image files, 
-HP-GL/2 files, PDF files, and text files. CUPS also supplies PostScript 
-and image file Raster Image Processor (&quot;RIP&quot;) filters that convert 
-PostScript or image files into bitmaps that can be sent to a raster 
-printer. </P>
+<P>Filters allow a user or application to print many types of files
+ without extra effort. Print jobs sent to a CUPS server are filtered
+ before sending them to a printer. Some filters convert job files to
+ different formats that the printer can understand. Others perform page
+ selection and ordering tasks.</P>
+<P>CUPS provides filters for printing many types of image files, HP-GL/2
+ files, PDF files, and text files. CUPS also supplies PostScript and
+ image file Raster Image Processor (&quot;RIP&quot;) filters that convert
+ PostScript or image files into bitmaps that can be sent to a raster
+ printer.</P>
 <H2><A NAME="2_6">Backends</A></H2>
-<P>Backends perform the most important task of all - they send the 
-filtered print data to the printer. </P>
-<P>CUPS provides backends for printing over parallel, serial, and USB 
-ports, and over the network via the IPP, JetDirect (AppSocket), and 
-Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are 
-available in network service packages such as the SMB backend included 
-with the popular SAMBA software. </P>
-<P>Backends are also used to determine the available devices. On 
-startup each backend is asked for a list of devices it supports, and 
-any information that is available. This allows the parallel backend to 
-tell CUPS that an EPSON Stylus Color 600 printer is attached to 
-parallel port 1, for example. </P>
+<P>Backends perform the most important task of all - they send the
+ filtered print data to the printer.</P>
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ ports, and over the network via the IPP, JetDirect (AppSocket), and
+ Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are
+ available in network service packages such as the SMB backend included
+ with the popular SAMBA software.</P>
+<P>Backends are also used to determine the available devices. On startup
+ each backend is asked for a list of devices it supports, and any
+ information that is available. This allows the parallel backend to tell
+ CUPS that an EPSON Stylus Color 600 printer is attached to parallel
+ port 1, for example.</P>
 <H2><A NAME="2_7">Printer Drivers</A></H2>
-<P>Printer drivers in CUPS consist of one of more filters specific to a 
-printer. CUPS includes sample printer drivers for Hewlett-Packard 
-LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color, 
-and Stylus Photo printers. While these drivers do not generate optimal 
-output for the different printer models, they do provide basic printing 
-and demonstrate how you can write your own printer drivers and 
-incorporate them into CUPS. </P>
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+ printer. CUPS includes sample printer drivers for Hewlett-Packard
+ LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+ and Stylus Photo printers. While these drivers do not generate optimal
+ output for the different printer models, they do provide basic printing
+ and demonstrate how you can write your own printer drivers and
+ incorporate them into CUPS.</P>
 <H2><A NAME="2_8">Networking</A></H2>
-<P>Printers and classes on the local system are automatically shared 
-with other systems on the network. This allows you to setup one system 
-to print to a printer and use this system as a printer server or spool 
-host for all of the others. Users may then select a local printer by 
-name or a remote printer using &quot;name@server&quot;. </P>
-<P>CUPS also provides <I>implicit classes</I>, which are collections of 
-printers and/or classes with the same name. This allows you to setup 
-multiple servers pointing to the same physical network printer, for 
-example, so that you aren't relying on a single system for printing. 
-Because this also works with printer classes, you can setup multiple 
-servers and printers and never worry about a single point of failure 
-unless all of the printers and servers go down! </P>
+<P>Printers and classes on the local system are automatically shared
+ with other systems on the network. This allows you to setup one system
+ to print to a printer and use this system as a printer server or spool
+ host for all of the others. Users may then select a local printer by
+ name or a remote printer using &quot;name@server&quot;.</P>
+<P>CUPS also provides<I> implicit classes</I>, which are collections of
+ printers and/or classes with the same name. This allows you to setup
+ multiple servers pointing to the same physical network printer, for
+ example, so that you aren't relying on a single system for printing.
+ Because this also works with printer classes, you can setup multiple
+ servers and printers and never worry about a single point of failure
+ unless all of the printers and servers go down!</P>
 <H1 ALIGN="RIGHT"><A NAME="CUPS_API">2 - The CUPS API</A></H1>
-<P>This chapter describes the CUPS Application Programmers Interface 
-(&quot;API&quot;). </P>
+<P>This chapter describes the CUPS Application Programmers Interface
+ (&quot;API&quot;).</P>
 <H2><A NAME="3_1">The CUPS API Library</A></H2>
-<P>The CUPS library provides a whole collection of interfaces needed to 
-support the internal needs of the CUPS software as well as the needs of 
-applications, filters, printer drivers, and backends. </P>
-<P>Unlike the rest of CUPS, the CUPS API library is provided under the 
-GNU Library General Public License. This means that you can use the 
-CUPS API library in both proprietary and open-source programs. </P>
+<P>The CUPS library provides a whole collection of interfaces needed to
+ support the internal needs of the CUPS software as well as the needs of
+ applications, filters, printer drivers, and backends.</P>
+<P>Unlike the rest of CUPS, the CUPS API library is provided under the
+ GNU Library General Public License. This means that you can use the
+ CUPS API library in both proprietary and open-source programs.</P>
 <P>Programs that use the CUPS API library typically will include the <CODE>
-&lt;cups/cups.h&gt;</CODE> header file: </P>
+&lt;cups/cups.h&gt;</CODE> header file:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1284,19 +1284,19 @@ jobid = cupsPrintFile(&quot;myprinter&quot;, &quot;filename.ps&quot;, &quot;titl
                       num_options, options);
 </PRE>
 </UL>
-<P>Use the <CODE>-lcups</CODE> compiler option when linking to the CUPS 
-API library: </P>
+<P>Use the <CODE>-lcups</CODE> compiler option when linking to the CUPS
+ API library:</P>
 <UL>
 <PRE>
 <B>cc -o program program.c -lcups ENTER</B>
 </PRE>
 </UL>
-<P>Additional options and libraries may be required depending on the 
-operating system and the location of the CUPS API library. </P>
+<P>Additional options and libraries may be required depending on the
+ operating system and the location of the CUPS API library.</P>
 <H3><A NAME="3_1_1">Detecting the CUPS API Library in GNU Autoconf</A></H3>
-<P>GNU autoconf is a popular configuration tool used by many programs. 
-Add the following lines to your <VAR>configure.in file to check for the 
-CUPS API library in your configuration script: </VAR></P>
+<P>GNU autoconf is a popular configuration tool used by many programs.
+ Add the following lines to your<VAR> configure.in file to check for the
+ CUPS API library in your configuration script:</VAR></P>
 <UL>
 <PRE>
 AC_CHECK_LIB(socket,socket,
@@ -1316,11 +1316,11 @@ AC_CHECK_LIB(cups,httpConnect)
 </PRE>
 </UL>
 <H2><A NAME="3_2">Printing Services</A></H2>
-<P>The CUPS API library provides some basic printing services for 
-applications that need to print files. </P>
+<P>The CUPS API library provides some basic printing services for
+ applications that need to print files.</P>
 <H3><A NAME="3_2_1">Include Files</A></H3>
 <P>The include file used by all of these functions is <CODE>
-&lt;cups/cups.h&gt;</CODE>: </P>
+&lt;cups/cups.h&gt;</CODE>:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1328,7 +1328,7 @@ applications that need to print files. </P>
 </UL>
 <H3><A NAME="3_2_2">Printing a File</A></H3>
 <P>The CUPS API provides two functions for printing files. The first is <CODE>
-cupsPrintFile</CODE> which prints a single named file: </P>
+cupsPrintFile</CODE> which prints a single named file:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1342,14 +1342,14 @@ int jobid;
 jobid = cupsPrintFile(&quot;<I>name</I>&quot;, &quot;<I>filename</I>&quot;, &quot;<I>title</I>&quot;, 0, NULL);
 </PRE>
 </UL>
-<P>The <CODE>name</CODE> string is the name of the printer or class to 
-print to. The <CODE>filename</CODE> string is the name of the file to 
-print. The <CODE>title</CODE> string is the name of the print job, e.g. 
-&quot;Acme Word Document&quot;. </P>
-<P>The return value is a unique ID number for the print job or 0 if 
-there was an error. </P>
+<P>The <CODE>name</CODE> string is the name of the printer or class to
+ print to. The <CODE>filename</CODE> string is the name of the file to
+ print. The <CODE>title</CODE> string is the name of the print job, e.g.
+ &quot;Acme Word Document&quot;.</P>
+<P>The return value is a unique ID number for the print job or 0 if
+ there was an error.</P>
 <H3><A NAME="3_2_3">Printing Multiple Files</A></H3>
-<P>The second printing function is <CODE>cupsPrintFiles</CODE>: </P>
+<P>The second printing function is <CODE>cupsPrintFiles</CODE>:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1365,13 +1365,12 @@ jobid = cupsPrintFiles(&quot;name&quot;, <I>num_files</I>, <I>files</I>, &quot;t
 </PRE>
 </UL>
 <P>Instead of passing a filename string as with <CODE>cupsPrintFile()</CODE>
-, you pass a file count (<CODE>num_files</CODE>) and filename pointer 
-array (<CODE>files</CODE>) for each file that you want to print. </P>
-<P>As with <CODE>cupsPrintFile()</CODE>, the return value is a unique 
-ID for the print job. </P>
+, you pass a file count (<CODE>num_files</CODE>) and filename pointer
+ array (<CODE>files</CODE>) for each file that you want to print.</P>
+<P>As with <CODE>cupsPrintFile()</CODE>, the return value is a unique ID
+ for the print job.</P>
 <H3><A NAME="3_2_4">Cancelling Jobs</A></H3>
-<P>The <CODE>cupsCancelJob()</CODE> function cancels a queued print 
-job: </P>
+<P>The <CODE>cupsCancelJob()</CODE> function cancels a queued print job:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1385,16 +1384,15 @@ int status;
 status = cupsCancelJob(&quot;<I>name</I>&quot;, <I>jobid</I>);
 </PRE>
 </UL>
-<P>The <CODE>name</CODE> string specifies the destination and is used 
-to determine the server to send the request to. The <CODE>jobid</CODE>
+<P>The <CODE>name</CODE> string specifies the destination and is used to
+ determine the server to send the request to. The <CODE>jobid</CODE>
  value is the integer returned from a previous <CODE>cupsPrintFile()</CODE>
- or <CODE>cupsPrintFiles()</CODE> call. </P>
-<P><CODE>cupsCancelJob()</CODE> returns <CODE>1</CODE> if the job was 
-successfully cancelled and <CODE>0</CODE> if there was an error. </P>
+ or <CODE>cupsPrintFiles()</CODE> call.</P>
+<P><CODE>cupsCancelJob()</CODE> returns <CODE>1</CODE> if the job was
+ successfully cancelled and <CODE>0</CODE> if there was an error.</P>
 <H3><A NAME="3_2_5">Getting the Available Printers and Classes</A></H3>
-<P>The <CODE>cupsGetDests()</CODE> function can be used to get a list 
-of the available printers, classes, and instances that a user has 
-defined: </P>
+<P>The <CODE>cupsGetDests()</CODE> function can be used to get a list of
+ the available printers, classes, and instances that a user has defined:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1409,10 +1407,10 @@ cups_dest_t *dests;
 num_dests = cupsGetDests(&amp;dests);
 </PRE>
 </UL>
-<P>Each destination is stored in a <CODE>cups_dest_t</CODE> structure 
-which defines the printer or class name, the instance name (if any), if 
-it is the default destination, and the default options the user has 
-defined for the destination: </P>
+<P>Each destination is stored in a <CODE>cups_dest_t</CODE> structure
+ which defines the printer or class name, the instance name (if any), if
+ it is the default destination, and the default options the user has
+ defined for the destination:</P>
 <UL>
 <PRE>
 typedef struct               /**** Destination ****/
@@ -1425,10 +1423,10 @@ typedef struct               /**** Destination ****/
 } cups_dest_t;
 </PRE>
 </UL>
-<P>The destinations are sorted by name and instance for your 
-convenience. Once you have the list of available destinations, you can 
-lookup a specific destination using the <CODE>cupsGetDest()</CODE>
- function: </P>
+<P>The destinations are sorted by name and instance for your
+ convenience. Once you have the list of available destinations, you can
+ lookup a specific destination using the <CODE>cupsGetDest()</CODE>
+ function:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1444,16 +1442,16 @@ cups_dest_t *mydest;
 mydest = cupsGetDest(&quot;<I>name</I>&quot;, &quot;<I>instance</I>&quot;, num_dests, dests);
 </PRE>
 </UL>
-<P>The <CODE>name</CODE> string is the printer or class name. You can 
-pass a value of <CODE>NULL</CODE> to get the default destination. </P>
-<P>The <CODE>instance</CODE> string is the user-defined instance name. 
-Pass <CODE>NULL</CODE> to select the default instance, e.g. &quot;name&quot; 
-instead of &quot;name/instance&quot;. </P>
+<P>The <CODE>name</CODE> string is the printer or class name. You can
+ pass a value of <CODE>NULL</CODE> to get the default destination.</P>
+<P>The <CODE>instance</CODE> string is the user-defined instance name.
+ Pass <CODE>NULL</CODE> to select the default instance, e.g. &quot;name&quot;
+ instead of &quot;name/instance&quot;.</P>
 <H3><A NAME="3_2_6">Printing with Options</A></H3>
 <P>All of the previous printing examples have passed <CODE>0</CODE> and <CODE>
 NULL</CODE> for the last two arguments to the <CODE>cupsPrintFile()</CODE>
- and <CODE>cupsPrintFiles()</CODE> functions. These last two arguments 
-are the number of options and a pointer to the option array: </P>
+ and <CODE>cupsPrintFiles()</CODE> functions. These last two arguments
+ are the number of options and a pointer to the option array:</P>
 <UL>
 <PRE>
 int cupsPrintFile(const char *name, const char *filename, const char *title,
@@ -1463,12 +1461,12 @@ int cupsPrintFiles(const char *name, int num_files, const char **files,
                   cups_option_t *options);
 </PRE>
 </UL>
-<P>The <CODE>cups_option_t</CODE> structure holds each option and its 
-value. These are converted as needed and passed to the CUPS server when 
-printing a file. </P>
+<P>The <CODE>cups_option_t</CODE> structure holds each option and its
+ value. These are converted as needed and passed to the CUPS server when
+ printing a file.</P>
 <P>The simplest way of handling options is to use the <CODE>num_options</CODE>
  and <CODE>options</CODE> members of the <CODE>cups_dest_t</CODE>
- structure described earlier: </P>
+ structure described earlier:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1488,11 +1486,11 @@ jobid  = cupsPrintFile(mydest-&gt;name, &quot;filename&quot;, &quot;title&quot;,
                        mydest-&gt;num_options, mydest-&gt;options);
 </PRE>
 </UL>
-<P>This effectively uses the options a user has previous selected 
-without a lot of code. </P>
+<P>This effectively uses the options a user has previous selected
+ without a lot of code.</P>
 <H3><A NAME="3_2_7">Setting Printer Options</A></H3>
 <P>Options can also be set by your program using the <CODE>
-cupsAddOption()</CODE> function: </P>
+cupsAddOption()</CODE> function:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1516,13 +1514,13 @@ num_options = cupsAddOption(&quot;<I>name</I>&quot;, &quot;<I>value</I>&quot;, n
 </PRE>
 </UL>
 <P>The <CODE>name</CODE> string is the name of the option, and the <CODE>
-value</CODE> string is the value for that option. </P>
-<P>Each call to <CODE>cupsAddOption()</CODE> returns the new number of 
-options. Since adding two options with the same name overwrites the 
-first value with the second, do not assume that calling <CODE>
-cupsAddOptions()</CODE> 20 times will result in 20 options. </P>
-<P>Call <CODE>cupsFreeOptions</CODE> once you are done using the 
-options: </P>
+value</CODE> string is the value for that option.</P>
+<P>Each call to <CODE>cupsAddOption()</CODE> returns the new number of
+ options. Since adding two options with the same name overwrites the
+ first value with the second, do not assume that calling <CODE>
+cupsAddOptions()</CODE> 20 times will result in 20 options.</P>
+<P>Call <CODE>cupsFreeOptions</CODE> once you are done using the
+ options:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1538,12 +1536,12 @@ cupsFreeOptions(num_options, options);
 </PRE>
 </UL>
 <H3><A NAME="3_2_8">Getting Errors</A></H3>
-<P>If any of the CUPS API printing functions returns an error, the 
-reason for that error can be found by calling <CODE>cupsLastError()</CODE>
+<P>If any of the CUPS API printing functions returns an error, the
+ reason for that error can be found by calling <CODE>cupsLastError()</CODE>
  and <CODE>cupsErrorString()</CODE>. <CODE>cupsLastError()</CODE>
  returns the last IPP error code that was encountered. <CODE>
-cupsErrorString()</CODE> converts the error code to a localized message 
-string suitable for presentation to the user: </P>
+cupsErrorString()</CODE> converts the error code to a localized message
+ string suitable for presentation to the user:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1559,22 +1557,22 @@ if (jobid == 0)
 </PRE>
 </UL>
 <H3><A NAME="3_2_9">Passwords and Authentication</A></H3>
-<P>CUPS supports authentication of any request, including submission of 
-print jobs. The default mechanism for getting the username and password 
-is to use the login user and a password from the console. </P>
-<P>To support other types of applications, in particular Graphical User 
-Interfaces (&quot;GUIs&quot;), the CUPS API provides functions to set the default 
-username and to register a callback function that returns a password 
-string. </P>
-<P>The <A HREF="cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>
- function is used to set a password callback in your program. Only one 
-function can be used at any time. </P>
-<P>The <A HREF="cupsSetUser"><CODE>cupsSetUser()</CODE></A> function 
-sets the current username for authentication. This function can be 
-called by your password callback function to change the current 
-username as needed. </P>
-<P>The following example shows a simple password callback that gets a 
-username and password from the user: </P>
+<P>CUPS supports authentication of any request, including submission of
+ print jobs. The default mechanism for getting the username and password
+ is to use the login user and a password from the console.</P>
+<P>To support other types of applications, in particular Graphical User
+ Interfaces (&quot;GUIs&quot;), the CUPS API provides functions to set the default
+ username and to register a callback function that returns a password
+ string.</P>
+<P>The<A HREF="cupsSetPasswordCB"> <CODE>cupsSetPasswordCB()</CODE></A>
+ function is used to set a password callback in your program. Only one
+ function can be used at any time.</P>
+<P>The<A HREF="cupsSetUser"> <CODE>cupsSetUser()</CODE></A> function
+ sets the current username for authentication. This function can be
+ called by your password callback function to change the current
+ username as needed.</P>
+<P>The following example shows a simple password callback that gets a
+ username and password from the user:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1606,30 +1604,30 @@ my_password_cb(const char *prompt)
 cupsSetPasswordCB(my_password_cb);
 </PRE>
 </UL>
-<P>Similarly, a GUI interface could display the prompt string in a 
-window with input fields for the username and password. The username 
-should probably default to the value of <A HREF="#cupsUser"><CODE>
-cupsUser()</CODE></A> to make things easier on the user. </P>
+<P>Similarly, a GUI interface could display the prompt string in a
+ window with input fields for the username and password. The username
+ should probably default to the value of<A HREF="#cupsUser"> <CODE>
+cupsUser()</CODE></A> to make things easier on the user.</P>
 <H2><A NAME="3_3">PPD Services</A></H2>
-<P>CUPS includes functions to access and manipulate PostScript Printer 
-Description (&quot;PPD&quot;) files that are used with the printer drivers in 
-CUPS. </P>
-<P>Each PPD file enumerates the available features provided by a 
-printer, including conflict information for specific options (e.g. 
-can't duplex output on envelopes.) </P>
+<P>CUPS includes functions to access and manipulate PostScript Printer
+ Description (&quot;PPD&quot;) files that are used with the printer drivers in
+ CUPS.</P>
+<P>Each PPD file enumerates the available features provided by a
+ printer, including conflict information for specific options (e.g.
+ can't duplex output on envelopes.)</P>
 <H3><A NAME="3_3_1">Include Files</A></H3>
-<P>Include the <CODE>&lt;cups/ppd.h&gt;</CODE> header file to use the PPD 
-functions: </P>
+<P>Include the <CODE>&lt;cups/ppd.h&gt;</CODE> header file to use the PPD
+ functions:</P>
 <UL>
 <PRE>
 #include &lt;cups/ppd.h&gt;
 </PRE>
 </UL>
 <P>This header file is also included by the <CODE>&lt;cups/cups.h&gt;</CODE>
- header file. </P>
+ header file.</P>
 <H3><A NAME="3_3_2">Getting a PPD File for a Printer</A></H3>
-<P>The <CODE>cupsGetPPD()</CODE> function retrieves the PPD file for 
-the named printer or class: </P>
+<P>The <CODE>cupsGetPPD()</CODE> function retrieves the PPD file for the
+ named printer or class:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1641,16 +1639,16 @@ const char *filename;
 filename = cupsGetPPD(&quot;<I>name</I>&quot;);
 </PRE>
 </UL>
-<P>The <CODE>name</CODE> string is the name of the printer or class, 
-including the remote server name as appropriate (e.g. 
-&quot;printer@server&quot;.) </P>
-<P>The return value is a pointer to a filename in static storage; this 
-value is overwritten with each call to <CODE>cupsGetPPD()</CODE>. If 
-the printer or class does not exist, a <CODE>NULL</CODE> pointer will 
-be returned. </P>
+<P>The <CODE>name</CODE> string is the name of the printer or class,
+ including the remote server name as appropriate (e.g.
+ &quot;printer@server&quot;.)</P>
+<P>The return value is a pointer to a filename in static storage; this
+ value is overwritten with each call to <CODE>cupsGetPPD()</CODE>. If
+ the printer or class does not exist, a <CODE>NULL</CODE> pointer will
+ be returned.</P>
 <H3><A NAME="3_3_3">Loading a PPD File</A></H3>
-<P>The <CODE>ppdOpenFile()</CODE> function &quot;opens&quot; a PPD file and loads 
-it into memory: </P>
+<P>The <CODE>ppdOpenFile()</CODE> function &quot;opens&quot; a PPD file and loads
+ it into memory:</P>
 <UL>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -1662,13 +1660,13 @@ ppd_file_t *ppd;
 ppd = ppdOpenFile(&quot;<I>filename</I>&quot;);
 </PRE>
 </UL>
-<P>The <CODE>filename</CODE> string is the name of the file to load, 
-such as the value returned by the <CODE>cupsGetPPD()</CODE> function. </P>
-<P>The return value is a pointer to a structure describing the contents 
-of the PPD file or NULL if the PPD file could not be read. </P>
+<P>The <CODE>filename</CODE> string is the name of the file to load,
+ such as the value returned by the <CODE>cupsGetPPD()</CODE> function.</P>
+<P>The return value is a pointer to a structure describing the contents
+ of the PPD file or NULL if the PPD file could not be read.</P>
 <H3><A NAME="3_3_4">Freeing PPD File Information</A></H3>
 <P>Once you are done using a PPD file, call the <CODE>ppdClose()</CODE>
- function to free all memory that has been used: </P>
+ function to free all memory that has been used:</P>
 <UL>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -1683,41 +1681,40 @@ ppdClose(ppd);
 </PRE>
 </UL>
 <H3><A NAME="3_3_5">The PPD File Structure</A></H3>
-<P>Each PPD file contains a number of capability attributes, printer 
-options, and conflict definitions. The page size options also include 
-the physical margins for the printer and the minimum and maximum sizes 
-for the printer. All of this information is stored in the <CODE>
-ppd_file_t</CODE> structure. </P>
+<P>Each PPD file contains a number of capability attributes, printer
+ options, and conflict definitions. The page size options also include
+ the physical margins for the printer and the minimum and maximum sizes
+ for the printer. All of this information is stored in the <CODE>
+ppd_file_t</CODE> structure.</P>
 <H4>Capabilities</H4>
-<P>Each PPD file contains a number of informational attributes that 
-describe the capabilities of the printer. These are provided in the <CODE>
-ppd_file_t</CODE> structure in the following members: 
+<P>Each PPD file contains a number of informational attributes that
+ describe the capabilities of the printer. These are provided in the <CODE>
+ppd_file_t</CODE> structure in the following members:
 <CENTER>
 <TABLE BORDER="1" WIDTH="80%">
 <TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
-<TR><TD><CODE>accurate_screens</CODE></TD><TD><CODE>int</CODE></TD><TD>
-1 = supports accurate screens</TD></TR>
-<TR><TD><CODE>color_device</CODE></TD><TD><CODE>int</CODE></TD><TD>1 = 
-color device</TD></TR>
+<TR><TD><CODE>accurate_screens</CODE></TD><TD><CODE>int</CODE></TD><TD>1
+ = supports accurate screens</TD></TR>
+<TR><TD><CODE>color_device</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ color device</TD></TR>
 <TR><TD><CODE>colorspace</CODE></TD><TD><CODE>ppd_cs_t</CODE></TD><TD>
-Default colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY,  PPD_CS_RGB, 
-PPD_CS_RGBK, PPD_CS_N</TD></TR>
-<TR><TD><CODE>contone_only</CODE></TD><TD><CODE>int</CODE></TD><TD>1 = 
-printer is continuous tone only</TD></TR>
+Default colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY, PPD_CS_RGB,
+ PPD_CS_RGBK, PPD_CS_N</TD></TR>
+<TR><TD><CODE>contone_only</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ printer is continuous tone only</TD></TR>
 <TR><TD><CODE>num_emulations
 <BR> emulations</CODE></TD><TD><CODE>int
-<BR> ppd_emul_t *</CODE></TD><TD>Emulations supported by the 
-printer</TD></TR>
-<TR><TD><CODE>flip_duplex</CODE></TD><TD><CODE>int</CODE></TD><TD>1 = 
-need to flip odd pages when duplexing</TD></TR>
+<BR> ppd_emul_t *</CODE></TD><TD>Emulations supported by the printer</TD>
+</TR>
+<TR><TD><CODE>flip_duplex</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ need to flip odd pages when duplexing</TD></TR>
 <TR><TD><CODE>num_fonts
 <BR> fonts</CODE></TD><TD><CODE>int
-<BR> char **</CODE></TD><TD>The fonts available on the printer.</TD>
-</TR>
+<BR> char **</CODE></TD><TD>The fonts available on the printer.</TD></TR>
 <TR><TD><CODE>jcl_begin
 <BR> jcl_ps
-<BR> jcl_end</CODE></TD><TD><CODE>char *</CODE></TD><TD>Job 
-Control Language commands for PostScript output</TD></TR>
+<BR> jcl_end</CODE></TD><TD><CODE>char *</CODE></TD><TD>Job Control
+ Language commands for PostScript output</TD></TR>
 <TR><TD><CODE>landscape</CODE></TD><TD><CODE>int</CODE></TD><TD>
 Landscape orientation, -90 or 90 degrees</TD></TR>
 <TR><TD><CODE>lang_encoding</CODE></TD><TD><CODE>char *</CODE></TD><TD>
@@ -1726,52 +1723,53 @@ The character used for the option strings</TD></TR>
 The language used for the options strings (English, French, etc.)</TD></TR>
 <TR><TD><CODE>language_level</CODE></TD><TD><CODE>int</CODE></TD><TD>
 PostScript language level, 1 to 3</TD></TR>
-<TR><TD><CODE>manual_copies</CODE></TD><TD><CODE>int</CODE></TD><TD>1 = 
-Copies are done manually</TD></TR>
+<TR><TD><CODE>manual_copies</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ Copies are done manually</TD></TR>
 <TR><TD><CODE>model_number</CODE></TD><TD><CODE>int</CODE></TD><TD>
 Driver-specific model number.</TD></TR>
-<TR><TD><CODE>patches</CODE></TD><TD><CODE>char *</CODE></TD><TD>Patch 
-commands to send to the printer</TD></TR>
+<TR><TD><CODE>patches</CODE></TD><TD><CODE>char *</CODE></TD><TD>Patch
+ commands to send to the printer</TD></TR>
 <TR><TD><CODE>manufacturer</CODE></TD><TD><CODE>char *</CODE></TD><TD>
 The Manufacturer attribute from the PPD file, if any</TD></TR>
-<TR><TD><CODE>modelname</CODE></TD><TD><CODE>char *</CODE></TD><TD>The 
-ModelName attribute from the PPD file</TD></TR>
-<TR><TD><CODE>nickname</CODE></TD><TD><CODE>char *</CODE></TD><TD>The 
-NickName attribute from the PPD file, if any</TD></TR>
-<TR><TD><CODE>product</CODE></TD><TD><CODE>char *</CODE></TD><TD>The 
-Product attribute from the PPD file, if any</TD></TR>
+<TR><TD><CODE>modelname</CODE></TD><TD><CODE>char *</CODE></TD><TD>The
+ ModelName attribute from the PPD file</TD></TR>
+<TR><TD><CODE>nickname</CODE></TD><TD><CODE>char *</CODE></TD><TD>The
+ NickName attribute from the PPD file, if any</TD></TR>
+<TR><TD><CODE>product</CODE></TD><TD><CODE>char *</CODE></TD><TD>The
+ Product attribute from the PPD file, if any</TD></TR>
 <TR><TD><CODE>shortnickname</CODE></TD><TD><CODE>char *</CODE></TD><TD>
 The ShortNickName attribute from the PPD file, if any</TD></TR>
-<TR><TD><CODE>throughput</CODE></TD><TD><CODE>int</CODE></TD><TD>Number 
-of pages per minute</TD></TR>
+<TR><TD><CODE>throughput</CODE></TD><TD><CODE>int</CODE></TD><TD>Number
+ of pages per minute</TD></TR>
 <TR><TD><CODE>ttrasterizer</CODE></TD><TD><CODE>char *</CODE></TD><TD>
 The TruType font rasterizer (Type42)</TD></TR>
-<TR><TD><CODE>variable_sizes</CODE></TD><TD><CODE>int</CODE></TD><TD>1 
-= supports variable sizes</TD></TR>
+<TR><TD><CODE>variable_sizes</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ supports variable sizes</TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H4>Options and Groups</H4>
 <P>PPD files support multiple options, which are stored in <CODE>
-ppd_option_t</CODE> and <CODE>ppd_choice_t</CODE> structures by the PPD 
-functions. </P>
+ppd_option_t</CODE> and <CODE>ppd_choice_t</CODE> structures by the PPD
+ functions.</P>
 <P>Each option in turn is associated with a group stored in the <CODE>
-ppd_group_t</CODE> structure. Groups can be specified in the PPD file; 
-if an option is not associated with a group then it is put in a 
-&quot;General&quot; or &quot;Extra&quot; group depending on the option. </P>
-<P>Groups can also have sub-groups; CUPS currently limits the depth of 
-sub-groups to 1 level to reduce programming complexity. </P>
+ppd_group_t</CODE> structure. Groups can be specified in the PPD file;
+ if an option is not associated with a group then it is put in a
+ &quot;General&quot; or &quot;Extra&quot; group depending on the option.</P>
+<P>Groups can also have sub-groups; CUPS currently limits the depth of
+ sub-groups to 1 level to reduce programming complexity.</P>
 <H4>Conflicts</H4>
-<P>PPD files support specification of conflict conditions between 
-different options. Conflicts are stored in <CODE>ppd_conflict_t</CODE>
- structures which specify the options that conflict with each other. </P>
+<P>PPD files support specification of conflict conditions between
+ different options. Conflicts are stored in <CODE>ppd_conflict_t</CODE>
+ structures which specify the options that conflict with each other.</P>
 <H4>Page Sizes</H4>
-<P>PPD files specify all of the available pages sizes and the physical 
-margins associated with them. These sizes are stored in <CODE>ppd_size_t</CODE>
- structures and are available in the <CODE>num_sizes</CODE> and <CODE>
-sizes</CODE> members of the <CODE>ppd_file_t</CODE> structure. You can 
-lookup a particular page size with the <CODE>ppdPageWidth()</CODE>, <CODE>
-ppdPageLength()</CODE>, and <CODE>ppdPageSize()</CODE> functions: </P>
+<P>PPD files specify all of the available pages sizes and the physical
+ margins associated with them. These sizes are stored in <CODE>
+ppd_size_t</CODE> structures and are available in the <CODE>num_sizes</CODE>
+ and <CODE>sizes</CODE> members of the <CODE>ppd_file_t</CODE>
+ structure. You can lookup a particular page size with the <CODE>
+ppdPageWidth()</CODE>, <CODE>ppdPageLength()</CODE>, and <CODE>
+ppdPageSize()</CODE> functions:</P>
 <UL>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -1790,10 +1788,10 @@ width  = ppdPageWidth(ppd, &quot;<I>size</I>&quot;);
 length = ppdPageLength(ppd, &quot;<I>size</I>&quot;);
 </PRE>
 </UL>
-<P>The <CODE>size</CODE> string is the named page size option. The 
-width and length are in points; there are 72 points per inch. The <CODE>
-ppd_size_t</CODE> structure contains the width, length, and margin 
-information: </P>
+<P>The <CODE>size</CODE> string is the named page size option. The width
+ and length are in points; there are 72 points per inch. The <CODE>
+ppd_size_t</CODE> structure contains the width, length, and margin
+ information:</P>
 <UL>
 <PRE>
 typedef struct    /**** Page Sizes ****/
@@ -1810,14 +1808,14 @@ typedef struct    /**** Page Sizes ****/
 </PRE>
 </UL>
 <H4>Custom Page Sizes</H4>
-<P>Besides the standard page sizes listed in a PPD file, some printers 
-support variable or custom page sizes. If <CODE>variables_sizes</CODE>
+<P>Besides the standard page sizes listed in a PPD file, some printers
+ support variable or custom page sizes. If <CODE>variables_sizes</CODE>
  is non-zero, the <CODE>custom_min</CODE>, <CODE>custom_max</CODE>, and <CODE>
-custom_margins</CODE> members of the <CODE>ppd_file_t</CODE> structure 
-define the limits of the variable sizes. </P>
+custom_margins</CODE> members of the <CODE>ppd_file_t</CODE> structure
+ define the limits of the variable sizes.</P>
 <P>To get the resulting media size, use a page size string of <CODE>
 Custom.<I>width</I>x<I>length</I></CODE>, where <CODE>width</CODE> and <CODE>
-length</CODE> are integer values in points: </P>
+length</CODE> are integer values in points:</P>
 <UL>
 <PRE>
 Custom.612x792   [8.5 inches wide, 11 inches long]
@@ -1826,8 +1824,8 @@ Custom.1224x792  [17 inches wide, 11 inches long]
 </UL>
 <H3><A NAME="3_3_6">Marking Options</A></H3>
 <P>Before marking any user-defined options, call the <CODE>
-ppdMarkDefaults()</CODE> function to mark the default options from the 
-PPD file: </P>
+ppdMarkDefaults()</CODE> function to mark the default options from the
+ PPD file:</P>
 <UL>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -1841,8 +1839,8 @@ ppd_file_t *ppd;
 ppdMarkDefaults(ppd);
 </PRE>
 </UL>
-<P>Then call the <CODE>ppdMarkOption()</CODE> function to mark 
-individual options: </P>
+<P>Then call the <CODE>ppdMarkOption()</CODE> function to mark
+ individual options:</P>
 <UL>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -1857,11 +1855,11 @@ int        conflicts;
 conflicts = ppdMarkOption(ppd, &quot;<I>name</I>&quot;, &quot;<I>value</I>&quot;);
 </PRE>
 </UL>
-<P>The <CODE>name</CODE> and <CODE>value</CODE> strings choose a 
-particular option and choice, respectively. The return value is 0 if 
-there are not conflicts created by the selection. </P>
-<P>CUPS also provides a convenience function for marking all options in 
-the <CODE>cups_option_t</CODE> structure: </P>
+<P>The <CODE>name</CODE> and <CODE>value</CODE> strings choose a
+ particular option and choice, respectively. The return value is 0 if
+ there are not conflicts created by the selection.</P>
+<P>CUPS also provides a convenience function for marking all options in
+ the <CODE>cups_option_t</CODE> structure:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1878,15 +1876,15 @@ int           conflicts;
 conflicts = cupsMarkOptions(ppd, num_options, options);
 </PRE>
 </UL>
-<P>The <CODE>cupsMarkOptions()</CODE> function also handles mapping the 
-IPP job template attributes to PPD options. The return value is the 
-number of conflicts present. </P>
+<P>The <CODE>cupsMarkOptions()</CODE> function also handles mapping the
+ IPP job template attributes to PPD options. The return value is the
+ number of conflicts present.</P>
 <H3><A NAME="3_3_7">Checking for Conflicts</A></H3>
 <P>The <CODE>ppdMarkOption()</CODE> and <CODE>cupsMarkOptions()</CODE>
- functions return the number of conflicts with the currently marked 
-options. </P>
-<P>Call the <CODE>ppdConflicts()</CODE> function to get the number of 
-conflicts after you have marked all of the options: </P>
+ functions return the number of conflicts with the currently marked
+ options.</P>
+<P>Call the <CODE>ppdConflicts()</CODE> function to get the number of
+ conflicts after you have marked all of the options:</P>
 <UL>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -1901,124 +1899,124 @@ int        conflicts;
 conflicts = ppdConflicts(ppd);
 </PRE>
 </UL>
-<P>The return value is the number of conflicting options, or 0 if there 
-are no conflicts. </P>
+<P>The return value is the number of conflicting options, or 0 if there
+ are no conflicts.</P>
 <H1 ALIGN="RIGHT"><A NAME="WRITING_FILTERS">3 - Writing Filters</A></H1>
-<P>This chapter describes how to write a file filter for CUPS. </P>
+<P>This chapter describes how to write a file filter for CUPS.</P>
 <H2><A NAME="4_1">Overview</A></H2>
-<P>File filters are programs that convert from one or more MIME types 
-to another type. Filters use a common command-line and environment 
-interface that allows them to be joined as needed to print files to any 
-type of printer. </P>
+<P>File filters are programs that convert from one or more MIME types to
+ another type. Filters use a common command-line and environment
+ interface that allows them to be joined as needed to print files to any
+ type of printer.</P>
 <H3><A NAME="4_1_1">Security Considerations</A></H3>
-<P>Filters are normally run as a non-priviledged user, so the major 
-security consideration is resource utilization - filters should not 
-depend on unlimited amounts of memory and disk space. </P>
+<P>Filters are normally run as a non-priviledged user, so the major
+ security consideration is resource utilization - filters should not
+ depend on unlimited amounts of memory and disk space.</P>
 <H3><A NAME="4_1_2">Users and Groups</A></H3>
-<P>The default CUPS configuration runs filters as user &quot;lp&quot; and group 
-&quot;other&quot;. </P>
+<P>The default CUPS configuration runs filters as user &quot;lp&quot; and group
+ &quot;other&quot;.</P>
 <H3><A NAME="4_1_3">Temporary Files</A></H3>
-<P>Temporary files should be created in the directory specified by the 
-&quot;TMPDIR&quot; environment variable. The <A HREF="#cupsTempFile"><CODE>
-cupsTempFile()</CODE></A> function can be used to safely choose 
-temporary files in this directory. </P>
+<P>Temporary files should be created in the directory specified by the
+ &quot;TMPDIR&quot; environment variable. The<A HREF="#cupsTempFile"> <CODE>
+cupsTempFile()</CODE></A> function can be used to safely choose
+ temporary files in this directory.</P>
 <H3><A NAME="4_1_4">Sending Messages to the User</A></H3>
-<P>The CUPS scheduler collects messages sent to the standard error file 
-by the filter. These messages are relayed to the user based upon the 
-scheduler <CODE>LogLevel</CODE> directive. </P>
-<P>The type of message is determined by an initial prefix sent on each 
-line: </P>
-<UL>
-<LI><CODE>DEBUG:</CODE> - a debug message </LI>
-<LI><CODE>INFO:</CODE> - an informational message </LI>
-<LI><CODE>WARNING:</CODE> - a warning message </LI>
-<LI><CODE>ERROR:</CODE> - an error message </LI>
-<LI><CODE>PAGE:</CODE> - a page accounting message </LI>
-</UL>
-<P>If the line of text does not begin with any of the above prefixes, 
-it is treated as a debug message. Text following the prefix is copied 
-to the <CODE>printer-state-message</CODE> attribute for the printer, 
-and also added to the <VAR>error_log</VAR> unless it is an 
-informational or page accounting message. </P>
+<P>The CUPS scheduler collects messages sent to the standard error file
+ by the filter. These messages are relayed to the user based upon the
+ scheduler <CODE>LogLevel</CODE> directive.</P>
+<P>The type of message is determined by an initial prefix sent on each
+ line:</P>
+<UL>
+<LI><CODE>DEBUG:</CODE> - a debug message</LI>
+<LI><CODE>INFO:</CODE> - an informational message</LI>
+<LI><CODE>WARNING:</CODE> - a warning message</LI>
+<LI><CODE>ERROR:</CODE> - an error message</LI>
+<LI><CODE>PAGE:</CODE> - a page accounting message</LI>
+</UL>
+<P>If the line of text does not begin with any of the above prefixes, it
+ is treated as a debug message. Text following the prefix is copied to
+ the <CODE>printer-state-message</CODE> attribute for the printer, and
+ also added to the<VAR> error_log</VAR> unless it is an informational or
+ page accounting message.</P>
 <H3><A NAME="4_1_5">Page Accounting</A></H3>
-<P>Page accounting messages are used to inform the server when one or 
-more pages are printed. Each line has the form: </P>
+<P>Page accounting messages are used to inform the server when one or
+ more pages are printed. Each line has the form:</P>
 <UL>
 <PRE>
 PAGE: page-number copy-count
 </PRE>
 </UL>
-<P>The <I>page-number</I> field is the current page number, starting at 
-1. The <I>copy-count</I> field specifies the number of copies of that 
-page that was produced. </P>
-<P>Page account messages are added to the <VAR>page_log</VAR> file and 
-cause the <CODE>job-sheets-completed</CODE> attribute to be updated for 
-the job. </P>
+<P>The<I> page-number</I> field is the current page number, starting at
+ 1. The<I> copy-count</I> field specifies the number of copies of that
+ page that was produced.</P>
+<P>Page account messages are added to the<VAR> page_log</VAR> file and
+ cause the <CODE>job-sheets-completed</CODE> attribute to be updated for
+ the job.</P>
 <H3><A NAME="4_1_6">Command-Line Arguments</A></H3>
-<P>Every filter accepts exactly 6 or 7 command-line arguments: </P>
+<P>Every filter accepts exactly 6 or 7 command-line arguments:</P>
 <UL>
 <PRE>
 printer job user title copies options [filename]
 </PRE>
-<LI><CODE>printer</CODE> - The name of the printer queue (normally 
this is the name of the program being run) </LI>
-<LI><CODE>job</CODE> - The numeric job ID for the job being  printed </LI>
-<LI><CODE>user</CODE> - The string from the <CODE> originating-user-name</CODE>
- attribute </LI>
-<LI><CODE>title</CODE> - The string from the <CODE> job-name</CODE>
- attribute </LI>
-<LI><CODE>copies</CODE> - The numeric value from the <CODE>
number-copies</CODE> attribute </LI>
-<LI><CODE>options</CODE> - String representations of the  job template 
-attributes, separated by spaces. Boolean attributes  are provided as 
-&quot;name&quot; for true values and &quot;noname&quot; for false  values. All other 
-attributes are provided as &quot;name=value&quot; for  single-valued attributes 
-and &quot;name=value1,value2,...,valueN&quot; for  set attributes </LI>
-<LI><CODE>filename</CODE> - The request file </LI>
-</UL>
-<P>The <I>filename</I> argument is only provided to the first filter in 
-the chain; all filters <B>must</B> be prepared to read the print file 
-from the standard input if the <I>filename</I> argument is omitted. </P>
+<LI><CODE>printer</CODE> - The name of the printer queue (normally this
is the name of the program being run)</LI>
+<LI><CODE>job</CODE> - The numeric job ID for the job being printed</LI>
+<LI><CODE>user</CODE> - The string from the <CODE>originating-user-name</CODE>
+ attribute</LI>
+<LI><CODE>title</CODE> - The string from the <CODE>job-name</CODE>
+ attribute</LI>
+<LI><CODE>copies</CODE> - The numeric value from the <CODE>number-copies</CODE>
attribute</LI>
+<LI><CODE>options</CODE> - String representations of the job template
+ attributes, separated by spaces. Boolean attributes are provided as
+ &quot;name&quot; for true values and &quot;noname&quot; for false values. All other
+ attributes are provided as &quot;name=value&quot; for single-valued attributes
+ and &quot;name=value1,value2,...,valueN&quot; for set attributes</LI>
+<LI><CODE>filename</CODE> - The request file</LI>
+</UL>
+<P>The<I> filename</I> argument is only provided to the first filter in
+ the chain; all filters<B> must</B> be prepared to read the print file
+ from the standard input if the<I> filename</I> argument is omitted.</P>
 <H3><A NAME="4_1_7">Copy Generation</A></H3>
-<P>The <I>copies</I> argument specifies the number of copies to produce 
-of the input file. In general, you should only generate copies if the <I>
-filename</I> argument is supplied. The only exception to this are 
-filters that produce device-independent PostScript output (without any 
-printer commands from the printer's PPD file), since the PostScript 
-filter <CODE>pstops</CODE> is responsible for copy generation. </P>
+<P>The<I> copies</I> argument specifies the number of copies to produce
+ of the input file. In general, you should only generate copies if the<I>
+ filename</I> argument is supplied. The only exception to this are
+ filters that produce device-independent PostScript output (without any
+ printer commands from the printer's PPD file), since the PostScript
+ filter <CODE>pstops</CODE> is responsible for copy generation.</P>
 <H3><A NAME="4_1_8">Environment Variables</A></H3>
-<P>Every filter receives a fixed set of environment variables that can 
-be used by the filter: </P>
-<UL>
-<LI><CODE>CHARSET</CODE> - The character set used by the client for 
this print file </LI>
-<LI><CODE>CONTENT_TYPE</CODE> - The original document type, such as 
- &quot;application/postscript&quot; </LI>
-<LI><CODE>CUPS_DATADIR</CODE> - The location of CUPS data files </LI>
-<LI><CODE>CUPS_SERVERROOT</CODE> - The location of CUPS configuration 
- files </LI>
-<LI><CODE>DEVICE_URI</CODE> - The output device URI </LI>
-<LI><CODE>LANG</CODE> - The language used by the client for  this print 
-file </LI>
-<LI><CODE>PATH</CODE> - The execution path exported to the filter </LI>
-<LI><CODE>PPD</CODE> - The full filename of the printer's PPD file </LI>
-<LI><CODE>PRINTER</CODE> - The name of the printer queue </LI>
-<LI><CODE>RIP_CACHE</CODE> - The maximum amount of memory each filter 
- should use </LI>
-<LI><CODE>SOFTWARE</CODE> - The name of the CUPS software, typically 
- &quot;CUPS/1.1&quot; </LI>
-<LI><CODE>TZ</CODE> - The local timezone </LI>
-<LI><CODE>USER</CODE> - The name of the current user </LI>
+<P>Every filter receives a fixed set of environment variables that can
+ be used by the filter:</P>
+<UL>
+<LI><CODE>CHARSET</CODE> - The character set used by the client for this
print file</LI>
+<LI><CODE>CONTENT_TYPE</CODE> - The original document type, such as
+ &quot;application/postscript&quot;</LI>
+<LI><CODE>CUPS_DATADIR</CODE> - The location of CUPS data files</LI>
+<LI><CODE>CUPS_SERVERROOT</CODE> - The location of CUPS configuration
+ files</LI>
+<LI><CODE>DEVICE_URI</CODE> - The output device URI</LI>
+<LI><CODE>LANG</CODE> - The language used by the client for this print
+ file</LI>
+<LI><CODE>PATH</CODE> - The execution path exported to the filter</LI>
+<LI><CODE>PPD</CODE> - The full filename of the printer's PPD file</LI>
+<LI><CODE>PRINTER</CODE> - The name of the printer queue</LI>
+<LI><CODE>RIP_CACHE</CODE> - The maximum amount of memory each filter
+ should use</LI>
+<LI><CODE>SOFTWARE</CODE> - The name of the CUPS software, typically
+ &quot;CUPS/1.1&quot;</LI>
+<LI><CODE>TZ</CODE> - The local timezone</LI>
+<LI><CODE>USER</CODE> - The name of the current user</LI>
 </UL>
 <H2><A NAME="4_2">Dissecting the HP-GL/2 Filter</A></H2>
-<P>The HP-GL/2 filter (<CODE>hpgltops</CODE>) provided with CUPS is a 
-complex program that converts HP-GL/2 files into device-independent 
-PostScript output. Since it produces device-independent PostScript 
-output, it does not need to handle copy generation or writing printer 
-options from the printer's PPD file. </P>
+<P>The HP-GL/2 filter (<CODE>hpgltops</CODE>) provided with CUPS is a
+ complex program that converts HP-GL/2 files into device-independent
+ PostScript output. Since it produces device-independent PostScript
+ output, it does not need to handle copy generation or writing printer
+ options from the printer's PPD file.</P>
 <H3><A NAME="4_2_1">Initializing the Filter</A></H3>
-<P>The first task of any filter is to ensure that the correct number of 
-command-line arguments are present: </P>
+<P>The first task of any filter is to ensure that the correct number of
+ command-line arguments are present:</P>
 <UL>
 <PRE>
 if (argc &lt; 6 || argc &gt; 7)
@@ -2028,8 +2026,8 @@ if (argc &lt; 6 || argc &gt; 7)
 }
 </PRE>
 </UL>
-<P>After this you open the print file or read from the standard input 
-as needed: </P>
+<P>After this you open the print file or read from the standard input as
+ needed:</P>
 <UL>
 <PRE>
 FILE *fp;
@@ -2055,9 +2053,9 @@ else
 }
 </PRE>
 </UL>
-<P>Once the print file has been opened, options can be processed using 
-the <A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A> and <A
-HREF="#cupsGetOption"><CODE>cupsGetOption()</CODE></A> functions: </P>
+<P>Once the print file has been opened, options can be processed using
+ the<A HREF="#cupsParseOptions"> <CODE>cupsParseOptions()</CODE></A> and<A
+HREF="#cupsGetOption"> <CODE>cupsGetOption()</CODE></A> functions:</P>
 <UL>
 <PRE>
 int           num_options;
@@ -2081,13 +2079,13 @@ if ((val = cupsGetOption(&quot;penwidth&quot;, num_options, options)) != NULL)
   PenWidth = (float)atoi(val) * 0.001f;
 </PRE>
 </UL>
-<P>After the options have been processed, the filter writes PostScript 
-code to the standard output based on the print file, closes the print 
-file (as needed), and returns 0 to the scheduler. </P>
+<P>After the options have been processed, the filter writes PostScript
+ code to the standard output based on the print file, closes the print
+ file (as needed), and returns 0 to the scheduler.</P>
 <H2><A NAME="4_3">PostScript Output</A></H2>
-<P>Filters that produce PostScript output must generate output 
-conforming to the Adobe Document Structuring Conventions, 3.0. In 
-general this means the beginning of each file must begin with: </P>
+<P>Filters that produce PostScript output must generate output
+ conforming to the Adobe Document Structuring Conventions, 3.0. In
+ general this means the beginning of each file must begin with:</P>
 <UL>
 <PRE>
 %!PS-Adobe-3.0
@@ -2096,9 +2094,9 @@ general this means the beginning of each file must begin with: </P>
 %%EndComments
 </PRE>
 </UL>
-<P>The <I>left</I>, <I>bottom</I>, <I>right</I>, and <I>top</I> values 
-are integers in points from the lower-lefthand corner of the page. </P>
-<P>Pages must be surrounded by: </P>
+<P>The<I> left</I>,<I> bottom</I>,<I> right</I>, and<I> top</I> values
+ are integers in points from the lower-lefthand corner of the page.</P>
+<P>Pages must be surrounded by:</P>
 <UL>
 <PRE>
 %%Page: number number
@@ -2108,7 +2106,7 @@ grestore
 showpage
 </PRE>
 </UL>
-<P>And the end of each file must contain: </P>
+<P>And the end of each file must contain:</P>
 <UL>
 <PRE>
 %%Trailer
@@ -2116,126 +2114,125 @@ showpage
 %%EOF
 </PRE>
 </UL>
-<P>These comments allow the PostScript filter to correctly perform page 
-accounting, copy generation, N-up printing, and so forth. </P>
+<P>These comments allow the PostScript filter to correctly perform page
+ accounting, copy generation, N-up printing, and so forth.</P>
 <H1 ALIGN="RIGHT"><A NAME="WRITING_DRIVERS">4 - Writing Printer Drivers</A>
 </H1>
-<P>This chapter discusses how to write a printer driver, which is a 
-special filter program that converts CUPS raster data into the 
-appropriate commands and data required for a printer. </P>
+<P>This chapter discusses how to write a printer driver, which is a
+ special filter program that converts CUPS raster data into the
+ appropriate commands and data required for a printer.</P>
 <H2><A NAME="5_1">Overview</A></H2>
-<P>Raster printers utilitize PPD files that specify one or more 
-device-specific filters that handle converting print files for the 
-printer. The simplest raster printer drivers provide a single filter 
-that converts CUPS raster data to the printer's native format. </P>
+<P>Raster printers utilitize PPD files that specify one or more
+ device-specific filters that handle converting print files for the
+ printer. The simplest raster printer drivers provide a single filter
+ that converts CUPS raster data to the printer's native format.</P>
 <H3><A NAME="5_1_1">CUPS Raster Data</A></H3>
-<P>CUPS raster data (<CODE>application/vnd.cups-raster</CODE>) consists 
-of a stream of raster page descriptions produced by one of the RIP 
-filters, such as <CODE>pstoraster</CODE> or <CODE>imagetoraster</CODE>. </P>
-<P>Each page of data begins with a page dictionary structure called <A HREF="#cups_raster_header_t">
-<CODE>cups_raster_header_t</CODE></A>. This structure contains the 
-colorspace, bits per color, media size, media type, hardware 
-resolution, and so forth. </P>
-<P>After the page dictionary comes the page data which is a 
-full-resolution, uncompressed bitmap representing the page in the 
-printer's output colorspace. </P>
+<P>CUPS raster data (<CODE>application/vnd.cups-raster</CODE>) consists
+ of a stream of raster page descriptions produced by one of the RIP
+ filters, such as <CODE>pstoraster</CODE> or <CODE>imagetoraster</CODE>.</P>
+<P>Each page of data begins with a page dictionary structure called<A HREF="#cups_raster_header_t">
+ <CODE>cups_raster_header_t</CODE></A>. This structure contains the
+ colorspace, bits per color, media size, media type, hardware
+ resolution, and so forth.</P>
+<P>After the page dictionary comes the page data which is a
+ full-resolution, uncompressed bitmap representing the page in the
+ printer's output colorspace.</P>
 <H3><A NAME="5_1_2">Page Accounting</A></H3>
-<P>Printer drivers must handle all page accounting. This means they 
-must send &quot;PAGE:&quot; messages to the standard error file for each page 
-(and in many cases, copy) sent to the printer. </P>
+<P>Printer drivers must handle all page accounting. This means they must
+ send &quot;PAGE:&quot; messages to the standard error file for each page (and in
+ many cases, copy) sent to the printer.</P>
 <H3><A NAME="5_1_3">Color Management</A></H3>
 <P>Printer drivers can implement their color management via the <CODE>
-cupsColorProfile</CODE> attributes in the PPD file or internally in the 
-driver from a device-independent colorspace. In general, color 
-management performed by the RIP filters is more efficient than that 
-performed inside printer drivers. </P>
-<P>For example, the <CODE>pstoraster</CODE> filter often only has to 
-perform a color conversion once each time the color is used for 
-multiple output pixels, while the raster filter must convert every 
-pixel on the page. </P>
+cupsColorProfile</CODE> attributes in the PPD file or internally in the
+ driver from a device-independent colorspace. In general, color
+ management performed by the RIP filters is more efficient than that
+ performed inside printer drivers.</P>
+<P>For example, the <CODE>pstoraster</CODE> filter often only has to
+ perform a color conversion once each time the color is used for
+ multiple output pixels, while the raster filter must convert every
+ pixel on the page.</P>
 <H3><A NAME="5_1_4">Device and Bitmap Variables</A></H3>
-<P>Besides the standard PostScript page device dictionary variables 
-defined in the Adobe PostScript Level 3 reference manual, the CUPS 
-filters support additional variables that are passed in the page device 
-dictionary header for the page and in some cases control the type of 
-raster data that is generated: 
+<P>Besides the standard PostScript page device dictionary variables
+ defined in the Adobe PostScript Level 3 reference manual, the CUPS
+ filters support additional variables that are passed in the page device
+ dictionary header for the page and in some cases control the type of
+ raster data that is generated:
 <CENTER>
 <TABLE BORDER="1" WIDTH="90%">
 <TR><TH>Variable</TH><TH>Type</TH><TH>Description</TH></TR>
-<TR><TD>cupsWidth</TD><TD>read-only integer</TD><TD>Width of bitmap in 
-pixels</TD></TR>
-<TR><TD>cupsHeight</TD><TD>read-only integer </TD><TD>Height of bitmap 
-in pixels</TD></TR>
-<TR><TD>cupsMediaType</TD><TD>read-write integer</TD><TD>
-Device-specific media type code</TD></TR>
-<TR><TD>cupsBitsPerColor</TD><TD>read-write integer</TD><TD>Number of 
-bits per color; 1, 2, 4, and 8 are currently  supported</TD></TR>
-<TR><TD>cupsBitsPerPixel</TD><TD>read-only integer </TD><TD>Number of 
-bits per pixel; 1 to 32</TD></TR>
-<TR><TD>cupsBytesPerLine</TD><TD>read-only integer</TD><TD>Number of 
-bytes per line of raster graphics</TD></TR>
-<TR><TD>cupsColorOrder</TD><TD>read-write enum</TD><TD>The order of 
-color values in the bitmap: 
-<UL>
-<LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK </LI>
-<LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK </LI>
-<LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;... </LI>
+<TR><TD>cupsWidth</TD><TD>read-only integer</TD><TD>Width of bitmap in
+ pixels</TD></TR>
+<TR><TD>cupsHeight</TD><TD>read-only integer</TD><TD>Height of bitmap in
+ pixels</TD></TR>
+<TR><TD>cupsMediaType</TD><TD>read-write integer</TD><TD>Device-specific
+ media type code</TD></TR>
+<TR><TD>cupsBitsPerColor</TD><TD>read-write integer</TD><TD>Number of
+ bits per color; 1, 2, 4, and 8 are currently supported</TD></TR>
+<TR><TD>cupsBitsPerPixel</TD><TD>read-only integer</TD><TD>Number of
+ bits per pixel; 1 to 32</TD></TR>
+<TR><TD>cupsBytesPerLine</TD><TD>read-only integer</TD><TD>Number of
+ bytes per line of raster graphics</TD></TR>
+<TR><TD>cupsColorOrder</TD><TD>read-write enum</TD><TD>The order of
+ color values in the bitmap:
+<UL>
+<LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK</LI>
+<LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK</LI>
+<LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;...</LI>
 </UL>
 </TD></TR>
-<TR><TD>cupsColorSpace</TD><TD>read-write enum</TD><TD>The colorspace 
-of the bitmap: 
-<UL>
-<LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance) </LI>
-<LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue </LI>
-<LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha </LI>
-<LI><CODE>CUPS_CSPACE_K</CODE> - Black </LI>
-<LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow </LI>
-<LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan </LI>
-<LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black </LI>
-<LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black </LI>
-<LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow </LI>
-<LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow, 
- light cyan, light magenta </LI>
-<LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic 
-magenta,  metallic cyan, black </LI>
-<LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic 
-magenta,  metallic cyan, metallic grey (silver) </LI>
-<LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white 
-pigment) </LI>
-<LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil) </LI>
-<LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver 
-foil) </LI>
+<TR><TD>cupsColorSpace</TD><TD>read-write enum</TD><TD>The colorspace of
+ the bitmap:
+<UL>
+<LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance)</LI>
+<LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue</LI>
+<LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha</LI>
+<LI><CODE>CUPS_CSPACE_K</CODE> - Black</LI>
+<LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan</LI>
+<LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black</LI>
+<LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow,
+ light cyan, light magenta</LI>
+<LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, metallic grey (silver)</LI>
+<LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white
+ pigment)</LI>
+<LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil)</LI>
+<LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver foil)</LI>
 </UL>
 </TD></TR>
 <TR><TD>cupsCompression</TD><TD>read-write integer</TD><TD>
 Device-specific compression type code</TD></TR>
-<TR><TD>cupsRowCount</TD><TD>read-write integer</TD><TD>Device-specific 
-row count value</TD></TR>
-<TR><TD>cupsRowFeed</TD><TD>read-write integer</TD><TD>Device-specific 
-row feed value</TD></TR>
-<TR><TD>cupsRowStep</TD><TD>read-write integer</TD><TD>Device-specific 
-row step value</TD></TR>
+<TR><TD>cupsRowCount</TD><TD>read-write integer</TD><TD>Device-specific
+ row count value</TD></TR>
+<TR><TD>cupsRowFeed</TD><TD>read-write integer</TD><TD>Device-specific
+ row feed value</TD></TR>
+<TR><TD>cupsRowStep</TD><TD>read-write integer</TD><TD>Device-specific
+ row step value</TD></TR>
 </TABLE>
 </CENTER>
 </P>
-<P>Bitmaps with a colorspace of CUPS_CSPACE_KCMYcm and more than 1 bit 
-per color are transmitted to the raster driver in KCMY colorspace; the 
-driver is responsible for producing the correct separation of normal 
-and light cyan and magenta inks. </P>
+<P>Bitmaps with a colorspace of CUPS_CSPACE_KCMYcm and more than 1 bit
+ per color are transmitted to the raster driver in KCMY colorspace; the
+ driver is responsible for producing the correct separation of normal
+ and light cyan and magenta inks.</P>
 <H2><A NAME="5_2">Dissecting the HP-PCL Driver</A></H2>
-<P>The HP-PCL driver provided with CUPS (<CODE>rastertohp</CODE>) 
-converts bitmap data from the raster filters into HP-PCL commands for 
-most PCL-compatible printers. The actual format of the raster data is 
-controlled by the PPD file being used - <VAR>deskjet.ppd</VAR> or <VAR>
-laserjet.ppd</VAR>. </P>
+<P>The HP-PCL driver provided with CUPS (<CODE>rastertohp</CODE>)
+ converts bitmap data from the raster filters into HP-PCL commands for
+ most PCL-compatible printers. The actual format of the raster data is
+ controlled by the PPD file being used -<VAR> deskjet.ppd</VAR> or<VAR>
+ laserjet.ppd</VAR>.</P>
 <H3><A NAME="5_2_1">PPD Files</A></H3>
-<P>PPD files play an important part of all raster printer drivers. 
-Options defined in the PPD file contain PostScript commands that 
-control the raster data that is sent to the printer driver. </P>
+<P>PPD files play an important part of all raster printer drivers.
+ Options defined in the PPD file contain PostScript commands that
+ control the raster data that is sent to the printer driver.</P>
 <P>A typical CUPS printer driver will include <CODE>ColorModel</CODE>, <CODE>
 InputSlot</CODE>, <CODE>PageSize</CODE>, <CODE>PageRegion</CODE>, and <CODE>
-Resolution</CODE> options. Each option is shown using the standard PPD 
-format: </P>
+Resolution</CODE> options. Each option is shown using the standard PPD
+ format:</P>
 <UL>
 <PRE>
 *OpenUI *PageSize/Media Size: PickOne
@@ -2259,22 +2256,22 @@ format: </P>
 *CloseUI: *PageSize
 </PRE>
 </UL>
-<P>The <CODE>OpenUI</CODE> keyword specifies the new option. The first 
-name is the option with an asterisk (*) in front of it. The first name 
-is usually followed by a slash (/) and a human-readable version of the 
-option name. </P>
-<P>Every option <B>must</B> have a default value, specified using the <CODE>
-Default<I>Option</I></CODE> keyword. </P>
-<P>Each option begins with the option name followed by the computer and 
-human-readable values. The PostScript commands follow these inside 
-double quotes. PostScript commands can be provided on a single line: </P>
+<P>The <CODE>OpenUI</CODE> keyword specifies the new option. The first
+ name is the option with an asterisk (*) in front of it. The first name
+ is usually followed by a slash (/) and a human-readable version of the
+ option name.</P>
+<P>Every option<B> must</B> have a default value, specified using the <CODE>
+Default<I>Option</I></CODE> keyword.</P>
+<P>Each option begins with the option name followed by the computer and
+ human-readable values. The PostScript commands follow these inside
+ double quotes. PostScript commands can be provided on a single line:</P>
 <UL>
 <PRE>
 *PageSize A4/A4: &quot;&lt;&lt;/PageSize[595 842]/ImagingBBox null&gt;&gt; setpagedevice&quot;
 </PRE>
 </UL>
-<P>or broken down on separate lines using the <CODE>End</CODE> keyword 
-to terminate them: </P>
+<P>or broken down on separate lines using the <CODE>End</CODE> keyword
+ to terminate them:</P>
 <UL>
 <PRE>
 *PageSize A4/A4: &quot;&lt;&lt;
@@ -2284,15 +2281,14 @@ to terminate them: </P>
 *End
 </PRE>
 </UL>
-<P>The choice of the two formats is usually esthetic. However, each 
-line in a PPD file must not exceed 255 characters, so if your 
-PostScript commands are long you may need to break them up on separate 
-lines. </P>
+<P>The choice of the two formats is usually esthetic. However, each line
+ in a PPD file must not exceed 255 characters, so if your PostScript
+ commands are long you may need to break them up on separate lines.</P>
 <H3><A NAME="5_2_2">Reading Raster Data</A></H3>
-<P>As with any filter, your printer driver should handle raster data 
-from a filename specified on the command-line or from the standard 
-input. The <A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>
- function opens a raster stream for printing: </P>
+<P>As with any filter, your printer driver should handle raster data
+ from a filename specified on the command-line or from the standard
+ input. The<A HREF="#cupsRasterOpen"> <CODE>cupsRasterOpen()</CODE></A>
+ function opens a raster stream for printing:</P>
 <UL>
 <PRE>
 int           fd;   /* File descriptor */
@@ -2333,8 +2329,8 @@ else
 ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
 </PRE>
 </UL>
-<P>Once you have opened the raster stream you just need to read each 
-page and print it: </P>
+<P>Once you have opened the raster stream you just need to read each
+ page and print it:</P>
 <UL>
 <PRE>
 cups_raster_header_t header;
@@ -2352,8 +2348,8 @@ while (cupsRasterReadHeader(ras, &amp;header))
 }
 </PRE>
 </UL>
-<P>After you have processed all pages, close the raster stream and 
-return: </P>
+<P>After you have processed all pages, close the raster stream and
+ return:</P>
 <UL>
 <PRE>
 cupsRasterClose(ras);
@@ -2362,91 +2358,91 @@ return (0);
 </PRE>
 </UL>
 <H1 ALIGN="RIGHT"><A NAME="WRITING_BACKENDS">5 - Writing Backends</A></H1>
-<P>This chapter describes how to write a backend for CUPS.  Backends 
-communicate directly with printers and allow printer drivers and 
-filters to send data using any type of connection transparently. </P>
+<P>This chapter describes how to write a backend for CUPS. Backends
+ communicate directly with printers and allow printer drivers and
+ filters to send data using any type of connection transparently.</P>
 <H2><A NAME="6_1">Overview</A></H2>
-<P>Backends are special filters that communicate with printers 
-directly. They are treated slightly differently than filters, however, 
-and have some unique requirements. </P>
+<P>Backends are special filters that communicate with printers directly.
+ They are treated slightly differently than filters, however, and have
+ some unique requirements.</P>
 <H3><A NAME="6_1_1">Security Considerations</A></H3>
-<P>Backends are run as the root user, so special care must be taken to 
-avoid potential security violations. In particular, remember that a 
-backend will be able to manipulate disk files, devices, and other 
-resources that potentially could damage a system or printer. </P>
+<P>Backends are run as the root user, so special care must be taken to
+ avoid potential security violations. In particular, remember that a
+ backend will be able to manipulate disk files, devices, and other
+ resources that potentially could damage a system or printer.</P>
 <H3><A NAME="6_1_2">Command-Line Arguments</A></H3>
-<P>Besides the standard filter arguments, backends are also run with no 
-arguments to get a list of available devices. This discovery process is 
-described later in this chapter. </P>
+<P>Besides the standard filter arguments, backends are also run with no
+ arguments to get a list of available devices. This discovery process is
+ described later in this chapter.</P>
 <H3><A NAME="6_1_3">Copy Generation</A></H3>
-<P>Like filters, backends should send multiple copies of the print file 
-only if a filename is supplied on the command-line.  Otherwise the 
-backend should assume that the upstream filter has already added the 
-necessary commands or data to produce the multiple copies. </P>
+<P>Like filters, backends should send multiple copies of the print file
+ only if a filename is supplied on the command-line. Otherwise the
+ backend should assume that the upstream filter has already added the
+ necessary commands or data to produce the multiple copies.</P>
 <H3><A NAME="6_1_4">Page Accounting</A></H3>
-<P>Backend filters generally do not do page accounting, however they 
-should at a minimum produce a single page message for each copy that is 
-produced when a filename is present on the command-line. This is 
-because the user selected &quot;raw&quot; printing and no other accounting 
-information is possible. </P>
+<P>Backend filters generally do not do page accounting, however they
+ should at a minimum produce a single page message for each copy that is
+ produced when a filename is present on the command-line. This is
+ because the user selected &quot;raw&quot; printing and no other accounting
+ information is possible.</P>
 <H3><A NAME="6_1_5">Exclusive Access</A></H3>
-<P>Backends that talk to local character or block devices should open 
-the device file in exclusive mode (<CODE>O_EXCL</CODE>) to cooperate 
-with other printers defined for the same device. </P>
+<P>Backends that talk to local character or block devices should open
+ the device file in exclusive mode (<CODE>O_EXCL</CODE>) to cooperate
+ with other printers defined for the same device.</P>
 <H3><A NAME="6_1_6">Retries</A></H3>
-<P>All backends <B>must</B> retry connections to the device. This 
-includes backends that talk to local character or block devices, as the 
-user may define more than one printer queue pointing at the same 
-physical device. </P>
-<P>To prevent excess CPU utilitization, the backend should go to sleep 
-for an amount of time between retries; the CUPS-supplied backends retry 
-once every 30 seconds. </P>
+<P>All backends<B> must</B> retry connections to the device. This
+ includes backends that talk to local character or block devices, as the
+ user may define more than one printer queue pointing at the same
+ physical device.</P>
+<P>To prevent excess CPU utilitization, the backend should go to sleep
+ for an amount of time between retries; the CUPS-supplied backends retry
+ once every 30 seconds.</P>
 <H2><A NAME="6_2">Dissecting the Serial Port Backend</A></H2>
-<P>The serial port backend provides support for serial printers. Since 
-it does everything a good backend needs to do, it provides an excellent 
-example of what to do. </P>
+<P>The serial port backend provides support for serial printers. Since
+ it does everything a good backend needs to do, it provides an excellent
+ example of what to do.</P>
 <H3><A NAME="6_2_1">Supporting Device Discovery</A></H3>
-<P>As previously noted, backends are special filter programs that talk 
-to printer devices. Another task a backend must perform is to list the 
-available devices it supports. The backend lists the available devices 
-when no additioanl arguments are supplied on the command-line (i.e. 
-just the command name...) </P>
-<P>The serial backend lists devices by looking at serial port files in 
-the <VAR>/dev</VAR> directory, by consulting a hardware inventory 
-(IRIX), and in some cases by trying to open the ports to see if they 
-actually exist. </P>
-<P>Once it finds a serial port it writes a single line for each port to 
-the standard error file. Each line looks like this: </P>
+<P>As previously noted, backends are special filter programs that talk
+ to printer devices. Another task a backend must perform is to list the
+ available devices it supports. The backend lists the available devices
+ when no additioanl arguments are supplied on the command-line (i.e.
+ just the command name...)</P>
+<P>The serial backend lists devices by looking at serial port files in
+ the<VAR> /dev</VAR> directory, by consulting a hardware inventory
+ (IRIX), and in some cases by trying to open the ports to see if they
+ actually exist.</P>
+<P>Once it finds a serial port it writes a single line for each port to
+ the standard error file. Each line looks like this:</P>
 <UL>
 <PRE>
 serial serial:/dev/ttyS0?baud=115200 &quot;Unknown&quot; &quot;Serial Port 1&quot;
 </PRE>
 </UL>
-<P>The first word &quot;serial&quot; is the <I>device class</I>; this identifies 
-the class of device which can be used to categorize it in user 
-interfaces. CUPS currently recognizes the following classes: </P>
-<UL>
-<LI>&quot;file&quot; - a disk file. </LI>
-<LI>&quot;direct&quot; - a parallel or fixed-rate serial data port,  currently 
-used for Centronics, IEEE-1284, and USB printer  ports. </LI>
-<LI>&quot;serial&quot; - a variable-rate serial port. </LI>
-<LI>&quot;network&quot; - a network connection, typically via AppSocket,  HTTP, 
-IPP, LPD, or SMB/CIFS protocols. </LI>
-</UL>
-<P>After the device class is the <I>device URI</I>, in this case 
-&quot;serial:/dev/ttyS0?baud=115200&quot;. This is the URI that should be used by 
-the user to select this port. For serial ports, the &quot;baud=115200&quot; 
-specifies the maximum baud rate supported by the port - the actual 
-value will vary based on the speed the user selects for the printer. </P>
-<P>The last two strings are the model and description for the port. The 
-&quot;Unknown&quot; string means that the printer model is unknown - some devices 
-are able to provide a make and model such as &quot;HP DeskJet&quot; that allows 
-users and software to choose an appropriate printer driver more easily. 
-Both the model and description must be enclosed inside double quotes. </P>
+<P>The first word &quot;serial&quot; is the<I> device class</I>; this identifies
+ the class of device which can be used to categorize it in user
+ interfaces. CUPS currently recognizes the following classes:</P>
+<UL>
+<LI>&quot;file&quot; - a disk file.</LI>
+<LI>&quot;direct&quot; - a parallel or fixed-rate serial data port, currently used
+ for Centronics, IEEE-1284, and USB printer ports.</LI>
+<LI>&quot;serial&quot; - a variable-rate serial port.</LI>
+<LI>&quot;network&quot; - a network connection, typically via AppSocket, HTTP,
+ IPP, LPD, or SMB/CIFS protocols.</LI>
+</UL>
+<P>After the device class is the<I> device URI</I>, in this case
+ &quot;serial:/dev/ttyS0?baud=115200&quot;. This is the URI that should be used by
+ the user to select this port. For serial ports, the &quot;baud=115200&quot;
+ specifies the maximum baud rate supported by the port - the actual
+ value will vary based on the speed the user selects for the printer.</P>
+<P>The last two strings are the model and description for the port. The
+ &quot;Unknown&quot; string means that the printer model is unknown - some devices
+ are able to provide a make and model such as &quot;HP DeskJet&quot; that allows
+ users and software to choose an appropriate printer driver more easily.
+ Both the model and description must be enclosed inside double quotes.</P>
 <H3><A NAME="6_2_2">Opening the Serial Port</A></H3>
-<P>As noted previously, all backends should open device files in 
-exclusive mode, and retry as needed until the port is available. The 
-serial port does this using a <CODE>do-while</CODE> loop: </P>
+<P>As noted previously, all backends should open device files in
+ exclusive mode, and retry as needed until the port is available. The
+ serial port does this using a <CODE>do-while</CODE> loop:</P>
 <UL>
 <PRE>
 do
@@ -2468,15 +2464,15 @@ do
 while (fd &lt; 0);
 </PRE>
 </UL>
-<P>If the port is busy or in use by another process, the backend will 
-go to sleep for 30 seconds and try again. If another error is detected 
-a message is sent to the user and the backend aborts the print job 
-until the problem can be corrected. </P>
+<P>If the port is busy or in use by another process, the backend will go
+ to sleep for 30 seconds and try again. If another error is detected a
+ message is sent to the user and the backend aborts the print job until
+ the problem can be corrected.</P>
 <H3><A NAME="6_2_3">Writing Data to the Port</A></H3>
-<P>Network and character devices pose an interesting problem when 
-writing data to the port - they may not be able to write all of the 
-bytes in your buffer before returning. To work around this problem you 
-must loop until all bytes have been written: </P>
+<P>Network and character devices pose an interesting problem when
+ writing data to the port - they may not be able to write all of the
+ bytes in your buffer before returning. To work around this problem you
+ must loop until all bytes have been written:</P>
 <UL>
 <PRE>
 while (nbytes &gt; 0)
@@ -2496,90 +2492,89 @@ while (nbytes &gt; 0)
 }
 </PRE>
 </UL>
-<P>The check for the <CODE>ENOTTY</CODE> error is needed on some 
-platforms to clear an error from a previous <CODE>ioctl()</CODE> call. </P>
+<P>The check for the <CODE>ENOTTY</CODE> error is needed on some
+ platforms to clear an error from a previous <CODE>ioctl()</CODE> call.</P>
 <H3><A NAME="6_2_4">Finishing Up</A></H3>
-<P>Once you have sent the print file, return 0 if the file printed 
-successfully or 1 if it did not. This will allow the scheduler to stop 
-the print job if there is a device error, preserving the print job for 
-later printing once the problem has been corrected. </P>
+<P>Once you have sent the print file, return 0 if the file printed
+ successfully or 1 if it did not. This will allow the scheduler to stop
+ the print job if there is a device error, preserving the print job for
+ later printing once the problem has been corrected.</P>
 <H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
-<H2 ALIGN="CENTER"><A NAME="7_1">Common UNIX Printing System License 
-Agreement</A></H2>
+<H2 ALIGN="CENTER"><A NAME="7_1">Common UNIX Printing System License
+ Agreement</A></H2>
 <P ALIGN="CENTER">Copyright 1997-2001 by Easy Software Products
 <BR> 44141 AIRPORT VIEW DR STE 204
 <BR> HOLLYWOOD, MARYLAND 20636-3111 USA
 <BR>
 <BR> Voice: +1.301.373.9600
-<BR> Email: <A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
-<BR> WWW: <A HREF="http://www.cups.org">http://www.cups.org</A></P>
+<BR> Email:<A HREF="mailto:cups-info@cups.org"> cups-info@cups.org</A>
+<BR> WWW:<A HREF="http://www.cups.org"> http://www.cups.org</A></P>
 <H3><A NAME="7_1_1">Introduction</A></H3>
-<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;), 
-is provided under the GNU General Public License (&quot;GPL&quot;) and GNU 
-Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these 
-licenses follow this introduction. </P>
-<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot; 
-subdirectory of the CUPS source distribution and in the 
-&quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups.sl&quot;, or 
-&quot;libcups.so&quot; files in the binary distributions. </P>
-<P>The GNU GPL applies to the remainder of the CUPS distribution, 
-including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript 
-5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.90. </P>
-<P>For those not familiar with the GNU GPL, the license basically 
-allows you to: </P>
-<UL>
-<LI>Use the CUPS software at no charge. </LI>
-<LI>Distribute verbatim copies of the software in source or  binary 
-form. </LI>
-<LI>Sell verbatim copies of the software for a media fee, or  sell 
-support for the software. </LI>
-<LI>Distribute or sell printer drivers and filters that use  CUPS so 
-long as source code is made available under the GPL. </LI>
-</UL>
-<P>What this license <B>does not</B> allow you to do is make changes or 
-add features to CUPS and then sell a binary distribution without source 
-code. You must provide source for any new drivers, changes, or 
-additions to the software, and all code must be provided under the GPL 
-or LGPL as appropriate. </P>
-<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to 
-develop applications that use the CUPS API library under other licenses 
-and/or conditions as appropriate for your application. </P>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these
+ licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the
+ &quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups_s.a&quot;,
+ &quot;libcups.sl&quot;, or &quot;libcups.so&quot; files in the binary distributions.</P>
+<P>The GNU GPL applies to the remainder of the CUPS distribution,
+ including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript
+ 5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.93a.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
 <H3><A NAME="7_1_2">Trademarks</A></H3>
-<P>Easy Software Products has trademarked the Common UNIX Printing 
-System, CUPS, and CUPS logo. These names and logos may be used freely 
-in any direct port or binary distribution of CUPS. To use them in 
-derivative products, please contract Easy Software Products for written 
-permission. Our intention is to protect the value of these trademarks 
-and ensure that any derivative product meets the same high-quality 
-standards as the original. </P>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. These names and logos may be used freely
+ in any direct port or binary distribution of CUPS. To use them in
+ derivative products, please contract Easy Software Products for written
+ permission. Our intention is to protect the value of these trademarks
+ and ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
 <H3><A NAME="7_1_3">Binary Distribution Rights</A></H3>
-<P>Easy Software Products also sells rights to the CUPS source code 
-under a binary distribution license for vendors that are unable to 
-release source code for their drivers, additions, and modifications to 
-CUPS under the GNU GPL and LGPL. For information please contact us at 
-the address shown above. </P>
-<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that 
-utilizes the GNU GhostScript 5.50 core to convert PostScript files into 
-a stream of raster images. For binary distribution licensing of this 
-software, please contact: <BLOCKQUOTE> Miles Jones
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that
+ utilizes the GNU GhostScript 5.50 core to convert PostScript files into
+ a stream of raster images. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Miles Jones
 <BR> Director of Marketing
 <BR> Artifex Software Inc.
 <BR> 454 Las Gallinas Ave., Suite 108
 <BR> San Rafael, CA 94903 USA
 <BR> Voice: +1.415.492.9861
 <BR> Fax: +1.415.492.9862
-<BR> EMail: <A HREF="mailto:info@arsoft.com">info@arsoft.com</A></BLOCKQUOTE>
+<BR> EMail:<A HREF="mailto:info@arsoft.com"> info@arsoft.com</A></BLOCKQUOTE>
 </P>
-<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.90 software. For binary 
-distribution licensing of this software, please contact: <BLOCKQUOTE>
+<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.93a software. For binary
+ distribution licensing of this software, please contact:<BLOCKQUOTE>
  Derek B. Noonburg
-<BR> Email: <A HREF="mailto:derekn@foolabs.com">derekn@foolabs.com</A>
-<BR> WWW: <A HREF="http://www.foolabs.com/xpdf/">
-http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<BR> Email:<A HREF="mailto:derekn@foolabs.com"> derekn@foolabs.com</A>
+<BR> WWW:<A HREF="http://www.foolabs.com/xpdf/">
+ http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
 <H3><A NAME="7_1_4">Support</A></H3>
-<P>Easy Software Products sells software support for CUPS as well as a 
-commercial printing product based on CUPS called ESP Print Pro. You can 
-find out more at our web site: </P>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
 <UL>
 <PRE>
 <A HREF="http://www.easysw.com">http://www.easysw.com</A>
@@ -2587,9 +2582,8 @@ find out more at our web site: </P>
 </UL>
 
 <!-- NEW PAGE -->
-
 <H2><A NAME="7_2">GNU GENERAL PUBLIC LICENSE</A></H2>
-<P>Version 2, June 1991 </P>
+<P>Version 2, June 1991</P>
 <PRE>
 Copyright 1989, 1991 Free Software Foundation, Inc.
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -2601,254 +2595,250 @@ copies of this license document, but changing it is not allowed.
 
 </PRE>
 <H4>Preamble</H4>
-<P>The licenses for most software are designed to take away your 
-freedom to share and change it.  By contrast, the GNU General Public 
-License is intended to guarantee your freedom to share and change free 
-software--to make sure the software is free for all its users.  This 
-General Public License applies to most of the Free Software 
-Foundation's software and to any other program whose authors commit to 
-using it.  (Some other Free Software Foundation software is covered by 
-the GNU Library General Public License instead.)  You can apply it to 
-your programs, too. </P>
-<P>When we speak of free software, we are referring to freedom, not 
-price.  Our General Public Licenses are designed to make sure that you 
-have the freedom to distribute copies of free software (and charge for 
-this service if you wish), that you receive source code or can get it 
-if you want it, that you can change the software or use pieces of it in 
-new free programs; and that you know you can do these things. </P>
-<P>To protect your rights, we need to make restrictions that forbid 
-anyone to deny you these rights or to ask you to surrender the rights. 
-These restrictions translate to certain responsibilities for you if you 
-distribute copies of the software, or if you modify it. </P>
-<P>For example, if you distribute copies of such a program, whether 
-gratis or for a fee, you must give the recipients all the rights that 
-you have.  You must make sure that they, too, receive or can get the 
-source code.  And you must show them these terms so they know their 
-rights. </P>
-<P>We protect your rights with two steps: (1) copyright the software, 
-and (2) offer you this license which gives you legal permission to 
-copy, distribute and/or modify the software. </P>
-<P>Also, for each author's protection and ours, we want to make certain 
-that everyone understands that there is no warranty for this free 
-software.  If the software is modified by someone else and passed on, 
-we want its recipients to know that what they have is not the original, 
-so that any problems introduced by others will not reflect on the 
-original authors' reputations. </P>
-<P>Finally, any free program is threatened constantly by software 
-patents.  We wish to avoid the danger that redistributors of a free 
-program will individually obtain patent licenses, in effect making the 
-program proprietary.  To prevent this, we have made it clear that any 
-patent must be licensed for everyone's free use or not licensed at all. </P>
-<P>The precise terms and conditions for copying, distribution and 
-modification follow. </P>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
 <H4>GNU GENERAL PUBLIC LICENSE
-<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND 
-MODIFICATION</H4>
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
 <OL START="0">
-<LI>This License applies to any program or other work which contains a 
-notice placed by the copyright holder saying it may be distributed 
-under the terms of this General Public License.  The &quot;Program&quot;, below, 
-refers to any such program or work, and a &quot;work based on the Program&quot; 
-means either the Program or any derivative work under copyright law: 
-that is to say, a work containing the Program or a portion of it, 
-either verbatim or with modifications and/or translated into another 
-language.  (Hereinafter, translation is included without limitation in 
-the term &quot;modification&quot;.)  Each licensee is addressed as &quot;you&quot;. </LI>
-<P>Activities other than copying, distribution and modification are not 
-covered by this License; they are outside its scope.  The act of 
-running the Program is not restricted, and the output from the Program 
-is covered only if its contents constitute a work based on the Program 
-(independent of having been made by running the Program). Whether that 
-is true depends on what the Program does. </P>
-<LI>You may copy and distribute verbatim copies of the Program's source 
-code as you receive it, in any medium, provided that you conspicuously 
-and appropriately publish on each copy an appropriate copyright notice 
-and disclaimer of warranty; keep intact all the notices that refer to 
-this License and to the absence of any warranty; and give any other 
-recipients of the Program a copy of this License along with the 
-Program. </LI>
-<P>You may charge a fee for the physical act of transferring a copy, 
-and you may at your option offer warranty protection in exchange for a 
-fee. </P>
-<LI>You may modify your copy or copies of the Program or any portion of 
-it, thus forming a work based on the Program, and copy and distribute 
-such modifications or work under the terms of Section 1 above, provided 
-that you also meet all of these conditions: 
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.</LI>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.</LI>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
 <OL TYPE="a">
-<LI>You must cause the modified files to carry prominent notices 
-stating that you changed the files and the date of any change. </LI>
-<LI>You must cause any work that you distribute or publish, that in 
-whole or in part contains or is derived from the Program or any part 
-thereof, to be licensed as a whole at no charge to all third parties 
-under the terms of this License. </LI>
-<LI>if the modified program normally reads commands interactively when 
-run, you must cause it, when started running for such interactive use 
-in the most ordinary way, to print or display an announcement including 
-an appropriate copyright notice and a notice that there is no warranty 
-(or else, saying that you provide a warranty) and that users may 
-redistribute the program under these conditions, and telling the user 
-how to view a copy of this License.  (Exception: if the Program itself 
-is interactive but does not normally print such an announcement, your 
-work based on the Program is not required to print an announcement.) </LI>
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
 </OL>
 </LI>
-<P>These requirements apply to the modified work as a whole.  If 
-identifiable sections of that work are not derived from the Program, 
-and can be reasonably considered independent and separate works in 
-themselves, then this License, and its terms, do not apply to those 
-sections when you distribute them as separate works.  But when you 
-distribute the same sections as part of a whole which is a work based 
-on the Program, the distribution of the whole must be on the terms of 
-this License, whose permissions for other licensees extend to the 
-entire whole, and thus to each and every part regardless of who wrote 
-it. </P>
-<P>Thus, it is not the intent of this section to claim rights or 
-contest your rights to work written entirely by you; rather, the intent 
-is to exercise the right to control the distribution of derivative or 
-collective works based on the Program. </P>
-<P>In addition, mere aggregation of another work not based on the 
-Program with the Program (or with a work based on the Program) on a 
-volume of a storage or distribution medium does not bring the other 
-work under the scope of this License. </P>
-<LI>You may copy and distribute the Program (or a work based on it, 
-under Section 2) in object code or executable form under the terms of 
-Sections 1 and 2 above provided that you also do one of the following: 
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
 <OL TYPE="a">
-<LI>Accompany it with the complete corresponding machine-readable 
-source code, which must be distributed under the terms of Sections 1 
-and 2 above on a medium customarily used for software interchange; or, </LI>
-<LI>Accompany it with a written offer, valid for at least three years, 
-to give any third party, for a charge no more than your cost of 
-physically performing source distribution, a complete machine-readable 
-copy of the corresponding source code, to be distributed under the 
-terms of Sections 1 and 2 above on a medium customarily used for 
-software interchange; or, </LI>
-<LI>Accompany it with the information you received as to the offer to 
-distribute corresponding source code.  (This alternative is allowed 
-only for noncommercial distribution and only if you received the 
-program in object code or executable form with such an offer, in accord 
-with Subsection b above.) </LI>
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
 </OL>
 </LI>
-<P>The source code for a work means the preferred form of the work for 
-making modifications to it.  For an executable work, complete source 
-code means all the source code for all modules it contains, plus any 
-associated interface definition files, plus the scripts used to control 
-compilation and installation of the executable.  However, as a special 
-exception, the source code distributed need not include anything that 
-is normally distributed (in either source or binary form) with the 
-major components (compiler, kernel, and so on) of the operating system 
-on which the executable runs, unless that component itself accompanies 
-the executable. </P>
-<P>If distribution of executable or object code is made by offering 
-access to copy from a designated place, then offering equivalent access 
-to copy the source code from the same place counts as distribution of 
-the source code, even though third parties are not compelled to copy 
-the source along with the object code. </P>
-<LI>You may not copy, modify, sublicense, or distribute the Program 
-except as expressly provided under this License.  Any attempt otherwise 
-to copy, modify, sublicense or distribute the Program is void, and will 
-automatically terminate your rights under this License. However, 
-parties who have received copies, or rights, from you under this 
-License will not have their licenses terminated so long as such parties 
-remain in full compliance. </LI>
-<LI>You are not required to accept this License, since you have not 
-signed it.  However, nothing else grants you permission to modify or 
-distribute the Program or its derivative works.  These actions are 
-prohibited by law if you do not accept this License.  Therefore, by 
-modifying or distributing the Program (or any work based on the 
-Program), you indicate your acceptance of this License to do so, and 
-all its terms and conditions for copying, distributing or modifying the 
-Program or works based on it. </LI>
-<LI>Each time you redistribute the Program (or any work based on the 
-Program), the recipient automatically receives a license from the 
-original licensor to copy, distribute or modify the Program subject to 
-these terms and conditions.  You may not impose any further 
-restrictions on the recipients' exercise of the rights granted herein. 
-You are not responsible for enforcing compliance by third parties to 
-this License. </LI>
-<LI>If, as a consequence of a court judgment or allegation of patent 
-infringement or for any other reason (not limited to patent issues), 
-conditions are imposed on you (whether by court order, agreement or 
-otherwise) that contradict the conditions of this License, they do not 
-excuse you from the conditions of this License.  If you cannot 
-distribute so as to satisfy simultaneously your obligations under this 
-License and any other pertinent obligations, then as a consequence you 
-may not distribute the Program at all.  For example, if a patent 
-license would not permit royalty-free redistribution of the Program by 
-all those who receive copies directly or indirectly through you, then 
-the only way you could satisfy both it and this License would be to 
-refrain entirely from distribution of the Program. </LI>
-<P>If any portion of this section is held invalid or unenforceable 
-under any particular circumstance, the balance of the section is 
-intended to apply and the section as a whole is intended to apply in 
-other circumstances. </P>
-<P>It is not the purpose of this section to induce you to infringe any 
-patents or other property right claims or to contest validity of any 
-such claims; this section has the sole purpose of protecting the 
-integrity of the free software distribution system, which is 
-implemented by public license practices.  Many people have made 
-generous contributions to the wide range of software distributed 
-through that system in reliance on consistent application of that 
-system; it is up to the author/donor to decide if he or she is willing 
-to distribute software through any other system and a licensee cannot 
-impose that choice. </P>
-<P>This section is intended to make thoroughly clear what is believed 
-to be a consequence of the rest of this License. </P>
-<LI>If the distribution and/or use of the Program is restricted in 
-certain countries either by patents or by copyrighted interfaces, the 
-original copyright holder who places the Program under this License may 
-add an explicit geographical distribution limitation excluding those 
-countries, so that distribution is permitted only in or among countries 
-not thus excluded.  In such case, this License incorporates the 
-limitation as if written in the body of this License. </LI>
-<LI>The Free Software Foundation may publish revised and/or new 
-versions of the General Public License from time to time.  Such new 
-versions will be similar in spirit to the present version, but may 
-differ in detail to address new problems or concerns. </LI>
-<P>Each version is given a distinguishing version number.  If the 
-Program specifies a version number of this License which applies to it 
-and &quot;any later version&quot;, you have the option of following the terms and 
-conditions either of that version or of any later version published by 
-the Free Software Foundation.  If the Program does not specify a 
-version number of this License, you may choose any version ever 
-published by the Free Software Foundation. </P>
-<LI>If you wish to incorporate parts of the Program into other free 
-programs whose distribution conditions are different, write to the 
-author to ask for permission.  For software which is copyrighted by the 
-Free Software Foundation, write to the Free Software Foundation; we 
-sometimes make exceptions for this.  Our decision will be guided by the 
-two goals of preserving the free status of all derivatives of our free 
-software and of promoting the sharing and reuse of software generally. </LI>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.</LI>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.</LI>
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
 </OL>
 <H4>NO WARRANTY</H4>
 <OL START="11">
-<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO 
-WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
- EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
-OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, 
-EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
- THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS 
-WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </LI>
-<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 
-AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU 
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 
-PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 
-FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF 
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
-DAMAGES. </LI>
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
 </OL>
 <H4>END OF TERMS AND CONDITIONS</H4>
 
 <!-- NEW PAGE -->
-
 <H2><A NAME="7_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
-<P>Version 2, June 1991 </P>
+<P>Version 2, June 1991</P>
 <PRE>
 Copyright (C) 1991 Free Software Foundation, Inc.
 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
@@ -2859,870 +2849,861 @@ of this license document, but changing it is not allowed.
  numbered 2 because it goes with version 2 of the ordinary GPL.]
 </PRE>
 <H4>Preamble</H4>
-<P>The licenses for most software are designed to take away your 
-freedom to share and change it.  By contrast, the GNU General Public 
-Licenses are intended to guarantee your freedom to share and change 
-free software--to make sure the software is free for all its users. </P>
-<P>This license, the Library General Public License, applies to some 
-specially designated Free Software Foundation software, and to any 
-other libraries whose authors decide to use it.  You can use it for 
-your libraries, too. </P>
-<P>When we speak of free software, we are referring to freedom, not 
-price.  Our General Public Licenses are designed to make sure that you 
-have the freedom to distribute copies of free software (and charge for 
-this service if you wish), that you receive source code or can get it 
-if you want it, that you can change the software or use pieces of it in 
-new free programs; and that you know you can do these things. </P>
-<P>To protect your rights, we need to make restrictions that forbid 
-anyone to deny you these rights or to ask you to surrender the rights. 
-These restrictions translate to certain responsibilities for you if you 
-distribute copies of the library, or if you modify it. </P>
-<P>For example, if you distribute copies of the library, whether gratis 
-or for a fee, you must give the recipients all the rights that we gave 
-you.  You must make sure that they, too, receive or can get the source 
-code.  If you link a program with the library, you must provide 
-complete object files to the recipients so that they can relink them 
-with the library, after making changes to the library and recompiling 
-it.  And you must show them these terms so they know their rights. </P>
-<P>Our method of protecting your rights has two steps: (1) copyright 
-the library, and (2) offer you this license which gives you legal 
-permission to copy, distribute and/or modify the library. </P>
-<P>Also, for each distributor's protection, we want to make certain 
-that everyone understands that there is no warranty for this free 
-library.  If the library is modified by someone else and passed on, we 
-want its recipients to know that what they have is not the original 
-version, so that any problems introduced by others will not reflect on 
-the original authors' reputations. </P>
-<P>Finally, any free program is threatened constantly by software 
-patents.  We wish to avoid the danger that companies distributing free 
-software will individually obtain patent licenses, thus in effect 
-transforming the program into proprietary software.  To prevent this, 
-we have made it clear that any patent must be licensed for everyone's 
-free use or not licensed at all. </P>
-<P>Most GNU software, including some libraries, is covered by the 
-ordinary GNU General Public License, which was designed for utility 
-programs.  This license, the GNU Library General Public License, 
-applies to certain designated libraries.  This license is quite 
-different from the ordinary one; be sure to read it in full, and don't 
-assume that anything in it is the same as in the ordinary license. </P>
-<P>The reason we have a separate public license for some libraries is 
-that they blur the distinction we usually make between modifying or 
-adding to a program and simply using it.  Linking a program with a 
-library, without changing the library, is in some sense simply using 
-the library, and is analogous to running a utility program or 
-application program.  However, in a textual and legal sense, the linked 
-executable is a combined work, a derivative of the original library, 
-and the ordinary General Public License treats it as such. </P>
-<P>Because of this blurred distinction, using the ordinary General 
-Public License for libraries did not effectively promote software 
-sharing, because most developers did not use the libraries.  We 
-concluded that weaker conditions might promote sharing better. </P>
-<P>However, unrestricted linking of non-free programs would deprive the 
-users of those programs of all benefit from the free status of the 
-libraries themselves.  This Library General Public License is intended 
-to permit developers of non-free programs to use free libraries, while 
-preserving your freedom as a user of such programs to change the free 
-libraries that are incorporated in them.  (We have not seen how to 
-achieve this as regards changes in header files, but we have achieved 
-it as regards changes in the actual functions of the Library.)  The 
-hope is that this will lead to faster development of free libraries. </P>
-<P>The precise terms and conditions for copying, distribution and 
-modification follow.  Pay close attention to the difference between a 
-&quot;work based on the library&quot; and a &quot;work that uses the library&quot;.  The 
-former contains code derived from the library, while the latter only 
-works together with the library. </P>
-<P>Note that it is possible for a library to be covered by the ordinary 
-General Public License rather than by this special one. </P>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
 <H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
-<P><STRONG>0.</STRONG> This License Agreement applies to any software 
-library which contains a notice placed by the copyright holder or other 
-authorized party saying it may be distributed under the terms of this 
-Library General Public License (also called &quot;this License&quot;).  Each 
-licensee is addressed as &quot;you&quot;. </P>
-<P>A &quot;library&quot; means a collection of software functions and/or data 
-prepared so as to be conveniently linked with application programs 
-(which use some of those functions and data) to form executables. </P>
-<P>The &quot;Library&quot;, below, refers to any such software library or work 
-which has been distributed under these terms.  A &quot;work based on the 
-Library&quot; means either the Library or any derivative work under 
-copyright law: that is to say, a work containing the Library or a 
-portion of it, either verbatim or with modifications and/or translated 
-straightforwardly into another language.  (Hereinafter, translation is 
-included without limitation in the term &quot;modification&quot;.) </P>
-<P>&quot;Source code&quot; for a work means the preferred form of the work for 
-making modifications to it.  For a library, complete source code means 
-all the source code for all modules it contains, plus any associated 
-interface definition files, plus the scripts used to control 
-compilation and installation of the library. </P>
-<P>Activities other than copying, distribution and modification are not 
-covered by this License; they are outside its scope.  The act of 
-running a program using the Library is not restricted, and output from 
-such a program is covered only if its contents constitute a work based 
-on the Library (independent of the use of the Library in a tool for 
-writing it).  Whether that is true depends on what the Library does and 
-what the program that uses the Library does. </P>
-<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of 
-the Library's complete source code as you receive it, in any medium, 
-provided that you conspicuously and appropriately publish on each copy 
-an appropriate copyright notice and disclaimer of warranty; keep intact 
-all the notices that refer to this License and to the absence of any 
-warranty; and distribute a copy of this License along with the Library. </P>
-<P>You may charge a fee for the physical act of transferring a copy, 
-and you may at your option offer warranty protection in exchange for a 
-fee. </P>
-<P><STRONG>2.</STRONG> You may modify your copy or copies of the 
-Library or any portion of it, thus forming a work based on the Library, 
-and copy and distribute such modifications or work under the terms of 
-Section 1 above, provided that you also meet all of these conditions: </P>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
 <OL TYPE="a">
-<LI>The modified work must itself be a software library. </LI>
+<LI>The modified work must itself be a software library.</LI>
 <P></P>
-<LI>You must cause the files modified to carry prominent notices 
stating that you changed the files and the date of any change. </LI>
+<LI>You must cause the files modified to carry prominent notices stating
that you changed the files and the date of any change.</LI>
 <P></P>
-<LI>You must cause the whole of the work to be licensed at no  charge 
-to all third parties under the terms of this License. </LI>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.</LI>
 <P></P>
-<LI>If a facility in the modified Library refers to a function or a 
- table of data to be supplied by an application program that uses  the 
-facility, other than as an argument passed when the facility  is 
-invoked, then you must make a good faith effort to ensure that,  in the 
-event an application does not supply such function or  table, the 
-facility still operates, and performs whatever part of  its purpose 
-remains meaningful. </LI>
-<P>(For example, a function in a library to compute square roots has  a 
-purpose that is entirely well-defined independent of the  application. 
- Therefore, Subsection 2d requires that any  application-supplied 
-function or table used by this function must  be optional: if the 
-application does not supply it, the square  root function must still 
-compute square roots.) </P>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.</LI>
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
 </OL>
-<P>These requirements apply to the modified work as a whole.  If 
-identifiable sections of that work are not derived from the Library, 
-and can be reasonably considered independent and separate works in 
-themselves, then this License, and its terms, do not apply to those 
-sections when you distribute them as separate works.  But when you 
-distribute the same sections as part of a whole which is a work based 
-on the Library, the distribution of the whole must be on the terms of 
-this License, whose permissions for other licensees extend to the 
-entire whole, and thus to each and every part regardless of who wrote 
-it. </P>
-<P>Thus, it is not the intent of this section to claim rights or 
-contest your rights to work written entirely by you; rather, the intent 
-is to exercise the right to control the distribution of derivative or 
-collective works based on the Library. </P>
-<P>In addition, mere aggregation of another work not based on the 
-Library with the Library (or with a work based on the Library) on a 
-volume of a storage or distribution medium does not bring the other 
-work under the scope of this License. </P>
-<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary 
-GNU General Public License instead of this License to a given copy of 
-the Library.  To do this, you must alter all the notices that refer to 
-this License, so that they refer to the ordinary GNU General Public 
-License, version 2, instead of to this License.  (If a newer version 
-than version 2 of the ordinary GNU General Public License has appeared, 
-then you can specify that version instead if you wish.)  Do not make 
-any other change in these notices. </P>
-<P>Once this change is made in a given copy, it is irreversible for 
-that copy, so the ordinary GNU General Public License applies to all 
-subsequent copies and derivative works made from that copy. </P>
-<P>This option is useful when you wish to copy part of the code of the 
-Library into a program that is not a library. </P>
-<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a 
-portion or derivative of it, under Section 2) in object code or 
-executable form under the terms of Sections 1 and 2 above provided that 
-you accompany it with the complete corresponding machine-readable 
-source code, which must be distributed under the terms of Sections 1 
-and 2 above on a medium customarily used for software interchange. </P>
-<P>If distribution of object code is made by offering access to copy 
-from a designated place, then offering equivalent access to copy the 
-source code from the same place satisfies the requirement to distribute 
-the source code, even though third parties are not compelled to copy 
-the source along with the object code. </P>
-<P><STRONG>5.</STRONG> A program that contains no derivative of any 
-portion of the Library, but is designed to work with the Library by 
-being compiled or linked with it, is called a &quot;work that uses the 
-Library&quot;.  Such a work, in isolation, is not a derivative work of the 
-Library, and therefore falls outside the scope of this License. </P>
-<P>However, linking a &quot;work that uses the Library&quot; with the Library 
-creates an executable that is a derivative of the Library (because it 
-contains portions of the Library), rather than a &quot;work that uses the 
-library&quot;.  The executable is therefore covered by this License. Section 
-6 states terms for distribution of such executables. </P>
-<P>When a &quot;work that uses the Library&quot; uses material from a header file 
-that is part of the Library, the object code for the work may be a 
-derivative work of the Library even though the source code is not. 
-Whether this is true is especially significant if the work can be 
-linked without the Library, or if the work is itself a library.  The 
-threshold for this to be true is not precisely defined by law. </P>
-<P>If such an object file uses only numerical parameters, data 
-structure layouts and accessors, and small macros and small inline 
-functions (ten lines or less in length), then the use of the object 
-file is unrestricted, regardless of whether it is legally a derivative 
-work.  (Executables containing this object code plus portions of the 
-Library will still fall under Section 6.) </P>
-<P>Otherwise, if the work is a derivative of the Library, you may 
-distribute the object code for the work under the terms of Section 6. 
-Any executables containing that work also fall under Section 6, whether 
-or not they are linked directly with the Library itself. </P>
-<P><STRONG>6.</STRONG> As an exception to the Sections above, you may 
-also compile or link a &quot;work that uses the Library&quot; with the Library to 
-produce a work containing portions of the Library, and distribute that 
-work under terms of your choice, provided that the terms permit 
-modification of the work for the customer's own use and reverse 
-engineering for debugging such modifications. </P>
-<P>You must give prominent notice with each copy of the work that the 
-Library is used in it and that the Library and its use are covered by 
-this License.  You must supply a copy of this License.  If the work 
-during execution displays copyright notices, you must include the 
-copyright notice for the Library among them, as well as a reference 
-directing the user to the copy of this License.  Also, you must do one 
-of these things: </P>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
 <OL TYPE="a">
-<LI>Accompany the work with the complete corresponding 
- machine-readable source code for the Library including whatever 
- changes were used in the work (which must be distributed under 
- Sections 1 and 2 above); and, if the work is an executable linked 
- with the Library, with the complete machine-readable &quot;work that  uses 
-the Library&quot;, as object code and/or source code, so that the  user can 
-modify the Library and then relink to produce a modified  executable 
-containing the modified Library.  (It is understood  that the user who 
-changes the contents of definitions files in the  Library will not 
-necessarily be able to recompile the application  to use the modified 
-definitions.) </LI>
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)</LI>
 <P></P>
-<LI>Accompany the work with a written offer, valid for at  least three 
-years, to give the same user the materials  specified in Subsection 6a, 
-above, for a charge no more  than the cost of performing this 
-distribution. </LI>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.</LI>
 <P></P>
-<LI>If distribution of the work is made by offering access to copy 
- from a designated place, offer equivalent access to copy the above 
specified materials from the same place. </LI>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
materials from the same place.</LI>
 <P></P>
-<LI>Verify that the user has already received a copy of these 
materials or that you have already sent this user a copy. </LI>
+<LI>Verify that the user has already received a copy of these materials
or that you have already sent this user a copy.</LI>
 </OL>
-<P>For an executable, the required form of the &quot;work that uses the 
-Library&quot; must include any data and utility programs needed for 
-reproducing the executable from it.  However, as a special exception, 
-the source code distributed need not include anything that is normally 
-distributed (in either source or binary form) with the major components 
-(compiler, kernel, and so on) of the operating system on which the 
-executable runs, unless that component itself accompanies the 
-executable. </P>
-<P>It may happen that this requirement contradicts the license 
-restrictions of other proprietary libraries that do not normally 
-accompany the operating system.  Such a contradiction means you cannot 
-use both them and the Library together in an executable that you 
-distribute. </P>
-<P><STRONG>7.</STRONG> You may place library facilities that are a work 
-based on the Library side-by-side in a single library together with 
-other library facilities not covered by this License, and distribute 
-such a combined library, provided that the separate distribution of the 
-work based on the Library and of the other library facilities is 
-otherwise permitted, and provided that you do these two things: </P>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
 <OL TYPE="a">
-<LI>Accompany the combined library with a copy of the same work  based 
-on the Library, uncombined with any other library  facilities.  This 
-must be distributed under the terms of the  Sections above. </LI>
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.</LI>
 <P></P>
-<LI>Give prominent notice with the combined library of the fact  that 
-part of it is a work based on the Library, and explaining  where to 
-find the accompanying uncombined form of the same work. </LI>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
 </OL>
-<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with, 
-or distribute the Library except as expressly provided under this 
-License.  Any attempt otherwise to copy, modify, sublicense, link with, 
-or distribute the Library is void, and will automatically terminate 
-your rights under this License.  However, parties who have received 
-copies, or rights, from you under this License will not have their 
-licenses terminated so long as such parties remain in full compliance. </P>
-<P><STRONG>9.</STRONG> You are not required to accept this License, 
-since you have not signed it.  However, nothing else grants you 
-permission to modify or distribute the Library or its derivative works. 
- These actions are prohibited by law if you do not accept this License. 
- Therefore, by modifying or distributing the Library (or any work based 
-on the Library), you indicate your acceptance of this License to do so, 
-and all its terms and conditions for copying, distributing or modifying 
-the Library or works based on it. </P>
-<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any 
-work based on the Library), the recipient automatically receives a 
-license from the original licensor to copy, distribute, link with or 
-modify the Library subject to these terms and conditions.  You may not 
-impose any further restrictions on the recipients' exercise of the 
-rights granted herein. You are not responsible for enforcing compliance 
-by third parties to this License. </P>
-<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or 
-allegation of patent infringement or for any other reason (not limited 
-to patent issues), conditions are imposed on you (whether by court 
-order, agreement or otherwise) that contradict the conditions of this 
-License, they do not excuse you from the conditions of this License. 
- If you cannot distribute so as to satisfy simultaneously your 
-obligations under this License and any other pertinent obligations, 
-then as a consequence you may not distribute the Library at all.  For 
-example, if a patent license would not permit royalty-free 
-redistribution of the Library by all those who receive copies directly 
-or indirectly through you, then the only way you could satisfy both it 
-and this License would be to refrain entirely from distribution of the 
-Library. </P>
-<P>If any portion of this section is held invalid or unenforceable 
-under any particular circumstance, the balance of the section is 
-intended to apply, and the section as a whole is intended to apply in 
-other circumstances. </P>
-<P>It is not the purpose of this section to induce you to infringe any 
-patents or other property right claims or to contest validity of any 
-such claims; this section has the sole purpose of protecting the 
-integrity of the free software distribution system which is implemented 
-by public license practices.  Many people have made generous 
-contributions to the wide range of software distributed through that 
-system in reliance on consistent application of that system; it is up 
-to the author/donor to decide if he or she is willing to distribute 
-software through any other system and a licensee cannot impose that 
-choice. </P>
-<P>This section is intended to make thoroughly clear what is believed 
-to be a consequence of the rest of this License. </P>
-<P><STRONG>12.</STRONG> If the distribution and/or use of the Library 
-is restricted in certain countries either by patents or by copyrighted 
-interfaces, the original copyright holder who places the Library under 
-this License may add an explicit geographical distribution limitation 
-excluding those countries, so that distribution is permitted only in or 
-among countries not thus excluded.  In such case, this License 
-incorporates the limitation as if written in the body of this License. </P>
-<P><STRONG>13.</STRONG> The Free Software Foundation may publish 
-revised and/or new versions of the Library General Public License from 
-time to time. Such new versions will be similar in spirit to the 
-present version, but may differ in detail to address new problems or 
-concerns. </P>
-<P>Each version is given a distinguishing version number.  If the 
-Library specifies a version number of this License which applies to it 
-and &quot;any later version&quot;, you have the option of following the terms and 
-conditions either of that version or of any later version published by 
-the Free Software Foundation.  If the Library does not specify a 
-license version number, you may choose any version ever published by 
-the Free Software Foundation. </P>
-<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library 
-into other free programs whose distribution conditions are incompatible 
-with these, write to the author to ask for permission.  For software 
-which is copyrighted by the Free Software Foundation, write to the Free 
-Software Foundation; we sometimes make exceptions for this.  Our 
-decision will be guided by the two goals of preserving the free status 
-of all derivatives of our free software and of promoting the sharing 
-and reuse of software generally. </P>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
 <P><STRONG>NO WARRANTY</STRONG></P>
-<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, 
-THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY 
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT 
-WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT 
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
-PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE 
-OF THE LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU 
-ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </P>
-<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW 
-OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY 
-WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE 
-LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL 
-OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
-DAMAGES. </P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
 <H4>END OF TERMS AND CONDITIONS</H4>
 <H1 ALIGN="RIGHT"><A NAME="CONSTANTS">B - Constants</A></H1>
-<P>This appendix lists all of the constants that are defined by the 
-CUPS API. </P>
+<P>This appendix lists all of the constants that are defined by the CUPS
+ API.</P>
 <H2><A NAME="8_1">CUPS Constants</A></H2>
 <H3><A NAME="8_1_1">Version Number</A></H3>
-<P>The <CODE>CUPS_VERSION</CODE> constant is a floating-point number 
-representing the API version number. The current version number is 
-1.0100 which represents CUPS version 1.1.0. </P>
+<P>The <CODE>CUPS_VERSION</CODE> constant is a floating-point number
+ representing the API version number. The current version number is
+ 1.0100 which represents CUPS version 1.1.0.</P>
 <H3><A NAME="8_1_2">Printer Capabilities</A></H3>
-<P>The <CODE>CUPS_PRINTER</CODE> constants represent capability bits 
-for printers and classes: </P>
-<UL>
-<LI><CODE>CUPS_PRINTER_LOCAL</CODE> - Is a local printer or class. </LI>
-<LI><CODE>CUPS_PRINTER_REMOTE</CODE> - Is a remote printer or class. </LI>
-<LI><CODE>CUPS_PRINTER_CLASS</CODE> - Is a class. </LI>
-<LI><CODE>CUPS_PRINTER_BW</CODE> - Printer prints in black and white. </LI>
-<LI><CODE>CUPS_PRINTER_COLOR</CODE> - Printer prints in color. </LI>
-<LI><CODE>CUPS_PRINTER_DUPLEX</CODE> - Printer can print double-sided. </LI>
-<LI><CODE>CUPS_PRINTER_STAPLE</CODE> - Printer can staple output. </LI>
-<LI><CODE>CUPS_PRINTER_COPIES</CODE> - Printer can produce multiple 
- copies on its own. </LI>
-<LI><CODE>CUPS_PRINTER_COLLATE</CODE> - Printer can collate copies. </LI>
-<LI><CODE>CUPS_PRINTER_PUNCH</CODE> - Printer can punch holes in 
-output. </LI>
-<LI><CODE>CUPS_PRINTER_COVER</CODE> - Printer can put covers on output. </LI>
-<LI><CODE>CUPS_PRINTER_BIND</CODE> - Printer can bind output. </LI>
-<LI><CODE>CUPS_PRINTER_SORT</CODE> - Printer can sort output. </LI>
-<LI><CODE>CUPS_PRINTER_SMALL</CODE> - Printer can print on media up  to 
-9x14 inches. </LI>
-<LI><CODE>CUPS_PRINTER_MEDIUM</CODE> - Printer can print on media  from 
-9x14 to 18x24 inches. </LI>
-<LI><CODE>CUPS_PRINTER_LARGE</CODE> - Printer can print on media 
- larger than 18x24 inches. </LI>
-<LI><CODE>CUPS_PRINTER_VARIABLE</CODE> - Printer can print on  variable 
-or custom media sizes. </LI>
-<LI><CODE>CUPS_PRINTER_IMPLICIT</CODE> - Is an implicit class. </LI>
-<LI><CODE>CUPS_PRINTER_OPTIONS</CODE> - All of the printer capability 
- and option bits. </LI>
+<P>The <CODE>CUPS_PRINTER</CODE> constants represent capability bits for
+ printers and classes:</P>
+<UL>
+<LI><CODE>CUPS_PRINTER_LOCAL</CODE> - Is a local printer or class.</LI>
+<LI><CODE>CUPS_PRINTER_REMOTE</CODE> - Is a remote printer or class.</LI>
+<LI><CODE>CUPS_PRINTER_CLASS</CODE> - Is a class.</LI>
+<LI><CODE>CUPS_PRINTER_BW</CODE> - Printer prints in black and white.</LI>
+<LI><CODE>CUPS_PRINTER_COLOR</CODE> - Printer prints in color.</LI>
+<LI><CODE>CUPS_PRINTER_DUPLEX</CODE> - Printer can print double-sided.</LI>
+<LI><CODE>CUPS_PRINTER_STAPLE</CODE> - Printer can staple output.</LI>
+<LI><CODE>CUPS_PRINTER_COPIES</CODE> - Printer can produce multiple
+ copies on its own.</LI>
+<LI><CODE>CUPS_PRINTER_COLLATE</CODE> - Printer can collate copies.</LI>
+<LI><CODE>CUPS_PRINTER_PUNCH</CODE> - Printer can punch holes in output.</LI>
+<LI><CODE>CUPS_PRINTER_COVER</CODE> - Printer can put covers on output.</LI>
+<LI><CODE>CUPS_PRINTER_BIND</CODE> - Printer can bind output.</LI>
+<LI><CODE>CUPS_PRINTER_SORT</CODE> - Printer can sort output.</LI>
+<LI><CODE>CUPS_PRINTER_SMALL</CODE> - Printer can print on media up to
+ 9x14 inches.</LI>
+<LI><CODE>CUPS_PRINTER_MEDIUM</CODE> - Printer can print on media from
+ 9x14 to 18x24 inches.</LI>
+<LI><CODE>CUPS_PRINTER_LARGE</CODE> - Printer can print on media larger
+ than 18x24 inches.</LI>
+<LI><CODE>CUPS_PRINTER_VARIABLE</CODE> - Printer can print on variable
+ or custom media sizes.</LI>
+<LI><CODE>CUPS_PRINTER_IMPLICIT</CODE> - Is an implicit class.</LI>
+<LI><CODE>CUPS_PRINTER_OPTIONS</CODE> - All of the printer capability
+ and option bits.</LI>
 </UL>
 <H3><A NAME="8_1_3">Encodings</A></H3>
-<P>CUPS defines the following character set encoding constants: </P>
-<UL>
-<LI><CODE>CUPS_US_ASCII</CODE> - US ASCII character set. </LI>
-<LI><CODE>CUPS_UTF_8</CODE> - UTF-8 encoding of Unicode. </LI>
-<LI><CODE>CUPS_ISO8859_1</CODE> - ISO-8859-1 character set. </LI>
-<LI><CODE>CUPS_ISO8859_2</CODE> - ISO-8859-2 character set. </LI>
-<LI><CODE>CUPS_ISO8859_3</CODE> - ISO-8859-3 character set. </LI>
-<LI><CODE>CUPS_ISO8859_4</CODE> - ISO-8859-4 character set. </LI>
-<LI><CODE>CUPS_ISO8859_5</CODE> - ISO-8859-5 character set. </LI>
-<LI><CODE>CUPS_ISO8859_6</CODE> - ISO-8859-6 character set. </LI>
-<LI><CODE>CUPS_ISO8859_7</CODE> - ISO-8859-7 character set. </LI>
-<LI><CODE>CUPS_ISO8859_8</CODE> - ISO-8859-8 character set. </LI>
-<LI><CODE>CUPS_ISO8859_9</CODE> - ISO-8859-9 character set. </LI>
-<LI><CODE>CUPS_ISO8859_10</CODE> - ISO-8859-10 character set. </LI>
-<LI><CODE>CUPS_ISO8859_13</CODE> - ISO-8859-13 character set. </LI>
-<LI><CODE>CUPS_ISO8859_14</CODE> - ISO-8859-14 character set. </LI>
-<LI><CODE>CUPS_ISO8859_15</CODE> - ISO-8859-15 character set. </LI>
-<LI><CODE>CUPS_WINDOWS_874</CODE> - Windows code page 874. </LI>
-<LI><CODE>CUPS_WINDOWS_1250</CODE> - Windows code page 1250. </LI>
-<LI><CODE>CUPS_WINDOWS_1251</CODE> - Windows code page 1251. </LI>
-<LI><CODE>CUPS_WINDOWS_1252</CODE> - Windows code page 1252. </LI>
-<LI><CODE>CUPS_WINDOWS_1253</CODE> - Windows code page 1253. </LI>
-<LI><CODE>CUPS_WINDOWS_1254</CODE> - Windows code page 1254. </LI>
-<LI><CODE>CUPS_WINDOWS_1255</CODE> - Windows code page 1255. </LI>
-<LI><CODE>CUPS_WINDOWS_1256</CODE> - Windows code page 1256. </LI>
-<LI><CODE>CUPS_WINDOWS_1257</CODE> - Windows code page 1257. </LI>
-<LI><CODE>CUPS_WINDOWS_1258</CODE> - Windows code page 1258. </LI>
+<P>CUPS defines the following character set encoding constants:</P>
+<UL>
+<LI><CODE>CUPS_US_ASCII</CODE> - US ASCII character set.</LI>
+<LI><CODE>CUPS_UTF_8</CODE> - UTF-8 encoding of Unicode.</LI>
+<LI><CODE>CUPS_ISO8859_1</CODE> - ISO-8859-1 character set.</LI>
+<LI><CODE>CUPS_ISO8859_2</CODE> - ISO-8859-2 character set.</LI>
+<LI><CODE>CUPS_ISO8859_3</CODE> - ISO-8859-3 character set.</LI>
+<LI><CODE>CUPS_ISO8859_4</CODE> - ISO-8859-4 character set.</LI>
+<LI><CODE>CUPS_ISO8859_5</CODE> - ISO-8859-5 character set.</LI>
+<LI><CODE>CUPS_ISO8859_6</CODE> - ISO-8859-6 character set.</LI>
+<LI><CODE>CUPS_ISO8859_7</CODE> - ISO-8859-7 character set.</LI>
+<LI><CODE>CUPS_ISO8859_8</CODE> - ISO-8859-8 character set.</LI>
+<LI><CODE>CUPS_ISO8859_9</CODE> - ISO-8859-9 character set.</LI>
+<LI><CODE>CUPS_ISO8859_10</CODE> - ISO-8859-10 character set.</LI>
+<LI><CODE>CUPS_ISO8859_13</CODE> - ISO-8859-13 character set.</LI>
+<LI><CODE>CUPS_ISO8859_14</CODE> - ISO-8859-14 character set.</LI>
+<LI><CODE>CUPS_ISO8859_15</CODE> - ISO-8859-15 character set.</LI>
+<LI><CODE>CUPS_WINDOWS_874</CODE> - Windows code page 874.</LI>
+<LI><CODE>CUPS_WINDOWS_1250</CODE> - Windows code page 1250.</LI>
+<LI><CODE>CUPS_WINDOWS_1251</CODE> - Windows code page 1251.</LI>
+<LI><CODE>CUPS_WINDOWS_1252</CODE> - Windows code page 1252.</LI>
+<LI><CODE>CUPS_WINDOWS_1253</CODE> - Windows code page 1253.</LI>
+<LI><CODE>CUPS_WINDOWS_1254</CODE> - Windows code page 1254.</LI>
+<LI><CODE>CUPS_WINDOWS_1255</CODE> - Windows code page 1255.</LI>
+<LI><CODE>CUPS_WINDOWS_1256</CODE> - Windows code page 1256.</LI>
+<LI><CODE>CUPS_WINDOWS_1257</CODE> - Windows code page 1257.</LI>
+<LI><CODE>CUPS_WINDOWS_1258</CODE> - Windows code page 1258.</LI>
 </UL>
 <H2><A NAME="8_2">HTTP Constants</A></H2>
 <H3><A NAME="8_2_1">Limits</A></H3>
-<P>The following constants define the limits for strings: </P>
+<P>The following constants define the limits for strings:</P>
 <UL>
-<LI><CODE>HTTP_MAX_BUFFER</CODE> - Size of socket buffer. </LI>
-<LI><CODE>HTTP_MAX_HOST</CODE> - Maximum length of hostname. </LI>
-<LI><CODE>HTTP_MAX_URI</CODE> - Maximum length of URI. </LI>
-<LI><CODE>HTTP_MAX_VALUE</CODE> - Maximum length of field values. </LI>
+<LI><CODE>HTTP_MAX_BUFFER</CODE> - Size of socket buffer.</LI>
+<LI><CODE>HTTP_MAX_HOST</CODE> - Maximum length of hostname.</LI>
+<LI><CODE>HTTP_MAX_URI</CODE> - Maximum length of URI.</LI>
+<LI><CODE>HTTP_MAX_VALUE</CODE> - Maximum length of field values.</LI>
 </UL>
 <H3><A NAME="8_2_2">Status Codes</A></H3>
 <P>The following status codes can be returned by <CODE>httpUpdate()</CODE>
-: </P>
-<UL>
-<LI><CODE>HTTP_ERROR</CODE> - A network error occurred </LI>
-<LI><CODE>HTTP_CONTINUE</CODE> - Continue response from HTTP proxy </LI>
-<LI><CODE>HTTP_OK</CODE> - OPTIONS/GET/HEAD/POST/TRACE command was 
-successful </LI>
-<LI><CODE>HTTP_CREATED</CODE> - PUT command was successful </LI>
-<LI><CODE>HTTP_ACCEPTED</CODE> - DELETE command was successful </LI>
-<LI><CODE>HTTP_NOT_AUTHORITATIVE</CODE> - Information isn't 
-authoritative </LI>
-<LI><CODE>HTTP_NO_CONTENT</CODE> - Successful command </LI>
-<LI><CODE>HTTP_RESET_CONTENT</CODE> - Content was reset/recreated </LI>
-<LI><CODE>HTTP_PARTIAL_CONTENT</CODE> - Only a partial file was 
-recieved/sent </LI>
-<LI><CODE>HTTP_MULTIPLE_CHOICES</CODE> - Multiple files match request </LI>
-<LI><CODE>HTTP_MOVED_PERMANENTLY</CODE> - Document has moved 
-permanently </LI>
-<LI><CODE>HTTP_MOVED_TEMPORARILY</CODE> - Document has moved 
-temporarily </LI>
-<LI><CODE>HTTP_SEE_OTHER</CODE> - See this other link... </LI>
-<LI><CODE>HTTP_NOT_MODIFIED</CODE> - File not modified </LI>
-<LI><CODE>HTTP_USE_PROXY</CODE> - Must use a proxy to access this URI </LI>
-<LI><CODE>HTTP_BAD_REQUEST</CODE> - Bad request </LI>
-<LI><CODE>HTTP_UNAUTHORIZED</CODE> - Unauthorized to access host </LI>
-<LI><CODE>HTTP_PAYMENT_REQUIRED</CODE> - Payment required </LI>
-<LI><CODE>HTTP_FORBIDDEN</CODE> - Forbidden to access this URI </LI>
-<LI><CODE>HTTP_NOT_FOUND</CODE> - URI was not found </LI>
-<LI><CODE>HTTP_METHOD_NOT_ALLOWED</CODE> - Method is not allowed </LI>
-<LI><CODE>HTTP_NOT_ACCEPTABLE</CODE> - Not Acceptable </LI>
-<LI><CODE>HTTP_PROXY_AUTHENTICATION</CODE> - Proxy Authentication is 
-Required </LI>
-<LI><CODE>HTTP_REQUEST_TIMEOUT</CODE> - Request timed out </LI>
-<LI><CODE>HTTP_CONFLICT</CODE> - Request is self-conflicting </LI>
-<LI><CODE>HTTP_GONE</CODE> - Server has gone away </LI>
-<LI><CODE>HTTP_LENGTH_REQUIRED</CODE> - A content length or encoding is 
-required </LI>
-<LI><CODE>HTTP_PRECONDITION</CODE> - Precondition failed </LI>
-<LI><CODE>HTTP_REQUEST_TOO_LARGE</CODE> - Request entity too large </LI>
-<LI><CODE>HTTP_URI_TOO_LONG</CODE> - URI too long </LI>
-<LI><CODE>HTTP_UNSUPPORTED_MEDIATYPE</CODE> - The requested media type 
-is unsupported </LI>
-<LI><CODE>HTTP_SERVER_ERROR</CODE> - Internal server error </LI>
-<LI><CODE>HTTP_NOT_IMPLEMENTED</CODE> - Feature not implemented </LI>
-<LI><CODE>HTTP_BAD_GATEWAY</CODE> - Bad gateway </LI>
-<LI><CODE>HTTP_SERVICE_UNAVAILABLE</CODE> - Service is unavailable </LI>
-<LI><CODE>HTTP_GATEWAY_TIMEOUT</CODE> - Gateway connection timed out </LI>
-<LI><CODE>HTTP_NOT_SUPPORTED</CODE> - HTTP version not supported </LI>
+:</P>
+<UL>
+<LI><CODE>HTTP_ERROR</CODE> - A network error occurred</LI>
+<LI><CODE>HTTP_CONTINUE</CODE> - Continue response from HTTP proxy</LI>
+<LI><CODE>HTTP_OK</CODE> - OPTIONS/GET/HEAD/POST/TRACE command was
+ successful</LI>
+<LI><CODE>HTTP_CREATED</CODE> - PUT command was successful</LI>
+<LI><CODE>HTTP_ACCEPTED</CODE> - DELETE command was successful</LI>
+<LI><CODE>HTTP_NOT_AUTHORITATIVE</CODE> - Information isn't
+ authoritative</LI>
+<LI><CODE>HTTP_NO_CONTENT</CODE> - Successful command</LI>
+<LI><CODE>HTTP_RESET_CONTENT</CODE> - Content was reset/recreated</LI>
+<LI><CODE>HTTP_PARTIAL_CONTENT</CODE> - Only a partial file was
+ recieved/sent</LI>
+<LI><CODE>HTTP_MULTIPLE_CHOICES</CODE> - Multiple files match request</LI>
+<LI><CODE>HTTP_MOVED_PERMANENTLY</CODE> - Document has moved permanently</LI>
+<LI><CODE>HTTP_MOVED_TEMPORARILY</CODE> - Document has moved temporarily</LI>
+<LI><CODE>HTTP_SEE_OTHER</CODE> - See this other link...</LI>
+<LI><CODE>HTTP_NOT_MODIFIED</CODE> - File not modified</LI>
+<LI><CODE>HTTP_USE_PROXY</CODE> - Must use a proxy to access this URI</LI>
+<LI><CODE>HTTP_BAD_REQUEST</CODE> - Bad request</LI>
+<LI><CODE>HTTP_UNAUTHORIZED</CODE> - Unauthorized to access host</LI>
+<LI><CODE>HTTP_PAYMENT_REQUIRED</CODE> - Payment required</LI>
+<LI><CODE>HTTP_FORBIDDEN</CODE> - Forbidden to access this URI</LI>
+<LI><CODE>HTTP_NOT_FOUND</CODE> - URI was not found</LI>
+<LI><CODE>HTTP_METHOD_NOT_ALLOWED</CODE> - Method is not allowed</LI>
+<LI><CODE>HTTP_NOT_ACCEPTABLE</CODE> - Not Acceptable</LI>
+<LI><CODE>HTTP_PROXY_AUTHENTICATION</CODE> - Proxy Authentication is
+ Required</LI>
+<LI><CODE>HTTP_REQUEST_TIMEOUT</CODE> - Request timed out</LI>
+<LI><CODE>HTTP_CONFLICT</CODE> - Request is self-conflicting</LI>
+<LI><CODE>HTTP_GONE</CODE> - Server has gone away</LI>
+<LI><CODE>HTTP_LENGTH_REQUIRED</CODE> - A content length or encoding is
+ required</LI>
+<LI><CODE>HTTP_PRECONDITION</CODE> - Precondition failed</LI>
+<LI><CODE>HTTP_REQUEST_TOO_LARGE</CODE> - Request entity too large</LI>
+<LI><CODE>HTTP_URI_TOO_LONG</CODE> - URI too long</LI>
+<LI><CODE>HTTP_UNSUPPORTED_MEDIATYPE</CODE> - The requested media type
+ is unsupported</LI>
+<LI><CODE>HTTP_SERVER_ERROR</CODE> - Internal server error</LI>
+<LI><CODE>HTTP_NOT_IMPLEMENTED</CODE> - Feature not implemented</LI>
+<LI><CODE>HTTP_BAD_GATEWAY</CODE> - Bad gateway</LI>
+<LI><CODE>HTTP_SERVICE_UNAVAILABLE</CODE> - Service is unavailable</LI>
+<LI><CODE>HTTP_GATEWAY_TIMEOUT</CODE> - Gateway connection timed out</LI>
+<LI><CODE>HTTP_NOT_SUPPORTED</CODE> - HTTP version not supported</LI>
 </UL>
 <H3><A NAME="8_2_3">Fields</A></H3>
-<P>The following fields are indices for each of the standard HTTP 
-fields in HTTP 1/1: </P>
-<UL>
-<LI><CODE>HTTP_FIELD_ACCEPT_LANGUAGE</CODE> - Accept-Language </LI>
-<LI><CODE>HTTP_FIELD_ACCEPT_RANGES</CODE> - Accept-Ranges </LI>
-<LI><CODE>HTTP_FIELD_AUTHORIZATION</CODE> - Authorization </LI>
-<LI><CODE>HTTP_FIELD_CONNECTION</CODE> - Connection </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_ENCODING</CODE> - Content-Encoding </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_LANGUAGE</CODE> - Content-Language </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_LENGTH</CODE> - Content-Length </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_LOCATION</CODE> - Content-Location </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_MD5</CODE> - Content-MD5 </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_RANGE</CODE> - Content-Range </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_TYPE</CODE> - Content-Type </LI>
-<LI><CODE>HTTP_FIELD_CONTENT_VERSION</CODE> - Content-Version </LI>
-<LI><CODE>HTTP_FIELD_DATE</CODE> - Date </LI>
-<LI><CODE>HTTP_FIELD_HOST</CODE> - Host </LI>
-<LI><CODE>HTTP_FIELD_IF_MODIFIED_SINCE</CODE> - If-Modified-Since </LI>
-<LI><CODE>HTTP_FIELD_IF_UNMODIFIED_SINCE</CODE> - If-Unmodified-Since </LI>
-<LI><CODE>HTTP_FIELD_KEEP_ALIVE</CODE> - Keep-Alive </LI>
-<LI><CODE>HTTP_FIELD_LAST_MODIFIED</CODE> - Last-Modified </LI>
-<LI><CODE>HTTP_FIELD_LINK</CODE> - Link </LI>
-<LI><CODE>HTTP_FIELD_LOCATION</CODE> - Location </LI>
-<LI><CODE>HTTP_FIELD_RANGE</CODE> - Range </LI>
-<LI><CODE>HTTP_FIELD_REFERER</CODE> - Referer </LI>
-<LI><CODE>HTTP_FIELD_RETRY_AFTER</CODE> - Retry-After </LI>
-<LI><CODE>HTTP_FIELD_TRANSFER_ENCODING</CODE> - Transfer-Encoding </LI>
-<LI><CODE>HTTP_FIELD_UPGRADE</CODE> - Upgrade </LI>
-<LI><CODE>HTTP_FIELD_USER_AGENT</CODE> - User-Agent </LI>
-<LI><CODE>HTTP_FIELD_WWW_AUTHENTICATE</CODE> - WWW-Authenticate </LI>
+<P>The following fields are indices for each of the standard HTTP fields
+ in HTTP 1/1:</P>
+<UL>
+<LI><CODE>HTTP_FIELD_ACCEPT_LANGUAGE</CODE> - Accept-Language</LI>
+<LI><CODE>HTTP_FIELD_ACCEPT_RANGES</CODE> - Accept-Ranges</LI>
+<LI><CODE>HTTP_FIELD_AUTHORIZATION</CODE> - Authorization</LI>
+<LI><CODE>HTTP_FIELD_CONNECTION</CODE> - Connection</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_ENCODING</CODE> - Content-Encoding</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_LANGUAGE</CODE> - Content-Language</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_LENGTH</CODE> - Content-Length</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_LOCATION</CODE> - Content-Location</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_MD5</CODE> - Content-MD5</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_RANGE</CODE> - Content-Range</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_TYPE</CODE> - Content-Type</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_VERSION</CODE> - Content-Version</LI>
+<LI><CODE>HTTP_FIELD_DATE</CODE> - Date</LI>
+<LI><CODE>HTTP_FIELD_HOST</CODE> - Host</LI>
+<LI><CODE>HTTP_FIELD_IF_MODIFIED_SINCE</CODE> - If-Modified-Since</LI>
+<LI><CODE>HTTP_FIELD_IF_UNMODIFIED_SINCE</CODE> - If-Unmodified-Since</LI>
+<LI><CODE>HTTP_FIELD_KEEP_ALIVE</CODE> - Keep-Alive</LI>
+<LI><CODE>HTTP_FIELD_LAST_MODIFIED</CODE> - Last-Modified</LI>
+<LI><CODE>HTTP_FIELD_LINK</CODE> - Link</LI>
+<LI><CODE>HTTP_FIELD_LOCATION</CODE> - Location</LI>
+<LI><CODE>HTTP_FIELD_RANGE</CODE> - Range</LI>
+<LI><CODE>HTTP_FIELD_REFERER</CODE> - Referer</LI>
+<LI><CODE>HTTP_FIELD_RETRY_AFTER</CODE> - Retry-After</LI>
+<LI><CODE>HTTP_FIELD_TRANSFER_ENCODING</CODE> - Transfer-Encoding</LI>
+<LI><CODE>HTTP_FIELD_UPGRADE</CODE> - Upgrade</LI>
+<LI><CODE>HTTP_FIELD_USER_AGENT</CODE> - User-Agent</LI>
+<LI><CODE>HTTP_FIELD_WWW_AUTHENTICATE</CODE> - WWW-Authenticate</LI>
 </UL>
 <H2><A NAME="8_3">IPP Constants</A></H2>
 <H3><A NAME="8_3_1">Limits</A></H3>
-<P>The following constants define array limits for IPP data: </P>
+<P>The following constants define array limits for IPP data:</P>
 <UL>
-<LI><CODE>IPP_MAX_NAME</CODE> - Maximum length of an attribute name </LI>
-<LI><CODE>IPP_MAX_VALUES</CODE> - Maximum number of set-of values  that 
-can be read in a request. </LI>
+<LI><CODE>IPP_MAX_NAME</CODE> - Maximum length of an attribute name</LI>
+<LI><CODE>IPP_MAX_VALUES</CODE> - Maximum number of set-of values that
+ can be read in a request.</LI>
 </UL>
 <H3><A NAME="8_3_2">Tags</A></H3>
 <UL>
-<LI><CODE>IPP_TAG_ZERO</CODE> - Wildcard tag value for searches; also 
- used to separate groups of attributes </LI>
-<LI><CODE>IPP_TAG_OPERATION</CODE> - Tag for values of type operation </LI>
-<LI><CODE>IPP_TAG_JOB</CODE> - Tag for values of type job </LI>
-<LI><CODE>IPP_TAG_END</CODE> - Tag for values of type end </LI>
-<LI><CODE>IPP_TAG_PRINTER</CODE> - Tag for values of type printer </LI>
-<LI><CODE>IPP_TAG_UNSUPPORTED_GROUP</CODE> - Tag for values of type 
-unsupported_group </LI>
-<LI><CODE>IPP_TAG_UNSUPPORTED_VALUE</CODE> - Tag for values of type 
-unsupported_value </LI>
-<LI><CODE>IPP_TAG_DEFAULT</CODE> - Tag for values of type default </LI>
-<LI><CODE>IPP_TAG_UNKNOWN</CODE> - Tag for values of type unknown </LI>
-<LI><CODE>IPP_TAG_NOVALUE</CODE> - Tag for values of type novalue </LI>
-<LI><CODE>IPP_TAG_NOTSETTABLE</CODE> - Tag for values of type 
-notsettable </LI>
-<LI><CODE>IPP_TAG_DELETEATTR</CODE> - Tag for values of type deleteattr </LI>
-<LI><CODE>IPP_TAG_ANYVALUE</CODE> - Tag for values of type anyvalue </LI>
-<LI><CODE>IPP_TAG_INTEGER</CODE> - Tag for values of type integer </LI>
-<LI><CODE>IPP_TAG_BOOLEAN</CODE> - Tag for values of type boolean </LI>
-<LI><CODE>IPP_TAG_ENUM</CODE> - Tag for values of type enum </LI>
-<LI><CODE>IPP_TAG_STRING</CODE> - Tag for values of type string </LI>
-<LI><CODE>IPP_TAG_DATE</CODE> - Tag for values of type date </LI>
-<LI><CODE>IPP_TAG_RESOLUTION</CODE> - Tag for values of type resolution </LI>
-<LI><CODE>IPP_TAG_RANGE</CODE> - Tag for values of type range </LI>
-<LI><CODE>IPP_TAG_COLLECTION</CODE> - Tag for values of type collection </LI>
-<LI><CODE>IPP_TAG_TEXTLANG</CODE> - Tag for values of type textlang </LI>
-<LI><CODE>IPP_TAG_NAMELANG</CODE> - Tag for values of type namelang </LI>
-<LI><CODE>IPP_TAG_TEXT</CODE> - Tag for values of type text </LI>
-<LI><CODE>IPP_TAG_NAME</CODE> - Tag for values of type name </LI>
-<LI><CODE>IPP_TAG_KEYWORD</CODE> - Tag for values of type keyword </LI>
-<LI><CODE>IPP_TAG_URI</CODE> - Tag for values of type uri </LI>
-<LI><CODE>IPP_TAG_URISCHEME</CODE> - Tag for values of type urischeme </LI>
-<LI><CODE>IPP_TAG_CHARSET</CODE> - Tag for values of type charset </LI>
-<LI><CODE>IPP_TAG_LANGUAGE</CODE> - Tag for values of type language </LI>
-<LI><CODE>IPP_TAG_MIMETYPE</CODE> - Tag for values of type mimetype </LI>
+<LI><CODE>IPP_TAG_ZERO</CODE> - Wildcard tag value for searches; also
+ used to separate groups of attributes</LI>
+<LI><CODE>IPP_TAG_OPERATION</CODE> - Tag for values of type operation</LI>
+<LI><CODE>IPP_TAG_JOB</CODE> - Tag for values of type job</LI>
+<LI><CODE>IPP_TAG_END</CODE> - Tag for values of type end</LI>
+<LI><CODE>IPP_TAG_PRINTER</CODE> - Tag for values of type printer</LI>
+<LI><CODE>IPP_TAG_UNSUPPORTED_GROUP</CODE> - Tag for values of type
+ unsupported_group</LI>
+<LI><CODE>IPP_TAG_UNSUPPORTED_VALUE</CODE> - Tag for values of type
+ unsupported_value</LI>
+<LI><CODE>IPP_TAG_DEFAULT</CODE> - Tag for values of type default</LI>
+<LI><CODE>IPP_TAG_UNKNOWN</CODE> - Tag for values of type unknown</LI>
+<LI><CODE>IPP_TAG_NOVALUE</CODE> - Tag for values of type novalue</LI>
+<LI><CODE>IPP_TAG_NOTSETTABLE</CODE> - Tag for values of type
+ notsettable</LI>
+<LI><CODE>IPP_TAG_DELETEATTR</CODE> - Tag for values of type deleteattr</LI>
+<LI><CODE>IPP_TAG_ANYVALUE</CODE> - Tag for values of type anyvalue</LI>
+<LI><CODE>IPP_TAG_INTEGER</CODE> - Tag for values of type integer</LI>
+<LI><CODE>IPP_TAG_BOOLEAN</CODE> - Tag for values of type boolean</LI>
+<LI><CODE>IPP_TAG_ENUM</CODE> - Tag for values of type enum</LI>
+<LI><CODE>IPP_TAG_STRING</CODE> - Tag for values of type string</LI>
+<LI><CODE>IPP_TAG_DATE</CODE> - Tag for values of type date</LI>
+<LI><CODE>IPP_TAG_RESOLUTION</CODE> - Tag for values of type resolution</LI>
+<LI><CODE>IPP_TAG_RANGE</CODE> - Tag for values of type range</LI>
+<LI><CODE>IPP_TAG_COLLECTION</CODE> - Tag for values of type collection</LI>
+<LI><CODE>IPP_TAG_TEXTLANG</CODE> - Tag for values of type textlang</LI>
+<LI><CODE>IPP_TAG_NAMELANG</CODE> - Tag for values of type namelang</LI>
+<LI><CODE>IPP_TAG_TEXT</CODE> - Tag for values of type text</LI>
+<LI><CODE>IPP_TAG_NAME</CODE> - Tag for values of type name</LI>
+<LI><CODE>IPP_TAG_KEYWORD</CODE> - Tag for values of type keyword</LI>
+<LI><CODE>IPP_TAG_URI</CODE> - Tag for values of type uri</LI>
+<LI><CODE>IPP_TAG_URISCHEME</CODE> - Tag for values of type urischeme</LI>
+<LI><CODE>IPP_TAG_CHARSET</CODE> - Tag for values of type charset</LI>
+<LI><CODE>IPP_TAG_LANGUAGE</CODE> - Tag for values of type language</LI>
+<LI><CODE>IPP_TAG_MIMETYPE</CODE> - Tag for values of type mimetype</LI>
 </UL>
 <H3><A NAME="8_3_3">Resolution Units</A></H3>
 <P>The <CODE>IPP_RES_PER_INCH</CODE> and <CODE>IPP_RES_PER_CM</CODE>
- constants specify dots per inch and dots per centimeter, respectively. </P>
+ constants specify dots per inch and dots per centimeter, respectively.</P>
 <H3><A NAME="8_3_4">Finishings</A></H3>
-<P>The finishing values specify special finishing operations to be 
-performed on the job. </P>
+<P>The finishing values specify special finishing operations to be
+ performed on the job.</P>
 <UL>
-<LI><CODE>IPP_FINISH_NONE</CODE> - Do no finishing </LI>
-<LI><CODE>IPP_FINISH_STAPLE</CODE> - Staple the job </LI>
-<LI><CODE>IPP_FINISH_PUNCH</CODE> - Punch the job </LI>
-<LI><CODE>IPP_FINISH_COVER</CODE> - Cover the job </LI>
-<LI><CODE>IPP_FINISH_BIND</CODE> - Bind the job </LI>
+<LI><CODE>IPP_FINISH_NONE</CODE> - Do no finishing</LI>
+<LI><CODE>IPP_FINISH_STAPLE</CODE> - Staple the job</LI>
+<LI><CODE>IPP_FINISH_PUNCH</CODE> - Punch the job</LI>
+<LI><CODE>IPP_FINISH_COVER</CODE> - Cover the job</LI>
+<LI><CODE>IPP_FINISH_BIND</CODE> - Bind the job</LI>
 </UL>
 <H3><A NAME="8_3_5">Orientations</A></H3>
-<P>The orientation values specify the orientation of the job. </P>
+<P>The orientation values specify the orientation of the job.</P>
 <UL>
-<LI><CODE>IPP_PORTRAIT</CODE> - No rotation </LI>
-<LI><CODE>IPP_LANDSCAPE</CODE> - 90 degrees counter-clockwise </LI>
-<LI><CODE>IPP_REVERSE_LANDSCAPE</CODE> - 90 degrees clockwise </LI>
-<LI><CODE>IPP_REVERSE_PORTRAIT</CODE> - 180 degrees </LI>
+<LI><CODE>IPP_PORTRAIT</CODE> - No rotation</LI>
+<LI><CODE>IPP_LANDSCAPE</CODE> - 90 degrees counter-clockwise</LI>
+<LI><CODE>IPP_REVERSE_LANDSCAPE</CODE> - 90 degrees clockwise</LI>
+<LI><CODE>IPP_REVERSE_PORTRAIT</CODE> - 180 degrees</LI>
 </UL>
 <H3><A NAME="8_3_6">Qualities</A></H3>
-<P>The quality values specify the desired quality of the print. </P>
+<P>The quality values specify the desired quality of the print.</P>
 <UL>
-<LI><CODE>IPP_QUALITY_DRAFT</CODE> - Draft quality </LI>
-<LI><CODE>IPP_QUALITY_NORMAL</CODE> - Normal quality </LI>
-<LI><CODE>IPP_QUALITY_HIGH</CODE> - High quality </LI>
+<LI><CODE>IPP_QUALITY_DRAFT</CODE> - Draft quality</LI>
+<LI><CODE>IPP_QUALITY_NORMAL</CODE> - Normal quality</LI>
+<LI><CODE>IPP_QUALITY_HIGH</CODE> - High quality</LI>
 </UL>
 <H3><A NAME="8_3_7">Job States</A></H3>
-<P>The job state values are used to represent the current job state. </P>
+<P>The job state values are used to represent the current job state.</P>
 <UL>
-<LI><CODE>IPP_JOB_PENDING</CODE> - Job is pending </LI>
-<LI><CODE>IPP_JOB_HELD</CODE> - Job is held </LI>
-<LI><CODE>IPP_JOB_PROCESSING</CODE> - Job is processing </LI>
-<LI><CODE>IPP_JOB_STOPPED</CODE> - Job is stopped </LI>
-<LI><CODE>IPP_JOB_CANCELLED</CODE> - Job is cancelled </LI>
-<LI><CODE>IPP_JOB_ABORTED</CODE> - Job is aborted </LI>
-<LI><CODE>IPP_JOB_COMPLETED</CODE> - Job is completed </LI>
+<LI><CODE>IPP_JOB_PENDING</CODE> - Job is pending</LI>
+<LI><CODE>IPP_JOB_HELD</CODE> - Job is held</LI>
+<LI><CODE>IPP_JOB_PROCESSING</CODE> - Job is processing</LI>
+<LI><CODE>IPP_JOB_STOPPED</CODE> - Job is stopped</LI>
+<LI><CODE>IPP_JOB_CANCELLED</CODE> - Job is cancelled</LI>
+<LI><CODE>IPP_JOB_ABORTED</CODE> - Job is aborted</LI>
+<LI><CODE>IPP_JOB_COMPLETED</CODE> - Job is completed</LI>
 </UL>
 <H3><A NAME="8_3_8">Printer States</A></H3>
-<P>The printer state values are used to represent the current printer 
-state. </P>
+<P>The printer state values are used to represent the current printer
+ state.</P>
 <UL>
-<LI><CODE>IPP_PRINTER_IDLE</CODE> - Printer is idle </LI>
-<LI><CODE>IPP_PRINTER_PROCESSING</CODE> - Printer is processing </LI>
-<LI><CODE>IPP_PRINTER_STOPPED</CODE> - Printer is stopped </LI>
+<LI><CODE>IPP_PRINTER_IDLE</CODE> - Printer is idle</LI>
+<LI><CODE>IPP_PRINTER_PROCESSING</CODE> - Printer is processing</LI>
+<LI><CODE>IPP_PRINTER_STOPPED</CODE> - Printer is stopped</LI>
 </UL>
 <H3><A NAME="8_3_9">Operations</A></H3>
-<P>The operation values represent the available IPP operations. </P>
-<UL>
-<LI><CODE>IPP_PRINT_JOB</CODE> - Print a file </LI>
-<LI><CODE>IPP_PRINT_URI</CODE> - Print a URI </LI>
-<LI><CODE>IPP_VALIDATE_JOB</CODE> - Validate job attributes </LI>
-<LI><CODE>IPP_CREATE_JOB</CODE> - Create a new job </LI>
-<LI><CODE>IPP_SEND_DOCUMENT</CODE> - Send a document to a job </LI>
-<LI><CODE>IPP_SEND_URI</CODE> - Send a URI to a job </LI>
-<LI><CODE>IPP_CANCEL_JOB</CODE> - Cancel a job </LI>
-<LI><CODE>IPP_GET_JOB_ATTRIBUTES</CODE> - Get job attributes </LI>
-<LI><CODE>IPP_GET_JOBS</CODE> - Get a list of all jobs </LI>
-<LI><CODE>IPP_GET_PRINTER_ATTRIBUTES</CODE> - Get printer attributes </LI>
-<LI><CODE>IPP_HOLD_JOB</CODE> - Hold a pending job </LI>
-<LI><CODE>IPP_RELEASE_JOB</CODE> - Release a held job </LI>
-<LI><CODE>IPP_RESTART_JOB</CODE> - Restart a completed job </LI>
-<LI><CODE>IPP_PAUSE_PRINTER</CODE> - Pause a printer </LI>
-<LI><CODE>IPP_RESUME_PRINTER</CODE> - Restart a paused printer </LI>
-<LI><CODE>IPP_PURGE_JOBS</CODE> - Purge jobs from the queue </LI>
-<LI><CODE>IPP_SET_PRINTER_ATTRIBUTES</CODE> - Set printer attributes </LI>
-<LI><CODE>IPP_SET_JOB_ATTRIBUTES</CODE> - Set job attributes </LI>
-<LI><CODE>IPP_GET_PRINTER_SUPPORTED_VALUES</CODE> - Get printer 
-supported values </LI>
-<LI><CODE>CUPS_GET_DEFAULT</CODE> - Get the default destination </LI>
-<LI><CODE>CUPS_GET_PRINTERS</CODE> - Get a list of all printers </LI>
-<LI><CODE>CUPS_ADD_PRINTER</CODE> - Add or modify a printer </LI>
-<LI><CODE>CUPS_DELETE_PRINTER</CODE> - Delete a printer </LI>
-<LI><CODE>CUPS_GET_CLASSES</CODE> - Get a list of all classes </LI>
-<LI><CODE>CUPS_ADD_CLASS</CODE> - Add or modify a class </LI>
-<LI><CODE>CUPS_DELETE_CLASS</CODE> - Delete a class </LI>
-<LI><CODE>CUPS_ACCEPT_JOBS</CODE> - Accept jobs on a printer or class </LI>
-<LI><CODE>CUPS_REJECT_JOBS</CODE> - Reject jobs on a printer or class </LI>
-<LI><CODE>CUPS_SET_DEFAULT</CODE> - Set the default destination </LI>
-<LI><CODE>CUPS_GET_DEVICES</CODE> - Get a list of all devices </LI>
-<LI><CODE>CUPS_GET_PPDS</CODE> - Get a list of all PPDs </LI>
-<LI><CODE>CUPS_MOVE_JOB</CODE> - Move a job to a new destination </LI>
+<P>The operation values represent the available IPP operations.</P>
+<UL>
+<LI><CODE>IPP_PRINT_JOB</CODE> - Print a file</LI>
+<LI><CODE>IPP_PRINT_URI</CODE> - Print a URI</LI>
+<LI><CODE>IPP_VALIDATE_JOB</CODE> - Validate job attributes</LI>
+<LI><CODE>IPP_CREATE_JOB</CODE> - Create a new job</LI>
+<LI><CODE>IPP_SEND_DOCUMENT</CODE> - Send a document to a job</LI>
+<LI><CODE>IPP_SEND_URI</CODE> - Send a URI to a job</LI>
+<LI><CODE>IPP_CANCEL_JOB</CODE> - Cancel a job</LI>
+<LI><CODE>IPP_GET_JOB_ATTRIBUTES</CODE> - Get job attributes</LI>
+<LI><CODE>IPP_GET_JOBS</CODE> - Get a list of all jobs</LI>
+<LI><CODE>IPP_GET_PRINTER_ATTRIBUTES</CODE> - Get printer attributes</LI>
+<LI><CODE>IPP_HOLD_JOB</CODE> - Hold a pending job</LI>
+<LI><CODE>IPP_RELEASE_JOB</CODE> - Release a held job</LI>
+<LI><CODE>IPP_RESTART_JOB</CODE> - Restart a completed job</LI>
+<LI><CODE>IPP_PAUSE_PRINTER</CODE> - Pause a printer</LI>
+<LI><CODE>IPP_RESUME_PRINTER</CODE> - Restart a paused printer</LI>
+<LI><CODE>IPP_PURGE_JOBS</CODE> - Purge jobs from the queue</LI>
+<LI><CODE>IPP_SET_PRINTER_ATTRIBUTES</CODE> - Set printer attributes</LI>
+<LI><CODE>IPP_SET_JOB_ATTRIBUTES</CODE> - Set job attributes</LI>
+<LI><CODE>IPP_GET_PRINTER_SUPPORTED_VALUES</CODE> - Get printer
+ supported values</LI>
+<LI><CODE>CUPS_GET_DEFAULT</CODE> - Get the default destination</LI>
+<LI><CODE>CUPS_GET_PRINTERS</CODE> - Get a list of all printers</LI>
+<LI><CODE>CUPS_ADD_PRINTER</CODE> - Add or modify a printer</LI>
+<LI><CODE>CUPS_DELETE_PRINTER</CODE> - Delete a printer</LI>
+<LI><CODE>CUPS_GET_CLASSES</CODE> - Get a list of all classes</LI>
+<LI><CODE>CUPS_ADD_CLASS</CODE> - Add or modify a class</LI>
+<LI><CODE>CUPS_DELETE_CLASS</CODE> - Delete a class</LI>
+<LI><CODE>CUPS_ACCEPT_JOBS</CODE> - Accept jobs on a printer or class</LI>
+<LI><CODE>CUPS_REJECT_JOBS</CODE> - Reject jobs on a printer or class</LI>
+<LI><CODE>CUPS_SET_DEFAULT</CODE> - Set the default destination</LI>
+<LI><CODE>CUPS_GET_DEVICES</CODE> - Get a list of all devices</LI>
+<LI><CODE>CUPS_GET_PPDS</CODE> - Get a list of all PPDs</LI>
+<LI><CODE>CUPS_MOVE_JOB</CODE> - Move a job to a new destination</LI>
 </UL>
 <H3><A NAME="8_3_10">Status Codes</A></H3>
-<P>Status codes are returned by all IPP requests. </P>
-<UL>
-<LI><CODE>IPP_OK</CODE> - Request completed with no errors </LI>
-<LI><CODE>IPP_OK_SUBST</CODE> - Request completed but some attribute 
- values were substituted </LI>
-<LI><CODE>IPP_OK_CONFLICT</CODE> - Request completed but some 
-attributes  conflicted </LI>
-<LI><CODE>IPP_BAD_REQUEST</CODE> - The request was bad </LI>
-<LI><CODE>IPP_FORBIDDEN</CODE> - You don't have access to the resource </LI>
-<LI><CODE>IPP_NOT_AUTHENTICATED</CODE> - You are not authenticated for 
- the resource </LI>
-<LI><CODE>IPP_NOT_AUTHORIZED</CODE> - You not authorized to access  the 
-resource </LI>
-<LI><CODE>IPP_NOT_POSSIBLE</CODE> - The requested operation cannot be 
- completed </LI>
-<LI><CODE>IPP_TIMEOUT</CODE> - A timeout occurred </LI>
-<LI><CODE>IPP_NOT_FOUND</CODE> - The resource was not found </LI>
-<LI><CODE>IPP_GONE</CODE> - The resource has gone away </LI>
-<LI><CODE>IPP_REQUEST_ENTITY</CODE> - The request was too large </LI>
-<LI><CODE>IPP_REQUEST_VALUE</CODE> - The request contained a value 
that was unknown to the server </LI>
-<LI><CODE>IPP_DOCUMENT_FORMAT</CODE> - The document format is not 
- supported by the server </LI>
-<LI><CODE>IPP_ATTRIBUTES</CODE> - Required attributes are missing </LI>
-<LI><CODE>IPP_URI_SCHEME</CODE> - The URI scheme is not supported </LI>
-<LI><CODE>IPP_CHARSET</CODE> - The charset is not supported </LI>
-<LI><CODE>IPP_CONFLICT</CODE> - One or more attributes conflict </LI>
-<LI><CODE>IPP_COMPRESSION_NOT_SUPPORTED</CODE> - The specified 
- compression is not supported </LI>
-<LI><CODE>IPP_COMPRESSION_ERROR</CODE> - The compressed data  contained 
-an error </LI>
-<LI><CODE>IPP_DOCUMENT_FORMAT_ERROR</CODE> - The document data 
contained an error in it </LI>
-<LI><CODE>IPP_DOCUMENT_ACCESS_ERROR</CODE> - The remote document  could 
-not be accessed </LI>
-<LI><CODE>IPP_INTERNAL_ERROR</CODE> - The server encountered an 
internal error </LI>
-<LI><CODE>IPP_OPERATION_NOT_SUPPORTED</CODE> - The requested operation 
- is not supported </LI>
-<LI><CODE>IPP_SERVICE_UNAVAILABLE</CODE> - The requested service  is 
-unavailable </LI>
-<LI><CODE>IPP_VERSION_NOT_SUPPORTED</CODE> - The IPP request  version 
-is not supported </LI>
-<LI><CODE>IPP_DEVICE_ERROR</CODE> - The output device encountered  an 
-error </LI>
-<LI><CODE>IPP_TEMPORARY_ERROR</CODE> - A temporary error occurred </LI>
-<LI><CODE>IPP_NOT_ACCEPTING</CODE> - The destination is not accepting 
- jobs </LI>
-<LI><CODE>IPP_PRINTER_BUSY</CODE> - The destination is busy </LI>
-<LI><CODE>IPP_ERROR_JOB_CANCELLED</CODE> - The requested job has been 
- cancelled </LI>
-<LI><CODE>IPP_MULTIPLE_JOBS_NOT_SUPPORTED</CODE> - The server  does not 
-support multiple jobs </LI>
+<P>Status codes are returned by all IPP requests.</P>
+<UL>
+<LI><CODE>IPP_OK</CODE> - Request completed with no errors</LI>
+<LI><CODE>IPP_OK_SUBST</CODE> - Request completed but some attribute
+ values were substituted</LI>
+<LI><CODE>IPP_OK_CONFLICT</CODE> - Request completed but some attributes
+ conflicted</LI>
+<LI><CODE>IPP_BAD_REQUEST</CODE> - The request was bad</LI>
+<LI><CODE>IPP_FORBIDDEN</CODE> - You don't have access to the resource</LI>
+<LI><CODE>IPP_NOT_AUTHENTICATED</CODE> - You are not authenticated for
+ the resource</LI>
+<LI><CODE>IPP_NOT_AUTHORIZED</CODE> - You not authorized to access the
+ resource</LI>
+<LI><CODE>IPP_NOT_POSSIBLE</CODE> - The requested operation cannot be
+ completed</LI>
+<LI><CODE>IPP_TIMEOUT</CODE> - A timeout occurred</LI>
+<LI><CODE>IPP_NOT_FOUND</CODE> - The resource was not found</LI>
+<LI><CODE>IPP_GONE</CODE> - The resource has gone away</LI>
+<LI><CODE>IPP_REQUEST_ENTITY</CODE> - The request was too large</LI>
+<LI><CODE>IPP_REQUEST_VALUE</CODE> - The request contained a value that
was unknown to the server</LI>
+<LI><CODE>IPP_DOCUMENT_FORMAT</CODE> - The document format is not
+ supported by the server</LI>
+<LI><CODE>IPP_ATTRIBUTES</CODE> - Required attributes are missing</LI>
+<LI><CODE>IPP_URI_SCHEME</CODE> - The URI scheme is not supported</LI>
+<LI><CODE>IPP_CHARSET</CODE> - The charset is not supported</LI>
+<LI><CODE>IPP_CONFLICT</CODE> - One or more attributes conflict</LI>
+<LI><CODE>IPP_COMPRESSION_NOT_SUPPORTED</CODE> - The specified
+ compression is not supported</LI>
+<LI><CODE>IPP_COMPRESSION_ERROR</CODE> - The compressed data contained
+ an error</LI>
+<LI><CODE>IPP_DOCUMENT_FORMAT_ERROR</CODE> - The document data contained
an error in it</LI>
+<LI><CODE>IPP_DOCUMENT_ACCESS_ERROR</CODE> - The remote document could
+ not be accessed</LI>
+<LI><CODE>IPP_INTERNAL_ERROR</CODE> - The server encountered an internal
error</LI>
+<LI><CODE>IPP_OPERATION_NOT_SUPPORTED</CODE> - The requested operation
+ is not supported</LI>
+<LI><CODE>IPP_SERVICE_UNAVAILABLE</CODE> - The requested service is
+ unavailable</LI>
+<LI><CODE>IPP_VERSION_NOT_SUPPORTED</CODE> - The IPP request version is
+ not supported</LI>
+<LI><CODE>IPP_DEVICE_ERROR</CODE> - The output device encountered an
+ error</LI>
+<LI><CODE>IPP_TEMPORARY_ERROR</CODE> - A temporary error occurred</LI>
+<LI><CODE>IPP_NOT_ACCEPTING</CODE> - The destination is not accepting
+ jobs</LI>
+<LI><CODE>IPP_PRINTER_BUSY</CODE> - The destination is busy</LI>
+<LI><CODE>IPP_ERROR_JOB_CANCELLED</CODE> - The requested job has been
+ cancelled</LI>
+<LI><CODE>IPP_MULTIPLE_JOBS_NOT_SUPPORTED</CODE> - The server does not
+ support multiple jobs</LI>
 </UL>
 <H2><A NAME="8_4">PPD Constants</A></H2>
 <H3><A NAME="8_4_1">PPD Format Version</A></H3>
-<P>The <CODE>PPD_VERSION</CODE> constant defines a floating point 
-number representing the newest format version that is supported by 
-CUPS, currently 4.3. </P>
+<P>The <CODE>PPD_VERSION</CODE> constant defines a floating point number
+ representing the newest format version that is supported by CUPS,
+ currently 4.3.</P>
 <H3><A NAME="8_4_2">PPD User-Interface Types</A></H3>
-<P>Each printer option has a type associated with it: </P>
+<P>Each printer option has a type associated with it:</P>
 <UL>
-<LI><CODE>PPD_UI_BOOLEAN</CODE> - The user can turn this option on or 
-off </LI>
-<LI><CODE>PPD_UI_PICKONE</CODE> - The user can choose one option value 
- to use. </LI>
-<LI><CODE>PPD_UI_PICKMANY</CODE> - The user can choose zero or more 
- option values. </LI>
+<LI><CODE>PPD_UI_BOOLEAN</CODE> - The user can turn this option on or
+ off</LI>
+<LI><CODE>PPD_UI_PICKONE</CODE> - The user can choose one option value
+ to use.</LI>
+<LI><CODE>PPD_UI_PICKMANY</CODE> - The user can choose zero or more
+ option values.</LI>
 </UL>
 <H3><A NAME="8_4_3">PPD Sections</A></H3>
-<P>Some options must be output before others, or in different sections 
-of the output document. The <CODE>ppd_section_t</CODE> enumeration 
-defines which section the option must be output in: </P>
-<UL>
-<LI><CODE>PPD_ORDER_ANY</CODE> - The option can be output in any of 
the document, page, or prolog sections of the document </LI>
-<LI><CODE>PPD_ORDER_DOCUMENT</CODE> - The option must be output in  the 
-DocumentSetup section of the document </LI>
-<LI><CODE>PPD_ORDER_EXIT</CODE> - The option must be output before  the 
-document </LI>
-<LI><CODE>PPD_ORDER_JCL</CODE> - The option must be output in the  job 
-control section of the document </LI>
-<LI><CODE>PPD_ORDER_PAGE</CODE> - The option must be output in the 
- PageSetup section of the document </LI>
-<LI><CODE>PPD_ORDER_PROLOG</CODE> - The option must be output in the 
- Prolog section of the document </LI>
+<P>Some options must be output before others, or in different sections
+ of the output document. The <CODE>ppd_section_t</CODE> enumeration
+ defines which section the option must be output in:</P>
+<UL>
+<LI><CODE>PPD_ORDER_ANY</CODE> - The option can be output in any of the
document, page, or prolog sections of the document</LI>
+<LI><CODE>PPD_ORDER_DOCUMENT</CODE> - The option must be output in the
+ DocumentSetup section of the document</LI>
+<LI><CODE>PPD_ORDER_EXIT</CODE> - The option must be output before the
+ document</LI>
+<LI><CODE>PPD_ORDER_JCL</CODE> - The option must be output in the job
+ control section of the document</LI>
+<LI><CODE>PPD_ORDER_PAGE</CODE> - The option must be output in the
+ PageSetup section of the document</LI>
+<LI><CODE>PPD_ORDER_PROLOG</CODE> - The option must be output in the
+ Prolog section of the document</LI>
 </UL>
 <H3><A NAME="8_4_4">PPD Colorspaces</A></H3>
-<P>Each printer has a default colorspace: </P>
+<P>Each printer has a default colorspace:</P>
 <UL>
-<LI><CODE>PPD_CS_CMYK</CODE> - The printer uses CMYK colors by default </LI>
-<LI><CODE>PPD_CS_CMY</CODE> - The printer uses CMY colors by default </LI>
-<LI><CODE>PPD_CS_GRAY</CODE> - The printer uses grayscale by default </LI>
-<LI><CODE>PPD_CS_RGB</CODE> - The printer uses RGB colors by default </LI>
-<LI><CODE>PPD_CS_RGBK</CODE> - The printer uses RGBK colors by default </LI>
-<LI><CODE>PPD_CS_N</CODE> - The printer uses a DeviceN colorspace  by 
-default </LI>
+<LI><CODE>PPD_CS_CMYK</CODE> - The printer uses CMYK colors by default</LI>
+<LI><CODE>PPD_CS_CMY</CODE> - The printer uses CMY colors by default</LI>
+<LI><CODE>PPD_CS_GRAY</CODE> - The printer uses grayscale by default</LI>
+<LI><CODE>PPD_CS_RGB</CODE> - The printer uses RGB colors by default</LI>
+<LI><CODE>PPD_CS_RGBK</CODE> - The printer uses RGBK colors by default</LI>
+<LI><CODE>PPD_CS_N</CODE> - The printer uses a DeviceN colorspace by
+ default</LI>
 </UL>
 <H2><A NAME="8_5">Raster Constants</A></H2>
 <H3><A NAME="8_5_1">Raster Sync Words</A></H3>
 <P>The <CODE>CUPS_RASTER_SYNC</CODE> and <CODE>CUPS_RASTER_REVSYNC</CODE>
- constants define the standard sync words at the beginning of each CUPS 
-raster file. </P>
+ constants define the standard sync words at the beginning of each CUPS
+ raster file.</P>
 <H3><A NAME="8_5_2">Raster Stream Modes</A></H3>
 <P>The <CODE>CUPS_RASTER_READ</CODE> and <CODE>CUPS_RASTER_WRITE</CODE>
- constants are used with the <A HREF="#cupsRasterOpen"><CODE>
-cupsRasterOpen()</CODE></A> function to specify a stream for reading or 
-writing. </P>
+ constants are used with the<A HREF="#cupsRasterOpen"> <CODE>
+cupsRasterOpen()</CODE></A> function to specify a stream for reading or
+ writing.</P>
 <H3><A NAME="8_5_3">Raster Boolean Constants</A></H3>
-<P>The <CODE>CUPS_FALSE</CODE> and <CODE>CUPS_TRUE</CODE> constants 
-represent boolean values in the page header. </P>
+<P>The <CODE>CUPS_FALSE</CODE> and <CODE>CUPS_TRUE</CODE> constants
+ represent boolean values in the page header.</P>
 <H3><A NAME="8_5_4">Raster Jog Values</A></H3>
-<P>The <CODE>cups_jog_t</CODE> enumeration defines constants for the 
-Jog page device dictionary variable: </P>
+<P>The <CODE>cups_jog_t</CODE> enumeration defines constants for the Jog
+ page device dictionary variable:</P>
 <UL>
-<LI><CODE>CUPS_JOG_NONE</CODE> - Do no jogging </LI>
-<LI><CODE>CUPS_JOG_FILE</CODE> - Jog pages after each file </LI>
-<LI><CODE>CUPS_JOG_JOB</CODE> - Jog pages after each job </LI>
-<LI><CODE>CUPS_JOG_SET</CODE> - Jog pages after each set of jobs </LI>
+<LI><CODE>CUPS_JOG_NONE</CODE> - Do no jogging</LI>
+<LI><CODE>CUPS_JOG_FILE</CODE> - Jog pages after each file</LI>
+<LI><CODE>CUPS_JOG_JOB</CODE> - Jog pages after each job</LI>
+<LI><CODE>CUPS_JOG_SET</CODE> - Jog pages after each set of jobs</LI>
 </UL>
 <H3><A NAME="8_5_5">Raster Orientation Values</A></H3>
-<P>The <CODE>cups_orient_t</CODE> enumeration defines constants for the 
-Orientation page device dictionary variable: </P>
+<P>The <CODE>cups_orient_t</CODE> enumeration defines constants for the
+ Orientation page device dictionary variable:</P>
 <UL>
-<LI><CODE>CUPS_ORIENT_0</CODE> - Portrait orientation </LI>
-<LI><CODE>CUPS_ORIENT_90</CODE> - Landscape orientation </LI>
-<LI><CODE>CUPS_ORIENT_180</CODE> - Reverse-portrait orientation </LI>
-<LI><CODE>CUPS_ORIENT_270</CODE> - Reverse-landscape orientation </LI>
+<LI><CODE>CUPS_ORIENT_0</CODE> - Portrait orientation</LI>
+<LI><CODE>CUPS_ORIENT_90</CODE> - Landscape orientation</LI>
+<LI><CODE>CUPS_ORIENT_180</CODE> - Reverse-portrait orientation</LI>
+<LI><CODE>CUPS_ORIENT_270</CODE> - Reverse-landscape orientation</LI>
 </UL>
 <H3><A NAME="8_5_6">Raster CutMedia Values</A></H3>
-<P>The <CODE>cups_cut_t</CODE> enumeration defines constants for the 
-CutMedia page device dictionary variable: </P>
+<P>The <CODE>cups_cut_t</CODE> enumeration defines constants for the
+ CutMedia page device dictionary variable:</P>
 <UL>
-<LI><CODE>CUPS_CUT_NONE</CODE> - Do no jogging </LI>
-<LI><CODE>CUPS_CUT_FILE</CODE> - Cut pages after each file </LI>
-<LI><CODE>CUPS_CUT_JOB</CODE> - Cut pages after each job </LI>
-<LI><CODE>CUPS_CUT_SET</CODE> - Cut pages after each set of jobs </LI>
-<LI><CODE>CUPS_CUT_PAGE</CODE> - Cut each page </LI>
+<LI><CODE>CUPS_CUT_NONE</CODE> - Do no jogging</LI>
+<LI><CODE>CUPS_CUT_FILE</CODE> - Cut pages after each file</LI>
+<LI><CODE>CUPS_CUT_JOB</CODE> - Cut pages after each job</LI>
+<LI><CODE>CUPS_CUT_SET</CODE> - Cut pages after each set of jobs</LI>
+<LI><CODE>CUPS_CUT_PAGE</CODE> - Cut each page</LI>
 </UL>
 <H3><A NAME="8_5_7">Raster AdvanceMedia Values</A></H3>
-<P>The <CODE>cups_advance_t</CODE> enumeration defines constants for 
-the AdvanceMedia page device dictionary variable: </P>
+<P>The <CODE>cups_advance_t</CODE> enumeration defines constants for the
+ AdvanceMedia page device dictionary variable:</P>
 <UL>
-<LI><CODE>CUPS_ADVANCE_NONE</CODE> - Do no jogging </LI>
-<LI><CODE>CUPS_ADVANCE_FILE</CODE> - Advance media after each file </LI>
-<LI><CODE>CUPS_ADVANCE_JOB</CODE> - Advance media after each job </LI>
-<LI><CODE>CUPS_ADVANCE_SET</CODE> - Advance media after each set of 
-jobs </LI>
-<LI><CODE>CUPS_ADVANCE_PAGE</CODE> - Advance media for each page </LI>
+<LI><CODE>CUPS_ADVANCE_NONE</CODE> - Do no jogging</LI>
+<LI><CODE>CUPS_ADVANCE_FILE</CODE> - Advance media after each file</LI>
+<LI><CODE>CUPS_ADVANCE_JOB</CODE> - Advance media after each job</LI>
+<LI><CODE>CUPS_ADVANCE_SET</CODE> - Advance media after each set of jobs</LI>
+<LI><CODE>CUPS_ADVANCE_PAGE</CODE> - Advance media for each page</LI>
 </UL>
 <H3><A NAME="8_5_8">Raster LeadingEdge Values</A></H3>
-<P>The <CODE>cups_edge_t</CODE> enumeration defines constants for the 
-LeadingEdge page device dictionary variable: </P>
-<UL>
-<LI><CODE>CUPS_EDGE_TOP</CODE> - The top of the media is the leading 
- edge </LI>
-<LI><CODE>CUPS_EDGE_RIGHT</CODE> - The right of the media is the 
-leading  edge </LI>
-<LI><CODE>CUPS_EDGE_BOTTOM</CODE> - The bottom of the media is the 
- leading edge </LI>
-<LI><CODE>CUPS_EDGE_LEFT</CODE> - The left of the media is the leading 
- edge </LI>
+<P>The <CODE>cups_edge_t</CODE> enumeration defines constants for the
+ LeadingEdge page device dictionary variable:</P>
+<UL>
+<LI><CODE>CUPS_EDGE_TOP</CODE> - The top of the media is the leading
+ edge</LI>
+<LI><CODE>CUPS_EDGE_RIGHT</CODE> - The right of the media is the leading
+ edge</LI>
+<LI><CODE>CUPS_EDGE_BOTTOM</CODE> - The bottom of the media is the
+ leading edge</LI>
+<LI><CODE>CUPS_EDGE_LEFT</CODE> - The left of the media is the leading
+ edge</LI>
 </UL>
 <H3><A NAME="8_5_9">Raster Color Order Values</A></H3>
-<P>The <CODE>cups_order_t</CODE> enumeration defines the possible color 
-value orderings: </P>
+<P>The <CODE>cups_order_t</CODE> enumeration defines the possible color
+ value orderings:</P>
 <UL>
-<LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK </LI>
-<LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK </LI>
-<LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;... </LI>
+<LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK</LI>
+<LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK</LI>
+<LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;...</LI>
 </UL>
 <H3><A NAME="8_5_10">Raster Colorspace Values</A></H3>
-<P>The <CODE>cups_cspace_t</CODE> enumeration defines the possible 
-colorspaces: </P>
-<UL>
-<LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance) </LI>
-<LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue </LI>
-<LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha </LI>
-<LI><CODE>CUPS_CSPACE_K</CODE> - Black </LI>
-<LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow </LI>
-<LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan </LI>
-<LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black </LI>
-<LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black </LI>
-<LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow </LI>
-<LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow, 
- light cyan, light magenta </LI>
-<LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic 
-magenta,  metallic cyan, black </LI>
-<LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic 
-magenta,  metallic cyan, metallic grey (silver) </LI>
-<LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white 
-pigment) </LI>
-<LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil) </LI>
-<LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver 
-foil) </LI>
+<P>The <CODE>cups_cspace_t</CODE> enumeration defines the possible
+ colorspaces:</P>
+<UL>
+<LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance)</LI>
+<LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue</LI>
+<LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha</LI>
+<LI><CODE>CUPS_CSPACE_K</CODE> - Black</LI>
+<LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan</LI>
+<LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black</LI>
+<LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow,
+ light cyan, light magenta</LI>
+<LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, metallic grey (silver)</LI>
+<LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white
+ pigment)</LI>
+<LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil)</LI>
+<LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver foil)</LI>
 </UL>
 <H1 ALIGN="RIGHT"><A NAME="STRUCTURES">C - Structures</A></H1>
-<P>This appendix describes all of the structures that are defined by 
-the CUPS API. </P>
+<P>This appendix describes all of the structures that are defined by the
+ CUPS API.</P>
 <H2><A NAME="9_1">Raster Structures</A></H2>
 <H3><A NAME="9_1_1">Raster Page Header</A></H3>
-<P>The raster page header consists of the PostScript page device 
-dictionary for the page: 
+<P>The raster page header consists of the PostScript page device
+ dictionary for the page:
 <CENTER>
 <TABLE BORDER="1" WIDTH="90%">
 <TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
@@ -3730,85 +3711,84 @@ dictionary for the page:
 <TR><TD>MediaColor</TD><TD>char[64]</TD><TD>The media color name</TD></TR>
 <TR><TD>MediaType</TD><TD>char[64]</TD><TD>The media type name</TD></TR>
 <TR><TD>OutputType</TD><TD>char[64]</TD><TD>The output type name</TD></TR>
-<TR><TD>AdvanceDistance</TD><TD>unsigned</TD><TD>The distance to 
-advance the media in points</TD></TR>
-<TR><TD>AdvanceMedia</TD><TD>cups_adv_t</TD><TD>When to advance the 
-media</TD></TR>
-<TR><TD>Collate</TD><TD>cups_bool_t</TD><TD>Whether or not to produce 
-collated copies</TD></TR>
+<TR><TD>AdvanceDistance</TD><TD>unsigned</TD><TD>The distance to advance
+ the media in points</TD></TR>
+<TR><TD>AdvanceMedia</TD><TD>cups_adv_t</TD><TD>When to advance the
+ media</TD></TR>
+<TR><TD>Collate</TD><TD>cups_bool_t</TD><TD>Whether or not to produce
+ collated copies</TD></TR>
 <TR><TD>CutMedia</TD><TD>cups_cut_t</TD><TD>When to cut the media</TD></TR>
-<TR><TD>Duplex</TD><TD>cups_bool_t</TD><TD>Whether or not to print on 
-both sides of the paper</TD></TR>
-<TR><TD>HWResolution</TD><TD>unsigned[2]</TD><TD>The resolution of the 
-page image in pixels per inch; the  HWResolution[0] represents the 
-horizontal resolution and  HWResolution[1] represents the vertical 
-resolution</TD></TR>
-<TR><TD>ImagingBoundingBox</TD><TD>unsigned[4]</TD><TD>The bounding box 
-for the page in points; the elements  represent the left, bottom, 
-right, and top coordinates of the  imaged area (if 0 then the whole 
-page is imaged)</TD></TR>
-<TR><TD>InsertSheet</TD><TD>cups_bool_t</TD><TD>Whether or not to 
-insert a sheet before this page</TD></TR>
+<TR><TD>Duplex</TD><TD>cups_bool_t</TD><TD>Whether or not to print on
+ both sides of the paper</TD></TR>
+<TR><TD>HWResolution</TD><TD>unsigned[2]</TD><TD>The resolution of the
+ page image in pixels per inch; the HWResolution[0] represents the
+ horizontal resolution and HWResolution[1] represents the vertical
+ resolution</TD></TR>
+<TR><TD>ImagingBoundingBox</TD><TD>unsigned[4]</TD><TD>The bounding box
+ for the page in points; the elements represent the left, bottom, right,
+ and top coordinates of the imaged area (if 0 then the whole page is
+ imaged)</TD></TR>
+<TR><TD>InsertSheet</TD><TD>cups_bool_t</TD><TD>Whether or not to insert
+ a sheet before this page</TD></TR>
 <TR><TD>Jog</TD><TD>cups_jog_t</TD><TD>When to jog copies of the page</TD>
 </TR>
-<TR><TD>LeadingEdge</TD><TD>cups_edge_t</TD><TD>The leading edge of the 
-page</TD></TR>
-<TR><TD>Margins</TD><TD>unsigned[2]</TD><TD>The lower-lefthand margin 
-of the page in points</TD></TR>
-<TR><TD>ManualFeed</TD><TD>cups_bool_t</TD><TD>Whether or not to 
-manually feed the page</TD></TR>
-<TR><TD>MediaPosition</TD><TD>unsigned</TD><TD>The input slot number to 
-use</TD></TR>
-<TR><TD>MediaWeight</TD><TD>unsigned</TD><TD>The weight of the output 
-media in grams/m<SUP>2</SUP></TD></TR>
-<TR><TD>MirrorPrint</TD><TD>cups_bool_t</TD><TD>Whether or not to 
-mirror the print</TD></TR>
-<TR><TD>NegativePrint</TD><TD>cups_bool_t</TD><TD>Whether or not to 
-invert the print</TD></TR>
-<TR><TD>NumCopies</TD><TD>unsigned</TD><TD>The number of copies to 
-produce</TD></TR>
-<TR><TD>Orientation</TD><TD>cups_orient_t</TD><TD>The orientation of 
-the page image</TD></TR>
-<TR><TD>OutputFaceUp</TD><TD>cups_bool_t</TD><TD>Whether or not to 
-output the page face up</TD></TR>
-<TR><TD>PageSize</TD><TD>unsigned[2]</TD><TD>The width and height of 
-the page in points</TD></TR>
-<TR><TD>Separations</TD><TD>cups_bool_t</TD><TD>Whether or not to 
-output separations</TD></TR>
-<TR><TD>TraySwitch</TD><TD>cups_bool_t</TD><TD>Whether or not to 
-automatically switch trays for the requested  media size/type</TD></TR>
-<TR><TD>Tumble</TD><TD>cups_bool_t</TD><TD>Whether or not to rotate the 
-back side of the page</TD></TR>
-<TR><TD>cupsWidth</TD><TD>unsigned</TD><TD>The width of the page image 
-in pixels</TD></TR>
-<TR><TD>cupsHeight</TD><TD>unsigned</TD><TD>The height of the page 
-image in pixels</TD></TR>
-<TR><TD>cupsMediaType</TD><TD>unsigned</TD><TD>The device-specific 
-media type code</TD></TR>
-<TR><TD>cupsBitsPerColor</TD><TD>unsigned</TD><TD>The number of bits 
-per color</TD></TR>
-<TR><TD>cupsBitsPerPixel</TD><TD>unsigned</TD><TD>The number of bits 
-per pixel</TD></TR>
-<TR><TD>cupsBytesPerLine</TD><TD>unsigned</TD><TD>The number of bytes 
-per line of image data</TD></TR>
-<TR><TD>cupsColorOrder</TD><TD>cups_order_t</TD><TD>The order of color 
-values</TD></TR>
-<TR><TD>cupsColorSpace</TD><TD>cups_cspace_t</TD><TD>The type of color 
-values</TD></TR>
-<TR><TD>cupsCompression</TD><TD>unsigned</TD><TD>The device-specific 
-compression code</TD></TR>
-<TR><TD>cupsRowCount</TD><TD>unsigned</TD><TD>The device-specific row 
-count</TD></TR>
-<TR><TD>cupsRowFeed</TD><TD>unsigned</TD><TD>The device-specific row 
-feed</TD></TR>
-<TR><TD>cupsRowStep</TD><TD>unsigned</TD><TD>The device-specific row 
-step</TD></TR>
+<TR><TD>LeadingEdge</TD><TD>cups_edge_t</TD><TD>The leading edge of the
+ page</TD></TR>
+<TR><TD>Margins</TD><TD>unsigned[2]</TD><TD>The lower-lefthand margin of
+ the page in points</TD></TR>
+<TR><TD>ManualFeed</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ manually feed the page</TD></TR>
+<TR><TD>MediaPosition</TD><TD>unsigned</TD><TD>The input slot number to
+ use</TD></TR>
+<TR><TD>MediaWeight</TD><TD>unsigned</TD><TD>The weight of the output
+ media in grams/m<SUP>2</SUP></TD></TR>
+<TR><TD>MirrorPrint</TD><TD>cups_bool_t</TD><TD>Whether or not to mirror
+ the print</TD></TR>
+<TR><TD>NegativePrint</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ invert the print</TD></TR>
+<TR><TD>NumCopies</TD><TD>unsigned</TD><TD>The number of copies to
+ produce</TD></TR>
+<TR><TD>Orientation</TD><TD>cups_orient_t</TD><TD>The orientation of the
+ page image</TD></TR>
+<TR><TD>OutputFaceUp</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ output the page face up</TD></TR>
+<TR><TD>PageSize</TD><TD>unsigned[2]</TD><TD>The width and height of the
+ page in points</TD></TR>
+<TR><TD>Separations</TD><TD>cups_bool_t</TD><TD>Whether or not to output
+ separations</TD></TR>
+<TR><TD>TraySwitch</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ automatically switch trays for the requested media size/type</TD></TR>
+<TR><TD>Tumble</TD><TD>cups_bool_t</TD><TD>Whether or not to rotate the
+ back side of the page</TD></TR>
+<TR><TD>cupsWidth</TD><TD>unsigned</TD><TD>The width of the page image
+ in pixels</TD></TR>
+<TR><TD>cupsHeight</TD><TD>unsigned</TD><TD>The height of the page image
+ in pixels</TD></TR>
+<TR><TD>cupsMediaType</TD><TD>unsigned</TD><TD>The device-specific media
+ type code</TD></TR>
+<TR><TD>cupsBitsPerColor</TD><TD>unsigned</TD><TD>The number of bits per
+ color</TD></TR>
+<TR><TD>cupsBitsPerPixel</TD><TD>unsigned</TD><TD>The number of bits per
+ pixel</TD></TR>
+<TR><TD>cupsBytesPerLine</TD><TD>unsigned</TD><TD>The number of bytes
+ per line of image data</TD></TR>
+<TR><TD>cupsColorOrder</TD><TD>cups_order_t</TD><TD>The order of color
+ values</TD></TR>
+<TR><TD>cupsColorSpace</TD><TD>cups_cspace_t</TD><TD>The type of color
+ values</TD></TR>
+<TR><TD>cupsCompression</TD><TD>unsigned</TD><TD>The device-specific
+ compression code</TD></TR>
+<TR><TD>cupsRowCount</TD><TD>unsigned</TD><TD>The device-specific row
+ count</TD></TR>
+<TR><TD>cupsRowFeed</TD><TD>unsigned</TD><TD>The device-specific row
+ feed</TD></TR>
+<TR><TD>cupsRowStep</TD><TD>unsigned</TD><TD>The device-specific row
+ step</TD></TR>
 </TABLE>
 </CENTER>
 </P>
-<H1 ALIGN="RIGHT"><A NAME="10"><A HREF="FUNCTIONS">D - Functions</A></A></H1>
-<P>This appendix provides a reference for all of the CUPS API 
-functions. 
+<H1 ALIGN="RIGHT"><A HREF="FUNCTIONS" NAME="10">D - Functions</A></H1>
+<P>This appendix provides a reference for all of the CUPS API functions.
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsAddOption">cupsAddOption()</A></H2>
@@ -3832,9 +3812,9 @@ cupsAddOption(const char *name,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_1_3">Returns</A></H3>
-<P>The new number of options. </P>
+<P>The new number of options.</P>
 <H3><A NAME="10_1_4">Description</A></H3>
-<P><CODE>cupsAddOption()</CODE> adds an option to the specified array. </P>
+<P><CODE>cupsAddOption()</CODE> adds an option to the specified array.</P>
 <H3><A NAME="10_1_5">Example</A></H3>
 <PRE>
 #include &lt;cups.h&gt;
@@ -3854,8 +3834,8 @@ num_options = cupsAddOption(&quot;media&quot;, &quot;letter&quot;, num_options,
 num_options = cupsAddOption(&quot;resolution&quot;, &quot;300dpi&quot;, num_options, &amp;options);
 </PRE>
 <H3><A NAME="10_1_6">See Also</A></H3>
-<A HREF="#cupsFreeOptions"><CODE> cupsFreeOptions()</CODE></A>, <A HREF="#cupsGetOption">
-<CODE>cupsGetOption()</CODE></A>, <A HREF="#cupsParseOptions"><CODE>
+<A HREF="#cupsFreeOptions"> <CODE>cupsFreeOptions()</CODE></A>,<A HREF="#cupsGetOption">
+ <CODE>cupsGetOption()</CODE></A>,<A HREF="#cupsParseOptions"> <CODE>
 cupsParseOptions()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -3875,10 +3855,10 @@ cupsCancelJob(const char *dest,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_2_3">Returns</A></H3>
-<P>1 on success, 0 on failure. On failure the error can be found by 
-calling <A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>. </P>
+<P>1 on success, 0 on failure. On failure the error can be found by
+ calling<A HREF="#cupsLastError"> <CODE>cupsLastError()</CODE></A>.</P>
 <H3><A NAME="10_2_4">Description</A></H3>
-<P><CODE>cupsCancelJob()</CODE> cancels the specifies job. </P>
+<P><CODE>cupsCancelJob()</CODE> cancels the specifies job.</P>
 <H3><A NAME="10_2_5">Example</A></H3>
 <PRE>
 #include &lt;cups.h&gt;
@@ -3886,8 +3866,8 @@ calling <A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>. </P>
 cupsCancelJob(&quot;LaserJet&quot;, 1);
 </PRE>
 <H3><A NAME="10_2_6">See Also</A></H3>
-<P><A HREF="#cupsLastError"><CODE> cupsLastError()</CODE></A>, <A HREF="#cupsPrintFile">
-<CODE>cupsPrintFile()</CODE></A>
+<P><A HREF="#cupsLastError"> <CODE>cupsLastError()</CODE></A>,<A HREF="#cupsPrintFile">
+ <CODE>cupsPrintFile()</CODE></A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsDoFileRequest">cupsDoFileRequest()</A></H2>
@@ -3911,14 +3891,14 @@ cupsDoFileRequest(http_t *http,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_3_3">Returns</A></H3>
-<P>IPP response data or <CODE>NULL</CODE> if the request fails. On 
-failure the error can be found by calling <A HREF="#cupsLastError"><CODE>
-cupsLastError()</CODE></A>. </P>
+<P>IPP response data or <CODE>NULL</CODE> if the request fails. On
+ failure the error can be found by calling<A HREF="#cupsLastError"> <CODE>
+cupsLastError()</CODE></A>.</P>
 <H3><A NAME="10_3_4">Description</A></H3>
-<P><CODE>cupsDoFileRequest()</CODE> does a HTTP POST request and 
-provides the IPP request and optionally the contents of a file to the 
-IPP server. It also handles resubmitting the request and performing 
-password authentication as needed. </P>
+<P><CODE>cupsDoFileRequest()</CODE> does a HTTP POST request and
+ provides the IPP request and optionally the contents of a file to the
+ IPP server. It also handles resubmitting the request and performing
+ password authentication as needed.</P>
 <H3><A NAME="10_3_5">Example</A></H3>
 <PRE>
 #include &lt;cups.h&gt;
@@ -3957,11 +3937,11 @@ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, &quot;requesting-user-nam
 response = cupsDoFileRequest(http, request, &quot;/resource&quot;, &quot;filename.txt&quot;);
 </PRE>
 <H3><A NAME="10_3_6">See Also</A></H3>
-<P><A HREF="#cupsLangDefault"><CODE> cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
-<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsUser"><CODE>
-cupsUser()</CODE></A>, <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
-, <A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>, <A HREF="#ippNew">
-<CODE>ippNew()</CODE></A>
+<P><A HREF="#cupsLangDefault"> <CODE>cupsLangDefault()</CODE></A>,<A HREF="#cupsLangEncoding">
+ <CODE>cupsLangEncoding()</CODE></A>,<A HREF="#cupsUser"> <CODE>
+cupsUser()</CODE></A>,<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
+,<A HREF="#ippAddString"> <CODE>ippAddString()</CODE></A>,<A HREF="#ippNew">
+ <CODE>ippNew()</CODE></A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsDoRequest">cupsDoRequest()</A></H2>
@@ -3982,13 +3962,13 @@ cupsDoRequest(http_t *http,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_4_3">Returns</A></H3>
-<P>IPP response data or <CODE>NULL</CODE> if the request fails. On 
-failure the error can be found by calling <A HREF="#cupsLastError"><CODE>
-cupsLastError()</CODE></A>. </P>
+<P>IPP response data or <CODE>NULL</CODE> if the request fails. On
+ failure the error can be found by calling<A HREF="#cupsLastError"> <CODE>
+cupsLastError()</CODE></A>.</P>
 <H3><A NAME="10_4_4">Description</A></H3>
-<P><CODE>cupsDoRequest()</CODE> does a HTTP POST request and provides 
-the IPP request to the IPP server. It also handles resubmitting the 
-request and performing password authentication as needed. </P>
+<P><CODE>cupsDoRequest()</CODE> does a HTTP POST request and provides
+ the IPP request to the IPP server. It also handles resubmitting the
+ request and performing password authentication as needed.</P>
 <H3><A NAME="10_4_5">Example</A></H3>
 <PRE>
 #include &lt;cups.h&gt;
@@ -4024,11 +4004,11 @@ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, &quot;printer-uri&quot;,
 response = cupsDoRequest(http, request, &quot;/resource&quot;);
 </PRE>
 <H3><A NAME="10_4_6">See Also</A></H3>
-<P><A HREF="#cupsLangDefault"><CODE> cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
-<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsUser"><CODE>
-cupsUser()</CODE></A>, <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
-, <A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>, <A HREF="#ippNew">
-<CODE>ippNew()</CODE></A>
+<P><A HREF="#cupsLangDefault"> <CODE>cupsLangDefault()</CODE></A>,<A HREF="#cupsLangEncoding">
+ <CODE>cupsLangEncoding()</CODE></A>,<A HREF="#cupsUser"> <CODE>
+cupsUser()</CODE></A>,<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
+,<A HREF="#ippAddString"> <CODE>ippAddString()</CODE></A>,<A HREF="#ippNew">
+ <CODE>ippNew()</CODE></A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsFreeOptions">cupsFreeOptions()</A></H2>
@@ -4048,8 +4028,8 @@ cupsFreeOptions(int num_options,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_5_3">Description</A></H3>
-<P><CODE>cupsFreeOptions()</CODE> frees all memory associated with the 
-option array specified. </P>
+<P><CODE>cupsFreeOptions()</CODE> frees all memory associated with the
+ option array specified.</P>
 <H3><A NAME="10_5_4">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4062,9 +4042,9 @@ cups_option_t *options;
 cupsFreeOptions(num_options, options);
 </PRE>
 <H3><A NAME="10_5_5">See Also</A></H3>
-<P><A HREF="#cupsAddOption"> cupsAddOption()</A>, <A HREF="#cupsGetOption">
-cupsGetOption()</A>, <A HREF="#cupsMarkOptions">cupsMarkOptions()</A>, <A
-HREF="#cupsParseOptions">cupsParseOptions()</A>
+<P><A HREF="#cupsAddOption"> cupsAddOption()</A>,<A HREF="#cupsGetOption">
+ cupsGetOption()</A>,<A HREF="#cupsMarkOptions"> cupsMarkOptions()</A>,<A
+HREF="#cupsParseOptions"> cupsParseOptions()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsGetClasses">cupsGetClasses()</A></H2>
@@ -4081,11 +4061,11 @@ cupsGetClasses(char ***classes);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_6_3">Returns</A></H3>
-<P>The number of printer classes available. </P>
+<P>The number of printer classes available.</P>
 <H3><A NAME="10_6_4">Description</A></H3>
-<P><CODE>cupsGetClasses()</CODE> gets a list of the available printer 
-classes. The returned array should be freed using the <CODE>free()</CODE>
- when it is no longer needed. </P>
+<P><CODE>cupsGetClasses()</CODE> gets a list of the available printer
+ classes. The returned array should be freed using the <CODE>free()</CODE>
+ when it is no longer needed.</P>
 <H3><A NAME="10_6_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4102,15 +4082,15 @@ num_classes = cupsGetClasses(
 
 if (num_classes &gt; 0)
 {
-  for (i = 0; i num_classes; i ++)
+  for (i = 0; i &lt;num_classes; i ++)
     free(classes[i]);
 
   free(classes);
 }
 </PRE>
 <H3><A NAME="10_6_6">See Also</A></H3>
-<P><A HREF="#cupsGetDefault"> cupsGetDefault(), <A HREF="#cupsGetPrinters">
-cupsGetPrinters()
+<P><A HREF="#cupsGetDefault"> cupsGetDefault(),<A HREF="#cupsGetPrinters">
+ cupsGetPrinters()
 <!-- NEW PAGE -->
 </A></A></P>
 <H2><A NAME="cupsGetDefault">cupsGetDefault()</A></H2>
@@ -4120,11 +4100,11 @@ const char *
 cupsGetDefault(void);
 </PRE>
 <H3><A NAME="10_7_2">Returns</A></H3>
-<P>A pointer to the default destination. </P>
+<P>A pointer to the default destination.</P>
 <H3><A NAME="10_7_3">Description</A></H3>
-<P><CODE>cupsGetDefault()</CODE> gets the default destination printer 
-or class. The default destination is stored in a static string and will 
-be overwritten (usually with the same value) after each call. </P>
+<P><CODE>cupsGetDefault()</CODE> gets the default destination printer or
+ class. The default destination is stored in a static string and will be
+ overwritten (usually with the same value) after each call.</P>
 <H3><A NAME="10_7_4">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4132,8 +4112,8 @@ be overwritten (usually with the same value) after each call. </P>
 printf(&quot;The default destination is %s\n&quot;, cupsGetDefault());
 </PRE>
 <H3><A NAME="10_7_5">See Also</A></H3>
-<P><A HREF="#cupsGetClasses"> cupsGetClasses(), <A HREF="#cupsGetPrinters">
-cupsGetPrinters()
+<P><A HREF="#cupsGetClasses"> cupsGetClasses(),<A HREF="#cupsGetPrinters">
+ cupsGetPrinters()
 <!-- NEW PAGE -->
 </A></A></P>
 <H2><A NAME="cupsGetOption">cupsGetOption()</A></H2>
@@ -4154,12 +4134,12 @@ cupsGetOption(const char *name,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_8_3">Returns</A></H3>
-<P>A pointer to the option values or <CODE>NULL</CODE> if the option is 
-not defined. </P>
+<P>A pointer to the option values or <CODE>NULL</CODE> if the option is
+ not defined.</P>
 <H3><A NAME="10_8_4">Description</A></H3>
-<P><CODE>cupsGetOption()</CODE> returns the first occurrence of the 
-named option. If the option is not included in the options array then a <CODE>
-NULL</CODE> pointer is returned. </P>
+<P><CODE>cupsGetOption()</CODE> returns the first occurrence of the
+ named option. If the option is not included in the options array then a
+ <CODE>NULL</CODE> pointer is returned.</P>
 <PRE>
 #include &lt;cups/cups.h&gt;
 
@@ -4172,9 +4152,9 @@ const char    *media;
 media = cupsGetOption(&quot;media&quot;, num_options, options);
 </PRE>
 <H3><A NAME="10_8_5">See Also</A></H3>
-<P><A HREF="#cupsAddOption"> cupsAddOption()</A>, <A HREF="#cupsFreeOptions">
-cupsFreeOptions()</A>, <A HREF="#cupsMarkOptions">cupsMarkOptions()</A>
-, <A HREF="#cupsParseOptions">cupsParseOptions()</A>
+<P><A HREF="#cupsAddOption"> cupsAddOption()</A>,<A HREF="#cupsFreeOptions">
+ cupsFreeOptions()</A>,<A HREF="#cupsMarkOptions"> cupsMarkOptions()</A>
+,<A HREF="#cupsParseOptions"> cupsParseOptions()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsGetPassword">cupsGetPassword()</A></H2>
@@ -4191,11 +4171,11 @@ cupsGetPassword(const char *prompt);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_9_3">Returns</A></H3>
-<P>A pointer to the password that was entered or <CODE>NULL</CODE> if 
-no password was entered. </P>
+<P>A pointer to the password that was entered or <CODE>NULL</CODE> if no
+ password was entered.</P>
 <H3><A NAME="10_9_4">Description</A></H3>
-<P><CODE>cupsGetPassword()</CODE> displays the prompt string and asks 
-the user for a password. The password text is not echoed to the user. </P>
+<P><CODE>cupsGetPassword()</CODE> displays the prompt string and asks
+ the user for a password. The password text is not echoed to the user.</P>
 <H3><A NAME="10_9_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4207,9 +4187,9 @@ char *password;
 password = cupsGetPassword(&quot;Please enter a password:&quot;);
 </PRE>
 <H3><A NAME="10_9_6">See Also</A></H3>
-<P><A HREF="#cupsServer"> cupsServer()</A>, <A HREF="#cupsSetPasswordCB">
-cupsSetPasswordCB()</A>, <A HREF="#cupsSetServer">cupsSetServer()</A>, <A
-HREF="#cupsSetUser">cupsSetUser()</A>, <A HREF="#cupsUser()">cupsUser()</A>
+<P><A HREF="#cupsServer"> cupsServer()</A>,<A HREF="#cupsSetPasswordCB">
+ cupsSetPasswordCB()</A>,<A HREF="#cupsSetServer"> cupsSetServer()</A>,<A
+HREF="#cupsSetUser"> cupsSetUser()</A>,<A HREF="#cupsUser()"> cupsUser()</A>
 <!-- NEW PAGE -->
 
 </P>
@@ -4228,14 +4208,14 @@ cupsGetPPD(const char *printer);
 </CENTER>
 <H3><A NAME="10_10_3">Returns</A></H3>
 <P>The name of a temporary file containing the PPD file or <CODE>NULL</CODE>
- if the printer cannot be located or does not have a PPD file. </P>
+ if the printer cannot be located or does not have a PPD file.</P>
 <H3><A NAME="10_10_4">Description</A></H3>
-<P><CODE>cupsGetPPD()</CODE> gets a copy of the PPD file for the named 
-printer. The printer name can be of the form &quot;printer&quot; or 
-&quot;printer@hostname&quot;. </P>
-<P>You should remove (unlink) the PPD file after you are done using it. 
-The filename is stored in a static buffer and will be overwritten with 
-each call to <CODE>cupsGetPPD()</CODE>. </P>
+<P><CODE>cupsGetPPD()</CODE> gets a copy of the PPD file for the named
+ printer. The printer name can be of the form &quot;printer&quot; or
+ &quot;printer@hostname&quot;.</P>
+<P>You should remove (unlink) the PPD file after you are done using it.
+ The filename is stored in a static buffer and will be overwritten with
+ each call to <CODE>cupsGetPPD()</CODE>.</P>
 <H3><A NAME="10_10_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4252,7 +4232,6 @@ unlink(ppd);
 </PRE>
 
 <!-- NEW PAGE -->
-
 <H2><A NAME="cupsGetPrinters">cupsGetPrinters()</A></H2>
 <H3><A NAME="10_11_1">Usage</A></H3>
 <PRE>
@@ -4267,11 +4246,11 @@ cupsGetPrinters(char ***printers);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_11_3">Returns</A></H3>
-<P>The number of printer printers available. </P>
+<P>The number of printer printers available.</P>
 <H3><A NAME="10_11_4">Description</A></H3>
-<P><CODE>cupsGetPrinters()</CODE> gets a list of the available 
-printers. The returned array should be freed using the <CODE>free()</CODE>
when it is no longer needed. </P>
+<P><CODE>cupsGetPrinters()</CODE> gets a list of the available printers.
+ The returned array should be freed using the <CODE>free()</CODE> when
it is no longer needed.</P>
 <H3><A NAME="10_11_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4288,15 +4267,15 @@ num_printers = cupsGetPrinters(
 
 if (num_printers &gt; 0)
 {
-  for (i = 0; i num_printers; i ++)
+  for (i = 0; i &lt;num_printers; i ++)
     free(printers[i]);
 
   free(printers);
 }
 </PRE>
 <H3><A NAME="10_11_6">See Also</A></H3>
-<P><A HREF="#cupsGetClasses"> cupsGetClasses(), <A HREF="#cupsGetDefault">
-cupsGetDefault()
+<P><A HREF="#cupsGetClasses"> cupsGetClasses(),<A HREF="#cupsGetDefault">
+ cupsGetDefault()
 <!-- NEW PAGE -->
 </A></A></P>
 <H2><A NAME="cupsLangDefault">cupsLangDefault()</A></H2>
@@ -4306,14 +4285,14 @@ const char *
 cupsLangDefault(void);
 </PRE>
 <H3><A NAME="10_12_2">Returns</A></H3>
-<P>A pointer to the default language structure. </P>
+<P>A pointer to the default language structure.</P>
 <H3><A NAME="10_12_3">Description</A></H3>
-<P><CODE>cupsLangDefault()</CODE> returns a language structure for the 
-default language. The default language is defined by the <CODE>LANG</CODE>
- environment variable. If the specified language cannot be located then 
-the POSIX (English) locale is used. </P>
-<P>Call <CODE>cupsLangFree()</CODE> to free any memory associated with 
-the language structure when you are done. </P>
+<P><CODE>cupsLangDefault()</CODE> returns a language structure for the
+ default language. The default language is defined by the <CODE>LANG</CODE>
+ environment variable. If the specified language cannot be located then
+ the POSIX (English) locale is used.</P>
+<P>Call <CODE>cupsLangFree()</CODE> to free any memory associated with
+ the language structure when you are done.</P>
 <H3><A NAME="10_12_4">Example</A></H3>
 <PRE>
 #include &lt;cups/language.h&gt;
@@ -4328,9 +4307,9 @@ language = cupsLangDefault();
 cupsLangFree(language);
 </PRE>
 <H3><A NAME="10_12_5">See Also</A></H3>
-<P><A HREF="#cupsLangEncoding"> cupsLangEncoding()</A>, <A HREF="#cupsLangFlush">
-cupsLangFlush()</A>, <A HREF="#cupsLangFree">cupsLangFree()</A>, <A HREF="#cupsLangGet">
-cupsLangGet()</A>, <A HREF="#cupsLangString">cupsLangString()</A>
+<P><A HREF="#cupsLangEncoding"> cupsLangEncoding()</A>,<A HREF="#cupsLangFlush">
+ cupsLangFlush()</A>,<A HREF="#cupsLangFree"> cupsLangFree()</A>,<A HREF="#cupsLangGet">
+ cupsLangGet()</A>,<A HREF="#cupsLangString"> cupsLangString()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsLangEncoding">cupsLangEncoding()</A></H2>
@@ -4347,10 +4326,10 @@ cupsLangEncoding(cups_lang_t *language);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_13_3">Returns</A></H3>
-<P>A pointer to the encoding string. </P>
+<P>A pointer to the encoding string.</P>
 <H3><A NAME="10_13_4">Description</A></H3>
-<P><CODE>cupsLangEncoding()</CODE> returns the language encoding used 
-for the specified language, e.g. &quot;iso-8859-1&quot;, &quot;utf-8&quot;, etc. </P>
+<P><CODE>cupsLangEncoding()</CODE> returns the language encoding used
+ for the specified language, e.g. &quot;iso-8859-1&quot;, &quot;utf-8&quot;, etc.</P>
 <H3><A NAME="10_13_5">Example</A></H3>
 <PRE>
 #include &lt;cups/language.h&gt;
@@ -4366,9 +4345,9 @@ encoding = cupsLangEncoding(language);
 cupsLangFree(language);
 </PRE>
 <H3><A NAME="10_13_6">See Also</A></H3>
-<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>, <A HREF="#cupsLangFlush">
-cupsLangFlush()</A>, <A HREF="#cupsLangFree">cupsLangFree()</A>, <A HREF="#cupsLangGet">
-cupsLangGet()</A>, <A HREF="#cupsLangString">cupsLangString()</A>
+<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>,<A HREF="#cupsLangFlush">
+ cupsLangFlush()</A>,<A HREF="#cupsLangFree"> cupsLangFree()</A>,<A HREF="#cupsLangGet">
+ cupsLangGet()</A>,<A HREF="#cupsLangString"> cupsLangString()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsLangFlush">cupsLangFlush()</A></H2>
@@ -4378,8 +4357,8 @@ void
 cupsLangFlush(void);
 </PRE>
 <H3><A NAME="10_14_2">Description</A></H3>
-<P><CODE>cupsLangFlush()</CODE> frees all language structures that have 
-been allocated. </P>
+<P><CODE>cupsLangFlush()</CODE> frees all language structures that have
+ been allocated.</P>
 <H3><A NAME="10_14_3">Example</A></H3>
 <PRE>
 #include &lt;cups/language.h&gt;
@@ -4389,9 +4368,9 @@ been allocated. </P>
 cupsLangFlush();
 </PRE>
 <H3><A NAME="10_14_4">See Also</A></H3>
-<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>, <A HREF="#cupsLangEncoding">
-cupsLangEncoding()</A>, <A HREF="#cupsLangFree">cupsLangFree()</A>, <A HREF="#cupsLangGet">
-cupsLangGet()</A>, <A HREF="#cupsLangString">cupsLangString()</A>
+<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>,<A HREF="#cupsLangEncoding">
+ cupsLangEncoding()</A>,<A HREF="#cupsLangFree"> cupsLangFree()</A>,<A HREF="#cupsLangGet">
+ cupsLangGet()</A>,<A HREF="#cupsLangString"> cupsLangString()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsLangFree">cupsLangFree()</A></H2>
@@ -4408,7 +4387,7 @@ cupsLangFree(cups_lang_t *language);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_15_3">Description</A></H3>
-<P><CODE>cupsLangFree()</CODE> frees the specified language structure. </P>
+<P><CODE>cupsLangFree()</CODE> frees the specified language structure.</P>
 <H3><A NAME="10_15_4">Example</A></H3>
 <PRE>
 #include &lt;cups/language.h&gt;
@@ -4419,9 +4398,9 @@ cups_lang_t *language;
 cupsLangFree(language);
 </PRE>
 <H3><A NAME="10_15_5">See Also</A></H3>
-<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>, <A HREF="#cupsLangEncoding">
-cupsLangEncoding()</A>, <A HREF="#cupsLangFlush">cupsLangFlush()</A>, <A HREF="#cupsLangGet">
-cupsLangGet()</A>, <A HREF="#cupsLangString">cupsLangString()</A>
+<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>,<A HREF="#cupsLangEncoding">
+ cupsLangEncoding()</A>,<A HREF="#cupsLangFlush"> cupsLangFlush()</A>,<A HREF="#cupsLangGet">
+ cupsLangGet()</A>,<A HREF="#cupsLangString"> cupsLangString()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsLangGet">cupsLangGet()</A></H2>
@@ -4438,11 +4417,11 @@ cupsLangGet(const char *name);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_16_3">Returns</A></H3>
-<P>A pointer to a language structure. </P>
+<P>A pointer to a language structure.</P>
 <H3><A NAME="10_16_4">Description</A></H3>
-<P><CODE>cupsLangGet()</CODE> returns a language structure for the 
-specified locale. If the locale is not defined then the POSIX (English) 
-locale is substituted. </P>
+<P><CODE>cupsLangGet()</CODE> returns a language structure for the
+ specified locale. If the locale is not defined then the POSIX (English)
+ locale is substituted.</P>
 <H3><A NAME="10_16_5">Example</A></H3>
 <PRE>
 #include &lt;cups/language.h&gt;
@@ -4458,9 +4437,9 @@ language = cupsLangGet(&quot;fr&quot;);
 cupsLangFree(language);
 </PRE>
 <H3><A NAME="10_16_6">See Also</A></H3>
-<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>, <A HREF="#cupsLangEncoding">
-cupsLangEncoding()</A>, <A HREF="#cupsLangFlush">cupsLangFlush()</A>, <A HREF="#cupsLangFree">
-cupsLangFree()</A>, <A HREF="#cupsLangString">cupsLangString()</A>
+<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>,<A HREF="#cupsLangEncoding">
+ cupsLangEncoding()</A>,<A HREF="#cupsLangFlush"> cupsLangFlush()</A>,<A HREF="#cupsLangFree">
+ cupsLangFree()</A>,<A HREF="#cupsLangString"> cupsLangString()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsLangString">cupsLangString()</A></H2>
@@ -4479,11 +4458,11 @@ cupsLangString(cups_lang_t *language,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_17_3">Returns</A></H3>
-<P>A pointer to the message string or <CODE>NULL</CODE> if the message 
-is not defined. </P>
+<P>A pointer to the message string or <CODE>NULL</CODE> if the message
+ is not defined.</P>
 <H3><A NAME="10_17_4">Description</A></H3>
-<P><CODE>cupsLangString()</CODE> returns a pointer to the specified 
-message string in the specified language. </P>
+<P><CODE>cupsLangString()</CODE> returns a pointer to the specified
+ message string in the specified language.</P>
 <H3><A NAME="10_17_5">Example</A></H3>
 <PRE>
 #include &lt;cups/language.h&gt;
@@ -4501,9 +4480,9 @@ s = cupsLangString(language, CUPS_MSG_YES);
 cupsLangFree(language);
 </PRE>
 <H3><A NAME="10_17_6">See Also</A></H3>
-<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>, <A HREF="#cupsLangEncoding">
-cupsLangEncoding()</A>, <A HREF="#cupsLangFlush">cupsLangFlush()</A>, <A HREF="#cupsLangFree">
-cupsLangFree()</A>, <A HREF="#cupsLangGet">cupsLangGet()</A>
+<P><A HREF="#cupsLangDefault"> cupsLangDefault()</A>,<A HREF="#cupsLangEncoding">
+ cupsLangEncoding()</A>,<A HREF="#cupsLangFlush"> cupsLangFlush()</A>,<A HREF="#cupsLangFree">
+ cupsLangFree()</A>,<A HREF="#cupsLangGet"> cupsLangGet()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsLastError">cupsLastError()</A></H2>
@@ -4513,11 +4492,11 @@ ipp_status_t
 cupsLastError(void);
 </PRE>
 <H3><A NAME="10_18_2">Returns</A></H3>
-<P>An enumeration containing the last IPP error. </P>
+<P>An enumeration containing the last IPP error.</P>
 <H3><A NAME="10_18_3">Description</A></H3>
-<P><CODE>cupsLastError()</CODE> returns the last IPP error that 
-occurred. If no error occurred then it will return <CODE>IPP_OK</CODE>
- or <CODE>IPP_OK_CONFLICT</CODE>. </P>
+<P><CODE>cupsLastError()</CODE> returns the last IPP error that
+ occurred. If no error occurred then it will return <CODE>IPP_OK</CODE>
+ or <CODE>IPP_OK_CONFLICT</CODE>.</P>
 <H3><A NAME="10_18_4">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4529,8 +4508,8 @@ ipp_status_t status;
 status = cupsLastError();
 </PRE>
 <H3><A NAME="10_18_5">See Also</A></H3>
-<P><A HREF="#cupsCancelJob"> cupsCancelJob()</A>, <A HREF="#cupsPrintFile">
-cupsPrintFile()</A>
+<P><A HREF="#cupsCancelJob"> cupsCancelJob()</A>,<A HREF="#cupsPrintFile">
+ cupsPrintFile()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsMarkOptions">cupsMarkOptions()</A></H2>
@@ -4552,11 +4531,10 @@ cupsMarkOptions(ppd_file_t *ppd,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_19_3">Returns</A></H3>
-<P>The number of conflicts found. </P>
+<P>The number of conflicts found.</P>
 <H3><A NAME="10_19_4">Description</A></H3>
-<P><CODE>cupsMarkOptions()</CODE> marks options in the PPD file. It 
-also handles mapping of IPP option names and values to PPD option 
-names. </P>
+<P><CODE>cupsMarkOptions()</CODE> marks options in the PPD file. It also
+ handles mapping of IPP option names and values to PPD option names.</P>
 <H3><A NAME="10_19_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4570,9 +4548,9 @@ ppd_file_t    *ppd;
 cupsMarkOptions(ppd, num_options, options);
 </PRE>
 <H3><A NAME="10_19_6">See Also</A></H3>
-<P><A HREF="#cupsAddOption"> cupsAddOption()</A>, <A HREF="#cupsFreeOptions">
-cupsFreeOptions()</A>, <A HREF="#cupsGetOption">cupsGetOption()</A>, <A HREF="#cupsParseOptions">
-cupsParseOptions()</A>
+<P><A HREF="#cupsAddOption"> cupsAddOption()</A>,<A HREF="#cupsFreeOptions">
+ cupsFreeOptions()</A>,<A HREF="#cupsGetOption"> cupsGetOption()</A>,<A HREF="#cupsParseOptions">
+ cupsParseOptions()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsParseOptions">cupsParseOptions()</A></H2>
@@ -4594,11 +4572,11 @@ cupsParseOptions(const char *arg,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_20_3">Returns</A></H3>
-<P>The new number of options in the array. </P>
+<P>The new number of options in the array.</P>
 <H3><A NAME="10_20_4">Description</A></H3>
-<P><CODE>cupsParseOptions()</CODE> parses the specifies string for one 
-or more options of the form &quot;name=value&quot;, &quot;name&quot;, or &quot;noname&quot;. It can 
-be called multiple times to combine the options from several strings. </P>
+<P><CODE>cupsParseOptions()</CODE> parses the specifies string for one
+ or more options of the form &quot;name=value&quot;, &quot;name&quot;, or &quot;noname&quot;. It can
+ be called multiple times to combine the options from several strings.</P>
 <H3><A NAME="10_20_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4613,9 +4591,9 @@ options     = (cups_option_t *)0;
 num_options = cupsParseOptions(argv[5], num_options, &amp;options);
 </PRE>
 <H3><A NAME="10_20_6">See Also</A></H3>
-<P><A HREF="#cupsAddOption"> cupsAddOption()</A>, <A HREF="#cupsFreeOptions">
-cupsFreeOptions()</A>, <A HREF="#cupsGetOption">cupsGetOption()</A>, <A HREF="#cupsMarkOptions">
-cupsMarkOptions()</A>
+<P><A HREF="#cupsAddOption"> cupsAddOption()</A>,<A HREF="#cupsFreeOptions">
+ cupsFreeOptions()</A>,<A HREF="#cupsGetOption"> cupsGetOption()</A>,<A HREF="#cupsMarkOptions">
+ cupsMarkOptions()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsPrintFile">cupsPrintFile()</A></H2>
@@ -4641,11 +4619,11 @@ cupsPrintFile(const char    *printer,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_21_3">Returns</A></H3>
-<P>The new job ID number or 0 on error. </P>
+<P>The new job ID number or 0 on error.</P>
 <H3><A NAME="10_21_4">Description</A></H3>
-<P><CODE>cupsPrintFile()</CODE> sends a file to the specified printer 
-or class for printing. If the job cannot be printed the error code can 
-be found by calling <CODE>cupsLastError()</CODE>. </P>
+<P><CODE>cupsPrintFile()</CODE> sends a file to the specified printer or
+ class for printing. If the job cannot be printed the error code can be
+ found by calling <CODE>cupsLastError()</CODE>.</P>
 <H3><A NAME="10_21_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4660,10 +4638,9 @@ jobid = cupsPrintFile(&quot;printer@hostname&quot;, &quot;filename.ps&quot;, &qu
                       num_options, options);
 </PRE>
 <H3><A NAME="10_21_6">See Also</A></H3>
-<P><A HREF="#cupsCancelJob"> cupsCancelJob()</A>, <A HREF="#cupsLastError">
-cupsLastError()</A>, <A HREF="#cupsPrintFiles">cupsPrintFiles()</A>
+<P><A HREF="#cupsCancelJob"> cupsCancelJob()</A>,<A HREF="#cupsLastError">
+ cupsLastError()</A>,<A HREF="#cupsPrintFiles"> cupsPrintFiles()</A>
 <!-- NEW PAGE -->
-
 </P>
 <H2><A NAME="cupsPrintFiles">cupsPrintFiles()</A></H2>
 <H3><A NAME="10_22_1">Usage</A></H3>
@@ -4690,11 +4667,11 @@ cupsPrintFiles(const char    *printer,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_22_3">Returns</A></H3>
-<P>The new job ID number or 0 on error. </P>
+<P>The new job ID number or 0 on error.</P>
 <H3><A NAME="10_22_4">Description</A></H3>
-<P><CODE>cupsPrintFiles()</CODE> sends multiple files to the specified 
-printer or class for printing. If the job cannot be printed the error 
-code can be found by calling <CODE>cupsLastError()</CODE>. </P>
+<P><CODE>cupsPrintFiles()</CODE> sends multiple files to the specified
+ printer or class for printing. If the job cannot be printed the error
+ code can be found by calling <CODE>cupsLastError()</CODE>.</P>
 <H3><A NAME="10_22_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -4711,8 +4688,8 @@ jobid = cupsPrintFiles(&quot;printer@hostname&quot;, num_files, files,
                        &quot;Job Title&quot;, num_options, options);
 </PRE>
 <H3><A NAME="10_22_6">See Also</A></H3>
-<P><A HREF="#cupsCancelJob"> cupsCancelJob()</A>, <A HREF="#cupsLastError">
-cupsLastError()</A>, <A HREF="#cupsPrintFile">cupsPrintFile()</A>
+<P><A HREF="#cupsCancelJob"> cupsCancelJob()</A>,<A HREF="#cupsLastError">
+ cupsLastError()</A>,<A HREF="#cupsPrintFile"> cupsPrintFile()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsRasterClose">cupsRasterClose()</A></H2>
@@ -4729,7 +4706,7 @@ cupsRasterClose(cups_raster_t *ras);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_23_3">Description</A></H3>
-<P><CODE>cupsRasterClose()</CODE> closes the specified raster stream. </P>
+<P><CODE>cupsRasterClose()</CODE> closes the specified raster stream.</P>
 <H3><A NAME="10_23_4">Example</A></H3>
 <PRE>
 #include &lt;cups/raster.h&gt;
@@ -4741,11 +4718,11 @@ cups_raster_t *ras;
 cupsRasterClose(ras);
 </PRE>
 <H3><A NAME="10_23_5">See Also</A></H3>
-<P><A HREF="#cupsRasterOpen"> cupsRasterOpen()</A>, <A HREF="#cupsRasterReadHeader">
-cupsRasterReadHeader()</A>, <A HREF="#cupsRasterReadPixels">
-cupsRasterReadPixels()</A>, <A HREF="#cupsRasterWriteHeader">
-cupsRasterWriteHeader()</A>, <A HREF="#cupsRasterWritePixels">
-cupsRasterWritePixels()</A>
+<P><A HREF="#cupsRasterOpen"> cupsRasterOpen()</A>,<A HREF="#cupsRasterReadHeader">
+ cupsRasterReadHeader()</A>,<A HREF="#cupsRasterReadPixels">
+ cupsRasterReadPixels()</A>,<A HREF="#cupsRasterWriteHeader">
+ cupsRasterWriteHeader()</A>,<A HREF="#cupsRasterWritePixels">
+ cupsRasterWritePixels()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsRasterOpen">cupsRasterOpen()</A></H2>
@@ -4761,15 +4738,15 @@ cupsRasterOpen(int fd,
 <TR><TH>Argument</TH><TH>Description</TH></TR>
 <TR><TD>fd</TD><TD>The file descriptor to use.</TD></TR>
 <TR><TD>mode</TD><TD>The mode to use; <CODE>CUPS_RASTER_READ</CODE> or <CODE>
- CUPS_RASTER_WRITE</CODE>.</TD></TR>
+CUPS_RASTER_WRITE</CODE>.</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_24_3">Returns</A></H3>
-<P>A pointer to a raster stream or <CODE>NULL</CODE> if there was an 
-error. </P>
+<P>A pointer to a raster stream or <CODE>NULL</CODE> if there was an
+ error.</P>
 <H3><A NAME="10_24_4">Description</A></H3>
-<P><CODE>cupsRasterOpen()</CODE> opens a raster stream for reading or 
-writing. </P>
+<P><CODE>cupsRasterOpen()</CODE> opens a raster stream for reading or
+ writing.</P>
 <H3><A NAME="10_24_5">Example</A></H3>
 <PRE>
 #include &lt;cups/raster.h&gt;
@@ -4781,11 +4758,11 @@ cups_raster_t *ras;
 ras = cupsRasterOpen(0, CUPS_RASTER_READ);
 </PRE>
 <H3><A NAME="10_24_6">See Also</A></H3>
-<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>, <A HREF="#cupsRasterReadHeader">
-cupsRasterReadHeader()</A>, <A HREF="#cupsRasterReadPixels">
-cupsRasterReadPixels()</A>, <A HREF="#cupsRasterWriteHeader">
-cupsRasterWriteHeader()</A>, <A HREF="#cupsRasterWritePixels">
-cupsRasterWritePixels()</A>
+<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>,<A HREF="#cupsRasterReadHeader">
+ cupsRasterReadHeader()</A>,<A HREF="#cupsRasterReadPixels">
+ cupsRasterReadPixels()</A>,<A HREF="#cupsRasterWriteHeader">
+ cupsRasterWriteHeader()</A>,<A HREF="#cupsRasterWritePixels">
+ cupsRasterWritePixels()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsRasterReadHeader">cupsRasterReadHeader()</A></H2>
@@ -4800,15 +4777,15 @@ cupsRasterReadHeader(cups_raster_t *ras,
 <TABLE BORDER WIDTH="80%">
 <TR><TH>Argument</TH><TH>Description</TH></TR>
 <TR><TD>ras</TD><TD>The raster stream to read from.</TD></TR>
-<TR><TD>header</TD><TD>A pointer to a page header structure to read 
-into.</TD></TR>
+<TR><TD>header</TD><TD>A pointer to a page header structure to read
+ into.</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_25_3">Returns</A></H3>
-<P>1 on success, 0 on EOF or error. </P>
+<P>1 on success, 0 on EOF or error.</P>
 <H3><A NAME="10_25_4">Description</A></H3>
-<P><CODE>cupsRasterReadHeader()</CODE> reads a page header from the 
-specified raster stream. </P>
+<P><CODE>cupsRasterReadHeader()</CODE> reads a page header from the
+ specified raster stream.</P>
 <H3><A NAME="10_25_5">Example</A></H3>
 <PRE>
 #include &lt;cups/raster.h&gt;
@@ -4832,11 +4809,11 @@ while (cupsRasterReadHeader(ras, &amp;header))
 }
 </PRE>
 <H3><A NAME="10_25_6">See Also</A></H3>
-<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>, <A HREF="#cupsRasterOpen">
-cupsRasterOpen()</A>, <A HREF="#cupsRasterReadPixels">
-cupsRasterReadPixels()</A>, <A HREF="#cupsRasterWriteHeader">
-cupsRasterWriteHeader()</A>, <A HREF="#cupsRasterWritePixels">
-cupsRasterWritePixels()</A>
+<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>,<A HREF="#cupsRasterOpen">
+ cupsRasterOpen()</A>,<A HREF="#cupsRasterReadPixels">
+ cupsRasterReadPixels()</A>,<A HREF="#cupsRasterWriteHeader">
+ cupsRasterWriteHeader()</A>,<A HREF="#cupsRasterWritePixels">
+ cupsRasterWritePixels()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsRasterReadPixels">cupsRasterReadPixels()</A></H2>
@@ -4857,10 +4834,10 @@ cupsRasterReadPixels(cups_raster_t *ras,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_26_3">Returns</A></H3>
-<P>The number of bytes read or 0 on EOF or error. </P>
+<P>The number of bytes read or 0 on EOF or error.</P>
 <H3><A NAME="10_26_4">Description</A></H3>
-<P><CODE>cupsRasterReadPixels()</CODE> reads pixel data from the 
-specified raster stream. </P>
+<P><CODE>cupsRasterReadPixels()</CODE> reads pixel data from the
+ specified raster stream.</P>
 <H3><A NAME="10_26_5">Example</A></H3>
 <PRE>
 #include &lt;cups/raster.h&gt;
@@ -4884,11 +4861,11 @@ while (cupsRasterReadHeader(ras, &amp;header))
 }
 </PRE>
 <H3><A NAME="10_26_6">See Also</A></H3>
-<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>, <A HREF="#cupsRasterOpen">
-cupsRasterOpen()</A>, <A HREF="#cupsRasterReadHeader">
-cupsRasterReadHeader()</A>, <A HREF="#cupsRasterWriteHeader">
-cupsRasterWriteHeader()</A>, <A HREF="#cupsRasterWritePixels">
-cupsRasterWritePixels()</A>
+<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>,<A HREF="#cupsRasterOpen">
+ cupsRasterOpen()</A>,<A HREF="#cupsRasterReadHeader">
+ cupsRasterReadHeader()</A>,<A HREF="#cupsRasterWriteHeader">
+ cupsRasterWriteHeader()</A>,<A HREF="#cupsRasterWritePixels">
+ cupsRasterWritePixels()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsRasterWriteHeader">cupsRasterWriteHeader()</A></H2>
@@ -4907,10 +4884,10 @@ cupsRasterWriteHeader(cups_raster_t *ras,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_27_3">Returns</A></H3>
-<P>1 on success, 0 on error. </P>
+<P>1 on success, 0 on error.</P>
 <H3><A NAME="10_27_4">Description</A></H3>
-<P><CODE>cupsRasterWriteHeader()</CODE> writes the specified page 
-header to a raster stream. </P>
+<P><CODE>cupsRasterWriteHeader()</CODE> writes the specified page header
+ to a raster stream.</P>
 <H3><A NAME="10_27_5">Example</A></H3>
 <PRE>
 #include &lt;cups/raster.h&gt;
@@ -4931,11 +4908,11 @@ for (line = 0; line &lt; header.cupsHeight; line ++)
 }
 </PRE>
 <H3><A NAME="10_27_6">See Also</A></H3>
-<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>, <A HREF="#cupsRasterOpen">
-cupsRasterOpen()</A>, <A HREF="#cupsRasterReadHeader">
-cupsRasterReadHeader()</A>, <A HREF="#cupsRasterReadPixels">
-cupsRasterReadPixels()</A>, <A HREF="#cupsRasterWritePixels">
-cupsRasterWritePixels()</A>
+<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>,<A HREF="#cupsRasterOpen">
+ cupsRasterOpen()</A>,<A HREF="#cupsRasterReadHeader">
+ cupsRasterReadHeader()</A>,<A HREF="#cupsRasterReadPixels">
+ cupsRasterReadPixels()</A>,<A HREF="#cupsRasterWritePixels">
+ cupsRasterWritePixels()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsRasterWritePixels">cupsRasterWritePixels()</A></H2>
@@ -4956,10 +4933,10 @@ cupsRasterWritePixels(cups_raster_t *ras,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_28_3">Returns</A></H3>
-<P>The number of bytes written. </P>
+<P>The number of bytes written.</P>
 <H3><A NAME="10_28_4">Description</A></H3>
-<P><CODE>cupsRasterWritePixels()</CODE> writes the specified pixel data 
-to a raster stream. </P>
+<P><CODE>cupsRasterWritePixels()</CODE> writes the specified pixel data
+ to a raster stream.</P>
 <H3><A NAME="10_28_5">Example</A></H3>
 <PRE>
 #include &lt;cups/raster.h&gt;
@@ -4980,11 +4957,11 @@ for (line = 0; line &lt; header.cupsHeight; line ++)
 }
 </PRE>
 <H3><A NAME="10_28_6">See Also</A></H3>
-<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>, <A HREF="#cupsRasterOpen">
-cupsRasterOpen()</A>, <A HREF="#cupsRasterReadHeader">
-cupsRasterReadHeader()</A>, <A HREF="#cupsRasterReadPixels">
-cupsRasterReadPixels()</A>, <A HREF="#cupsRasterWriteHeader">
-cupsRasterWriteHeader()</A>
+<P><A HREF="#cupsRasterClose"> cupsRasterClose()</A>,<A HREF="#cupsRasterOpen">
+ cupsRasterOpen()</A>,<A HREF="#cupsRasterReadHeader">
+ cupsRasterReadHeader()</A>,<A HREF="#cupsRasterReadPixels">
+ cupsRasterReadPixels()</A>,<A HREF="#cupsRasterWriteHeader">
+ cupsRasterWriteHeader()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsServer">cupsServer()</A></H2>
@@ -4994,17 +4971,17 @@ const char *
 cupsServer(void);
 </PRE>
 <H3><A NAME="10_29_2">Returns</A></H3>
-<P>A pointer to the default server name. </P>
+<P>A pointer to the default server name.</P>
 <H3><A NAME="10_29_3">Description</A></H3>
-<P><CODE>cupsServer()</CODE> returns a pointer to the default server 
-name. The server name is stored in a static location and will be 
-overwritten with every call to <CODE>cupsServer()</CODE></P>
-<P>The default server is determined from the following locations: </P>
+<P><CODE>cupsServer()</CODE> returns a pointer to the default server
+ name. The server name is stored in a static location and will be
+ overwritten with every call to <CODE>cupsServer()</CODE></P>
+<P>The default server is determined from the following locations:</P>
 <OL>
-<LI>The <CODE>CUPS_SERVER</CODE> environment variable, </LI>
-<LI>The <CODE>ServerName</CODE> directive in the <VAR> client.conf</VAR>
- file, </LI>
-<LI>The default host, &quot;localhost&quot;. </LI>
+<LI>The <CODE>CUPS_SERVER</CODE> environment variable,</LI>
+<LI>The <CODE>ServerName</CODE> directive in the<VAR> client.conf</VAR>
+ file,</LI>
+<LI>The default host, &quot;localhost&quot;.</LI>
 </OL>
 <H3><A NAME="10_29_4">Example</A></H3>
 <PRE>
@@ -5015,9 +4992,9 @@ const char *server;
 server = cupsServer();
 </PRE>
 <H3><A NAME="10_29_5">See Also</A></H3>
-<P><A HREF="#cupsGetPassword"> cupsGetPassword()</A>, <A HREF="#cupsSetPasswordCB">
-cupsSetPasswordCB()</A>, <A HREF="#cupsSetServer">cupsSetServer()</A>, <A
-HREF="#cupsSetUser">cupsSetUser()</A>, <A HREF="#cupsUser">cupsUser()</A>
+<P><A HREF="#cupsGetPassword"> cupsGetPassword()</A>,<A HREF="#cupsSetPasswordCB">
+ cupsSetPasswordCB()</A>,<A HREF="#cupsSetServer"> cupsSetServer()</A>,<A
+HREF="#cupsSetUser"> cupsSetUser()</A>,<A HREF="#cupsUser"> cupsUser()</A>
 <!-- NEW PAGE -->
 
 </P>
@@ -5035,11 +5012,11 @@ cupsSetPasswordCB(const char *(*cb)(const char *prompt));
 </TABLE>
 </CENTER>
 <H3><A NAME="10_30_3">Description</A></H3>
-<P><CODE>cupsSetPasswordCB()</CODE> sets the callback function to use 
-when asking the user for a password. The callback function must accept 
-a single character string pointer (the prompt string) and return <CODE>
-NULL</CODE> if the user did not enter a password string or a pointer to 
-the password string otherwise. </P>
+<P><CODE>cupsSetPasswordCB()</CODE> sets the callback function to use
+ when asking the user for a password. The callback function must accept
+ a single character string pointer (the prompt string) and return <CODE>
+NULL</CODE> if the user did not enter a password string or a pointer to
+ the password string otherwise.</P>
 <H3><A NAME="10_30_4">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -5060,9 +5037,9 @@ cupsSetPasswordCB(my_password_cb);
 password = cupsGetPassword(&quot;Please enter a password:&quot;);
 </PRE>
 <H3><A NAME="10_30_5">See Also</A></H3>
-<P><A HREF="#cupsServer"> cupsServer()</A>, <A HREF="#cupsSetServer">
-cupsSetServer()</A>, <A HREF="#cupsSetUser">cupsSetUser()</A>, <A HREF="#cupsUser()">
-cupsUser()</A>
+<P><A HREF="#cupsServer"> cupsServer()</A>,<A HREF="#cupsSetServer">
+ cupsSetServer()</A>,<A HREF="#cupsSetUser"> cupsSetUser()</A>,<A HREF="#cupsUser()">
+ cupsUser()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsSetServer">cupsSetServer()</A></H2>
@@ -5079,9 +5056,9 @@ cupsSetServer(const char *server);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_31_3">Description</A></H3>
-<P><CODE>cupsSetServer()</CODE> sets the default server to use for the 
-CUPS API. If the <CODE>server</CODE> argument is <CODE>NULL</CODE>, the 
-default server is used. </P>
+<P><CODE>cupsSetServer()</CODE> sets the default server to use for the
+ CUPS API. If the <CODE>server</CODE> argument is <CODE>NULL</CODE>, the
+ default server is used.</P>
 <H3><A NAME="10_31_4">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -5089,9 +5066,9 @@ default server is used. </P>
 cupsSetServer(&quot;foo.bar.com&quot;);
 </PRE>
 <H3><A NAME="10_31_5">See Also</A></H3>
-<P><A HREF="#cupsServer"> cupsServer()</A>, <A HREF="#cupsSetPasswordCB">
-cupsSetPasswordCB()</A>, <A HREF="#cupsSetUser">cupsSetUser()</A>, <A HREF="#cupsUser()">
-cupsUser()</A>
+<P><A HREF="#cupsServer"> cupsServer()</A>,<A HREF="#cupsSetPasswordCB">
+ cupsSetPasswordCB()</A>,<A HREF="#cupsSetUser"> cupsSetUser()</A>,<A HREF="#cupsUser()">
+ cupsUser()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsSetUser">cupsSetUser()</A></H2>
@@ -5108,9 +5085,9 @@ cupsSetUser(const char *user);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_32_3">Description</A></H3>
-<P><CODE>cupsSetUser()</CODE> sets the default user name for 
-authentication. If the <CODE>user</CODE> argument is <CODE>NULL</CODE>
- then the current login user is used. </P>
+<P><CODE>cupsSetUser()</CODE> sets the default user name for
+ authentication. If the <CODE>user</CODE> argument is <CODE>NULL</CODE>
+ then the current login user is used.</P>
 <H3><A NAME="10_32_4">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -5120,9 +5097,9 @@ authentication. If the <CODE>user</CODE> argument is <CODE>NULL</CODE>
 cupsSetUser(&quot;root&quot;);
 </PRE>
 <H3><A NAME="10_32_5">See Also</A></H3>
-<P><A HREF="#cupsServer"> cupsServer()</A>, <A HREF="#cupsSetPasswordCB">
-cupsSetPasswordCB()</A>, <A HREF="#cupsSetServer">cupsSetServer()</A>, <A
-HREF="#cupsUser()">cupsUser()</A>
+<P><A HREF="#cupsServer"> cupsServer()</A>,<A HREF="#cupsSetPasswordCB">
+ cupsSetPasswordCB()</A>,<A HREF="#cupsSetServer"> cupsSetServer()</A>,<A
+HREF="#cupsUser()"> cupsUser()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="cupsTempFile">cupsTempFile()</A></H2>
@@ -5136,17 +5113,17 @@ cupsTempFile(char *filename,
 <CENTER>
 <TABLE BORDER WIDTH="80%">
 <TR><TH>Argument</TH><TH>Description</TH></TR>
-<TR><TD>filename</TD><TD>The character string to hold the temporary 
-filename.</TD></TR>
+<TR><TD>filename</TD><TD>The character string to hold the temporary
+ filename.</TD></TR>
 <TR><TD>length</TD><TD>The size of the filename string in bytes.</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_33_3">Returns</A></H3>
-<P>A pointer to <CODE>filename</CODE>. </P>
+<P>A pointer to <CODE>filename</CODE>.</P>
 <H3><A NAME="10_33_4">Description</A></H3>
-<P><CODE>cupsTempFile()</CODE> generates a temporary filename for the <VAR>
-/var/tmp</VAR> directory or the directory specified by the <CODE>TMPDIR</CODE>
- environment variable. </P>
+<P><CODE>cupsTempFile()</CODE> generates a temporary filename for the<VAR>
+ /var/tmp</VAR> directory or the directory specified by the <CODE>TMPDIR</CODE>
+ environment variable.</P>
 <H3><A NAME="10_33_5">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -5157,7 +5134,6 @@ cupsTempFile(filename, sizeof(filename));
 </PRE>
 
 <!-- NEW PAGE -->
-
 <H2><A NAME="cupsUser">cupsUser()</A></H2>
 <H3><A NAME="10_34_1">Usage</A></H3>
 <PRE>
@@ -5165,11 +5141,11 @@ const char *
 cupsUser(void);
 </PRE>
 <H3><A NAME="10_34_2">Returns</A></H3>
-<P>A pointer to the current username or <CODE>NULL</CODE> if the user 
-ID is undefined. </P>
+<P>A pointer to the current username or <CODE>NULL</CODE> if the user ID
+ is undefined.</P>
 <H3><A NAME="10_34_3">Description</A></H3>
-<P><CODE>cupsUser()</CODE> returns the name associated with the current 
-user ID as reported by the <CODE>getuid()</CODE> system call. </P>
+<P><CODE>cupsUser()</CODE> returns the name associated with the current
+ user ID as reported by the <CODE>getuid()</CODE> system call.</P>
 <H3><A NAME="10_34_4">Example</A></H3>
 <PRE>
 #include &lt;cups/cups.h&gt;
@@ -5179,8 +5155,8 @@ const char *user;
 user = cupsUser();
 </PRE>
 <H3><A NAME="10_34_5">See Also</A></H3>
-<P><A HREF="#cupsGetPassword"> cupsGetPassword()</A>, <A HREF="#cupsServer">
-cupsServer()</A>
+<P><A HREF="#cupsGetPassword"> cupsGetPassword()</A>,<A HREF="#cupsServer">
+ cupsServer()</A>
 <!-- NEW PAGE -->
 </P>
 <H2><A NAME="httpBlocking">httpBlocking()</A></H2>
@@ -5193,14 +5169,14 @@ void httpBlocking(http_t *http, int blocking)
 <TABLE BORDER WIDTH="80%">
 <TR><TH>Argument</TH><TH>Description</TH></TR>
 <TR><TD>http</TD><TD>The HTTP connection</TD></TR>
-<TR><TD>blocking</TD><TD>0 if the connection should be non-blocking, 1 
-if it should  be blocking</TD></TR>
+<TR><TD>blocking</TD><TD>0 if the connection should be non-blocking, 1
+ if it should be blocking</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_35_3">Description</A></H3>
-<P>The <CODE>httpBlocking()</CODE> function sets the blocking mode for 
-the HTTP connection. By default HTTP connections will block (stop) the 
-client program until data is available or can be sent to the server. </P>
+<P>The <CODE>httpBlocking()</CODE> function sets the blocking mode for
+ the HTTP connection. By default HTTP connections will block (stop) the
+ client program until data is available or can be sent to the server.</P>
 <H3><A NAME="10_35_4">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5211,8 +5187,8 @@ http = httpConnect(&quot;server&quot;, port);
 httpBlocking(http, 0);
 </PRE>
 <H3><A NAME="10_35_5">See Also</A></H3>
-<A HREF="#httpCheck"><CODE> httpCheck()</CODE></A>, <A HREF="#httpConnect">
-<CODE>httpConnect()</CODE></A>
+<A HREF="#httpCheck"> <CODE>httpCheck()</CODE></A>,<A HREF="#httpConnect">
+ <CODE>httpConnect()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpCheck">httpCheck()</A></H2>
@@ -5228,10 +5204,10 @@ int httpCheck(http_t *http);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_36_3">Returns</A></H3>
-<P>0 if there is no data pending, 1 otherwise. </P>
+<P>0 if there is no data pending, 1 otherwise.</P>
 <H3><A NAME="10_36_4">Description</A></H3>
-<P>The <CODE>httpCheck()</CODE> function checks to see if there is any 
-data pending on an HTTP connection. </P>
+<P>The <CODE>httpCheck()</CODE> function checks to see if there is any
+ data pending on an HTTP connection.</P>
 <H3><A NAME="10_36_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5244,9 +5220,9 @@ if (httpCheck(http))
 }
 </PRE>
 <H3><A NAME="10_36_6">See Also</A></H3>
-<A HREF="#httpBlocking"><CODE> httpBlocking()</CODE></A>, <A HREF="#httpConnect">
-<CODE>httpConnect()</CODE></A>, <A HREF="#httpGets"><CODE>httpGets()</CODE>
-</A>, <A HREF="#httpRead"><CODE>httpRead()</CODE></A>
+<A HREF="#httpBlocking"> <CODE>httpBlocking()</CODE></A>,<A HREF="#httpConnect">
+ <CODE>httpConnect()</CODE></A>,<A HREF="#httpGets"> <CODE>httpGets()</CODE>
+</A>,<A HREF="#httpRead"> <CODE>httpRead()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpClearFields">httpClearFields()</A></H2>
@@ -5262,8 +5238,8 @@ void httpClearFields(http_t *http)
 </TABLE>
 </CENTER>
 <H3><A NAME="10_37_3">Description</A></H3>
-<P>The <CODE>httpClearFields()</CODE> function clears all HTTP request 
-fields for the HTTP connection. </P>
+<P>The <CODE>httpClearFields()</CODE> function clears all HTTP request
+ fields for the HTTP connection.</P>
 <H3><A NAME="10_37_4">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5273,8 +5249,8 @@ http_t *http;
 httpClearFields(http);
 </PRE>
 <H3><A NAME="10_37_5">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpGetField">
-<CODE>httpGetField()</CODE></A>, <A HREF="#httpSetField"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpGetField">
+ <CODE>httpGetField()</CODE></A>,<A HREF="#httpSetField"> <CODE>
 httpSetField()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -5291,8 +5267,8 @@ void httpClose(http_t *http);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_38_3">Description</A></H3>
-<P>The <CODE>httpClose()</CODE> function closes an active HTTP 
-connection. </P>
+<P>The <CODE>httpClose()</CODE> function closes an active HTTP
+ connection.</P>
 <H3><A NAME="10_38_4">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5302,7 +5278,7 @@ http_t *http;
 httpClose(http);
 </PRE>
 <H3><A NAME="10_38_5">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpConnect">httpConnect()</A></H2>
@@ -5314,17 +5290,17 @@ http_t *httpConnect(const char *hostname, int port);
 <CENTER>
 <TABLE BORDER WIDTH="80%">
 <TR><TH>Argument</TH><TH>Description</TH></TR>
-<TR><TD>hostname</TD><TD>The name or IP address of the server to 
-connect to</TD></TR>
+<TR><TD>hostname</TD><TD>The name or IP address of the server to connect
+ to</TD></TR>
 <TR><TD>port</TD><TD>The port number to use</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_39_3">Returns</A></H3>
-<P>A pointer to a HTTP connection structure or NULL if the connection 
-could not be made. </P>
+<P>A pointer to a HTTP connection structure or NULL if the connection
+ could not be made.</P>
 <H3><A NAME="10_39_4">Description</A></H3>
-<P>The <CODE>httpConnect()</CODE> function opens a HTTP connection to 
-the specified server and port. </P>
+<P>The <CODE>httpConnect()</CODE> function opens a HTTP connection to
+ the specified server and port.</P>
 <H3><A NAME="10_39_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5334,10 +5310,10 @@ http_t *http;
 http = httpConnect(cupsServer(), ippPort());
 </PRE>
 <H3><A NAME="10_39_6">See Also</A></H3>
-<A HREF="#httpClose"><CODE> httpClose()</CODE></A>, <A HREF="#httpGet"><CODE>
-httpGet()</CODE></A>, <A HREF="#httpGets"><CODE>httpGets()</CODE></A>, <A
-HREF="#httpPost"><CODE>httpPost()</CODE></A>, <A HREF="#httpRead"><CODE>
-httpRead()</CODE></A>, <A HREF="#httpWrite"><CODE>httpWrite()</CODE></A>
+<A HREF="#httpClose"> <CODE>httpClose()</CODE></A>,<A HREF="#httpGet"> <CODE>
+httpGet()</CODE></A>,<A HREF="#httpGets"> <CODE>httpGets()</CODE></A>,<A HREF="#httpPost">
+ <CODE>httpPost()</CODE></A>,<A HREF="#httpRead"> <CODE>httpRead()</CODE>
+</A>,<A HREF="#httpWrite"> <CODE>httpWrite()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpDecode64">httpDecode64()</A></H2>
@@ -5354,10 +5330,10 @@ char *httpDecode64(char *out, const char *in);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_40_3">Returns</A></H3>
-<P>A pointer to the decoded string. </P>
+<P>A pointer to the decoded string.</P>
 <H3><A NAME="10_40_4">Description</A></H3>
-<P>The <CODE>httpDecode64()</CODE> function decodes a base-64 encoded 
-string to the original string. </P>
+<P>The <CODE>httpDecode64()</CODE> function decodes a base-64 encoded
+ string to the original string.</P>
 <H3><A NAME="10_40_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5368,7 +5344,7 @@ char original_string[255];
 httpDecode64(original_string, encoded_string);
 </PRE>
 <H3><A NAME="10_40_6">See Also</A></H3>
-<A HREF="#httpEncode64"><CODE> httpEncode64()</CODE></A>
+<A HREF="#httpEncode64"> <CODE>httpEncode64()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpDelete">httpDelete()</A></H2>
@@ -5385,10 +5361,10 @@ int httpDelete(http_t *http, const char *uri);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_41_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_41_4">Description</A></H3>
-<P>The <CODE>httpDelete()</CODE> function sends a HTTP DELETE request 
-to the server. </P>
+<P>The <CODE>httpDelete()</CODE> function sends a HTTP DELETE request to
+ the server.</P>
 <H3><A NAME="10_41_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5398,8 +5374,8 @@ http_t *http;
 httpDelete(http, &quot;/some/uri&quot;);
 </PRE>
 <H3><A NAME="10_41_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>,<A HREF="#httpUpdate"> <CODE>
 httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -5417,10 +5393,10 @@ char *httpEncode64(char *out, const char *in);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_42_3">Returns</A></H3>
-<P>A pointer to the encoded string. </P>
+<P>A pointer to the encoded string.</P>
 <H3><A NAME="10_42_4">Description</A></H3>
-<P>The <CODE>httpEncode64()</CODE> function decodes a base-64 encoded 
-string to the original string. </P>
+<P>The <CODE>httpEncode64()</CODE> function decodes a base-64 encoded
+ string to the original string.</P>
 <H3><A NAME="10_42_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5431,7 +5407,7 @@ char original_string[255];
 httpEncode64(encoded_string, original_string);
 </PRE>
 <H3><A NAME="10_42_6">See Also</A></H3>
-<A HREF="#httpDecode64"><CODE> httpDecode64()</CODE></A>
+<A HREF="#httpDecode64"> <CODE>httpDecode64()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpError">httpError()</A></H2>
@@ -5447,10 +5423,10 @@ int httpError(http_t *http);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_43_3">Returns</A></H3>
-<P>The last error that occurred or 0 if no error has occurred. </P>
+<P>The last error that occurred or 0 if no error has occurred.</P>
 <H3><A NAME="10_43_4">Description</A></H3>
-<P>The <CODE>httpError()</CODE> function returns the last error that 
-occurred on the HTTP connection. </P>
+<P>The <CODE>httpError()</CODE> function returns the last error that
+ occurred on the HTTP connection.</P>
 <H3><A NAME="10_43_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5463,7 +5439,7 @@ if (httpError(http))
 }
 </PRE>
 <H3><A NAME="10_43_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpFlush">httpFlush()</A></H2>
@@ -5479,8 +5455,8 @@ void httpFlush(http_t *http);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_44_3">Description</A></H3>
-<P>The <CODE>httpFlush()</CODE> function flushes any remaining data 
-left from a GET or POST operation. </P>
+<P>The <CODE>httpFlush()</CODE> function flushes any remaining data left
+ from a GET or POST operation.</P>
 <H3><A NAME="10_44_4">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5490,7 +5466,7 @@ http_t *http;
 httpFlush(http);
 </PRE>
 <H3><A NAME="10_44_5">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, 
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpGet">httpGet()</A></H2>
@@ -5507,10 +5483,10 @@ int httpGet(http_t *http, const char *uri);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_45_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_45_4">Description</A></H3>
-<P>The <CODE>httpGet()</CODE> function sends a HTTP GET request to the 
-server. </P>
+<P>The <CODE>httpGet()</CODE> function sends a HTTP GET request to the
+ server.</P>
 <H3><A NAME="10_45_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5520,8 +5496,8 @@ http_t *http;
 httpGet(http, &quot;/some/uri&quot;);
 </PRE>
 <H3><A NAME="10_45_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>,<A HREF="#httpUpdate"> <CODE>
 httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -5534,17 +5510,17 @@ char *httpGets(char *line, int length, http_t *http)
 <CENTER>
 <TABLE BORDER WIDTH="80%">
 <TR><TH>Argument</TH><TH>Description</TH></TR>
-<TR><TD>line</TD><TD>The string to fill with a line from the HTTP 
-connection</TD></TR>
+<TR><TD>line</TD><TD>The string to fill with a line from the HTTP
+ connection</TD></TR>
 <TR><TD>length</TD><TD>The maximum length of the string</TD></TR>
 <TR><TD>http</TD><TD>The HTTP connection</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_46_3">Returns</A></H3>
-<P>A pointer to the string or NULL if no line could be retrieved. </P>
+<P>A pointer to the string or NULL if no line could be retrieved.</P>
 <H3><A NAME="10_46_4">Description</A></H3>
-<P>The <CODE>httpGets()</CODE> function is used to read a request line 
-from the HTTP connection. It is not normally used by a client program. </P>
+<P>The <CODE>httpGets()</CODE> function is used to read a request line
+ from the HTTP connection. It is not normally used by a client program.</P>
 <H3><A NAME="10_46_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5558,8 +5534,8 @@ if (httpGets(line, sizeof(line), http))
 }
 </PRE>
 <H3><A NAME="10_46_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpUpdate">
-<CODE>httpUpdate()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpUpdate">
+ <CODE>httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpGetDateString">httpGetDateString()</A></H2>
@@ -5575,11 +5551,11 @@ const char *httpGetDateString(time_t time)
 </TABLE>
 </CENTER>
 <H3><A NAME="10_47_3">Returns</A></H3>
-<P>A pointer to a static string containing the HTTP date/time string 
-for the specified UNIX time value. </P>
+<P>A pointer to a static string containing the HTTP date/time string for
+ the specified UNIX time value.</P>
 <H3><A NAME="10_47_4">Description</A></H3>
-<P>The <CODE>httpGetDateString()</CODE> function generates a date/time 
-string suitable for HTTP requests from a UNIX time value. </P>
+<P>The <CODE>httpGetDateString()</CODE> function generates a date/time
+ string suitable for HTTP requests from a UNIX time value.</P>
 <H3><A NAME="10_47_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5587,7 +5563,7 @@ string suitable for HTTP requests from a UNIX time value. </P>
 puts(httpGetDateString(time(NULL)));
 </PRE>
 <H3><A NAME="10_47_6">See Also</A></H3>
-<A HREF="#httpGetDateTime"><CODE> httpGetDateTime()</CODE></A>
+<A HREF="#httpGetDateTime"> <CODE>httpGetDateTime()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpGetDateTime">httpGetDateTime()</A></H2>
@@ -5603,10 +5579,10 @@ time_t httpGetDateTime(const char *date)
 </TABLE>
 </CENTER>
 <H3><A NAME="10_48_3">Returns</A></H3>
-<P>A UNIX time value. </P>
+<P>A UNIX time value.</P>
 <H3><A NAME="10_48_4">Description</A></H3>
-<P>The <CODE>httpGetDateTime()</CODE> function converts a HTTP 
-date/time string to a UNIX time value. </P>
+<P>The <CODE>httpGetDateTime()</CODE> function converts a HTTP date/time
+ string to a UNIX time value.</P>
 <H3><A NAME="10_48_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5614,7 +5590,7 @@ date/time string to a UNIX time value. </P>
 printf(&quot;%d\n&quot;, httpGetDateTime(&quot;Fri, 30 June 2000 12:34:56 GMT&quot;));
 </PRE>
 <H3><A NAME="10_48_6">See Also</A></H3>
-<A HREF="#httpGetDateString"><CODE> httpGetDateString()</CODE></A>
+<A HREF="#httpGetDateString"> <CODE>httpGetDateString()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpGetField">httpGetField()</A></H2>
@@ -5631,10 +5607,10 @@ const char *httpGetField(http_t *http, http_field_t field);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_49_3">Returns</A></H3>
-<P>A pointer to the field value string. </P>
+<P>A pointer to the field value string.</P>
 <H3><A NAME="10_49_4">Description</A></H3>
-<P>The <CODE>httpGetField()</CODE> function returns the current value 
-for the specified HTTP field. </P>
+<P>The <CODE>httpGetField()</CODE> function returns the current value
+ for the specified HTTP field.</P>
 <H3><A NAME="10_49_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5647,8 +5623,8 @@ while (httpUpdate(http) == HTTP_CONTINUE);
 puts(httpGetField(http, HTTP_FIELD_CONTENT_TYPE));
 </PRE>
 <H3><A NAME="10_49_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpHead">httpHead()</A></H2>
@@ -5665,10 +5641,10 @@ int httpHead(http_t *http, const char *uri);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_50_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_50_4">Description</A></H3>
-<P>The <CODE>httpHead()</CODE> function sends a HTTP HEAD request to 
-the server. </P>
+<P>The <CODE>httpHead()</CODE> function sends a HTTP HEAD request to the
+ server.</P>
 <H3><A NAME="10_50_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5678,8 +5654,8 @@ http_t *http;
 httpHead(http, &quot;/some/uri&quot;);
 </PRE>
 <H3><A NAME="10_50_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>,<A HREF="#httpUpdate"> <CODE>
 httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -5689,9 +5665,9 @@ httpUpdate()</CODE></A>
 void httpInitialize(void);
 </PRE>
 <H3><A NAME="10_51_2">Description</A></H3>
-<P>The <CODE>httpInitialize()</CODE> function initializes the 
-networking code as needed by the underlying platform. It is called 
-automatically by the <CODE>httpConnect()</CODE> function. </P>
+<P>The <CODE>httpInitialize()</CODE> function initializes the networking
+ code as needed by the underlying platform. It is called automatically
+ by the <CODE>httpConnect()</CODE> function.</P>
 <H3><A NAME="10_51_3">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5699,7 +5675,7 @@ automatically by the <CODE>httpConnect()</CODE> function. </P>
 httpInitialize();
 </PRE>
 <H3><A NAME="10_51_4">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpOptions">httpOptions()</A></H2>
@@ -5716,10 +5692,10 @@ int httpOptions(http_t *http, const char *uri);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_52_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_52_4">Description</A></H3>
-<P>The <CODE>httpOptions()</CODE> function sends a HTTP OPTIONS request 
-to the server. </P>
+<P>The <CODE>httpOptions()</CODE> function sends a HTTP OPTIONS request
+ to the server.</P>
 <H3><A NAME="10_52_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5729,8 +5705,8 @@ http_t *http;
 httpOptions(http, &quot;/some/uri&quot;);
 </PRE>
 <H3><A NAME="10_52_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>,<A HREF="#httpUpdate"> <CODE>
 httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -5748,10 +5724,10 @@ int httpPost(http_t *http, const char *uri);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_53_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_53_4">Description</A></H3>
-<P>The <CODE>httpPost()</CODE> function sends a HTTP POST request to 
-the server. </P>
+<P>The <CODE>httpPost()</CODE> function sends a HTTP POST request to the
+ server.</P>
 <H3><A NAME="10_53_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5761,8 +5737,8 @@ http_t *http;
 httpPost(http, &quot;/some/uri&quot;);
 </PRE>
 <H3><A NAME="10_53_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>,<A HREF="#httpUpdate"> <CODE>
 httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -5780,11 +5756,11 @@ int httpPrintf(http_t *http, const char *format, ...);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_54_3">Returns</A></H3>
-<P>The number of bytes written. </P>
+<P>The number of bytes written.</P>
 <H3><A NAME="10_54_4">Description</A></H3>
-<P>The <CODE>httpPrintf()</CODE> function sends a formatted string to 
-the HTTP connection. It is normally only used by the CUPS API and 
-scheduler. </P>
+<P>The <CODE>httpPrintf()</CODE> function sends a formatted string to
+ the HTTP connection. It is normally only used by the CUPS API and
+ scheduler.</P>
 <H3><A NAME="10_54_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5794,7 +5770,7 @@ http_t *http;
 httpPrintf(http, &quot;GET / HTTP/1.1 \r\n&quot;);
 </PRE>
 <H3><A NAME="10_54_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpPut">httpPut()</A></H2>
@@ -5811,10 +5787,10 @@ int httpPut(http_t *http, const char *uri);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_55_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_55_4">Description</A></H3>
-<P>The <CODE>httpPut()</CODE> function sends a HTTP PUT request to the 
-server. </P>
+<P>The <CODE>httpPut()</CODE> function sends a HTTP PUT request to the
+ server.</P>
 <H3><A NAME="10_55_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5824,8 +5800,8 @@ http_t *http;
 httpDelete(http, &quot;/some/uri&quot;);
 </PRE>
 <H3><A NAME="10_55_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>,<A HREF="#httpUpdate"> <CODE>
 httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -5844,10 +5820,10 @@ int httpRead(http_t *http, char *buffer, int length);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_56_3">Returns</A></H3>
-<P>The number of bytes read or -1 on error. </P>
+<P>The number of bytes read or -1 on error.</P>
 <H3><A NAME="10_56_4">Description</A></H3>
-<P>The <CODE>httpRead()</CODE> function reads data from the HTTP 
-connection, possibly the result of a GET or POST request. </P>
+<P>The <CODE>httpRead()</CODE> function reads data from the HTTP
+ connection, possibly the result of a GET or POST request.</P>
 <H3><A NAME="10_56_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5865,8 +5841,8 @@ while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) &gt; 0)
 }
 </PRE>
 <H3><A NAME="10_56_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpWrite">
-<CODE>httpWrite()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpWrite">
+ <CODE>httpWrite()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpReconnect">httpReconnect()</A></H2>
@@ -5882,11 +5858,11 @@ int httpReconnect(http_t *http);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_57_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_57_4">Description</A></H3>
-<P>The <CODE>httpReconnect()</CODE> function reconnects to the HTTP 
-server. This is usually done automatically if the HTTP functions detect 
-that the server connection has terminated. </P>
+<P>The <CODE>httpReconnect()</CODE> function reconnects to the HTTP
+ server. This is usually done automatically if the HTTP functions detect
+ that the server connection has terminated.</P>
 <H3><A NAME="10_57_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5896,7 +5872,7 @@ http_t *http;
 httpReconnect(http);
 </PRE>
 <H3><A NAME="10_57_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpSeparate">httpSeparate()</A></H2>
@@ -5912,20 +5888,20 @@ void httpSeparate(const char *uri, char *method,
 <TR><TH>Argument</TH><TH>Description</TH></TR>
 <TR><TD>uri</TD><TD>The URI to separate</TD></TR>
 <TR><TD>method</TD><TD>The method (scheme) of the URI</TD></TR>
-<TR><TD>username</TD><TD>The username (and password) portion of the 
-URI, if any</TD></TR>
+<TR><TD>username</TD><TD>The username (and password) portion of the URI,
+ if any</TD></TR>
 <TR><TD>host</TD><TD>The hostname portion of the URI, if any</TD></TR>
-<TR><TD>port</TD><TD>The port number for the URI, either as specified 
-or as  default for the method/scheme</TD></TR>
-<TR><TD>resource</TD><TD>The resource string, usually a filename on the 
-server</TD></TR>
+<TR><TD>port</TD><TD>The port number for the URI, either as specified or
+ as default for the method/scheme</TD></TR>
+<TR><TD>resource</TD><TD>The resource string, usually a filename on the
+ server</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_58_3">Description</A></H3>
-<P>The <CODE>httpSeparate()</CODE> function separates the specified URI 
-into its component parts. The method, username, hostname, and resource 
-strings should be at least <CODE>HTTP_MAX_URI</CODE> characters long to 
-avoid potential buffer overflow problems. </P>
+<P>The <CODE>httpSeparate()</CODE> function separates the specified URI
+ into its component parts. The method, username, hostname, and resource
+ strings should be at least <CODE>HTTP_MAX_URI</CODE> characters long to
+ avoid potential buffer overflow problems.</P>
 <H3><A NAME="10_58_4">Example</A></H3>
 <PRE>
 char uri[HTTP_MAX_URI];
@@ -5938,7 +5914,7 @@ int port;
 httpSeparate(uri, method, username, host, &amp;port, resource);
 </PRE>
 <H3><A NAME="10_58_5">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpSetField">httpSetField()</A></H2>
@@ -5956,8 +5932,8 @@ void httpSetField(http_t *http, http_field_t field, const char *value);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_59_3">Description</A></H3>
-<P>The <CODE>httpSetField()</CODE> function sets the current value for 
-the specified HTTP field. </P>
+<P>The <CODE>httpSetField()</CODE> function sets the current value for
+ the specified HTTP field.</P>
 <H3><A NAME="10_59_4">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -5969,8 +5945,8 @@ httpGet(http, &quot;/some/uri&quot;);
 while (httpUpdate(http) == HTTP_CONTINUE);
 </PRE>
 <H3><A NAME="10_59_5">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpGetField">
-<CODE>httpGetField()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpGetField">
+ <CODE>httpGetField()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpTrace">httpTrace()</A></H2>
@@ -5987,10 +5963,10 @@ int httpTrace(http_t *http, const char *uri);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_60_3">Returns</A></H3>
-<P>0 on success, non-zero on failure. </P>
+<P>0 on success, non-zero on failure.</P>
 <H3><A NAME="10_60_4">Description</A></H3>
-<P>The <CODE>httpTrace()</CODE> function sends a HTTP TRACE request to 
-the server. </P>
+<P>The <CODE>httpTrace()</CODE> function sends a HTTP TRACE request to
+ the server.</P>
 <H3><A NAME="10_60_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -6000,8 +5976,8 @@ http_t *http;
 httpTrace(http, &quot;/some/uri&quot;);
 </PRE>
 <H3><A NAME="10_60_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpSetField">
-<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpSetField">
+ <CODE>httpSetField()</CODE></A>,<A HREF="#httpUpdate"> <CODE>
 httpUpdate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6018,16 +5994,16 @@ http_status_t httpUpdate(http_t *http);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_61_3">Returns</A></H3>
-<P>The HTTP status of the current request. </P>
+<P>The HTTP status of the current request.</P>
 <H3><A NAME="10_61_4">Description</A></H3>
-<P>The <CODE>httpUpdate()</CODE> function updates the current request 
-status. It is used after any DELETE, GET, HEAD, OPTIONS, POST, PUT, or 
-TRACE request to finalize the HTTP request and retrieve the request 
-status. </P>
-<P>Since proxies and the current blocking mode can cause the request to 
-take longer, programs should continue calling <CODE>httpUpdate()</CODE>
+<P>The <CODE>httpUpdate()</CODE> function updates the current request
+ status. It is used after any DELETE, GET, HEAD, OPTIONS, POST, PUT, or
+ TRACE request to finalize the HTTP request and retrieve the request
+ status.</P>
+<P>Since proxies and the current blocking mode can cause the request to
+ take longer, programs should continue calling <CODE>httpUpdate()</CODE>
  until the return status is not the constant value <CODE>HTTP_CONTINUE</CODE>
-. </P>
+.</P>
 <H3><A NAME="10_61_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -6040,12 +6016,12 @@ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
 printf(&quot;Request status is %d\n&quot;, status);
 </PRE>
 <H3><A NAME="10_61_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpDelete">
-<CODE>httpDelete()</CODE></A>, <A HREF="#httpGet"><CODE>httpGet()</CODE></A>
-, <A HREF="#httpHead"><CODE>httpHead()</CODE></A>, <A HREF="#httpOptions">
-<CODE>httpOptions()</CODE></A>, <A HREF="#httpPost"><CODE>httpPost()</CODE>
-</A>, <A HREF="#httpPut"><CODE>httpPut()</CODE></A>, <A HREF="#httpTrace">
-<CODE>httpTrace()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpDelete">
+ <CODE>httpDelete()</CODE></A>,<A HREF="#httpGet"> <CODE>httpGet()</CODE>
+</A>,<A HREF="#httpHead"> <CODE>httpHead()</CODE></A>,<A HREF="#httpOptions">
+ <CODE>httpOptions()</CODE></A>,<A HREF="#httpPost"> <CODE>httpPost()</CODE>
+</A>,<A HREF="#httpPut"> <CODE>httpPut()</CODE></A>,<A HREF="#httpTrace">
+ <CODE>httpTrace()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="httpWrite">httpWrite()</A></H2>
@@ -6063,10 +6039,10 @@ int httpWrite(http_t *http, char *buffer, int length);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_62_3">Returns</A></H3>
-<P>The number of bytes read or -1 on error. </P>
+<P>The number of bytes read or -1 on error.</P>
 <H3><A NAME="10_62_4">Description</A></H3>
-<P>The <CODE>httpWrite()</CODE> function reads data from the HTTP 
-connection, possibly the result of a GET or POST request. </P>
+<P>The <CODE>httpWrite()</CODE> function reads data from the HTTP
+ connection, possibly the result of a GET or POST request.</P>
 <H3><A NAME="10_62_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -6090,8 +6066,8 @@ while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) &gt; 0)
 }
 </PRE>
 <H3><A NAME="10_62_6">See Also</A></H3>
-<A HREF="#httpConnect"><CODE> httpConnect()</CODE></A>, <A HREF="#httpRead">
-<CODE>httpRead()</CODE></A>
+<A HREF="#httpConnect"> <CODE>httpConnect()</CODE></A>,<A HREF="#httpRead">
+ <CODE>httpRead()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippAddBoolean">ippAddBoolean()</A></H2>
@@ -6111,11 +6087,11 @@ ipp_attribute_t *ippAddBoolean(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_63_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_63_4">Description</A></H3>
-<P>The <CODE>ippAddBoolean()</CODE> function adds a single boolean 
-attribute value to the specified IPP request. </P>
+<P>The <CODE>ippAddBoolean()</CODE> function adds a single boolean
+ attribute value to the specified IPP request.</P>
 <H3><A NAME="10_63_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6125,15 +6101,15 @@ ipp_t *ipp;
 ippAddBoolean(ipp, IPP_TAG_OPERATION, &quot;my-jobs&quot;, 1);
 </PRE>
 <H3><A NAME="10_63_6">See Also</A></H3>
-<A HREF="#ippAddBooleans"><CODE> ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate">
-<CODE>ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>
-ippAddInteger()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
-ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
-</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
-<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBooleans"> <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate">
+ <CODE>ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>
+ippAddInteger()</CODE></A>,<A HREF="#ippAddIntegers"> <CODE>
+ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange"> <CODE>ippAddRange()</CODE>
+</A>,<A HREF="#ippAddRanges"> <CODE>ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution">
+ <CODE>ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6156,13 +6132,13 @@ ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_64_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_64_4">Description</A></H3>
-<P>The <CODE>ippAddBooleans()</CODE> function adds one or more boolean 
-attribute values to the specified IPP request. If the <CODE>values</CODE>
+<P>The <CODE>ippAddBooleans()</CODE> function adds one or more boolean
+ attribute values to the specified IPP request. If the <CODE>values</CODE>
  pointer is <CODE>NULL</CODE> then an array of <CODE>num_values</CODE>
- false values is created. </P>
+ false values is created.</P>
 <H3><A NAME="10_64_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6173,15 +6149,15 @@ char values[10];
 ippAddBooleans(ipp, IPP_TAG_OPERATION, &quot;some-attribute&quot;, 10, values);
 </PRE>
 <H3><A NAME="10_64_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddDate">
-<CODE>ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>
-ippAddInteger()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
-ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
-</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
-<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddDate">
+ <CODE>ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>
+ippAddInteger()</CODE></A>,<A HREF="#ippAddIntegers"> <CODE>
+ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange"> <CODE>ippAddRange()</CODE>
+</A>,<A HREF="#ippAddRanges"> <CODE>ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution">
+ <CODE>ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6202,11 +6178,11 @@ ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_65_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_65_4">Description</A></H3>
-<P>The <CODE>ippAddDate()</CODE> function adds a single date-time 
-attribute value to the specified IPP request. </P>
+<P>The <CODE>ippAddDate()</CODE> function adds a single date-time
+ attribute value to the specified IPP request.</P>
 <H3><A NAME="10_65_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6217,16 +6193,16 @@ ippAddDate(ipp, IPP_TAG_OPERATION, &quot;some-attribute&quot;,
            ippTimeToDate(time(NULL));
 </PRE>
 <H3><A NAME="10_65_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddInteger"><CODE>
-ippAddInteger()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
-ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
-</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
-<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
-ippAddStrings()</CODE></A>, <A HREF="#ippTimeToDate"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>
+ippAddInteger()</CODE></A>,<A HREF="#ippAddIntegers"> <CODE>
+ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange"> <CODE>ippAddRange()</CODE>
+</A>,<A HREF="#ippAddRanges"> <CODE>ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution">
+ <CODE>ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
+ippAddStrings()</CODE></A>,<A HREF="#ippTimeToDate"> <CODE>
 ippTimeToDate()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6243,18 +6219,18 @@ ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group,
 <TR><TH>Argument</TH><TH>Description</TH></TR>
 <TR><TD>ipp</TD><TD>The IPP request</TD></TR>
 <TR><TD>group</TD><TD>The IPP group</TD></TR>
-<TR><TD>tag</TD><TD>The type of integer value (IPP_TAG_INTEGER or 
-IPP_TAG_ENUM)</TD></TR>
+<TR><TD>tag</TD><TD>The type of integer value (IPP_TAG_INTEGER or
+ IPP_TAG_ENUM)</TD></TR>
 <TR><TD>name</TD><TD>The name of attribute</TD></TR>
 <TR><TD>value</TD><TD>The integer value</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_66_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_66_4">Description</A></H3>
-<P>The <CODE>ippAddInteger()</CODE> function adds a single integer 
-attribute value to the specified IPP request. </P>
+<P>The <CODE>ippAddInteger()</CODE> function adds a single integer
+ attribute value to the specified IPP request.</P>
 <H3><A NAME="10_66_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6264,15 +6240,15 @@ ipp_t *ipp;
 ippAddInteger(ipp, IPP_TAG_OPERATION, &quot;limit&quot;, 100);
 </PRE>
 <H3><A NAME="10_66_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
-ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
-</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
-<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddIntegers"> <CODE>
+ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange"> <CODE>ippAddRange()</CODE>
+</A>,<A HREF="#ippAddRanges"> <CODE>ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution">
+ <CODE>ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6289,21 +6265,21 @@ ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group,
 <TR><TH>Argument</TH><TH>Description</TH></TR>
 <TR><TD>ipp</TD><TD>The IPP request</TD></TR>
 <TR><TD>group</TD><TD>The IPP group</TD></TR>
-<TR><TD>tag</TD><TD>The type of integer value (IPP_TAG_INTEGER or 
-IPP_TAG_ENUM)</TD></TR>
+<TR><TD>tag</TD><TD>The type of integer value (IPP_TAG_INTEGER or
+ IPP_TAG_ENUM)</TD></TR>
 <TR><TD>name</TD><TD>The name of attribute</TD></TR>
 <TR><TD>num_values</TD><TD>The number of values</TD></TR>
 <TR><TD>values</TD><TD>The integer values</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_67_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_67_4">Description</A></H3>
-<P>The <CODE>ippAddIntegers()</CODE> function adds one or more integer 
-attribute values to the specified IPP request.  If the <CODE>values</CODE>
- pointer is <CODE>NULL</CODE> then an array of <CODE>num_values</CODE>
0 values is created. </P>
+<P>The <CODE>ippAddIntegers()</CODE> function adds one or more integer
+ attribute values to the specified IPP request. If the <CODE>values</CODE>
+ pointer is <CODE>NULL</CODE> then an array of <CODE>num_values</CODE> 0
values is created.</P>
 <H3><A NAME="10_67_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6314,15 +6290,15 @@ int values[100];
 ippAddIntegers(ipp, IPP_TAG_OPERATION, &quot;some-attribute&quot;, 100, values);
 </PRE>
 <H3><A NAME="10_67_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges">
-<CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
-ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddRange"> <CODE>ippAddRange()</CODE></A>,<A HREF="#ippAddRanges">
+ <CODE>ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution"> <CODE>
+ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6345,11 +6321,11 @@ ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_68_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_68_4">Description</A></H3>
-<P>The <CODE>ippAddRange()</CODE> function adds a single range 
-attribute value to the specified IPP request. </P>
+<P>The <CODE>ippAddRange()</CODE> function adds a single range attribute
+ value to the specified IPP request.</P>
 <H3><A NAME="10_68_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6359,15 +6335,15 @@ ipp_t *ipp;
 ippAddRange(ipp, IPP_TAG_OPERATION, &quot;page-ranges&quot;, 1, 10);
 </PRE>
 <H3><A NAME="10_68_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRanges">
-<CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
-ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddIntegers"> <CODE>ippAddIntegers()</CODE></A>,<A HREF="#ippAddRanges">
+ <CODE>ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution"> <CODE>
+ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6391,13 +6367,13 @@ ipp_attribute_t *ippAddRanges(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_69_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_69_4">Description</A></H3>
-<P>The <CODE>ippAddRanges()</CODE> function adds one or more range 
-attribute values to the specified IPP request. If the <CODE>values</CODE>
+<P>The <CODE>ippAddRanges()</CODE> function adds one or more range
+ attribute values to the specified IPP request. If the <CODE>values</CODE>
  pointer is <CODE>NULL</CODE> then an array of <CODE>num_values</CODE>
- 0,0 ranges is created. </P>
+ 0,0 ranges is created.</P>
 <H3><A NAME="10_69_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6409,15 +6385,15 @@ int highs[2];
 ippAddRanges(ipp, IPP_TAG_OPERATION, &quot;page-ranges&quot;, 2, lows, highs);
 </PRE>
 <H3><A NAME="10_69_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
-<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
-ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddIntegers"> <CODE>ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange">
+ <CODE>ippAddRange()</CODE></A>,<A HREF="#ippAddResolution"> <CODE>
+ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6441,11 +6417,11 @@ ipp_attribute_t *ippAddResolution(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_70_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_70_4">Description</A></H3>
-<P>The <CODE>ippAddResolution()</CODE> function adds a single 
-resolution attribute value to the specified IPP request. </P>
+<P>The <CODE>ippAddResolution()</CODE> function adds a single resolution
+ attribute value to the specified IPP request.</P>
 <H3><A NAME="10_70_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6456,15 +6432,15 @@ ippAddBoolean(ipp, IPP_TAG_OPERATION, &quot;printer-resolution&quot;,
               720, 720, IPP_RES_PER_INCH);
 </PRE>
 <H3><A NAME="10_70_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
-<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
-ippAddRanges()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddIntegers"> <CODE>ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange">
+ <CODE>ippAddRange()</CODE></A>,<A HREF="#ippAddRanges"> <CODE>
+ippAddRanges()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6490,13 +6466,13 @@ ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_71_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_71_4">Description</A></H3>
-<P>The <CODE>ippAddResolutions()</CODE> function adds one or more 
-resolution attribute values to the specified IPP request. If the <CODE>
+<P>The <CODE>ippAddResolutions()</CODE> function adds one or more
+ resolution attribute values to the specified IPP request. If the <CODE>
 values</CODE> pointer is <CODE>NULL</CODE> then an array of <CODE>
-num_values</CODE> 0,0 resolutions is created. </P>
+num_values</CODE> 0,0 resolutions is created.</P>
 <H3><A NAME="10_71_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6510,15 +6486,15 @@ ippAddBoolean(ipp, IPP_TAG_OPERATION, &quot;printer-resolutions-supported&quot;,
               5, xres, yres, units);
 </PRE>
 <H3><A NAME="10_71_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
-<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
-ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
-ippAddResolution()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddIntegers"> <CODE>ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange">
+ <CODE>ippAddRange()</CODE></A>,<A HREF="#ippAddRanges"> <CODE>
+ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution"> <CODE>
+ippAddResolution()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6535,11 +6511,11 @@ ipp_attribute_t *ippAddSeparator(ipp_t *ipp);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_72_3">Returns</A></H3>
-<P>A pointer to the new separator or NULL if the separator could not be 
-created. </P>
+<P>A pointer to the new separator or NULL if the separator could not be
+ created.</P>
 <H3><A NAME="10_72_4">Description</A></H3>
-<P>The <CODE>ippAddSeparator()</CODE> function adds a group separator 
-to the specified IPP request. </P>
+<P>The <CODE>ippAddSeparator()</CODE> function adds a group separator to
+ the specified IPP request.</P>
 <H3><A NAME="10_72_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6549,15 +6525,15 @@ ipp_t *ipp;
 ippAddSeparator(ipp);
 </PRE>
 <H3><A NAME="10_72_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
-<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
-ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
-ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddString"><CODE>
-ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddIntegers"> <CODE>ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange">
+ <CODE>ippAddRange()</CODE></A>,<A HREF="#ippAddRanges"> <CODE>
+ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution"> <CODE>
+ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddString"> <CODE>
+ippAddString()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6581,14 +6557,14 @@ ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_73_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_73_4">Description</A></H3>
-<P>The <CODE>ippAddString()</CODE> function adds a single string 
-attribute value to the specified IPP request. For <CODE>IPP_TAG_NAMELANG</CODE>
- and <CODE>IPP_TAG_TEXTLANG</CODE> strings, the charset value is 
-provided with the string to identify the string encoding used. 
-Otherwise the charset value is ignored. </P>
+<P>The <CODE>ippAddString()</CODE> function adds a single string
+ attribute value to the specified IPP request. For <CODE>
+IPP_TAG_NAMELANG</CODE> and <CODE>IPP_TAG_TEXTLANG</CODE> strings, the
+ charset value is provided with the string to identify the string
+ encoding used. Otherwise the charset value is ignored.</P>
 <H3><A NAME="10_73_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6599,15 +6575,15 @@ ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_NAME, &quot;job-name&quot;,
              NULL, &quot;abc123&quot;);
 </PRE>
 <H3><A NAME="10_73_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
-<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
-ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
-ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddIntegers"> <CODE>ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange">
+ <CODE>ippAddRange()</CODE></A>,<A HREF="#ippAddRanges"> <CODE>
+ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution"> <CODE>
+ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddStrings"> <CODE>
 ippAddStrings()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6633,16 +6609,16 @@ ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group,
 </TABLE>
 </CENTER>
 <H3><A NAME="10_74_3">Returns</A></H3>
-<P>A pointer to the new attribute or NULL if the attribute could not be 
-created. </P>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
 <H3><A NAME="10_74_4">Description</A></H3>
-<P>The <CODE>ippAddStrings()</CODE> function adds one or more string 
-attribute values to the specified IPP request. For <CODE>
-IPP_TAG_NAMELANG</CODE> and <CODE>IPP_TAG_TEXTLANG</CODE> strings, the 
-charset value is provided with the strings to identify the string 
-encoding used. Otherwise the charset value is ignored. If the <CODE>
+<P>The <CODE>ippAddStrings()</CODE> function adds one or more string
+ attribute values to the specified IPP request. For <CODE>
+IPP_TAG_NAMELANG</CODE> and <CODE>IPP_TAG_TEXTLANG</CODE> strings, the
+ charset value is provided with the strings to identify the string
+ encoding used. Otherwise the charset value is ignored. If the <CODE>
 values</CODE> pointer is <CODE>NULL</CODE> then an array of <CODE>
-num_values</CODE> NULL strings is created. </P>
+num_values</CODE> NULL strings is created.</P>
 <H3><A NAME="10_74_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6654,15 +6630,15 @@ ippAddStrings(ipp, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, &quot;attr-name&quot;,
               2, NULL, values);
 </PRE>
 <H3><A NAME="10_74_6">See Also</A></H3>
-<A HREF="#ippAddBoolean"><CODE> ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
-<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
-ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
-</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
-<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
-ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
-ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
-ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
-ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+<A HREF="#ippAddBoolean"> <CODE>ippAddBoolean()</CODE></A>,<A HREF="#ippAddBooleans">
+ <CODE>ippAddBooleans()</CODE></A>,<A HREF="#ippAddDate"> <CODE>
+ippAddDate()</CODE></A>,<A HREF="#ippAddInteger"> <CODE>ippAddInteger()</CODE>
+</A>,<A HREF="#ippAddIntegers"> <CODE>ippAddIntegers()</CODE></A>,<A HREF="#ippAddRange">
+ <CODE>ippAddRange()</CODE></A>,<A HREF="#ippAddRanges"> <CODE>
+ippAddRanges()</CODE></A>,<A HREF="#ippAddResolution"> <CODE>
+ippAddResolution()</CODE></A>,<A HREF="#ippAddResolutions"> <CODE>
+ippAddResolutions()</CODE></A>,<A HREF="#ippAddSeparator"> <CODE>
+ippAddSeparator()</CODE></A>,<A HREF="#ippAddString"> <CODE>
 ippAddString()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6679,10 +6655,10 @@ time_t ippDateToTime(const ipp_uchar_t date[11]);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_75_3">Returns</A></H3>
-<P>A UNIX time value. </P>
+<P>A UNIX time value.</P>
 <H3><A NAME="10_75_4">Description</A></H3>
-<P>The <CODE>ippDateToTime()</CODE> function converts an IPP date-time 
-value to a UNIX time value. </P>
+<P>The <CODE>ippDateToTime()</CODE> function converts an IPP date-time
+ value to a UNIX time value.</P>
 <H3><A NAME="10_75_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6692,7 +6668,7 @@ ipp_uchar_t date[11];
 printf(&quot;UNIX time is %d\n&quot;, ippDateToTime(date));
 </PRE>
 <H3><A NAME="10_75_6">See Also</A></H3>
-<A HREF="#ippTimeToDate"><CODE> ippTimeToDate()</CODE></A>
+<A HREF="#ippTimeToDate"> <CODE>ippTimeToDate()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippDelete">ippDelete()</A></H2>
@@ -6708,8 +6684,8 @@ void ippDelete(ipp_t *ipp);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_76_3">Description</A></H3>
-<P>The <CODE>ippDelete()</CODE> function deletes all memory used by an 
-IPP request or response. </P>
+<P>The <CODE>ippDelete()</CODE> function deletes all memory used by an
+ IPP request or response.</P>
 <H3><A NAME="10_76_4">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6719,7 +6695,7 @@ ipp_t *ipp;
 ippDelete(ipp);
 </PRE>
 <H3><A NAME="10_76_5">See Also</A></H3>
-<A HREF="#ippNew"><CODE> ippNew()</CODE></A>
+<A HREF="#ippNew"> <CODE>ippNew()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippFindAttribute">ippFindAttribute()</A></H2>
@@ -6734,19 +6710,19 @@ ipp_attribute_t *ippFindAttribute(ipp_t *ipp, const char *name, ipp_tag_t tag);
 <TR><TD>ipp</TD><TD>The IPP request or response</TD></TR>
 <TR><TD>name</TD><TD>The name of the attribute</TD></TR>
 <TR><TD>tag</TD><TD>The required value tag for the attribute or <CODE>
- IPP_TAG_ZERO</CODE> for any type of value.</TD></TR>
+IPP_TAG_ZERO</CODE> for any type of value.</TD></TR>
 </TABLE>
 </CENTER>
 <H3><A NAME="10_77_3">Returns</A></H3>
 <P>A pointer to the first occurrence of the requested attribute, or <CODE>
-NULL</CODE> if it was not found. </P>
+NULL</CODE> if it was not found.</P>
 <H3><A NAME="10_77_4">Description</A></H3>
-<P><CODE>ippFindAttribute()</CODE> finds the first occurrence of the 
-named attribute. The <CODE>tag</CODE> parameter restricts the search to 
-a specific value type - use <CODE>IPP_TAG_ZERO</CODE> to find any value 
-with the name. </P>
+<P><CODE>ippFindAttribute()</CODE> finds the first occurrence of the
+ named attribute. The <CODE>tag</CODE> parameter restricts the search to
+ a specific value type - use <CODE>IPP_TAG_ZERO</CODE> to find any value
+ with the name.</P>
 <P>The value tags <CODE>IPP_TAG_NAME</CODE> and <CODE>IPP_TAG_TEXT</CODE>
- match the name/text values with or without the language code. </P>
+ match the name/text values with or without the language code.</P>
 <H3><A NAME="10_77_5">Example</A></H3>
 <PRE>
 ipp_attribute_t *attr;
@@ -6754,9 +6730,9 @@ ipp_attribute_t *attr;
 attr = ippFindAttribute(response, &quot;printer-state-message&quot;, IPP_TAG_TEXT);
 </PRE>
 <H3><A NAME="10_77_6">See Also</A></H3>
-<A HREF="#cupsDoFileRequest"><CODE> cupsDoFileRequest()</CODE></A>, <A HREF="#cupsDoRequest">
-<CODE>cupsDoRequest()</CODE></A>, <A HREF="#ippDelete"><CODE>ippDelete()</CODE>
-</A>, <A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+<A HREF="#cupsDoFileRequest"> <CODE>cupsDoFileRequest()</CODE></A>,<A HREF="#cupsDoRequest">
+ <CODE>cupsDoRequest()</CODE></A>,<A HREF="#ippDelete"> <CODE>
+ippDelete()</CODE></A>,<A HREF="#ippNew"> <CODE>ippNew()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippLength">ippLength()</A></H2>
@@ -6772,16 +6748,16 @@ int ippLength(ipp_t *ipp);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_78_3">Returns</A></H3>
-<P>The total encoded length of the IPP request or response in bytes. </P>
+<P>The total encoded length of the IPP request or response in bytes.</P>
 <H3><A NAME="10_78_4">Description</A></H3>
-<P><CODE>ippLength()</CODE> returns the length of the IPP request or 
-response in bytes. </P>
+<P><CODE>ippLength()</CODE> returns the length of the IPP request or
+ response in bytes.</P>
 <H3><A NAME="10_78_5">Example</A></H3>
 <PRE>
 printf(&quot;The length of the response is %d bytes.\n&quot;, ippLength(response));
 </PRE>
 <H3><A NAME="10_78_6">See Also</A></H3>
-<A HREF="#ippDelete"><CODE> ippDelete()</CODE></A>, <A HREF="#ippNew"><CODE>
+<A HREF="#ippDelete"> <CODE>ippDelete()</CODE></A>,<A HREF="#ippNew"> <CODE>
 ippNew()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -6791,10 +6767,10 @@ ippNew()</CODE></A>
 ipp_t *ippNew(void);
 </PRE>
 <H3><A NAME="10_79_2">Returns</A></H3>
-<P>A pointer to a new IPP request or response. </P>
+<P>A pointer to a new IPP request or response.</P>
 <H3><A NAME="10_79_3">Description</A></H3>
-<P>The <CODE>ippNew()</CODE> function creates a new IPP request or 
-response. </P>
+<P>The <CODE>ippNew()</CODE> function creates a new IPP request or
+ response.</P>
 <H3><A NAME="10_79_4">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6804,7 +6780,7 @@ ipp_t *ipp;
 ipp = ippNew();
 </PRE>
 <H3><A NAME="10_79_5">See Also</A></H3>
-<A HREF="#ippDelete"><CODE> ippDelete()</CODE></A>
+<A HREF="#ippDelete"> <CODE>ippDelete()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippPort">ippPort()</A></H2>
@@ -6813,10 +6789,10 @@ ipp = ippNew();
 int ippPort(void);
 </PRE>
 <H3><A NAME="10_80_2">Returns</A></H3>
-<P>The default TCP/IP port number for IPP requests. </P>
+<P>The default TCP/IP port number for IPP requests.</P>
 <H3><A NAME="10_80_3">Description</A></H3>
-<P>The <CODE>ippPort()</CODE> function returns the default IPP port 
-number for requests. </P>
+<P>The <CODE>ippPort()</CODE> function returns the default IPP port
+ number for requests.</P>
 <H3><A NAME="10_80_4">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -6827,8 +6803,8 @@ http_t *http;
 http = httpConnect(cupsServer(), ippPort());
 </PRE>
 <H3><A NAME="10_80_5">See Also</A></H3>
-<A HREF="#cupsServer"><CODE> cupsServer()</CODE></A>, <A HREF="#ippSetPort">
-<CODE>ippSetPort()</CODE></A>
+<A HREF="#cupsServer"> <CODE>cupsServer()</CODE></A>,<A HREF="#ippSetPort">
+ <CODE>ippSetPort()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippRead">ippRead()</A></H2>
@@ -6845,12 +6821,12 @@ ipp_state_t ippRead(http_t *http, ipp_t *ipp);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_81_3">Returns</A></H3>
-<P>The current read state. </P>
+<P>The current read state.</P>
 <H3><A NAME="10_81_4">Description</A></H3>
-<P>The <CODE>ippRead()</CODE> function reads IPP attributes from the 
-specified HTTP connection. Programs should continue calling <CODE>
+<P>The <CODE>ippRead()</CODE> function reads IPP attributes from the
+ specified HTTP connection. Programs should continue calling <CODE>
 ippRead()</CODE> until <CODE>IPP_ERROR</CODE> or <CODE>IPP_DATA</CODE>
- is returned. </P>
+ is returned.</P>
 <H3><A NAME="10_81_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -6872,7 +6848,7 @@ if (status == IPP_DATA)
 }
 </PRE>
 <H3><A NAME="10_81_6">See Also</A></H3>
-<A HREF="#ippWrite"><CODE> ippWrite()</CODE></A>
+<A HREF="#ippWrite"> <CODE>ippWrite()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippSetPort">ippSetPort()</A></H2>
@@ -6889,8 +6865,8 @@ ippSetPort(int port);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_82_3">Description</A></H3>
-<P>The <CODE>ippSetPort()</CODE> function sets the default IPP port 
-number for requests. </P>
+<P>The <CODE>ippSetPort()</CODE> function sets the default IPP port
+ number for requests.</P>
 <H3><A NAME="10_82_4">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -6901,7 +6877,7 @@ number for requests. </P>
 ippSetPort(8631);
 </PRE>
 <H3><A NAME="10_82_5">See Also</A></H3>
-<A HREF="#ippPort"><CODE> ippPort()</CODE></A>
+<A HREF="#ippPort"> <CODE>ippPort()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippTimeToDate">ippTimeToDate()</A></H2>
@@ -6917,10 +6893,10 @@ ipp_uchar_t *ippTimeToDate(time_t time);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_83_3">Returns</A></H3>
-<P>A static pointer to an IPP date-time value. </P>
+<P>A static pointer to an IPP date-time value.</P>
 <H3><A NAME="10_83_4">Description</A></H3>
-<P>The <CODE>ippTimeToDate()</CODE> function converts a UNIX time to an 
-IPP date-time value. </P>
+<P>The <CODE>ippTimeToDate()</CODE> function converts a UNIX time to an
+ IPP date-time value.</P>
 <H3><A NAME="10_83_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ipp.h&gt;
@@ -6930,7 +6906,7 @@ ipp_uchar_t *date;
 date = ippTimeToDate(time(NULL));
 </PRE>
 <H3><A NAME="10_83_6">See Also</A></H3>
-<A HREF="#ippDateToTime"><CODE> ippDateToTime()</CODE></A>
+<A HREF="#ippDateToTime"> <CODE>ippDateToTime()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ippWrite">ippWrite()</A></H2>
@@ -6947,12 +6923,12 @@ ipp_state_t ippWrite(http_t *http, ipp_t *ipp);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_84_3">Returns</A></H3>
-<P>The current write state. </P>
+<P>The current write state.</P>
 <H3><A NAME="10_84_4">Description</A></H3>
-<P>The <CODE>ippWrite()</CODE> function writes IPP attributes to the 
-specified HTTP connection. Programs should continue calling <CODE>
+<P>The <CODE>ippWrite()</CODE> function writes IPP attributes to the
+ specified HTTP connection. Programs should continue calling <CODE>
 ippWrite()</CODE> until <CODE>IPP_ERROR</CODE> or <CODE>IPP_DATA</CODE>
- is returned. </P>
+ is returned.</P>
 <H3><A NAME="10_84_5">Example</A></H3>
 <PRE>
 #include &lt;cups/http.h&gt;
@@ -6975,7 +6951,7 @@ if (status == IPP_DATA)
 }
 </PRE>
 <H3><A NAME="10_84_6">See Also</A></H3>
-<A HREF="#ippRead"><CODE> ippRead()</CODE></A>
+<A HREF="#ippRead"> <CODE>ippRead()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdClose">ppdClose()</A></H2>
@@ -6991,8 +6967,8 @@ void ppdClose(ppd_file_t *ppd);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_85_3">Description</A></H3>
-<P>The <CODE>ppdClose()</CODE> function frees all memory associated 
-with the PPD file. </P>
+<P>The <CODE>ppdClose()</CODE> function frees all memory associated with
+ the PPD file.</P>
 <H3><A NAME="10_85_4">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7002,8 +6978,8 @@ ppd_file_t *ppd;
 ppdClose(ppd);
 </PRE>
 <H3><A NAME="10_85_5">See Also</A></H3>
-<A HREF="#ppdOpen"><CODE> ppdOpen()</CODE></A>, <A HREF="#ppdOpenFd"><CODE>
-ppdOpenFd()</CODE></A>, <A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE>
+<A HREF="#ppdOpen"> <CODE>ppdOpen()</CODE></A>,<A HREF="#ppdOpenFd"> <CODE>
+ppdOpenFd()</CODE></A>,<A HREF="#ppdOpenFile"> <CODE>ppdOpenFile()</CODE>
 </A>
 <!-- NEW PAGE -->
 
@@ -7020,10 +6996,10 @@ int ppdConflicts(ppd_file_t *ppd);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_86_3">Returns</A></H3>
-<P>The number of option conflicts in the file. </P>
+<P>The number of option conflicts in the file.</P>
 <H3><A NAME="10_86_4">Description</A></H3>
-<P>The <CODE>ppdConflicts()</CODE> function returns the number of 
-conflicts with the currently selected options. </P>
+<P>The <CODE>ppdConflicts()</CODE> function returns the number of
+ conflicts with the currently selected options.</P>
 <H3><A NAME="10_86_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7033,9 +7009,9 @@ ppd_file_t *ppd;
 printf(&quot;%d conflicts\n&quot;, ppdConflicts(ppd));
 </PRE>
 <H3><A NAME="10_86_6">See Also</A></H3>
-<A HREF="#cupsMarkOptions"><CODE> cupsMarkOptions()</CODE></A>, <A HREF="#ppdIsMarked">
-<CODE>ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
-ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+<A HREF="#cupsMarkOptions"> <CODE>cupsMarkOptions()</CODE></A>,<A HREF="#ppdIsMarked">
+ <CODE>ppdIsMarked()</CODE></A>,<A HREF="#ppdMarkDefaults"> <CODE>
+ppdMarkDefaults()</CODE></A>,<A HREF="#ppdMarkOption"> <CODE>
 ppdMarkOption()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -7054,10 +7030,10 @@ int ppdEmit(ppd_file_t *ppd, FILE *file, ppd_section_t section);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_87_3">Returns</A></H3>
-<P>0 on success, -1 on error. </P>
+<P>0 on success, -1 on error.</P>
 <H3><A NAME="10_87_4">Description</A></H3>
-<P>The <CODE>ppdEmit()</CODE> function sends printer-specific option 
-commands to the specified file. </P>
+<P>The <CODE>ppdEmit()</CODE> function sends printer-specific option
+ commands to the specified file.</P>
 <H3><A NAME="10_87_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7067,7 +7043,7 @@ ppd_file_t *ppd;
 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
 </PRE>
 <H3><A NAME="10_87_6">See Also</A></H3>
-<A HREF="#ppdEmitFd"><CODE> ppdEmitFd()</CODE></A>
+<A HREF="#ppdEmitFd"> <CODE>ppdEmitFd()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdEmitFd">ppdEmitFd()</A></H2>
@@ -7085,10 +7061,10 @@ int ppdEmitFd(ppd_file_t *ppd, int fd, ppd_section_t section);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_88_3">Returns</A></H3>
-<P>0 on success, -1 on error. </P>
+<P>0 on success, -1 on error.</P>
 <H3><A NAME="10_88_4">Description</A></H3>
-<P>The <CODE>ppdEmitFd()</CODE> function sends printer-specific option 
-commands to the specified file descriptor. </P>
+<P>The <CODE>ppdEmitFd()</CODE> function sends printer-specific option
+ commands to the specified file descriptor.</P>
 <H3><A NAME="10_88_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7098,7 +7074,7 @@ ppd_file_t *ppd;
 ppdEmitFd(ppd, 1, PPD_ORDER_PAGE);
 </PRE>
 <H3><A NAME="10_88_6">See Also</A></H3>
-<A HREF="#ppdEmit"><CODE> ppdEmit()</CODE></A>
+<A HREF="#ppdEmit"> <CODE>ppdEmit()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdFindChoice">ppdFindChoice()</A></H2>
@@ -7115,10 +7091,10 @@ ppd_choice_t *ppdFindChoice(ppd_option_t *option, const char *choice);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_89_3">Returns</A></H3>
-<P>A pointer to the choice data or NULL if the choice does not exist. </P>
+<P>A pointer to the choice data or NULL if the choice does not exist.</P>
 <H3><A NAME="10_89_4">Description</A></H3>
-<P>The <CODE>ppdFindChoice()</CODE> function returns a pointer to the 
-choice data for the specified option. </P>
+<P>The <CODE>ppdFindChoice()</CODE> function returns a pointer to the
+ choice data for the specified option.</P>
 <H3><A NAME="10_89_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7131,8 +7107,8 @@ option = ppdFindOption(ppd, &quot;PageSize&quot;);
 choice = ppdFindChoice(option, &quot;Letter&quot;);
 </PRE>
 <H3><A NAME="10_89_6">See Also</A></H3>
-<A HREF="#ppdFindMarkedChoice"><CODE> ppdFindMarkedChoice()</CODE></A>, <A
-HREF="#ppdFindOption"><CODE>ppdFindOption()</CODE></A>
+<A HREF="#ppdFindMarkedChoice"> <CODE>ppdFindMarkedChoice()</CODE></A>,<A
+HREF="#ppdFindOption"> <CODE>ppdFindOption()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdFindMarkedChoice">ppdFindMarkedChoice()</A></H2>
@@ -7149,11 +7125,11 @@ ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_90_3">Returns</A></H3>
-<P>A pointer to the choice data or NULL if the choice does not exist or 
-is not marked. </P>
+<P>A pointer to the choice data or NULL if the choice does not exist or
+ is not marked.</P>
 <H3><A NAME="10_90_4">Description</A></H3>
-<P>The <CODE>ppdFindMarkedChoice()</CODE> function returns a pointer to 
-the marked choice data for the specified option. </P>
+<P>The <CODE>ppdFindMarkedChoice()</CODE> function returns a pointer to
+ the marked choice data for the specified option.</P>
 <H3><A NAME="10_90_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7164,8 +7140,8 @@ ppd_choice_t *choice;
 choice = ppdFindMarkedChoice(ppd, &quot;PageSize&quot;);
 </PRE>
 <H3><A NAME="10_90_6">See Also</A></H3>
-<A HREF="#ppdFindChoice"><CODE> ppdFindChoice()</CODE></A>, <A HREF="#ppdFindOption">
-<CODE>ppdFindOption()</CODE></A>
+<A HREF="#ppdFindChoice"> <CODE>ppdFindChoice()</CODE></A>,<A HREF="#ppdFindOption">
+ <CODE>ppdFindOption()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdFindOption">ppdFindOption()</A></H2>
@@ -7182,10 +7158,10 @@ ppd_option_t *ppdFindOption(ppd_file_t *ppd, const char *keyword);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_91_3">Returns</A></H3>
-<P>A pointer to the option data or NULL if the option does not exist. </P>
+<P>A pointer to the option data or NULL if the option does not exist.</P>
 <H3><A NAME="10_91_4">Description</A></H3>
-<P>The <CODE>ppdFindOption()</CODE> function returns a pointer to the 
-option data for the specified option. </P>
+<P>The <CODE>ppdFindOption()</CODE> function returns a pointer to the
+ option data for the specified option.</P>
 <H3><A NAME="10_91_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7196,8 +7172,8 @@ ppd_option_t *option;
 option = ppdFindOption(ppd, &quot;PageSize&quot;);
 </PRE>
 <H3><A NAME="10_91_6">See Also</A></H3>
-<A HREF="#ppdFindChoice"><CODE> ppdFindChoice()</CODE></A>, <A HREF="#ppdFindMarkedChoice">
-<CODE>ppdFindMarkedChoice()</CODE></A>
+<A HREF="#ppdFindChoice"> <CODE>ppdFindChoice()</CODE></A>,<A HREF="#ppdFindMarkedChoice">
+ <CODE>ppdFindMarkedChoice()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdIsMarked">ppdIsMarked()</A></H2>
@@ -7215,10 +7191,10 @@ int ppdIsMarked(ppd_file_t *ppd, const char *keyword, char char *choice);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_92_3">Returns</A></H3>
-<P>1 if the choice is marked, 0 otherwise. </P>
+<P>1 if the choice is marked, 0 otherwise.</P>
 <H3><A NAME="10_92_4">Description</A></H3>
-<P>The <CODE>ppdIsMarked()</CODE> function returns whether or not the 
-specified option choice is marked. </P>
+<P>The <CODE>ppdIsMarked()</CODE> function returns whether or not the
+ specified option choice is marked.</P>
 <H3><A NAME="10_92_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7229,10 +7205,10 @@ printf(&quot;Letter size %s selected.\n&quot;,
        ppdIsMarked(ppd, &quot;PageSize&quot;, &quot;Letter&quot;) ? &quot;is&quot; : &quot;is not&quot;);
 </PRE>
 <H3><A NAME="10_92_6">See Also</A></H3>
-<A HREF="#cupsMarkOptions"><CODE> cupsMarkOptions()</CODE></A>, <A HREF="#ppdConflicts">
-<CODE>ppdConflicts()</CODE></A>, <A HREF="#ppdIsMarked"><CODE>
-ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
-ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+<A HREF="#cupsMarkOptions"> <CODE>cupsMarkOptions()</CODE></A>,<A HREF="#ppdConflicts">
+ <CODE>ppdConflicts()</CODE></A>,<A HREF="#ppdIsMarked"> <CODE>
+ppdIsMarked()</CODE></A>,<A HREF="#ppdMarkDefaults"> <CODE>
+ppdMarkDefaults()</CODE></A>,<A HREF="#ppdMarkOption"> <CODE>
 ppdMarkOption()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -7249,8 +7225,8 @@ void ppdMarkDefaults(ppd_file_t *ppd);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_93_3">Description</A></H3>
-<P>The <CODE>ppdMarkDefaults()</CODE> function marks all of the default 
-choices in the PPD file. </P>
+<P>The <CODE>ppdMarkDefaults()</CODE> function marks all of the default
+ choices in the PPD file.</P>
 <H3><A NAME="10_93_4">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7260,10 +7236,10 @@ ppd_file_t *ppd;
 ppdMarkDefaults(ppd);
 </PRE>
 <H3><A NAME="10_93_5">See Also</A></H3>
-<A HREF="#cupsMarkOptions"><CODE> cupsMarkOptions()</CODE></A>, <A HREF="#ppdConflicts">
-<CODE>ppdConflicts()</CODE></A>, <A HREF="#ppdIsMarked"><CODE>
-ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
-ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+<A HREF="#cupsMarkOptions"> <CODE>cupsMarkOptions()</CODE></A>,<A HREF="#ppdConflicts">
+ <CODE>ppdConflicts()</CODE></A>,<A HREF="#ppdIsMarked"> <CODE>
+ppdIsMarked()</CODE></A>,<A HREF="#ppdMarkDefaults"> <CODE>
+ppdMarkDefaults()</CODE></A>,<A HREF="#ppdMarkOption"> <CODE>
 ppdMarkOption()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -7282,10 +7258,10 @@ int ppdMarkOption(ppd_file_t *ppd, const char *keyword, const char *choice);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_94_3">Returns</A></H3>
-<P>The number of conflicts in the PPD file. </P>
+<P>The number of conflicts in the PPD file.</P>
 <H3><A NAME="10_94_4">Description</A></H3>
-<P>The <CODE>ppdMarkOption()</CODE> function marks the specified option 
-choice. </P>
+<P>The <CODE>ppdMarkOption()</CODE> function marks the specified option
+ choice.</P>
 <H3><A NAME="10_94_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7295,10 +7271,10 @@ ppd_file_t *ppd;
 ppdMarkOption(ppd, &quot;PageSize&quot;, &quot;Letter&quot;);
 </PRE>
 <H3><A NAME="10_94_6">See Also</A></H3>
-<A HREF="#cupsMarkOptions"><CODE> cupsMarkOptions()</CODE></A>, <A HREF="#ppdConflicts">
-<CODE>ppdConflicts()</CODE></A>, <A HREF="#ppdIsMarked"><CODE>
-ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
-ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+<A HREF="#cupsMarkOptions"> <CODE>cupsMarkOptions()</CODE></A>,<A HREF="#ppdConflicts">
+ <CODE>ppdConflicts()</CODE></A>,<A HREF="#ppdIsMarked"> <CODE>
+ppdIsMarked()</CODE></A>,<A HREF="#ppdMarkDefaults"> <CODE>
+ppdMarkDefaults()</CODE></A>,<A HREF="#ppdMarkOption"> <CODE>
 ppdMarkOption()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -7315,11 +7291,11 @@ ppd_file_t *ppdOpen(FILE *file);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_95_3">Returns</A></H3>
-<P>A pointer to a PPD file structure or NULL if the PPD file could not 
-be read. </P>
+<P>A pointer to a PPD file structure or NULL if the PPD file could not
+ be read.</P>
 <H3><A NAME="10_95_4">Description</A></H3>
-<P>The <CODE>ppdOpen()</CODE> function reads a PPD file from the 
-specified file into memory. </P>
+<P>The <CODE>ppdOpen()</CODE> function reads a PPD file from the
+ specified file into memory.</P>
 <H3><A NAME="10_95_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7332,8 +7308,8 @@ ppd = ppdOpen(file);
 fclose(file);
 </PRE>
 <H3><A NAME="10_95_6">See Also</A></H3>
-<A HREF="#ppdClose"><CODE> ppdClose()</CODE></A>, <A HREF="#ppdOpenFd"><CODE>
-ppdOpenFd()</CODE></A>, <A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE>
+<A HREF="#ppdClose"> <CODE>ppdClose()</CODE></A>,<A HREF="#ppdOpenFd"> <CODE>
+ppdOpenFd()</CODE></A>,<A HREF="#ppdOpenFile"> <CODE>ppdOpenFile()</CODE>
 </A>
 <!-- NEW PAGE -->
 
@@ -7350,11 +7326,11 @@ ppd_file_t *ppdOpenFd(int fd);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_96_3">Returns</A></H3>
-<P>A pointer to a PPD file structure or NULL if the PPD file could not 
-be read. </P>
+<P>A pointer to a PPD file structure or NULL if the PPD file could not
+ be read.</P>
 <H3><A NAME="10_96_4">Description</A></H3>
-<P>The <CODE>ppdOpenFd()</CODE> function reads a PPD file from the 
-specified file descriptor into memory. </P>
+<P>The <CODE>ppdOpenFd()</CODE> function reads a PPD file from the
+ specified file descriptor into memory.</P>
 <H3><A NAME="10_96_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7367,11 +7343,10 @@ ppd = ppdOpenFd(fd);
 close(fd);
 </PRE>
 <H3><A NAME="10_96_6">See Also</A></H3>
-<A HREF="#ppdClose"><CODE> ppdClose()</CODE></A>, <A HREF="#ppdOpen"><CODE>
-ppdOpen()</CODE></A>, <A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE></A>
+<A HREF="#ppdClose"> <CODE>ppdClose()</CODE></A>,<A HREF="#ppdOpen"> <CODE>
+ppdOpen()</CODE></A>,<A HREF="#ppdOpenFile"> <CODE>ppdOpenFile()</CODE></A>
 <!-- NEW PAGE -->
 
-
 <H2><A NAME="ppdOpenFile">ppdOpenFile()</A></H2>
 <H3><A NAME="10_97_1">Usage</A></H3>
 <PRE>
@@ -7385,11 +7360,11 @@ ppd_file_t *ppdOpenFile(const char *filename);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_97_3">Returns</A></H3>
-<P>A pointer to a PPD file structure or NULL if the PPD file could not 
-be read. </P>
+<P>A pointer to a PPD file structure or NULL if the PPD file could not
+ be read.</P>
 <H3><A NAME="10_97_4">Description</A></H3>
-<P>The <CODE>ppdOpenFile()</CODE> function reads a PPD file from the 
-named file into memory. </P>
+<P>The <CODE>ppdOpenFile()</CODE> function reads a PPD file from the
+ named file into memory.</P>
 <H3><A NAME="10_97_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7399,8 +7374,8 @@ ppd_file_t *ppd;
 ppd = ppdOpenFile(&quot;filename.ppd&quot;);
 </PRE>
 <H3><A NAME="10_97_6">See Also</A></H3>
-<A HREF="#ppdClose"><CODE> ppdClose()</CODE></A>, <A HREF="#ppdOpen"><CODE>
-ppdOpen()</CODE></A>, <A HREF="#ppdOpenFd"><CODE>ppdOpenFd()</CODE></A>
+<A HREF="#ppdClose"> <CODE>ppdClose()</CODE></A>,<A HREF="#ppdOpen"> <CODE>
+ppdOpen()</CODE></A>,<A HREF="#ppdOpenFd"> <CODE>ppdOpenFd()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdPageLength">ppdPageLength()</A></H2>
@@ -7417,11 +7392,11 @@ float ppdPageLength(ppd_file_t *ppd, const char *name);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_98_3">Returns</A></H3>
-<P>The length of the specified page size in points or 0 if the page 
-size does not exist. </P>
+<P>The length of the specified page size in points or 0 if the page size
+ does not exist.</P>
 <H3><A NAME="10_98_4">Description</A></H3>
-<P>The <CODE>ppdPageLength()</CODE> function returns the page length of 
-the specified page size. </P>
+<P>The <CODE>ppdPageLength()</CODE> function returns the page length of
+ the specified page size.</P>
 <H3><A NAME="10_98_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7431,8 +7406,8 @@ ppd_file_t *ppd;
 printf(&quot;Length = %.0f\n&quot;, ppdPageLength(ppd, &quot;Letter&quot;));
 </PRE>
 <H3><A NAME="10_98_6">See Also</A></H3>
-<A HREF="#ppdPageLength"><CODE> ppdPageLength()</CODE></A>, <A HREF="#ppdPageSize">
-<CODE>ppdPageSize()</CODE></A>, <A HREF="#ppdPageWidth"><CODE>
+<A HREF="#ppdPageLength"> <CODE>ppdPageLength()</CODE></A>,<A HREF="#ppdPageSize">
+ <CODE>ppdPageSize()</CODE></A>,<A HREF="#ppdPageWidth"> <CODE>
 ppdPageWidth()</CODE></A>
 <!-- NEW PAGE -->
 
@@ -7450,11 +7425,11 @@ ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_99_3">Returns</A></H3>
-<P>A pointer to the page size record of the specified page size in 
-points or NULL if the page size does not exist. </P>
+<P>A pointer to the page size record of the specified page size in
+ points or NULL if the page size does not exist.</P>
 <H3><A NAME="10_99_4">Description</A></H3>
-<P>The <CODE>ppdPageSize()</CODE> function returns the page size record 
-for the specified page size. </P>
+<P>The <CODE>ppdPageSize()</CODE> function returns the page size record
+ for the specified page size.</P>
 <H3><A NAME="10_99_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7474,8 +7449,8 @@ if (size != NULL)
 }
 </PRE>
 <H3><A NAME="10_99_6">See Also</A></H3>
-<A HREF="#ppdPageLength"><CODE> ppdPageLength()</CODE></A>, <A HREF="#ppdPageWidth">
-<CODE>ppdPageWidth()</CODE></A>
+<A HREF="#ppdPageLength"> <CODE>ppdPageLength()</CODE></A>,<A HREF="#ppdPageWidth">
+ <CODE>ppdPageWidth()</CODE></A>
 <!-- NEW PAGE -->
 
 <H2><A NAME="ppdPageWidth">ppdPageWidth()</A></H2>
@@ -7492,11 +7467,11 @@ float ppdPageWidth(ppd_file_t *ppd, const char *name);
 </TABLE>
 </CENTER>
 <H3><A NAME="10_100_3">Returns</A></H3>
-<P>The width of the specified page size in points or 0 if the page size 
-does not exist. </P>
+<P>The width of the specified page size in points or 0 if the page size
+ does not exist.</P>
 <H3><A NAME="10_100_4">Description</A></H3>
-<P>The <CODE>ppdPageWidth()</CODE> function returns the page width of 
-the specified page size. </P>
+<P>The <CODE>ppdPageWidth()</CODE> function returns the page width of
+ the specified page size.</P>
 <H3><A NAME="10_100_5">Example</A></H3>
 <PRE>
 #include &lt;cups/ppd.h&gt;
@@ -7506,6 +7481,6 @@ ppd_file_t *ppd;
 printf(&quot;Width = %.0f\n&quot;, ppdPageWidth(ppd, &quot;Letter&quot;));
 </PRE>
 <H3><A NAME="10_100_6">See Also</A></H3>
-<A HREF="#ppdPageLength"><CODE> ppdPageLength()</CODE></A>, <A HREF="#ppdPageSize">
-<CODE>ppdPageSize()</CODE></A></BODY>
+<A HREF="#ppdPageLength"> <CODE>ppdPageLength()</CODE></A>,<A HREF="#ppdPageSize">
+ <CODE>ppdPageSize()</CODE></A></BODY>
 </HTML>
index 672132355ad5b3883ce9a4a0d78914cf236260ee..50d39b1efbfc822e89b1bb0257d06eb1a66faf46 100644 (file)
Binary files a/doc/spm.pdf and b/doc/spm.pdf differ
index 55bf517bb376af1b20f14fb0ff9cd92ba83b2cdb..94dbb01262f4d5d56d970f75eb088b7c68b70854 100644 (file)
@@ -1,7 +1,7 @@
 <HTML>
 <HEAD>
        <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2001, All Rights Reserved">
-       <META NAME="DOCNUMBER" CONTENT="CUPS-SPM-1.1.7">
+       <META NAME="DOCNUMBER" CONTENT="CUPS-SPM-1.2.0">
        <META NAME="Author" CONTENT="Easy Software Products">
        <TITLE>CUPS Software Programmers Manual</TITLE>
 </HEAD>
@@ -11,7 +11,7 @@
 
 <P>This software programmers manual provides software
 programming information for the Common UNIX Printing System
-("CUPS") Version 1.1.7.
+("CUPS") Version 1.2.0.
 
 <EMBED SRC="system-overview.shtml">
 
index 3a320e8fe7d0f92eb7c847ad42bcf4c478fc10e6..5845b01a5fbb738ae1f4b9a1248bac0e5a8bd255 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Performance Specification</TITLE>
+<TITLE>CUPS Software Performance Specification</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-SPS-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Performance Specification</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Performance Specification</H1></A><BR>
 CUPS-SPS-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -52,30 +52,30 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
-<P>This software performance specification provides an analysis of the 
-memory, disk, and processor utilitization of each program in the Common 
-UNIX Printing System (&quot;CUPS&quot;) Version 1.1.</P>
-<P>For the purposes of comparison, all figures are for the Linux Intel 
-platform. Memory utilization on other platforms should be similar. </P>
+<P>This software performance specification provides an analysis of the
+ memory, disk, and processor utilitization of each program in the Common
+ UNIX Printing System (&quot;CUPS&quot;) Version 1.1.</P>
+<P>For the purposes of comparison, all figures are for the Linux Intel
+ platform. Memory utilization on other platforms should be similar.</P>
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
-<P>This software performance specification is organized into the 
-following sections:</P>
+<P>This software performance specification is organized into the
+ following sections:</P>
 <UL>
 <LI>1 - Scope</LI>
 <LI>2 - References</LI>
@@ -85,72 +85,72 @@ following sections:</P>
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
+<P>The following CUPS documentation is referenced by this document:</P>
 <UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 Programs</A></H1>
-<P>The following table describes the average memory, disk, and CPU 
-usage of each program in CUPS. </P>
-<P>The base memory column shows the initial memory requirements for 
-each program, including any shared libraries that are provided by CUPS. </P>
-<P>The max memory column shows the maximum amount of memory that will 
-be used by the program based upon the default configuration settings 
-supplied with CUPS. </P>
-<P>The temp files column indicates whether any temporary files are 
-created. </P>
-<P>The CPU usage column specifies a relative CPU usage by the program 
-under normal conditions, either low, medium, or high.  Low usage 
-indicates that the program will never use more than 33% of the 
-available CPU time. Medium usage indicates the program will use as much 
-as 66% of the available CPU time. High usage indicates the program uses 
-66% or more of the available CPU time. 
+<P>The following table describes the average memory, disk, and CPU usage
+ of each program in CUPS.</P>
+<P>The base memory column shows the initial memory requirements for each
+ program, including any shared libraries that are provided by CUPS.</P>
+<P>The max memory column shows the maximum amount of memory that will be
+ used by the program based upon the default configuration settings
+ supplied with CUPS.</P>
+<P>The temp files column indicates whether any temporary files are
+ created.</P>
+<P>The CPU usage column specifies a relative CPU usage by the program
+ under normal conditions, either low, medium, or high. Low usage
+ indicates that the program will never use more than 33% of the
+ available CPU time. Medium usage indicates the program will use as much
+ as 66% of the available CPU time. High usage indicates the program uses
+ 66% or more of the available CPU time.
 <CENTER>
 <TABLE BORDER="1" WIDTH="80%">
 <TR><TH COLSPAN="3">Backends</TH></TR>
-<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp 
-Files</TH><TH>CPU Usage</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
 <TR><TD>ipp</TD><TD>91k</TD><TD>256k</TD><TD>Up to size of print file</TD><TD>
 Low</TD></TR>
 <TR><TD>lpd</TD><TD>89k</TD><TD>89k</TD><TD>Up to size of print file</TD><TD>
 Low</TD></TR>
-<TR><TD>parallel</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print 
-file</TD><TD>Low</TD></TR>
+<TR><TD>parallel</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print
+ file</TD><TD>Low</TD></TR>
 <TR><TD>serial</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print file</TD><TD>
 Low</TD></TR>
 <TR><TD>socket</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print file</TD><TD>
@@ -158,10 +158,10 @@ Low</TD></TR>
 <TR><TD>usb</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print file</TD><TD>
 Low</TD></TR>
 <TR><TH COLSPAN="3">CGIs</TH></TR>
-<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp 
-Files</TH><TH>CPU Usage</TH></TR>
-<TR><TD>admin.cgi</TD><TD>107k</TD><TD>256k</TD><TD>Up to size of PPD 
-file</TD><TD>Medium</TD></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
+<TR><TD>admin.cgi</TD><TD>107k</TD><TD>256k</TD><TD>Up to size of PPD
+ file</TD><TD>Medium</TD></TR>
 <TR><TD>classes.cgi</TD><TD>95k</TD><TD>Size of class objects</TD><TD>
 None</TD><TD>Medium</TD></TR>
 <TR><TD>jobs.cgi</TD><TD>93k</TD><TD>Size of job objects</TD><TD>None</TD><TD>
@@ -169,8 +169,8 @@ Medium</TD></TR>
 <TR><TD>printers.cgi</TD><TD>95k</TD><TD>Size of printer objects</TD><TD>
 None</TD><TD>Medium</TD></TR>
 <TR><TH COLSPAN="3">Command-Line Programs</TH></TR>
-<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp 
-Files</TH><TH>CPU Usage</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
 <TR><TD>accept</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
 <TR><TD>cancel</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
 <TR><TD>disable</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
@@ -188,31 +188,31 @@ None</TD><TD>Medium</TD></TR>
 Medium</TD></TR>
 <TR><TD>lpr</TD><TD>87k</TD><TD>256k</TD><TD>None</TD><TD>Low</TD></TR>
 <TR><TD>lprm</TD><TD>84k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
-<TR><TD>lpstat</TD><TD>119k</TD><TD>Size of job, printer, and class 
-objects</TD><TD>None</TD><TD>Medium</TD></TR>
+<TR><TD>lpstat</TD><TD>119k</TD><TD>Size of job, printer, and class
+ objects</TD><TD>None</TD><TD>Medium</TD></TR>
 <TR><TD>reject</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
 <TR><TH COLSPAN="3">Daemons</TH></TR>
-<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp 
-Files</TH><TH>CPU Usage</TH></TR>
-<TR><TD>cups-lpd</TD><TD>92k</TD><TD>256k</TD><TD>One file per control 
-or data file from client</TD><TD>Low</TD></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
+<TR><TD>cups-lpd</TD><TD>92k</TD><TD>256k</TD><TD>One file per control
+ or data file from client</TD><TD>Low</TD></TR>
 <TR><TD>cupsd</TD><TD>308k</TD><TD>See Scheduler Requirements</TD><TD>
 See Scheduler Requirements</TD><TD>Medium</TD></TR>
 <TR><TD>cups-polld</TD><TD>84k</TD><TD>Size of printer and class objects</TD><TD>
 None</TD><TD>Low</TD></TR>
 <TR><TH COLSPAN="3">Filters</TH></TR>
-<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp 
-Files</TH><TH>CPU Usage</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
 <TR><TD>hpgltops</TD><TD>263k</TD><TD>320k</TD><TD>None</TD><TD>Medium</TD>
 </TR>
-<TR><TD>imagetops</TD><TD>628k</TD><TD>10M</TD><TD>Swap file for 
-uncompressed image data</TD><TD>Medium</TD></TR>
-<TR><TD>imagetoraster</TD><TD>652k</TD><TD>10M</TD><TD>Swap file for 
-uncompressed image data</TD><TD>High</TD></TR>
-<TR><TD>pstops</TD><TD>775k</TD><TD>840k</TD><TD>Up to size of print 
-file</TD><TD>Medium</TD></TR>
-<TR><TD>pstoraster</TD><TD>4M</TD><TD>14M</TD><TD>Swap file for command 
-lists</TD><TD>High</TD></TR>
+<TR><TD>imagetops</TD><TD>628k</TD><TD>10M</TD><TD>Swap file for
+ uncompressed image data</TD><TD>Medium</TD></TR>
+<TR><TD>imagetoraster</TD><TD>652k</TD><TD>10M</TD><TD>Swap file for
+ uncompressed image data</TD><TD>High</TD></TR>
+<TR><TD>pstops</TD><TD>775k</TD><TD>840k</TD><TD>Up to size of print
+ file</TD><TD>Medium</TD></TR>
+<TR><TD>pstoraster</TD><TD>4M</TD><TD>14M</TD><TD>Swap file for command
+ lists</TD><TD>High</TD></TR>
 <TR><TD>rastertoepson</TD><TD>693k</TD><TD>1M</TD><TD>None</TD><TD>Low</TD>
 </TR>
 <TR><TD>rastertohp</TD><TD>690k</TD><TD>1M</TD><TD>None</TD><TD>Low</TD></TR>
@@ -222,11 +222,11 @@ Low</TD></TR>
 </CENTER>
 </P>
 <H1><A NAME="4">4 Scheduler Objects</A></H1>
-<P>The <CODE>cupsd</CODE> program is the CUPS scheduler process. It 
-manages many interdependent server objects that are used to manage and 
-print files to printers. </P>
-<P>The following table provides the memory and disk cost associated 
-with each server object. 
+<P>The <CODE>cupsd</CODE> program is the CUPS scheduler process. It
+ manages many interdependent server objects that are used to manage and
+ print files to printers.</P>
+<P>The following table provides the memory and disk cost associated with
+ each server object.
 <CENTER>
 <TABLE BORDER="1" WIDTH="80%">
 <TR><TH>Object</TH><TH>Memory Per</TH><TH>Disk Per</TH></TR>
@@ -249,49 +249,49 @@ with each server object.
 <H1 TYPE="A" VALUE="1"><A NAME="5">A Glossary</A></H1>
 <H2><A NAME="5_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="5_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 </BODY>
 </HTML>
index 79527d3fb57b18eab62b0b6cd87413e48a65eeb6..888366894c814f9e66748a55eb0c5922fa8540a2 100644 (file)
Binary files a/doc/sps.pdf and b/doc/sps.pdf differ
index f06bfd22163c71bcef63527c585f5982991403f0..8171ad8821028d42181af4026c0cc73fcbe77670 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Security Report</TITLE>
+<TITLE>CUPS Software Security Report</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-SSR-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Security Report</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Security Report</H1></A><BR>
 CUPS-SSR-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -57,28 +57,28 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
-<P>This software security report provides an analysis of possible 
-security concerns for the Common UNIX Printing System (&quot;CUPS&quot;) Version 
-1.1.</P>
+<P>This software security report provides an analysis of possible
+ security concerns for the Common UNIX Printing System (&quot;CUPS&quot;) Version
+ 1.1.</P>
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
-<P>This software security report is organized into the following 
-sections:</P>
+<P>This software security report is organized into the following
+ sections:</P>
 <UL>
 <LI>1 - Scope</LI>
 <LI>2 - References</LI>
@@ -88,183 +88,182 @@ sections:</P>
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
+<P>The following CUPS documentation is referenced by this document:</P>
 <UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 Local Access Risks</A></H1>
-<P>Local access risks are those that can be exploited only with a local 
-user account. This section does not address issues related to 
-dissemination of the root password or other security issues associated 
-with the UNIX operating system. </P>
+<P>Local access risks are those that can be exploited only with a local
+ user account. This section does not address issues related to
+ dissemination of the root password or other security issues associated
+ with the UNIX operating system.</P>
 <H2><A NAME="3_1">3.1 Security Breaches</A></H2>
-<P>There is one known security vulnerability with local access: </P>
+<P>There is one known security vulnerability with local access:</P>
 <OL>
-<LI>Device URIs are passed to backend filters in argv[0] and in  an 
-environment variable. Since device URIs can contain  usernames and 
-passwords it may be possible for a local user to  gain access to a 
-remote resource. </LI>
-<P>We recommend that any password-protected accounts used for  remote 
-printing have limited access priviledges so that the  possible damages 
-can be minimized. </P>
-<P>The device URI is &quot;sanitized&quot; (the username and password are 
- removed) when sent to an IPP client so that a remote user  cannot 
-exploit this vulnerability. </P>
+<LI>Device URIs are passed to backend filters in argv[0] and in an
+ environment variable. Since device URIs can contain usernames and
+ passwords it may be possible for a local user to gain access to a
+ remote resource.</LI>
+<P>We recommend that any password-protected accounts used for remote
+ printing have limited access priviledges so that the possible damages
+ can be minimized.</P>
+<P>The device URI is &quot;sanitized&quot; (the username and password are removed)
+ when sent to an IPP client so that a remote user cannot exploit this
+ vulnerability.</P>
 </OL>
 <H1><A NAME="4">4 Remote Access Risks</A></H1>
-<P>Remote access risks are those that can be exploited without a local 
-user account and/or from a remote system. This section does not address 
-issues related to network or firewall security. </P>
+<P>Remote access risks are those that can be exploited without a local
+ user account and/or from a remote system. This section does not address
+ issues related to network or firewall security.</P>
 <H2><A NAME="4_1">4.1 Denial of Service Attacks</A></H2>
-<P>Like all Internet services, the CUPS server is vulnerable to denial 
-of service attacks, including: </P>
+<P>Like all Internet services, the CUPS server is vulnerable to denial
+ of service attacks, including:</P>
 <OL>
-<LI>Establishing multiple connections to the server until the server 
- will accept no more. </LI>
-<P>This cannot be protected against by the current software. It  is 
-possible that future versions of the CUPS software could be  configured 
-to limit the number of connections allowed from a  single host, however 
-that still would not prevent a distributed  attack. </P>
-<LI>Repeatedly opening and closing connections to the server as fast 
- as possible. </LI>
-<P>There is no easy way of protecting against this in the CUPS 
- software. If the attack is coming from outside the local  network it 
-might be possible to filter such an attack, however  once the 
-connection request has been received by the server it  must at least 
-accept the connection to find out who is  connecting. </P>
-<LI>Flooding the network with broadcast packets on port 631. </LI>
-<P>It might be possible to disable browsing if this condition  is 
-detected by the CUPS software, however if there are large  numbers of 
-printers available on the network such an algorithm  might think that 
-an attack was occurring when instead a valid  update was being 
-received. </P>
-<LI>Sending partial IPP requests; specifically, sending part of an 
- attribute value and then stopping transmission. </LI>
-<P>The current code is structured to read and write the IPP  request 
-data on-the-fly, so there is no easy way to protect  against this for 
-large attribute values. </P>
-<LI>Sending large/long print jobs to printers, preventing other users 
- from printing. </LI>
-<P>There are limited facilities for protecting against large print 
- jobs (the <CODE>MaxRequestSize</CODE> attribute), however this will 
- not protect printers from malicious users and print files that 
- generate hundreds or thousands of pages. In general, we recommend 
- restricting printer access to known hosts or networks, and adding 
- user-level access control as needed for expensive printers. </P>
+<LI>Establishing multiple connections to the server until the server
+ will accept no more.</LI>
+<P>This cannot be protected against by the current software. It is
+ possible that future versions of the CUPS software could be configured
+ to limit the number of connections allowed from a single host, however
+ that still would not prevent a distributed attack.</P>
+<LI>Repeatedly opening and closing connections to the server as fast as
+ possible.</LI>
+<P>There is no easy way of protecting against this in the CUPS software.
+ If the attack is coming from outside the local network it might be
+ possible to filter such an attack, however once the connection request
+ has been received by the server it must at least accept the connection
+ to find out who is connecting.</P>
+<LI>Flooding the network with broadcast packets on port 631.</LI>
+<P>It might be possible to disable browsing if this condition is
+ detected by the CUPS software, however if there are large numbers of
+ printers available on the network such an algorithm might think that an
+ attack was occurring when instead a valid update was being received.</P>
+<LI>Sending partial IPP requests; specifically, sending part of an
+ attribute value and then stopping transmission.</LI>
+<P>The current code is structured to read and write the IPP request data
+ on-the-fly, so there is no easy way to protect against this for large
+ attribute values.</P>
+<LI>Sending large/long print jobs to printers, preventing other users
+ from printing.</LI>
+<P>There are limited facilities for protecting against large print jobs
+ (the <CODE>MaxRequestSize</CODE> attribute), however this will not
+ protect printers from malicious users and print files that generate
+ hundreds or thousands of pages. In general, we recommend restricting
+ printer access to known hosts or networks, and adding user-level access
+ control as needed for expensive printers.</P>
 </OL>
 <H2><A NAME="4_2">4.2 Security Breaches</A></H2>
-<P>The current CUPS server supports Basic, Digest, and local 
-certificate authentication: </P>
+<P>The current CUPS server supports Basic, Digest, and local certificate
+ authentication:</P>
 <OL>
-<LI>Basic authentication essentially places the clear text of  the 
-username and password on the network. Since CUPS uses the  UNIX 
-username and password account information, the  authentication 
-information could be used to gain access to  accounts (possibly 
-priviledged accounts) on the server. </LI>
-<LI>Digest authentication uses an MD5 checksum of the username, 
- password, and domain (&quot;CUPS&quot;), so the original username and  password 
-is not sent over the network. However, the current  implementation does 
-not authenticate the entire message and  uses the client's IP address 
-for the nonce value, making it  possible to launch &quot;man in the middle&quot; 
-and replay attacks from  the same client.  The next minor release of 
-CUPS will support  Digest authentication of the entire message body, 
-effectively  stopping these methods of attack. </LI>
-<LI>Local certificate authentication passes 128-bit  &quot;certificates&quot; 
-that identify an authenticated user.  Certificates are created 
-on-the-fly from random data and stored  in files under <CODE>
-/etc/cups/certs</CODE>. They have  restricted read permissions: root + 
-system for the root  certificate, and lp + system for CGI certificates. 
-Because  certificates are only available on the local system, the CUPS 
- server does not accept local authentication unless the client  is 
-connected to the localhost address (127.0.0.1.) </LI>
+<LI>Basic authentication essentially places the clear text of the
+ username and password on the network. Since CUPS uses the UNIX username
+ and password account information, the authentication information could
+ be used to gain access to accounts (possibly priviledged accounts) on
+ the server.</LI>
+<LI>Digest authentication uses an MD5 checksum of the username,
+ password, and domain (&quot;CUPS&quot;), so the original username and password is
+ not sent over the network. However, the current implementation does not
+ authenticate the entire message and uses the client's IP address for
+ the nonce value, making it possible to launch &quot;man in the middle&quot; and
+ replay attacks from the same client. The next minor release of CUPS
+ will support Digest authentication of the entire message body,
+ effectively stopping these methods of attack.</LI>
+<LI>Local certificate authentication passes 128-bit &quot;certificates&quot; that
+ identify an authenticated user. Certificates are created on-the-fly
+ from random data and stored in files under <CODE>/etc/cups/certs</CODE>
+. They have restricted read permissions: root + system for the root
+ certificate, and lp + system for CGI certificates. Because certificates
+ are only available on the local system, the CUPS server does not accept
+ local authentication unless the client is connected to the localhost
+ address (127.0.0.1.)</LI>
 </OL>
-<P>The default CUPS configuration disables remote administration. We do 
-not recommend that remote administration be enabled for all hosts. 
-However, if you have a trusted network or subnet, access can be 
-restricted accordingly.  Also, we highly recommend using Digest 
-authentication when possible. Unfortunately, most web browsers do not 
-support Digest authentication at this time. </P>
+<P>The default CUPS configuration disables remote administration. We do
+ not recommend that remote administration be enabled for all hosts.
+ However, if you have a trusted network or subnet, access can be
+ restricted accordingly. Also, we highly recommend using Digest
+ authentication when possible. Unfortunately, most web browsers do not
+ support Digest authentication at this time.</P>
 <H1 TYPE="A" VALUE="1"><A NAME="5">A Glossary</A></H1>
 <H2><A NAME="5_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="5_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 </BODY>
 </HTML>
index f24244cd93deca569d3e80431307c6010d454491..6dccf74de42771a3d508e3c25f5bb7fde815be56 100644 (file)
Binary files a/doc/ssr.pdf and b/doc/ssr.pdf differ
index 2ed71e25a03f09fb83c969e6d02c6f2d07cc2ece..bd95c898076f5edebb41b8be525715529de2cbbc 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Test Plan</TITLE>
+<TITLE>CUPS Software Test Plan</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-STP-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Test Plan</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Test Plan</H1></A><BR>
 CUPS-STP-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -68,27 +68,27 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
-<P>This software test plan provides detailed tests that are used to 
-evaluate the stability and compliance of the Common UNIX Printing 
-System (&quot;CUPS&quot;) Version 1.1. </P>
+<P>This software test plan provides detailed tests that are used to
+ evaluate the stability and compliance of the Common UNIX Printing
+ System (&quot;CUPS&quot;) Version 1.1.</P>
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
-<P>This software test plan is organized into the following sections: </P>
+<P>This software test plan is organized into the following sections:</P>
 <UL>
 <LI>1 - Scope</LI>
 <LI>2 - References</LI>
@@ -99,164 +99,164 @@ EPSON printers are included that use these filters. </P>
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
+<P>The following CUPS documentation is referenced by this document:</P>
 <UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 Test Procedure</A></H1>
-<P>The test software and data files are located in the <VAR>test</VAR>
- subdirectory of the source distribution. A script is provided to 
-compile the <CODE>ipptest</CODE> program and run all of the tests that 
-follow, producing a success/fail report. </P>
-<P>The <CODE>test</CODE> target of the top-level makefile can be used 
-to run this script: </P>
+<P>The test software and data files are located in the<VAR> test</VAR>
+ subdirectory of the source distribution. A script is provided to
+ compile the <CODE>ipptest</CODE> program and run all of the tests that
+ follow, producing a success/fail report.</P>
+<P>The <CODE>test</CODE> target of the top-level makefile can be used to
+ run this script:</P>
 <UL>
 <PRE>
 make test
 </PRE>
 </UL>
-<P>or you can run the test script directly: </P>
+<P>or you can run the test script directly:</P>
 <UL>
 <PRE>
 cd test
 ./run-stp-tests
 </PRE>
 </UL>
-<P>A Software Test Report is stored in HTML and PDF files that are 
-generated using the <A HREF="http://www.easysw.com/htmldoc">HTMLDOC</A>
- software. </P>
+<P>A Software Test Report is stored in HTML and PDF files that are
+ generated using the<A HREF="http://www.easysw.com/htmldoc"> HTMLDOC</A>
+ software.</P>
 <H1><A NAME="4">4 IPP Compliance Tests</A></H1>
-<P>This section describes the tests used to validate the IPP standards 
-compliance of the CUPS server. </P>
+<P>This section describes the tests used to validate the IPP standards
+ compliance of the CUPS server.</P>
 <H2><A NAME="4_1">4.1 Request Tests</A></H2>
-<P>These tests verify that the CUPS scheduler only accepts valid IPP 
-requests that start with the <CODE>attributes-charset</CODE> and <CODE>
+<P>These tests verify that the CUPS scheduler only accepts valid IPP
+ requests that start with the <CODE>attributes-charset</CODE> and <CODE>
 attributes-natural-language</CODE> attributes and also contain a <CODE>
-printer-uri</CODE> or <CODE>job-uri</CODE> attribute. </P>
+printer-uri</CODE> or <CODE>job-uri</CODE> attribute.</P>
 <P>It also verifies that the CUPS scheduler always responds with <CODE>
 attributes-charset</CODE> and <CODE>attributes-natural-language</CODE>
- attributes, using default values if they are not provided by the 
-client. </P>
+ attributes, using default values if they are not provided by the
+ client.</P>
 <H2><A NAME="4_2">4.2 CUPS Printer Operation Tests</A></H2>
-<P>These tests verify that the CUPS printer operations are supported 
-and function properly. Two printers called <CODE>Test1</CODE> and <CODE>
-Test2</CODE> are created, one as a PostScript printer and one as a 
-raster printer. </P>
+<P>These tests verify that the CUPS printer operations are supported and
+ function properly. Two printers called <CODE>Test1</CODE> and <CODE>
+Test2</CODE> are created, one as a PostScript printer and one as a
+ raster printer.</P>
 <H2><A NAME="4_3">4.3 Job Operation Tests</A></H2>
-<P>These test verify that the CUPS scheduler accepts print jobs for all 
-supported file formats and that the <CODE>cancel-job</CODE>, <CODE>
-hold-job</CODE>, and <CODE>resume-job</CODE> operations work. </P>
+<P>These test verify that the CUPS scheduler accepts print jobs for all
+ supported file formats and that the <CODE>cancel-job</CODE>, <CODE>
+hold-job</CODE>, and <CODE>resume-job</CODE> operations work.</P>
 <H1><A NAME="5">5 Command Tests</A></H1>
-<P>This section describes the tests used to validate the Berkeley and 
-System V commands included with CUPS. </P>
+<P>This section describes the tests used to validate the Berkeley and
+ System V commands included with CUPS.</P>
 <H2><A NAME="5_1">5.1 lpadmin</A></H2>
-<P>This test verifies that printers can be added, modified, and 
-defaulted using the <CODE>lpadmin</CODE> command. </P>
+<P>This test verifies that printers can be added, modified, and
+ defaulted using the <CODE>lpadmin</CODE> command.</P>
 <H2><A NAME="5_2">5.2 lpc</A></H2>
-<P>This test verifies that the <CODE>lpc</CODE> command can show the 
-current status of all print queues. </P>
+<P>This test verifies that the <CODE>lpc</CODE> command can show the
+ current status of all print queues.</P>
 <H2><A NAME="5_3">5.3 lpq</A></H2>
-<P>This test verifies that the <CODE>lpq</CODE> command lists any jobs 
-in the queue. </P>
+<P>This test verifies that the <CODE>lpq</CODE> command lists any jobs
+ in the queue.</P>
 <H2><A NAME="5_4">5.4 lpstat</A></H2>
-<P>This test verifies that the <CODE>lpstat</CODE> command works with 
-all reports using the &quot;<CODE>-t</CODE>&quot; option. </P>
+<P>This test verifies that the <CODE>lpstat</CODE> command works with
+ all reports using the &quot;<CODE>-t</CODE>&quot; option.</P>
 <H2><A NAME="5_5">5.5 lp</A></H2>
-<P>This test verifies that the <CODE>lp</CODE> command works with both 
-the default destination and a specific destination. </P>
+<P>This test verifies that the <CODE>lp</CODE> command works with both
+ the default destination and a specific destination.</P>
 <H2><A NAME="5_6">5.6 lpr</A></H2>
-<P>This test verifies that the <CODE>lpr</CODE> command works with both 
-the default destination and a specific destination. </P>
+<P>This test verifies that the <CODE>lpr</CODE> command works with both
+ the default destination and a specific destination.</P>
 <H2><A NAME="5_7">5.7 lprm</A></H2>
-<P>This test verifies that the <CODE>lprm</CODE> command can properly 
-cancel a job. </P>
+<P>This test verifies that the <CODE>lprm</CODE> command can properly
+ cancel a job.</P>
 <H2><A NAME="5_8">5.8 cancel</A></H2>
-<P>This test verifies that the <CODE>cancel</CODE> command can properly 
-cancel a job or all jobs. </P>
+<P>This test verifies that the <CODE>cancel</CODE> command can properly
+ cancel a job or all jobs.</P>
 <H2><A NAME="5_9">5.9 lpinfo</A></H2>
-<P>This test verifies that the <CODE>lpinfo</CODE> command returns a 
-list of available printer drivers and devices. </P>
+<P>This test verifies that the <CODE>lpinfo</CODE> command returns a
+ list of available printer drivers and devices.</P>
 <H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
 <H2><A NAME="6_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="6_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 </BODY>
 </HTML>
index 00637189090c1b30795aa9f046c0e8eb7de0a6a0..2251be5b783ad46c963a70a8169c426340b3424e 100644 (file)
Binary files a/doc/stp.pdf and b/doc/stp.pdf differ
index 576c6c8b05349cac3fbc08b1ba9f5238d735add0..8f84e624e4283485e67a3c995ee273aa52a7dadd 100644 (file)
@@ -124,24 +124,26 @@ Copyright 1997-2001, All Rights Reserved<BR>
 </UL>
 <HR>
 <H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
-<P>This software users manual describes how to use the Common UNIX 
-Printing System<SUP>TM</SUP> (&quot;CUPS<SUP>TM</SUP>&quot;) Version 1.1.7. </P>
+<P>This software users manual describes how to use the Common UNIX
+ Printing &lt;&lt;&lt;&lt;&lt;&lt;&lt; sum.shtml System<SUP>TM</SUP> (&quot;CUPS<SUP>TM</SUP>&quot;)
+ Version 1.1.7. ======= System<SUP>TM</SUP> (&quot;CUPS<SUP>TM</SUP>&quot;)
+ Version 1.1.13. &gt;&gt;&gt;&gt;&gt;&gt;&gt; 1.29</P>
 <H2><A NAME="1_1">System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 
 <!-- NEED 2in -->
 <H2><A NAME="1_2">Document Overview</A></H2>
@@ -155,16 +157,16 @@ EPSON printers are included that use these filters. </P>
 <LI><A HREF="#LICENSE">A - Software License Agreement</A></LI>
 </UL>
 <H2><A NAME="1_3">Notation Conventions</A></H2>
-<P>Various font and syntax conventions are used in this guide. Examples 
-and their meanings and uses are explained below: 
+<P>Various font and syntax conventions are used in this guide. Examples
+ and their meanings and uses are explained below:
 <CENTER>
 <TABLE WIDTH="80%">
 <TR><TH>Example</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
-<BR><CODE> lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands; 
-the first mention of a command or  function in a chapter is followed by 
-a manual page section  number.</TD></TR>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands;
+ the first mention of a command or function in a chapter is followed by
+ a manual page section number.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD><VAR>/var</VAR>
 <BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
@@ -174,217 +176,217 @@ File and directory names.</TD></TR>
 &nbsp;&nbsp;&nbsp;</TD><TD>Screen output.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD><TD>
-&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are 
+&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are
  in ALL CAPS.</TD></TR>
 <TR><TD>&nbsp;</TD></TR>
-<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are 
-written using the period (.) to indicate  the decimal point.</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are
+ written using the period (.) to indicate the decimal point.</TD></TR>
 </TABLE>
 </CENTER>
 
 <!-- NEED 3in -->
 </P>
 <H2><A NAME="1_4">Abbreviations</A></H2>
- The following abbreviations are used throughout this manual: 
+ The following abbreviations are used throughout this manual:
 <UL>
 <DL>
-<DT>kb </DT>
+<DT>kb</DT>
 <DD>Kilobytes, or 1024 bytes
-<BR>&nbsp; </DD>
-<DT>Mb </DT>
+<BR>&nbsp;</DD>
+<DT>Mb</DT>
 <DD>Megabytes, or 1048576 bytes
-<BR>&nbsp; </DD>
-<DT>Gb </DT>
+<BR>&nbsp;</DD>
+<DT>Gb</DT>
 <DD>Gigabytes, or 1073741824 bytes
-<BR>&nbsp; </DD>
+<BR>&nbsp;</DD>
 </DL>
 </UL>
 <H2><A NAME="1_5">Other References</A></H2>
 <UL>
 <DL>
-<DT>CUPS Software Administrators Manual </DT>
+<DT>CUPS Software Administrators Manual</DT>
 <DD>An administration guide for the CUPS software.
-<BR>&nbsp; </DD>
-<DT>CUPS Software Programmers Manual </DT>
-<DD>A programmer guide for interfacing with and/or extending the CUPS 
+<BR>&nbsp;</DD>
+<DT>CUPS Software Programmers Manual</DT>
+<DD>A programmer guide for interfacing with and/or extending the CUPS
  software.
-<BR>&nbsp; </DD>
+<BR>&nbsp;</DD>
 </DL>
 </UL>
 <H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
-<P>This chapter provides an overview of how the Common UNIX Printing 
-System works. </P>
+<P>This chapter provides an overview of how the Common UNIX Printing
+ System works.</P>
 <H2><A NAME="2_1">The Printing Problem</A></H2>
-<P>For years <I>the printing problem</I> has plagued UNIX. Unlike 
-Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system 
-in place for supporting printers. Among the solutions currently 
-available, the Berkeley and System V printing systems are the most 
-prevalent. </P>
-<P>These printing systems support line printers (text only) or 
-PostScript printers (text and graphics), and with some coaxing they can 
-be made to support a full range of printers and file formats. However, 
-because each varient of the UNIX operating system uses a different 
-printing system than the next developing printer drivers for a wide 
-range of printers and operating systems is extremely difficult. That 
-combined with the limited volume of customers for each UNIX varient has 
-forced most printer vendors to give up supporting UNIX entirely. </P>
-<P>CUPS is designed to eliminate <I>the printing problem</I>. One 
-common printing system can be used by all UNIX varients to support the 
-printing needs of users. Printer vendors can use its modular filter 
-interface to develop a single driver program that supports a wide range 
-of file formats with little or no effort.  Since CUPS provides both the 
-System V and Berkeley printing commands, users (and applications) can 
-reap the benefits of this new technology with no changes. </P>
+<P>For years<I> the printing problem</I> has plagued UNIX. Unlike
+ Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system
+ in place for supporting printers. Among the solutions currently
+ available, the Berkeley and System V printing systems are the most
+ prevalent.</P>
+<P>These printing systems support line printers (text only) or
+ PostScript printers (text and graphics), and with some coaxing they can
+ be made to support a full range of printers and file formats. However,
+ because each varient of the UNIX operating system uses a different
+ printing system than the next developing printer drivers for a wide
+ range of printers and operating systems is extremely difficult. That
+ combined with the limited volume of customers for each UNIX varient has
+ forced most printer vendors to give up supporting UNIX entirely.</P>
+<P>CUPS is designed to eliminate<I> the printing problem</I>. One common
+ printing system can be used by all UNIX varients to support the
+ printing needs of users. Printer vendors can use its modular filter
+ interface to develop a single driver program that supports a wide range
+ of file formats with little or no effort. Since CUPS provides both the
+ System V and Berkeley printing commands, users (and applications) can
+ reap the benefits of this new technology with no changes.</P>
 <H2><A NAME="2_2">The Technology</A></H2>
-<P>CUPS is based upon an emerging Internet standard called the Internet 
-Printing Protocol. IPP has been embraced by dozens of printer and 
-printer server manufacturers and is supported by Microsoft Windows 
-2000. </P>
-<P>IPP defines a standard protocol for printing as well as managing 
-print jobs and printer options like media size, resolution, and so 
-forth. Like all IP-based protocols, IPP can be used locally or over the 
-Internet to printers hundreds or thousands of miles away. Unlike other 
-protocols, however, IPP also supports access control, authentication, 
-and encryption, making it a much more capable and secure printing 
-solution than older ones. </P>
-<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;) 
-which is the basis of web servers on the Internet. This allows users to 
-view documentation, check status information on a printer or server, 
-and manage their printers, classes, and jobs using their web browser. </P>
-<P>CUPS provides a complete IPP/1.1 based printing system that provides 
-Basic, Digest, and local certificate authentication and user, domain, 
-or IP-based access control. TLS encryption will be available in future 
-versions of CUPS. </P>
+<P>CUPS is based upon an emerging Internet standard called the Internet
+ Printing Protocol. IPP has been embraced by dozens of printer and
+ printer server manufacturers and is supported by Microsoft Windows
+ 2000.</P>
+<P>IPP defines a standard protocol for printing as well as managing
+ print jobs and printer options like media size, resolution, and so
+ forth. Like all IP-based protocols, IPP can be used locally or over the
+ Internet to printers hundreds or thousands of miles away. Unlike other
+ protocols, however, IPP also supports access control, authentication,
+ and encryption, making it a much more capable and secure printing
+ solution than older ones.</P>
+<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;)
+ which is the basis of web servers on the Internet. This allows users to
+ view documentation, check status information on a printer or server,
+ and manage their printers, classes, and jobs using their web browser.</P>
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+ Basic, Digest, and local certificate authentication and user, domain,
+ or IP-based access control. TLS encryption will be available in future
+ versions of CUPS.</P>
 <H2><A NAME="2_3">Jobs</A></H2>
-<P>Each file or set of files that is submitted for printing is called a <I>
-job</I>. Jobs are identified by a unique number starting at 1 and are 
-assigned to a particular destination, usually a printer. Jobs can also 
-have options associated with them such as media size, number of copies, 
-and priority. </P>
+<P>Each file or set of files that is submitted for printing is called a<I>
+ job</I>. Jobs are identified by a unique number starting at 1 and are
+ assigned to a particular destination, usually a printer. Jobs can also
+ have options associated with them such as media size, number of copies,
+ and priority.</P>
 <H2><A NAME="2_4">Classes</A></H2>
-<P>CUPS supports collections of printers known as <I>classes</I>. Jobs 
-sent to a class are forwarded to the first available printer in the 
-class. </P>
+<P>CUPS supports collections of printers known as<I> classes</I>. Jobs
+ sent to a class are forwarded to the first available printer in the
+ class.</P>
 <H2><A NAME="2_5">Filters</A></H2>
-<P>Filters allow a user or application to print many types of files 
-without extra effort. Print jobs sent to a CUPS server are filtered 
-before sending them to a printer. Some filters convert job files to 
-different formats that the printer can understand. Others perform page 
-selection and ordering tasks. </P>
-<P>CUPS provides filters for printing many types of image files, 
-HP-GL/2 files, PDF files, and text files. CUPS also supplies PostScript 
-and image file Raster Image Processor (&quot;RIP&quot;) filters that convert 
-PostScript or image files into bitmaps that can be sent to a raster 
-printer. </P>
+<P>Filters allow a user or application to print many types of files
+ without extra effort. Print jobs sent to a CUPS server are filtered
+ before sending them to a printer. Some filters convert job files to
+ different formats that the printer can understand. Others perform page
+ selection and ordering tasks.</P>
+<P>CUPS provides filters for printing many types of image files, HP-GL/2
+ files, PDF files, and text files. CUPS also supplies PostScript and
+ image file Raster Image Processor (&quot;RIP&quot;) filters that convert
+ PostScript or image files into bitmaps that can be sent to a raster
+ printer.</P>
 <H2><A NAME="2_6">Backends</A></H2>
-<P>Backends perform the most important task of all - they send the 
-filtered print data to the printer. </P>
-<P>CUPS provides backends for printing over parallel, serial, and USB 
-ports, and over the network via the IPP, JetDirect (AppSocket), and 
-Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are 
-available in network service packages such as the SMB backend included 
-with the popular SAMBA software. </P>
-<P>Backends are also used to determine the available devices. On 
-startup each backend is asked for a list of devices it supports, and 
-any information that is available. This allows the parallel backend to 
-tell CUPS that an EPSON Stylus Color 600 printer is attached to 
-parallel port 1, for example. </P>
+<P>Backends perform the most important task of all - they send the
+ filtered print data to the printer.</P>
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ ports, and over the network via the IPP, JetDirect (AppSocket), and
+ Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are
+ available in network service packages such as the SMB backend included
+ with the popular SAMBA software.</P>
+<P>Backends are also used to determine the available devices. On startup
+ each backend is asked for a list of devices it supports, and any
+ information that is available. This allows the parallel backend to tell
+ CUPS that an EPSON Stylus Color 600 printer is attached to parallel
+ port 1, for example.</P>
 <H2><A NAME="2_7">Printer Drivers</A></H2>
-<P>Printer drivers in CUPS consist of one of more filters specific to a 
-printer. CUPS includes sample printer drivers for Hewlett-Packard 
-LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color, 
-and Stylus Photo printers. While these drivers do not generate optimal 
-output for the different printer models, they do provide basic printing 
-and demonstrate how you can write your own printer drivers and 
-incorporate them into CUPS. </P>
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+ printer. CUPS includes sample printer drivers for Hewlett-Packard
+ LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+ and Stylus Photo printers. While these drivers do not generate optimal
+ output for the different printer models, they do provide basic printing
+ and demonstrate how you can write your own printer drivers and
+ incorporate them into CUPS.</P>
 <H2><A NAME="2_8">Networking</A></H2>
-<P>Printers and classes on the local system are automatically shared 
-with other systems on the network. This allows you to setup one system 
-to print to a printer and use this system as a printer server or spool 
-host for all of the others. Users may then select a local printer by 
-name or a remote printer using &quot;name@server&quot;. </P>
-<P>CUPS also provides <I>implicit classes</I>, which are collections of 
-printers and/or classes with the same name. This allows you to setup 
-multiple servers pointing to the same physical network printer, for 
-example, so that you aren't relying on a single system for printing. 
-Because this also works with printer classes, you can setup multiple 
-servers and printers and never worry about a single point of failure 
-unless all of the printers and servers go down! </P>
+<P>Printers and classes on the local system are automatically shared
+ with other systems on the network. This allows you to setup one system
+ to print to a printer and use this system as a printer server or spool
+ host for all of the others. Users may then select a local printer by
+ name or a remote printer using &quot;name@server&quot;.</P>
+<P>CUPS also provides<I> implicit classes</I>, which are collections of
+ printers and/or classes with the same name. This allows you to setup
+ multiple servers pointing to the same physical network printer, for
+ example, so that you aren't relying on a single system for printing.
+ Because this also works with printer classes, you can setup multiple
+ servers and printers and never worry about a single point of failure
+ unless all of the printers and servers go down!</P>
 <H1 ALIGN="RIGHT"><A NAME="USING_SYSTEM">2 - Using the Printing System</A>
 </H1>
-<P>This chapter shows you how to submit, query, and cancel print jobs 
-to different printers. </P>
+<P>This chapter shows you how to submit, query, and cancel print jobs to
+ different printers.</P>
 <H2><A NAME="3_1">Submitting Files for Printing</A></H2>
 <P>CUPS provides both the System V (<CODE>lp(1)</CODE>) and Berkeley (<CODE>
-lpr(1)</CODE>) printing commands. Type the following command to print a 
-file to the default (or only) printer on the system: </P>
+lpr(1)</CODE>) printing commands. Type the following command to print a
+ file to the default (or only) printer on the system:</P>
 <UL>
 <PRE>
 <B>lp filename ENTER</B>
 </PRE>
 </UL>
-<P>or: </P>
+<P>or:</P>
 <UL>
 <PRE>
 <B>lpr filename ENTER</B>
 </PRE>
 </UL>
-<P>CUPS understands many different types of files directly, including 
-PostScript and image files. This allows you to print from inside your 
-applications or at the command-line, whichever is most convenient! </P>
+<P>CUPS understands many different types of files directly, including
+ PostScript and image files. This allows you to print from inside your
+ applications or at the command-line, whichever is most convenient!</P>
 <H2><A NAME="3_2">Choosing a Printer</A></H2>
-<P>Many systems will have more than one printer available to the user. 
-These printers can be attached to the local system via a parallel, 
-serial, or USB port, or available over the network. </P>
-<P>Use the <CODE>lpstat(1)</CODE> command to see a list of available 
-printers: </P>
+<P>Many systems will have more than one printer available to the user.
+ These printers can be attached to the local system via a parallel,
+ serial, or USB port, or available over the network.</P>
+<P>Use the <CODE>lpstat(1)</CODE> command to see a list of available
+ printers:</P>
 <UL>
 <PRE>
 <B>lpstat -p -d ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>-p</CODE> option specifies that you want to see a list of 
-printers, and the <CODE>-d</CODE> option reports the current system 
-default printer or class. </P>
-<P>Use the <CODE>-d</CODE> option with the <CODE>lp</CODE> command to 
-print to a specific printer: </P>
+<P>The <CODE>-p</CODE> option specifies that you want to see a list of
+ printers, and the <CODE>-d</CODE> option reports the current system
+ default printer or class.</P>
+<P>Use the <CODE>-d</CODE> option with the <CODE>lp</CODE> command to
+ print to a specific printer:</P>
 <UL>
 <PRE>
 <B>lp -d printer filename ENTER</B>
 </PRE>
 </UL>
-<P>or the <CODE>-P</CODE> option with the <CODE>lpr</CODE> command: </P>
+<P>or the <CODE>-P</CODE> option with the <CODE>lpr</CODE> command:</P>
 <UL>
 <PRE>
 <B>lpr -P printer filename ENTER</B>
 </PRE>
 </UL>
 <H2><A NAME="3_3">Setting Printer Options</A></H2>
-<P>For many types of files, the default printer options may be 
-sufficient for your needs. However, there may be times when you need to 
-change the options for a particular file you are printing. </P>
-<P>The <CODE>lp</CODE> and <CODE>lpr</CODE> commands allow you to pass 
-printer options using the <CODE>-o</CODE> option: </P>
+<P>For many types of files, the default printer options may be
+ sufficient for your needs. However, there may be times when you need to
+ change the options for a particular file you are printing.</P>
+<P>The <CODE>lp</CODE> and <CODE>lpr</CODE> commands allow you to pass
+ printer options using the <CODE>-o</CODE> option:</P>
 <UL>
 <PRE>
 <B>lp -o landscape -o scaling=75 -o media=A4 filename.jpg
 <B>lpr -o landscape -o scaling=75 -o media=A4 filename.jpg
 </B></B></PRE>
 </UL>
-<P>The available printer options vary depending on the printer. The 
-standard options are described in <A HREF="#STANDARD_OPTIONS">Chapter 
-3, &quot;Standard Printing Options&quot;</A>. </P>
+<P>The available printer options vary depending on the printer. The
+ standard options are described in<A HREF="#STANDARD_OPTIONS"> Chapter
+ 3, &quot;Standard Printing Options&quot;</A>.</P>
 <H2><A NAME="3_4">Printing Multiple Copies</A></H2>
-<P>Both the <CODE>lp</CODE> and <CODE>lpr</CODE> commands have options 
-for printing more than one copy of a file: </P>
+<P>Both the <CODE>lp</CODE> and <CODE>lpr</CODE> commands have options
+ for printing more than one copy of a file:</P>
 <UL>
 <PRE>
 <B>lp -n <I>num-copies</I> filename ENTER</B>
 <B>lpr -#<I>num-copies</I> filename ENTER</B>
 </PRE>
 </UL>
-<P>Copies are normally <I>not</I> collated for you. Use the <CODE>-o 
-Collate=True</CODE> option to get collated copies : </P>
+<P>Copies are normally<I> not</I> collated for you. Use the <CODE>-o
+ Collate=True</CODE> option to get collated copies :</P>
 <UL>
 <PRE>
 <B>lp -n <I>num-copies</I> -o Collate=True filename ENTER</B>
@@ -394,8 +396,8 @@ Collate=True</CODE> option to get collated copies : </P>
 
 <!-- NEED 3in -->
 <H2><A NAME="3_5">Checking the Printer Status from the Command-Line</A></H2>
-<P>The <CODE>lpstat</CODE> command can be used to check for jobs that 
-you have submitted for printing: </P>
+<P>The <CODE>lpstat</CODE> command can be used to check for jobs that
+ you have submitted for printing:</P>
 <UL>
 <PRE>
 <B>lpstat ENTER</B>
@@ -405,7 +407,7 @@ Printer-3 johndoe 372842
 </PRE>
 </UL>
 <P>The jobs are listed in the order they will be printed. Use the <CODE>
--p</CODE> option to see which files and printers are active: </P>
+-p</CODE> option to see which files and printers are active:</P>
 <UL>
 <PRE>
 <B>lpstat -p ENTER</B>
@@ -414,8 +416,8 @@ printer DeskJet now printing DeskJet-1.
 </UL>
 
 <!-- NEED 2in -->
-<P>Use the <CODE>-o</CODE> and <CODE>-p</CODE> options together to show 
-the jobs and the printers: </P>
+<P>Use the <CODE>-o</CODE> and <CODE>-p</CODE> options together to show
+ the jobs and the printers:</P>
 <UL>
 <PRE>
 <B>lpstat -o -p ENTER</B>
@@ -426,37 +428,37 @@ printer DeskJet now printing DeskJet-1.
 </PRE>
 </UL>
 <H2><A NAME="3_6">Checking the Printer Status from the Web</A></H2>
-<P>Since CUPS uses the Internet Printing Protocol, it is also a 
-fully-functional web server. To use your web browser to monitor the 
-printers on your system, open the URL: </P>
+<P>Since CUPS uses the Internet Printing Protocol, it is also a
+ fully-functional web server. To use your web browser to monitor the
+ printers on your system, open the URL:</P>
 <UL>
 <PRE>
 <A HREF="http://localhost:631">http://localhost:631</A>
 </PRE>
 </UL>
-<P>From there you can view the status of classes, jobs, and printers 
-with the click of a button! </P>
+<P>From there you can view the status of classes, jobs, and printers
+ with the click of a button!</P>
 <H2><A NAME="3_7">Canceling a Print Job</A></H2>
-<P>The <CODE>cancel(1)</CODE> and <CODE>lprm(1)</CODE> commands cancel 
-a print job: </P>
+<P>The <CODE>cancel(1)</CODE> and <CODE>lprm(1)</CODE> commands cancel a
+ print job:</P>
 <UL>
 <PRE>
 <B>cancel <I>job-id</I> ENTER</B>
 <B>lprm <I>job-id</I> ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>job-id</CODE> is the number that was reported to you by 
-the <CODE>lp</CODE> or <CODE>lpstat</CODE> commands. </P>
-<H1 ALIGN="RIGHT"><A NAME="STANDARD_OPTIONS">3 - Standard Printer 
-Options</A></H1>
-<P>This chapter describes the standard printer options that are 
-available when printing with the <CODE>lp</CODE> and <CODE>lpr</CODE>
- commands. </P>
+<P>The <CODE>job-id</CODE> is the number that was reported to you by the
+ <CODE>lp</CODE> or <CODE>lpstat</CODE> commands.</P>
+<H1 ALIGN="RIGHT"><A NAME="STANDARD_OPTIONS">3 - Standard Printer
+ Options</A></H1>
+<P>This chapter describes the standard printer options that are
+ available when printing with the <CODE>lp</CODE> and <CODE>lpr</CODE>
+ commands.</P>
 <H2><A NAME="4_1">General Options</A></H2>
-<P>The following options apply when printing all types of files. </P>
+<P>The following options apply when printing all types of files.</P>
 <H3><A NAME="4_1_1">Setting the Orientation</A></H3>
-<P>The <CODE>-o landscape</CODE> option will rotate the page 90 degrees 
-to print in landscape orientation: </P>
+<P>The <CODE>-o landscape</CODE> option will rotate the page 90 degrees
+ to print in landscape orientation:</P>
 <UL>
 <PRE>
 <B>lp -o landscape filename ENTER</B>
@@ -466,8 +468,8 @@ to print in landscape orientation: </P>
 
 <!-- NEED 2in -->
 <H3><A NAME="4_1_2">Selecting the Media Size, Type, and Source</A></H3>
-<P>The <CODE>-o media=xyz</CODE> option sets the media size, type, 
-and/or source: </P>
+<P>The <CODE>-o media=xyz</CODE> option sets the media size, type,
+ and/or source:</P>
 <UL>
 <PRE>
 <B>lp -o media=Letter filename ENTER</B>
@@ -478,31 +480,31 @@ and/or source: </P>
 </UL>
 
 <!-- NEED 3in -->
-<P>The available media sizes, types, and sources depend on the printer, 
-but most support the following options (case is not significant): </P>
-<UL>
-<LI><CODE>Letter</CODE> - US Letter (8.5x11 inches, or 216x279mm) </LI>
-<LI><CODE>Legal</CODE> - US Legal (8.5x14 inches, or 216x356mm) </LI>
-<LI><CODE>A4</CODE> - ISO A4 (8.27x11.69 inches, or 210x297mm) </LI>
-<LI><CODE>COM10</CODE> - US #10 Envelope (9.5x4.125 inches, or 
- 241x105mm) </LI>
-<LI><CODE>DL</CODE> - ISO DL Envelope (8.66x4.33 inches, or 220x110mm) </LI>
-<LI><CODE>Transparency</CODE> - Transparency media type or source </LI>
-<LI><CODE>Upper</CODE> - Upper paper tray </LI>
-<LI><CODE>Lower</CODE> - Lower paper tray </LI>
-<LI><CODE>MultiPurpose</CODE> - Multi-purpose paper tray </LI>
-<LI><CODE>LargeCapacity</CODE> - Large capacity paper tray </LI>
-</UL>
-<P>The actual options supported are defined in the printer's PPD file 
-in the <CODE>PageSize</CODE>, <CODE>InputSlot</CODE>, and <CODE>
-MediaType</CODE> options. </P>
+<P>The available media sizes, types, and sources depend on the printer,
+ but most support the following options (case is not significant):</P>
+<UL>
+<LI><CODE>Letter</CODE> - US Letter (8.5x11 inches, or 216x279mm)</LI>
+<LI><CODE>Legal</CODE> - US Legal (8.5x14 inches, or 216x356mm)</LI>
+<LI><CODE>A4</CODE> - ISO A4 (8.27x11.69 inches, or 210x297mm)</LI>
+<LI><CODE>COM10</CODE> - US #10 Envelope (9.5x4.125 inches, or
+ 241x105mm)</LI>
+<LI><CODE>DL</CODE> - ISO DL Envelope (8.66x4.33 inches, or 220x110mm)</LI>
+<LI><CODE>Transparency</CODE> - Transparency media type or source</LI>
+<LI><CODE>Upper</CODE> - Upper paper tray</LI>
+<LI><CODE>Lower</CODE> - Lower paper tray</LI>
+<LI><CODE>MultiPurpose</CODE> - Multi-purpose paper tray</LI>
+<LI><CODE>LargeCapacity</CODE> - Large capacity paper tray</LI>
+</UL>
+<P>The actual options supported are defined in the printer's PPD file in
+ the <CODE>PageSize</CODE>, <CODE>InputSlot</CODE>, and <CODE>MediaType</CODE>
+ options.</P>
 <H3><A NAME="4_1_3">Printing On Both Sides of the Paper</A></H3>
-<P>The <CODE>-o sides=two-sided-short-edge</CODE> and <CODE>-o 
-sides=two-sided-long-edge</CODE> options will enable duplexing on the 
-printer, if the printer supports it. The <CODE>-o 
-sides=two-sided-short-edge</CODE> option is suitable for landscape 
-pages, while the <CODE>-o sides=two-sided-long-edge</CODE> option is 
-suitable for portrait pages: </P>
+<P>The <CODE>-o sides=two-sided-short-edge</CODE> and <CODE>-o
+ sides=two-sided-long-edge</CODE> options will enable duplexing on the
+ printer, if the printer supports it. The <CODE>-o
+ sides=two-sided-short-edge</CODE> option is suitable for landscape
+ pages, while the <CODE>-o sides=two-sided-long-edge</CODE> option is
+ suitable for portrait pages:</P>
 <UL>
 <PRE>
 <B>lp -o sides=two-sided-short-edge filename ENTER</B>
@@ -510,7 +512,7 @@ suitable for portrait pages: </P>
 <B>lpr -o sides=two-sided-long-edge filename ENTER</B>
 </PRE>
 </UL>
-<P>The default is to print single-sided: </P>
+<P>The default is to print single-sided:</P>
 <UL>
 <PRE>
 <B>lp -o sides=one-sided filename ENTER</B>
@@ -518,10 +520,10 @@ suitable for portrait pages: </P>
 </PRE>
 </UL>
 <H2><A NAME="4_2">Banner Options</A></H2>
-<P>The following options apply when printing all types of files. </P>
+<P>The following options apply when printing all types of files.</P>
 <H3><A NAME="4_2_1">Selecting the Banner Page(s)</A></H3>
-<P>The <CODE>-o jobsheets=start,end</CODE> option sets the banner 
-page(s) to use for a job: </P>
+<P>The <CODE>-o jobsheets=start,end</CODE> option sets the banner
+ page(s) to use for a job:</P>
 <UL>
 <PRE>
 <B>lp -o job-sheets=none filename ENTER</B>
@@ -529,31 +531,31 @@ page(s) to use for a job: </P>
 <B>lpr -o job-sheets=classified,classified filename ENTER</B>
 </PRE>
 </UL>
-<P>If only one banner file is specified, it will be printed before the 
-files in the job. If a second banner file is specified, it is printed 
-after the files in the job. </P>
-<P>The available banner pages depend on the local system configuration; 
-CUPS includes the following banner files: </P>
-<UL>
-<LI><CODE>none</CODE> - Do not produce a banner page. </LI>
-<LI><CODE>classified</CODE> - A banner page with a &quot;classified&quot;  label 
-at the top and bottom. </LI>
-<LI><CODE>confidential</CODE> - A banner page with a  &quot;confidential&quot; 
-label at the top and bottom. </LI>
-<LI><CODE>secret</CODE> - A banner page with a &quot;secret&quot; label  at the 
-top and bottom. </LI>
-<LI><CODE>standard</CODE> - A banner page with no label at the  top and 
-bottom. </LI>
-<LI><CODE>topsecret</CODE> - A banner page with a &quot;top secret&quot;  label 
-at the top and bottom. </LI>
-<LI><CODE>unclassified</CODE> - A banner page with an  &quot;unclassified&quot; 
-label at the top and bottom. </LI>
+<P>If only one banner file is specified, it will be printed before the
+ files in the job. If a second banner file is specified, it is printed
+ after the files in the job.</P>
+<P>The available banner pages depend on the local system configuration;
+ CUPS includes the following banner files:</P>
+<UL>
+<LI><CODE>none</CODE> - Do not produce a banner page.</LI>
+<LI><CODE>classified</CODE> - A banner page with a &quot;classified&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>confidential</CODE> - A banner page with a &quot;confidential&quot;
+ label at the top and bottom.</LI>
+<LI><CODE>secret</CODE> - A banner page with a &quot;secret&quot; label at the top
+ and bottom.</LI>
+<LI><CODE>standard</CODE> - A banner page with no label at the top and
+ bottom.</LI>
+<LI><CODE>topsecret</CODE> - A banner page with a &quot;top secret&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>unclassified</CODE> - A banner page with an &quot;unclassified&quot;
+ label at the top and bottom.</LI>
 </UL>
 <H2><A NAME="4_3">Document Options</A></H2>
-<P>The following options apply when printing all types of files. </P>
+<P>The following options apply when printing all types of files.</P>
 <H3><A NAME="4_3_1">Selecting a Range of Pages</A></H3>
-<P>The <CODE>-o page-ranges=pages</CODE> option selects a range of 
-pages for printing: </P>
+<P>The <CODE>-o page-ranges=pages</CODE> option selects a range of pages
+ for printing:</P>
 <UL>
 <PRE>
 <B>lp -o page-ranges=1 filename ENTER</B>
@@ -562,14 +564,14 @@ pages for printing: </P>
 <B>lpr -o page-ranges=1-4,7,9-12 filename ENTER</B>
 </PRE>
 </UL>
-<P>As shown above, the <CODE>pages</CODE> value can be a single page, a 
-range of pages, or a collection of page numbers and ranges separated by 
-commas. The pages will always be printed in ascending order, regardless 
-of the order of the pages in the <CODE>page-ranges</CODE> option. </P>
-<P>The default is to print all pages. </P>
+<P>As shown above, the <CODE>pages</CODE> value can be a single page, a
+ range of pages, or a collection of page numbers and ranges separated by
+ commas. The pages will always be printed in ascending order, regardless
+ of the order of the pages in the <CODE>page-ranges</CODE> option.</P>
+<P>The default is to print all pages.</P>
 <H3><A NAME="4_3_2">Selecting Even or Odd Pages</A></H3>
-<P>Use the <CODE>-o page-set=set</CODE> option to select the even or 
-odd pages: </P>
+<P>Use the <CODE>-o page-set=set</CODE> option to select the even or odd
+ pages:</P>
 <UL>
 <PRE>
 <B>lp -o page-set=odd filename ENTER</B>
@@ -577,11 +579,11 @@ odd pages: </P>
 <B>lpr -o page-set=even filename ENTER</B>
 </PRE>
 </UL>
-<P>The default is to print all pages. </P>
+<P>The default is to print all pages.</P>
 <H3><A NAME="4_3_3">N-Up Printing</A></H3>
-<P>The <CODE>-o number-up=value</CODE> option selects N-Up printing. 
- N-Up printing places multiple document pages on a single printed page. 
- CUPS supports 1-Up, 2-Up, and 4-Up formats: </P>
+<P>The <CODE>-o number-up=value</CODE> option selects N-Up printing.
+ N-Up printing places multiple document pages on a single printed page.
+ CUPS supports 1-Up, 2-Up, and 4-Up formats:</P>
 <UL>
 <PRE>
 <B>lp -o number-up=1 filename ENTER</B>
@@ -590,34 +592,34 @@ odd pages: </P>
 <B>lpr -o number-up=4 filename ENTER</B>
 </PRE>
 </UL>
-<P>The default format is 1-Up. </P>
+<P>The default format is 1-Up.</P>
 <H3><A NAME="4_3_4">Setting the Brightness</A></H3>
-<P>You can control the overall brightness of the printed output using 
-the <CODE>-o brightness=percent</CODE> option: </P>
+<P>You can control the overall brightness of the printed output using
+ the <CODE>-o brightness=percent</CODE> option:</P>
 <UL>
 <PRE>
 <B>lp -o brightness=120 filename ENTER</B>
 <B>lpr -o brightness=120 filename ENTER</B>
 </PRE>
 </UL>
-<P>Values greater than 100 will lighten the print, while values less 
-than 100 will darken it. </P>
+<P>Values greater than 100 will lighten the print, while values less
+ than 100 will darken it.</P>
 <H3><A NAME="4_3_5">Setting the Gamma Correction</A></H3>
-<P>You can control the overall gamma correction of the printed output 
-using the <CODE>-o gamma=value</CODE> option: </P>
+<P>You can control the overall gamma correction of the printed output
+ using the <CODE>-o gamma=value</CODE> option:</P>
 <UL>
 <PRE>
 <B>lp -o gamma=1700 filename ENTER</B>
 <B>lpr -o gamma=1700 filename ENTER</B>
 </PRE>
 </UL>
-<P>Values greater than 1000 will lighten the print, while values less 
-than 1000 will darken it. The default gamma is 1000. </P>
+<P>Values greater than 1000 will lighten the print, while values less
+ than 1000 will darken it. The default gamma is 1000.</P>
 <H2><A NAME="4_4">Text Options</A></H2>
-<P>The following options apply when printing text files. </P>
+<P>The following options apply when printing text files.</P>
 <H3><A NAME="4_4_1">Setting the Number of Characters Per Inch</A></H3>
-<P>The <CODE>-o cpi=value</CODE> option sets the number of characters 
-per inch: </P>
+<P>The <CODE>-o cpi=value</CODE> option sets the number of characters
+ per inch:</P>
 <UL>
 <PRE>
 <B>lp -o cpi=10 filename ENTER</B>
@@ -625,32 +627,32 @@ per inch: </P>
 <B>lpr -o cpi=17 filename ENTER</B>
 </PRE>
 </UL>
-<P>The default characters per inch is 10. </P>
+<P>The default characters per inch is 10.</P>
 <H3><A NAME="4_4_2">Setting the Number of Lines Per Inch</A></H3>
-<P>The <CODE>-o lpi=value</CODE> option sets the number of lines per 
-inch: </P>
+<P>The <CODE>-o lpi=value</CODE> option sets the number of lines per
+ inch:</P>
 <UL>
 <PRE>
 <B>lp -o lpi=6 filename ENTER</B>
 <B>lpr -o lpi=8 filename ENTER</B>
 </PRE>
 </UL>
-<P>The default lines per inch is 6. </P>
+<P>The default lines per inch is 6.</P>
 <H3><A NAME="4_4_3">Setting the Number of Columns</A></H3>
-<P>The <CODE>-o columns=value</CODE> option sets the number of text 
-columns: </P>
+<P>The <CODE>-o columns=value</CODE> option sets the number of text
+ columns:</P>
 <UL>
 <PRE>
 <B>lp -o columns=2 filename ENTER</B>
 <B>lpr -o columns=3 filename ENTER</B>
 </PRE>
 </UL>
-<P>The default number of columns is 1. </P>
+<P>The default number of columns is 1.</P>
 <H3><A NAME="4_4_4">Setting the Page Margins</A></H3>
-<P>Normally the page margins are set to the hard limits of the printer. 
-Use the <CODE>-o page-left=value</CODE>, <CODE>-o page-right=value</CODE>
+<P>Normally the page margins are set to the hard limits of the printer.
+ Use the <CODE>-o page-left=value</CODE>, <CODE>-o page-right=value</CODE>
 , <CODE>-o page-top=value</CODE>, and <CODE>-o page-bottom=value</CODE>
- options to adjust the page margins: </P>
+ options to adjust the page margins:</P>
 <UL>
 <PRE>
 <B>lp -o page-left=<I>value</I> filename ENTER</B>
@@ -660,13 +662,13 @@ Use the <CODE>-o page-left=value</CODE>, <CODE>-o page-right=value</CODE>
 <B>lpr -o page-bottom=<I>value</I> filename ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>value</CODE> argument is the margin in points; each point 
-is 1/72 inch or 0.35mm. </P>
+<P>The <CODE>value</CODE> argument is the margin in points; each point
+ is 1/72 inch or 0.35mm.</P>
 <H3><A NAME="4_4_5">Pretty Printing</A></H3>
-<P>The <CODE>-o prettyprint</CODE> option puts a header at the top of 
-each page with the page number, job title (usually the filename), and 
-the date. Also, C and C++ keywords are highlighted, and comment lines 
-are italicized: </P>
+<P>The <CODE>-o prettyprint</CODE> option puts a header at the top of
+ each page with the page number, job title (usually the filename), and
+ the date. Also, C and C++ keywords are highlighted, and comment lines
+ are italicized:</P>
 <UL>
 <PRE>
 <B>lp -o prettyprint filename ENTER</B>
@@ -674,49 +676,57 @@ are italicized: </P>
 </PRE>
 </UL>
 <H2><A NAME="4_5">Image Options</A></H2>
-<P>The following options apply when printing image files. </P>
+<P>The following options apply when printing image files.</P>
 <H3><A NAME="4_5_1">Positioning the Image</A></H3>
-<P>The <CODE>-o position=name</CODE> option specifies the position of 
-the image on the page: </P>
-<UL>
-<LI><CODE>center</CODE> - Center the image on the page (default) </LI>
-<LI><CODE>top</CODE> - Print the image centered at the top of the page </LI>
-<LI><CODE>left</CODE> - Print the image centered on the left of page </LI>
-<LI><CODE>right</CODE> - Print the image centered on the right of the 
-page </LI>
-<LI><CODE>top-left</CODE> - Print the image at the top left corner of 
- the page </LI>
-<LI><CODE>top-right</CODE> - Print the image at the top right corner of 
- the page </LI>
-<LI><CODE>bottom</CODE> - Print the image centered at the bottom of 
the page </LI>
-<LI><CODE>bottom-left</CODE> - Print the image at the bottom left 
corner of the page </LI>
-<LI><CODE>bottom-right</CODE> - Print the image at the bottom right 
- corner of the page </LI>
+<P>The <CODE>-o position=name</CODE> option specifies the position of
+ the image on the page:</P>
+<UL>
+<LI><CODE>center</CODE> - Center the image on the page (default)</LI>
+<LI><CODE>top</CODE> - Print the image centered at the top of the page</LI>
+<LI><CODE>left</CODE> - Print the image centered on the left of page</LI>
+<LI><CODE>right</CODE> - Print the image centered on the right of the
+ page</LI>
+<LI><CODE>top-left</CODE> - Print the image at the top left corner of
+ the page</LI>
+<LI><CODE>top-right</CODE> - Print the image at the top right corner of
+ the page</LI>
+<LI><CODE>bottom</CODE> - Print the image centered at the bottom of the
page</LI>
+<LI><CODE>bottom-left</CODE> - Print the image at the bottom left corner
of the page</LI>
+<LI><CODE>bottom-right</CODE> - Print the image at the bottom right
+ corner of the page</LI>
 </UL>
 <H3><A NAME="4_5_2">Scaling the Image</A></H3>
-<P>The <CODE>-o scaling=percent</CODE> and <CODE>-o ppi=value</CODE>
- options change the size of a printed image: </P>
+<P>The <CODE>-o scaling=percent</CODE>, <CODE>-o ppi=value</CODE>, and <CODE>
+-o natural-scaling=percent</CODE> options change the size of a printed
+ image:</P>
 <UL>
 <PRE>
 <B>lp -o scaling=<I>percent</I> filename ENTER</B>
 <B>lp -o ppi=<I>value</I> filename ENTER</B>
-<B>lpr -o ppi=<I>value</I> filename ENTER</B>
+<B>lpr -o natural-scaling=<I>percent</I> filename ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>percent</CODE> value is a number from 1 to 800 specifying 
-the size in relation to the page (<I>not</I> the image.) A scaling of 
-100 percent will fill the page as completely as the image aspect ratio 
-allows. A scaling of 200 percent will print on up to 4 pages. </P>
-<P>The ppi <CODE>value</CODE> is a number from 1 to 1200 specifying the 
-resolution of the image in pixels per inch. An image that is 3000x2400 
-pixels will print 10x8 inches at 300 pixels per inch, for example. If 
-the specified resolution makes the image larger than the page, multiple 
-pages will be printed to satisfy the request. </P>
+<P>The <CODE>scaling=percent</CODE> value is a number from 1 to 800
+ specifying the size in relation to the page (<I>not</I> the image.) A
+ scaling of 100 percent will fill the page as completely as the image
+ aspect ratio allows. A scaling of 200 percent will print on up to 4
+ pages.</P>
+<P>The <CODE>ppi=value</CODE> value is a number from 1 to 1200
+ specifying the resolution of the image in pixels per inch. An image
+ that is 3000x2400 pixels will print 10x8 inches at 300 pixels per inch,
+ for example. If the specified resolution makes the image larger than
+ the page, multiple pages will be printed to satisfy the request.</P>
+<P>The <CODE>natural-scaling=percent</CODE> value is a number from 1 to
+ 800 specifying the size in relation to the natural image size. A
+ scaling of 100 percent will print the image at its natural size, while
+ a scaling of 50 percent will print the image at half its natural size.
+ If the specified scaling makes the image larger than the page, multiple
+ pages will be printed to satisfy the request.</P>
 <H3><A NAME="4_5_3">Adjusting the Hue (Tint) of an Image</A></H3>
-<P>The <CODE>-o hue=value</CODE> option will adjust the hue of the 
-printed image, much like the tint control on your television: </P>
+<P>The <CODE>-o hue=value</CODE> option will adjust the hue of the
+ printed image, much like the tint control on your television:</P>
 <UL>
 <PRE>
 <B>lp -o hue=<I>value</I> filename ENTER</B>
@@ -725,9 +735,9 @@ printed image, much like the tint control on your television: </P>
 </UL>
 
 <!-- NEED 3in -->
-<P>The <CODE>value</CODE> argument is a number from -360 to 360 and 
-represents the color hue rotation. The following table summarizes the 
-change you'll see with different colors: 
+<P>The <CODE>value</CODE> argument is a number from -360 to 360 and
+ represents the color hue rotation. The following table summarizes the
+ change you'll see with different colors:
 <CENTER>
 <TABLE BORDER="1" WIDTH="50%">
 <TR><TH>Original</TH><TH>hue=-45</TH><TH>hue=45</TH></TR>
@@ -740,84 +750,83 @@ change you'll see with different colors:
 </TABLE>
 </CENTER>
 </P>
-<P>The default hue adjustment is 0. </P>
+<P>The default hue adjustment is 0.</P>
 <H3><A NAME="4_5_4">Adjusting the Saturation (Color) of an Image</A></H3>
-<P>The <CODE>-o saturation=percent</CODE> option adjusts the saturation 
-of the colors in an image, much like the color knob on your television: </P>
+<P>The <CODE>-o saturation=percent</CODE> option adjusts the saturation
+ of the colors in an image, much like the color knob on your television:</P>
 <UL>
 <PRE>
 <B>lp -o saturation=<I>percent</I> filename ENTER</B>
 <B>lpr -o saturation=<I>percent</I> filename ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>percent</CODE> argument specifies the color saturation 
-from 0 to 200. A color saturation of 0 produces a black-and-white 
-print, while a value of 200 will make the colors extremely intense. </P>
-<P>The default saturation is 100. 
+<P>The <CODE>percent</CODE> argument specifies the color saturation from
+ 0 to 200. A color saturation of 0 produces a black-and-white print,
+ while a value of 200 will make the colors extremely intense.</P>
+<P>The default saturation is 100.
 <!-- NEED 4in -->
 </P>
 <H2><A NAME="4_6">HP-GL/2 Options</A></H2>
-<P>The following options apply to HP-GL/2 files. </P>
+<P>The following options apply to HP-GL/2 files.</P>
 <H3><A NAME="4_6_1">Printing in Black</A></H3>
-<P>The <CODE>-o blackplot</CODE> option specifies that all pens should 
-plot in black: </P>
+<P>The <CODE>-o blackplot</CODE> option specifies that all pens should
+ plot in black:</P>
 <UL>
 <PRE>
 <B>lp -o blackplot filename ENTER</B>
 <B>lpr -o blackplot filename ENTER</B>
 </PRE>
 </UL>
-<P>The default is to use the colors defined in the plot file or the 
-standard pen colors defined in the HP-GL/2 reference manual from 
-Hewlett Packard. </P>
+<P>The default is to use the colors defined in the plot file or the
+ standard pen colors defined in the HP-GL/2 reference manual from
+ Hewlett Packard.</P>
 <H3><A NAME="4_6_2">Fitting the Plot on the Page</A></H3>
-<P>The <CODE>-o fitplot</CODE> option specifies that the plot should be 
-scaled to fit on the page: </P>
+<P>The <CODE>-o fitplot</CODE> option specifies that the plot should be
+ scaled to fit on the page:</P>
 <UL>
 <PRE>
 <B>lp -o fitplot filename ENTER</B>
 <B>lpr -o fitplot filename ENTER</B>
 </PRE>
 </UL>
-<P>The default is to use the absolute distances specified in the plot 
-file. 
+<P>The default is to use the absolute distances specified in the plot
+ file.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>This feature depends upon an accurate plot size (<CODE>PS</CODE>) 
- command in the HP-GL/2 file. If no plot size is given in the file 
- than the HP-GL/2 filter assumes the plot is ANSI E size. </P>
+<P>This feature depends upon an accurate plot size (<CODE>PS</CODE>)
+ command in the HP-GL/2 file. If no plot size is given in the file than
+ the HP-GL/2 filter assumes the plot is ANSI E size.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H3><A NAME="4_6_3">Setting the Default Pen Width</A></H3>
-<P>The <CODE>-o penwidth=value</CODE> option specifies the default pen 
-width for HP-GL/2 files: </P>
+<P>The <CODE>-o penwidth=value</CODE> option specifies the default pen
+ width for HP-GL/2 files:</P>
 <UL>
 <PRE>
 <B>lp -o penwidth=<I>value</I> filename ENTER</B>
 <B>lpr -o penwidth=<I>value</I> filename ENTER</B>
 </PRE>
 </UL>
-<P>The pen width <CODE>value</CODE> specifies the pen width in 
-micrometers. The default value of 1000 produces lines that are 1 
-millimeter in width. Specifying a pen width of 0 produces lines that 
-are exactly 1 pixel wide. 
+<P>The pen width <CODE>value</CODE> specifies the pen width in
+ micrometers. The default value of 1000 produces lines that are 1
+ millimeter in width. Specifying a pen width of 0 produces lines that
+ are exactly 1 pixel wide.
 <CENTER>
 <TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
 <TR><TD><B> NOTE:</B>
-<P>This option is ignored when the pen widths are set in the  plot 
-file. </P>
+<P>This option is ignored when the pen widths are set in the plot file.</P>
 </TD></TR>
 </TABLE>
 </CENTER>
 </P>
 <H2><A NAME="4_7">Raw or Unfiltered Output</A></H2>
-<P>The <CODE>-o raw</CODE> option allows you to send files directly to 
-a printer without filtering. This is sometimes required when printing 
-from applications that provide their own &quot;printer drivers&quot; for your 
-printer: </P>
+<P>The <CODE>-o raw</CODE> option allows you to send files directly to a
+ printer without filtering. This is sometimes required when printing
+ from applications that provide their own &quot;printer drivers&quot; for your
+ printer:</P>
 <UL>
 <PRE>
 <B>lp -o raw filename ENTER</B>
@@ -825,37 +834,37 @@ printer: </P>
 </PRE>
 </UL>
 <P>The <CODE>-l</CODE> option can also be used with the <CODE>lpr</CODE>
- command to send files directly to a printer: </P>
+ command to send files directly to a printer:</P>
 <UL>
 <PRE>
 <B>lpr -l filename ENTER</B>
 </PRE>
 </UL>
-<H1 ALIGN="RIGHT"><A NAME="SAVING_OPTIONS">4 - Saving Printer Options 
-and Defaults</A></H1>
-<P>This chapter describes how to save printer options for your printer 
-and set your own default printer. </P>
+<H1 ALIGN="RIGHT"><A NAME="SAVING_OPTIONS">4 - Saving Printer Options
+ and Defaults</A></H1>
+<P>This chapter describes how to save printer options for your printer
+ and set your own default printer.</P>
 <H2><A NAME="5_1">Printer Options</A></H2>
-<P>Each printer supports a large number of options, which you learned 
-about in <A HREF="#STANDARD_OPTIONS">Chapter 3, &quot;Standard Printer 
-Options&quot;</A>. Rather than specifying these options each time you print 
-a file, CUPS allows you to save them as &quot;default&quot; options for the 
-printer. </P>
-<P>The <CODE>lpoptions(1)</CODE> command saves the options for your 
-printers. Like the <CODE>lp</CODE> and <CODE>lpr</CODE> commands, it 
-accepts printer options using the <CODE>-o</CODE> argument: </P>
+<P>Each printer supports a large number of options, which you learned
+ about in<A HREF="#STANDARD_OPTIONS"> Chapter 3, &quot;Standard Printer
+ Options&quot;</A>. Rather than specifying these options each time you print
+ a file, CUPS allows you to save them as &quot;default&quot; options for the
+ printer.</P>
+<P>The <CODE>lpoptions(1)</CODE> command saves the options for your
+ printers. Like the <CODE>lp</CODE> and <CODE>lpr</CODE> commands, it
+ accepts printer options using the <CODE>-o</CODE> argument:</P>
 <UL>
 <PRE>
 <B>lpoptions -o media=A4 -o sides=two-sided-long-edge ENTER</B>
 <B>lpoptions -o media=Legal -o scaling=100 ENTER</B>
 </PRE>
 </UL>
-<P>Once saved, any <CODE>lp</CODE> or <CODE>lpr</CODE> command will use 
-them when you print. </P>
+<P>Once saved, any <CODE>lp</CODE> or <CODE>lpr</CODE> command will use
+ them when you print.</P>
 <H2><A NAME="5_2">Setting Options for a Specific Printer</A></H2>
-<P>The previous example shows how to set the options for the default 
-printer. The <CODE>-p printer</CODE> option specifies the options are 
-for another printer: </P>
+<P>The previous example shows how to set the options for the default
+ printer. The <CODE>-p printer</CODE> option specifies the options are
+ for another printer:</P>
 <UL>
 <PRE>
 <B>lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTER</B>
@@ -863,8 +872,8 @@ for another printer: </P>
 </PRE>
 </UL>
 <H2><A NAME="5_3">Viewing the Current Defaults</A></H2>
-<P>The <CODE>lpoptions</CODE> command can also be used to show the 
-current options by not specifying any new options on the command-line: </P>
+<P>The <CODE>lpoptions</CODE> command can also be used to show the
+ current options by not specifying any new options on the command-line:</P>
 <UL>
 <PRE>
 <B>lpoptions ENTER</B>
@@ -874,28 +883,28 @@ media=Legal scaling=100
 </PRE>
 </UL>
 <H2><A NAME="5_4">Setting the Default Printer</A></H2>
-<P>The administrator normally will set a system-wide default printer 
-that is normally used as the default printer by everyone. Use the <CODE>
--d printer</CODE> option to set your own default printer: </P>
+<P>The administrator normally will set a system-wide default printer
+ that is normally used as the default printer by everyone. Use the <CODE>
+-d printer</CODE> option to set your own default printer:</P>
 <UL>
 <PRE>
 <B>lpoptions -d deskjet ENTER</B>
 </PRE>
 </UL>
 <P>The printer can be local (<CODE>deskjet</CODE>) or remote (<CODE>
-deskjet@server</CODE>). </P>
+deskjet@server</CODE>).</P>
 <H2><A NAME="5_5">Printer Instances</A></H2>
-<P>Besides setting options for each print queue, CUPS supports <I>
-printer instances</I> which allow you to define several different sets 
-of options for each printer. You specify a printer instance using the 
-slash (<CODE>/</CODE>) character: </P>
+<P>Besides setting options for each print queue, CUPS supports<I>
+ printer instances</I> which allow you to define several different sets
+ of options for each printer. You specify a printer instance using the
+ slash (<CODE>/</CODE>) character:</P>
 <UL>
 <PRE>
 <B>lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTER</B>
 <B>lpoptions -p laserjet/legal -o media=Legal ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>lp</CODE> and lpr commands also understand this notation: </P>
+<P>The <CODE>lp</CODE> and lpr commands also understand this notation:</P>
 <UL>
 <PRE>
 <B>lp -d laserjet/duplex filename ENTER</B>
@@ -903,8 +912,8 @@ slash (<CODE>/</CODE>) character: </P>
 </PRE>
 </UL>
 <H2><A NAME="5_6">Removing Instances</A></H2>
-<P>Use the <CODE>-x printer/instance</CODE> option to remove a printer 
-instance that you no longer need: </P>
+<P>Use the <CODE>-x printer/instance</CODE> option to remove a printer
+ instance that you no longer need:</P>
 <UL>
 <PRE>
 <B>lpoptions -x laserjet ENTER</B>
@@ -912,86 +921,85 @@ instance that you no longer need: </P>
 <B>lpoptions -x laserjet/legal ENTER</B>
 </PRE>
 </UL>
-<P>The <CODE>-x</CODE> option only removes the default options for that 
-printer and instance; the original print queue will remain until 
-deleted with the <CODE>lpadmin(8)</CODE> command by the administrator. </P>
+<P>The <CODE>-x</CODE> option only removes the default options for that
+ printer and instance; the original print queue will remain until
+ deleted with the <CODE>lpadmin(8)</CODE> command by the administrator.</P>
 <H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
-<H2 ALIGN="CENTER"><A NAME="6_1">Common UNIX Printing System License 
-Agreement</A></H2>
+<H2 ALIGN="CENTER"><A NAME="6_1">Common UNIX Printing System License
+ Agreement</A></H2>
 <P ALIGN="CENTER">Copyright 1997-2001 by Easy Software Products
 <BR> 44141 AIRPORT VIEW DR STE 204
 <BR> HOLLYWOOD, MARYLAND 20636-3111 USA
 <BR>
 <BR> Voice: +1.301.373.9600
-<BR> Email: <A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
-<BR> WWW: <A HREF="http://www.cups.org">http://www.cups.org</A></P>
+<BR> Email:<A HREF="mailto:cups-info@cups.org"> cups-info@cups.org</A>
+<BR> WWW:<A HREF="http://www.cups.org"> http://www.cups.org</A></P>
 <H3><A NAME="6_1_1">Introduction</A></H3>
-<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;), 
-is provided under the GNU General Public License (&quot;GPL&quot;) and GNU 
-Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these 
-licenses follow this introduction. </P>
-<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot; 
-subdirectory of the CUPS source distribution and in the 
-&quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups.sl&quot;, or 
-&quot;libcups.so&quot; files in the binary distributions. </P>
-<P>The GNU GPL applies to the remainder of the CUPS distribution, 
-including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript 
-5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.90. </P>
-<P>For those not familiar with the GNU GPL, the license basically 
-allows you to: </P>
-<UL>
-<LI>Use the CUPS software at no charge. </LI>
-<LI>Distribute verbatim copies of the software in source or  binary 
-form. </LI>
-<LI>Sell verbatim copies of the software for a media fee, or  sell 
-support for the software. </LI>
-<LI>Distribute or sell printer drivers and filters that use  CUPS so 
-long as source code is made available under the GPL. </LI>
-</UL>
-<P>What this license <B>does not</B> allow you to do is make changes or 
-add features to CUPS and then sell a binary distribution without source 
-code. You must provide source for any new drivers, changes, or 
-additions to the software, and all code must be provided under the GPL 
-or LGPL as appropriate. </P>
-<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to 
-develop applications that use the CUPS API library under other licenses 
-and/or conditions as appropriate for your application. </P>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these
+ licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the
+ &quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups_s.a&quot;,
+ &quot;libcups.sl&quot;, or &quot;libcups.so&quot; files in the binary distributions.</P>
+<P>The GNU GPL applies to the remainder of the CUPS distribution,
+ including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript
+ 5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.93a.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
 <H3><A NAME="6_1_2">Trademarks</A></H3>
-<P>Easy Software Products has trademarked the Common UNIX Printing 
-System, CUPS, and CUPS logo. These names and logos may be used freely 
-in any direct port or binary distribution of CUPS. To use them in 
-derivative products, please contract Easy Software Products for written 
-permission. Our intention is to protect the value of these trademarks 
-and ensure that any derivative product meets the same high-quality 
-standards as the original. </P>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. These names and logos may be used freely
+ in any direct port or binary distribution of CUPS. To use them in
+ derivative products, please contract Easy Software Products for written
+ permission. Our intention is to protect the value of these trademarks
+ and ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
 <H3><A NAME="6_1_3">Binary Distribution Rights</A></H3>
-<P>Easy Software Products also sells rights to the CUPS source code 
-under a binary distribution license for vendors that are unable to 
-release source code for their drivers, additions, and modifications to 
-CUPS under the GNU GPL and LGPL. For information please contact us at 
-the address shown above. </P>
-<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that 
-utilizes the GNU GhostScript 5.50 core to convert PostScript files into 
-a stream of raster images. For binary distribution licensing of this 
-software, please contact: <BLOCKQUOTE> Miles Jones
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that
+ utilizes the GNU GhostScript 5.50 core to convert PostScript files into
+ a stream of raster images. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Miles Jones
 <BR> Director of Marketing
 <BR> Artifex Software Inc.
 <BR> 454 Las Gallinas Ave., Suite 108
 <BR> San Rafael, CA 94903 USA
 <BR> Voice: +1.415.492.9861
 <BR> Fax: +1.415.492.9862
-<BR> EMail: <A HREF="mailto:info@arsoft.com">info@arsoft.com</A></BLOCKQUOTE>
+<BR> EMail:<A HREF="mailto:info@arsoft.com"> info@arsoft.com</A></BLOCKQUOTE>
 </P>
-<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.90 software. For binary 
-distribution licensing of this software, please contact: <BLOCKQUOTE>
+<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.93a software. For binary
+ distribution licensing of this software, please contact:<BLOCKQUOTE>
  Derek B. Noonburg
-<BR> Email: <A HREF="mailto:derekn@foolabs.com">derekn@foolabs.com</A>
-<BR> WWW: <A HREF="http://www.foolabs.com/xpdf/">
-http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<BR> Email:<A HREF="mailto:derekn@foolabs.com"> derekn@foolabs.com</A>
+<BR> WWW:<A HREF="http://www.foolabs.com/xpdf/">
+ http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
 <H3><A NAME="6_1_4">Support</A></H3>
-<P>Easy Software Products sells software support for CUPS as well as a 
-commercial printing product based on CUPS called ESP Print Pro. You can 
-find out more at our web site: </P>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
 <UL>
 <PRE>
 <A HREF="http://www.easysw.com">http://www.easysw.com</A>
@@ -1000,7 +1008,7 @@ find out more at our web site: </P>
 
 <!-- NEW PAGE -->
 <H2><A NAME="6_2">GNU GENERAL PUBLIC LICENSE</A></H2>
-<P>Version 2, June 1991 </P>
+<P>Version 2, June 1991</P>
 <PRE>
 Copyright 1989, 1991 Free Software Foundation, Inc.
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -1012,252 +1020,250 @@ copies of this license document, but changing it is not allowed.
 
 </PRE>
 <H4>Preamble</H4>
-<P>The licenses for most software are designed to take away your 
-freedom to share and change it.  By contrast, the GNU General Public 
-License is intended to guarantee your freedom to share and change free 
-software--to make sure the software is free for all its users.  This 
-General Public License applies to most of the Free Software 
-Foundation's software and to any other program whose authors commit to 
-using it.  (Some other Free Software Foundation software is covered by 
-the GNU Library General Public License instead.)  You can apply it to 
-your programs, too. </P>
-<P>When we speak of free software, we are referring to freedom, not 
-price.  Our General Public Licenses are designed to make sure that you 
-have the freedom to distribute copies of free software (and charge for 
-this service if you wish), that you receive source code or can get it 
-if you want it, that you can change the software or use pieces of it in 
-new free programs; and that you know you can do these things. </P>
-<P>To protect your rights, we need to make restrictions that forbid 
-anyone to deny you these rights or to ask you to surrender the rights. 
-These restrictions translate to certain responsibilities for you if you 
-distribute copies of the software, or if you modify it. </P>
-<P>For example, if you distribute copies of such a program, whether 
-gratis or for a fee, you must give the recipients all the rights that 
-you have.  You must make sure that they, too, receive or can get the 
-source code.  And you must show them these terms so they know their 
-rights. </P>
-<P>We protect your rights with two steps: (1) copyright the software, 
-and (2) offer you this license which gives you legal permission to 
-copy, distribute and/or modify the software. </P>
-<P>Also, for each author's protection and ours, we want to make certain 
-that everyone understands that there is no warranty for this free 
-software.  If the software is modified by someone else and passed on, 
-we want its recipients to know that what they have is not the original, 
-so that any problems introduced by others will not reflect on the 
-original authors' reputations. </P>
-<P>Finally, any free program is threatened constantly by software 
-patents.  We wish to avoid the danger that redistributors of a free 
-program will individually obtain patent licenses, in effect making the 
-program proprietary.  To prevent this, we have made it clear that any 
-patent must be licensed for everyone's free use or not licensed at all. </P>
-<P>The precise terms and conditions for copying, distribution and 
-modification follow. </P>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
 <H4>GNU GENERAL PUBLIC LICENSE
 <BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
 <OL START="0">
-<LI>This License applies to any program or other work which contains a 
-notice placed by the copyright holder saying it may be distributed 
-under the terms of this General Public License.  The &quot;Program&quot;, below, 
-refers to any such program or work, and a &quot;work based on the Program&quot; 
-means either the Program or any derivative work under copyright law: 
-that is to say, a work containing the Program or a portion of it, 
-either verbatim or with modifications and/or translated into another 
-language.  (Hereinafter, translation is included without limitation in 
-the term &quot;modification&quot;.)  Each licensee is addressed as &quot;you&quot;. </LI>
-<P>Activities other than copying, distribution and modification are not 
-covered by this License; they are outside its scope.  The act of 
-running the Program is not restricted, and the output from the Program 
-is covered only if its contents constitute a work based on the Program 
-(independent of having been made by running the Program). Whether that 
-is true depends on what the Program does. </P>
-<LI>You may copy and distribute verbatim copies of the Program's source 
-code as you receive it, in any medium, provided that you conspicuously 
-and appropriately publish on each copy an appropriate copyright notice 
-and disclaimer of warranty; keep intact all the notices that refer to 
-this License and to the absence of any warranty; and give any other 
-recipients of the Program a copy of this License along with the 
-Program. </LI>
-<P>You may charge a fee for the physical act of transferring a copy, 
-and you may at your option offer warranty protection in exchange for a 
-fee. </P>
-<LI>You may modify your copy or copies of the Program or any portion of 
-it, thus forming a work based on the Program, and copy and distribute 
-such modifications or work under the terms of Section 1 above, provided 
-that you also meet all of these conditions: 
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.</LI>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.</LI>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
 <OL TYPE="a">
-<LI>You must cause the modified files to carry prominent notices 
-stating that you changed the files and the date of any change. </LI>
-<LI>You must cause any work that you distribute or publish, that in 
-whole or in part contains or is derived from the Program or any part 
-thereof, to be licensed as a whole at no charge to all third parties 
-under the terms of this License. </LI>
-<LI>if the modified program normally reads commands interactively when 
-run, you must cause it, when started running for such interactive use 
-in the most ordinary way, to print or display an announcement including 
-an appropriate copyright notice and a notice that there is no warranty 
-(or else, saying that you provide a warranty) and that users may 
-redistribute the program under these conditions, and telling the user 
-how to view a copy of this License.  (Exception: if the Program itself 
-is interactive but does not normally print such an announcement, your 
-work based on the Program is not required to print an announcement.) </LI>
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
 </OL>
 </LI>
-<P>These requirements apply to the modified work as a whole.  If 
-identifiable sections of that work are not derived from the Program, 
-and can be reasonably considered independent and separate works in 
-themselves, then this License, and its terms, do not apply to those 
-sections when you distribute them as separate works.  But when you 
-distribute the same sections as part of a whole which is a work based 
-on the Program, the distribution of the whole must be on the terms of 
-this License, whose permissions for other licensees extend to the 
-entire whole, and thus to each and every part regardless of who wrote 
-it. </P>
-<P>Thus, it is not the intent of this section to claim rights or 
-contest your rights to work written entirely by you; rather, the intent 
-is to exercise the right to control the distribution of derivative or 
-collective works based on the Program. </P>
-<P>In addition, mere aggregation of another work not based on the 
-Program with the Program (or with a work based on the Program) on a 
-volume of a storage or distribution medium does not bring the other 
-work under the scope of this License. </P>
-<LI>You may copy and distribute the Program (or a work based on it, 
-under Section 2) in object code or executable form under the terms of 
-Sections 1 and 2 above provided that you also do one of the following: 
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
 <OL TYPE="a">
-<LI>Accompany it with the complete corresponding machine-readable 
-source code, which must be distributed under the terms of Sections 1 
-and 2 above on a medium customarily used for software interchange; or, </LI>
-<LI>Accompany it with a written offer, valid for at least three years, 
-to give any third party, for a charge no more than your cost of 
-physically performing source distribution, a complete machine-readable 
-copy of the corresponding source code, to be distributed under the 
-terms of Sections 1 and 2 above on a medium customarily used for 
-software interchange; or, </LI>
-<LI>Accompany it with the information you received as to the offer to 
-distribute corresponding source code.  (This alternative is allowed 
-only for noncommercial distribution and only if you received the 
-program in object code or executable form with such an offer, in accord 
-with Subsection b above.) </LI>
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
 </OL>
 </LI>
-<P>The source code for a work means the preferred form of the work for 
-making modifications to it.  For an executable work, complete source 
-code means all the source code for all modules it contains, plus any 
-associated interface definition files, plus the scripts used to control 
-compilation and installation of the executable.  However, as a special 
-exception, the source code distributed need not include anything that 
-is normally distributed (in either source or binary form) with the 
-major components (compiler, kernel, and so on) of the operating system 
-on which the executable runs, unless that component itself accompanies 
-the executable. </P>
-<P>If distribution of executable or object code is made by offering 
-access to copy from a designated place, then offering equivalent access 
-to copy the source code from the same place counts as distribution of 
-the source code, even though third parties are not compelled to copy 
-the source along with the object code. </P>
-<LI>You may not copy, modify, sublicense, or distribute the Program 
-except as expressly provided under this License.  Any attempt otherwise 
-to copy, modify, sublicense or distribute the Program is void, and will 
-automatically terminate your rights under this License. However, 
-parties who have received copies, or rights, from you under this 
-License will not have their licenses terminated so long as such parties 
-remain in full compliance. </LI>
-<LI>You are not required to accept this License, since you have not 
-signed it.  However, nothing else grants you permission to modify or 
-distribute the Program or its derivative works.  These actions are 
-prohibited by law if you do not accept this License.  Therefore, by 
-modifying or distributing the Program (or any work based on the 
-Program), you indicate your acceptance of this License to do so, and 
-all its terms and conditions for copying, distributing or modifying the 
-Program or works based on it. </LI>
-<LI>Each time you redistribute the Program (or any work based on the 
-Program), the recipient automatically receives a license from the 
-original licensor to copy, distribute or modify the Program subject to 
-these terms and conditions.  You may not impose any further 
-restrictions on the recipients' exercise of the rights granted herein. 
-You are not responsible for enforcing compliance by third parties to 
-this License. </LI>
-<LI>If, as a consequence of a court judgment or allegation of patent 
-infringement or for any other reason (not limited to patent issues), 
-conditions are imposed on you (whether by court order, agreement or 
-otherwise) that contradict the conditions of this License, they do not 
-excuse you from the conditions of this License.  If you cannot 
-distribute so as to satisfy simultaneously your obligations under this 
-License and any other pertinent obligations, then as a consequence you 
-may not distribute the Program at all.  For example, if a patent 
-license would not permit royalty-free redistribution of the Program by 
-all those who receive copies directly or indirectly through you, then 
-the only way you could satisfy both it and this License would be to 
-refrain entirely from distribution of the Program. </LI>
-<P>If any portion of this section is held invalid or unenforceable 
-under any particular circumstance, the balance of the section is 
-intended to apply and the section as a whole is intended to apply in 
-other circumstances. </P>
-<P>It is not the purpose of this section to induce you to infringe any 
-patents or other property right claims or to contest validity of any 
-such claims; this section has the sole purpose of protecting the 
-integrity of the free software distribution system, which is 
-implemented by public license practices.  Many people have made 
-generous contributions to the wide range of software distributed 
-through that system in reliance on consistent application of that 
-system; it is up to the author/donor to decide if he or she is willing 
-to distribute software through any other system and a licensee cannot 
-impose that choice. </P>
-<P>This section is intended to make thoroughly clear what is believed 
-to be a consequence of the rest of this License. </P>
-<LI>If the distribution and/or use of the Program is restricted in 
-certain countries either by patents or by copyrighted interfaces, the 
-original copyright holder who places the Program under this License may 
-add an explicit geographical distribution limitation excluding those 
-countries, so that distribution is permitted only in or among countries 
-not thus excluded.  In such case, this License incorporates the 
-limitation as if written in the body of this License. </LI>
-<LI>The Free Software Foundation may publish revised and/or new 
-versions of the General Public License from time to time.  Such new 
-versions will be similar in spirit to the present version, but may 
-differ in detail to address new problems or concerns. </LI>
-<P>Each version is given a distinguishing version number.  If the 
-Program specifies a version number of this License which applies to it 
-and &quot;any later version&quot;, you have the option of following the terms and 
-conditions either of that version or of any later version published by 
-the Free Software Foundation.  If the Program does not specify a 
-version number of this License, you may choose any version ever 
-published by the Free Software Foundation. </P>
-<LI>If you wish to incorporate parts of the Program into other free 
-programs whose distribution conditions are different, write to the 
-author to ask for permission.  For software which is copyrighted by the 
-Free Software Foundation, write to the Free Software Foundation; we 
-sometimes make exceptions for this.  Our decision will be guided by the 
-two goals of preserving the free status of all derivatives of our free 
-software and of promoting the sharing and reuse of software generally. </LI>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.</LI>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.</LI>
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
 </OL>
 <H4>NO WARRANTY</H4>
 <OL START="11">
-<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO 
-WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
- EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
-OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, 
-EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
- THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS 
-WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </LI>
-<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 
-AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU 
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 
-PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 
-FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF 
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
-DAMAGES. </LI>
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
 </OL>
 <H4>END OF TERMS AND CONDITIONS</H4>
 
 <!-- NEW PAGE -->
 <H2><A NAME="6_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
-<P>Version 2, June 1991 </P>
+<P>Version 2, June 1991</P>
 <PRE>
 Copyright (C) 1991 Free Software Foundation, Inc.
 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
@@ -1268,376 +1274,372 @@ of this license document, but changing it is not allowed.
  numbered 2 because it goes with version 2 of the ordinary GPL.]
 </PRE>
 <H4>Preamble</H4>
-<P>The licenses for most software are designed to take away your 
-freedom to share and change it.  By contrast, the GNU General Public 
-Licenses are intended to guarantee your freedom to share and change 
-free software--to make sure the software is free for all its users. </P>
-<P>This license, the Library General Public License, applies to some 
-specially designated Free Software Foundation software, and to any 
-other libraries whose authors decide to use it.  You can use it for 
-your libraries, too. </P>
-<P>When we speak of free software, we are referring to freedom, not 
-price.  Our General Public Licenses are designed to make sure that you 
-have the freedom to distribute copies of free software (and charge for 
-this service if you wish), that you receive source code or can get it 
-if you want it, that you can change the software or use pieces of it in 
-new free programs; and that you know you can do these things. </P>
-<P>To protect your rights, we need to make restrictions that forbid 
-anyone to deny you these rights or to ask you to surrender the rights. 
-These restrictions translate to certain responsibilities for you if you 
-distribute copies of the library, or if you modify it. </P>
-<P>For example, if you distribute copies of the library, whether gratis 
-or for a fee, you must give the recipients all the rights that we gave 
-you.  You must make sure that they, too, receive or can get the source 
-code.  If you link a program with the library, you must provide 
-complete object files to the recipients so that they can relink them 
-with the library, after making changes to the library and recompiling 
-it.  And you must show them these terms so they know their rights. </P>
-<P>Our method of protecting your rights has two steps: (1) copyright 
-the library, and (2) offer you this license which gives you legal 
-permission to copy, distribute and/or modify the library. </P>
-<P>Also, for each distributor's protection, we want to make certain 
-that everyone understands that there is no warranty for this free 
-library.  If the library is modified by someone else and passed on, we 
-want its recipients to know that what they have is not the original 
-version, so that any problems introduced by others will not reflect on 
-the original authors' reputations. </P>
-<P>Finally, any free program is threatened constantly by software 
-patents.  We wish to avoid the danger that companies distributing free 
-software will individually obtain patent licenses, thus in effect 
-transforming the program into proprietary software.  To prevent this, 
-we have made it clear that any patent must be licensed for everyone's 
-free use or not licensed at all. </P>
-<P>Most GNU software, including some libraries, is covered by the 
-ordinary GNU General Public License, which was designed for utility 
-programs.  This license, the GNU Library General Public License, 
-applies to certain designated libraries.  This license is quite 
-different from the ordinary one; be sure to read it in full, and don't 
-assume that anything in it is the same as in the ordinary license. </P>
-<P>The reason we have a separate public license for some libraries is 
-that they blur the distinction we usually make between modifying or 
-adding to a program and simply using it.  Linking a program with a 
-library, without changing the library, is in some sense simply using 
-the library, and is analogous to running a utility program or 
-application program.  However, in a textual and legal sense, the linked 
-executable is a combined work, a derivative of the original library, 
-and the ordinary General Public License treats it as such. </P>
-<P>Because of this blurred distinction, using the ordinary General 
-Public License for libraries did not effectively promote software 
-sharing, because most developers did not use the libraries.  We 
-concluded that weaker conditions might promote sharing better. </P>
-<P>However, unrestricted linking of non-free programs would deprive the 
-users of those programs of all benefit from the free status of the 
-libraries themselves.  This Library General Public License is intended 
-to permit developers of non-free programs to use free libraries, while 
-preserving your freedom as a user of such programs to change the free 
-libraries that are incorporated in them.  (We have not seen how to 
-achieve this as regards changes in header files, but we have achieved 
-it as regards changes in the actual functions of the Library.)  The 
-hope is that this will lead to faster development of free libraries. </P>
-<P>The precise terms and conditions for copying, distribution and 
-modification follow.  Pay close attention to the difference between a 
-&quot;work based on the library&quot; and a &quot;work that uses the library&quot;.  The 
-former contains code derived from the library, while the latter only 
-works together with the library. </P>
-<P>Note that it is possible for a library to be covered by the ordinary 
-General Public License rather than by this special one. </P>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
 <H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
-<P><STRONG>0.</STRONG> This License Agreement applies to any software 
-library which contains a notice placed by the copyright holder or other 
-authorized party saying it may be distributed under the terms of this 
-Library General Public License (also called &quot;this License&quot;).  Each 
-licensee is addressed as &quot;you&quot;. </P>
-<P>A &quot;library&quot; means a collection of software functions and/or data 
-prepared so as to be conveniently linked with application programs 
-(which use some of those functions and data) to form executables. </P>
-<P>The &quot;Library&quot;, below, refers to any such software library or work 
-which has been distributed under these terms.  A &quot;work based on the 
-Library&quot; means either the Library or any derivative work under 
-copyright law: that is to say, a work containing the Library or a 
-portion of it, either verbatim or with modifications and/or translated 
-straightforwardly into another language.  (Hereinafter, translation is 
-included without limitation in the term &quot;modification&quot;.) </P>
-<P>&quot;Source code&quot; for a work means the preferred form of the work for 
-making modifications to it.  For a library, complete source code means 
-all the source code for all modules it contains, plus any associated 
-interface definition files, plus the scripts used to control 
-compilation and installation of the library. </P>
-<P>Activities other than copying, distribution and modification are not 
-covered by this License; they are outside its scope.  The act of 
-running a program using the Library is not restricted, and output from 
-such a program is covered only if its contents constitute a work based 
-on the Library (independent of the use of the Library in a tool for 
-writing it).  Whether that is true depends on what the Library does and 
-what the program that uses the Library does. </P>
-<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of 
-the Library's complete source code as you receive it, in any medium, 
-provided that you conspicuously and appropriately publish on each copy 
-an appropriate copyright notice and disclaimer of warranty; keep intact 
-all the notices that refer to this License and to the absence of any 
-warranty; and distribute a copy of this License along with the Library. </P>
-<P>You may charge a fee for the physical act of transferring a copy, 
-and you may at your option offer warranty protection in exchange for a 
-fee. </P>
-<P><STRONG>2.</STRONG> You may modify your copy or copies of the 
-Library or any portion of it, thus forming a work based on the Library, 
-and copy and distribute such modifications or work under the terms of 
-Section 1 above, provided that you also meet all of these conditions: </P>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
 <OL TYPE="a">
-<LI>The modified work must itself be a software library. </LI>
+<LI>The modified work must itself be a software library.</LI>
 <P></P>
-<LI>You must cause the files modified to carry prominent notices 
stating that you changed the files and the date of any change. </LI>
+<LI>You must cause the files modified to carry prominent notices stating
that you changed the files and the date of any change.</LI>
 <P></P>
-<LI>You must cause the whole of the work to be licensed at no  charge 
-to all third parties under the terms of this License. </LI>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.</LI>
 <P></P>
-<LI>If a facility in the modified Library refers to a function or a 
- table of data to be supplied by an application program that uses  the 
-facility, other than as an argument passed when the facility  is 
-invoked, then you must make a good faith effort to ensure that,  in the 
-event an application does not supply such function or  table, the 
-facility still operates, and performs whatever part of  its purpose 
-remains meaningful. </LI>
-<P>(For example, a function in a library to compute square roots has  a 
-purpose that is entirely well-defined independent of the  application. 
- Therefore, Subsection 2d requires that any  application-supplied 
-function or table used by this function must  be optional: if the 
-application does not supply it, the square  root function must still 
-compute square roots.) </P>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.</LI>
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
 </OL>
-<P>These requirements apply to the modified work as a whole.  If 
-identifiable sections of that work are not derived from the Library, 
-and can be reasonably considered independent and separate works in 
-themselves, then this License, and its terms, do not apply to those 
-sections when you distribute them as separate works.  But when you 
-distribute the same sections as part of a whole which is a work based 
-on the Library, the distribution of the whole must be on the terms of 
-this License, whose permissions for other licensees extend to the 
-entire whole, and thus to each and every part regardless of who wrote 
-it. </P>
-<P>Thus, it is not the intent of this section to claim rights or 
-contest your rights to work written entirely by you; rather, the intent 
-is to exercise the right to control the distribution of derivative or 
-collective works based on the Library. </P>
-<P>In addition, mere aggregation of another work not based on the 
-Library with the Library (or with a work based on the Library) on a 
-volume of a storage or distribution medium does not bring the other 
-work under the scope of this License. </P>
-<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary 
-GNU General Public License instead of this License to a given copy of 
-the Library.  To do this, you must alter all the notices that refer to 
-this License, so that they refer to the ordinary GNU General Public 
-License, version 2, instead of to this License.  (If a newer version 
-than version 2 of the ordinary GNU General Public License has appeared, 
-then you can specify that version instead if you wish.)  Do not make 
-any other change in these notices. </P>
-<P>Once this change is made in a given copy, it is irreversible for 
-that copy, so the ordinary GNU General Public License applies to all 
-subsequent copies and derivative works made from that copy. </P>
-<P>This option is useful when you wish to copy part of the code of the 
-Library into a program that is not a library. </P>
-<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a 
-portion or derivative of it, under Section 2) in object code or 
-executable form under the terms of Sections 1 and 2 above provided that 
-you accompany it with the complete corresponding machine-readable 
-source code, which must be distributed under the terms of Sections 1 
-and 2 above on a medium customarily used for software interchange. </P>
-<P>If distribution of object code is made by offering access to copy 
-from a designated place, then offering equivalent access to copy the 
-source code from the same place satisfies the requirement to distribute 
-the source code, even though third parties are not compelled to copy 
-the source along with the object code. </P>
-<P><STRONG>5.</STRONG> A program that contains no derivative of any 
-portion of the Library, but is designed to work with the Library by 
-being compiled or linked with it, is called a &quot;work that uses the 
-Library&quot;.  Such a work, in isolation, is not a derivative work of the 
-Library, and therefore falls outside the scope of this License. </P>
-<P>However, linking a &quot;work that uses the Library&quot; with the Library 
-creates an executable that is a derivative of the Library (because it 
-contains portions of the Library), rather than a &quot;work that uses the 
-library&quot;.  The executable is therefore covered by this License. Section 
-6 states terms for distribution of such executables. </P>
-<P>When a &quot;work that uses the Library&quot; uses material from a header file 
-that is part of the Library, the object code for the work may be a 
-derivative work of the Library even though the source code is not. 
-Whether this is true is especially significant if the work can be 
-linked without the Library, or if the work is itself a library.  The 
-threshold for this to be true is not precisely defined by law. </P>
-<P>If such an object file uses only numerical parameters, data 
-structure layouts and accessors, and small macros and small inline 
-functions (ten lines or less in length), then the use of the object 
-file is unrestricted, regardless of whether it is legally a derivative 
-work.  (Executables containing this object code plus portions of the 
-Library will still fall under Section 6.) </P>
-<P>Otherwise, if the work is a derivative of the Library, you may 
-distribute the object code for the work under the terms of Section 6. 
-Any executables containing that work also fall under Section 6, whether 
-or not they are linked directly with the Library itself. </P>
-<P><STRONG>6.</STRONG> As an exception to the Sections above, you may 
-also compile or link a &quot;work that uses the Library&quot; with the Library to 
-produce a work containing portions of the Library, and distribute that 
-work under terms of your choice, provided that the terms permit 
-modification of the work for the customer's own use and reverse 
-engineering for debugging such modifications. </P>
-<P>You must give prominent notice with each copy of the work that the 
-Library is used in it and that the Library and its use are covered by 
-this License.  You must supply a copy of this License.  If the work 
-during execution displays copyright notices, you must include the 
-copyright notice for the Library among them, as well as a reference 
-directing the user to the copy of this License.  Also, you must do one 
-of these things: </P>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
 <OL TYPE="a">
-<LI>Accompany the work with the complete corresponding 
- machine-readable source code for the Library including whatever 
- changes were used in the work (which must be distributed under 
- Sections 1 and 2 above); and, if the work is an executable linked 
- with the Library, with the complete machine-readable &quot;work that  uses 
-the Library&quot;, as object code and/or source code, so that the  user can 
-modify the Library and then relink to produce a modified  executable 
-containing the modified Library.  (It is understood  that the user who 
-changes the contents of definitions files in the  Library will not 
-necessarily be able to recompile the application  to use the modified 
-definitions.) </LI>
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)</LI>
 <P></P>
-<LI>Accompany the work with a written offer, valid for at  least three 
-years, to give the same user the materials  specified in Subsection 6a, 
-above, for a charge no more  than the cost of performing this 
-distribution. </LI>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.</LI>
 <P></P>
-<LI>If distribution of the work is made by offering access to copy 
- from a designated place, offer equivalent access to copy the above 
specified materials from the same place. </LI>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
materials from the same place.</LI>
 <P></P>
-<LI>Verify that the user has already received a copy of these 
materials or that you have already sent this user a copy. </LI>
+<LI>Verify that the user has already received a copy of these materials
or that you have already sent this user a copy.</LI>
 </OL>
-<P>For an executable, the required form of the &quot;work that uses the 
-Library&quot; must include any data and utility programs needed for 
-reproducing the executable from it.  However, as a special exception, 
-the source code distributed need not include anything that is normally 
-distributed (in either source or binary form) with the major components 
-(compiler, kernel, and so on) of the operating system on which the 
-executable runs, unless that component itself accompanies the 
-executable. </P>
-<P>It may happen that this requirement contradicts the license 
-restrictions of other proprietary libraries that do not normally 
-accompany the operating system.  Such a contradiction means you cannot 
-use both them and the Library together in an executable that you 
-distribute. </P>
-<P><STRONG>7.</STRONG> You may place library facilities that are a work 
-based on the Library side-by-side in a single library together with 
-other library facilities not covered by this License, and distribute 
-such a combined library, provided that the separate distribution of the 
-work based on the Library and of the other library facilities is 
-otherwise permitted, and provided that you do these two things: </P>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
 <OL TYPE="a">
-<LI>Accompany the combined library with a copy of the same work  based 
-on the Library, uncombined with any other library  facilities.  This 
-must be distributed under the terms of the  Sections above. </LI>
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.</LI>
 <P></P>
-<LI>Give prominent notice with the combined library of the fact  that 
-part of it is a work based on the Library, and explaining  where to 
-find the accompanying uncombined form of the same work. </LI>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
 </OL>
-<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with, 
-or distribute the Library except as expressly provided under this 
-License.  Any attempt otherwise to copy, modify, sublicense, link with, 
-or distribute the Library is void, and will automatically terminate 
-your rights under this License.  However, parties who have received 
-copies, or rights, from you under this License will not have their 
-licenses terminated so long as such parties remain in full compliance. </P>
-<P><STRONG>9.</STRONG> You are not required to accept this License, 
-since you have not signed it.  However, nothing else grants you 
-permission to modify or distribute the Library or its derivative works. 
- These actions are prohibited by law if you do not accept this License. 
- Therefore, by modifying or distributing the Library (or any work based 
-on the Library), you indicate your acceptance of this License to do so, 
-and all its terms and conditions for copying, distributing or modifying 
-the Library or works based on it. </P>
-<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any 
-work based on the Library), the recipient automatically receives a 
-license from the original licensor to copy, distribute, link with or 
-modify the Library subject to these terms and conditions.  You may not 
-impose any further restrictions on the recipients' exercise of the 
-rights granted herein. You are not responsible for enforcing compliance 
-by third parties to this License. </P>
-<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or 
-allegation of patent infringement or for any other reason (not limited 
-to patent issues), conditions are imposed on you (whether by court 
-order, agreement or otherwise) that contradict the conditions of this 
-License, they do not excuse you from the conditions of this License. 
- If you cannot distribute so as to satisfy simultaneously your 
-obligations under this License and any other pertinent obligations, 
-then as a consequence you may not distribute the Library at all.  For 
-example, if a patent license would not permit royalty-free 
-redistribution of the Library by all those who receive copies directly 
-or indirectly through you, then the only way you could satisfy both it 
-and this License would be to refrain entirely from distribution of the 
-Library. </P>
-<P>If any portion of this section is held invalid or unenforceable 
-under any particular circumstance, the balance of the section is 
-intended to apply, and the section as a whole is intended to apply in 
-other circumstances. </P>
-<P>It is not the purpose of this section to induce you to infringe any 
-patents or other property right claims or to contest validity of any 
-such claims; this section has the sole purpose of protecting the 
-integrity of the free software distribution system which is implemented 
-by public license practices.  Many people have made generous 
-contributions to the wide range of software distributed through that 
-system in reliance on consistent application of that system; it is up 
-to the author/donor to decide if he or she is willing to distribute 
-software through any other system and a licensee cannot impose that 
-choice. </P>
-<P>This section is intended to make thoroughly clear what is believed 
-to be a consequence of the rest of this License. </P>
-<P><STRONG>12.</STRONG> If the distribution and/or use of the Library 
-is restricted in certain countries either by patents or by copyrighted 
-interfaces, the original copyright holder who places the Library under 
-this License may add an explicit geographical distribution limitation 
-excluding those countries, so that distribution is permitted only in or 
-among countries not thus excluded.  In such case, this License 
-incorporates the limitation as if written in the body of this License. </P>
-<P><STRONG>13.</STRONG> The Free Software Foundation may publish 
-revised and/or new versions of the Library General Public License from 
-time to time. Such new versions will be similar in spirit to the 
-present version, but may differ in detail to address new problems or 
-concerns. </P>
-<P>Each version is given a distinguishing version number.  If the 
-Library specifies a version number of this License which applies to it 
-and &quot;any later version&quot;, you have the option of following the terms and 
-conditions either of that version or of any later version published by 
-the Free Software Foundation.  If the Library does not specify a 
-license version number, you may choose any version ever published by 
-the Free Software Foundation. </P>
-<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library 
-into other free programs whose distribution conditions are incompatible 
-with these, write to the author to ask for permission.  For software 
-which is copyrighted by the Free Software Foundation, write to the Free 
-Software Foundation; we sometimes make exceptions for this.  Our 
-decision will be guided by the two goals of preserving the free status 
-of all derivatives of our free software and of promoting the sharing 
-and reuse of software generally. </P>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
 <P><STRONG>NO WARRANTY</STRONG></P>
-<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, 
-THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY 
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT 
-WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT 
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
-PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE 
-OF THE LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU 
-ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </P>
-<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW 
-OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY 
-WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE 
-LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL 
-OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
-DAMAGES. </P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
 <H4>END OF TERMS AND CONDITIONS</H4>
 </BODY>
 </HTML>
index 34bdc62d904101182b974b7c8d6c993d6ab613b3..4426de5a988f27745f93b8c74d116c3a77653cf4 100644 (file)
Binary files a/doc/sum.pdf and b/doc/sum.pdf differ
index 46e689c3a0122ffca5821bf5cf5e1fa2ff620a96..fd15b012334c975854106cebefbbb59df33f1789 100644 (file)
@@ -2,7 +2,7 @@
 <HEAD>
        <META NAME="Description" CONTENT="Common UNIX Printing System Software Users Manual">
        <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2001, All Rights Reserved">
-       <META NAME="DOCNUMBER" CONTENT="CUPS-SUM-1.1.7">
+       <META NAME="DOCNUMBER" CONTENT="CUPS-SUM-1.2.0">
        <META NAME="Author" CONTENT="Easy Software Products">
        <TITLE>CUPS Software Users Manual</TITLE>
 </HEAD>
@@ -11,7 +11,7 @@
 <H1 ALIGN="RIGHT">Preface</H1>
 
 <P>This software users manual describes how to use the Common UNIX Printing
-System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.7.
+System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.2.0.
 
 <EMBED SRC="system-overview.shtml">
 
@@ -592,27 +592,36 @@ image on the page:
 
 <H3>Scaling the Image</H3>
 
-<P>The <CODE>-o scaling=percent</CODE> and <CODE>-o ppi=value</CODE>
+<P>The <CODE>-o scaling=percent</CODE>, <CODE>-o
+ppi=value</CODE>, and <CODE>-o natural-scaling=percent</CODE>
 options change the size of a printed image:
 
 <UL><PRE>
 <B>lp -o scaling=<I>percent</I> filename ENTER</B>
 <B>lp -o ppi=<I>value</I> filename ENTER</B>
-<B>lpr -o ppi=<I>value</I> filename ENTER</B>
+<B>lpr -o natural-scaling=<I>percent</I> filename ENTER</B>
 </PRE></UL>
 
-<P>The <CODE>percent</CODE> value is a number from 1 to 800
+<P>The <CODE>scaling=percent</CODE> value is a number from 1 to 800
 specifying the size in relation to the page (<I>not</I> the image.) A
 scaling of 100 percent will fill the page as completely as the image
 aspect ratio allows. A scaling of 200 percent will print on up to 4
 pages.
 
-<P>The ppi <CODE>value</CODE> is a number from 1 to 1200 specifying the
+<P>The <CODE>ppi=value</CODE> value is a number from 1 to 1200 specifying the
 resolution of the image in pixels per inch. An image that is 3000x2400
 pixels will print 10x8 inches at 300 pixels per inch, for example. If
 the specified resolution makes the image larger than the page, multiple
 pages will be printed to satisfy the request.
 
+<P>The <CODE>natural-scaling=percent</CODE> value is a number
+from 1 to 800 specifying the size in relation to the natural
+image size. A scaling of 100 percent will print the image at its
+natural size, while a scaling of 50 percent will print the image
+at half its natural size. If the specified scaling makes the
+image larger than the page, multiple pages will be printed to
+satisfy the request.
+
 <H3>Adjusting the Hue (Tint) of an Image</H3>
 
 <P>The <CODE>-o hue=value</CODE> option will adjust the hue of the
index edeacc4cd0dcbf7b215d4f26aad131afee83ad6e..9eb11cea5978edede727c26e37cd1d282d089948 100644 (file)
@@ -1,27 +1,27 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <HTML>
 <HEAD>
-<TITLE> CUPS Software Version Description</TITLE>
+<TITLE>CUPS Software Version Description</TITLE>
 <META NAME="author" CONTENT="Easy Software Products">
 <META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
 <META NAME="docnumber" CONTENT="CUPS-SVD-1.1">
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
 <STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
 --></STYLE>
 </HEAD>
 <BODY>
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Version Description</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Version Description</H1></A><BR>
 CUPS-SVD-1.1<BR>
 Easy Software Products<BR>
 Copyright 1997-2001, All Rights Reserved<BR>
@@ -76,27 +76,27 @@ Copyright 1997-2001, All Rights Reserved<BR>
 <HR>
 <H1><A NAME="1">1 Scope</A></H1>
 <H2><A NAME="1_1">1.1 Identification</A></H2>
- This software version description document provides release 
-information for the Common UNIX Printing System (&quot;CUPS&quot;) Version 1.1. 
+ This software version description document provides release information
+ for the Common UNIX Printing System (&quot;CUPS&quot;) Version 1.1.
 <H2><A NAME="1_2">1.2 System Overview</A></H2>
-<P>CUPS provides a portable printing layer for UNIX&reg;-based operating 
-systems. It has been developed by <A HREF="http://www.easysw.com">Easy 
-Software Products</A> to promote a standard printing solution for all 
-UNIX vendors and users. CUPS provides the System V and Berkeley 
-command-line interfaces. </P>
-<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for 
-managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server 
-Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are 
-also supported with reduced functionality. CUPS adds network printer 
-browsing and PostScript Printer Description (&quot;PPD&quot;) based printing 
-options to support real-world printing under UNIX. </P>
-<P>CUPS also includes a customized version of GNU Ghostscript 
-(currently based off GNU Ghostscript 5.50) and an image file RIP that 
-are used to support non-PostScript printers. Sample drivers for HP and 
-EPSON printers are included that use these filters. </P>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by<A HREF="http://www.easysw.com"> Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS also includes a customized version of GNU Ghostscript (currently
+ based off GNU Ghostscript 5.50) and an image file RIP that are used to
+ support non-PostScript printers. Sample drivers for HP and EPSON
+ printers are included that use these filters.</P>
 <H2><A NAME="1_3">1.3 Document Overview</A></H2>
-<P>This software version description document is organized into the 
-following sections:</P>
+<P>This software version description document is organized into the
+ following sections:</P>
 <UL>
 <LI><A HREF="#1">1 - Scope</A></LI>
 <LI><A HREF="#2">2 - References</A></LI>
@@ -106,108 +106,108 @@ following sections:</P>
 </UL>
 <H1><A NAME="2">2 References</A></H1>
 <H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
-<P>The following CUPS documentation is referenced by this document: </P>
+<P>The following CUPS documentation is referenced by this document:</P>
 <UL>
-<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan </LI>
-<LI>CUPS-IDD-1.1: CUPS System Interface Design Description </LI>
-<LI>CUPS-IPP-1.1: CUPS Implementation of IPP </LI>
-<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual </LI>
-<LI>CUPS-SDD-1.1: CUPS Software Design Description </LI>
-<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual </LI>
-<LI>CUPS-SSR-1.1: CUPS Software Security Report </LI>
-<LI>CUPS-STP-1.1: CUPS Software Test Plan </LI>
-<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual </LI>
-<LI>CUPS-SVD-1.1: CUPS Software Version Description </LI>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
 </UL>
 <H2><A NAME="2_2">2.2 Other Documents</A></H2>
-<P>The following non-CUPS documents are referenced by this document: </P>
+<P>The following non-CUPS documents are referenced by this document:</P>
 <UL>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
-Adobe  PostScript Printer Description File Format Specification, 
Version 4.3.</A></LI>
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
 <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
-Adobe  PostScript Language Reference, Third Edition.</A></LI>
-<LI>IPP: Job and Printer Set Operations </LI>
-<LI>IPP/1.1: Encoding and Transport </LI>
-<LI>IPP/1.1: Implementers Guide </LI>
-<LI>IPP/1.1: Model and Semantics </LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line 
-Printer Daemon Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design 
-Goals for an Internet Printing Protocol</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale 
-for the Structure of the Model and Protocol</A> for the Internet 
-Printing Protocol</LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping 
-between LPD and IPP Protocols</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext 
-Transfer Protocol -- HTTP/1.1</A></LI>
-<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP 
-Authentication: Basic and Digest Access</A> Authentication </LI>
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP: Job and Printer Set Operations</LI>
+<LI>IPP/1.1: Encoding and Transport</LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI>IPP/1.1: Model and Semantics</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol</A> for the Internet
+ Printing Protocol</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
 </UL>
 <H1><A NAME="3">3 Additions</A></H1>
-<P>CUPS 1.1 includes many new features from the 1.0.x releases. </P>
+<P>CUPS 1.1 includes many new features from the 1.0.x releases.</P>
 <H2><A NAME="3_1">3.1 Filters</A></H2>
 <H3><A NAME="3_1_1">3.1.1 <CODE>imagetoraster</CODE>, <CODE>imagetops</CODE>
 </A></H3>
-<P>The image file filters have been upgraded to support conversion of 
-Microsoft Bitmap (&quot;BMP&quot;) and Alias PIX files. </P>
+<P>The image file filters have been upgraded to support conversion of
+ Microsoft Bitmap (&quot;BMP&quot;) and Alias PIX files.</P>
 <H3><A NAME="3_1_2">3.1.2 pdftops</A></H3>
-<P>A new pdftops filter has been developed that is based on the 
-excellent Xpdf 0.90 software from Derek B. Noonburg. The new filter is 
-faster, smaller, and considerably more reliable than the 
-Ghostscript-based filter in CUPS 1.0. </P>
+<P>A new pdftops filter has been developed that is based on the
+ excellent Xpdf 0.90 software from Derek B. Noonburg. The new filter is
+ faster, smaller, and considerably more reliable than the
+ Ghostscript-based filter in CUPS 1.0.</P>
 <H3><A NAME="3_1_3">3.1.3 pstoraster</A></H3>
-<P>The <CODE>pstoraster</CODE> filter has been integrated with GNU 
-GhostScript 5.50. The new RIP supports most Level 3 PostScript language 
-features. </P>
+<P>The <CODE>pstoraster</CODE> filter has been integrated with GNU
+ GhostScript 5.50. The new RIP supports most Level 3 PostScript language
+ features.</P>
 <H3><A NAME="3_1_4">3.1.4 rastertoepson</A></H3>
-<P>The new <CODE>rastertoepson</CODE> filter supports EPSON printers 
-using the ESC/P or ESC/P2 command sets. PPDs are supplied for 9-pin, 
-24-pin, Stylus Color, and Stylus Photo printers. </P>
+<P>The new <CODE>rastertoepson</CODE> filter supports EPSON printers
+ using the ESC/P or ESC/P2 command sets. PPDs are supplied for 9-pin,
+ 24-pin, Stylus Color, and Stylus Photo printers.</P>
 <H2><A NAME="3_2">3.2 User-Defined Printers and Options</A></H2>
-<P>The new <CODE>lpoptions</CODE> command allows users to configure 
-default document options and create additional &quot;instances&quot; of existing 
-printers, each with unique options. </P>
+<P>The new <CODE>lpoptions</CODE> command allows users to configure
+ default document options and create additional &quot;instances&quot; of existing
+ printers, each with unique options.</P>
 <P>The <CODE>lp</CODE>, <CODE>lpr</CODE>, and <CODE>lpstat</CODE>
- commands have been upgraded to use this option and printer instance 
-information automatically. </P>
+ commands have been upgraded to use this option and printer instance
+ information automatically.</P>
 <H2><A NAME="3_3">3.3 Daemons</A></H2>
-<P>CUPS 1.1 includes two new daemons that provide enhanced network 
-printing support. </P>
+<P>CUPS 1.1 includes two new daemons that provide enhanced network
+ printing support.</P>
 <H3><A NAME="3_3_1">3.3.1 cups-lpd</A></H3>
-<P>The <CODE>cups-lpd</CODE> daemon provides support for clients using 
-the Line Printer Daemon protocol. </P>
+<P>The <CODE>cups-lpd</CODE> daemon provides support for clients using
+ the Line Printer Daemon protocol.</P>
 <H3><A NAME="3_3_2">3.3.2 cups-polld</A></H3>
-<P>The <CODE>cups-polld</CODE> daemon provides remote polling services 
-for the scheduler. </P>
+<P>The <CODE>cups-polld</CODE> daemon provides remote polling services
+ for the scheduler.</P>
 <H2><A NAME="3_4">3.4 Commands</A></H2>
-<P>CUPS 1.1 includes several new printing commands. </P>
+<P>CUPS 1.1 includes several new printing commands.</P>
 <H3><A NAME="3_4_1">3.4.1 lpoptions</A></H3>
-<P>The <CODE>lpoptions</CODE> command provides user-defined printers 
-and options. </P>
+<P>The <CODE>lpoptions</CODE> command provides user-defined printers and
+ options.</P>
 <H3><A NAME="3_4_2">3.4.2 lpmove</A></H3>
-<P>The <CODE>lpmove</CODE> command moves a print job to a new 
-destination. </P>
+<P>The <CODE>lpmove</CODE> command moves a print job to a new
+ destination.</P>
 <H3><A NAME="3_4_3">3.4.3 lpinfo</A></H3>
-<P>The <CODE>lpinfo</CODE> command lists the available PPD files or 
-devices. </P>
+<P>The <CODE>lpinfo</CODE> command lists the available PPD files or
+ devices.</P>
 <H2><A NAME="3_5">3.5 IPP Implementation</A></H2>
 <P>CUPS 1.1 adds support for the <CODE>set-job-attributes</CODE>
- extension operation as well as two new CUPS-specific extension 
-operations to determine which devices and printer drivers are available 
-on the system. </P>
-<P>Further information on the CUPS implementation of IPP can be found 
-in CUPS-IPP-1.1. </P>
+ extension operation as well as two new CUPS-specific extension
+ operations to determine which devices and printer drivers are available
+ on the system.</P>
+<P>Further information on the CUPS implementation of IPP can be found in
+ CUPS-IPP-1.1.</P>
 <H1><A NAME="4">4 Changes</A></H1>
-<P>CUPS 1.1 includes many changes from the 1.0.x releases. </P>
+<P>CUPS 1.1 includes many changes from the 1.0.x releases.</P>
 <H2><A NAME="4_1">4.1 Directory Structure</A></H2>
-<P>The directory structure in CUPS 1.1 has been modified to conform to 
-the Filesystem Hierarchy Standard, 2.0. The following table describes 
-the new file locations. 
+<P>The directory structure in CUPS 1.1 has been modified to conform to
+ the Filesystem Hierarchy Standard, 2.0. The following table describes
+ the new file locations.
 <CENTER>
-<TABLE BORDER WIDTH="80%"><CAPTION> Table 1: Directory structure 
-changes from CUPS 1.0.x to 1.1.x.</CAPTION>
+<TABLE BORDER WIDTH="80%"><CAPTION> Table 1: Directory structure changes
+ from CUPS 1.0.x to 1.1.x.</CAPTION>
 <TR><TH>Description</TH><TH>CUPS 1.0.x</TH><TH>CUPS 1.1.x</TH></TR>
 <TR><TD>Backends</TD><TD>/var/cups/backend</TD><TD>/usr/lib/cups/backend</TD>
 </TR>
@@ -231,67 +231,66 @@ changes from CUPS 1.0.x to 1.1.x.</CAPTION>
 </CENTER>
 </P>
 <H2><A NAME="4_2">4.2 IPP Implementation</A></H2>
-<P>CUPS 1.1 is based on version 1.1 of the Internet Printing Protocol. </P>
+<P>CUPS 1.1 is based on version 1.1 of the Internet Printing Protocol.</P>
 <P>The new scheduler supports the <CODE>create-job</CODE> and <CODE>
 send-document</CODE> operations. In addition, the <CODE>job-sheets</CODE>
 , <CODE>job-sheets-default</CODE>, and <CODE>job-sheets-supported</CODE>
- attributes are now supported for banner pages. </P>
+ attributes are now supported for banner pages.</P>
 <P>The <CODE>CUPS-get-printers</CODE> and <CODE>CUPS-get-classes</CODE>
- operations have been upgraded to support limited filtering based upon 
-the <CODE>printer-type</CODE>, <CODE>printer-location</CODE>, <CODE>
-printer-info</CODE>, and <CODE>printer-make-and-model</CODE>
- attributes. </P>
+ operations have been upgraded to support limited filtering based upon
+ the <CODE>printer-type</CODE>, <CODE>printer-location</CODE>, <CODE>
+printer-info</CODE>, and <CODE>printer-make-and-model</CODE> attributes.</P>
 <P>The <CODE>CUPS-add-printer</CODE> operation now supports the <CODE>
-ppd-name</CODE> attribute to specify a locally-available PPD file 
-rather than sending the PPD file from the client with the request. </P>
-<P>Further information on the CUPS implementation of IPP can be found 
-in CUPS-IPP-1.1. </P>
+ppd-name</CODE> attribute to specify a locally-available PPD file rather
+ than sending the PPD file from the client with the request.</P>
+<P>Further information on the CUPS implementation of IPP can be found in
+ CUPS-IPP-1.1.</P>
 <H1 TYPE="A" VALUE="1"><A NAME="5">A Glossary</A></H1>
 <H2><A NAME="5_1">A.1 Terms</A></H2>
 <DL>
-<DT>C </DT>
-<DD>A computer language. </DD>
-<DT>parallel </DT>
-<DD>Sending or receiving data more than 1 bit at a time. </DD>
-<DT>pipe </DT>
-<DD>A one-way communications channel between two programs. </DD>
-<DT>serial </DT>
-<DD>Sending or receiving data 1 bit at a time. </DD>
-<DT>socket </DT>
-<DD>A two-way network communications channel. </DD>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
 </DL>
 <H2><A NAME="5_2">A.2 Acronyms</A></H2>
 <DL>
-<DT>ASCII </DT>
-<DD>American Standard Code for Information Interchange </DD>
-<DT>CUPS </DT>
-<DD>Common UNIX Printing System </DD>
-<DT>ESC/P </DT>
-<DD>EPSON Standard Code for Printers </DD>
-<DT>FTP </DT>
-<DD>File Transfer Protocol </DD>
-<DT>HP-GL </DT>
-<DD>Hewlett-Packard Graphics Language </DD>
-<DT>HP-PCL </DT>
-<DD>Hewlett-Packard Page Control Language </DD>
-<DT>HP-PJL </DT>
-<DD>Hewlett-Packard Printer Job Language </DD>
-<DT>IETF </DT>
-<DD>Internet Engineering Task Force </DD>
-<DT>IPP </DT>
-<DD>Internet Printing Protocol </DD>
-<DT>ISO </DT>
-<DD>International Standards Organization </DD>
-<DT>LPD </DT>
-<DD>Line Printer Daemon </DD>
-<DT>MIME </DT>
-<DD>Multimedia Internet Mail Exchange </DD>
-<DT>PPD </DT>
-<DD>PostScript Printer Description </DD>
-<DT>SMB </DT>
-<DD>Server Message Block </DD>
-<DT>TFTP </DT>
-<DD>Trivial File Transfer Protocol </DD>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
 </DL>
 </BODY>
 </HTML>
index 05918d142a635eca69e96fa89da53dba113acc8e..b0d4a71a668338dfe320ef50b38371a9b0571c16 100644 (file)
Binary files a/doc/svd.pdf and b/doc/svd.pdf differ
index fdc02bdd947144ccd1830492db8b243ffbad235d..1a209fe1414bc38fb5433cd077171c7e9d2bdf8a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.41 2001/02/02 16:37:44 mike Exp $"
+# "$Id: Makefile,v 1.41.2.1 2001/12/26 16:52:38 mike Exp $"
 #
 #   Filter makefile for the Common UNIX Printing System (CUPS).
 #
@@ -25,7 +25,7 @@
 include ../Makedefs
 
 TARGETS        =       hpgltops texttops pstops imagetops imagetoraster \
-               rastertoepson rastertohp
+               rastertodymo rastertoepson rastertohp
 
 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
@@ -36,8 +36,8 @@ IMAGEOBJS =   image-bmp.o image-colorspace.o image-gif.o image-jpeg.o \
 FORMOBJS =     form-attr.o form-main.o form-ps.o form-text.o form-tree.o
 OBJS   =       $(HPGLOBJS) $(IMAGEOBJS) $(FORMOBJS) \
                imagetops.o imagetoraster.o common.o pstops.o raster.o \
-               rastertoepson.o rastertohp.o texttops.o textcommon.o
-
+               rastertodymo.o rastertoepson.o rastertohp.o texttops.o \
+               textcommon.o 
 
 #
 # Make all targets...
@@ -59,20 +59,21 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(LIBDIR)
-       $(CHMOD) ugo+rx $(LIBDIR)
+       $(INSTALL_DIR) $(SERVERBIN)/filter
+       for file in $(TARGETS); do \
+               $(INSTALL_BIN) $$file $(SERVERBIN)/filter; \
+       done
+       $(INSTALL_DIR) $(LIBDIR)
        $(INSTALL_LIB) $(LIBCUPSIMAGE) $(LIBDIR)
-       -if test $(LIBCUPSIMAGE) != "libcupsimage.a" -a $(LIBCUPSIMAGE) != "libcupsimage.la"; then \
+       -if test $(LIBCUPSIMAGE) = "libcupsimage.so.2" -o $(LIBCUPSIMAGE) = "libcupsimage.sl.2"; then \
                $(RM) $(LIBDIR)/`basename $(LIBCUPSIMAGE) .2`; \
                $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/`basename $(LIBCUPSIMAGE) .2`; \
        fi
-       -$(MKDIR) $(SERVERBIN)/filter
-       $(CHMOD) ugo+rx $(SERVERBIN)
-       $(CHMOD) ugo+rx $(SERVERBIN)/filter
-       $(INSTALL_BIN) $(TARGETS) $(SERVERBIN)/filter
-       -$(MKDIR) $(INCLUDEDIR)/cups
-       $(CHMOD) ugo+rx $(INCLUDEDIR)
-       $(CHMOD) ugo+rx $(INCLUDEDIR)/cups
+       -if test $(LIBCUPSIMAGE) = "libcupsimage.2.dylib"; then \
+               $(RM) $(LIBDIR)/libcupsimage.dylib; \
+               $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/libcupsimage.dylib; \
+       fi
+       $(INSTALL_DIR) $(INCLUDEDIR)/cups
        $(INSTALL_DATA) raster.h $(INCLUDEDIR)/cups
 
 
@@ -107,14 +108,37 @@ libcupsimage.so.2 libcupsimage.sl.2:      $(IMAGEOBJS) ../Makedefs
        $(LN) $@ `basename $@ .2`
 
 
+#
+# libcupsimage.2.dylib
+#
+
+libcupsimage.2.dylib:  $(IMAGEOBJS) ../Makedefs
+       echo Linking $@...
+       $(DSO) $(DSOFLAGS) -o $@ $(IMAGEOBJS) $(DSOLIBS) $(LINKCUPS) -lm -lcc_dynamic
+       $(RM) libcupsimage.dylib
+       $(LN) $@ libcupsimage.dylib
+
+
+#
+# libcupsimage_s.a
+#
+
+libcupsimage_s.a:      $(IMAGEOBJS) ../Makedefs
+       echo Linking $@...
+       $(DSO) $(DSOFLAGS) -o libcupsimage_s.o $(IMAGEOBJS) $(DSOLIBS) \
+               $(LINKCUPS) -lm
+       $(RM) $@
+       $(AR) $(ARFLAGS) $@ libcupsimage_s.o
+
+
 #
 # libcupsimage.la
 #
 
 libcupsimage.la:       $(IMAGEOBJS) ../Makedefs
        echo Linking $@...
-       $(CC) -o $@ $(IMAGEOBJS:.o=.lo) -rpath $(LIBDIR) \
-               -version-info 2:0
+       $(DSO) -o $(DSOFLAGS) $@ $(IMAGEOBJS:.o=.lo) $(DSOLIBS) \
+               -rpath $(LIBDIR) -version-info 2:0
 
 
 #
@@ -165,6 +189,16 @@ pstops:    pstops.o common.o ../Makedefs ../cups/$(LIBCUPS)
 pstops.o:      common.h
 
 
+#
+# rastertodymo
+#
+
+rastertodymo:  rastertodymo.o ../Makedefs ../cups/$(LIBCUPS) libcupsimage.a
+       echo Linking $@...
+       $(CC) $(LDFLAGS) -o $@ rastertodymo.o libcupsimage.a $(LIBS)
+rastertodymo.o:        raster.h
+
+
 #
 # rastertoepson
 #
@@ -203,5 +237,5 @@ $(OBJS):    ../Makedefs ../cups/cups.h ../cups/ppd.h ../cups/language.h
 
 
 #
-# End of "$Id: Makefile,v 1.41 2001/02/02 16:37:44 mike Exp $".
+# End of "$Id: Makefile,v 1.41.2.1 2001/12/26 16:52:38 mike Exp $".
 #
index 3781f22fe06d8adaf49429090b468cd8c46d1e49..b4601317d240d1eaeb7946941a29ec7db2e529da 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: image-colorspace.c,v 1.22 2001/03/29 14:58:52 mike Exp $"
+ * "$Id: image-colorspace.c,v 1.22.2.1 2001/12/26 16:52:38 mike Exp $"
  *
  *   Colorspace conversions for the Common UNIX Printing System (CUPS).
  *
@@ -23,6 +23,7 @@
  *
  * Contents:
  *
+ *   ImageSetProfile()   - Set the device color profile.
  *   ImageWhiteToWhite() - Convert luminance colors to device-dependent
  *   ImageWhiteToRGB()   - Convert luminance data to RGB.
  *   ImageWhiteToBlack() - Convert luminance colors to black.
 
 
 /*
- * Globals...
+ * Local globals...
  */
 
-extern int     ImageHaveProfile;
-extern int     ImageDensity[256];
-extern int     ImageMatrix[3][3][256];
+static int     ImageHaveProfile = 0;   /* Do we have a color profile? */
+static int     ImageDensity[256];      /* Ink/marker density LUT */
+static int     ImageMatrix[3][3][256]; /* Color transform matrix LUT */
+
 
 /*
  * Local functions...
@@ -78,6 +80,31 @@ static void  zrotate(float [3][3], float, float);
 static void    zshear(float [3][3], float, float);
 
 
+/*
+ * 'ImageSetProfile()' - Set the device color profile.
+ */
+
+void
+ImageSetProfile(float d,               /* I - Ink/marker density */
+                float g,               /* I - Ink/marker gamma */
+                float matrix[3][3])    /* I - Color transform matrix */
+{
+  int          i, j, k;                /* Looping vars */
+  float                m;                      /* Current matrix value */
+  int          *im;                    /* Pointer into ImageMatrix */
+
+  ImageHaveProfile  = 1;
+
+  for (i = 0, im = ImageMatrix[0][0]; i < 3; i ++)
+    for (j = 0; j < 3; j ++)
+      for (k = 0, m = matrix[i][j]; k < 256; k ++)
+        *im++ = (int)(k * m + 0.5);
+
+  for (k = 0, im = ImageDensity; k < 256; k ++)
+    *im++ = 255.0 * d * pow((float)k / 255.0, g) + 0.5;
+}
+
+
 /*
  * 'ImageWhiteToWhite()' - Convert luminance colors to device-dependent
  *                         luminance.
@@ -878,5 +905,5 @@ zshear(float mat[3][3],     /* I - Matrix */
 
 
 /*
- * End of "$Id: image-colorspace.c,v 1.22 2001/03/29 14:58:52 mike Exp $".
+ * End of "$Id: image-colorspace.c,v 1.22.2.1 2001/12/26 16:52:38 mike Exp $".
  */
index 6bf640c7c5b83fb4955ec8df5e9a26ade8fa426e..f6a517115e5d98a4d87cf6ae97107a1a8aac2170 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: image-jpeg.c,v 1.11 2001/01/22 15:03:38 mike Exp $"
+ * "$Id: image-jpeg.c,v 1.11.2.1 2001/12/26 16:52:38 mike Exp $"
  *
  *   JPEG image routines for the Common UNIX Printing System (CUPS).
  *
@@ -98,7 +98,7 @@ ImageReadJPEG(image_t    *img,                /* IO - Image */
   }
 
   fprintf(stderr, "DEBUG: JPEG image %dx%dx%d, %dx%d PPI\n",
-          img->xsize, img->colorspace, cinfo.output_components,
+          img->xsize, img->ysize, cinfo.output_components,
          img->xppi, img->yppi);
 
   ImageSetMaxTiles(img, 0);
@@ -190,5 +190,5 @@ ImageReadJPEG(image_t    *img,              /* IO - Image */
 
 
 /*
- * End of "$Id: image-jpeg.c,v 1.11 2001/01/22 15:03:38 mike Exp $".
+ * End of "$Id: image-jpeg.c,v 1.11.2.1 2001/12/26 16:52:38 mike Exp $".
  */
index db1d827fd8f0a0fe21771b429edf2a62608d2ad4..ee14f77d5b4abe05c6f37f33e94a50da312d2348 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: image.c,v 1.28 2001/03/01 22:51:30 mike Exp $"
+ * "$Id: image.c,v 1.28.2.1 2001/12/26 16:52:38 mike Exp $"
  *
  *   Base image support for the Common UNIX Printing System (CUPS).
  *
@@ -26,7 +26,6 @@
  *   ImageOpen()        - Open an image file and read it into memory.
  *   ImageClose()       - Close an image file.
  *   ImageSetMaxTiles() - Set the maximum number of tiles to cache.
- *   ImageSetProfile()  - Set the device color profile.
  *   ImageGetCol()      - Get a column of pixels from an image.
  *   ImageGetRow()      - Get a row of pixels from an image.
  *   ImagePutCol()      - Put a column of pixels to an image.
 #include <cups/cups.h>
 
 
-/*
- * Globals...
- */
-
-int    ImageHaveProfile = 0;   /* Do we have a color profile? */
-int    ImageDensity[256];      /* Ink/marker density LUT */
-int    ImageMatrix[3][3][256]; /* Color transform matrix LUT */
-
-
 /*
  * Local functions...
  */
@@ -311,31 +301,6 @@ ImageSetMaxTiles(image_t *img,             /* I - Image to set */
 }
 
 
-/*
- * 'ImageSetProfile()' - Set the device color profile.
- */
-
-void
-ImageSetProfile(float d,               /* I - Ink/marker density */
-                float g,               /* I - Ink/marker gamma */
-                float matrix[3][3])    /* I - Color transform matrix */
-{
-  int          i, j, k;                /* Looping vars */
-  float                m;                      /* Current matrix value */
-  int          *im;                    /* Pointer into ImageMatrix */
-
-  ImageHaveProfile  = 1;
-
-  for (i = 0, im = ImageMatrix[0][0]; i < 3; i ++)
-    for (j = 0; j < 3; j ++)
-      for (k = 0, m = matrix[i][j]; k < 256; k ++)
-        *im++ = (int)(k * m + 0.5);
-
-  for (k = 0, im = ImageDensity; k < 256; k ++)
-    *im++ = 255.0 * d * pow((float)k / 255.0, g) + 0.5;
-}
-
-
 /*
  * 'ImageGetCol()' - Get a column of pixels from an image.
  */
@@ -804,5 +769,5 @@ flush_tile(image_t *img)    /* I - Image */
 
 
 /*
- * End of "$Id: image.c,v 1.28 2001/03/01 22:51:30 mike Exp $".
+ * End of "$Id: image.c,v 1.28.2.1 2001/12/26 16:52:38 mike Exp $".
  */
index ac1db10bafc918165c573a723ab37e87caf21656..f494cd4adf7a6645423d8330c983a9fc5381c347 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: imagetops.c,v 1.36.2.1 2001/05/13 18:38:18 mike Exp $"
+ * "$Id: imagetops.c,v 1.36.2.2 2001/12/26 16:52:39 mike Exp $"
  *
  *   Image file to PostScript filter for the Common UNIX Printing System (CUPS).
  *
@@ -305,6 +305,12 @@ main(int  argc,            /* I - Number of command-line arguments */
     xinches = (float)img->xsize / (float)xppi;
     yinches = (float)img->ysize / (float)yppi;
 
+    if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
+    {
+      xinches = xinches * atoi(val) / 100;
+      yinches = yinches * atoi(val) / 100;
+    }
+
     if (cupsGetOption("orientation", num_options, options) == NULL &&
         cupsGetOption("landscape", num_options, options) == NULL)
     {
@@ -859,5 +865,5 @@ ps_ascii85(ib_t *data,              /* I - Data to print */
 
 
 /*
- * End of "$Id: imagetops.c,v 1.36.2.1 2001/05/13 18:38:18 mike Exp $".
+ * End of "$Id: imagetops.c,v 1.36.2.2 2001/12/26 16:52:39 mike Exp $".
  */
index 22c457f4395f8b50a4dcc4cc85a93da88e5fca72..229f7a0a87ec648cc211a3802252a4d957e2d1d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: imagetoraster.c,v 1.56.2.1 2001/05/13 18:38:19 mike Exp $"
+ * "$Id: imagetoraster.c,v 1.56.2.2 2001/12/26 16:52:39 mike Exp $"
  *
  *   Image file to raster filter for the Common UNIX Printing System (CUPS).
  *
@@ -677,6 +677,12 @@ main(int  argc,            /* I - Number of command-line arguments */
     xinches = (float)img->xsize / (float)xppi;
     yinches = (float)img->ysize / (float)yppi;
 
+    if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
+    {
+      xinches = xinches * atoi(val) / 100;
+      yinches = yinches * atoi(val) / 100;
+    }
+
     if (cupsGetOption("orientation", num_options, options) == NULL &&
         cupsGetOption("landscape", num_options, options) == NULL)
     {
@@ -4442,5 +4448,5 @@ make_lut(ib_t  *lut,              /* I - Lookup table */
 
 
 /*
- * End of "$Id: imagetoraster.c,v 1.56.2.1 2001/05/13 18:38:19 mike Exp $".
+ * End of "$Id: imagetoraster.c,v 1.56.2.2 2001/12/26 16:52:39 mike Exp $".
  */
index bc4e585860f4c7d6265abc4528c3ee9df45cc14d..507004ab73a3b61a855e21334ab85a3f07a342b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: pstops.c,v 1.54.2.1 2001/05/13 18:38:20 mike Exp $"
+ * "$Id: pstops.c,v 1.54.2.2 2001/12/26 16:52:39 mike Exp $"
  *
  *   PostScript filter for the Common UNIX Printing System (CUPS).
  *
@@ -100,6 +100,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
   int          nbytes,         /* Number of bytes read */
                tbytes;         /* Total bytes to read for binary data */
   int          page;           /* Current page sequence number */
+  int          real_page;      /* "Real" page number in document */
   int          page_count;     /* Page count for NUp */
   int          subpage;        /* Sub-page number */
   int          copy;           /* Current copy */
@@ -248,6 +249,12 @@ main(int  argc,                    /* I - Number of command-line arguments */
     return (1);
   }
 
+ /*
+  * See if this is an EPS file...
+  */
+
+  UseESPsp = strstr(line, "EPS") != NULL;
+
  /*
   * Start sending the document with any commands needed...
   */
@@ -280,14 +287,15 @@ main(int  argc,                   /* I - Number of command-line arguments */
     */
 
     UseESPsp = 1;
+  }
 
-    WriteLabelProlog(val);
+  WriteLabelProlog(val);
 
+  if (UseESPsp)
     puts("userdict begin\n"
         "/ESPshowpage /showpage load def\n"
         "/showpage { } def\n"
         "end");
-  }
 
   if (Copies > 1 && (!Collate || !slowcollate))
   {
@@ -345,7 +353,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
     * Then read all of the pages, filtering as needed...
     */
 
-    for (page = 1;;)
+    for (page = 1, real_page = 1;;)
     {
       if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
           strncmp(line, "%%BeginDocument ", 16) == 0)  /* Adobe Acrobat BUG */
@@ -362,7 +370,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
       }
       else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
       {
-       if (!check_range(NumPages + 1))
+       if (!check_range(real_page))
        {
          while (psgets(line, sizeof(line), fp) != NULL)
            if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
@@ -371,7 +379,10 @@ main(int  argc,                    /* I - Number of command-line arguments */
            else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
               level --;
            else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
+           {
+             real_page ++;
              break;
+           }
 
           continue;
         }
@@ -398,6 +409,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
        }
 
        NumPages ++;
+       real_page ++;
       }
       else if (strncmp(line, "%%BeginBinary:", 14) == 0 ||
                (strncmp(line, "%%BeginData:", 12) == 0 &&
@@ -963,5 +975,5 @@ start_nup(int number)       /* I - Page number */
 
 
 /*
- * End of "$Id: pstops.c,v 1.54.2.1 2001/05/13 18:38:20 mike Exp $".
+ * End of "$Id: pstops.c,v 1.54.2.2 2001/12/26 16:52:39 mike Exp $".
  */
index 0518f768678e705253ff763e4d20c63f61713e94..3ccebd45e638701079d3d0dfecf648efcbdfd8e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: rastertodymo.c,v 1.4 2001/07/18 20:45:51 mike Exp $"
+ * "$Id: rastertodymo.c,v 1.4.2.1 2001/12/26 16:52:40 mike Exp $"
  *
  *   DYMO label printer filter for the Common UNIX Printing System (CUPS).
  *
@@ -357,5 +357,5 @@ main(int  argc,             /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: rastertodymo.c,v 1.4 2001/07/18 20:45:51 mike Exp $".
+ * End of "$Id: rastertodymo.c,v 1.4.2.1 2001/12/26 16:52:40 mike Exp $".
  */
index 0700d211b6da2a59a8a6588a0bbb6ea9003937a8..a28dd5cf0c8505dfc162049cd51706883b938656 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: textcommon.c,v 1.16.2.1 2001/05/13 18:38:21 mike Exp $"
+ * "$Id: textcommon.c,v 1.16.2.2 2001/12/26 16:52:40 mike Exp $"
  *
  *   Common text filter routines for the Common UNIX Printing System (CUPS).
  *
@@ -970,10 +970,19 @@ TextMain(const char *name,        /* I - Name of filter */
 
             if (PrettyPrint)
               Page[line][i].attr = attr;
+           else if (ch == ' ' && Page[line][i].ch)
+             ch = Page[line][i].ch;
             else if (ch == Page[line][i].ch)
               Page[line][i].attr |= ATTR_BOLD;
             else if (Page[line][i].ch == '_')
               Page[line][i].attr |= ATTR_UNDERLINE;
+            else if (ch == '_')
+           {
+              Page[line][i].attr |= ATTR_UNDERLINE;
+
+              if (Page[line][i].ch)
+               ch = Page[line][i].ch;
+           }
            else
               Page[line][i].attr = attr;
 
@@ -1142,5 +1151,5 @@ getutf8(FILE *fp) /* I - File to read from */
 
 
 /*
- * End of "$Id: textcommon.c,v 1.16.2.1 2001/05/13 18:38:21 mike Exp $".
+ * End of "$Id: textcommon.c,v 1.16.2.2 2001/12/26 16:52:40 mike Exp $".
  */
index 06ebc57e25564576edd79c07c0e498d5a5bfdcf5..81d3289efacab4a32cf656d9303f939736d4620d 100644 (file)
@@ -64,10 +64,10 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(DATADIR)/fonts
-       $(CHMOD) ugo+rx $(DATADIR)
-       $(CHMOD) ugo+rx $(DATADIR)/fonts
-       $(INSTALL_DATA) $(FONTS) $(DATADIR)/fonts
+       $(INSTALL_DIR) $(DATADIR)/fonts
+       for file in $(FONTS); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/fonts; \
+       done
 
 
 #
index 3703403d56cbadfc54ecd6926812e84a99efd00c..e3edc2d6420eeb9e38c066b3eae62e881b4cbc26 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.8 2000/07/07 17:02:44 mike Exp $"
+# "$Id: Makefile,v 1.8.2.1 2001/12/26 16:52:40 mike Exp $"
 #
 #   Locale file makefile for the Common UNIX Printing System (CUPS).
 #
@@ -28,7 +28,7 @@ include ../Makedefs
 # Locales...
 #
 
-LOCALES        =       C de en es fr it
+LOCALES        =       C cs de en es fr it
 
 
 #
@@ -50,13 +50,9 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(LOCALEDIR)
-       $(CHMOD) ugo+rx $(LOCALEDIR)
+       $(INSTALL_DIR) $(LOCALEDIR)
        for dir in $(LOCALES) ; do \
-               if test ! -d $(LOCALEDIR)/$$dir ; then \
-                       $(MKDIR) $(LOCALEDIR)/$$dir ; \
-                       $(CHMOD) ugo+rx $(LOCALEDIR)/$$dir ; \
-               fi ; \
+               $(INSTALL_DIR) $(LOCALEDIR)/$$dir ; \
                $(INSTALL_DATA) $$dir/cups_$$dir $(LOCALEDIR)/$$dir ; \
        done
 
@@ -76,5 +72,5 @@ translate.o:  ../cups/http.h
 
 
 #
-# End of "$Id: Makefile,v 1.8 2000/07/07 17:02:44 mike Exp $".
+# End of "$Id: Makefile,v 1.8.2.1 2001/12/26 16:52:40 mike Exp $".
 #
index 9396282f228d84672c3199ed6e80a10d7ba55564..96af00b99ba332e61c0dd691bd9425b7fa1a9991 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.12 2001/02/20 17:33:00 mike Exp $"
+# "$Id: Makefile,v 1.12.2.1 2001/12/26 16:52:41 mike Exp $"
 #
 #   Man page makefile for the Common UNIX Printing System (CUPS).
 #
@@ -28,23 +28,26 @@ include ../Makedefs
 # Man pages...
 #
 
-MAN1   =       backend.man filter.man lp.man lpoptions.man lpq.man lprm.man \
-               lpr.man lpstat.man
+MAN1   =       backend.man filter.man lp.man lpoptions.man lppasswd.man \
+               lpq.man lprm.man lpr.man lpstat.man
+MAN3   =       cups-config.man
 MAN5   =       classes.conf.man cupsd.conf.man mime.convs.man mime.types.man \
                printers.conf.man
-MAN8   =       accept.man cups-lpd.man cups-polld.man cupsd.man enable.man \
-               lpadmin.man lpinfo.man lpmove.man lpc.man
+MAN8   =       accept.man cupsaddsmb.man cups-lpd.man cups-polld.man \
+               cupsd.man enable.man lpadmin.man lpinfo.man lpmove.man \
+               lpc.man
 
 CAT1   =       $(MAN1:.man=.$(CAT1EXT))
-CAT5   =       $(MAN5:.man=.$(CAT1EXT))
-CAT8   =       $(MAN8:.man=.$(CAT1EXT))
+CAT3   =       $(MAN3:.man=.$(CAT3EXT))
+CAT5   =       $(MAN5:.man=.$(CAT5EXT))
+CAT8   =       $(MAN8:.man=.$(CAT8EXT))
 
 
 #
 # Make everything...
 #
 
-all:   $(CAT1) $(CAT5) $(CAT8)
+all:   $(CAT1) $(CAT3) $(CAT5) $(CAT8)
 
 
 #
@@ -52,7 +55,7 @@ all:  $(CAT1) $(CAT5) $(CAT8)
 #
 
 clean:
-       $(RM) $(CAT1) $(CAT5) $(CAT8)
+       $(RM) $(CAT1) $(CAT3) $(CAT5) $(CAT8)
 
 
 #
@@ -60,21 +63,21 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(MANDIR)/man1
-       -$(CHMOD) ugo+rx $(MANDIR)
-       -$(CHMOD) ugo+rx $(MANDIR)/man1
+       $(INSTALL_DIR) $(MANDIR)/man1
        for file in $(MAN1); do \
                $(INSTALL_MAN) $$file $(MANDIR)/man1/`basename $$file man`1; \
        done
        $(RM) $(MANDIR)/man1/cancel.1
        $(LN) lp.1 $(MANDIR)/man1/cancel.1
-       -$(MKDIR) $(MANDIR)/man5
-       -$(CHMOD) ugo+rx $(MANDIR)/man5
+       $(INSTALL_DIR) $(PMANDIR)/man3
+       for file in $(MAN3); do \
+               $(INSTALL_MAN) $$file $(PMANDIR)/man3/`basename $$file man`3; \
+       done
+       $(INSTALL_DIR) $(MANDIR)/man5
        for file in $(MAN5); do \
                $(INSTALL_MAN) $$file $(MANDIR)/man5/`basename $$file man`5; \
        done
-       -$(MKDIR) $(AMANDIR)/man$(MAN8EXT)
-       -$(CHMOD) ugo+rx $(AMANDIR)/man$(MAN8EXT)
+       $(INSTALL_DIR) $(AMANDIR)/man$(MAN8EXT)
        for file in $(MAN8); do \
                $(INSTALL_MAN) $$file $(AMANDIR)/man$(MAN8EXT)/`basename $$file man`$(MAN8EXT); \
        done
@@ -82,23 +85,30 @@ install:
        $(LN) accept.$(MAN8EXT) $(AMANDIR)/man$(MAN8EXT)/reject.$(MAN8EXT)
        $(RM) $(AMANDIR)/man$(MAN8EXT)/disable.$(MAN8EXT)
        $(LN) enable.$(MAN8EXT) $(AMANDIR)/man$(MAN8EXT)/disable.$(MAN8EXT)
-       -$(MKDIR) $(MANDIR)/cat1
-       -$(CHMOD) ugo+rx $(MANDIR)/cat1
-       $(INSTALL_MAN) $(CAT1) $(MANDIR)/cat1
+       $(INSTALL_DIR) $(MANDIR)/cat1
+       for file in $(CAT1); do \
+               $(INSTALL_MAN) $$file $(MANDIR)/cat1; \
+       done
        $(RM) $(MANDIR)/cat1/cancel.$(CAT1EXT)
        $(LN) lp.$(CAT1EXT) $(MANDIR)/cat1/cancel.$(CAT1EXT)
-       -$(MKDIR) $(MANDIR)/cat5
-       -$(CHMOD) ugo+rx $(MANDIR)/cat5
-       $(INSTALL_MAN) $(CAT5) $(MANDIR)/cat5
-       -$(MKDIR) $(AMANDIR)/cat$(MAN8EXT)
-       -$(CHMOD) ugo+rx $(AMANDIR)/cat$(MAN8EXT)
-       $(INSTALL_MAN) $(CAT8) $(AMANDIR)/cat$(MAN8EXT)
+       $(INSTALL_DIR) $(PMANDIR)/cat3
+       for file in $(CAT3); do \
+               $(INSTALL_MAN) $$file $(PMANDIR)/cat3; \
+       done
+       $(INSTALL_DIR) $(MANDIR)/cat5
+       for file in $(CAT5); do \
+               $(INSTALL_MAN) $$file $(MANDIR)/cat5; \
+       done
+       $(INSTALL_DIR) $(AMANDIR)/cat$(MAN8EXT)
+       for file in $(CAT8); do \
+               $(INSTALL_MAN) $$file $(AMANDIR)/cat$(MAN8EXT); \
+       done
        $(RM) $(AMANDIR)/cat$(MAN8EXT)/reject.$(CAT8EXT)
-       $(LN) accept.$(CAT1EXT) $(AMANDIR)/cat$(MAN8EXT)/reject.$(CAT8EXT)
+       $(LN) accept.$(CAT8EXT) $(AMANDIR)/cat$(MAN8EXT)/reject.$(CAT8EXT)
        $(RM) $(AMANDIR)/cat$(MAN8EXT)/disable.$(CAT8EXT)
-       $(LN) enable.$(CAT1EXT) $(AMANDIR)/cat$(MAN8EXT)/disable.$(CAT8EXT)
+       $(LN) enable.$(CAT8EXT) $(AMANDIR)/cat$(MAN8EXT)/disable.$(CAT8EXT)
 
 
 #
-# End of "$Id: Makefile,v 1.12 2001/02/20 17:33:00 mike Exp $".
+# End of "$Id: Makefile,v 1.12.2.1 2001/12/26 16:52:41 mike Exp $".
 #
index e681adaae889b76ca19fb381fd5f678ffd185755..e4cad76cea029386e90d0a5d34e9c72ce2dcafa6 100644 (file)
@@ -1,5 +1,5 @@
 .\"
-.\" "$Id: cups-config.man,v 1.1 2001/10/26 03:16:48 mike Exp $"
+.\" "$Id: cups-config.man,v 1.1.2.1 2001/12/26 16:52:41 mike Exp $"
 .\"
 .\"   cups-config man page for the Common UNIX Printing System (CUPS).
 .\"
@@ -91,5 +91,5 @@ http://localhost:631/documentation.html
 .SH COPYRIGHT
 Copyright 1993-2001 by Easy Software Products, All Rights Reserved.
 .\"
-.\" End of "$Id: cups-config.man,v 1.1 2001/10/26 03:16:48 mike Exp $".
+.\" End of "$Id: cups-config.man,v 1.1.2.1 2001/12/26 16:52:41 mike Exp $".
 .\"
index 4d7da8879b95de3b46272e76dba3ecd324562898..a6fcab69f33b7427912a9cd08ccb58311018bfc6 100644 (file)
@@ -1,5 +1,5 @@
 .\"
-.\" "$Id: cupsaddsmb.man,v 1.2 2001/11/09 17:19:41 mike Exp $"
+.\" "$Id: cupsaddsmb.man,v 1.2.2.1 2001/12/26 16:52:41 mike Exp $"
 .\"
 .\"   cupsaddsmb man page for the Common UNIX Printing System (CUPS).
 .\"
@@ -110,5 +110,5 @@ http://localhost:631/documentation.html
 .SH COPYRIGHT
 Copyright 1993-2001 by Easy Software Products, All Rights Reserved.
 .\"
-.\" End of "$Id: cupsaddsmb.man,v 1.2 2001/11/09 17:19:41 mike Exp $".
+.\" End of "$Id: cupsaddsmb.man,v 1.2.2.1 2001/12/26 16:52:41 mike Exp $".
 .\"
index edfd8c6d904c3a17c4376c16b190c0bec0b3826d..a76adcc1c818785e9c479feee4843e93f6270fff 100644 (file)
@@ -1,5 +1,5 @@
 .\"
-.\" "$Id: lp.man,v 1.6 2001/03/09 14:26:54 mike Exp $"
+.\" "$Id: lp.man,v 1.6.2.1 2001/12/26 16:52:41 mike Exp $"
 .\"
 .\"   lp/cancel man page for the Common UNIX Printing System (CUPS).
 .\"
@@ -21,7 +21,7 @@
 .\"       EMail: cups-info@cups.org
 .\"         WWW: http://www.cups.org
 .\"
-.TH lp 1 "Common UNIX Printing System" "23 January 2001" "Easy Software Products"
+.TH lp 1 "Common UNIX Printing System" "25 September 2001" "Easy Software Products"
 .SH NAME
 lp \- print files
 .br
@@ -36,7 +36,7 @@ cancel \- cancel jobs
 .I num-copies
 [ \-o
 .I option
-] [ \-p/q
+] [ \-q
 .I priority
 ] [ \-s ] [ \-t
 .I title
@@ -57,7 +57,7 @@ cancel \- cancel jobs
 .I num-copies
 [ \-o
 .I option
-] [ \-p/q
+] [ \-q
 .I priority
 ] [ \-t
 .I title
@@ -114,10 +114,10 @@ Sets the number of copies to print from 1 to 100.
 .br
 Sets a job option.
 .TP 5
-\-p/q \fIpriority\fR
+\-q \fIpriority\fR
 .br
-Sets the job priority from 1 (lowest) to 100 (highest). The default priority
-is 50.
+Sets the job priority from 1 (lowest) to 100 (highest). The
+default priority is 50.
 .TP 5
 \-s
 .br
@@ -145,6 +145,10 @@ any printable character except SPACE and TAB. Also, printer and class names are
 \fBnot\fR case-sensitive. 
 .LP
 The "m" option is not functional in CUPS 1.1.
+.LP
+The "q" option accepts a different range of values than the
+Solaris lp command, matching the IPP job priority values (1-100)
+instead of the Solaris values (0-39).
 .SH SEE ALSO
 lpstat(1),
 CUPS Software Users Manual,
@@ -152,5 +156,5 @@ http://localhost:631/documentation.html
 .SH COPYRIGHT
 Copyright 1993-2001 by Easy Software Products, All Rights Reserved.
 .\"
-.\" End of "$Id: lp.man,v 1.6 2001/03/09 14:26:54 mike Exp $".
+.\" End of "$Id: lp.man,v 1.6.2.1 2001/12/26 16:52:41 mike Exp $".
 .\"
index 9681b6854cc981797ce7ab91ecb0b047c0244b71..141afc8cabd8e3382cb5a3eb52a317d5fee2c7ec 100644 (file)
@@ -19,7 +19,8 @@
 // Array
 //------------------------------------------------------------------------
 
-Array::Array() {
+Array::Array(XRef *xrefA) {
+  xref = xrefA;
   elems = NULL;
   size = length = 0;
   ref = 1;
@@ -43,7 +44,7 @@ void Array::add(Object *elem) {
 }
 
 Object *Array::get(int i, Object *obj) {
-  return elems[i].fetch(obj);
+  return elems[i].fetch(xref, obj);
 }
 
 Object *Array::getNF(int i, Object *obj) {
index ecf2eea6fdeca7120c8223da3bc5bd0ae422c16c..1616fc33f4b15a4f862c69a65ddcdbb4fc0c4775 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "Object.h"
 
+class XRef;
+
 //------------------------------------------------------------------------
 // Array
 //------------------------------------------------------------------------
@@ -23,7 +25,7 @@ class Array {
 public:
 
   // Constructor.
-  Array();
+  Array(XRef *xrefA);
 
   // Destructor.
   ~Array();
@@ -44,6 +46,7 @@ public:
 
 private:
 
+  XRef *xref;                  // the xref table for this PDF file
   Object *elems;               // array of elements
   int size;                    // size of <elems> array
   int length;                  // number of elements in array
index 815cca3ae077b01848aae938bd4dc0ed128d05a5..fadb4763b6bd76c3098409b57348afebc903a528 100644 (file)
@@ -13,6 +13,7 @@
 #include <stddef.h>
 #include "gmem.h"
 #include "Object.h"
+#include "XRef.h"
 #include "Array.h"
 #include "Dict.h"
 #include "Page.h"
 // Catalog
 //------------------------------------------------------------------------
 
-Catalog::Catalog(Object *catDict) {
-  Object pagesDict;
+Catalog::Catalog(XRef *xrefA, GBool printCommands) {
+  Object catDict, pagesDict;
   Object obj, obj2;
   int numPages0;
   int i;
 
   ok = gTrue;
+  xref = xrefA;
   pages = NULL;
   pageRefs = NULL;
   numPages = pagesSize = 0;
+  baseURI = NULL;
 
-  if (!catDict->isDict()) {
-    error(-1, "Catalog object is wrong type (%s)", catDict->getTypeName());
+  xref->getCatalog(&catDict);
+  if (!catDict.isDict()) {
+    error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
     goto err1;
   }
 
   // read page tree
-  catDict->dictLookup("Pages", &pagesDict);
+  catDict.dictLookup("Pages", &pagesDict);
   // This should really be isDict("Pages"), but I've seen at least one
   // PDF file where the /Type entry is missing.
   if (!pagesDict.isDict()) {
@@ -64,25 +68,24 @@ Catalog::Catalog(Object *catDict) {
     pageRefs[i].num = -1;
     pageRefs[i].gen = -1;
   }
-  numPages = readPageTree(pagesDict.getDict(), NULL, 0);
+  numPages = readPageTree(pagesDict.getDict(), NULL, 0, printCommands);
   if (numPages != numPages0) {
     error(-1, "Page count in top-level pages object is incorrect");
   }
   pagesDict.free();
 
   // read named destination dictionary
-  catDict->dictLookup("Dests", &dests);
+  catDict.dictLookup("Dests", &dests);
 
   // read root of named destination tree
-  if (catDict->dictLookup("Names", &obj)->isDict())
+  if (catDict.dictLookup("Names", &obj)->isDict())
     obj.dictLookup("Dests", &nameTree);
   else
     nameTree.initNull();
   obj.free();
 
   // read base URI
-  baseURI = NULL;
-  if (catDict->dictLookup("URI", &obj)->isDict()) {
+  if (catDict.dictLookup("URI", &obj)->isDict()) {
     if (obj.dictLookup("Base", &obj2)->isString()) {
       baseURI = obj2.getString()->copy();
     }
@@ -90,6 +93,7 @@ Catalog::Catalog(Object *catDict) {
   }
   obj.free();
 
+  catDict.free();
   return;
 
  err3:
@@ -97,6 +101,7 @@ Catalog::Catalog(Object *catDict) {
  err2:
   pagesDict.free();
  err1:
+  catDict.free();
   dests.initNull();
   nameTree.initNull();
   ok = gFalse;
@@ -121,7 +126,8 @@ Catalog::~Catalog() {
   }
 }
 
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
+                         GBool printCommands) {
   Object kids;
   Object kid;
   Object kidRef;
@@ -140,7 +146,7 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
     kids.arrayGet(i, &kid);
     if (kid.isDict("Page")) {
       attrs2 = new PageAttrs(attrs1, kid.getDict());
-      page = new Page(start+1, kid.getDict(), attrs2);
+      page = new Page(xref, start+1, kid.getDict(), attrs2, printCommands);
       if (!page->isOk()) {
        ++start;
        goto err3;
@@ -166,7 +172,8 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
     // This should really be isDict("Pages"), but I've seen at least one
     // PDF file where the /Type entry is missing.
     } else if (kid.isDict()) {
-      if ((start = readPageTree(kid.getDict(), attrs1, start)) < 0)
+      if ((start = readPageTree(kid.getDict(), attrs1, start, printCommands))
+         < 0)
        goto err2;
     } else {
       error(-1, "Kid object (page %d) is wrong type (%s)",
index b0f314323383787890e65efd60af1d52cbf3cbe5..5bf0c74a79f40005968836dc828304fe9a2af790 100644 (file)
@@ -13,6 +13,7 @@
 #pragma interface
 #endif
 
+class XRef;
 class Object;
 class Page;
 class PageAttrs;
@@ -27,7 +28,7 @@ class Catalog {
 public:
 
   // Constructor.
-  Catalog(Object *catDict);
+  Catalog(XRef *xrefA, GBool printCommands = gFalse);
 
   // Destructor.
   ~Catalog();
@@ -57,6 +58,7 @@ public:
 
 private:
 
+  XRef *xref;                  // the xref table for this PDF file
   Page **pages;                        // array of pages
   Ref *pageRefs;               // object ID for each page
   int numPages;                        // number of pages
@@ -66,7 +68,8 @@ private:
   GString *baseURI;            // base URI for URI-type links
   GBool ok;                    // true if catalog is valid
 
-  int readPageTree(Dict *pages, PageAttrs *attrs, int start);
+  int readPageTree(Dict *pages, PageAttrs *attrs, int start,
+                  GBool printCommands);
   Object *findDestInTree(Object *tree, GString *name, Object *obj);
 };
 
index 159f4bf36bb512bbcfb05d0e1316f30b813f80b7..c6426602977dfdec3d9ed42cc49ece700884a77d 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef COMPACTFONTINFO_H
 #define COMPACTFONTINFO_H
 
-static const char *type1CStdStrings[391] = {
+static char *type1CStdStrings[391] = {
   ".notdef",
   "space",
   "exclam",
index ae9b73239db692f92197f7191d4c1ceb5c1be874..623f59417f7f14a81998052e3908571baadb4886 100644 (file)
@@ -28,42 +28,96 @@ static Guchar passwordPad[32] = {
 // Decrypt
 //------------------------------------------------------------------------
 
-Decrypt::Decrypt(Guchar *fileKey, int objNum, int objGen) {
+Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
+  int i;
+
   // construct object key
-  objKey[0] = fileKey[0];
-  objKey[1] = fileKey[1];
-  objKey[2] = fileKey[2];
-  objKey[3] = fileKey[3];
-  objKey[4] = fileKey[4];
-  objKey[5] = objNum & 0xff;
-  objKey[6] = (objNum >> 8) & 0xff;
-  objKey[7] = (objNum >> 16) & 0xff;
-  objKey[8] = objGen & 0xff;
-  objKey[9] = (objGen >> 8) & 0xff;
-  md5(objKey, 10, objKey);
+  for (i = 0; i < keyLength; ++i) {
+    objKey[i] = fileKey[i];
+  }
+  objKey[keyLength] = objNum & 0xff;
+  objKey[keyLength + 1] = (objNum >> 8) & 0xff;
+  objKey[keyLength + 2] = (objNum >> 16) & 0xff;
+  objKey[keyLength + 3] = objGen & 0xff;
+  objKey[keyLength + 4] = (objGen >> 8) & 0xff;
+  md5(objKey, keyLength + 5, objKey);
 
   // set up for decryption
   x = y = 0;
-  rc4InitKey(objKey, 10, state);
+  if ((objKeyLength = keyLength + 5) > 16) {
+    objKeyLength = 16;
+  }
+  rc4InitKey(objKey, objKeyLength, state);
 }
 
 void Decrypt::reset() {
   x = y = 0;
-  rc4InitKey(objKey, 10, state);
+  rc4InitKey(objKey, objKeyLength, state);
 }
 
 Guchar Decrypt::decryptByte(Guchar c) {
   return rc4DecryptByte(state, &x, &y, c);
 }
 
-GBool Decrypt::makeFileKey(GString *ownerKey, GString *userKey,
+GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
+                          GString *ownerKey, GString *userKey,
                           int permissions, GString *fileID,
-                          GString *userPassword, Guchar *fileKey) {
-  Guchar *buf;
-  Guchar userTest[32];
+                          GString *ownerPassword, GString *userPassword,
+                          Guchar *fileKey, GBool *ownerPasswordOk) {
+  Guchar test[32];
+  GString *userPassword2;
   Guchar fState[256];
   Guchar fx, fy;
   int len, i;
+
+  // try using the supplied owner password to generate the user password
+  if (ownerPassword) {
+    len = ownerPassword->getLength();
+    if (len < 32) {
+      memcpy(test, ownerPassword->getCString(), len);
+      memcpy(test + len, passwordPad, 32 - len);
+    } else {
+      memcpy(test, ownerPassword->getCString(), 32);
+    }
+  } else {
+    memcpy(test, passwordPad, 32);
+  }
+  md5(test, 32, test);
+  if (encRevision == 3) {
+    for (i = 0; i < 50; ++i) {
+      md5(test, 16, test);
+    }
+  }
+  rc4InitKey(test, keyLength, fState);
+  fx = fy = 0;
+  for (i = 0; i < 32; ++i) {
+    test[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
+  }
+  userPassword2 = new GString((char *)test, 32);
+  if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
+                  permissions, fileID, userPassword2, fileKey)) {
+    *ownerPasswordOk = gTrue;
+    delete userPassword2;
+    return gTrue;
+  }
+  *ownerPasswordOk = gFalse;
+  delete userPassword2;
+
+  // try using the supplied user password
+  return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
+                     permissions, fileID, userPassword, fileKey);
+}
+
+GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
+                           GString *ownerKey, GString *userKey,
+                           int permissions, GString *fileID,
+                           GString *userPassword, Guchar *fileKey) {
+  Guchar *buf;
+  Guchar test[32];
+  Guchar fState[256];
+  Guchar tmpKey[16];
+  Guchar fx, fy;
+  int len, i, j;
   GBool ok;
 
   // generate file key
@@ -86,16 +140,41 @@ GBool Decrypt::makeFileKey(GString *ownerKey, GString *userKey,
   buf[67] = (permissions >> 24) & 0xff;
   memcpy(buf + 68, fileID->getCString(), fileID->getLength());
   md5(buf, 68 + fileID->getLength(), fileKey);
+  if (encRevision == 3) {
+    for (i = 0; i < 50; ++i) {
+      md5(fileKey, 16, fileKey);
+    }
+  }
 
-  // test user key
-  fx = fy = 0;
-  rc4InitKey(fileKey, 5, fState);
-  for (i = 0; i < 32; ++i) {
-    userTest[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
+  // test user password
+  if (encRevision == 2) {
+    rc4InitKey(fileKey, keyLength, fState);
+    fx = fy = 0;
+    for (i = 0; i < 32; ++i) {
+      test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
+    }
+    ok = memcmp(test, passwordPad, 32) == 0;
+  } else if (encRevision == 3) {
+    memcpy(test, userKey->getCString(), 32);
+    for (i = 19; i >= 0; --i) {
+      for (j = 0; j < keyLength; ++j) {
+       tmpKey[j] = fileKey[j] ^ i;
+      }
+      rc4InitKey(tmpKey, keyLength, fState);
+      fx = fy = 0;
+      for (j = 0; j < 32; ++j) {
+       test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
+      }
+    }
+    memcpy(buf, passwordPad, 32);
+    memcpy(buf + 32, fileID->getCString(), fileID->getLength());
+    md5(buf, 32 + fileID->getLength(), buf);
+    ok = memcmp(test, buf, 16) == 0;
+  } else {
+    ok = gFalse;
   }
-  ok = memcmp(userTest, passwordPad, 32) == 0;
-  gfree(buf);
 
+  gfree(buf);
   return ok;
 }
 
@@ -136,6 +215,7 @@ static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
 // MD5 message digest
 //------------------------------------------------------------------------
 
+// this works around a bug in older Sun compilers
 static inline Gulong rotateLeft(Gulong x, int r) {
   x &= 0xffffffff;
   return ((x << r) | (x >> (32 - r))) & 0xffffffff;
index 3ea43741dc77c5b698402277d2a46a377dc02bb5..1bdb2b7ec2c324e0a6a542f55654ffd83fbcfd58 100644 (file)
@@ -24,7 +24,7 @@ class Decrypt {
 public:
 
   // Initialize the decryptor object.
-  Decrypt(Guchar *fileKey, int objNum, int objGen);
+  Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen);
 
   // Reset decryption.
   void reset();
@@ -32,16 +32,26 @@ public:
   // Decrypt one byte.
   Guchar decryptByte(Guchar c);
 
-  // Generate a file key.  The <fileKey> buffer must have space for
-  // at least 16 bytes.  Checks user key and returns gTrue if okay.
-  // <userPassword> may be NULL.
-  static GBool makeFileKey(GString *ownerKey, GString *userKey,
+  // Generate a file key.  The <fileKey> buffer must have space for at
+  // least 16 bytes.  Checks <ownerPassword> and then <userPassword>
+  // and returns true if either is correct.  Sets <ownerPasswordOk> if
+  // the owner password was correct.  Either or both of the passwords
+  // may be NULL, which is treated as an empty string.
+  static GBool makeFileKey(int encVersion, int encRevision, int keyLength,
+                          GString *ownerKey, GString *userKey,
                           int permissions, GString *fileID,
-                          GString *userPassword, Guchar *fileKey);
+                          GString *ownerPassword, GString *userPassword,
+                          Guchar *fileKey, GBool *ownerPasswordOk);
 
 private:
 
-  Guchar objKey[16];
+  static GBool makeFileKey2(int encVersion, int encRevision, int keyLength,
+                           GString *ownerKey, GString *userKey,
+                           int permissions, GString *fileID,
+                           GString *userPassword, Guchar *fileKey);
+
+  int objKeyLength;
+  Guchar objKey[21];
   Guchar state[256];
   Guchar x, y;
 };
index 9ec4815bd98cb3ad1e945f90f85f4fefe57951aa..1ebadfce0acaeeb4c311a0961d2811d75cba3cd6 100644 (file)
@@ -21,7 +21,8 @@
 // Dict
 //------------------------------------------------------------------------
 
-Dict::Dict() {
+Dict::Dict(XRef *xrefA) {
+  xref = xrefA;
   entries = NULL;
   size = length = 0;
   ref = 1;
@@ -31,13 +32,13 @@ Dict::~Dict() {
   int i;
 
   for (i = 0; i < length; ++i) {
-    gfree((void *)entries[i].key);
+    gfree(entries[i].key);
     entries[i].val.free();
   }
   gfree(entries);
 }
 
-void Dict::add(const char *key, Object *val) {
+void Dict::add(char *key, Object *val) {
   if (length + 1 > size) {
     size += 8;
     entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry));
@@ -47,7 +48,7 @@ void Dict::add(const char *key, Object *val) {
   ++length;
 }
 
-inline DictEntry *Dict::find(const char *key) {
+inline DictEntry *Dict::find(char *key) {
   int i;
 
   for (i = 0; i < length; ++i) {
@@ -57,30 +58,30 @@ inline DictEntry *Dict::find(const char *key) {
   return NULL;
 }
 
-GBool Dict::is(const char *type) {
+GBool Dict::is(char *type) {
   DictEntry *e;
 
   return (e = find("Type")) && e->val.isName(type);
 }
 
-Object *Dict::lookup(const char *key, Object *obj) {
+Object *Dict::lookup(char *key, Object *obj) {
   DictEntry *e;
 
-  return (e = find(key)) ? e->val.fetch(obj) : obj->initNull();
+  return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull();
 }
 
-Object *Dict::lookupNF(const char *key, Object *obj) {
+Object *Dict::lookupNF(char *key, Object *obj) {
   DictEntry *e;
 
   return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
 }
 
-const char *Dict::getKey(int i) {
+char *Dict::getKey(int i) {
   return entries[i].key;
 }
 
 Object *Dict::getVal(int i, Object *obj) {
-  return entries[i].val.fetch(obj);
+  return entries[i].val.fetch(xref, obj);
 }
 
 Object *Dict::getValNF(int i, Object *obj) {
index 37f656587cbfc8d2c53aab90154c124cdbde1685..c4f1ea58d4b64223c4dabcf87d8ceb717773148e 100644 (file)
@@ -20,7 +20,7 @@
 //------------------------------------------------------------------------
 
 struct DictEntry {
-  const char *key;
+  char *key;
   Object val;
 };
 
@@ -28,7 +28,7 @@ class Dict {
 public:
 
   // Constructor.
-  Dict();
+  Dict(XRef *xrefA);
 
   // Destructor.
   ~Dict();
@@ -41,29 +41,35 @@ public:
   int getLength() { return length; }
 
   // Add an entry.  NB: does not copy key.
-  void add(const char *key, Object *val);
+  void add(char *key, Object *val);
 
   // Check if dictionary is of specified type.
-  GBool is(const char *type);
+  GBool is(char *type);
 
   // Look up an entry and return the value.  Returns a null object
   // if <key> is not in the dictionary.
-  Object *lookup(const char *key, Object *obj);
-  Object *lookupNF(const char *key, Object *obj);
+  Object *lookup(char *key, Object *obj);
+  Object *lookupNF(char *key, Object *obj);
 
   // Iterative accessors.
-  const char *getKey(int i);
+  char *getKey(int i);
   Object *getVal(int i, Object *obj);
   Object *getValNF(int i, Object *obj);
 
+  // Set the xref pointer.  This is only used in one special case: the
+  // trailer dictionary, which is read before the xref table is
+  // parsed.
+  void setXRef(XRef *xrefA) { xref = xrefA; }
+
 private:
 
+  XRef *xref;                  // the xref table for this PDF file
   DictEntry *entries;          // array of entries
   int size;                    // size of <entries> array
   int length;                  // number of entries in dictionary
   int ref;                     // reference count
 
-  DictEntry *find(const char *key);
+  DictEntry *find(char *key);
 };
 
 #endif
index 96a96d2bf2fdbdeb4bafe72057b6b31692f6b712..81010e0199ecb65331a802e343fbcf48988df7c5 100644 (file)
@@ -34,13 +34,10 @@ void CDECL error(int pos, const char *msg, ...) {
   if (errQuiet) {
     return;
   }
-  if (printCommands) {
-    fflush(stdout);
-  }
   if (pos >= 0) {
-    fprintf(errFile, "ERROR: (%d): ", pos);
+    fprintf(errFile, "Error (%d): ", pos);
   } else {
-    fprintf(errFile, "ERROR: ");
+    fprintf(errFile, "Error: ");
   }
   va_start(args, msg);
   vfprintf(errFile, msg, args);
index f526445019628ec60b34af043e807b6771a61b18..3d084cc9da8cdce207fa388c4e0fb7cf8dcc3197 100644 (file)
@@ -21,7 +21,7 @@
 // FontEncoding
 //------------------------------------------------------------------------
 
-inline int FontEncoding::hash(const char *name) {
+inline int FontEncoding::hash(char *name) {
   Guint h;
 
   h = (Guint)name[0] & 0xff;
@@ -33,7 +33,7 @@ inline int FontEncoding::hash(const char *name) {
 FontEncoding::FontEncoding() {
   int i;
 
-  encoding = (const char **)gmalloc(256 * sizeof(const char *));
+  encoding = (char **)gmalloc(256 * sizeof(char *));
   size = 256;
   freeEnc = gTrue;
   for (i = 0; i < 256; ++i)
@@ -42,24 +42,24 @@ FontEncoding::FontEncoding() {
     hashTab[i] = -1;
 }
 
-FontEncoding::FontEncoding(const char **nencoding, int nsize) {
+FontEncoding::FontEncoding(char **encodingA, int sizeA) {
   int i;
 
-  encoding = nencoding;
-  size = nsize;
+  encoding = encodingA;
+  size = sizeA;
   freeEnc = gFalse;
   for (i = 0; i < fontEncHashSize; ++i)
     hashTab[i] = -1;
   for (i = 0; i < size; ++i) {
-    if (nencoding[i])
-      addChar1(i, nencoding[i]);
+    if (encoding[i])
+      addChar1(i, encoding[i]);
   }
 }
 
 FontEncoding::FontEncoding(FontEncoding *fontEnc) {
   int i;
 
-  encoding = (const char **)gmalloc(fontEnc->size * sizeof(const char *));
+  encoding = (char **)gmalloc(fontEnc->size * sizeof(char *));
   size = fontEnc->size;
   freeEnc = gTrue;
   for (i = 0; i < size; ++i) {
@@ -69,7 +69,7 @@ FontEncoding::FontEncoding(FontEncoding *fontEnc) {
   memcpy(hashTab, fontEnc->hashTab, fontEncHashSize * sizeof(short));
 }
 
-void FontEncoding::addChar(int code, const char *name) {
+void FontEncoding::addChar(int code, char *name) {
   int h, i;
 
   // replace character associated with code
@@ -83,7 +83,7 @@ void FontEncoding::addChar(int code, const char *name) {
       if (++h == fontEncHashSize)
        h = 0;
     }
-    gfree((void *)encoding[code]);
+    gfree(encoding[code]);
   }
 
   // associate name with code
@@ -93,7 +93,7 @@ void FontEncoding::addChar(int code, const char *name) {
   addChar1(code, name);
 }
 
-void FontEncoding::addChar1(int code, const char *name) {
+void FontEncoding::addChar1(int code, char *name) {
   int h, i, code2;
 
   // insert name in hash table
@@ -121,13 +121,13 @@ FontEncoding::~FontEncoding() {
   if (freeEnc) {
     for (i = 0; i < size; ++i) {
       if (encoding[i])
-       gfree((void *)encoding[i]);
+       gfree(encoding[i]);
     }
-    gfree((void *)encoding);
+    gfree(encoding);
   }
 }
 
-int FontEncoding::getCharCode(const char *name) {
+int FontEncoding::getCharCode(char *name) {
   int h, i, code;
 
   h = hash(name);
index 120858b9bdcf5327c8539d5b90d8af231f0de912..9a5695dbe557a8edc1291cb5a65f1a4f97e380a0 100644 (file)
@@ -28,7 +28,7 @@ public:
   FontEncoding();
 
   // Construct an encoding from an array of char names.
-  FontEncoding(const char **encoding, int size);
+  FontEncoding(char **encodingA, int sizeA);
 
   // Destructor.
   ~FontEncoding();
@@ -40,21 +40,21 @@ public:
   int getSize() { return size; }
 
   // Add a char to the encoding.
-  void addChar(int code, const char *name);
+  void addChar(int code, char *name);
 
   // Return the character name associated with <code>.
-  const char *getCharName(int code) { return encoding[code]; }
+  char *getCharName(int code) { return encoding[code]; }
 
   // Return the code associated with <name>.
-  int getCharCode(const char *name);
+  int getCharCode(char *name);
 
 private:
 
   FontEncoding(FontEncoding *fontEnc);
-  int hash(const char *name);
-  void addChar1(int code, const char *name);
+  int hash(char *name);
+  void addChar1(int code, char *name);
 
-  const char **encoding;       // code --> name mapping
+  char **encoding;             // code --> name mapping
   int size;                    // number of codes
   GBool freeEnc;               // should we free the encoding array?
   short                                // name --> code hash table
index 5ec923a0dbfa3e8146558d9ad6cf10c5c6661da5..4054db7cd0c857f40b6e9d01efccb969ec5c73d9 100644 (file)
@@ -32,7 +32,7 @@ static char *getString(int sid, Guchar *stringIdxPtr,
 
 //------------------------------------------------------------------------
 
-static inline const char *nextLine(const char *line, const char *end) {
+static inline char *nextLine(char *line, char *end) {
   while (line < end && *line != '\n' && *line != '\r')
     ++line;
   while (line < end && *line == '\n' || *line == '\r')
@@ -56,9 +56,8 @@ FontFile::~FontFile() {
 // Type1FontFile
 //------------------------------------------------------------------------
 
-Type1FontFile::Type1FontFile(const char *file, int len) {
-  const char *line, *line1;
-  char *p, *p2;
+Type1FontFile::Type1FontFile(char *file, int len) {
+  char *line, *line1, *p, *p2;
   char buf[256];
   char c;
   int n, code, i;
@@ -125,7 +124,7 @@ Type1FontFile::Type1FontFile(const char *file, int len) {
 
 Type1FontFile::~Type1FontFile() {
   if (name)
-    gfree((void *)name);
+    gfree(name);
   if (encoding && freeEnc)
     delete encoding;
 }
@@ -140,11 +139,11 @@ FontEncoding *Type1FontFile::getEncoding(GBool taken) {
 // Type1CFontFile
 //------------------------------------------------------------------------
 
-Type1CFontFile::Type1CFontFile(const char *file, int len) {
+Type1CFontFile::Type1CFontFile(char *file, int len) {
   char buf[256];
   Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
   Guchar *stringIdxPtr, *stringStartPtr;
-  int idxOffSize, stringOffSize;
+  int topOffSize, idxOffSize, stringOffSize;
   int nFonts, nStrings, nGlyphs;
   int nCodes, nRanges, nLeft, nSups;
   Gushort *glyphNames;
@@ -157,14 +156,13 @@ Type1CFontFile::Type1CFontFile(const char *file, int len) {
   int key;
   int i, j, n;
 
-  (void)len;
-
   name = NULL;
   encoding = NULL;
   freeEnc = gTrue;
 
   // read header
   topPtr = (Guchar *)file + (file[2] & 0xff);
+  topOffSize = file[3] & 0xff;
 
   // read name index (first font only)
   nFonts = getWord(topPtr, 2);
@@ -175,7 +173,7 @@ Type1CFontFile::Type1CFontFile(const char *file, int len) {
   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
   if ((n = idxPtr1 - idxPtr0) > 255)
     n = 255;
-  strncpy(buf, (const char *)idxPtr0, n);
+  strncpy(buf, (char *)idxPtr0, n);
   buf[n] = '\0';
   name = copyString(buf);
   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
@@ -318,7 +316,7 @@ Type1CFontFile::Type1CFontFile(const char *file, int len) {
 
 Type1CFontFile::~Type1CFontFile() {
   if (name)
-    gfree((void *)name);
+    gfree(name);
   if (encoding && freeEnc)
     delete encoding;
 }
@@ -415,7 +413,7 @@ static char *getString(int sid, Guchar *stringIdxPtr,
                                       stringOffSize);
     if ((len = idxPtr1 - idxPtr0) > 255)
       len = 255;
-    strncpy(buf, (const char *)idxPtr0, len);
+    strncpy(buf, (char *)idxPtr0, len);
     buf[len] = '\0';
   }
   return buf;
@@ -425,10 +423,10 @@ static char *getString(int sid, Guchar *stringIdxPtr,
 // Type1CFontConverter
 //------------------------------------------------------------------------
 
-Type1CFontConverter::Type1CFontConverter(const char *nfile, int nlen, FILE *nout) {
-  file = nfile;
-  len = nlen;
-  out = nout;
+Type1CFontConverter::Type1CFontConverter(char *fileA, int lenA, FILE *outA) {
+  file = fileA;
+  len = lenA;
+  out = outA;
   r1 = 55665;
   line = 0;
 }
@@ -437,7 +435,7 @@ Type1CFontConverter::~Type1CFontConverter() {
 }
 
 void Type1CFontConverter::convert() {
-  const char *fontName;
+  char *fontName;
   struct {
     int version;
     int notice;
@@ -464,7 +462,7 @@ void Type1CFontConverter::convert() {
   char buf[256], eBuf[256];
   Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
   Guchar *stringIdxPtr, *stringStartPtr;
-  int idxOffSize, stringOffSize;
+  int topOffSize, idxOffSize, stringOffSize;
   int nFonts, nStrings, nGlyphs;
   int nCodes, nRanges, nLeft, nSups;
   Gushort *glyphNames;
@@ -479,6 +477,7 @@ void Type1CFontConverter::convert() {
 
   // read header
   topPtr = (Guchar *)file + (file[2] & 0xff);
+  topOffSize = file[3] & 0xff;
 
   // read name (first font only)
   nFonts = getWord(topPtr, 2);
@@ -489,7 +488,7 @@ void Type1CFontConverter::convert() {
   idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
   if ((n = idxPtr1 - idxPtr0) > 255)
     n = 255;
-  strncpy(buf, (const char *)idxPtr0, n);
+  strncpy(buf, (char *)idxPtr0, n);
   buf[n] = '\0';
   fontName = copyString(buf);
   topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
@@ -587,8 +586,15 @@ void Type1CFontConverter::convert() {
   topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
                                    stringOffSize);
 
-  // skip global subrs
+#if 1 //~
+  // get global subrs
+  int nGSubrs;
+  int gSubrOffSize;
+
+  nGSubrs = getWord(topPtr, 2);
+  gSubrOffSize = topPtr[2];
   topPtr += 3;
+#endif
 
   // write header and font dictionary, up to encoding
   fprintf(out, "%%!FontType1-1.0: %s", fontName);
@@ -845,7 +851,7 @@ void Type1CFontConverter::convert() {
        nominalWidthXFP = fp[0];
        break;
       default:
-       error(-1, "Uknown Type 1C private dict entry %04x", key);
+       error(-1, "Unknown Type 1C private dict entry %04x", key);
        break;
       }
       i = 0;
@@ -918,11 +924,11 @@ void Type1CFontConverter::convert() {
 
   // clean up
   if (dict.charset > 2)
-    gfree((void *)glyphNames);
-  gfree((void *)fontName);
+    gfree(glyphNames);
+  gfree(fontName);
 }
 
-void Type1CFontConverter::eexecWrite(const char *s) {
+void Type1CFontConverter::eexecWrite(char *s) {
   Guchar *p;
   Guchar x;
 
@@ -939,7 +945,7 @@ void Type1CFontConverter::eexecWrite(const char *s) {
   }
 }
 
-void Type1CFontConverter::cvtGlyph(const char *name, Guchar *s, int n) {
+void Type1CFontConverter::cvtGlyph(char *name, Guchar *s, int n) {
   int nHints;
   int x;
   GBool first = gTrue;
@@ -1509,12 +1515,12 @@ void Type1CFontConverter::cvtGlyphWidth(GBool useOp) {
   eexecDumpOp1(13);
 }
 
-void Type1CFontConverter::eexecDumpNum(double x, GBool nfp) {
+void Type1CFontConverter::eexecDumpNum(double x, GBool fpA) {
   Guchar buf[12];
   int y, n;
 
   n = 0;
-  if (nfp) {
+  if (fpA) {
     if (x >= -32768 && x < 32768) {
       y = (int)(x * 256.0);
       buf[0] = 255;
@@ -1557,16 +1563,16 @@ void Type1CFontConverter::eexecDumpNum(double x, GBool nfp) {
       n = 5;
     }
   }
-  charBuf->append((const char *)buf, n);
+  charBuf->append((char *)buf, n);
 }
 
-void Type1CFontConverter::eexecDumpOp1(int nop) {
-  charBuf->append((char)nop);
+void Type1CFontConverter::eexecDumpOp1(int opA) {
+  charBuf->append((char)opA);
 }
 
-void Type1CFontConverter::eexecDumpOp2(int nop) {
+void Type1CFontConverter::eexecDumpOp2(int opA) {
   charBuf->append((char)12);
-  charBuf->append((char)nop);
+  charBuf->append((char)opA);
 }
 
 void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
@@ -1595,7 +1601,7 @@ void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
   }
 }
 
-void Type1CFontConverter::getDeltaInt(char *buf, const char *name, double *nop,
+void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *opA,
                                      int n) {
   int x, i;
 
@@ -1603,14 +1609,14 @@ void Type1CFontConverter::getDeltaInt(char *buf, const char *name, double *nop,
   buf += strlen(buf);
   x = 0;
   for (i = 0; i < n; ++i) {
-    x += (int)nop[i];
+    x += (int)opA[i];
     sprintf(buf, "%s%d", i > 0 ? " " : "", x);
     buf += strlen(buf);
   }
   sprintf(buf, "] def\n");
 }
 
-void Type1CFontConverter::getDeltaReal(char *buf, const char *name, double *nop,
+void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *opA,
                                       int n) {
   double x;
   int i;
@@ -1619,9 +1625,906 @@ void Type1CFontConverter::getDeltaReal(char *buf, const char *name, double *nop,
   buf += strlen(buf);
   x = 0;
   for (i = 0; i < n; ++i) {
-    x += nop[i];
+    x += opA[i];
     sprintf(buf, "%s%g", i > 0 ? " " : "", x);
     buf += strlen(buf);
   }
   sprintf(buf, "] def\n");
 }
+
+//------------------------------------------------------------------------
+// TrueTypeFontFile
+//------------------------------------------------------------------------
+
+//
+// Terminology
+// -----------
+//
+// character code = number used as an element of a text string
+//
+// character name = glyph name = name for a particular glyph within a
+//                  font
+//
+// glyph index = position (within some internal table in the font)
+//               where the instructions to draw a particular glyph are
+//               stored
+//
+// Type 1 fonts
+// ------------
+//
+// Type 1 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+//           Encoding[charCode] = charName
+//
+// CharStrings: dictionary of instructions, keyed by character names,
+//              maps character name to glyph data
+//
+//              CharStrings[charName] = glyphData
+//
+// TrueType fonts
+// --------------
+//
+// TrueType fonts contain:
+//
+// 'cmap' table: mapping from character code to glyph index; there may
+//               be multiple cmaps in a TrueType font
+//
+//               cmap[charCode] = glyphIdx
+//
+// 'post' table: mapping from glyph index to glyph name
+//
+//               post[glyphIdx] = glyphName
+//
+// Type 42 fonts
+// -------------
+//
+// Type 42 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+//           Encoding[charCode] = charName
+//
+// CharStrings: dictionary of glyph indexes, keyed by character names,
+//              maps character name to glyph index
+//
+//              CharStrings[charName] = glyphIdx
+//
+
+struct TTFontTableHdr {
+  char tag[4];
+  Guint checksum;
+  Guint offset;
+  Guint length;
+};
+
+// TrueType tables required by the Type 42 spec.
+static char *t42ReqTables[9] = {
+  "head",
+  "hhea",
+  "loca",
+  "maxp",
+  "cvt ",
+  "prep",
+  "glyf",
+  "hmtx",
+  "fpgm"
+};
+
+// Glyph names in some arbitrary standard that Apple uses for their
+// TrueType fonts.
+static char *macGlyphNames[258] = {
+  ".notdef",
+  "null",
+  "CR",
+  "space",
+  "exclam",
+  "quotedbl",
+  "numbersign",
+  "dollar",
+  "percent",
+  "ampersand",
+  "quotesingle",
+  "parenleft",
+  "parenright",
+  "asterisk",
+  "plus",
+  "comma",
+  "hyphen",
+  "period",
+  "slash",
+  "zero",
+  "one",
+  "two",
+  "three",
+  "four",
+  "five",
+  "six",
+  "seven",
+  "eight",
+  "nine",
+  "colon",
+  "semicolon",
+  "less",
+  "equal",
+  "greater",
+  "question",
+  "at",
+  "A",
+  "B",
+  "C",
+  "D",
+  "E",
+  "F",
+  "G",
+  "H",
+  "I",
+  "J",
+  "K",
+  "L",
+  "M",
+  "N",
+  "O",
+  "P",
+  "Q",
+  "R",
+  "S",
+  "T",
+  "U",
+  "V",
+  "W",
+  "X",
+  "Y",
+  "Z",
+  "bracketleft",
+  "backslash",
+  "bracketright",
+  "asciicircum",
+  "underscore",
+  "grave",
+  "a",
+  "b",
+  "c",
+  "d",
+  "e",
+  "f",
+  "g",
+  "h",
+  "i",
+  "j",
+  "k",
+  "l",
+  "m",
+  "n",
+  "o",
+  "p",
+  "q",
+  "r",
+  "s",
+  "t",
+  "u",
+  "v",
+  "w",
+  "x",
+  "y",
+  "z",
+  "braceleft",
+  "bar",
+  "braceright",
+  "asciitilde",
+  "Adieresis",
+  "Aring",
+  "Ccedilla",
+  "Eacute",
+  "Ntilde",
+  "Odieresis",
+  "Udieresis",
+  "aacute",
+  "agrave",
+  "acircumflex",
+  "adieresis",
+  "atilde",
+  "aring",
+  "ccedilla",
+  "eacute",
+  "egrave",
+  "ecircumflex",
+  "edieresis",
+  "iacute",
+  "igrave",
+  "icircumflex",
+  "idieresis",
+  "ntilde",
+  "oacute",
+  "ograve",
+  "ocircumflex",
+  "odieresis",
+  "otilde",
+  "uacute",
+  "ugrave",
+  "ucircumflex",
+  "udieresis",
+  "dagger",
+  "degree",
+  "cent",
+  "sterling",
+  "section",
+  "bullet",
+  "paragraph",
+  "germandbls",
+  "registered",
+  "copyright",
+  "trademark",
+  "acute",
+  "dieresis",
+  "notequal",
+  "AE",
+  "Oslash",
+  "infinity",
+  "plusminus",
+  "lessequal",
+  "greaterequal",
+  "yen",
+  "mu1",
+  "partialdiff",
+  "summation",
+  "product",
+  "pi",
+  "integral",
+  "ordfeminine",
+  "ordmasculine",
+  "Ohm",
+  "ae",
+  "oslash",
+  "questiondown",
+  "exclamdown",
+  "logicalnot",
+  "radical",
+  "florin",
+  "approxequal",
+  "increment",
+  "guillemotleft",
+  "guillemotright",
+  "ellipsis",
+  "nbspace",
+  "Agrave",
+  "Atilde",
+  "Otilde",
+  "OE",
+  "oe",
+  "endash",
+  "emdash",
+  "quotedblleft",
+  "quotedblright",
+  "quoteleft",
+  "quoteright",
+  "divide",
+  "lozenge",
+  "ydieresis",
+  "Ydieresis",
+  "fraction",
+  "currency",
+  "guilsinglleft",
+  "guilsinglright",
+  "fi",
+  "fl",
+  "daggerdbl",
+  "periodcentered",
+  "quotesinglbase",
+  "quotedblbase",
+  "perthousand",
+  "Acircumflex",
+  "Ecircumflex",
+  "Aacute",
+  "Edieresis",
+  "Egrave",
+  "Iacute",
+  "Icircumflex",
+  "Idieresis",
+  "Igrave",
+  "Oacute",
+  "Ocircumflex",
+  "applelogo",
+  "Ograve",
+  "Uacute",
+  "Ucircumflex",
+  "Ugrave",
+  "dotlessi",
+  "circumflex",
+  "tilde",
+  "overscore",
+  "breve",
+  "dotaccent",
+  "ring",
+  "cedilla",
+  "hungarumlaut",
+  "ogonek",
+  "caron",
+  "Lslash",
+  "lslash",
+  "Scaron",
+  "scaron",
+  "Zcaron",
+  "zcaron",
+  "brokenbar",
+  "Eth",
+  "eth",
+  "Yacute",
+  "yacute",
+  "Thorn",
+  "thorn",
+  "minus",
+  "multiply",
+  "onesuperior",
+  "twosuperior",
+  "threesuperior",
+  "onehalf",
+  "onequarter",
+  "threequarters",
+  "franc",
+  "Gbreve",
+  "gbreve",
+  "Idot",
+  "Scedilla",
+  "scedilla",
+  "Cacute",
+  "cacute",
+  "Ccaron",
+  "ccaron",
+  "dmacron"
+};
+
+TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
+  int pos, i;
+
+  file = fileA;
+  len = lenA;
+
+  encoding = NULL;
+  freeEnc = gTrue;
+
+  // read table directory
+  nTables = getUShort(4);
+  tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
+  pos = 12;
+  for (i = 0; i < nTables; ++i) {
+    tableHdrs[i].tag[0] = getByte(pos+0);
+    tableHdrs[i].tag[1] = getByte(pos+1);
+    tableHdrs[i].tag[2] = getByte(pos+2);
+    tableHdrs[i].tag[3] = getByte(pos+3);
+    tableHdrs[i].checksum = getULong(pos+4);
+    tableHdrs[i].offset = getULong(pos+8);
+    tableHdrs[i].length = getULong(pos+12);
+    pos += 16;
+  }
+
+  // check for tables that are required by both the TrueType spec
+  // and the Type 42 spec
+  if (seekTable("head") < 0 ||
+      seekTable("hhea") < 0 ||
+      seekTable("loca") < 0 ||
+      seekTable("maxp") < 0 ||
+      seekTable("glyf") < 0 ||
+      seekTable("hmtx") < 0) {
+    error(-1, "TrueType font file is missing a required table");
+    return;
+  }
+
+  // read the 'head' table
+  pos = seekTable("head");
+  bbox[0] = getShort(pos + 36);
+  bbox[1] = getShort(pos + 38);
+  bbox[2] = getShort(pos + 40);
+  bbox[3] = getShort(pos + 42);
+  locaFmt = getShort(pos + 50);
+
+  // read the 'maxp' table
+  pos = seekTable("maxp");
+  nGlyphs = getUShort(pos + 4);
+}
+
+TrueTypeFontFile::~TrueTypeFontFile() {
+  if (encoding && freeEnc) {
+    delete encoding;
+  }
+  gfree(tableHdrs);
+}
+
+char *TrueTypeFontFile::getName() {
+  return NULL;
+}
+
+FontEncoding *TrueTypeFontFile::getEncoding(GBool taken) {
+  int cmap[256];
+  int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapLen, cmapOffset;
+  int segCnt, segStart, segEnd, segDelta, segOffset;
+  int pos, i, j, k;
+  Guint fmt;
+  GString *s;
+  int stringIdx, stringPos, n;
+
+  //----- construct the (char code) -> (glyph idx) mapping
+
+  // map everything to the missing glyph
+  for (i = 0; i < 256; ++i) {
+    cmap[i] = 0;
+  }
+
+  // look for the 'cmap' table
+  if ((pos = seekTable("cmap")) >= 0) {
+    nCmaps = getUShort(pos+2);
+
+    // if the font has a Windows-symbol cmap, use it;
+    // otherwise, use the first cmap in the table
+    for (i = 0; i < nCmaps; ++i) {
+      cmapPlatform = getUShort(pos + 4 + 8*i);
+      cmapEncoding = getUShort(pos + 4 + 8*i + 2);
+      if (cmapPlatform == 3 && cmapEncoding == 0) {
+       break;
+      }
+    }
+    if (i >= nCmaps) {
+      i = 0;
+      cmapPlatform = getUShort(pos + 4);
+      cmapEncoding = getUShort(pos + 4 + 2);
+    }
+    pos += getULong(pos + 4 + 8*i + 4);
+
+    // read the cmap
+    cmapFmt = getUShort(pos);
+    switch (cmapFmt) {
+    case 0: // byte encoding table (Apple standard)
+      cmapLen = getUShort(pos + 2);
+      for (i = 0; i < cmapLen && i < 256; ++i) {
+       cmap[i] = getByte(pos + 6 + i);
+      }
+      break;
+    case 4: // segment mapping to delta values (Microsoft standard)
+      if (cmapPlatform == 3 && cmapEncoding == 0) {
+       // Windows-symbol uses char codes 0xf000 - 0xf0ff
+       cmapOffset = 0xf000;
+      } else {
+       cmapOffset = 0;
+      }
+      segCnt = getUShort(pos + 6) / 2;
+      for (i = 0; i < segCnt; ++i) {
+       segEnd = getUShort(pos + 14 + 2*i);
+       segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
+       segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
+       segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
+       if (segStart - cmapOffset <= 0xff &&
+           segEnd - cmapOffset >= 0) {
+         for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
+              j <= segEnd && j - cmapOffset <= 0xff;
+              ++j) {
+           if (segOffset == 0) {
+             k = (j + segDelta) & 0xffff;
+           } else {
+             k = getUShort(pos + 16 + 6*segCnt + 2*i +
+                           segOffset + 2 * (j - segStart));
+             if (k != 0) {
+               k = (k + segDelta) & 0xffff;
+             }
+           }
+           cmap[j - cmapOffset] = k;
+         }
+       }
+      }
+      break;
+    default:
+      error(-1, "Unimplemented cmap type (%d) in TrueType font file",
+           cmapFmt);
+      break;
+    }
+  }
+
+  //----- construct the (glyph idx) -> (glyph name) mapping
+  //----- and compute the (char code) -> (glyph name) mapping
+
+  encoding = new FontEncoding();
+
+  if ((pos = seekTable("post")) >= 0) {
+    fmt = getULong(pos);
+
+    // Apple font
+    if (fmt == 0x00010000) {
+      for (i = 0; i < 256; ++i) {
+       j = (cmap[i] < 258) ? cmap[i] : 0;
+       encoding->addChar(i, copyString(macGlyphNames[j]));
+      }
+
+    // Microsoft font
+    } else if (fmt == 0x00020000) {
+      stringIdx = 0;
+      stringPos = pos + 34 + 2*nGlyphs;
+      for (i = 0; i < 256; ++i) {
+       if (cmap[i] < nGlyphs) {
+         j = getUShort(pos + 34 + 2 * cmap[i]);
+         if (j < 258) {
+           encoding->addChar(i, copyString(macGlyphNames[j]));
+         } else {
+           j -= 258;
+           if (j != stringIdx) {
+             for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
+                  stringIdx < j;
+                  ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
+           }
+           n = getByte(stringPos);
+           s = new GString(file + stringPos + 1, n);
+           encoding->addChar(i, copyString(s->getCString()));
+           delete s;
+           ++stringIdx;
+           stringPos += 1 + n;
+         }
+       } else {
+         encoding->addChar(i, copyString(macGlyphNames[0]));
+       }
+      }
+
+    // Apple subset
+    } else if (fmt == 0x000280000) {
+      for (i = 0; i < 256; ++i) {
+       if (cmap[i] < nGlyphs) {
+         j = i + getChar(pos + 32 + cmap[i]);
+       } else {
+         j = 0;
+       }
+       encoding->addChar(i, copyString(macGlyphNames[j]));
+      }
+
+    // Ugh, just assume the Apple glyph set
+    } else {
+      for (i = 0; i < 256; ++i) {
+       j = (cmap[i] < 258) ? cmap[i] : 0;
+       encoding->addChar(i, copyString(macGlyphNames[j]));
+      }
+    }
+
+  // no "post" table: assume the Apple glyph set
+  } else {
+    for (i = 0; i < 256; ++i) {
+      j = (cmap[i] < 258) ? cmap[i] : 0;
+      encoding->addChar(i, copyString(macGlyphNames[j]));
+    }
+  }
+
+  if (taken) {
+    freeEnc = gFalse;
+  }
+  return encoding;
+}
+
+void TrueTypeFontFile::convertToType42(char *name, FontEncoding *encodingA,
+                                      FILE *out) {
+  // write the header
+  fprintf(out, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
+
+  // begin the font dictionary
+  fprintf(out, "10 dict begin\n");
+  fprintf(out, "/FontName /%s def\n", name);
+  fprintf(out, "/FontType 42 def\n");
+  fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
+  fprintf(out, "/FontBBox [%d %d %d %d] def\n",
+         bbox[0], bbox[1], bbox[2], bbox[3]);
+  fprintf(out, "/PaintType 0 def\n");
+
+  // write the guts of the dictionary
+  cvtEncoding(encodingA, out);
+  cvtCharStrings(encodingA, out);
+  cvtSfnts(out);
+
+  // end the dictionary and define the font
+  fprintf(out, "FontName currentdict end definefont pop\n");
+}
+
+int TrueTypeFontFile::getByte(int pos) {
+  return file[pos] & 0xff;
+}
+
+int TrueTypeFontFile::getChar(int pos) {
+  int x;
+
+  x = file[pos] & 0xff;
+  if (x & 0x80)
+    x |= 0xffffff00;
+  return x;
+}
+
+int TrueTypeFontFile::getUShort(int pos) {
+  int x;
+
+  x = file[pos] & 0xff;
+  x = (x << 8) + (file[pos+1] & 0xff);
+  return x;
+}
+
+int TrueTypeFontFile::getShort(int pos) {
+  int x;
+
+  x = file[pos] & 0xff;
+  x = (x << 8) + (file[pos+1] & 0xff);
+  if (x & 0x8000)
+    x |= 0xffff0000;
+  return x;
+}
+
+Guint TrueTypeFontFile::getULong(int pos) {
+  int x;
+
+  x = file[pos] & 0xff;
+  x = (x << 8) + (file[pos+1] & 0xff);
+  x = (x << 8) + (file[pos+2] & 0xff);
+  x = (x << 8) + (file[pos+3] & 0xff);
+  return x;
+}
+
+double TrueTypeFontFile::getFixed(int pos) {
+  int x, y;
+
+  x = getShort(pos);
+  y = getUShort(pos+2);
+  return (double)x + (double)y / 65536;
+}
+
+int TrueTypeFontFile::seekTable(char *tag) {
+  int i;
+
+  for (i = 0; i < nTables; ++i) {
+    if (!strncmp(tableHdrs[i].tag, tag, 4))
+      return tableHdrs[i].offset;
+  }
+  return -1;
+}
+
+void TrueTypeFontFile::cvtEncoding(FontEncoding *encodingA, FILE *out) {
+  char *name;
+  int i;
+
+  fprintf(out, "/Encoding 256 array\n");
+  for (i = 0; i < 256; ++i) {
+    if (!(name = encodingA->getCharName(i))) {
+      name = ".notdef";
+    }
+    fprintf(out, "dup %d /%s put\n", i, name);
+  }
+  fprintf(out, "readonly def\n");
+}
+
+void TrueTypeFontFile::cvtCharStrings(FontEncoding *encodingA, FILE *out) {
+  int cmap[256];
+  int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapLen, cmapOffset;
+  int segCnt, segStart, segEnd, segDelta, segOffset;
+  char *name;
+  int pos, i, j, k;
+
+  //----- read the cmap: construct the (char code) -> (glyph idx) mapping
+
+  // map everything to the missing glyph
+  for (i = 0; i < 256; ++i) {
+    cmap[i] = 0;
+  }
+
+  // look for the 'cmap' table
+  if ((pos = seekTable("cmap")) >= 0) {
+    nCmaps = getUShort(pos+2);
+
+    // if the font has a Windows-symbol cmap, use it;
+    // otherwise, use the first cmap in the table
+    for (i = 0; i < nCmaps; ++i) {
+      cmapPlatform = getUShort(pos + 4 + 8*i);
+      cmapEncoding = getUShort(pos + 4 + 8*i + 2);
+      if (cmapPlatform == 3 && cmapEncoding == 0) {
+       break;
+      }
+    }
+    if (i >= nCmaps) {
+      i = 0;
+      cmapPlatform = getUShort(pos + 4);
+      cmapEncoding = getUShort(pos + 4 + 2);
+    }
+    pos += getULong(pos + 4 + 8*i + 4);
+
+    // read the cmap
+    cmapFmt = getUShort(pos);
+    switch (cmapFmt) {
+    case 0: // byte encoding table (Apple standard)
+      cmapLen = getUShort(pos + 2);
+      for (i = 0; i < cmapLen && i < 256; ++i) {
+       cmap[i] = getByte(pos + 6 + i);
+      }
+      break;
+    case 4: // segment mapping to delta values (Microsoft standard)
+      if (cmapPlatform == 3 && cmapEncoding == 0) {
+       // Windows-symbol uses char codes 0xf000 - 0xf0ff
+       cmapOffset = 0xf000;
+      } else {
+       cmapOffset = 0;
+      }
+      segCnt = getUShort(pos + 6) / 2;
+      for (i = 0; i < segCnt; ++i) {
+       segEnd = getUShort(pos + 14 + 2*i);
+       segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
+       segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
+       segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
+       if (segStart - cmapOffset <= 0xff &&
+           segEnd - cmapOffset >= 0) {
+         for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
+              j <= segEnd && j - cmapOffset <= 0xff;
+              ++j) {
+           if (segOffset == 0) {
+             k = (j + segDelta) & 0xffff;
+           } else {
+             k = getUShort(pos + 16 + 6*segCnt + 2*i +
+                           segOffset + 2 * (j - segStart));
+             if (k != 0) {
+               k = (k + segDelta) & 0xffff;
+             }
+           }
+           cmap[j - cmapOffset] = k;
+         }
+       }
+      }
+      break;
+    default:
+      error(-1, "Unimplemented cmap type (%d) in TrueType font file",
+           cmapFmt);
+      break;
+    }
+  }
+
+  //----- map char code to glyph index
+
+  // 1. use encoding to map name to char code
+  // 2. use cmap to map char code to glyph index
+
+  fprintf(out, "/CharStrings 256 dict dup begin\n");
+  fprintf(out, "/.notdef 0 def\n");
+
+  // kludge: this loop goes backward because the WinAnsi and MacRoman
+  // encodings define certain chars multiple times (space, hyphen,
+  // etc.), and we want the lowest-numbered definition to "stick"
+  // (because the higher-numbered defn(s) may not have valid cmap
+  // entries)
+  i = encodingA->getSize();
+  if (i > 255) {
+    i = 255;
+  }
+  for (; i >= 0; --i) {
+    name = encodingA->getCharName(i);
+    if (name && strcmp(name, ".notdef")) {
+      fprintf(out, "/%s %d def\n", name, cmap[i]);
+    }
+  }
+
+  fprintf(out, "end readonly def\n");
+}
+
+void TrueTypeFontFile::cvtSfnts(FILE *out) {
+  char tableDir[12 + 9*16];
+  int *list;
+  int nTablesOut, pos, destPos, i, j, k1, k2;
+
+  fprintf(out, "/sfnts [\n");
+
+  // count tables
+  nTablesOut = 0;
+  for (i = 0; i < 9; ++i) {
+    for (j = 0; j < nTables; ++j) {
+      if (!strncmp(t42ReqTables[i], tableHdrs[j].tag, 4)) {
+       ++nTablesOut;
+       break;
+      }
+    }
+  }
+
+  // header
+  tableDir[0] = 0x00;          // sfnt version
+  tableDir[1] = 0x01;
+  tableDir[2] = 0x00;
+  tableDir[3] = 0x00;
+  tableDir[4] = (nTablesOut >> 8) & 0xff;   // numTables
+  tableDir[5] = nTablesOut & 0xff;
+  tableDir[6] = 0;             // searchRange
+  tableDir[7] = (char)128;
+  tableDir[8] = 0;             // entrySelector
+  tableDir[9] = 3;
+  tableDir[10] = 0;            // rangeShift
+  tableDir[11] = 16;
+
+  // table directory
+  pos = 12;
+  destPos = 12 + 16 * nTablesOut;
+  for (i = 0; i < 9; ++i) {
+    for (j = 0; j < nTables; ++j) {
+      if (!strncmp(t42ReqTables[i], tableHdrs[j].tag, 4)) {
+       break;
+      }
+    }
+    if (j < nTables) {
+      memcpy(&tableDir[pos], t42ReqTables[i], 4);
+      tableDir[pos+4] = (tableHdrs[j].checksum >> 24) & 0xff;
+      tableDir[pos+5] = (tableHdrs[j].checksum >> 16) & 0xff;
+      tableDir[pos+6] = (tableHdrs[j].checksum >> 8) & 0xff;
+      tableDir[pos+7] = tableHdrs[j].checksum & 0xff;
+      tableDir[pos+8] = (destPos >> 24) & 0xff;
+      tableDir[pos+9] = (destPos >> 16) & 0xff;
+      tableDir[pos+10] = (destPos >> 8) & 0xff;
+      tableDir[pos+11] = destPos & 0xff;
+      tableDir[pos+12] = (tableHdrs[j].length >> 24) & 0xff;
+      tableDir[pos+13] = (tableHdrs[j].length >> 16) & 0xff;
+      tableDir[pos+14] = (tableHdrs[j].length >> 8) & 0xff;
+      tableDir[pos+15] = tableHdrs[j].length & 0xff;
+      pos += 16;
+      destPos += tableHdrs[j].length;
+      if (tableHdrs[j].length & 3) {
+       destPos += 4 - (tableHdrs[j].length & 3);
+      }
+    }
+  }
+
+  dumpString(tableDir, 12 + 16 * nTablesOut, out);
+
+  for (i = 0; i < 9; ++i) {
+    for (j = 0; j < nTables; ++j) {
+      if (!strncmp(t42ReqTables[i], tableHdrs[j].tag, 4)) {
+       break;
+      }
+    }
+    if (j < nTables) {
+      if (!strcmp(t42ReqTables[i], "glyf") && tableHdrs[j].length > 65532) {
+       // the 'glyf' table won't fit in a single string, and we're only
+       // allowed to break at glyph boundaries
+       list = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
+       pos = seekTable("loca");
+       for (k1 = 0; k1 <= nGlyphs; ++k1) {
+         if (locaFmt) {
+           list[k1] = getULong(pos + 4*k1);
+         } else {
+           list[k1] = 2 * getUShort(pos + 2*k1);
+         }
+       }
+       k1 = 0;
+       while (k1 < nGlyphs) {
+         for (k2 = k1 + 1;
+              k2 < nGlyphs && list[k2+1] - list[k1] <= 65532;
+              ++k2) ;
+         // ghostscript is unhappy if we break at anything other
+         // than a multiple of four bytes
+         while (((list[k2] - list[k1]) & 3) && k2 > k1 + 1) {
+           --k2;
+         }
+         dumpString(file + tableHdrs[j].offset + list[k1],
+                    list[k2] - list[k1], out);
+         k1 = k2;
+       }
+       gfree(list);
+      } else {
+       dumpString(file + tableHdrs[j].offset, tableHdrs[j].length, out);
+      }
+    }
+  }
+
+  fprintf(out, "] def\n");
+}
+
+void TrueTypeFontFile::dumpString(char *s, int n, FILE *out) {
+  int i, j;
+
+  fprintf(out, "<");
+  for (i = 0; i < n; i += 32) {
+    for (j = 0; j < 32 && i+j < n; ++j) {
+      fprintf(out, "%02X", s[i+j] & 0xff);
+    }
+    if (i+32 < n) {
+      fprintf(out, "\n");
+    }
+  }
+  if (n & 3) {
+    for (i = 0; i < 4 - (n & 3); ++i) {
+      fprintf(out, "00");
+    }
+  }
+  // append an extra mystery zero byte because the Type 42 spec says so
+  fprintf(out, "00>\n");
+}
index 59382a962a47087dd86a66911b13e295abe0a688..b64d827ebc0772ce1e9417302be13c65cd83302b 100644 (file)
@@ -30,7 +30,7 @@ public:
 
   // Returns the font name, as specified internally by the font file.
   // Returns NULL if no name is available.
-  virtual const char *getName() = 0;
+  virtual char *getName() = 0;
 
   // Returns the custom font encoding, or NULL if the encoding is
   // not available.  If <taken> is set, the caller of this function
@@ -45,14 +45,14 @@ public:
 class Type1FontFile: public FontFile {
 public:
 
-  Type1FontFile(const char *file, int len);
+  Type1FontFile(char *file, int len);
   virtual ~Type1FontFile();
-  virtual const char *getName() { return name; }
+  virtual char *getName() { return name; }
   virtual FontEncoding *getEncoding(GBool taken);
 
 private:
 
-  const char *name;
+  char *name;
   FontEncoding *encoding;
   GBool freeEnc;
 };
@@ -64,14 +64,14 @@ private:
 class Type1CFontFile: public FontFile {
 public:
 
-  Type1CFontFile(const char *file, int len);
+  Type1CFontFile(char *file, int len);
   virtual ~Type1CFontFile();
-  virtual const char *getName() { return name; }
+  virtual char *getName() { return name; }
   virtual FontEncoding *getEncoding(GBool taken);
 
 private:
 
-  const char *name;
+  char *name;
   FontEncoding *encoding;
   GBool freeEnc;
 };
@@ -83,23 +83,23 @@ private:
 class Type1CFontConverter {
 public:
 
-  Type1CFontConverter(const char *file, int len, FILE *out);
+  Type1CFontConverter(char *fileA, int lenA, FILE *outA);
   ~Type1CFontConverter();
   void convert();
 
 private:
 
-  void eexecWrite(const char *s);
-  void cvtGlyph(const char *name, Guchar *s, int n);
+  void eexecWrite(char *s);
+  void cvtGlyph(char *name, Guchar *s, int n);
   void cvtGlyphWidth(GBool useOp);
-  void eexecDumpNum(double x, GBool fp);
-  void eexecDumpOp1(int op);
-  void eexecDumpOp2(int op);
+  void eexecDumpNum(double x, GBool fpA);
+  void eexecDumpOp1(int opA);
+  void eexecDumpOp2(int opA);
   void eexecWriteCharstring(Guchar *s, int n);
-  void getDeltaInt(char *buf, const char *name, double *op, int n);
-  void getDeltaReal(char *buf, const char *name, double *op, int n);
+  void getDeltaInt(char *buf, char *name, double *opA, int n);
+  void getDeltaReal(char *buf, char *name, double *opA, int n);
 
-  const char *file;
+  char *file;
   int len;
   FILE *out;
   double op[48];               // operands
@@ -114,4 +114,57 @@ private:
   int line;                    // number of eexec chars on current line
 };
 
+//------------------------------------------------------------------------
+// TrueTypeFontFile
+//------------------------------------------------------------------------
+
+struct TTFontTableHdr;
+
+class TrueTypeFontFile: public FontFile {
+public:
+
+  TrueTypeFontFile(char *fileA, int lenA);
+  ~TrueTypeFontFile();
+
+  // This always returns NULL, since it's probably better to trust the
+  // font name in the PDF file rather than the one in the TrueType
+  // font file.
+  virtual char *getName();
+
+  virtual FontEncoding *getEncoding(GBool taken);
+
+  // Convert to a Type 42 font, suitable for embedding in a PostScript
+  // file.  The name will be used as the PostScript font name (so we
+  // don't need to depend on the 'name' table in the font).  The
+  // encoding is needed because the PDF Font object can modify the
+  // encoding.
+  void convertToType42(char *name, FontEncoding *encodingA, FILE *out);
+
+private:
+
+  char *file;
+  int len;
+
+  FontEncoding *encoding;
+  GBool freeEnc;
+
+  TTFontTableHdr *tableHdrs;
+  int nTables;
+  int bbox[4];
+  int locaFmt;
+  int nGlyphs;
+
+  int getByte(int pos);
+  int getChar(int pos);
+  int getUShort(int pos);
+  int getShort(int pos);
+  Guint getULong(int pos);
+  double getFixed(int pos);
+  int seekTable(char *tag);
+  void cvtEncoding(FontEncoding *encodingA, FILE *out);
+  void cvtCharStrings(FontEncoding *encodingA, FILE *out);
+  void cvtSfnts(FILE *out);
+  void dumpString(char *s, int n, FILE *out);
+};
+
 #endif
index 9b20f0faa33cf14ed7e5c9cc66fad1b12bac9c9f..a5b4cced334e304230bd40f215f660b8cd88afb8 100644 (file)
@@ -16,7 +16,7 @@
 //------------------------------------------------------------------------
 
 #define standardEncodingSize 335
-static const char *standardEncodingNames[standardEncodingSize] = {
+static char *standardEncodingNames[standardEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -357,7 +357,7 @@ static FontEncoding standardEncoding(standardEncodingNames,
                                      standardEncodingSize);
 
 #define symbolEncodingSize 257
-static const char *symbolEncodingNames[symbolEncodingSize] = {
+static char *symbolEncodingNames[symbolEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -620,7 +620,7 @@ static FontEncoding symbolEncoding(symbolEncodingNames,
                                    symbolEncodingSize);
 
 #define zapfDingbatsEncodingSize 270
-static const char *zapfDingbatsEncodingNames[zapfDingbatsEncodingSize] = {
+static char *zapfDingbatsEncodingNames[zapfDingbatsEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -896,7 +896,7 @@ static FontEncoding zapfDingbatsEncoding(zapfDingbatsEncodingNames,
                                          zapfDingbatsEncodingSize);
 
 #define macRomanEncodingSize 256
-static const char *macRomanEncodingNames[macRomanEncodingSize] = {
+static char *macRomanEncodingNames[macRomanEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -1158,7 +1158,7 @@ static FontEncoding macRomanEncoding(macRomanEncodingNames,
                                      macRomanEncodingSize);
 
 #define winAnsiEncodingSize 256
-static const char *winAnsiEncodingNames[winAnsiEncodingSize] = {
+static char *winAnsiEncodingNames[winAnsiEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -1287,7 +1287,7 @@ static const char *winAnsiEncodingNames[winAnsiEncodingSize] = {
   "braceright",
   "asciitilde",
   "bullet",
-  "bullet",
+  "Euro",
   "bullet",
   "quotesinglbase",
   "florin",
@@ -2041,28 +2041,30 @@ static Gushort zapfDingbatsWidths[270] = {
 //------------------------------------------------------------------------
 
 struct BuiltinFont {
-  const char *name;
+  char *name;
   Gushort *widths;
   FontEncoding *encoding;
+  short ascent;
+  short descent;
 };
 
 #define numBuiltinFonts ((int)(sizeof(builtinFonts)/sizeof(BuiltinFont)))
 
 static BuiltinFont builtinFonts[] = {
-  {"Courier",               courierWidths,              &standardEncoding},
-  {"Courier-Bold",          courierBoldWidths,          &standardEncoding},
-  {"Courier-BoldOblique",   courierBoldObliqueWidths,   &standardEncoding},
-  {"Courier-Oblique",       courierObliqueWidths,       &standardEncoding},
-  {"Helvetica",             helveticaWidths,            &standardEncoding},
-  {"Helvetica-Bold",        helveticaBoldWidths,        &standardEncoding},
-  {"Helvetica-BoldOblique", helveticaBoldObliqueWidths, &standardEncoding},
-  {"Helvetica-Oblique",     helveticaObliqueWidths,     &standardEncoding},
-  {"Symbol",                symbolWidths,               &symbolEncoding},
-  {"Times-Bold",            timesBoldWidths,            &standardEncoding},
-  {"Times-BoldItalic",      timesBoldItalicWidths,      &standardEncoding},
-  {"Times-Italic",          timesItalicWidths,          &standardEncoding},
-  {"Times-Roman",           timesRomanWidths,           &standardEncoding},
-  {"ZapfDingbats",          zapfDingbatsWidths,         &zapfDingbatsEncoding}
+  {"Courier",               courierWidths,              &standardEncoding,       624,  -207},
+  {"Courier-Bold",          courierBoldWidths,          &standardEncoding,       674,  -257},
+  {"Courier-BoldOblique",   courierBoldObliqueWidths,   &standardEncoding,       674,  -257},
+  {"Courier-Oblique",       courierObliqueWidths,       &standardEncoding,       624,  -207},
+  {"Helvetica",             helveticaWidths,            &standardEncoding,       729,  -219},
+  {"Helvetica-Bold",        helveticaBoldWidths,        &standardEncoding,       729,  -219},
+  {"Helvetica-BoldOblique", helveticaBoldObliqueWidths, &standardEncoding,       729,  -219},
+  {"Helvetica-Oblique",     helveticaObliqueWidths,     &standardEncoding,       729,  -219},
+  {"Symbol",                symbolWidths,               &symbolEncoding,        1010,  -293},
+  {"Times-Bold",            timesBoldWidths,            &standardEncoding,       670,  -210},
+  {"Times-BoldItalic",      timesBoldItalicWidths,      &standardEncoding,       682,  -203},
+  {"Times-Italic",          timesItalicWidths,          &standardEncoding,       684,  -206},
+  {"Times-Roman",           timesRomanWidths,           &standardEncoding,       682,  -217},
+  {"ZapfDingbats",          zapfDingbatsWidths,         &zapfDingbatsEncoding,   820,  -143}
 };
 
 #endif
index 76428d05e6da8e325c1cea32124d0215cae76df0..a9f8c06937736c0fd9596c6c273f83627ca66d5a 100644 (file)
 // FormWidget
 //------------------------------------------------------------------------
 
-FormWidget::FormWidget(Dict *dict) {
+FormWidget::FormWidget(XRef *xrefA, Dict *dict) {
   Object obj1, obj2;
   double t;
 
   ok = gFalse;
+  xref = xrefA;
 
   if (dict->lookup("AP", &obj1)->isDict()) {
     obj1.dictLookupNF("N", &obj2);
@@ -74,7 +75,7 @@ FormWidget::~FormWidget() {
 void FormWidget::draw(Gfx *gfx) {
   Object obj;
 
-  if (appearance.fetch(&obj)->isStream()) {
+  if (appearance.fetch(xref, &obj)->isStream()) {
     gfx->doWidgetForm(&obj, xMin, yMin, xMax, yMax);
   }
   obj.free();
@@ -84,7 +85,7 @@ void FormWidget::draw(Gfx *gfx) {
 // FormWidgets
 //------------------------------------------------------------------------
 
-FormWidgets::FormWidgets(Object *annots) {
+FormWidgets::FormWidgets(XRef *xref, Object *annots) {
   FormWidget *widget;
   Object obj1, obj2;
   int size;
@@ -100,7 +101,7 @@ FormWidgets::FormWidgets(Object *annots) {
        obj1.dictLookup("Subtype", &obj2);
        if (obj2.isName("Widget") ||
            obj2.isName("Stamp")) {
-         widget = new FormWidget(obj1.getDict());
+         widget = new FormWidget(xref, obj1.getDict());
          if (widget->isOk()) {
            if (nWidgets >= size) {
              size += 16;
index d746083bf40e0e00e4e189be62d556ada3868937..c14421e81fa0416ecd9eca1d51a0ae881ed1726e 100644 (file)
@@ -13,6 +13,7 @@
 #pragma interface
 #endif
 
+class XRef;
 class Gfx;
 
 //------------------------------------------------------------------------
@@ -22,17 +23,18 @@ class Gfx;
 class FormWidget {
 public:
 
-  FormWidget(Dict *dict);
+  FormWidget(XRef *xrefA, Dict *dict);
   ~FormWidget();
   GBool isOk() { return ok; }
 
   void draw(Gfx *gfx);
 
   // Get appearance object.
-  Object *getAppearance(Object *obj) { return appearance.fetch(obj); }
+  Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
 
 private:
 
+  XRef *xref;                  // the xref table for this PDF file
   Object appearance;           // a reference to the Form XObject stream
                                //   for the normal appearance
   double xMin, yMin,           // widget rectangle
@@ -48,7 +50,7 @@ class FormWidgets {
 public:
 
   // Extract widgets from array of annotations.
-  FormWidgets(Object *annots);
+  FormWidgets(XRef *xref, Object *annots);
 
   ~FormWidgets();
 
index fb323930da9fad9acdad864f98e14b42302fd3eb..a55efde82d05dc6fbf64f4f72ae927717e125ff0 100644 (file)
 #include "GfxState.h"
 #include "OutputDev.h"
 #include "Params.h"
+#include "Page.h"
 #include "Error.h"
 #include "Gfx.h"
 
+//------------------------------------------------------------------------
+// constants
+//------------------------------------------------------------------------
+
+// Max number of splits along the t axis for an axial shading fill.
+#define axialMaxSplits 256
+
+// Max delta allowed in any color component for an axial shading fill.
+#define axialColorDelta (1 / 256.0)
+
 //------------------------------------------------------------------------
 // Operator table
 //------------------------------------------------------------------------
@@ -189,15 +200,11 @@ Operator Gfx::opTab[] = {
 
 #define numOps (sizeof(opTab) / sizeof(Operator))
 
-//------------------------------------------------------------------------
-
-GBool printCommands = gFalse;
-
 //------------------------------------------------------------------------
 // GfxResources
 //------------------------------------------------------------------------
 
-GfxResources::GfxResources(Dict *resDict, GfxResources *next) {
+GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
   Object obj1;
 
   if (resDict) {
@@ -206,7 +213,7 @@ GfxResources::GfxResources(Dict *resDict, GfxResources *next) {
     fonts = NULL;
     resDict->lookup("Font", &obj1);
     if (obj1.isDict()) {
-      fonts = new GfxFontDict(obj1.getDict());
+      fonts = new GfxFontDict(xref, obj1.getDict());
     }
     obj1.free();
 
@@ -219,6 +226,9 @@ GfxResources::GfxResources(Dict *resDict, GfxResources *next) {
     // get pattern dictionary
     resDict->lookup("Pattern", &patternDict);
 
+    // get shading dictionary
+    resDict->lookup("Shading", &shadingDict);
+
     // get graphics state parameter dictionary
     resDict->lookup("ExtGState", &gStateDict);
 
@@ -230,7 +240,7 @@ GfxResources::GfxResources(Dict *resDict, GfxResources *next) {
     gStateDict.initNull();
   }
 
-  this->next = next;
+  next = nextA;
 }
 
 GfxResources::~GfxResources() {
@@ -240,10 +250,11 @@ GfxResources::~GfxResources() {
   xObjDict.free();
   colorSpaceDict.free();
   patternDict.free();
+  shadingDict.free();
   gStateDict.free();
 }
 
-GfxFont *GfxResources::lookupFont(const char *name) {
+GfxFont *GfxResources::lookupFont(char *name) {
   GfxFont *font;
   GfxResources *resPtr;
 
@@ -257,7 +268,7 @@ GfxFont *GfxResources::lookupFont(const char *name) {
   return NULL;
 }
 
-GBool GfxResources::lookupXObject(const char *name, Object *obj) {
+GBool GfxResources::lookupXObject(char *name, Object *obj) {
   GfxResources *resPtr;
 
   for (resPtr = this; resPtr; resPtr = resPtr->next) {
@@ -271,7 +282,7 @@ GBool GfxResources::lookupXObject(const char *name, Object *obj) {
   return gFalse;
 }
 
-GBool GfxResources::lookupXObjectNF(const char *name, Object *obj) {
+GBool GfxResources::lookupXObjectNF(char *name, Object *obj) {
   GfxResources *resPtr;
 
   for (resPtr = this; resPtr; resPtr = resPtr->next) {
@@ -285,7 +296,7 @@ GBool GfxResources::lookupXObjectNF(const char *name, Object *obj) {
   return gFalse;
 }
 
-void GfxResources::lookupColorSpace(const char *name, Object *obj) {
+void GfxResources::lookupColorSpace(char *name, Object *obj) {
   GfxResources *resPtr;
 
   for (resPtr = this; resPtr; resPtr = resPtr->next) {
@@ -299,7 +310,7 @@ void GfxResources::lookupColorSpace(const char *name, Object *obj) {
   obj->initNull();
 }
 
-GfxPattern *GfxResources::lookupPattern(const char *name) {
+GfxPattern *GfxResources::lookupPattern(char *name) {
   GfxResources *resPtr;
   GfxPattern *pattern;
   Object obj;
@@ -318,7 +329,26 @@ GfxPattern *GfxResources::lookupPattern(const char *name) {
   return NULL;
 }
 
-GBool GfxResources::lookupGState(const char *name, Object *obj) {
+GfxShading *GfxResources::lookupShading(char *name) {
+  GfxResources *resPtr;
+  GfxShading *shading;
+  Object obj;
+
+  for (resPtr = this; resPtr; resPtr = resPtr->next) {
+    if (resPtr->shadingDict.isDict()) {
+      if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) {
+       shading = GfxShading::parse(&obj);
+       obj.free();
+       return shading;
+      }
+      obj.free();
+    }
+  }
+  error(-1, "Unknown shading '%s'", name);
+  return NULL;
+}
+
+GBool GfxResources::lookupGState(char *name, Object *obj) {
   GfxResources *resPtr;
 
   for (resPtr = this; resPtr; resPtr = resPtr->next) {
@@ -337,18 +367,20 @@ GBool GfxResources::lookupGState(const char *name, Object *obj) {
 // Gfx
 //------------------------------------------------------------------------
 
-Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict,
-        double dpi, double x1, double y1, double x2, double y2, GBool crop,
-        double cropX1, double cropY1, double cropX2, double cropY2,
-        int rotate) {
+Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, double dpi,
+        PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
+        GBool printCommandsA) {
   int i;
 
+  xref = xrefA;
+  printCommands = printCommandsA;
+
   // start the resource stack
-  res = new GfxResources(resDict, NULL);
+  res = new GfxResources(xref, resDict, NULL);
 
   // initialize
-  out = out1;
-  state = new GfxState(dpi, x1, y1, x2, y2, rotate, out->upsideDown());
+  out = outA;
+  state = new GfxState(dpi, box, rotate, out->upsideDown());
   fontChanged = gFalse;
   clip = clipNone;
   ignoreUndef = 0;
@@ -361,11 +393,12 @@ Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict,
 
   // set crop box
   if (crop) {
-    state->moveTo(cropX1, cropY1);
-    state->lineTo(cropX2, cropY1);
-    state->lineTo(cropX2, cropY2);
-    state->lineTo(cropX1, cropY2);
+    state->moveTo(cropBox->x1, cropBox->y1);
+    state->lineTo(cropBox->x2, cropBox->y1);
+    state->lineTo(cropBox->x2, cropBox->y2);
+    state->lineTo(cropBox->x1, cropBox->y2);
     state->closePath();
+    state->clip();
     out->clip(state);
     state->clearPath();
   }
@@ -406,7 +439,7 @@ void Gfx::display(Object *obj, GBool topLevel) {
     error(-1, "Weird page contents");
     return;
   }
-  parser = new Parser(new Lexer(obj));
+  parser = new Parser(xref, new Lexer(xref, obj));
   go(topLevel);
   delete parser;
   parser = NULL;
@@ -433,6 +466,7 @@ void Gfx::go(GBool topLevel) {
          args[i].print(stdout);
        }
        printf("\n");
+       fflush(stdout);
       }
       execOp(&obj, args, numArgs);
       obj.free();
@@ -457,6 +491,7 @@ void Gfx::go(GBool topLevel) {
        printf("throwing away arg: ");
        obj.print(stdout);
        printf("\n");
+       fflush(stdout);
       }
       obj.free();
     }
@@ -476,6 +511,7 @@ void Gfx::go(GBool topLevel) {
        args[i].print(stdout);
       }
       printf("\n");
+      fflush(stdout);
     }
     for (i = 0; i < numArgs; ++i)
       args[i].free();
@@ -485,16 +521,11 @@ void Gfx::go(GBool topLevel) {
   if (topLevel && numCmds > 0) {
     out->dump();
   }
-
-  // clean up
-  if (printCommands) {
-    fflush(stdout);
-  }
 }
 
 void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
   Operator *op;
-  const char *name;
+  char *name;
   int i;
 
   // find operator
@@ -531,7 +562,7 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
   (this->*op->func)(args, numArgs);
 }
 
-Operator *Gfx::findOp(const char *name) {
+Operator *Gfx::findOp(char *name) {
   int a, b, m, cmp;
 
   a = -1;
@@ -576,17 +607,11 @@ int Gfx::getPos() {
 //------------------------------------------------------------------------
 
 void Gfx::opSave(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   out->saveState(state);
   state = state->save();
 }
 
 void Gfx::opRestore(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   state = state->restore();
   out->restoreState(state);
 
@@ -598,8 +623,6 @@ void Gfx::opRestore(Object args[], int numArgs) {
 }
 
 void Gfx::opConcat(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->concatCTM(args[0].getNum(), args[1].getNum(),
                   args[2].getNum(), args[3].getNum(),
                   args[4].getNum(), args[5].getNum());
@@ -616,8 +639,6 @@ void Gfx::opSetDash(Object args[], int numArgs) {
   double *dash;
   int i;
 
-  (void)numArgs;
-
   a = args[0].getArray();
   length = a->getLength();
   if (length == 0) {
@@ -778,7 +799,7 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
   if (colorSpace) {
     state->setFillColorSpace(colorSpace);
   } else {
-    error(getPos(), "Bad color space");
+    error(getPos(), "Bad color space (fill)");
   }
   for (i = 0; i < gfxColorMaxComps; ++i) {
     color.c[i] = 0;
@@ -804,7 +825,7 @@ void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
   if (colorSpace) {
     state->setStrokeColorSpace(colorSpace);
   } else {
-    error(getPos(), "Bad color space");
+    error(getPos(), "Bad color space (stroke)");
   }
   for (i = 0; i < gfxColorMaxComps; ++i) {
     color.c[i] = 0;
@@ -906,14 +927,10 @@ void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opMoveTo(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->moveTo(args[0].getNum(), args[1].getNum());
 }
 
 void Gfx::opLineTo(Object args[], int numArgs) {
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     error(getPos(), "No current point in lineto");
     return;
@@ -924,8 +941,6 @@ void Gfx::opLineTo(Object args[], int numArgs) {
 void Gfx::opCurveTo(Object args[], int numArgs) {
   double x1, y1, x2, y2, x3, y3;
 
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     error(getPos(), "No current point in curveto");
     return;
@@ -942,8 +957,6 @@ void Gfx::opCurveTo(Object args[], int numArgs) {
 void Gfx::opCurveTo1(Object args[], int numArgs) {
   double x1, y1, x2, y2, x3, y3;
 
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     error(getPos(), "No current point in curveto1");
     return;
@@ -960,8 +973,6 @@ void Gfx::opCurveTo1(Object args[], int numArgs) {
 void Gfx::opCurveTo2(Object args[], int numArgs) {
   double x1, y1, x2, y2, x3, y3;
 
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     error(getPos(), "No current point in curveto2");
     return;
@@ -978,8 +989,6 @@ void Gfx::opCurveTo2(Object args[], int numArgs) {
 void Gfx::opRectangle(Object args[], int numArgs) {
   double x, y, w, h;
 
-  (void)numArgs;
-
   x = args[0].getNum();
   y = args[1].getNum();
   w = args[2].getNum();
@@ -992,9 +1001,6 @@ void Gfx::opRectangle(Object args[], int numArgs) {
 }
 
 void Gfx::opClosePath(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isPath()) {
     error(getPos(), "No current point in closepath");
     return;
@@ -1007,16 +1013,10 @@ void Gfx::opClosePath(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opEndPath(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   doEndPath();
 }
 
 void Gfx::opStroke(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in stroke");
     return;
@@ -1027,9 +1027,6 @@ void Gfx::opStroke(Object args[], int numArgs) {
 }
 
 void Gfx::opCloseStroke(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in closepath/stroke");
     return;
@@ -1042,9 +1039,6 @@ void Gfx::opCloseStroke(Object args[], int numArgs) {
 }
 
 void Gfx::opFill(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in fill");
     return;
@@ -1060,9 +1054,6 @@ void Gfx::opFill(Object args[], int numArgs) {
 }
 
 void Gfx::opEOFill(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in eofill");
     return;
@@ -1078,9 +1069,6 @@ void Gfx::opEOFill(Object args[], int numArgs) {
 }
 
 void Gfx::opFillStroke(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in fill/stroke");
     return;
@@ -1097,9 +1085,6 @@ void Gfx::opFillStroke(Object args[], int numArgs) {
 }
 
 void Gfx::opCloseFillStroke(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in closepath/fill/stroke");
     return;
@@ -1117,9 +1102,6 @@ void Gfx::opCloseFillStroke(Object args[], int numArgs) {
 }
 
 void Gfx::opEOFillStroke(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in eofill/stroke");
     return;
@@ -1136,9 +1118,6 @@ void Gfx::opEOFillStroke(Object args[], int numArgs) {
 }
 
 void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (!state->isCurPt()) {
     //error(getPos(), "No path in closepath/eofill/stroke");
     return;
@@ -1155,25 +1134,19 @@ void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
   doEndPath();
 }
 
-void Gfx::opShFill(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-}
-
 void Gfx::doPatternFill(GBool eoFill) {
   GfxPatternColorSpace *patCS;
   GfxPattern *pattern;
   GfxTilingPattern *tPat;
   GfxColorSpace *cs;
-  GfxPath *path;
-  GfxSubpath *subpath;
   double xMin, yMin, xMax, yMax, x, y, x1, y1;
+  double cxMin, cyMin, cxMax, cyMax;
   int xi0, yi0, xi1, yi1, xi, yi;
   double *ctm, *btm, *ptm;
-  double m[6], ictm[6], m1[6], im[6];
+  double m[6], ictm[6], m1[6], im[6], imb[6];
   double det;
   double xstep, ystep;
-  int i, j;
+  int i;
 
   // get color space
   patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
@@ -1223,33 +1196,14 @@ void Gfx::doPatternFill(GBool eoFill) {
   im[4] = (m[2] * m[5] - m[3] * m[4]) * det;
   im[5] = (m[1] * m[4] - m[0] * m[5]) * det;
 
-  // compute bounding box of current path, in pattern space
-  xMin = xMax = yMin = yMax = 0; // make gcc happy
-  path = state->getPath();
-  for (i = 0; i < path->getNumSubpaths(); ++i) {
-    subpath = path->getSubpath(i);
-    for (j = 0; j < subpath->getNumPoints(); ++j) {
-      x = subpath->getX(j);
-      y = subpath->getY(j);
-      x1 = x * im[0] + y * im[2] + im[4];
-      y1 = x * im[1] + y * im[3] + im[5];
-      if (i == 0 && j == 0) {
-       xMin = xMax = x1;
-       yMin = yMax = y1;
-      } else {
-       if (x1 < xMin) {
-         xMin = x1;
-       } else if (x1 > xMax) {
-         xMax = x1;
-       }
-       if (y1 < yMin) {
-         yMin = y1;
-       } else if (y1 > yMax) {
-         yMax = y1;
-       }
-      }
-    }
-  }
+  // construct a (base space) -> (pattern space) transform matrix
+  det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]);
+  imb[0] = m1[3] * det;
+  imb[1] = -m1[1] * det;
+  imb[2] = -m1[2] * det;
+  imb[3] = m1[0] * det;
+  imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det;
+  imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
 
   // save current graphics state
   out->saveState(state);
@@ -1265,6 +1219,7 @@ void Gfx::doPatternFill(GBool eoFill) {
   out->updateFillColor(state);
 
   // clip to current path
+  state->clip();
   if (eoFill) {
     out->eoClip(state);
   } else {
@@ -1272,6 +1227,47 @@ void Gfx::doPatternFill(GBool eoFill) {
   }
   state->clearPath();
 
+  // transform clip region bbox to pattern space
+  state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
+  xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4];
+  yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5];
+  x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4];
+  y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5];
+  if (x1 < xMin) {
+    xMin = x1;
+  } else if (x1 > xMax) {
+    xMax = x1;
+  }
+  if (y1 < yMin) {
+    yMin = y1;
+  } else if (y1 > yMax) {
+    yMax = y1;
+  }
+  x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4];
+  y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5];
+  if (x1 < xMin) {
+    xMin = x1;
+  } else if (x1 > xMax) {
+    xMax = x1;
+  }
+  if (y1 < yMin) {
+    yMin = y1;
+  } else if (y1 > yMax) {
+    yMax = y1;
+  }
+  x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4];
+  y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5];
+  if (x1 < xMin) {
+    xMin = x1;
+  } else if (x1 > xMax) {
+    xMax = x1;
+  }
+  if (y1 < yMin) {
+    yMin = y1;
+  } else if (y1 > yMax) {
+    yMax = y1;
+  }
+
   // draw the pattern
   //~ this should treat negative steps differently -- start at right/top
   //~ edge instead of left/bottom (?)
@@ -1300,12 +1296,335 @@ void Gfx::doPatternFill(GBool eoFill) {
   out->restoreState(state);
 }
 
+void Gfx::opShFill(Object args[], int numArgs) {
+  GfxShading *shading;
+  double xMin, yMin, xMax, yMax;
+
+  if (!(shading = res->lookupShading(args[0].getName()))) {
+    return;
+  }
+
+  // save current graphics state
+  out->saveState(state);
+  state = state->save();
+
+  // clip to bbox
+  if (shading->getHasBBox()) {
+    shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+    state->moveTo(xMin, yMin);
+    state->lineTo(xMax, yMin);
+    state->lineTo(xMax, yMax);
+    state->lineTo(xMin, yMax);
+    state->closePath();
+    state->clip();
+    out->clip(state);
+    state->clearPath();
+  }
+
+  // set the color space
+  state->setFillColorSpace(shading->getColorSpace()->copy());
+
+  // do shading type-specific operations
+  switch (shading->getType()) {
+  case 2:
+    doAxialShFill((GfxAxialShading *)shading);
+    break;
+  }
+
+  // restore graphics state
+  state = state->restore();
+  out->restoreState(state);
+
+  delete shading;
+}
+
+void Gfx::doAxialShFill(GfxAxialShading *shading) {
+  double xMin, yMin, xMax, yMax;
+  double x0, y0, x1, y1;
+  double det;
+  double *ctm;
+  double ictm[6];
+  double dx, dy, mul;
+  double tMin, tMax, t, tx, ty;
+  double s[4], sMin, sMax, tmp;
+  double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
+  double t0, t1, tt;
+  double ta[axialMaxSplits + 1];
+  int next[axialMaxSplits + 1];
+  GfxColor color0, color1;
+  int nComps;
+  int i, j, k, kk;
+
+  // get clip region bbox and transform to current user space
+  state->getClipBBox(&x0, &y0, &x1, &y1);
+  ctm = state->getCTM();
+  det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+  ictm[0] = ctm[3] * det;
+  ictm[1] = -ctm[1] * det;
+  ictm[2] = -ctm[2] * det;
+  ictm[3] = ctm[0] * det;
+  ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+  ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+  xMin = xMax = x0 * ictm[0] + y0 * ictm[2] + ictm[4];
+  yMin = yMax = x0 * ictm[1] + y0 * ictm[3] + ictm[5];
+  tx = x0 * ictm[0] + y1 * ictm[2] + ictm[4];
+  ty = x0 * ictm[1] + y1 * ictm[3] + ictm[5];
+  if (tx < xMin) {
+    xMin = tx;
+  } else if (tx > xMax) {
+    xMax = tx;
+  }
+  if (ty < yMin) {
+    yMin = ty;
+  } else if (ty > yMax) {
+    yMax = ty;
+  }
+  tx = x1 * ictm[0] + y0 * ictm[2] + ictm[4];
+  ty = x1 * ictm[1] + y0 * ictm[3] + ictm[5];
+  if (tx < xMin) {
+    xMin = tx;
+  } else if (tx > xMax) {
+    xMax = tx;
+  }
+  if (ty < yMin) {
+    yMin = ty;
+  } else if (ty > yMax) {
+    yMax = ty;
+  }
+  tx = x1 * ictm[0] + y1 * ictm[2] + ictm[4];
+  ty = x1 * ictm[1] + y1 * ictm[3] + ictm[5];
+  if (tx < xMin) {
+    xMin = tx;
+  } else if (tx > xMax) {
+    xMax = tx;
+  }
+  if (ty < yMin) {
+    yMin = ty;
+  } else if (ty > yMax) {
+    yMax = ty;
+  }
+
+  // compute min and max t values, based on the four corners of the
+  // clip region bbox
+  shading->getCoords(&x0, &y0, &x1, &y1);
+  dx = x1 - x0;
+  dy = y1 - y0;
+  mul = 1 / (dx * dx + dy * dy);
+  tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
+  t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
+  if (t < tMin) {
+    tMin = t;
+  } else if (t > tMax) {
+    tMax = t;
+  }
+  t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
+  if (t < tMin) {
+    tMin = t;
+  } else if (t > tMax) {
+    tMax = t;
+  }
+  t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
+  if (t < tMin) {
+    tMin = t;
+  } else if (t > tMax) {
+    tMax = t;
+  }
+  if (tMin < 0 && !shading->getExtend0()) {
+    tMin = 0;
+  }
+  if (tMax > 1 && !shading->getExtend1()) {
+    tMax = 1;
+  }
+
+  // get the function domain
+  t0 = shading->getDomain0();
+  t1 = shading->getDomain1();
+
+  // Traverse the t axis and do the shading.
+  //
+  // For each point (tx, ty) on the t axis, consider a line through
+  // that point perpendicular to the t axis:
+  //
+  //     x(s) = tx + s * -dy   -->   s = (x - tx) / -dy
+  //     y(s) = ty + s * dx    -->   s = (y - ty) / dx
+  //
+  // Then look at the intersection of this line with the bounding box
+  // (xMin, yMin, xMax, yMax).  In the general case, there are four
+  // intersection points:
+  //
+  //     s0 = (xMin - tx) / -dy
+  //     s1 = (xMax - tx) / -dy
+  //     s2 = (yMin - ty) / dx
+  //     s3 = (yMax - ty) / dx
+  //
+  // and we want the middle two s values.
+  //
+  // In the case where dx = 0, take s0 and s1; in the case where dy =
+  // 0, take s2 and s3.
+  //
+  // Each filled polygon is bounded by two of these line segments
+  // perpdendicular to the t axis.
+  //
+  // The t axis is bisected into smaller regions until the color
+  // difference across a region is small enough, and then the region
+  // is painted with a single color.
+
+  // set up
+  nComps = shading->getColorSpace()->getNComps();
+  ta[0] = tMin;
+  ta[axialMaxSplits] = tMax;
+  next[0] = axialMaxSplits;
+
+  // compute the color at t = tMin
+  if (tMin < 0) {
+    tt = t0;
+  } else if (tMin > 1) {
+    tt = t1;
+  } else {
+    tt = t0 + (t1 - t0) * tMin;
+  }
+  shading->getColor(tt, &color0);
+
+  // compute the coordinates of the point on the t axis at t = tMin;
+  // then compute the intersection of the perpendicular line with the
+  // bounding box
+  tx = x0 + tMin * dx;
+  ty = y0 + tMin * dy;
+  if (dx == 0 && dy == 0) {
+    sMin = sMax = 0;
+  } if (dx == 0) {
+    sMin = (xMin - tx) / -dy;
+    sMax = (xMax - tx) / -dy;
+    if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+  } else if (dy == 0) {
+    sMin = (yMin - ty) / dx;
+    sMax = (yMax - ty) / dx;
+    if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+  } else {
+    s[0] = (yMin - ty) / dx;
+    s[1] = (yMax - ty) / dx;
+    s[2] = (xMin - tx) / -dy;
+    s[3] = (xMax - tx) / -dy;
+    for (j = 0; j < 3; ++j) {
+      kk = j;
+      for (k = j + 1; k < 4; ++k) {
+       if (s[k] < s[kk]) {
+         kk = k;
+       }
+      }
+      tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
+    }
+    sMin = s[1];
+    sMax = s[2];
+  }
+  ux0 = tx - sMin * dy;
+  uy0 = ty + sMin * dx;
+  vx0 = tx - sMax * dy;
+  vy0 = ty + sMax * dx;
+
+  i = 0;
+  while (i < axialMaxSplits) {
+
+    // bisect until color difference is small enough or we hit the
+    // bisection limit
+    j = next[i];
+    while (j > i + 1) {
+      if (ta[j] < 0) {
+       tt = t0;
+      } else if (ta[j] > 1) {
+       tt = t1;
+      } else {
+       tt = t0 + (t1 - t0) * ta[j];
+      }
+      shading->getColor(tt, &color1);
+      for (k = 0; k < nComps; ++k) {
+       if (fabs(color1.c[k] - color0.c[k]) > axialColorDelta) {
+         break;
+       }
+      }
+      if (k == nComps) {
+       break;
+      }
+      k = (i + j) / 2;
+      ta[k] = 0.5 * (ta[i] + ta[j]);
+      next[i] = k;
+      next[k] = j;
+      j = k;
+    }
+
+    // use the average of the colors of the two sides of the region
+    for (k = 0; k < nComps; ++k) {
+      color0.c[k] = 0.5 * (color0.c[k] + color1.c[k]);
+    }
+
+    // compute the coordinates of the point on the t axis; then
+    // compute the intersection of the perpendicular line with the
+    // bounding box
+    tx = x0 + ta[j] * dx;
+    ty = y0 + ta[j] * dy;
+    if (dx == 0 && dy == 0) {
+      sMin = sMax = 0;
+    } if (dx == 0) {
+      sMin = (xMin - tx) / -dy;
+      sMax = (xMax - tx) / -dy;
+      if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+    } else if (dy == 0) {
+      sMin = (yMin - ty) / dx;
+      sMax = (yMax - ty) / dx;
+      if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+    } else {
+      s[0] = (yMin - ty) / dx;
+      s[1] = (yMax - ty) / dx;
+      s[2] = (xMin - tx) / -dy;
+      s[3] = (xMax - tx) / -dy;
+      for (j = 0; j < 3; ++j) {
+       kk = j;
+       for (k = j + 1; k < 4; ++k) {
+         if (s[k] < s[kk]) {
+           kk = k;
+         }
+       }
+       tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
+      }
+      sMin = s[1];
+      sMax = s[2];
+    }
+    ux1 = tx - sMin * dy;
+    uy1 = ty + sMin * dx;
+    vx1 = tx - sMax * dy;
+    vy1 = ty + sMax * dx;
+
+    // set the color
+    state->setFillColor(&color0);
+    out->updateFillColor(state);
+
+    // fill the region
+    state->moveTo(ux0, uy0);
+    state->lineTo(vx0, vy0);
+    state->lineTo(vx1, vy1);
+    state->lineTo(ux1, uy1);
+    state->closePath();
+    out->fill(state);
+    state->clearPath();
+
+    // set up for next region
+    ux0 = ux1;
+    uy0 = uy1;
+    vx0 = vx1;
+    vy0 = vy1;
+    color0 = color1;
+    i = next[i];
+  }
+}
+
 void Gfx::doEndPath() {
-  if (state->isPath()) {
-    if (clip == clipNormal)
+  if (state->isPath() && clip != clipNone) {
+    state->clip();
+    if (clip == clipNormal) {
       out->clip(state);
-    else if (clip == clipEO)
+    } else {
       out->eoClip(state);
+    }
   }
   clip = clipNone;
   state->clearPath();
@@ -1316,16 +1635,10 @@ void Gfx::doEndPath() {
 //------------------------------------------------------------------------
 
 void Gfx::opClip(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   clip = clipNormal;
 }
 
 void Gfx::opEOClip(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   clip = clipEO;
 }
 
@@ -1334,9 +1647,6 @@ void Gfx::opEOClip(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opBeginText(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   state->setTextMat(1, 0, 0, 1, 0, 0);
   state->textMoveTo(0, 0);
   out->updateTextMat(state);
@@ -1345,8 +1655,6 @@ void Gfx::opBeginText(Object args[], int numArgs) {
 }
 
 void Gfx::opEndText(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
 }
 
 //------------------------------------------------------------------------
@@ -1354,9 +1662,6 @@ void Gfx::opEndText(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opSetCharSpacing(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   state->setCharSpace(args[0].getNum());
   out->updateCharSpace(state);
 }
@@ -1371,43 +1676,35 @@ void Gfx::opSetFont(Object args[], int numArgs) {
     printf("  font: '%s' %g\n",
           font->getName() ? font->getName()->getCString() : "???",
           args[1].getNum());
+    fflush(stdout);
   }
   state->setFont(font, args[1].getNum());
   fontChanged = gTrue;
 }
 
 void Gfx::opSetTextLeading(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->setLeading(args[0].getNum());
 }
 
 void Gfx::opSetTextRender(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->setRender(args[0].getInt());
   out->updateRender(state);
 }
 
 void Gfx::opSetTextRise(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->setRise(args[0].getNum());
   out->updateRise(state);
 }
 
 void Gfx::opSetWordSpacing(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->setWordSpace(args[0].getNum());
   out->updateWordSpace(state);
 }
 
 void Gfx::opSetHorizScaling(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->setHorizScaling(args[0].getNum());
   out->updateHorizScaling(state);
+  fontChanged = gTrue;
 }
 
 //------------------------------------------------------------------------
@@ -1417,8 +1714,6 @@ void Gfx::opSetHorizScaling(Object args[], int numArgs) {
 void Gfx::opTextMove(Object args[], int numArgs) {
   double tx, ty;
 
-  (void)numArgs;
-
   tx = state->getLineX() + args[0].getNum();
   ty = state->getLineY() + args[1].getNum();
   state->textMoveTo(tx, ty);
@@ -1428,8 +1723,6 @@ void Gfx::opTextMove(Object args[], int numArgs) {
 void Gfx::opTextMoveSet(Object args[], int numArgs) {
   double tx, ty;
 
-  (void)numArgs;
-
   tx = state->getLineX() + args[0].getNum();
   ty = args[1].getNum();
   state->setLeading(-ty);
@@ -1439,8 +1732,6 @@ void Gfx::opTextMoveSet(Object args[], int numArgs) {
 }
 
 void Gfx::opSetTextMatrix(Object args[], int numArgs) {
-  (void)numArgs;
-
   state->setTextMat(args[0].getNum(), args[1].getNum(),
                    args[2].getNum(), args[3].getNum(),
                    args[4].getNum(), args[5].getNum());
@@ -1453,9 +1744,6 @@ void Gfx::opSetTextMatrix(Object args[], int numArgs) {
 void Gfx::opTextNextLine(Object args[], int numArgs) {
   double tx, ty;
 
-  (void)args;
-  (void)numArgs;
-
   tx = state->getLineX();
   ty = state->getLineY() - state->getLeading();
   state->textMoveTo(tx, ty);
@@ -1467,8 +1755,6 @@ void Gfx::opTextNextLine(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opShowText(Object args[], int numArgs) {
-  (void)numArgs;
-
   if (!state->getFont()) {
     error(getPos(), "No font in show");
     return;
@@ -1479,8 +1765,6 @@ void Gfx::opShowText(Object args[], int numArgs) {
 void Gfx::opMoveShowText(Object args[], int numArgs) {
   double tx, ty;
 
-  (void)numArgs;
-
   if (!state->getFont()) {
     error(getPos(), "No font in move/show");
     return;
@@ -1495,8 +1779,6 @@ void Gfx::opMoveShowText(Object args[], int numArgs) {
 void Gfx::opMoveSetShowText(Object args[], int numArgs) {
   double tx, ty;
 
-  (void)numArgs;
-
   if (!state->getFont()) {
     error(getPos(), "No font in move/set/show");
     return;
@@ -1517,8 +1799,6 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) {
   Object obj;
   int i;
 
-  (void)numArgs;
-
   if (!state->getFont()) {
     error(getPos(), "No font in show/space");
     return;
@@ -1547,7 +1827,7 @@ void Gfx::doShowText(GString *s) {
   GString *s16;
   char s16a[2];
   int m, n;
-#if 0 //~type3
+#if 1 //~type3
   double dx, dy, width, height, w, h, x, y;
   double oldCTM[6], newCTM[6];
   double *mat;
@@ -1555,8 +1835,9 @@ void Gfx::doShowText(GString *s) {
   Parser *oldParser;
   int i;
 #else
-  double dx, dy, width, height, w, h, sWidth, sHeight;
+  double dx, dy, width, height, w, h;
 #endif
+  double sWidth, sHeight;
 
   if (fontChanged) {
     out->updateFont(state);
@@ -1580,12 +1861,12 @@ void Gfx::doShowText(GString *s) {
     while (n > 0) {
       m = getNextChar16(enc, p, &c16);
       if (enc->wMode == 0) {
-       width = state->getFontSize() * state->getHorizScaling() *
-               font->getWidth16(c16) +
+       width = state->getFontSize() * font->getWidth16(c16) +
                state->getCharSpace();
-       if (c16 == ' ') {
+       if (m == 1 && c16 == ' ') {
          width += state->getWordSpace();
        }
+       width *= state->getHorizScaling();
        height = 0;
       } else {
        width = 0;
@@ -1616,7 +1897,7 @@ void Gfx::doShowText(GString *s) {
 
   //----- 8-bit font
   } else {
-#if 0 //~type3
+#if 1 //~type3
     //~ also check out->renderType3()
     if (font->getType() == fontType3) {
       out->beginString(state, s);
@@ -1644,6 +1925,8 @@ void Gfx::doShowText(GString *s) {
        c8 = *p;
        font->getCharProc(c8, &charProc);
        state->transform(state->getCurX() + dx, state->getCurY() + dy, &x, &y);
+       out->saveState(state);
+       state = state->save();
        state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
        //~ out->updateCTM(???)
        if (charProc.isStream()) {
@@ -1651,16 +1934,15 @@ void Gfx::doShowText(GString *s) {
        } else {
          error(getPos(), "Missing or bad Type3 CharProc entry");
        }
-       state->setCTM(oldCTM[0], oldCTM[1], oldCTM[2],
-                     oldCTM[3], oldCTM[4], oldCTM[5]);
-       //~ out->updateCTM(???) - use gsave/grestore instead?
+       state = state->restore();
+       out->restoreState(state);
        charProc.free();
-       width = state->getFontSize() * state->getHorizScaling() *
-               font->getWidth(c8) +
+       width = state->getFontSize() * font->getWidth(c8) +
                state->getCharSpace();
        if (c8 == ' ') {
          width += state->getWordSpace();
        }
+       width *= state->getHorizScaling();
        state->textShift(width);
       }
       parser = oldParser;
@@ -1672,11 +1954,12 @@ void Gfx::doShowText(GString *s) {
       state->textTransformDelta(0, state->getRise(), &dx, &dy);
       for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) {
        c8 = *p;
-       width = state->getFontSize() * state->getHorizScaling() *
-               font->getWidth(c8) +
+       width = state->getFontSize() * font->getWidth(c8) +
                state->getCharSpace();
-       if (c8 == ' ')
+       if (c8 == ' ') {
          width += state->getWordSpace();
+       }
+       width *= state->getHorizScaling();
        state->textTransformDelta(width, 0, &w, &h);
        out->drawChar(state, state->getCurX() + dx, state->getCurY() + dy,
                      w, h, c8);
@@ -1685,13 +1968,14 @@ void Gfx::doShowText(GString *s) {
       out->endString(state);
     } else {
       out->drawString(state, s);
-      width = state->getFontSize() * state->getHorizScaling() *
-             font->getWidth(s) +
+      width = state->getFontSize() * font->getWidth(s) +
              s->getLength() * state->getCharSpace();
       for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) {
-       if (*p == ' ')
+       if (*p == ' ') {
          width += state->getWordSpace();
+       }
       }
+      width *= state->getHorizScaling();
       state->textShift(width);
     }
   }
@@ -1772,13 +2056,17 @@ void Gfx::opXObject(Object args[], int numArgs) {
 
 void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
   Dict *dict;
-  Object obj1, obj2;
   int width, height;
   int bits;
   GBool mask;
+  GBool invert;
   GfxColorSpace *colorSpace;
   GfxImageColorMap *colorMap;
-  GBool invert;
+  Object maskObj;
+  GBool haveMask;
+  int maskColors[2*gfxColorMaxComps];
+  Object obj1, obj2;
+  int i;
 
   // get stream dict
   dict = str->getDict();
@@ -1886,10 +2174,25 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
       goto err1;
     }
 
+    // get the mask
+    haveMask = gFalse;
+    dict->lookup("Mask", &maskObj);
+    if (maskObj.isArray()) {
+      for (i = 0; i < maskObj.arrayGetLength(); ++i) {
+       maskObj.arrayGet(i, &obj1);
+       maskColors[i] = obj1.getInt();
+       obj1.free();
+      }
+      haveMask = gTrue;
+    }
+
     // draw it
-    out->drawImage(state, ref, str, width, height, colorMap, inlineImg);
+    out->drawImage(state, ref, str, width, height, colorMap,
+                  haveMask ? maskColors : (int *)NULL,  inlineImg);
     delete colorMap;
     str->close();
+
+    maskObj.free();
   }
 
   return;
@@ -1951,7 +2254,7 @@ void Gfx::doForm(Object *str) {
 
   // get resources
   dict->lookup("Resources", &resObj);
-  resDict = resObj.isDict() ? resObj.getDict() : NULL;
+  resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
 
   // draw it
   doForm1(str, resDict, m, bbox);
@@ -2013,7 +2316,7 @@ void Gfx::doWidgetForm(Object *str, double xMin, double yMin,
 
   // get resources
   dict->lookup("Resources", &resObj);
-  resDict = resObj.isDict() ? resObj.getDict() : NULL;
+  resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
 
   // draw it
   doForm1(str, resDict, m, bbox);
@@ -2029,7 +2332,7 @@ void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
   int i;
 
   // push new resources on stack
-  res = new GfxResources(resDict, res);
+  res = new GfxResources(xref, resDict, res);
 
   // save current graphics state
   out->saveState(state);
@@ -2056,6 +2359,7 @@ void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
   state->lineTo(bbox[2], bbox[3]);
   state->lineTo(bbox[0], bbox[3]);
   state->closePath();
+  state->clip();
   out->clip(state);
   state->clearPath();
 
@@ -2090,9 +2394,6 @@ void Gfx::opBeginImage(Object args[], int numArgs) {
   Stream *str;
   int c1, c2;
 
-  (void)args;
-  (void)numArgs;
-
   // build dict/stream
   str = buildImageStream();
 
@@ -2114,11 +2415,11 @@ void Gfx::opBeginImage(Object args[], int numArgs) {
 Stream *Gfx::buildImageStream() {
   Object dict;
   Object obj;
-  const char *key;
+  char *key;
   Stream *str;
 
   // build dictionary
-  dict.initDict();
+  dict.initDict(xref);
   parser->getObj(&obj);
   while (!obj.isCmd("ID") && !obj.isEOF()) {
     if (!obj.isName()) {
@@ -2147,16 +2448,10 @@ Stream *Gfx::buildImageStream() {
 }
 
 void Gfx::opImageData(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   error(getPos(), "Internal: got 'ID' operator");
 }
 
 void Gfx::opEndImage(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   error(getPos(), "Internal: got 'EI' operator");
 }
 
@@ -2165,17 +2460,11 @@ void Gfx::opEndImage(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opSetCharWidth(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
-  error(getPos(), "Encountered 'd0' operator in content stream");
+//  error(getPos(), "Encountered 'd0' operator in content stream");
 }
 
 void Gfx::opSetCacheDevice(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
-  error(getPos(), "Encountered 'd1' operator in content stream");
+//  error(getPos(), "Encountered 'd1' operator in content stream");
 }
 
 //------------------------------------------------------------------------
@@ -2183,16 +2472,10 @@ void Gfx::opSetCacheDevice(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   ++ignoreUndef;
 }
 
 void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
-
   if (ignoreUndef > 0)
     --ignoreUndef;
 }
@@ -2202,28 +2485,24 @@ void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
 //------------------------------------------------------------------------
 
 void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
-  (void)numArgs;
-
   if (printCommands) {
     printf("  marked content: %s ", args[0].getName());
     if (numArgs == 2)
       args[2].print(stdout);
     printf("\n");
+    fflush(stdout);
   }
 }
 
 void Gfx::opEndMarkedContent(Object args[], int numArgs) {
-  (void)args;
-  (void)numArgs;
 }
 
 void Gfx::opMarkPoint(Object args[], int numArgs) {
-  (void)numArgs;
-
   if (printCommands) {
     printf("  mark point: %s ", args[0].getName());
     if (numArgs == 2)
       args[2].print(stdout);
     printf("\n");
+    fflush(stdout);
   }
 }
index 011fbfcd145b0b9d7a16ef961cfe5652dfaa27c8..24e124697a8acfc6b67a3a9b84bbcc769a1145e5 100644 (file)
@@ -16,6 +16,7 @@
 #include "gtypes.h"
 
 class GString;
+class XRef;
 class Array;
 class Stream;
 class Parser;
@@ -25,8 +26,11 @@ class GfxFontDict;
 class GfxFont;
 struct GfxFontEncoding16;
 class GfxPattern;
+class GfxShading;
+class GfxAxialShading;
 class GfxState;
 class Gfx;
+struct PDFRectangle;
 
 //------------------------------------------------------------------------
 // Gfx
@@ -62,15 +66,16 @@ struct Operator {
 class GfxResources {
 public:
 
-  GfxResources(Dict *resDict, GfxResources *next);
+  GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA);
   ~GfxResources();
 
-  GfxFont *lookupFont(const char *name);
-  GBool lookupXObject(const char *name, Object *obj);
-  GBool lookupXObjectNF(const char *name, Object *obj);
-  void lookupColorSpace(const char *name, Object *obj);
-  GfxPattern *lookupPattern(const char *name);
-  GBool lookupGState(const char *name, Object *obj);
+  GfxFont *lookupFont(char *name);
+  GBool lookupXObject(char *name, Object *obj);
+  GBool lookupXObjectNF(char *name, Object *obj);
+  void lookupColorSpace(char *name, Object *obj);
+  GfxPattern *lookupPattern(char *name);
+  GfxShading *lookupShading(char *name);
+  GBool lookupGState(char *name, Object *obj);
 
   GfxResources *getNext() { return next; }
 
@@ -80,6 +85,7 @@ private:
   Object xObjDict;
   Object colorSpaceDict;
   Object patternDict;
+  Object shadingDict;
   Object gStateDict;
   GfxResources *next;
 };
@@ -88,10 +94,9 @@ class Gfx {
 public:
 
   // Constructor for regular output.
-  Gfx(OutputDev *out1, int pageNum, Dict *resDict,
-      double dpi, double x1, double y1, double x2, double y2, GBool crop,
-      double cropX1, double cropY1, double cropX2, double cropY2,
-      int rotate);
+  Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, double dpi,
+      PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
+      GBool printCommandsA);
 
   // Destructor.
   ~Gfx();
@@ -104,7 +109,9 @@ public:
 
 private:
 
+  XRef *xref;                  // the xref table for this PDF file
   OutputDev *out;              // output device
+  GBool printCommands;         // print the drawing commands (for debugging)
   GfxResources *res;           // resource stack
 
   GfxState *state;             // current graphics state
@@ -120,7 +127,7 @@ private:
 
   void go(GBool topLevel);
   void execOp(Object *cmd, Object args[], int numArgs);
-  Operator *findOp(const char *name);
+  Operator *findOp(char *name);
   GBool checkArg(Object *arg, TchkType type);
   int getPos();
 
@@ -170,8 +177,9 @@ private:
   void opCloseFillStroke(Object args[], int numArgs);
   void opEOFillStroke(Object args[], int numArgs);
   void opCloseEOFillStroke(Object args[], int numArgs);
-  void opShFill(Object args[], int numArgs);
   void doPatternFill(GBool eoFill);
+  void opShFill(Object args[], int numArgs);
+  void doAxialShFill(GfxAxialShading *shading);
   void doEndPath();
 
   // path clipping operators
index 413796f2d9abb76efea8ea47851d27003f297fee..96b802e146e989094d533e2cbe26470fb1b3e2c5 100644 (file)
 
 //------------------------------------------------------------------------
 
-#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
 extern "C" {
-static int cmpWidthExcep(const void *w1, const void *w2);
-static int cmpWidthExcepV(const void *w1, const void *w2);
+static int CDECL cmpWidthExcep(const void *w1, const void *w2);
+static int CDECL cmpWidthExcepV(const void *w1, const void *w2);
 }
-#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
 
 //------------------------------------------------------------------------
 
@@ -68,16 +66,16 @@ static Gushort *defCharWidths[12] = {
 // GfxFont
 //------------------------------------------------------------------------
 
-GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
+GfxFont::GfxFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
   BuiltinFont *builtinFont;
   Object obj1, obj2, obj3, obj4;
   int missingWidth;
-  const char *name2, *p;
+  char *name2, *p;
   int i;
 
   // get font tag and ID
-  tag = new GString(tag1);
-  id = id1;
+  tag = new GString(tagA);
+  id = idA;
 
   // get font type
   type = fontUnknownType;
@@ -106,7 +104,7 @@ GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
   // without embedding them, so munge the names into the equivalent
   // PostScript names.  This is a kludge -- it would be nice if Adobe
   // followed their own spec.
-  if (type == fontTrueType) {
+  if (type == fontTrueType && name) {
     p = name->getCString();
     name2 = NULL;
     if (!strncmp(p, "Arial", 5)) {
@@ -160,12 +158,39 @@ GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
   // assume Times-Roman by default (for substitution purposes)
   flags = fontSerif;
 
+  // default ascent/descent values
+  if (builtinFont) {
+    ascent = 0.001 * builtinFont->ascent;
+    descent = 0.001 * builtinFont->descent;
+  } else {
+    ascent = 0.95;
+    descent = -0.35;
+  }
+
   // get info from font descriptor
   embFontName = NULL;
   embFontID.num = -1;
   embFontID.gen = -1;
   missingWidth = 0;
-  fontDict->lookup("FontDescriptor", &obj1);
+  if (type == fontType0) {
+    fontDict->lookup("DescendantFonts", &obj2);
+    if (obj2.isArray()) {
+      obj2.arrayGet(0, &obj3);
+      if (obj3.isDict()) {
+       obj3.dictLookup("FontDescriptor", &obj1);
+      } else {
+       error(-1, "Bad descendant font in Type 0 font");
+       obj1.initNull();
+      }
+      obj3.free();
+    } else {
+      error(-1, "Missing DescendantFonts entry in Type 0 font");
+      obj1.initNull();
+    }
+    obj2.free();
+  } else {
+    fontDict->lookup("FontDescriptor", &obj1);
+  }
   if (obj1.isDict()) {
 
     // get flags
@@ -197,7 +222,7 @@ GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
       obj1.dictLookupNF("FontFile3", &obj2);
       if (obj2.isRef()) {
        embFontID = obj2.getRef();
-       obj2.fetch(&obj3);
+       obj2.fetch(xref, &obj3);
        if (obj3.isStream()) {
          obj3.streamGetDict()->lookup("Subtype", &obj4);
          if (obj4.isName("Type1"))
@@ -223,6 +248,30 @@ GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
       missingWidth = obj2.getInt();
     }
     obj2.free();
+
+    // get Ascent and Descent
+    obj1.dictLookup("Ascent", &obj2);
+    if (obj2.isNum()) {
+      ascent = 0.001 * obj2.getNum();
+    }
+    obj2.free();
+    obj1.dictLookup("Descent", &obj2);
+    if (obj2.isNum()) {
+      descent = 0.001 * obj2.getNum();
+    }
+    obj2.free();
+
+    // font FontBBox
+    fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
+    if (obj1.dictLookup("FontBBox", &obj2)->isArray()) {
+      for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) {
+       if (obj2.arrayGet(i, &obj3)->isNum()) {
+         fontBBox[i] = obj3.getNum();
+       }
+       obj3.free();
+      }
+    }
+    obj2.free();
   }
   obj1.free();
 
@@ -256,7 +305,7 @@ GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
   if (type == fontType0) {
     getType0EncAndWidths(fontDict);
   } else {
-    getEncAndWidths(fontDict, builtinFont, missingWidth);
+    getEncAndWidths(xref, fontDict, builtinFont, missingWidth);
   }
 }
 
@@ -390,10 +439,10 @@ Object *GfxFont::getCharProc(int code, Object *proc) {
   return proc;
 }
 
-void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
-                             int missingWidth) {
+void GfxFont::getEncAndWidths(XRef *xref, Dict *fontDict,
+                             BuiltinFont *builtinFont, int missingWidth) {
   Object obj1, obj2, obj3;
-  const char *buf;
+  char *buf;
   int len;
   FontFile *fontFile;
   int code, i;
@@ -433,26 +482,31 @@ void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
   obj1.free();
 
   // check embedded or external font file for base encoding
-  if ((type == fontType1 || type == fontType1C) &&
+  if ((type == fontType1 || type == fontType1C || type == fontTrueType) &&
       (extFontFile || embFontID.num >= 0)) {
-    if (extFontFile)
+    if (extFontFile) {
       buf = readExtFontFile(&len);
-    else
-      buf = readEmbFontFile(&len);
+    } else {
+      buf = readEmbFontFile(xref, &len);
+    }
     if (buf) {
-      if (type == fontType1)
+      if (type == fontType1) {
        fontFile = new Type1FontFile(buf, len);
-      else
+      } else if (type == fontType1C) {
        fontFile = new Type1CFontFile(buf, len);
+      } else {
+       fontFile = new TrueTypeFontFile(buf, len);
+      }
       if (fontFile->getName()) {
        if (embFontName)
          delete embFontName;
        embFontName = new GString(fontFile->getName());
       }
-      if (!encoding)
+      if (!encoding) {
        encoding = fontFile->getEncoding(gTrue);
+      }
       delete fontFile;
-      gfree((void *)buf);
+      gfree(buf);
     }
   }
 
@@ -500,7 +554,7 @@ void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
 }
 
 void GfxFont::findExtFontFile() {
-  const char **path;
+  char **path;
   FILE *f;
 
   for (path = fontPath; *path; ++path) {
@@ -524,7 +578,7 @@ void GfxFont::findExtFontFile() {
   }
 }
 
-const char *GfxFont::readExtFontFile(int *len) {
+char *GfxFont::readExtFontFile(int *len) {
   FILE *f;
   char *buf;
 
@@ -542,7 +596,7 @@ const char *GfxFont::readExtFontFile(int *len) {
   return buf;
 }
 
-const char *GfxFont::readEmbFontFile(int *len) {
+char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
   char *buf;
   Object obj1, obj2;
   Stream *str;
@@ -550,7 +604,7 @@ const char *GfxFont::readEmbFontFile(int *len) {
   int size, i;
 
   obj1.initRef(embFontID.num, embFontID.gen);
-  obj1.fetch(&obj2);
+  obj1.fetch(xref, &obj2);
   if (!obj2.isStream()) {
     error(-1, "Embedded font file is not a stream");
     obj2.free();
@@ -584,7 +638,7 @@ void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding,
   Object obj1, obj2;
   int firstChar, lastChar;
   int code, code2;
-  const char *charName;
+  char *charName;
   Gushort *defWidths;
   int index;
   double mult;
@@ -594,72 +648,73 @@ void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding,
     widths[code] = missingWidth * 0.001;
   }
 
+  // use widths from font dict, if present
+  fontDict->lookup("FirstChar", &obj1);
+  firstChar = obj1.isInt() ? obj1.getInt() : 0;
+  obj1.free();
+  fontDict->lookup("LastChar", &obj1);
+  lastChar = obj1.isInt() ? obj1.getInt() : 255;
+  obj1.free();
+  if (type == fontType3)
+    mult = fontMat[0];
+  else
+    mult = 0.001;
+  fontDict->lookup("Widths", &obj1);
+  if (obj1.isArray()) {
+    for (code = firstChar; code <= lastChar; ++code) {
+      obj1.arrayGet(code - firstChar, &obj2);
+      if (obj2.isNum())
+       widths[code] = obj2.getNum() * mult;
+      obj2.free();
+    }
+
   // use widths from built-in font
-  if (builtinEncoding) {
+  } else if (builtinEncoding) {
     code2 = 0; // to make gcc happy
     for (code = 0; code < 256; ++code) {
       if ((charName = encoding->getCharName(code)) &&
-         (code2 = builtinEncoding->getCharCode(charName)) >= 0)
+         (code2 = builtinEncoding->getCharCode(charName)) >= 0) {
        widths[code] = builtinWidths[code2] * 0.001;
+      } else if (code == 32) {
+       // this is a kludge for broken PDF files that encode char 32
+       // as .notdef
+       widths[code] = builtinWidths[' '] * 0.001;
+      }
     }
 
-  // get widths from font dict
+  // couldn't find widths -- use defaults 
   } else {
-    fontDict->lookup("FirstChar", &obj1);
-    firstChar = obj1.isInt() ? obj1.getInt() : 0;
-    obj1.free();
-    fontDict->lookup("LastChar", &obj1);
-    lastChar = obj1.isInt() ? obj1.getInt() : 255;
-    obj1.free();
-    if (type == fontType3)
-      mult = fontMat[0];
-    else
-      mult = 0.001;
-    fontDict->lookup("Widths", &obj1);
-    if (obj1.isArray()) {
-      for (code = firstChar; code <= lastChar; ++code) {
-       obj1.arrayGet(code - firstChar, &obj2);
-       if (obj2.isNum())
-         widths[code] = obj2.getNum() * mult;
-       obj2.free();
-      }
-    } else {
-
-      // couldn't find widths -- use defaults 
 #if 0 //~
-      //~ certain PDF generators apparently don't include widths
-      //~ for Arial and TimesNewRoman -- and this error message
-      //~ is a nuisance
-      error(-1, "No character widths resource for non-builtin font");
+    //~ certain PDF generators apparently don't include widths
+    //~ for Arial and TimesNewRoman -- and this error message
+    //~ is a nuisance
+    error(-1, "No character widths resource for non-builtin font");
 #endif
-      if (isFixedWidth())
-       index = 0;
-      else if (isSerif())
-       index = 8;
-      else
-       index = 4;
-      if (isBold())
-       index += 2;
-      if (isItalic())
-       index += 1;
-      defWidths = defCharWidths[index];
-      code2 = 0; // to make gcc happy
-      for (code = 0; code < 256; ++code) {
-       if ((charName = encoding->getCharName(code)) &&
-           (code2 = standardEncoding.getCharCode(charName)) >= 0)
-         widths[code] = defWidths[code2] * 0.001;
-      }
+    if (isFixedWidth())
+      index = 0;
+    else if (isSerif())
+      index = 8;
+    else
+      index = 4;
+    if (isBold())
+      index += 2;
+    if (isItalic())
+      index += 1;
+    defWidths = defCharWidths[index];
+    code2 = 0; // to make gcc happy
+    for (code = 0; code < 256; ++code) {
+      if ((charName = encoding->getCharName(code)) &&
+         (code2 = standardEncoding.getCharCode(charName)) >= 0)
+       widths[code] = defWidths[code2] * 0.001;
     }
-    obj1.free();
   }
+  obj1.free();
 }
 
 void GfxFont::getType0EncAndWidths(Dict *fontDict) {
   Object obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8;
-#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
   int excepsSize;
   int i, j, k, n;
-#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
 
   widths16.exceps = NULL;
   widths16.excepsV = NULL;
@@ -713,7 +768,7 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
       goto err4;
 #endif
     } else {
-      error(-1, "Uknown Type 0 character set: %s-%s",
+      error(-1, "Unknown Type 0 character set: %s-%s",
            obj4.getString()->getCString(), obj5.getString()->getCString());
       goto err4;
     }
@@ -721,8 +776,6 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     error(-1, "Unknown Type 0 character set");
     goto err4;
   }
-
-#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
   obj5.free();
   obj4.free();
   obj3.free();
@@ -914,7 +967,7 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     error(-1, "Bad encoding for Type 0 font");
     goto err1;
   }
-#  if JAPANESE_SUPPORT
+#if JAPANESE_SUPPORT
   if (enc16.charSet == font16AdobeJapan12) {
     for (i = 0; gfxJapan12Tab[i].name; ++i) {
       if (!strcmp(obj1.getName(), gfxJapan12Tab[i].name))
@@ -927,8 +980,8 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     }
     enc16.enc = gfxJapan12Tab[i].enc;
   }
-#  endif
-#  if CHINESE_GB_SUPPORT
+#endif
+#if CHINESE_GB_SUPPORT
   if (enc16.charSet == font16AdobeGB12) {
     for (i = 0; gfxGB12Tab[i].name; ++i) {
       if (!strcmp(obj1.getName(), gfxGB12Tab[i].name))
@@ -941,8 +994,8 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     }
     enc16.enc = gfxGB12Tab[i].enc;
   }
-#  endif
-#  if CHINESE_CNS_SUPPORT
+#endif
+#if CHINESE_CNS_SUPPORT
   if (enc16.charSet == font16AdobeCNS13) {
     for (i = 0; gfxCNS13Tab[i].name; ++i) {
       if (!strcmp(obj1.getName(), gfxCNS13Tab[i].name))
@@ -955,11 +1008,10 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
     }
     enc16.enc = gfxCNS13Tab[i].enc;
   }
-#  endif
+#endif
   obj1.free();
 
   return;
-#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
 
  err4:
   obj5.free();
@@ -975,21 +1027,21 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
   makeWidths(fontDict, NULL, NULL, 0);
 }
 
-#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
-static int cmpWidthExcep(const void *w1, const void *w2) {
+extern "C" {
+static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
   return ((GfxFontWidthExcep *)w1)->first - ((GfxFontWidthExcep *)w2)->first;
 }
 
-static int cmpWidthExcepV(const void *w1, const void *w2) {
+static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
   return ((GfxFontWidthExcepV *)w1)->first - ((GfxFontWidthExcepV *)w2)->first;
 }
-#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
+}
 
 //------------------------------------------------------------------------
 // GfxFontDict
 //------------------------------------------------------------------------
 
-GfxFontDict::GfxFontDict(Dict *fontDict) {
+GfxFontDict::GfxFontDict(XRef *xref, Dict *fontDict) {
   int i;
   Object obj1, obj2;
 
@@ -997,10 +1049,10 @@ GfxFontDict::GfxFontDict(Dict *fontDict) {
   fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
   for (i = 0; i < numFonts; ++i) {
     fontDict->getValNF(i, &obj1);
-    obj1.fetch(&obj2);
+    obj1.fetch(xref, &obj2);
     if (obj1.isRef() && obj2.isDict()) {
-      fonts[i] = new GfxFont(fontDict->getKey(i), obj1.getRef(),
-                            obj2.getDict());
+      fonts[i] = new GfxFont(xref, fontDict->getKey(i),
+                            obj1.getRef(), obj2.getDict());
     } else {
       error(-1, "font resource is not a dictionary");
       fonts[i] = NULL;
@@ -1018,7 +1070,7 @@ GfxFontDict::~GfxFontDict() {
   gfree(fonts);
 }
 
-GfxFont *GfxFontDict::lookup(const char *tag) {
+GfxFont *GfxFontDict::lookup(char *tag) {
   int i;
 
   for (i = 0; i < numFonts; ++i) {
index 6853b1cc1afd4cd98fb2e526af19dd3178201d83..e51635632ac9a32130aba19608da4ea9e07696e9 100644 (file)
@@ -98,7 +98,7 @@ class GfxFont {
 public:
 
   // Constructor.
-  GfxFont(const char *tag1, Ref id1, Dict *fontDict);
+  GfxFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict);
 
   // Destructor.
   ~GfxFont();
@@ -110,7 +110,7 @@ public:
   Ref getID() { return id; }
 
   // Does this font match the tag?
-  GBool matches(const char *tag1) { return !tag->cmp(tag1); }
+  GBool matches(char *tagA) { return !tag->cmp(tagA); }
 
   // Get base font name.
   GString *getName() { return name; }
@@ -128,8 +128,8 @@ public:
 
   // Get the PostScript font name for the embedded font.  Returns
   // NULL if there is no embedded font.
-  const char *getEmbeddedFontName()
-    { return embFontName ? embFontName->getCString() : (const char *)NULL; }
+  char *getEmbeddedFontName()
+    { return embFontName ? embFontName->getCString() : (char *)NULL; }
 
   // Get the name of the external font file.  Returns NULL if there
   // is no external font file.
@@ -156,10 +156,10 @@ public:
   FontEncoding *getEncoding() { return encoding; }
 
   // Return the character name associated with <code>.
-  const char *getCharName(int code) { return encoding->getCharName(code); }
+  char *getCharName(int code) { return encoding->getCharName(code); }
 
   // Return the code associated with <name>.
-  int getCharCode(const char *charName) { return encoding->getCharCode(charName); }
+  int getCharCode(char *charName) { return encoding->getCharCode(charName); }
 
   // Return the Type 3 CharProc for the character associated with <code>.
   Object *getCharProc(int code, Object *proc);
@@ -174,14 +174,21 @@ public:
   // Return the font matrix.
   double *getFontMatrix() { return fontMat; }
 
+  // Return the font bounding box.
+  double *getFontBBox() { return fontBBox; }
+
+  // Return the ascent and descent values.
+  double getAscent() { return ascent; }
+  double getDescent() { return descent; }
+
   // Read an external or embedded font file into a buffer.
-  const char *readExtFontFile(int *len);
-  const char *readEmbFontFile(int *len);
+  char *readExtFontFile(int *len);
+  char *readEmbFontFile(XRef *xref, int *len);
 
 private:
 
-  void getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
-                      int missingWidth);
+  void getEncAndWidths(XRef *xref, Dict *fontDict,
+                      BuiltinFont *builtinFont, int missingWidth);
   void findExtFontFile();
   void makeWidths(Dict *fontDict, FontEncoding *builtinEncoding,
                  Gushort *builtinWidths, int missingWidth);
@@ -198,6 +205,9 @@ private:
   GString *extFontFile;                // external font file name
   Object charProcs;            // Type3 CharProcs dictionary
   double fontMat[6];           // font matrix
+  double fontBBox[4];          // font bounding box
+  double ascent;               // max height above baseline
+  double descent;              // max depth below baseline
   union {
     FontEncoding *encoding;    // 8-bit font encoding
     struct {
@@ -219,13 +229,13 @@ class GfxFontDict {
 public:
 
   // Build the font dictionary, given the PDF font dictionary.
-  GfxFontDict(Dict *fontDict);
+  GfxFontDict(XRef *xref, Dict *fontDict);
 
   // Destructor.
   ~GfxFontDict();
 
   // Get the specified font.
-  GfxFont *lookup(const char *tag);
+  GfxFont *lookup(char *tag);
 
   // Iterative access.
   int getNumFonts() { return numFonts; }
index 1abf9a56ec47025632d26f02c6ad3f769bbccbde..14074157008ff0925327d99dce1de7034d4564e5 100644 (file)
@@ -17,6 +17,7 @@
 #include "Error.h"
 #include "Object.h"
 #include "Array.h"
+#include "Page.h"
 #include "GfxState.h"
 
 //------------------------------------------------------------------------
@@ -261,9 +262,9 @@ GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
   whiteX = whiteY = whiteZ = 1;
   blackX = blackY = blackZ = 0;
   gammaR = gammaG = gammaB = 1;
-  m[0] = 1; m[1] = 0; m[2] = 0;
-  m[3] = 0; m[4] = 1; m[5] = 0;
-  m[6] = 0; m[7] = 0; m[8] = 1;
+  mat[0] = 1; mat[1] = 0; mat[2] = 0;
+  mat[3] = 0; mat[4] = 1; mat[5] = 0;
+  mat[6] = 0; mat[7] = 0; mat[8] = 1;
 }
 
 GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
@@ -284,7 +285,7 @@ GfxColorSpace *GfxCalRGBColorSpace::copy() {
   cs->gammaG = gammaG;
   cs->gammaB = gammaB;
   for (i = 0; i < 9; ++i) {
-    cs->m[i] = m[i];
+    cs->mat[i] = mat[i];
   }
   return cs;
 }
@@ -344,7 +345,7 @@ GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
       obj2.arrayGetLength() == 9) {
     for (i = 0; i < 9; ++i) {
       obj2.arrayGet(i, &obj3);
-      cs->m[i] = obj3.getNum();
+      cs->mat[i] = obj3.getNum();
       obj3.free();
     }
   }
@@ -609,11 +610,11 @@ void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
 // GfxICCBasedColorSpace
 //------------------------------------------------------------------------
 
-GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
-                                            Ref *iccProfileStream) {
-  this->nComps = nComps;
-  this->alt = alt;
-  this->iccProfileStream = *iccProfileStream;
+GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
+                                            Ref *iccProfileStreamA) {
+  nComps = nCompsA;
+  alt = altA;
+  iccProfileStream = *iccProfileStreamA;
   rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
   rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
 }
@@ -636,19 +637,19 @@ GfxColorSpace *GfxICCBasedColorSpace::copy() {
 
 GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
   GfxICCBasedColorSpace *cs;
-  Ref iccProfileStream;
-  int nComps;
-  GfxColorSpace *alt;
+  Ref iccProfileStreamA;
+  int nCompsA;
+  GfxColorSpace *altA;
   Dict *dict;
   Object obj1, obj2, obj3;
   int i;
 
   arr->getNF(1, &obj1);
   if (obj1.isRef()) {
-    iccProfileStream = obj1.getRef();
+    iccProfileStreamA = obj1.getRef();
   } else {
-    iccProfileStream.num = 0;
-    iccProfileStream.gen = 0;
+    iccProfileStreamA.num = 0;
+    iccProfileStreamA.gen = 0;
   }
   obj1.free();
   arr->get(1, &obj1);
@@ -664,19 +665,19 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
     obj1.free();
     return NULL;
   }
-  nComps = obj2.getInt();
+  nCompsA = obj2.getInt();
   obj2.free();
   if (dict->lookup("Alternate", &obj2)->isNull() ||
-      !(alt = GfxColorSpace::parse(&obj2))) {
-    switch (nComps) {
+      !(altA = GfxColorSpace::parse(&obj2))) {
+    switch (nCompsA) {
     case 1:
-      alt = new GfxDeviceGrayColorSpace();
+      altA = new GfxDeviceGrayColorSpace();
       break;
     case 3:
-      alt = new GfxDeviceRGBColorSpace();
+      altA = new GfxDeviceRGBColorSpace();
       break;
     case 4:
-      alt = new GfxDeviceCMYKColorSpace();
+      altA = new GfxDeviceCMYKColorSpace();
       break;
     default:
       error(-1, "Bad ICCBased color space - invalid N");
@@ -686,10 +687,10 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
     }
   }
   obj2.free();
-  cs = new GfxICCBasedColorSpace(nComps, alt, &iccProfileStream);
+  cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
   if (dict->lookup("Range", &obj2)->isArray() &&
-      obj2.arrayGetLength() == 2 * nComps) {
-    for (i = 0; i < nComps; ++i) {
+      obj2.arrayGetLength() == 2 * nCompsA) {
+    for (i = 0; i < nCompsA; ++i) {
       obj2.arrayGet(2*i, &obj3);
       cs->rangeMin[i] = obj3.getNum();
       obj3.free();
@@ -730,12 +731,12 @@ void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
 // GfxIndexedColorSpace
 //------------------------------------------------------------------------
 
-GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *base,
-                                          int indexHigh) {
-  this->base = base;
-  this->indexHigh = indexHigh;
-  this->lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
-                                  sizeof(Guchar));
+GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
+                                          int indexHighA) {
+  base = baseA;
+  indexHigh = indexHighA;
+  lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
+                            sizeof(Guchar));
 }
 
 GfxIndexedColorSpace::~GfxIndexedColorSpace() {
@@ -754,8 +755,8 @@ GfxColorSpace *GfxIndexedColorSpace::copy() {
 
 GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
   GfxIndexedColorSpace *cs;
-  GfxColorSpace *base;
-  int indexHigh;
+  GfxColorSpace *baseA;
+  int indexHighA;
   Object obj1;
   int x;
   char *s;
@@ -766,7 +767,7 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
     goto err1;
   }
   arr->get(1, &obj1);
-  if (!(base = GfxColorSpace::parse(&obj1))) {
+  if (!(baseA = GfxColorSpace::parse(&obj1))) {
     error(-1, "Bad Indexed color space (base color space)");
     goto err2;
   }
@@ -775,14 +776,14 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
     error(-1, "Bad Indexed color space (hival)");
     goto err2;
   }
-  indexHigh = obj1.getInt();
+  indexHighA = obj1.getInt();
   obj1.free();
-  cs = new GfxIndexedColorSpace(base, indexHigh);
+  cs = new GfxIndexedColorSpace(baseA, indexHighA);
   arr->get(3, &obj1);
-  n = base->getNComps();
+  n = baseA->getNComps();
   if (obj1.isStream()) {
     obj1.streamReset();
-    for (i = 0; i <= indexHigh; ++i) {
+    for (i = 0; i <= indexHighA; ++i) {
       for (j = 0; j < n; ++j) {
        if ((x = obj1.streamGetChar()) == EOF) {
          error(-1, "Bad Indexed color space (lookup table stream too short)");
@@ -793,12 +794,12 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
     }
     obj1.streamClose();
   } else if (obj1.isString()) {
-    if (obj1.getString()->getLength() < (indexHigh + 1) * n) {
+    if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
       error(-1, "Bad Indexed color space (lookup table string too short)");
       goto err3;
     }
     s = obj1.getString()->getCString();
-    for (i = 0; i <= indexHigh; ++i) {
+    for (i = 0; i <= indexHighA; ++i) {
       for (j = 0; j < n; ++j) {
        cs->lookup[i*n + j] = (Guchar)*s++;
       }
@@ -868,12 +869,12 @@ void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
 // GfxSeparationColorSpace
 //------------------------------------------------------------------------
 
-GfxSeparationColorSpace::GfxSeparationColorSpace(GString *name,
-                                                GfxColorSpace *alt,
-                                                Function *func) {
-  this->name = name;
-  this->alt = alt;
-  this->func = func;
+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
+                                                GfxColorSpace *altA,
+                                                Function *funcA) {
+  name = nameA;
+  alt = altA;
+  func = funcA;
 }
 
 GfxSeparationColorSpace::~GfxSeparationColorSpace() {
@@ -889,9 +890,9 @@ GfxColorSpace *GfxSeparationColorSpace::copy() {
 //~ handle the 'All' and 'None' colorants
 GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
   GfxSeparationColorSpace *cs;
-  GString *name;
-  GfxColorSpace *alt;
-  Function *func;
+  GString *nameA;
+  GfxColorSpace *altA;
+  Function *funcA;
   Object obj1;
 
   if (arr->getLength() != 4) {
@@ -902,27 +903,31 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
     error(-1, "Bad Separation color space (name)");
     goto err2;
   }
-  name = new GString(obj1.getName());
+  nameA = new GString(obj1.getName());
   obj1.free();
   arr->get(2, &obj1);
-  if (!(alt = GfxColorSpace::parse(&obj1))) {
+  if (!(altA = GfxColorSpace::parse(&obj1))) {
     error(-1, "Bad Separation color space (alternate color space)");
     goto err3;
   }
   obj1.free();
-  func = Function::parse(arr->get(3, &obj1));
-  obj1.free();
-  if (!func->isOk()) {
+  arr->get(3, &obj1);
+  if (!(funcA = Function::parse(&obj1))) {
     goto err4;
   }
-  cs = new GfxSeparationColorSpace(name, alt, func);
+  if (!funcA->isOk()) {
+    goto err5;
+  }
+  obj1.free();
+  cs = new GfxSeparationColorSpace(nameA, altA, funcA);
   return cs;
 
+ err5:
+  delete funcA;
  err4:
-  delete func;
-  delete alt;
+  delete altA;
  err3:
-  delete name;
+  delete nameA;
  err2:
   obj1.free();
  err1:
@@ -954,12 +959,12 @@ void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
 // GfxDeviceNColorSpace
 //------------------------------------------------------------------------
 
-GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nComps,
-                                          GfxColorSpace *alt,
-                                          Function *func) {
-  this->nComps = nComps;
-  this->alt = alt;
-  this->func = func;
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
+                                          GfxColorSpace *altA,
+                                          Function *funcA) {
+  nComps = nCompsA;
+  alt = altA;
+  func = funcA;
 }
 
 GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
@@ -986,10 +991,10 @@ GfxColorSpace *GfxDeviceNColorSpace::copy() {
 //~ handle the 'None' colorant
 GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
   GfxDeviceNColorSpace *cs;
-  int nComps;
-  GString *names[gfxColorMaxComps];
-  GfxColorSpace *alt;
-  Function *func;
+  int nCompsA;
+  GString *namesA[gfxColorMaxComps];
+  GfxColorSpace *altA;
+  Function *funcA;
   Object obj1, obj2;
   int i;
 
@@ -1001,40 +1006,44 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
     error(-1, "Bad DeviceN color space (names)");
     goto err2;
   }
-  nComps = obj1.arrayGetLength();
-  for (i = 0; i < nComps; ++i) {
+  nCompsA = obj1.arrayGetLength();
+  for (i = 0; i < nCompsA; ++i) {
     if (!obj1.arrayGet(i, &obj2)->isName()) {
       error(-1, "Bad DeviceN color space (names)");
       obj2.free();
       goto err2;
     }
-    names[i] = new GString(obj2.getName());
+    namesA[i] = new GString(obj2.getName());
     obj2.free();
   }
   obj1.free();
   arr->get(2, &obj1);
-  if (!(alt = GfxColorSpace::parse(&obj1))) {
+  if (!(altA = GfxColorSpace::parse(&obj1))) {
     error(-1, "Bad DeviceN color space (alternate color space)");
     goto err3;
   }
   obj1.free();
-  func = Function::parse(arr->get(3, &obj1));
-  obj1.free();
-  if (!func->isOk()) {
+  arr->get(3, &obj1);
+  if (!(funcA = Function::parse(&obj1))) {
     goto err4;
   }
-  cs = new GfxDeviceNColorSpace(nComps, alt, func);
-  for (i = 0; i < nComps; ++i) {
-    cs->names[i] = names[i];
+  if (!funcA->isOk()) {
+    goto err5;
+  }
+  obj1.free();
+  cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
+  for (i = 0; i < nCompsA; ++i) {
+    cs->names[i] = namesA[i];
   }
   return cs;
 
+ err5:
+  delete funcA;
  err4:
-  delete func;
-  delete alt;
+  delete altA;
  err3:
-  for (i = 0; i < nComps; ++i) {
-    delete names[i];
+  for (i = 0; i < nCompsA; ++i) {
+    delete namesA[i];
   }
  err2:
   obj1.free();
@@ -1067,8 +1076,8 @@ void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
 // GfxPatternColorSpace
 //------------------------------------------------------------------------
 
-GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *under) {
-  this->under = under;
+GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
+  under = underA;
 }
 
 GfxPatternColorSpace::~GfxPatternColorSpace() {
@@ -1084,24 +1093,24 @@ GfxColorSpace *GfxPatternColorSpace::copy() {
 
 GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
   GfxPatternColorSpace *cs;
-  GfxColorSpace *under;
+  GfxColorSpace *underA;
   Object obj1;
 
   if (arr->getLength() != 1 && arr->getLength() != 2) {
     error(-1, "Bad Pattern color space");
     return NULL;
   }
-  under = NULL;
+  underA = NULL;
   if (arr->getLength() == 2) {
     arr->get(1, &obj1);
-    if (!(under = GfxColorSpace::parse(&obj1))) {
+    if (!(underA = GfxColorSpace::parse(&obj1))) {
       error(-1, "Bad Pattern color space (underlying color space)");
       obj1.free();
       return NULL;
     }
     obj1.free();
   }
-  cs = new GfxPatternColorSpace(under);
+  cs = new GfxPatternColorSpace(underA);
   return cs;
 }
 
@@ -1122,8 +1131,8 @@ void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
 // Pattern
 //------------------------------------------------------------------------
 
-GfxPattern::GfxPattern(int type) {
-  this->type = type;
+GfxPattern::GfxPattern(int typeA) {
+  type = typeA;
 }
 
 GfxPattern::~GfxPattern() {
@@ -1237,480 +1246,254 @@ GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
 }
 
 //------------------------------------------------------------------------
-// Function
+// GfxShading
 //------------------------------------------------------------------------
 
-Function::Function() {
-}
-
-Function::~Function() {
+GfxShading::GfxShading() {
 }
 
-Function *Function::parse(Object *funcObj) {
-  Function *func;
-  Dict *dict;
-  int funcType;
-  Object obj1;
-
-  if (funcObj->isStream()) {
-    dict = funcObj->streamGetDict();
-  } else if (funcObj->isDict()) {
-    dict = funcObj->getDict();
-  } else {
-    error(-1, "Expected function dictionary or stream");
-    return NULL;
-  }
-
-  if (!dict->lookup("FunctionType", &obj1)->isInt()) {
-    error(-1, "Function type is missing or wrong type");
-    obj1.free();
-    return NULL;
-  }
-  funcType = obj1.getInt();
-  obj1.free();
-
-  if (funcType == 0) {
-    func = new SampledFunction(funcObj, dict);
-  } else if (funcType == 2) {
-    func = new ExponentialFunction(funcObj, dict);
-  } else {
-    error(-1, "Unimplemented function type");
-    return NULL;
-  }
-  if (!func->isOk()) {
-    delete func;
-    return NULL;
-  }
-
-  return func;
+GfxShading::~GfxShading() {
+  delete colorSpace;
 }
 
-GBool Function::init(Dict *dict) {
+GfxShading *GfxShading::parse(Object *obj) {
+  GfxShading *shading;
+  int typeA;
+  GfxColorSpace *colorSpaceA;
+  GfxColor backgroundA;
+  GBool hasBackgroundA;
+  double xMinA, yMinA, xMaxA, yMaxA;
+  GBool hasBBoxA;
   Object obj1, obj2;
   int i;
 
-  //----- Domain
-  if (!dict->lookup("Domain", &obj1)->isArray()) {
-    error(-1, "Function is missing domain");
-    goto err2;
-  }
-  m = obj1.arrayGetLength() / 2;
-  if (m > funcMaxInputs) {
-    error(-1, "Functions with more than %d inputs are unsupported",
-         funcMaxInputs);
-    goto err2;
-  }
-  for (i = 0; i < m; ++i) {
-    obj1.arrayGet(2*i, &obj2);
-    if (!obj2.isNum()) {
-      error(-1, "Illegal value in function domain array");
+  shading = NULL;
+  if (obj->isDict()) {
+
+    if (!obj->dictLookup("ShadingType", &obj1)->isInt()) {
+      error(-1, "Invalid ShadingType in shading dictionary");
+      obj1.free();
       goto err1;
     }
-    domain[i][0] = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2*i+1, &obj2);
-    if (!obj2.isNum()) {
-      error(-1, "Illegal value in function domain array");
+    typeA = obj1.getInt();
+    obj1.free();
+    if (typeA != 2) {
+      error(-1, "Unimplemented shading type %d", typeA);
       goto err1;
     }
-    domain[i][1] = obj2.getNum();
-    obj2.free();
-  }
-  obj1.free();
 
-  //----- Range
-  hasRange = gFalse;
-  n = 0;
-  if (dict->lookup("Range", &obj1)->isArray()) {
-    hasRange = gTrue;
-    n = obj1.arrayGetLength() / 2;
-    if (n > funcMaxOutputs) {
-      error(-1, "Functions with more than %d outputs are unsupported",
-           funcMaxOutputs);
-      goto err2;
-    }
-    for (i = 0; i < n; ++i) {
-      obj1.arrayGet(2*i, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function range array");
-       goto err1;
-      }
-      range[i][0] = obj2.getNum();
-      obj2.free();
-      obj1.arrayGet(2*i+1, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function range array");
-       goto err1;
-      }
-      range[i][1] = obj2.getNum();
-      obj2.free();
+    obj->dictLookup("ColorSpace", &obj1);
+    if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) {
+      error(-1, "Bad color space in shading dictionary");
+      obj1.free();
+      goto err1;
     }
     obj1.free();
-  }
-
-  return gTrue;
 
- err1:
-  obj2.free();
- err2:
-  obj1.free();
-  return gFalse;
-}
-
-//------------------------------------------------------------------------
-// SampledFunction
-//------------------------------------------------------------------------
-
-SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
-  Stream *str;
-  int nSamples, sampleBits;
-  double sampleMul;
-  Object obj1, obj2;
-  Guint buf, bitMask;
-  int bits;
-  int s;
-  int i;
-
-  samples = NULL;
-  ok = gFalse;
-
-  //----- initialize the generic stuff
-  if (!init(dict)) {
-    goto err1;
-  }
-  if (!hasRange) {
-    error(-1, "Type 0 function is missing range");
-    goto err1;
-  }
-
-  //----- get the stream
-  if (!funcObj->isStream()) {
-    error(-1, "Type 0 function isn't a stream");
-    goto err1;
-  }
-  str = funcObj->getStream();
-
-  //----- Size
-  if (!dict->lookup("Size", &obj1)->isArray() ||
-      obj1.arrayGetLength() != m) {
-    error(-1, "Function has missing or invalid size array");
-    goto err2;
-  }
-  for (i = 0; i < m; ++i) {
-    obj1.arrayGet(i, &obj2);
-    if (!obj2.isInt()) {
-      error(-1, "Illegal value in function size array");
-      goto err3;
+    for (i = 0; i < gfxColorMaxComps; ++i) {
+      backgroundA.c[i] = 0;
     }
-    sampleSize[i] = obj2.getInt();
-    obj2.free();
-  }
-  obj1.free();
-
-  //----- BitsPerSample
-  if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
-    error(-1, "Function has missing or invalid BitsPerSample");
-    goto err2;
-  }
-  sampleBits = obj1.getInt();
-  sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
-  obj1.free();
-
-  //----- Encode
-  if (dict->lookup("Encode", &obj1)->isArray() &&
-      obj1.arrayGetLength() == 2*m) {
-    for (i = 0; i < m; ++i) {
-      obj1.arrayGet(2*i, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function encode array");
-       goto err3;
-      }
-      encode[i][0] = obj2.getNum();
-      obj2.free();
-      obj1.arrayGet(2*i+1, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function encode array");
-       goto err3;
+    hasBackgroundA = gFalse;
+    if (obj->dictLookup("Background", &obj1)->isArray()) {
+      if (obj1.arrayGetLength() == colorSpaceA->getNComps()) {
+       hasBackgroundA = gTrue;
+       for (i = 0; i < colorSpaceA->getNComps(); ++i) {
+         backgroundA.c[i] = obj1.arrayGet(i, &obj2)->getNum();
+         obj2.free();
+       }
+      } else {
+       error(-1, "Bad Background in shading dictionary");
       }
-      encode[i][1] = obj2.getNum();
-      obj2.free();
-    }
-  } else {
-    for (i = 0; i < m; ++i) {
-      encode[i][0] = 0;
-      encode[i][1] = sampleSize[i] - 1;
     }
-  }
-  obj1.free();
+    obj1.free();
 
-  //----- Decode
-  if (dict->lookup("Decode", &obj1)->isArray() &&
-      obj1.arrayGetLength() == 2*n) {
-    for (i = 0; i < n; ++i) {
-      obj1.arrayGet(2*i, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function decode array");
-       goto err3;
+    xMinA = yMinA = xMaxA = yMaxA = 0;
+    hasBBoxA = gFalse;
+    if (obj->dictLookup("BBox", &obj1)->isArray()) {
+      if (obj1.arrayGetLength() == 4) {
+       hasBBoxA = gTrue;
+       xMinA = obj1.arrayGet(0, &obj2)->getNum();
+       obj2.free();
+       yMinA = obj1.arrayGet(1, &obj2)->getNum();
+       obj2.free();
+       xMaxA = obj1.arrayGet(2, &obj2)->getNum();
+       obj2.free();
+       yMaxA = obj1.arrayGet(3, &obj2)->getNum();
+       obj2.free();
+      } else {
+       error(-1, "Bad BBox in shading dictionary");
       }
-      decode[i][0] = obj2.getNum();
-      obj2.free();
-      obj1.arrayGet(2*i+1, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function decode array");
-       goto err3;
-      }
-      decode[i][1] = obj2.getNum();
-      obj2.free();
-    }
-  } else {
-    for (i = 0; i < n; ++i) {
-      decode[i][0] = range[i][0];
-      decode[i][1] = range[i][1];
     }
-  }
-  obj1.free();
+    obj1.free();
 
-  //----- samples
-  nSamples = n;
-  for (i = 0; i < m; ++i)
-    nSamples *= sampleSize[i];
-  samples = (double *)gmalloc(nSamples * sizeof(double));
-  buf = 0;
-  bits = 0;
-  bitMask = (1 << sampleBits) - 1;
-  str->reset();
-  for (i = 0; i < nSamples; ++i) {
-    if (sampleBits == 8) {
-      s = str->getChar();
-    } else if (sampleBits == 16) {
-      s = str->getChar();
-      s = (s << 8) + str->getChar();
-    } else if (sampleBits == 32) {
-      s = str->getChar();
-      s = (s << 8) + str->getChar();
-      s = (s << 8) + str->getChar();
-      s = (s << 8) + str->getChar();
-    } else {
-      while (bits < sampleBits) {
-       buf = (buf << 8) | (str->getChar() & 0xff);
-       bits += 8;
-      }
-      s = (buf >> (bits - sampleBits)) & bitMask;
-      bits -= sampleBits;
+    shading = GfxAxialShading::parse(obj->getDict());
+
+    if (shading) {
+      shading->type = typeA;
+      shading->colorSpace = colorSpaceA;
+      shading->background = backgroundA;
+      shading->hasBackground = hasBackgroundA;
+      shading->xMin = xMinA;
+      shading->yMin = yMinA;
+      shading->xMax = xMaxA;
+      shading->yMax = yMaxA;
+      shading->hasBBox = hasBBoxA;
     }
-    samples[i] = (double)s * sampleMul;
   }
-  str->close();
 
-  ok = gTrue;
-  return;
+  return shading;
 
- err3:
-  obj2.free();
- err2:
-  obj1.free();
  err1:
-  return;
-}
-
-SampledFunction::~SampledFunction() {
-  if (samples) {
-    gfree(samples);
-  }
+  return NULL;
 }
 
-SampledFunction::SampledFunction(SampledFunction *func) {
-  int nSamples, i;
+//------------------------------------------------------------------------
+// GfxAxialShading
+//------------------------------------------------------------------------
 
-  memcpy(this, func, sizeof(SampledFunction));
+GfxAxialShading::GfxAxialShading(double x0A, double y0A,
+                                double x1A, double y1A,
+                                double t0A, double t1A,
+                                Function **funcsA, int nFuncsA,
+                                GBool extend0A, GBool extend1A) {
+  int i;
 
-  nSamples = n;
-  for (i = 0; i < m; ++i) {
-    nSamples *= sampleSize[i];
+  x0 = x0A;
+  y0 = y0A;
+  x1 = x1A;
+  y1 = y1A;
+  t0 = t0A;
+  t1 = t1A;
+  nFuncs = nFuncsA;
+  for (i = 0; i < nFuncs; ++i) {
+    funcs[i] = funcsA[i];
   }
-  samples = (double *)gmalloc(nSamples * sizeof(double));
-  memcpy(samples, func->samples, nSamples * sizeof(double));
+  extend0 = extend0A;
+  extend1 = extend1A;
 }
 
-void SampledFunction::transform(double *in, double *out) {
-  double e[4];
-  double s;
-  double x0, x1;
-  int e0, e1;
-  double efrac;
+GfxAxialShading::~GfxAxialShading() {
   int i;
 
-  // map input values into sample array
-  for (i = 0; i < m; ++i) {
-    e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
-           (encode[i][1] - encode[i][0]) + encode[i][0];
-    if (e[i] < 0) {
-      e[i] = 0;
-    } else if (e[i] > sampleSize[i] - 1) {
-      e[i] = sampleSize[i] - 1;
-    }
-  }
-
-  for (i = 0; i < n; ++i) {
-
-    // m-linear interpolation
-    // (only m=1 is currently supported)
-    e0 = (int)floor(e[0]);
-    e1 = (int)ceil(e[0]);
-    efrac = e[0] - e0;
-    x0 = samples[e0 * n + i];
-    x1 = samples[e1 * n + i];
-    s = (1 - efrac) * x0 + efrac * x1;
-
-    // map output values to range
-    out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
-    if (out[i] < range[i][0]) {
-      out[i] = range[i][0];
-    } else if (out[i] > range[i][1]) {
-      out[i] = range[i][1];
-    }
+  for (i = 0; i < nFuncs; ++i) {
+    delete funcs[i];
   }
 }
 
-//------------------------------------------------------------------------
-// ExponentialFunction
-//------------------------------------------------------------------------
-
-ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
+GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
+  double x0A, y0A, x1A, y1A;
+  double t0A, t1A;
+  Function *funcsA[gfxColorMaxComps];
+  int nFuncsA;
+  GBool extend0A, extend1A;
   Object obj1, obj2;
-  GBool hasN;
   int i;
 
-  ok = gFalse;
-  hasN = gFalse;
-
-  //----- initialize the generic stuff
-  if (!init(dict)) {
-    goto err1;
-  }
-  if (m != 1) {
-    error(-1, "Exponential function with more than one input");
+  x0A = y0A = x1A = y1A = 0;
+  if (dict->lookup("Coords", &obj1)->isArray() &&
+      obj1.arrayGetLength() == 4) {
+    x0A = obj1.arrayGet(0, &obj2)->getNum();
+    obj2.free();
+    y0A = obj1.arrayGet(1, &obj2)->getNum();
+    obj2.free();
+    x1A = obj1.arrayGet(2, &obj2)->getNum();
+    obj2.free();
+    y1A = obj1.arrayGet(3, &obj2)->getNum();
+    obj2.free();
+  } else {
+    error(-1, "Missing or invalid Coords in shading dictionary");
     goto err1;
   }
+  obj1.free();
 
-  //----- default values
-  for (i = 0; i < funcMaxOutputs; ++i) {
-    c0[i] = 0;
-    c1[i] = 1;
+  t0A = 0;
+  t1A = 1;
+  if (dict->lookup("Domain", &obj1)->isArray() &&
+      obj1.arrayGetLength() == 2) {
+    t0A = obj1.arrayGet(0, &obj2)->getNum();
+    obj2.free();
+    t1A = obj1.arrayGet(1, &obj2)->getNum();
+    obj2.free();
   }
+  obj1.free();
 
-  //----- C0
-  if (dict->lookup("C0", &obj1)->isArray()) {
-    if (!hasN) {
-      n = obj1.arrayGetLength();
-    } else if (obj1.arrayGetLength() != n) {
-      error(-1, "Function's C0 array is wrong length");
-      goto err2;
-    }
-    for (i = 0; i < n; ++i) {
+  dict->lookup("Function", &obj1);
+  if (obj1.isArray()) {
+    nFuncsA = obj1.arrayGetLength();
+    for (i = 0; i < nFuncsA; ++i) {
       obj1.arrayGet(i, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function C0 array");
-       goto err3;
+      if (!(funcsA[i] = Function::parse(&obj2))) {
+       obj1.free();
+       obj2.free();
+       goto err1;
       }
-      c0[i] = obj2.getNum();
       obj2.free();
     }
-    obj1.free();
+  } else {
+    nFuncsA = 1;
+    if (!(funcsA[0] = Function::parse(&obj1))) {
+      obj1.free();
+      goto err1;
+    }
   }
-
-  //----- C1
-  if (dict->lookup("C1", &obj1)->isArray()) {
-    if (!hasN) {
-      n = obj1.arrayGetLength();
-    } else if (obj1.arrayGetLength() != n) {
-      error(-1, "Function's C1 array is wrong length");
+  obj1.free();
+  for (i = 0; i < nFuncsA; ++i) {
+    if (!funcsA[i]->isOk()) {
       goto err2;
     }
-    for (i = 0; i < n; ++i) {
-      obj1.arrayGet(i, &obj2);
-      if (!obj2.isNum()) {
-       error(-1, "Illegal value in function C1 array");
-       goto err3;
-      }
-      c1[i] = obj2.getNum();
-      obj2.free();
-    }
-    obj1.free();
   }
 
-  //----- N (exponent)
-  if (!dict->lookup("N", &obj1)->isNum()) {
-    error(-1, "Function has missing or invalid N");
-    goto err2;
+  extend0A = extend1A = gFalse;
+  if (dict->lookup("Extend", &obj1)->isArray() &&
+      obj1.arrayGetLength() == 2) {
+    extend0A = obj1.arrayGet(0, &obj2)->getBool();
+    obj2.free();
+    extend1A = obj1.arrayGet(1, &obj2)->getBool();
+    obj2.free();
   }
-  e = obj1.getNum();
   obj1.free();
 
-  ok = gTrue;
-  return;
+  return new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
+                            funcsA, nFuncsA, extend0A, extend1A);
 
- err3:
-  obj2.free();
  err2:
-  obj1.free();
+  for (i = 0; i < nFuncsA; ++i) {
+    delete funcsA[i];
+  }
  err1:
-  return;
-}
-
-ExponentialFunction::~ExponentialFunction() {
-}
-
-ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
-  memcpy(this, func, sizeof(ExponentialFunction));
+  return NULL;
 }
 
-void ExponentialFunction::transform(double *in, double *out) {
-  double x;
+void GfxAxialShading::getColor(double t, GfxColor *color) {
   int i;
 
-  if (in[0] < domain[0][0]) {
-    x = domain[0][0];
-  } else if (in[0] > domain[0][1]) {
-    x = domain[0][1];
-  } else {
-    x = in[0];
-  }
-  for (i = 0; i < n; ++i) {
-    out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
-    if (hasRange) {
-      if (out[i] < range[i][0]) {
-       out[i] = range[i][0];
-      } else if (out[i] > range[i][1]) {
-       out[i] = range[i][1];
-      }
-    }
+  for (i = 0; i < nFuncs; ++i) {
+    funcs[i]->transform(&t, &color->c[i]);
   }
-  return;
 }
 
 //------------------------------------------------------------------------
 // GfxImageColorMap
 //------------------------------------------------------------------------
 
-GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
-                                  GfxColorSpace *colorSpace) {
+GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
+                                  GfxColorSpace *colorSpaceA) {
   GfxIndexedColorSpace *indexedCS;
   GfxSeparationColorSpace *sepCS;
   int maxPixel, indexHigh;
   Guchar *lookup2;
   Function *sepFunc;
   Object obj;
-  double x;
+  double x[gfxColorMaxComps];
   double y[gfxColorMaxComps];
   int i, j, k;
 
   ok = gTrue;
 
   // bits per component and color space
-  this->bits = bits;
+  bits = bitsA;
   maxPixel = (1 << bits) - 1;
-  this->colorSpace = colorSpace;
+  colorSpace = colorSpaceA;
 
   // get decode map
   if (decode->isNull()) {
@@ -1783,8 +1566,8 @@ GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
     lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
     sepFunc = sepCS->getFunc();
     for (i = 0; i <= maxPixel; ++i) {
-      x = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
-      sepFunc->transform(&x, y);
+      x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
+      sepFunc->transform(x, y);
       for (k = 0; k < nComps2; ++k) {
        lookup[i*nComps2 + k] = y[k];
       }
@@ -2014,14 +1797,14 @@ void GfxPath::curveTo(double x1, double y1, double x2, double y2,
 // GfxState
 //------------------------------------------------------------------------
 
-GfxState::GfxState(double dpi, double px1a, double py1a,
-                  double px2a, double py2a, int rotate, GBool upsideDown) {
+GfxState::GfxState(double dpi, PDFRectangle *pageBox, int rotate,
+                  GBool upsideDown) {
   double k;
 
-  px1 = px1a;
-  py1 = py1a;
-  px2 = px2a;
-  py2 = py2a;
+  px1 = pageBox->x1;
+  py1 = pageBox->y1;
+  px2 = pageBox->x2;
+  py2 = pageBox->y2;
   k = dpi / 72.0;
   if (rotate == 90) {
     ctm[0] = 0;
@@ -2095,6 +1878,11 @@ GfxState::GfxState(double dpi, double px1a, double py1a,
   curX = curY = 0;
   lineX = lineY = 0;
 
+  clipXMin = 0;
+  clipYMin = 0;
+  clipXMax = pageWidth;
+  clipYMax = pageHeight;
+
   saved = NULL;
 }
 
@@ -2233,6 +2021,47 @@ void GfxState::clearPath() {
   path = new GfxPath();
 }
 
+void GfxState::clip() {
+  double xMin, yMin, xMax, yMax, x, y;
+  GfxSubpath *subpath;
+  int i, j;
+
+  xMin = xMax = yMin = yMax = 0; // make gcc happy
+  for (i = 0; i < path->getNumSubpaths(); ++i) {
+    subpath = path->getSubpath(i);
+    for (j = 0; j < subpath->getNumPoints(); ++j) {
+      transform(subpath->getX(j), subpath->getY(j), &x, &y);
+      if (i == 0 && j == 0) {
+       xMin = xMax = x;
+       yMin = yMax = y;
+      } else {
+       if (x < xMin) {
+         xMin = x;
+       } else if (x > xMax) {
+         xMax = x;
+       }
+       if (y < yMin) {
+         yMin = y;
+       } else if (y > yMax) {
+         yMax = y;
+       }
+      }
+    }
+  }
+  if (xMin > clipXMin) {
+    clipXMin = xMin;
+  }
+  if (yMin > clipYMin) {
+    clipYMin = yMin;
+  }
+  if (xMax < clipXMax) {
+    clipXMax = xMax;
+  }
+  if (yMax < clipYMax) {
+    clipYMax = yMax;
+  }
+}
+
 void GfxState::textShift(double tx) {
   double dx, dy;
 
index 2056c4d1fb36f6f110a82fbb08d103f3e3e64e4e..a628f6bf1fca99c708816c347c9bccfc65246ff6 100644 (file)
 
 #include "gtypes.h"
 #include "Object.h"
+#include "Function.h"
 
 class Array;
-class Function;
 class GfxFont;
+struct PDFRectangle;
 
 //------------------------------------------------------------------------
 // GfxColor
 //------------------------------------------------------------------------
 
-#define gfxColorMaxComps 8
+#define gfxColorMaxComps funcMaxOutputs
 
 struct GfxColor {
   double c[gfxColorMaxComps];
@@ -201,14 +202,14 @@ public:
   double getGammaR() { return gammaR; }
   double getGammaG() { return gammaG; }
   double getGammaB() { return gammaB; }
-  double *getMatrix() { return m; }
+  double *getMatrix() { return mat; }
 
 private:
 
   double whiteX, whiteY, whiteZ;    // white point
   double blackX, blackY, blackZ;    // black point
   double gammaR, gammaG, gammaB;    // gamma values
-  double m[9];                     // ABC -> XYZ transform matrix
+  double mat[9];               // ABC -> XYZ transform matrix
 };
 
 //------------------------------------------------------------------------
@@ -283,8 +284,8 @@ private:
 class GfxICCBasedColorSpace: public GfxColorSpace {
 public:
 
-  GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
-                       Ref *iccProfileStream);
+  GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
+                       Ref *iccProfileStreamA);
   virtual ~GfxICCBasedColorSpace();
   virtual GfxColorSpace *copy();
   virtual GfxColorSpaceMode getMode() { return csICCBased; }
@@ -320,7 +321,7 @@ private:
 class GfxIndexedColorSpace: public GfxColorSpace {
 public:
 
-  GfxIndexedColorSpace(GfxColorSpace *base, int indexHigh);
+  GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA);
   virtual ~GfxIndexedColorSpace();
   virtual GfxColorSpace *copy();
   virtual GfxColorSpaceMode getMode() { return csIndexed; }
@@ -356,8 +357,8 @@ private:
 class GfxSeparationColorSpace: public GfxColorSpace {
 public:
 
-  GfxSeparationColorSpace(GString *name, GfxColorSpace *alt,
-                         Function *func);
+  GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA,
+                         Function *funcA);
   virtual ~GfxSeparationColorSpace();
   virtual GfxColorSpace *copy();
   virtual GfxColorSpaceMode getMode() { return csSeparation; }
@@ -424,7 +425,7 @@ private:
 class GfxPatternColorSpace: public GfxColorSpace {
 public:
 
-  GfxPatternColorSpace(GfxColorSpace *under);
+  GfxPatternColorSpace(GfxColorSpace *underA);
   virtual ~GfxPatternColorSpace();
   virtual GfxColorSpace *copy();
   virtual GfxColorSpaceMode getMode() { return csPattern; }
@@ -454,7 +455,7 @@ private:
 class GfxPattern {
 public:
 
-  GfxPattern(int type);
+  GfxPattern(int typeA);
   virtual ~GfxPattern();
 
   static GfxPattern *parse(Object *obj);
@@ -504,94 +505,66 @@ private:
 };
 
 //------------------------------------------------------------------------
-// Function
+// GfxShading
 //------------------------------------------------------------------------
 
-#define funcMaxInputs  1
-#define funcMaxOutputs 8
-
-class Function {
+class GfxShading {
 public:
 
-  Function();
-
-  virtual ~Function();
-
-  // Construct a function.  Returns NULL if unsuccessful.
-  static Function *parse(Object *funcObj);
-
-  // Initialize the entries common to all function types.
-  GBool init(Dict *dict);
-
-  virtual Function *copy() = 0;
-
-  // Return size of input and output tuples.
-  int getInputSize() { return m; }
-  int getOutputSize() { return n; }
+  GfxShading();
+  virtual ~GfxShading();
 
-  // Transform an input tuple into an output tuple.
-  virtual void transform(double *in, double *out) = 0;
+  static GfxShading *parse(Object *obj);
 
-  virtual GBool isOk() = 0;
+  int getType() { return type; }
+  GfxColorSpace *getColorSpace() { return colorSpace; }
+  GfxColor *getBackground() { return &background; }
+  GBool getHasBackground() { return hasBackground; }
+  void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA)
+    { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
+  GBool getHasBBox() { return hasBBox; }
 
-protected:
+private:
 
-  int m, n;                    // size of input and output tuples
-  double                       // min and max values for function domain
-    domain[funcMaxInputs][2];
-  double                       // min and max values for function range
-    range[funcMaxOutputs][2];
-  GBool hasRange;              // set if range is defined
+  int type;
+  GfxColorSpace *colorSpace;
+  GfxColor background;
+  GBool hasBackground;
+  double xMin, yMin, xMax, yMax;
+  GBool hasBBox;
 };
 
 //------------------------------------------------------------------------
-// SampledFunction
+// GfxAxialShading
 //------------------------------------------------------------------------
 
-class SampledFunction: public Function {
+class GfxAxialShading: public GfxShading {
 public:
 
-  SampledFunction(Object *funcObj, Dict *dict);
-  virtual ~SampledFunction();
-  virtual Function *copy() { return new SampledFunction(this); }
-  virtual void transform(double *in, double *out);
-  virtual GBool isOk() { return ok; }
-
-private:
-
-  SampledFunction(SampledFunction *func);
-
-  int                          // number of samples for each domain element
-    sampleSize[funcMaxInputs];
-  double                       // min and max values for domain encoder
-    encode[funcMaxInputs][2];
-  double                       // min and max values for range decoder
-    decode[funcMaxOutputs][2];
-  double *samples;             // the samples
-  GBool ok;
-};
-
-//------------------------------------------------------------------------
-// ExponentialFunction
-//------------------------------------------------------------------------
+  GfxAxialShading(double x0A, double y0A,
+                 double x1A, double y1A,
+                 double t0A, double t1A,
+                 Function **funcsA, int nFuncsA,
+                 GBool extend0A, GBool extend1A);
+  virtual ~GfxAxialShading();
 
-class ExponentialFunction: public Function {
-public:
+  static GfxAxialShading *parse(Dict *dict);
 
-  ExponentialFunction(Object *funcObj, Dict *dict);
-  virtual ~ExponentialFunction();
-  virtual Function *copy() { return new ExponentialFunction(this); }
-  virtual void transform(double *in, double *out);
-  virtual GBool isOk() { return ok; }
+  void getCoords(double *x0A, double *y0A, double *x1A, double *y1A)
+    { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
+  double getDomain0() { return t0; }
+  double getDomain1() { return t1; }
+  void getColor(double t, GfxColor *color);
+  GBool getExtend0() { return extend0; }
+  GBool getExtend1() { return extend1; }
 
 private:
 
-  ExponentialFunction(ExponentialFunction *func);
-
-  double c0[funcMaxOutputs];
-  double c1[funcMaxOutputs];
-  double e;
-  GBool ok;
+  double x0, y0, x1, y1;
+  double t0, t1;
+  Function *funcs[gfxColorMaxComps];
+  int nFuncs;
+  GBool extend0, extend1;
 };
 
 //------------------------------------------------------------------------
@@ -602,7 +575,7 @@ class GfxImageColorMap {
 public:
 
   // Constructor.
-  GfxImageColorMap(int bits, Object *decode, GfxColorSpace *colorSpace);
+  GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA);
 
   // Destructor.
   ~GfxImageColorMap();
@@ -750,10 +723,10 @@ class GfxState {
 public:
 
   // Construct a default GfxState, for a device with resolution <dpi>,
-  // page box (<x1>,<y1>)-(<x2>,<y2>), page rotation <rotate>, and
-  // coordinate system specified by <upsideDown>.
-  GfxState(double dpi, double px1a, double py1a,
-          double px2a, double py2a, int rotate, GBool upsideDown);
+  // page box <pageBox>, page rotation <rotate>, and coordinate system
+  // specified by <upsideDown>.
+  GfxState(double dpi, PDFRectangle *pageBox, int rotate,
+          GBool upsideDown);
 
   // Destructor.
   ~GfxState();
@@ -771,6 +744,10 @@ public:
   double getPageHeight() { return pageHeight; }
   GfxColor *getFillColor() { return &fillColor; }
   GfxColor *getStrokeColor() { return &strokeColor; }
+  void getFillGray(double *gray)
+    { fillColorSpace->getGray(&fillColor, gray); }
+  void getStrokeGray(double *gray)
+    { strokeColorSpace->getGray(&fillColor, gray); }
   void getFillRGB(GfxRGB *rgb)
     { fillColorSpace->getRGB(&fillColor, rgb); }
   void getStrokeRGB(GfxRGB *rgb)
@@ -804,6 +781,8 @@ public:
   GfxPath *getPath() { return path; }
   double getCurX() { return curX; }
   double getCurY() { return curY; }
+  void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax)
+    { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; }
   double getLineX() { return lineX; }
   double getLineY() { return lineY; }
 
@@ -848,9 +827,9 @@ public:
   void setFlatness(int flatness1) { flatness = flatness1; }
   void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
   void setLineCap(int lineCap1) { lineCap = lineCap1; }
-  void setMiterLimit(double miterLimit1) { miterLimit = miterLimit1; }
-  void setFont(GfxFont *font1, double fontSize1)
-    { font = font1; fontSize = fontSize1; }
+  void setMiterLimit(double limit) { miterLimit = limit; }
+  void setFont(GfxFont *fontA, double fontSizeA)
+    { font = fontA; fontSize = fontSizeA; }
   void setTextMat(double a, double b, double c,
                  double d, double e, double f)
     { textMat[0] = a; textMat[1] = b; textMat[2] = c;
@@ -861,12 +840,12 @@ public:
     { wordSpace = space; }
   void setHorizScaling(double scale)
     { horizScaling = 0.01 * scale; }
-  void setLeading(double leading1)
-    { leading = leading1; }
-  void setRise(double rise1)
-    { rise = rise1; }
-  void setRender(int render1)
-    { render = render1; }
+  void setLeading(double leadingA)
+    { leading = leadingA; }
+  void setRise(double riseA)
+    { rise = riseA; }
+  void setRender(int renderA)
+    { render = renderA; }
 
   // Add to path.
   void moveTo(double x, double y)
@@ -880,6 +859,9 @@ public:
     { path->close(); curX = path->getLastX(); curY = path->getLastY(); }
   void clearPath();
 
+  // Update clip region.
+  void clip();
+
   // Text position.
   void textMoveTo(double tx, double ty)
     { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); }
@@ -929,6 +911,9 @@ private:
   double curX, curY;           // current point (user coords)
   double lineX, lineY;         // start of current text line (text coords)
 
+  double clipXMin, clipYMin,   // bounding box for clip region
+         clipXMax, clipYMax;
+
   GfxState *saved;             // next GfxState on stack
 
   GfxState(GfxState *state);
index 4ca8cfe9f51e323d3fa41fd16bf6a7fddbcb0f8f..442566b721773933937bb2c130c7d6746093e403 100644 (file)
@@ -44,22 +44,22 @@ static char specialChars[256] = {
 // Lexer
 //------------------------------------------------------------------------
 
-Lexer::Lexer(Stream *str) {
+Lexer::Lexer(XRef *xref, Stream *str) {
   Object obj;
 
   curStr.initStream(str);
-  streams = new Array();
+  streams = new Array(xref);
   streams->add(curStr.copy(&obj));
   strPtr = 0;
   freeArray = gTrue;
   curStr.streamReset();
 }
 
-Lexer::Lexer(Object *obj) {
+Lexer::Lexer(XRef *xref, Object *obj) {
   Object obj2;
 
   if (obj->isStream()) {
-    streams = new Array();
+    streams = new Array(xref);
     freeArray = gTrue;
     streams->add(obj->copy(&obj2));
   } else {
@@ -204,11 +204,15 @@ Object *Lexer::getObj(Object *obj) {
 
       case '(':
        ++numParen;
+       c2 = c;
        break;
 
       case ')':
-       if (--numParen == 0)
+       if (--numParen == 0) {
          done = gTrue;
+       } else {
+         c2 = c;
+       }
        break;
 
       case '\\':
index 70144b86bc3216db4caacf0d4ce8e7aa19bd16e0..5edbeda6b1ceb37ba9e8a32a4adaabe1292ebe34 100644 (file)
@@ -16,6 +16,8 @@
 #include "Object.h"
 #include "Stream.h"
 
+class XRef;
+
 #define tokBufSize 128         // size of token buffer
 
 //------------------------------------------------------------------------
@@ -27,11 +29,11 @@ public:
 
   // Construct a lexer for a single stream.  Deletes the stream when
   // lexer is deleted.
-  Lexer(Stream *str);
+  Lexer(XRef *xref, Stream *str);
 
   // Construct a lexer for a stream or array of streams (assumes obj
   // is either a stream or array of streams).
-  Lexer(Object *obj);
+  Lexer(XRef *xref, Object *obj);
 
   // Destructor.
   ~Lexer();
index a53e0990b870b633d89302f0575374d78e02c87d..999c1f202f9f93c3f83a40a1ddc9c7c96d2f4088 100644 (file)
@@ -28,11 +28,11 @@ static GString *getFileSpecName(Object *fileSpecObj);
 // LinkDest
 //------------------------------------------------------------------------
 
-LinkDest::LinkDest(Array *a, GBool pageIsRef1) {
+LinkDest::LinkDest(Array *a, GBool pageIsRefA) {
   Object obj1, obj2;
 
   // initialize fields
-  pageIsRef = pageIsRef1;
+  pageIsRef = pageIsRefA;
   left = bottom = right = top = zoom = 0;
   ok = gFalse;
 
@@ -384,8 +384,8 @@ LinkNamed::~LinkNamed() {
 // LinkUnknown
 //------------------------------------------------------------------------
 
-LinkUnknown::LinkUnknown(const char *action1) {
-  action = new GString(action1);
+LinkUnknown::LinkUnknown(char *actionA) {
+  action = new GString(actionA);
 }
 
 LinkUnknown::~LinkUnknown() {
@@ -447,11 +447,14 @@ Link::Link(Dict *dict, GString *baseURI) {
   // get border
   borderW = 0;
   if (!dict->lookup("Border", &obj1)->isNull()) {
-    if (obj1.isArray() && obj1.arrayGet(2, &obj2)->isNum())
-      borderW = obj2.getNum();
-    else
-      error(-1, "Bad annotation border");
-    obj2.free();
+    if (obj1.isArray() && obj1.arrayGetLength() >= 3) {
+      if (obj1.arrayGet(2, &obj2)->isNum()) {
+       borderW = obj2.getNum();
+      } else {
+       error(-1, "Bad annotation border");
+      }
+      obj2.free();
+    }
   }
   obj1.free();
 
index a502763525db9e061cf9788b2ca75a20574b2947..4d16724788a83a96f58a7731165409d893ad48e5 100644 (file)
@@ -249,7 +249,7 @@ class LinkUnknown: public LinkAction {
 public:
 
   // Build a LinkUnknown with the specified action type.
-  LinkUnknown(const char *action1);
+  LinkUnknown(char *actionA);
 
   // Destructor.
   virtual ~LinkUnknown();
index 95c601ae410d6e877c8de2efb437e1bfc78efe49..abc87af72dab09231bcc450b99f11d790f5e52a3 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.6 2001/03/02 22:34:16 andy Exp $"
+# "$Id: Makefile,v 1.6.2.1 2001/12/26 16:52:45 mike Exp $"
 #
 #   pdftops filter Makefile for the Common UNIX Printing System (CUPS).
 #
@@ -16,7 +16,7 @@ include ../Makedefs
 
 LIBOBJS        =       Decrypt.o GString.o gfile.o gmempp.o gmem.o parseargs.o \
                Array.o Catalog.o Dict.o Error.o FontEncoding.o \
-               FontFile.o FormWidget.o Gfx.o GfxFont.o GfxState.o \
+               FontFile.o FormWidget.o Function.o Gfx.o GfxFont.o GfxState.o \
                Lexer.o Link.o Object.o OutputDev.o Page.o Params.o \
                Parser.o PDFDoc.o PSOutputDev.o Stream.o XRef.o
 OBJS   =       pdftops.o $(LIBOBJS)
@@ -43,10 +43,7 @@ clean:
 #
 
 install:
-       $(MKDIR) $(SERVERBIN)/filter
-       $(CHMOD) ugo+rx $(SERVERBIN)
-       $(CHMOD) ugo+rx $(SERVERBIN)/filter
-       $(RM) $(SERVERBIN)/filter/pdftops
+       $(INSTALL_DIR) $(SERVERBIN)/filter
        $(INSTALL_BIN) pdftops $(SERVERBIN)/filter
 
 
@@ -89,6 +86,7 @@ FontEncoding.o:       gmem.h FontEncoding.h gtypes.h
 FontFile.o:    gmem.h Error.h config.h FontFile.h gtypes.h GString.h \
                FontEncoding.h StdFontInfo.h CompactFontInfo.h
 FormWidget.o:  FormWidget.h gmem.h Object.h Gfx.h
+Function.o:    gmem.h Object.h Dict.h Stream.h Error.h Function.h
 Gfx.o:         gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h \
                Lexer.h Parser.h GfxFont.h FontEncoding.h GfxState.h \
                OutputDev.h Params.h Error.h config.h Gfx.h
@@ -130,5 +128,5 @@ XRef.o:             gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h \
 $(OBJS):       ../config.h ../Makedefs
 
 #
-# End of "$Id: Makefile,v 1.6 2001/03/02 22:34:16 andy Exp $".
+# End of "$Id: Makefile,v 1.6.2.1 2001/12/26 16:52:45 mike Exp $".
 #
index b3ebe40f0e6cefd2326f723e6b5d1653d17315b0..ca671ea2cff13dbe1b15836ff5e6065ed94ca4b2 100644 (file)
@@ -22,7 +22,7 @@
 // Object
 //------------------------------------------------------------------------
 
-const char *objTypeNames[numObjTypes] = {
+char *objTypeNames[numObjTypes] = {
   "boolean",
   "integer",
   "real",
@@ -44,21 +44,21 @@ int Object::numAlloc[numObjTypes] =
   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #endif
 
-Object *Object::initArray() {
+Object *Object::initArray(XRef *xref) {
   initObj(objArray);
-  array = new Array();
+  array = new Array(xref);
   return this;
 }
 
-Object *Object::initDict() {
+Object *Object::initDict(XRef *xref) {
   initObj(objDict);
-  dict = new Dict();
+  dict = new Dict(xref);
   return this;
 }
 
-Object *Object::initStream(Stream *stream1) {
+Object *Object::initStream(Stream *streamA) {
   initObj(objStream);
-  stream = stream1;
+  stream = streamA;
   return this;
 }
 
@@ -92,7 +92,7 @@ Object *Object::copy(Object *obj) {
   return obj;
 }
 
-Object *Object::fetch(Object *obj) {
+Object *Object::fetch(XRef *xref, Object *obj) {
   return (type == objRef && xref) ?
          xref->fetch(ref.num, ref.gen, obj) : copy(obj);
 }
@@ -103,7 +103,7 @@ void Object::free() {
     delete string;
     break;
   case objName:
-    gfree((void *)name);
+    gfree(name);
     break;
   case objArray:
     if (!array->decRef()) {
@@ -121,7 +121,7 @@ void Object::free() {
     }
     break;
   case objCmd:
-    gfree((void *)cmd);
+    gfree(cmd);
     break;
   default:
     break;
@@ -132,7 +132,7 @@ void Object::free() {
   type = objNone;
 }
 
-const char *Object::getTypeName() {
+char *Object::getTypeName() {
   return objTypeNames[type];
 }
 
@@ -216,7 +216,5 @@ void Object::memCheck(FILE *f) {
        fprintf(f, "  %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
     }
   }
-#else
-  (void)f;
 #endif
 }
index d5132efa5aca19b1d79458fff1b94f293565aebb..49af5861398e85f1a5b9edfe49e403fb54ae8627 100644 (file)
@@ -19,6 +19,7 @@
 #include "gmem.h"
 #include "GString.h"
 
+class XRef;
 class Array;
 class Dict;
 class Stream;
@@ -78,27 +79,25 @@ public:
     type(objNone) {}
 
   // Initialize an object.
-  Object *initBool(GBool booln1)
-    { initObj(objBool); booln = booln1; return this; }
-  Object *initInt(int intg1)
-    { initObj(objInt); intg = intg1; return this; }
-  Object *initReal(double real1)
-    { initObj(objReal); real = real1; return this; }
-  Object *initString(GString *string1)
-    { initObj(objString); string = string1; return this; }
-  Object *initName(const char *name1)
-    { initObj(objName); name = copyString(name1); return this; }
+  Object *initBool(GBool boolnA)
+    { initObj(objBool); booln = boolnA; return this; }
+  Object *initInt(int intgA)
+    { initObj(objInt); intg = intgA; return this; }
+  Object *initReal(double realA)
+    { initObj(objReal); real = realA; return this; }
+  Object *initString(GString *stringA)
+    { initObj(objString); string = stringA; return this; }
+  Object *initName(char *nameA)
+    { initObj(objName); name = copyString(nameA); return this; }
   Object *initNull()
     { initObj(objNull); return this; }
-  Object *initArray();
-  Object *initDict();
-  Object *initDict(Dict *dict1)
-    { initObj(objDict); dict = dict1; return this; }
-  Object *initStream(Stream *stream1);
-  Object *initRef(int num1, int gen1)
-    { initObj(objRef); ref.num = num1; ref.gen = gen1; return this; }
-  Object *initCmd(const char *cmd1)
-    { initObj(objCmd); cmd = copyString(cmd1); return this; }
+  Object *initArray(XRef *xref);
+  Object *initDict(XRef *xref);
+  Object *initStream(Stream *streamA);
+  Object *initRef(int numA, int genA)
+    { initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
+  Object *initCmd(char *cmdA)
+    { initObj(objCmd); cmd = copyString(cmdA); return this; }
   Object *initError()
     { initObj(objError); return this; }
   Object *initEOF()
@@ -109,7 +108,7 @@ public:
 
   // If object is a Ref, fetch and return the referenced object.
   // Otherwise, return a copy of the object.
-  Object *fetch(Object *obj);
+  Object *fetch(XRef *xref, Object *obj);
 
   // Free object contents.
   void free();
@@ -133,12 +132,12 @@ public:
   GBool isNone() { return type == objNone; }
 
   // Special type checking.
-  GBool isName(const char *name1)
-    { return type == objName && !strcmp(name, name1); }
-  GBool isDict(const char *dictType);
-  GBool isStream(const char *dictType);
-  GBool isCmd(const char *cmd1)
-    { return type == objCmd && !strcmp(cmd, cmd1); }
+  GBool isName(char *nameA)
+    { return type == objName && !strcmp(name, nameA); }
+  GBool isDict(char *dictType);
+  GBool isStream(char *dictType);
+  GBool isCmd(char *cmdA)
+    { return type == objCmd && !strcmp(cmd, cmdA); }
 
   // Accessors.  NB: these assume object is of correct type.
   GBool getBool() { return booln; }
@@ -146,7 +145,7 @@ public:
   double getReal() { return real; }
   double getNum() { return type == objInt ? (double)intg : real; }
   GString *getString() { return string; }
-  const char *getName() { return name; }
+  char *getName() { return name; }
   Array *getArray() { return array; }
   Dict *getDict() { return dict; }
   Stream *getStream() { return stream; }
@@ -162,16 +161,16 @@ public:
 
   // Dict accessors.
   int dictGetLength();
-  void dictAdd(const char *key, Object *val);
-  GBool dictIs(const char *dictType);
-  Object *dictLookup(const char *key, Object *obj);
-  Object *dictLookupNF(const char *key, Object *obj);
-  const char *dictGetKey(int i);
+  void dictAdd(char *key, Object *val);
+  GBool dictIs(char *dictType);
+  Object *dictLookup(char *key, Object *obj);
+  Object *dictLookupNF(char *key, Object *obj);
+  char *dictGetKey(int i);
   Object *dictGetVal(int i, Object *obj);
   Object *dictGetValNF(int i, Object *obj);
 
   // Stream accessors.
-  GBool streamIs(const char *dictType);
+  GBool streamIs(char *dictType);
   void streamReset();
   void streamClose();
   int streamGetChar();
@@ -182,7 +181,7 @@ public:
   Dict *streamGetDict();
 
   // Output.
-  const char *getTypeName();
+  char *getTypeName();
   void print(FILE *f = stdout);
 
   // Memory testing.
@@ -196,12 +195,12 @@ private:
     int intg;                  //   integer
     double real;               //   real
     GString *string;           //   string
-    const char *name;          //   name
+    char *name;                        //   name
     Array *array;              //   array
     Dict *dict;                        //   dictionary
     Stream *stream;            //   stream
     Ref ref;                   //   indirect reference
-    const char *cmd;           //   command
+    char *cmd;                 //   command
   };
 
 #ifdef DEBUG_MEM
@@ -237,22 +236,22 @@ inline Object *Object::arrayGetNF(int i, Object *obj)
 inline int Object::dictGetLength()
   { return dict->getLength(); }
 
-inline void Object::dictAdd(const char *key, Object *val)
+inline void Object::dictAdd(char *key, Object *val)
   { dict->add(key, val); }
 
-inline GBool Object::dictIs(const char *dictType)
+inline GBool Object::dictIs(char *dictType)
   { return dict->is(dictType); }
 
-inline GBool Object::isDict(const char *dictType)
+inline GBool Object::isDict(char *dictType)
   { return type == objDict && dictIs(dictType); }
 
-inline Object *Object::dictLookup(const char *key, Object *obj)
+inline Object *Object::dictLookup(char *key, Object *obj)
   { return dict->lookup(key, obj); }
 
-inline Object *Object::dictLookupNF(const char *key, Object *obj)
+inline Object *Object::dictLookupNF(char *key, Object *obj)
   { return dict->lookupNF(key, obj); }
 
-inline const char *Object::dictGetKey(int i)
+inline char *Object::dictGetKey(int i)
   { return dict->getKey(i); }
 
 inline Object *Object::dictGetVal(int i, Object *obj)
@@ -267,10 +266,10 @@ inline Object *Object::dictGetValNF(int i, Object *obj)
 
 #include "Stream.h"
 
-inline GBool Object::streamIs(const char *dictType)
+inline GBool Object::streamIs(char *dictType)
   { return stream->getDict()->is(dictType); }
 
-inline GBool Object::isStream(const char *dictType)
+inline GBool Object::isStream(char *dictType)
   { return type == objStream && streamIs(dictType); }
 
 inline void Object::streamReset()
index b90636116b8f548fa8454c0c71cd5b1d51089128..014b2aef65fec18c6167cbd8b9fb61334de104f9 100644 (file)
 // OutputDev
 //------------------------------------------------------------------------
 
-void OutputDev::setDefaultCTM(double *ctm1) {
+void OutputDev::setDefaultCTM(double *ctm) {
   int i;
   double det;
 
-  for (i = 0; i < 6; ++i)
-    ctm[i] = ctm1[i];
-  det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
-  ictm[0] = ctm[3] * det;
-  ictm[1] = -ctm[1] * det;
-  ictm[2] = -ctm[2] * det;
-  ictm[3] = ctm[0] * det;
-  ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
-  ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+  for (i = 0; i < 6; ++i) {
+    defCTM[i] = ctm[i];
+  }
+  det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]);
+  defICTM[0] = defCTM[3] * det;
+  defICTM[1] = -defCTM[1] * det;
+  defICTM[2] = -defCTM[2] * det;
+  defICTM[3] = defCTM[0] * det;
+  defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det;
+  defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det;
 }
 
 void OutputDev::cvtDevToUser(int dx, int dy, double *ux, double *uy) {
-  *ux = ictm[0] * dx + ictm[2] * dy + ictm[4];
-  *uy = ictm[1] * dx + ictm[3] * dy + ictm[5];
+  *ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4];
+  *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5];
 }
 
 void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) {
-  *dx = (int)(ctm[0] * ux + ctm[2] * uy + ctm[4] + 0.5);
-  *dy = (int)(ctm[1] * ux + ctm[3] * uy + ctm[5] + 0.5);
+  *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5);
+  *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5);
 }
 
 void OutputDev::updateAll(GfxState *state) {
@@ -62,9 +63,6 @@ void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
                              GBool inlineImg) {
   int i, j;
 
-  (void)state;
-  (void)invert;
-
   if (inlineImg) {
     str->reset();
     j = height * ((width + 7) / 8);
@@ -75,11 +73,9 @@ void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
 
 void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
                          int width, int height, GfxImageColorMap *colorMap,
-                         GBool inlineImg) {
+                         int *maskColors, GBool inlineImg) {
   int i, j;
 
-  (void)state;
-
   if (inlineImg) {
     str->reset();
     j = height * ((width * colorMap->getNumPixelComps() *
index 7128183faea808cc01a09ce9286b8147eb896a46..c332fa933fd2709d87208495f501a82ab6655b72 100644 (file)
@@ -48,10 +48,10 @@ public:
   //----- initialization and control
 
   // Set default transform matrix.
-  virtual void setDefaultCTM(double *ctm1);
+  virtual void setDefaultCTM(double *ctm);
 
   // Start a page.
-  virtual void startPage(int, GfxState *) {}
+  virtual void startPage(int pageNum, GfxState *state) {}
 
   // End a page.
   virtual void endPage() {}
@@ -66,56 +66,56 @@ public:
   virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
 
   //----- link borders
-  virtual void drawLink(Link *, Catalog *) {}
+  virtual void drawLink(Link *link, Catalog *catalog) {}
 
   //----- save/restore graphics state
-  virtual void saveState(GfxState *) {}
-  virtual void restoreState(GfxState *) {}
+  virtual void saveState(GfxState *state) {}
+  virtual void restoreState(GfxState *state) {}
 
   //----- update graphics state
   virtual void updateAll(GfxState *state);
-  virtual void updateCTM(GfxState *, double, double,
-                        double, double, double, double) {}
-  virtual void updateLineDash(GfxState *) {}
-  virtual void updateFlatness(GfxState *) {}
-  virtual void updateLineJoin(GfxState *) {}
-  virtual void updateLineCap(GfxState *) {}
-  virtual void updateMiterLimit(GfxState *) {}
-  virtual void updateLineWidth(GfxState *) {}
-  virtual void updateFillColor(GfxState *) {}
-  virtual void updateStrokeColor(GfxState *) {}
-  virtual void updateFillOpacity(GfxState *) {}
-  virtual void updateStrokeOpacity(GfxState *) {}
-
-  //----- update text 
-  virtual void updateFont(GfxState *) {}
-  virtual void updateTextMat(GfxState *) {}
-  virtual void updateCharSpace(GfxState *) {}
-  virtual void updateRender(GfxState *) {}
-  virtual void updateRise(GfxState *) {}
-  virtual void updateWordSpace(GfxState *) {}
-  virtual void updateHorizScaling(GfxState *) {}
-  virtual void updateTextPos(GfxState *) {}
-  virtual void updateTextShift(GfxState *, double) {}
+  virtual void updateCTM(GfxState *state, double m11, double m12,
+                        double m21, double m22, double m31, double m32) {}
+  virtual void updateLineDash(GfxState *state) {}
+  virtual void updateFlatness(GfxState *state) {}
+  virtual void updateLineJoin(GfxState *state) {}
+  virtual void updateLineCap(GfxState *state) {}
+  virtual void updateMiterLimit(GfxState *state) {}
+  virtual void updateLineWidth(GfxState *state) {}
+  virtual void updateFillColor(GfxState *state) {}
+  virtual void updateStrokeColor(GfxState *state) {}
+  virtual void updateFillOpacity(GfxState *state) {}
+  virtual void updateStrokeOpacity(GfxState *state) {}
+
+  //----- update text state
+  virtual void updateFont(GfxState *state) {}
+  virtual void updateTextMat(GfxState *state) {}
+  virtual void updateCharSpace(GfxState *state) {}
+  virtual void updateRender(GfxState *state) {}
+  virtual void updateRise(GfxState *state) {}
+  virtual void updateWordSpace(GfxState *state) {}
+  virtual void updateHorizScaling(GfxState *state) {}
+  virtual void updateTextPos(GfxState *state) {}
+  virtual void updateTextShift(GfxState *state, double shift) {}
 
   //----- path painting
-  virtual void stroke(GfxState *) {}
-  virtual void fill(GfxState *) {}
-  virtual void eoFill(GfxState *) {}
+  virtual void stroke(GfxState *state) {}
+  virtual void fill(GfxState *state) {}
+  virtual void eoFill(GfxState *state) {}
 
   //----- path clipping
-  virtual void clip(GfxState *) {}
-  virtual void eoClip(GfxState *) {}
+  virtual void clip(GfxState *state) {}
+  virtual void eoClip(GfxState *state) {}
 
   //----- text drawing
-  virtual void beginString(GfxState *, GString *) {}
-  virtual void endString(GfxState *) {}
-  virtual void drawChar(GfxState *, double, double,
-                       double, double, Guchar) {}
-  virtual void drawChar16(GfxState *, double, double,
-                         double, double, int) {}
-  virtual void drawString(GfxState *, GString *) {}
-  virtual void drawString16(GfxState *, GString *) {}
+  virtual void beginString(GfxState *state, GString *s) {}
+  virtual void endString(GfxState *state) {}
+  virtual void drawChar(GfxState *state, double x, double y,
+                       double dx, double dy, Guchar c) {}
+  virtual void drawChar16(GfxState *state, double x, double y,
+                         double dx, double dy, int c) {}
+  virtual void drawString(GfxState *state, GString *s) {}
+  virtual void drawString16(GfxState *state, GString *s) {}
 
   //----- image drawing
   virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
@@ -123,7 +123,7 @@ public:
                             GBool inlineImg);
   virtual void drawImage(GfxState *state, Object *ref, Stream *str,
                         int width, int height, GfxImageColorMap *colorMap,
-                        GBool inlineImg);
+                        int *maskColors, GBool inlineImg);
 
 #if OPI_SUPPORT
   //----- OPI functions
@@ -133,8 +133,8 @@ public:
 
 private:
 
-  double ctm[6];               // coordinate transform matrix
-  double ictm[6];              // inverse CTM
+  double defCTM[6];            // default coordinate transform matrix
+  double defICTM[6];           // inverse of default CTM
 };
 
 #endif
index b10410e540689ebde8ffccca5df9adef76617dfe..ae04280543101010ca0e0d43795cdfe863a40cae 100644 (file)
@@ -37,7 +37,8 @@
 // PDFDoc
 //------------------------------------------------------------------------
 
-PDFDoc::PDFDoc(GString *fileName1, GString *userPassword) {
+PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
+              GString *userPassword, GBool printCommandsA) {
   Object obj;
   GString *fileName2;
 
@@ -48,9 +49,10 @@ PDFDoc::PDFDoc(GString *fileName1, GString *userPassword) {
   xref = NULL;
   catalog = NULL;
   links = NULL;
+  printCommands = printCommandsA;
 
   // try to open file
-  fileName = fileName1;
+  fileName = fileNameA;
   fileName2 = NULL;
 #ifdef VMS
   if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) {
@@ -77,36 +79,35 @@ PDFDoc::PDFDoc(GString *fileName1, GString *userPassword) {
   obj.initNull();
   str = new FileStream(file, 0, -1, &obj);
 
-  ok = setup(userPassword);
+  ok = setup(ownerPassword, userPassword);
 }
 
-PDFDoc::PDFDoc(BaseStream *nstr, GString *userPassword) {
+PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
+              GString *userPassword, GBool printCommandsA) {
   ok = gFalse;
   fileName = NULL;
   file = NULL;
-  str = nstr;
+  str = strA;
   xref = NULL;
   catalog = NULL;
   links = NULL;
-  ok = setup(userPassword);
+  printCommands = printCommandsA;
+  ok = setup(ownerPassword, userPassword);
 }
 
-GBool PDFDoc::setup(GString *userPassword) {
-  Object catObj;
-
+GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
   // check header
   checkHeader();
 
   // read xref table
-  xref = new XRef(str, userPassword);
+  xref = new XRef(str, ownerPassword, userPassword);
   if (!xref->isOk()) {
     error(-1, "Couldn't read xref table");
     return gFalse;
   }
 
   // read catalog
-  catalog = new Catalog(xref->getCatalog(&catObj));
-  catObj.free();
+  catalog = new Catalog(xref, printCommands);
   if (!catalog->isOk()) {
     error(-1, "Couldn't read page catalog");
     return gFalse;
@@ -203,8 +204,8 @@ GBool PDFDoc::isLinearized() {
 
   lin = gFalse;
   obj1.initNull();
-  parser = new Parser(new Lexer(str->makeSubStream(str->getStart(),
-                                                  -1, &obj1)));
+  parser = new Parser(xref, new Lexer(xref, str->makeSubStream(str->getStart(),
+                                                              -1, &obj1)));
   parser->getObj(&obj1);
   parser->getObj(&obj2);
   parser->getObj(&obj3);
@@ -248,4 +249,3 @@ void PDFDoc::getLinks(Page *page) {
   links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
   obj.free();
 }
-
index e679db9795edec920d234882c4ce902da48b732f..c693e991a18e7b444a5e768070371fd17db2d78e 100644 (file)
 #endif
 
 #include <stdio.h>
+#include "XRef.h"
 #include "Link.h"
 #include "Catalog.h"
 #include "Page.h"
 
 class GString;
 class BaseStream;
-class XRef;
 class OutputDev;
 class Links;
 class LinkAction;
@@ -33,8 +33,10 @@ class LinkDest;
 class PDFDoc {
 public:
 
-  PDFDoc(GString *fileName1, GString *userPassword = NULL);
-  PDFDoc(BaseStream *str, GString *userPassword = NULL);
+  PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
+        GString *userPassword = NULL, GBool printCommandsA = gFalse);
+  PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
+        GString *userPassword = NULL, GBool printCommandsA = gFalse);
   ~PDFDoc();
 
   // Was PDF document successfully opened?
@@ -43,6 +45,9 @@ public:
   // Get file name.
   GString *getFileName() { return fileName; }
 
+  // Get the xref table.
+  XRef *getXRef() { return xref; }
+
   // Get catalog.
   Catalog *getCatalog() { return catalog; }
 
@@ -88,10 +93,14 @@ public:
   GBool isEncrypted() { return xref->isEncrypted(); }
 
   // Check various permissions.
-  GBool okToPrint() { return xref->okToPrint(); }
-  GBool okToChange() { return xref->okToChange(); }
-  GBool okToCopy() { return xref->okToCopy(); }
-  GBool okToAddNotes() { return xref->okToAddNotes(); }
+  GBool okToPrint(GBool ignoreOwnerPW = gFalse)
+    { return xref->okToPrint(ignoreOwnerPW); }
+  GBool okToChange(GBool ignoreOwnerPW = gFalse)
+    { return xref->okToChange(ignoreOwnerPW); }
+  GBool okToCopy(GBool ignoreOwnerPW = gFalse)
+    { return xref->okToCopy(ignoreOwnerPW); }
+  GBool okToAddNotes(GBool ignoreOwnerPW = gFalse)
+    { return xref->okToAddNotes(ignoreOwnerPW); }
 
   // Is this document linearized?
   GBool isLinearized();
@@ -107,7 +116,7 @@ public:
 
 private:
 
-  GBool setup(GString *userPassword);
+  GBool setup(GString *ownerPassword, GString *userPassword);
   void checkHeader();
   void getLinks(Page *page);
 
@@ -118,6 +127,7 @@ private:
   XRef *xref;
   Catalog *catalog;
   Links *links;
+  GBool printCommands;
 
   GBool ok;
 };
index 84e8ca7c720d2ab98c40b7ea097084bc8a8f2b82..b62a23d24ba50ed33ac560a0a9f933fe724913ff 100644 (file)
@@ -11,7 +11,6 @@
 #endif
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <stddef.h>
 #include <stdarg.h>
 #include <signal.h>
@@ -20,6 +19,7 @@
 #include "config.h"
 #include "Object.h"
 #include "Error.h"
+#include "Function.h"
 #include "GfxState.h"
 #include "GfxFont.h"
 #include "FontFile.h"
 #include "ICSupport.h"
 #endif
 
-//------------------------------------------------------------------------
-// Parameters
-//------------------------------------------------------------------------
-
-// Generate Level 1 PostScript?
-GBool psOutLevel1 = gFalse;
-
-// Generate Level 1 separable PostScript?
-GBool psOutLevel1Sep = gFalse;
-
-// Generate Encapsulated PostScript?
-GBool psOutEPS = gFalse;
-
-#if OPI_SUPPORT
-// Generate OPI comments?
-GBool psOutOPI = gFalse;
-#endif
-
-int paperWidth = defPaperWidth;
-int paperHeight = defPaperHeight;
-
 //------------------------------------------------------------------------
 // PostScript prolog and setup
 //------------------------------------------------------------------------
 
-static const char *prolog[] = {
+static char *prolog[] = {
   "/xpdf 75 dict def xpdf begin",
   "% PDF special state",
   "/pdfDictSize 14 def",
@@ -94,19 +73,83 @@ static const char *prolog[] = {
   "  /pdfHorizScaling 1 def",
   "} def",
   "/pdfEndPage { end } def",
+  "% separation convention operators",
+  "/findcmykcustomcolor where {",
+  "  pop",
+  "}{",
+  "  /findcmykcustomcolor { 5 array astore } def",
+  "} ifelse",
+  "/setcustomcolor where {",
+  "  pop",
+  "}{",
+  "  /setcustomcolor {",
+  "    exch",
+  "    [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
+  "      0 4 getinterval cvx",
+  "      [ exch /dup load exch { mul exch dup } /forall load",
+  "        /pop load dup ] cvx",
+  "    ] setcolorspace setcolor",
+  "  } def",
+  "} ifelse",
+  "/customcolorimage where {",
+  "  pop",
+  "}{",
+  "  /customcolorimage {",
+  "    gsave",
+  "    [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
+  "      0 4 getinterval cvx",
+  "      [ exch /dup load exch { mul exch dup } /forall load",
+  "        /pop load dup ] cvx",
+  "    ] setcolorspace",
+  "    10 dict begin",
+  "      /ImageType 1 def",
+  "      /DataSource exch def",
+  "      /ImageMatrix exch def",
+  "      /BitsPerComponent exch def",
+  "      /Height exch def",
+  "      /Width exch def",
+  "      /Decode [1 0] def",
+  "    currentdict end",
+  "    image",
+  "    grestore",
+  "  } def",
+  "} ifelse",
+  "% PDF color state",
   "/sCol {",
   "  pdfLastStroke not {",
   "    pdfStroke aload length",
-  "    dup 1 eq { pop setgray }",
-  "      { 3 eq { setrgbcolor } { setcmykcolor } ifelse } ifelse",
+  "    dup 1 eq {",
+  "      pop setgray",
+  "    }{",
+  "      dup 3 eq {",
+  "        pop setrgbcolor",
+  "      }{",
+  "        4 eq {",
+  "          setcmykcolor",
+  "        }{",
+  "          findcmykcustomcolor exch setcustomcolor",
+  "        } ifelse",
+  "      } ifelse",
+  "    } ifelse",
   "    /pdfLastStroke true def /pdfLastFill false def",
   "  } if",
   "} def",
   "/fCol {",
   "  pdfLastFill not {",
   "    pdfFill aload length",
-  "    dup 1 eq { pop setgray }",
-  "      { 3 eq { setrgbcolor } { setcmykcolor } ifelse } ifelse",
+  "    dup 1 eq {",
+  "      pop setgray",
+  "    }{",
+  "      dup 3 eq {",
+  "        pop setrgbcolor",
+  "      }{",
+  "        4 eq {",
+  "          setcmykcolor",
+  "        }{",
+  "          findcmykcustomcolor exch setcustomcolor",
+  "        } ifelse",
+  "      } ifelse",
+  "    } ifelse",
   "    /pdfLastFill true def /pdfLastStroke false def",
   "  } if",
   "} def",
@@ -145,6 +188,12 @@ static const char *prolog[] = {
   "     /pdfLastFill true def /pdfLastStroke false def } def",
   "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
   "     /pdfLastStroke true def /pdfLastFill false def } def",
+  "/ck { 6 copy 6 array astore /pdfFill exch def",
+  "      findcmykcustomcolor exch setcustomcolor",
+  "      /pdfLastFill true def /pdfLastStroke false def } def",
+  "/CK { 6 copy 6 array astore /pdfStroke exch def",
+  "      findcmykcustomcolor exch setcustomcolor",
+  "      /pdfLastStroke true def /pdfLastFill false def } def",
   "% path segment operators",
   "/m { moveto } def",
   "/l { lineto } def",
@@ -178,13 +227,10 @@ static const char *prolog[] = {
   "      pdfFontSize mul pdfHorizScaling mul",
   "      1 index stringwidth pdfTextMat idtransform pop",
   "      sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
-  "      pdfWordSpacing 0 pdfTextMat dtransform 32",
-  "      4 3 roll pdfCharSpacing add 0 pdfTextMat dtransform",
-#if 0 /* temporary fix until we can figure out why the width is wrong */
+  "      pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
+  "      4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
+  "      pdfTextMat dtransform",
   "      6 5 roll awidthshow",
-#else
-  "      6 5 roll show pop pop pop pop pop",
-#endif /* 0 */
   "      0 pdfTextRise neg pdfTextMat dtransform rmoveto } def",
   "/TJm { pdfFontSize 0.001 mul mul neg 0",
   "       pdfTextMat dtransform rmoveto } def",
@@ -216,6 +262,20 @@ static const char *prolog[] = {
   "    not { pop exit } if",
   "    (%-EOD-) eq { exit } if } loop",
   "} def",
+  "/pdfImSep {",
+  "  findcmykcustomcolor exch",
+  "  dup /Width get /pdfImBuf1 exch string def",
+  "  begin Width Height BitsPerComponent ImageMatrix DataSource end",
+  "  /pdfImData exch def",
+  "  { pdfImData pdfImBuf1 readstring pop",
+  "    0 1 2 index length 1 sub {",
+  "      1 index exch 2 copy get 255 exch sub put",
+  "    } for }",
+  "  6 5 roll customcolorimage",
+  "  { currentfile pdfImBuf readline",
+  "    not { pop exit } if",
+  "    (%-EOD-) eq { exit } if } loop",
+  "} def",
   "/pdfImM {",
   "  fCol imagemask",
   "  { currentfile pdfImBuf readline",
@@ -231,19 +291,19 @@ static const char *prolog[] = {
 //------------------------------------------------------------------------
 
 struct PSFont {
-  const char *name;            // PDF name
-  const char *psName;          // PostScript name
+  char *name;                  // PDF name
+  char *psName;                        // PostScript name
 };
 
 struct PSSubstFont {
-  const char *psName;          // PostScript name
+  char *psName;                        // PostScript name
   double mWidth;               // width of 'm' character
 };
 
 static PSFont psFonts[] = {
   {"Courier",               "Courier"},
   {"Courier-Bold",          "Courier-Bold"},
-  {"Courier-Oblique",       "Courier-Bold"},
+  {"Courier-Oblique",       "Courier-Oblique"},
   {"Courier-BoldOblique",   "Courier-BoldOblique"},
   {"Helvetica",             "Helvetica"},
   {"Helvetica-Bold",        "Helvetica-Bold"},
@@ -273,31 +333,87 @@ static PSSubstFont psSubstFonts[] = {
   {"Courier-BoldOblique",   0.600}
 };
 
+//------------------------------------------------------------------------
+// process colors
+//------------------------------------------------------------------------
+
+#define psProcessCyan     1
+#define psProcessMagenta  2
+#define psProcessYellow   4
+#define psProcessBlack    8
+#define psProcessCMYK    15
+
+//------------------------------------------------------------------------
+// PSOutCustomColor
+//------------------------------------------------------------------------
+
+class PSOutCustomColor {
+public:
+
+  PSOutCustomColor(double cA, double mA,
+                  double yA, double kA, GString *nameA);
+  ~PSOutCustomColor();
+
+  double c, m, y, k;
+  GString *name;
+  PSOutCustomColor *next;
+};
+
+PSOutCustomColor::PSOutCustomColor(double cA, double mA,
+                                  double yA, double kA, GString *nameA) {
+  c = cA;
+  m = mA;
+  y = yA;
+  k = kA;
+  name = nameA;
+  next = NULL;
+}
+
+PSOutCustomColor::~PSOutCustomColor() {
+  delete name;
+}
+
 //------------------------------------------------------------------------
 // PSOutputDev
 //------------------------------------------------------------------------
 
-PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
+extern "C" {
+typedef void (*SignalFunc)(int);
+}
+
+PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
                         int firstPage, int lastPage,
-                        GBool embedType11, GBool doForm1) {
+                        PSOutLevel levelA, PSOutMode modeA, GBool doOPIA,
+                        GBool embedType1A, GBool embedTrueTypeA,
+                        int paperWidthA, int paperHeightA) {
   Page *page;
+  PDFRectangle *box;
   Dict *resDict;
   FormWidgets *formWidgets;
-  const char **p;
+  char **p;
   int pg;
   Object obj1, obj2;
   int i;
 
   // initialize
-  embedType1 = embedType11;
-  doForm = doForm1;
+  xref = xrefA;
+  level = levelA;
+  mode = modeA;
+  doOPI = doOPIA;
+  embedType1 = embedType1A;
+  embedTrueType = embedTrueTypeA;
+  paperWidth = paperWidthA;
+  paperHeight = paperHeightA;
   fontIDs = NULL;
   fontFileIDs = NULL;
   fontFileNames = NULL;
   embFontList = NULL;
   f = NULL;
-  if (doForm)
+  if (mode == psModeForm) {
     lastPage = firstPage;
+  }
+  processColors = 0;
+  customColors = NULL;
 
   // open file or pipe
   ok = gTrue;
@@ -308,7 +424,7 @@ PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
     fileType = psPipe;
 #ifdef HAVE_POPEN
 #ifndef WIN32
-    signal(SIGPIPE, SIG_IGN);
+    signal(SIGPIPE, (SignalFunc)SIG_IGN);
 #endif
     if (!(f = popen(fileName + 1, "w"))) {
       error(-1, "Couldn't run print command '%s'", fileName);
@@ -344,63 +460,70 @@ PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
   embFontList = new GString();
 
   // write header
-  if (doForm) {
-    writePS("%%!PS-Adobe-3.0 Resource-Form\n");
+  switch (mode) {
+  case psModePS:
+    writePS("%%!PS-Adobe-3.0\n");
     writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
     writePS("%%%%LanguageLevel: %d\n",
-           (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
-    if (psOutLevel1Sep) {
-      writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+           (level == psLevel1 || level == psLevel1Sep) ? 1 : 2);
+    if (level == psLevel1Sep || level == psLevel2Sep) {
+      writePS("%%%%DocumentProcessColors: (atend)\n");
+      writePS("%%%%DocumentCustomColors: (atend)\n");
     }
+    writePS("%%%%DocumentMedia: plain %d %d 0 () ()\n",
+           paperWidth, paperHeight);
+    writePS("%%%%Pages: %d\n", lastPage - firstPage + 1);
     writePS("%%%%EndComments\n");
-    page = catalog->getPage(firstPage);
-    writePS("32 dict dup begin\n");
-    writePS("/BBox [%d %d %d %d] def\n",
-           (int)page->getX1(), (int)page->getY1(),
-           (int)page->getX2(), (int)page->getY2());
-    writePS("/FormType 1 def\n");
-    writePS("/Matrix [1 0 0 1 0 0] def\n");
-  } else if (psOutEPS) {
+    writePS("%%%%BeginDefaults\n");
+    writePS("%%%%PageMedia: plain\n");
+    writePS("%%%%EndDefaults\n");
+    break;
+  case psModeEPS:
     writePS("%%!PS-Adobe-3.0 EPSF-3.0\n");
     writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
     writePS("%%%%LanguageLevel: %d\n",
-           (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
-    if (psOutLevel1Sep) {
-      writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+           (level == psLevel1 || level == psLevel1Sep) ? 1 : 2);
+    if (level == psLevel1Sep || level == psLevel2Sep) {
+      writePS("%%%%DocumentProcessColors: (atend)\n");
+      writePS("%%%%DocumentCustomColors: (atend)\n");
     }
     page = catalog->getPage(firstPage);
+    box = page->getBox();
     writePS("%%%%BoundingBox: %d %d %d %d\n",
-           (int)floor(page->getX1()), (int)floor(page->getY1()),
-           (int)ceil(page->getX2()), (int)ceil(page->getY2()));
-    if (floor(page->getX1()) != ceil(page->getX1()) ||
-       floor(page->getY1()) != ceil(page->getY1()) ||
-       floor(page->getX2()) != ceil(page->getX2()) ||
-       floor(page->getY2()) != ceil(page->getY2())) {
+           (int)floor(box->x1), (int)floor(box->y1),
+           (int)ceil(box->x2), (int)ceil(box->y2));
+    if (floor(box->x1) != ceil(box->x1) ||
+       floor(box->y1) != ceil(box->y1) ||
+       floor(box->x2) != ceil(box->x2) ||
+       floor(box->y2) != ceil(box->y2)) {
       writePS("%%%%HiResBoundingBox: %g %g %g %g\n",
-             page->getX1(), page->getY1(),
-             page->getX2(), page->getY2());
+             box->x1, box->y1, box->x2, box->y2);
     }
     writePS("%%%%DocumentSuppliedResources: (atend)\n");
     writePS("%%%%EndComments\n");
-  } else {
-    writePS("%%!PS-Adobe-3.0\n");
+    break;
+  case psModeForm:
+    writePS("%%!PS-Adobe-3.0 Resource-Form\n");
     writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
     writePS("%%%%LanguageLevel: %d\n",
-           (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
-    if (psOutLevel1Sep) {
-      writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+           (level == psLevel1 || level == psLevel1Sep) ? 1 : 2);
+    if (level == psLevel1Sep || level == psLevel2Sep) {
+      writePS("%%%%DocumentProcessColors: (atend)\n");
+      writePS("%%%%DocumentCustomColors: (atend)\n");
     }
-    writePS("%%%%DocumentMedia: plain %d %d 0 () ()\n",
-           paperWidth, paperHeight);
-    writePS("%%%%Pages: %d\n", lastPage - firstPage + 1);
     writePS("%%%%EndComments\n");
-    writePS("%%%%BeginDefaults\n");
-    writePS("%%%%PageMedia: plain\n");
-    writePS("%%%%EndDefaults\n");
+    page = catalog->getPage(firstPage);
+    box = page->getBox();
+    writePS("32 dict dup begin\n");
+    writePS("/BBox [%d %d %d %d] def\n",
+           (int)box->x1, (int)box->y1, (int)box->x2, (int)box->y2);
+    writePS("/FormType 1 def\n");
+    writePS("/Matrix [1 0 0 1 0 0] def\n");
+    break;
   }
 
   // write prolog
-  if (!doForm) {
+  if (mode != psModeForm) {
     writePS("%%%%BeginProlog\n");
   }
   writePS("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
@@ -408,13 +531,13 @@ PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
     writePS("%s\n", *p);
   }
   writePS("%%%%EndResource\n");
-  if (!doForm) {
+  if (mode != psModeForm) {
     writePS("%%%%EndProlog\n");
   }
 
   // set up fonts and images
   type3Warning = gFalse;
-  if (doForm) {
+  if (mode == psModeForm) {
     // swap the form and xpdf dicts
     writePS("xpdf end begin dup begin\n");
   } else {
@@ -426,7 +549,7 @@ PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
     if ((resDict = page->getResourceDict())) {
       setupResources(resDict);
     }
-    formWidgets = new FormWidgets(page->getAnnots(&obj1));
+    formWidgets = new FormWidgets(xref, page->getAnnots(&obj1));
     obj1.free();
     for (i = 0; i < formWidgets->getNumWidgets(); ++i) {
       if (formWidgets->getWidget(i)->getAppearance(&obj1)->isStream()) {
@@ -440,17 +563,14 @@ PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
     }
     delete formWidgets;
   }
-  if (!doForm) {
+  if (mode != psModeForm) {
 #if OPI_SUPPORT
-    if (psOutOPI) {
+    if (doOPI) {
       writePS("/opiMatrix matrix currentmatrix def\n");
     }
 #endif
-    if (!psOutEPS) {
-      if (!getenv("PPD") || !getenv("SOFTWARE")) {
-        // pdfSetup not used for CUPS filter...
-        writePS("%d %d pdfSetup\n", paperWidth, paperHeight);
-      }
+    if (mode != psModeEPS) {
+      writePS("%d %d pdfSetup\n", paperWidth, paperHeight);
     }
     writePS("%%%%EndSetup\n");
   }
@@ -466,20 +586,43 @@ PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
 }
 
 PSOutputDev::~PSOutputDev() {
+  PSOutCustomColor *cc;
   int i;
 
   if (f) {
-    if (doForm) {
+    if (mode == psModeForm) {
       writePS("/Foo exch /Form defineresource pop\n");
-    } else if (psOutEPS) {
+    } else  {
       writePS("%%%%Trailer\n");
       writePS("end\n");
       writePS("%%%%DocumentSuppliedResources:\n");
       writePS("%s", embFontList->getCString());
-      writePS("%%%%EOF\n");
-    } else {
-      writePS("%%%%Trailer\n");
-      writePS("end\n");
+      if (level == psLevel1Sep || level == psLevel2Sep) {
+         writePS("%%%%DocumentProcessColors:");
+         if (processColors & psProcessCyan) {
+          writePS(" Cyan");
+        }
+         if (processColors & psProcessMagenta) {
+          writePS(" Magenta");
+        }
+         if (processColors & psProcessYellow) {
+          writePS(" Yellow");
+        }
+         if (processColors & psProcessBlack) {
+          writePS(" Black");
+        }
+         writePS("\n");
+         writePS("%%%%DocumentCustomColors:");
+        for (cc = customColors; cc; cc = cc->next) {
+          writePS(" (%s)", cc->name->getCString());
+        }
+         writePS("\n");
+         writePS("%%%%CMYKCustomColor:\n");
+        for (cc = customColors; cc; cc = cc->next) {
+          writePS("%%%%+ %g %g %g %g (%s)\n",
+                  cc->c, cc->m, cc->y, cc->k, cc->name->getCString());
+        }
+      }
       writePS("%%%%EOF\n");
     }
     if (fileType == psFile) {
@@ -492,7 +635,7 @@ PSOutputDev::~PSOutputDev() {
     else if (fileType == psPipe) {
       pclose(f);
 #ifndef WIN32
-      signal(SIGPIPE, SIG_DFL);
+      signal(SIGPIPE, (SignalFunc)SIG_DFL);
 #endif
     }
 #endif
@@ -512,6 +655,11 @@ PSOutputDev::~PSOutputDev() {
     }
     gfree(fontFileNames);
   }
+  while (customColors) {
+    cc = customColors;
+    customColors = cc->next;
+    delete cc;
+  }
 }
 
 void PSOutputDev::setupResources(Dict *resDict) {
@@ -546,7 +694,7 @@ void PSOutputDev::setupFonts(Dict *resDict) {
 
   resDict->lookup("Font", &fontDict);
   if (fontDict.isDict()) {
-    gfxFontDict = new GfxFontDict(fontDict.getDict());
+    gfxFontDict = new GfxFontDict(xref, fontDict.getDict());
     for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
       font = gfxFontDict->getFont(i);
       setupFont(font);
@@ -559,8 +707,8 @@ void PSOutputDev::setupFonts(Dict *resDict) {
 void PSOutputDev::setupFont(GfxFont *font) {
   Ref fontFileID;
   GString *name;
-  const char *psName;
-  const char *charName;
+  char *psName;
+  char *charName;
   double xs, ys;
   GBool do16Bit;
   int code;
@@ -604,6 +752,13 @@ void PSOutputDev::setupFont(GfxFont *font) {
     psName = font->getEmbeddedFontName();
     setupEmbeddedType1CFont(font, &fontFileID, psName);
 
+  // check for embedded TrueType font
+  } else if (embedTrueType && font->getType() == fontTrueType &&
+            font->getEmbeddedFontID(&fontFileID)) {
+    psName = font->getEmbeddedFontName();
+    setupEmbeddedTrueTypeFont(font, &fontFileID, psName);
+
+  // check for Japanese font
   } else if (font->is16Bit() && font->getCharSet16() == font16AdobeJapan12) {
     psName = "Ryumin-Light-RKSJ";
     do16Bit = gTrue;
@@ -673,6 +828,11 @@ void PSOutputDev::setupFont(GfxFont *font) {
       writePS((i == 0) ? "[ " : "  ");
       for (j = 0; j < 8; ++j) {
        charName = font->getCharName(i+j);
+       // this is a kludge for broken PDF files that encode char 32
+       // as .notdef
+       if (i+j == 32 && charName && !strcmp(charName, ".notdef")) {
+         charName = "space";
+       }
        writePS("/%s", charName ? charName : ".notdef");
       }
       writePS((i == 256-8) ? "]\n" : "\n");
@@ -681,7 +841,7 @@ void PSOutputDev::setupFont(GfxFont *font) {
   }
 }
 
-void PSOutputDev::setupEmbeddedType1Font(Ref *id, const char *psName) {
+void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
   static char hexChar[17] = "0123456789abcdef";
   Object refObj, strObj, obj1, obj2;
   Dict *dict;
@@ -707,7 +867,7 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, const char *psName) {
 
   // get the font stream and info
   refObj.initRef(id->num, id->gen);
-  refObj.fetch(&strObj);
+  refObj.fetch(xref, &strObj);
   refObj.free();
   if (!strObj.isStream()) {
     error(-1, "Embedded font file object is not a stream");
@@ -731,12 +891,10 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, const char *psName) {
   obj2.free();
 
   // beginning comment
-  if (psOutEPS) {
-    writePS("%%%%BeginResource: font %s\n", psName);
-    embFontList->append("%%+ font ");
-    embFontList->append(psName);
-    embFontList->append("\n");
-  }
+  writePS("%%%%BeginResource: font %s\n", psName);
+  embFontList->append("%%+ font ");
+  embFontList->append(psName);
+  embFontList->append("\n");
 
   // copy ASCII portion of font
   strObj.streamReset();
@@ -792,9 +950,7 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, const char *psName) {
   writePS("cleartomark\n");
 
   // ending comment
-  if (psOutEPS) {
-    writePS("%%%%EndResource\n");
-  }
+  writePS("%%%%EndResource\n");
 
  err1:
   strObj.streamClose();
@@ -803,7 +959,7 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, const char *psName) {
 
 //~ This doesn't handle .pfb files or binary eexec data (which only
 //~ happens in pfb files?).
-void PSOutputDev::setupEmbeddedType1Font(GString *fileName, const char *psName) {
+void PSOutputDev::setupEmbeddedType1Font(GString *fileName, char *psName) {
   FILE *fontFile;
   int c;
   int i;
@@ -824,12 +980,10 @@ void PSOutputDev::setupEmbeddedType1Font(GString *fileName, const char *psName)
   fontFileNames[fontFileNameLen++] = fileName->copy();
 
   // beginning comment
-  if (psOutEPS) {
-    writePS("%%%%BeginResource: font %s\n", psName);
-    embFontList->append("%%+ font ");
-    embFontList->append(psName);
-    embFontList->append("\n");
-  }
+  writePS("%%%%BeginResource: font %s\n", psName);
+  embFontList->append("%%+ font ");
+  embFontList->append(psName);
+  embFontList->append("\n");
 
   // copy the font file
   if (!(fontFile = fopen(fileName->getCString(), "rb"))) {
@@ -841,14 +995,12 @@ void PSOutputDev::setupEmbeddedType1Font(GString *fileName, const char *psName)
   fclose(fontFile);
 
   // ending comment
-  if (psOutEPS) {
-    writePS("%%%%EndResource\n");
-  }
+  writePS("%%%%EndResource\n");
 }
 
 void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
-                                         const char *psName) {
-  const char *fontBuf;
+                                         char *psName) {
+  char *fontBuf;
   int fontLen;
   Type1CFontConverter *cvt;
   int i;
@@ -868,31 +1020,65 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
   fontFileIDs[fontFileIDLen++] = *id;
 
   // beginning comment
-  if (psOutEPS) {
-    writePS("%%%%BeginResource: font %s\n", psName);
-    embFontList->append("%%+ font ");
-    embFontList->append(psName);
-    embFontList->append("\n");
-  }
+  writePS("%%%%BeginResource: font %s\n", psName);
+  embFontList->append("%%+ font ");
+  embFontList->append(psName);
+  embFontList->append("\n");
 
   // convert it to a Type 1 font
-  fontBuf = font->readEmbFontFile(&fontLen);
+  fontBuf = font->readEmbFontFile(xref, &fontLen);
   cvt = new Type1CFontConverter(fontBuf, fontLen, f);
   cvt->convert();
   delete cvt;
-  gfree((void *)fontBuf);
+  gfree(fontBuf);
 
   // ending comment
-  if (psOutEPS) {
-    writePS("%%%%EndResource\n");
+  writePS("%%%%EndResource\n");
+}
+
+void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
+                                           char *psName) {
+  char *fontBuf;
+  int fontLen;
+  TrueTypeFontFile *ttFile;
+  int i;
+
+  // check if font is already embedded
+  for (i = 0; i < fontFileIDLen; ++i) {
+    if (fontFileIDs[i].num == id->num &&
+       fontFileIDs[i].gen == id->gen)
+      return;
   }
+
+  // add entry to fontFileIDs list
+  if (fontFileIDLen >= fontFileIDSize) {
+    fontFileIDSize += 64;
+    fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+  }
+  fontFileIDs[fontFileIDLen++] = *id;
+
+  // beginning comment
+  writePS("%%%%BeginResource: font %s\n", psName);
+  embFontList->append("%%+ font ");
+  embFontList->append(psName);
+  embFontList->append("\n");
+
+  // convert it to a Type 42 font
+  fontBuf = font->readEmbFontFile(xref, &fontLen);
+  ttFile = new TrueTypeFontFile(fontBuf, fontLen);
+  ttFile->convertToType42(psName, font->getEncoding(), f);
+  delete ttFile;
+  gfree(fontBuf);
+
+  // ending comment
+  writePS("%%%%EndResource\n");
 }
 
 void PSOutputDev::setupImages(Dict *resDict) {
   Object xObjDict, xObj, xObjRef, subtypeObj;
   int i;
 
-  if (!doForm) {
+  if (mode != psModeForm) {
     return;
   }
 
@@ -1006,24 +1192,9 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
 void PSOutputDev::startPage(int pageNum, GfxState *state) {
   int x1, y1, x2, y2, width, height, t;
 
-  if (doForm) {
-
-    writePS("/PaintProc {\n");
-    writePS("begin xpdf begin\n");
-    writePS("pdfStartPage\n");
-    tx = ty = 0;
-    xScale = yScale = 1;
-    landscape = gFalse;
-
-  } else if (psOutEPS) {
-
-    writePS("pdfStartPage\n");
-    tx = ty = 0;
-    xScale = yScale = 1;
-    landscape = gFalse;
-
-  } else {
+  switch (mode) {
 
+  case psModePS:
     writePS("%%%%Page: %d %d\n", pageNum, seqPage);
     writePS("%%%%BeginPageSetup\n");
 
@@ -1073,11 +1244,28 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
 
     writePS("%%%%EndPageSetup\n");
     ++seqPage;
+    break;
+
+  case psModeEPS:
+    writePS("pdfStartPage\n");
+    tx = ty = 0;
+    xScale = yScale = 1;
+    landscape = gFalse;
+    break;
+
+  case psModeForm:
+    writePS("/PaintProc {\n");
+    writePS("begin xpdf begin\n");
+    writePS("pdfStartPage\n");
+    tx = ty = 0;
+    xScale = yScale = 1;
+    landscape = gFalse;
+    break;
   }
 }
 
 void PSOutputDev::endPage() {
-  if (doForm) {
+  if (mode == psModeForm) {
     writePS("pdfEndPage\n");
     writePS("end end\n");
     writePS("} def\n");
@@ -1090,21 +1278,15 @@ void PSOutputDev::endPage() {
 }
 
 void PSOutputDev::saveState(GfxState *state) {
-  (void)state;
-
   writePS("q\n");
 }
 
 void PSOutputDev::restoreState(GfxState *state) {
-  (void)state;
-
   writePS("Q\n");
 }
 
 void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
                            double m21, double m22, double m31, double m32) {
-  (void)state;
-
   writePS("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32);
 }
 
@@ -1141,39 +1323,134 @@ void PSOutputDev::updateLineWidth(GfxState *state) {
 }
 
 void PSOutputDev::updateFillColor(GfxState *state) {
+  GfxColor color;
+  double gray;
   GfxRGB rgb;
   GfxCMYK cmyk;
+  GfxSeparationColorSpace *sepCS;
 
-  if (psOutLevel1Sep) {
+  switch (level) {
+  case psLevel1:
+    state->getFillGray(&gray);
+    writePS("%g g\n", gray);
+    break;
+  case psLevel1Sep:
     state->getFillCMYK(&cmyk);
     writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
-  } else {
-    state->getFillRGB(&rgb);
-    if (rgb.r == rgb.g && rgb.g == rgb.b) {
-      writePS("%g g\n", rgb.r);
+    break;
+  case psLevel2:
+    if (state->getFillColorSpace()->getMode() == csDeviceCMYK) {
+      state->getFillCMYK(&cmyk);
+      writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+    } else {
+      state->getFillRGB(&rgb);
+      if (rgb.r == rgb.g && rgb.g == rgb.b) {
+       writePS("%g g\n", rgb.r);
+      } else {
+       writePS("%g %g %g rg\n", rgb.r, rgb.g, rgb.b);
+      }
+    }
+    break;
+  case psLevel2Sep:
+    if (state->getFillColorSpace()->getMode() == csSeparation) {
+      sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace();
+      color.c[0] = 1;
+      sepCS->getCMYK(&color, &cmyk);
+      writePS("%g %g %g %g %g (%s) ck\n",
+             state->getFillColor()->c[0],
+             cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+             sepCS->getName()->getCString());
+      addCustomColor(sepCS);
     } else {
-      writePS("%g %g %g rg\n", rgb.r, rgb.g, rgb.b);
+      state->getFillCMYK(&cmyk);
+      writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+      addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
     }
+    break;
   }
 }
 
 void PSOutputDev::updateStrokeColor(GfxState *state) {
+  GfxColor color;
+  double gray;
   GfxRGB rgb;
   GfxCMYK cmyk;
+  GfxSeparationColorSpace *sepCS;
 
-  if (psOutLevel1Sep) {
+  switch (level) {
+  case psLevel1:
+    state->getStrokeGray(&gray);
+    writePS("%g G\n", gray);
+    break;
+  case psLevel1Sep:
     state->getStrokeCMYK(&cmyk);
     writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
-  } else {
-    state->getStrokeRGB(&rgb);
-    if (rgb.r == rgb.g && rgb.g == rgb.b) {
-      writePS("%g G\n", rgb.r);
+    break;
+  case psLevel2:
+    if (state->getStrokeColorSpace()->getMode() == csDeviceCMYK) {
+      state->getStrokeCMYK(&cmyk);
+      writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
     } else {
-      writePS("%g %g %g RG\n", rgb.r, rgb.g, rgb.b);
+      state->getStrokeRGB(&rgb);
+      if (rgb.r == rgb.g && rgb.g == rgb.b) {
+       writePS("%g G\n", rgb.r);
+      } else {
+       writePS("%g %g %g RG\n", rgb.r, rgb.g, rgb.b);
+      }
     }
+    break;
+  case psLevel2Sep:
+    if (state->getStrokeColorSpace()->getMode() == csSeparation) {
+      sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace();
+      color.c[0] = 1;
+      sepCS->getCMYK(&color, &cmyk);
+      writePS("%g %g %g %g %g (%s) CK\n",
+             state->getStrokeColor()->c[0],
+             cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+             sepCS->getName()->getCString());
+      addCustomColor(sepCS);
+    } else {
+      state->getStrokeCMYK(&cmyk);
+      writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+      addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+    }
+    break;
   }
 }
 
+void PSOutputDev::addProcessColor(double c, double m, double y, double k) {
+  if (c > 0) {
+    processColors |= psProcessCyan;
+  }
+  if (m > 0) {
+    processColors |= psProcessMagenta;
+  }
+  if (y > 0) {
+    processColors |= psProcessYellow;
+  }
+  if (k > 0) {
+    processColors |= psProcessBlack;
+  }
+}
+
+void PSOutputDev::addCustomColor(GfxSeparationColorSpace *sepCS) {
+  PSOutCustomColor *cc;
+  GfxColor color;
+  GfxCMYK cmyk;
+
+  for (cc = customColors; cc; cc = cc->next) {
+    if (!cc->name->cmp(sepCS->getName())) {
+      return;
+    }
+  }
+  color.c[0] = 1;
+  sepCS->getCMYK(&color, &cmyk);
+  cc = new PSOutCustomColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+                           sepCS->getName()->copy());
+  cc->next = customColors;
+  customColors = cc;
+}
+
 void PSOutputDev::updateFont(GfxState *state) {
   if (state->getFont()) {
     writePS("/F%d_%d %g Tf\n",
@@ -1215,8 +1492,6 @@ void PSOutputDev::updateTextPos(GfxState *state) {
 }
 
 void PSOutputDev::updateTextShift(GfxState *state, double shift) {
-  (void)state;
-
   writePS("%g TJm\n", shift);
 }
 
@@ -1311,13 +1586,9 @@ void PSOutputDev::drawString(GfxState *state, GString *s) {
 }
 
 void PSOutputDev::drawString16(GfxState *state, GString *s) {
-#if defined(JAPANESE_SUPPORT) || defined(CHINESE_SUPPORT)
   int c1, c2;
   double w;
   int i;
-#else
-  (void)s;
-#endif /* JAPANESE_SUPPORT || CHINESE_SUPPORT */
 
   // check for invisible text -- this is used by Acrobat Capture
   if ((state->getRender() & 3) == 3)
@@ -1360,10 +1631,8 @@ void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
                                GBool inlineImg) {
   int len;
 
-  (void)state;
-
   len = height * ((width + 7) / 8);
-  if (psOutLevel1 || psOutLevel1Sep) {
+  if (level == psLevel1 || level == psLevel1Sep) {
     doImageL1(NULL, invert, inlineImg, str, width, height, len);
   } else {
     doImageL2(ref, NULL, invert, inlineImg, str, width, height, len);
@@ -1372,20 +1641,23 @@ void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
 
 void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
                            int width, int height, GfxImageColorMap *colorMap,
-                           GBool inlineImg) {
+                           int *maskColors, GBool inlineImg) {
   int len;
 
-  (void)state;
-
   len = height * ((width * colorMap->getNumPixelComps() *
                   colorMap->getBits() + 7) / 8);
-  if (psOutLevel1) {
+  switch (level) {
+  case psLevel1:
     doImageL1(colorMap, gFalse, inlineImg, str, width, height, len);
-  } else if (psOutLevel1Sep) {
+    break;
+  case psLevel1Sep:
     //~ handle indexed, separation, ... color spaces
     doImageL1Sep(colorMap, gFalse, inlineImg, str, width, height, len);
-  } else {
+    break;
+  case psLevel2:
+  case psLevel2Sep:
     doImageL2(ref, colorMap, gFalse, inlineImg, str, width, height, len);
+    break;
   }
 }
 
@@ -1397,9 +1669,6 @@ void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
   double gray;
   int x, y, i;
 
-  (void)inlineImg;
-  (void)len;
-
   // width, height, matrix, bits per component
   if (colorMap) {
     writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
@@ -1518,6 +1787,9 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
   GString *s;
   int n, numComps;
   GBool useRLE, useA85;
+  GfxSeparationColorSpace *sepCS;
+  GfxColor color;
+  GfxCMYK cmyk;
   int c;
   int i;
 
@@ -1528,7 +1800,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
   }
 
   // set up to use the array created by setupImages()
-  if (doForm && !inlineImg) {
+  if (mode == psModeForm && !inlineImg) {
     writePS("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
   }
 
@@ -1565,7 +1837,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
     writePS("  /Decode [%d %d]\n", invert ? 1 : 0, invert ? 0 : 1);
   }
 
-  if (doForm) {
+  if (mode == psModeForm) {
 
     if (inlineImg) {
 
@@ -1606,26 +1878,32 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
       useRLE = gFalse;
       useA85 = str->isBinary();
     }
-    if (useA85)
+    if (useA85) {
       writePS("    /ASCII85Decode filter\n");
-    if (useRLE)
+    }
+    if (useRLE) {
       writePS("    /RunLengthDecode filter\n");
-    else
+    } else {
       writePS("%s", s->getCString());
-    if (s)
+    }
+    if (s) {
       delete s;
+    }
 
     // cut off inline image streams at appropriate length
-    if (inlineImg)
+    if (inlineImg) {
       str = new FixedLengthEncoder(str, len);
-    else if (!useRLE)
+    } else if (!useRLE) {
       str = str->getBaseStream();
+    }
 
     // add RunLengthEncode and ASCII85 encode filters
-    if (useRLE)
+    if (useRLE) {
       str = new RunLengthEncoder(str);
-    if (useA85)
+    }
+    if (useA85) {
       str = new ASCII85Encoder(str);
+    }
 
     // end of image dictionary
     writePS(">>\n");
@@ -1650,12 +1928,22 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
       writePS("%%%%BeginData: %d Hex Bytes\n", n);
     }
 #endif
-    writePS("%s\n", colorMap ? "pdfIm" : "pdfImM");
+    if (level == psLevel2Sep && colorMap &&
+       colorMap->getColorSpace()->getMode() == csSeparation) {
+      color.c[0] = 1;
+      sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
+      sepCS->getCMYK(&color, &cmyk);
+      writePS("%g %g %g %g (%s) pdfImSep\n",
+             cmyk.c, cmyk.m, cmyk.y, cmyk.k, sepCS->getName()->getCString());
+    } else {
+      writePS("%s\n", colorMap ? "pdfIm" : "pdfImM");
+    }
 
     // copy the stream data
     str->reset();
-    while ((c = str->getChar()) != EOF)
+    while ((c = str->getChar()) != EOF) {
       fputc(c, f);
+    }
 
     // add newline and trailer to the end
     fputc('\n', f);
@@ -1667,8 +1955,9 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
 #endif
 
     // delete encoders
-    if (useRLE || useA85)
+    if (useRLE || useA85) {
       delete str;
+    }
   }
 }
 
@@ -1679,7 +1968,9 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
   GfxIndexedColorSpace *indexedCS;
   GfxSeparationColorSpace *separationCS;
   Guchar *lookup;
-  double x[1], y[gfxColorMaxComps];
+  double x[gfxColorMaxComps], y[gfxColorMaxComps];
+  GfxColor color;
+  GfxCMYK cmyk;
   int n, numComps;
   int i, j, k;
 
@@ -1687,6 +1978,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
 
   case csDeviceGray:
     writePS("/DeviceGray");
+    processColors |= psProcessBlack;
     break;
 
   case csCalGray:
@@ -1703,10 +1995,12 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
            calGrayCS->getBlackX(), calGrayCS->getBlackY(),
            calGrayCS->getBlackZ());
     writePS(">>]");
+    processColors |= psProcessBlack;
     break;
 
   case csDeviceRGB:
     writePS("/DeviceRGB");
+    processColors |= psProcessCMYK;
     break;
 
   case csCalRGB:
@@ -1728,10 +2022,12 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
            calRGBCS->getBlackX(), calRGBCS->getBlackY(),
            calRGBCS->getBlackZ());
     writePS(">>]");
+    processColors |= psProcessCMYK;
     break;
 
   case csDeviceCMYK:
     writePS("/DeviceCMYK");
+    processColors |= psProcessCMYK;
     break;
 
   case csLab:
@@ -1757,6 +2053,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
     writePS(" /BlackPoint [%g %g %g]\n",
            labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
     writePS(">>]");
+    processColors |= psProcessCMYK;
     break;
 
   case csICCBased:
@@ -1777,6 +2074,9 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
        for (k = 0; k < numComps; ++k) {
          writePS("%02x", lookup[j * numComps + k]);
        }
+       color.c[0] = j;
+       indexedCS->getCMYK(&color, &cmyk);
+       addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
       }
       writePS("\n");
     }
@@ -1788,7 +2088,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
     //~ separation color space, with the specified alternate color
     //~ space and tint transform
     separationCS = (GfxSeparationColorSpace *)colorSpace;
-    writePS(" [/Indexed ");
+    writePS("[/Indexed ");
     dumpColorSpaceL2(separationCS->getAlt());
     writePS(" 255 <\n");
     numComps = separationCS->getAlt()->getNComps();
@@ -1804,6 +2104,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
       writePS("\n");
     }
     writePS(">]");
+    addCustomColor(separationCS);
     break;
 
   case csDeviceN:
@@ -1822,7 +2123,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
 void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) {
   Object dict;
 
-  if (psOutOPI) {
+  if (doOPI) {
     opiDict->lookup("2.0", &dict);
     if (dict.isDict()) {
       opiBegin20(state, dict.getDict());
@@ -2184,7 +2485,7 @@ void PSOutputDev::opiTransform(GfxState *state, double x0, double y0,
 void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) {
   Object dict;
 
-  if (psOutOPI) {
+  if (doOPI) {
     opiDict->lookup("2.0", &dict);
     if (dict.isDict()) {
       writePS("%%%%EndIncludedImage\n");
index 62dce661158784ed5f7230887a3abbda7c2a1df3..81279be4acc2b5fc2e5eb3aac9cbd13d954a9129 100644 (file)
 class GfxPath;
 class GfxFont;
 class GfxColorSpace;
+class GfxSeparationColorSpace;
+class PSOutCustomColor;
 
 //------------------------------------------------------------------------
-// Parameters
+// PSOutputDev
 //------------------------------------------------------------------------
 
-// Generate Level 1 PostScript?
-extern GBool psOutLevel1;
-
-// Generate Level 1 separable PostScript?
-extern GBool psOutLevel1Sep;
-
-// Generate Encapsulated PostScript?
-extern GBool psOutEPS;
-
-#if OPI_SUPPORT
-// Generate OPI comments?
-extern GBool psOutOPI;
-#endif
-
-// Paper size.
-extern int paperWidth;
-extern int paperHeight;
+enum PSOutLevel {
+  psLevel1,
+  psLevel1Sep,
+  psLevel2,
+  psLevel2Sep
+};
 
-//------------------------------------------------------------------------
-// PSOutputDev
-//------------------------------------------------------------------------
+enum PSOutMode {
+  psModePS,
+  psModeEPS,
+  psModeForm
+};
 
 enum PSFileType {
   psFile,                      // write to file
@@ -58,9 +51,11 @@ class PSOutputDev: public OutputDev {
 public:
 
   // Open a PostScript output file, and write the prolog.
-  PSOutputDev(const char *fileName, Catalog *catalog,
+  PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
              int firstPage, int lastPage,
-             GBool embedType11, GBool doForm1);
+             PSOutLevel levelA, PSOutMode modeA, GBool doOPIA,
+             GBool embedType1A, GBool embedTrueTypeA,
+             int paperWidthA, int paperHeightA);
 
   // Destructor -- writes the trailer and closes the file.
   virtual ~PSOutputDev();
@@ -131,7 +126,7 @@ public:
                             GBool inlineImg);
   virtual void drawImage(GfxState *state, Object *ref, Stream *str,
                         int width, int height, GfxImageColorMap *colorMap,
-                        GBool inlineImg);
+                        int *maskColors, GBool inlineImg);
 
 #if OPI_SUPPORT
   //----- OPI functions
@@ -144,11 +139,14 @@ private:
   void setupResources(Dict *resDict);
   void setupFonts(Dict *resDict);
   void setupFont(GfxFont *font);
-  void setupEmbeddedType1Font(Ref *id, const char *psName);
-  void setupEmbeddedType1Font(GString *fileName, const char *psName);
-  void setupEmbeddedType1CFont(GfxFont *font, Ref *id, const char *psName);
+  void setupEmbeddedType1Font(Ref *id, char *psName);
+  void setupEmbeddedType1Font(GString *fileName, char *psName);
+  void setupEmbeddedType1CFont(GfxFont *font, Ref *id, char *psName);
+  void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, char *psName);
   void setupImages(Dict *resDict);
   void setupImage(Ref id, Stream *str);
+  void addProcessColor(double c, double m, double y, double k);
+  void addCustomColor(GfxSeparationColorSpace *sepCS);
   void doPath(GfxPath *path);
   void doImageL1(GfxImageColorMap *colorMap,
                 GBool invert, GBool inlineImg,
@@ -160,21 +158,30 @@ private:
                 GBool invert, GBool inlineImg,
                 Stream *str, int width, int height, int len);
   void dumpColorSpaceL2(GfxColorSpace *colorSpace);
+#if OPI_SUPPORT
   void opiBegin20(GfxState *state, Dict *dict);
   void opiBegin13(GfxState *state, Dict *dict);
   void opiTransform(GfxState *state, double x0, double y0,
                    double *x1, double *y1);
   GBool getFileSpec(Object *fileSpec, Object *fileName);
+#endif
   void writePS(const char *fmt, ...);
   void writePSString(GString *s);
 
+  PSOutLevel level;            // PostScript level (1, 2, separation)
+  PSOutMode mode;              // PostScript mode (PS, EPS, form)
+  GBool doOPI;                 // generate OPI comments?
   GBool embedType1;            // embed Type 1 fonts?
-  GBool doForm;                        // generate a form?
+  GBool embedTrueType;         // embed TrueType fonts?
+  int paperWidth;              // width of paper, in pts
+  int paperHeight;             // height of paper, in pts
 
   FILE *f;                     // PostScript file
   PSFileType fileType;         // file / pipe / stdout
   int seqPage;                 // current sequential page number
 
+  XRef *xref;                  // the xref table for this PDF file
+
   Ref *fontIDs;                        // list of object IDs of all used fonts
   int fontIDLen;               // number of entries in fontIDs array
   int fontIDSize;              // size of fontIDs array
@@ -191,6 +198,10 @@ private:
 
   GString *embFontList;                // resource comments for embedded fonts
 
+  int processColors;           // used process colors
+  PSOutCustomColor             // used custom colors
+    *customColors;
+
 #if OPI_SUPPORT
   int opi13Nest;               // nesting level of OPI 1.3 objects
   int opi20Nest;               // nesting level of OPI 2.0 objects
index c2ac6b190bdd2c1246d23ecb486ac8cf798dab72..975fcf1b6d83d6a0f412dd9c9ee7910dfea9c6ff 100644 (file)
 //------------------------------------------------------------------------
 
 PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
-  Object obj1, obj2;
+  Object obj1;
   double w, h;
 
   // get old/default values
   if (attrs) {
-    x1 = attrs->x1;
-    y1 = attrs->y1;
-    x2 = attrs->x2;
-    y2 = attrs->y2;
-    cropX1 = attrs->cropX1;
-    cropY1 = attrs->cropY1;
-    cropX2 = attrs->cropX2;
-    cropY2 = attrs->cropY2;
+    mediaBox = attrs->mediaBox;
+    cropBox = attrs->cropBox;
+    haveCropBox = attrs->haveCropBox;
     rotate = attrs->rotate;
     attrs->resources.copy(&resources);
   } else {
     // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
     // but some (non-compliant) PDF files don't specify a MediaBox
-    x1 = 0;
-    y1 = 0;
-    x2 = 612;
-    y2 = 792;
-    cropX1 = cropY1 = cropX2 = cropY2 = 0;
+    mediaBox.x1 = 0;
+    mediaBox.y1 = 0;
+    mediaBox.x2 = 612;
+    mediaBox.y2 = 792;
+    cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
+    haveCropBox = gFalse;
     rotate = 0;
     resources.initNull();
   }
 
   // media box
-  dict->lookup("MediaBox", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 4) {
-    obj1.arrayGet(0, &obj2);
-    if (obj2.isNum())
-      x1 = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    if (obj2.isNum())
-      y1 = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2, &obj2);
-    if (obj2.isNum())
-      x2 = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(3, &obj2);
-    if (obj2.isNum())
-      y2 = obj2.getNum();
-    obj2.free();
-  }
-  obj1.free();
+  readBox(dict, "MediaBox", &mediaBox);
 
   // crop box
-  dict->lookup("CropBox", &obj1);
-  if (obj1.isArray() && obj1.arrayGetLength() == 4) {
-    obj1.arrayGet(0, &obj2);
-    if (obj2.isNum())
-      cropX1 = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(1, &obj2);
-    if (obj2.isNum())
-      cropY1 = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(2, &obj2);
-    if (obj2.isNum())
-      cropX2 = obj2.getNum();
-    obj2.free();
-    obj1.arrayGet(3, &obj2);
-    if (obj2.isNum())
-      cropY2 = obj2.getNum();
-    obj2.free();
-  }
-  obj1.free();
+  cropBox = mediaBox;
+  haveCropBox = readBox(dict, "CropBox", &cropBox);
 
   // if the MediaBox is excessively larger than the CropBox,
   // just use the CropBox
   limitToCropBox = gFalse;
-  w = 0.25 * (cropX2 - cropX1);
-  h = 0.25 * (cropY2 - cropY1);
-  if (cropX2 > cropX1 &&
-      ((cropX1 - x1) + (x2 - cropX2) > w ||
-       (cropY1 - y1) + (y2 - cropY2) > h)) {
-    limitToCropBox = gTrue;
+  if (haveCropBox) {
+    w = 0.25 * (cropBox.x2 - cropBox.x1);
+    h = 0.25 * (cropBox.y2 - cropBox.y1);
+    if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w ||
+       (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) {
+      limitToCropBox = gTrue;
+    }
   }
 
+  // other boxes
+  bleedBox = cropBox;
+  readBox(dict, "BleedBox", &bleedBox);
+  trimBox = cropBox;
+  readBox(dict, "TrimBox", &trimBox);
+  artBox = cropBox;
+  readBox(dict, "ArtBox", &artBox);
+
   // rotate
   dict->lookup("Rotate", &obj1);
-  if (obj1.isInt())
+  if (obj1.isInt()) {
     rotate = obj1.getInt();
+  }
   obj1.free();
-  while (rotate < 0)
+  while (rotate < 0) {
     rotate += 360;
-  while (rotate >= 360)
+  }
+  while (rotate >= 360) {
     rotate -= 360;
+  }
 
   // resource dictionary
   dict->lookup("Resources", &obj1);
@@ -136,17 +107,66 @@ PageAttrs::~PageAttrs() {
   resources.free();
 }
 
+GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
+  PDFRectangle tmp;
+  Object obj1, obj2;
+  GBool ok;
+
+  dict->lookup(key, &obj1);
+  if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+    ok = gTrue;
+    obj1.arrayGet(0, &obj2);
+    if (obj2.isNum()) {
+      tmp.x1 = obj2.getNum();
+    } else {
+      ok = gFalse;
+    }
+    obj2.free();
+    obj1.arrayGet(1, &obj2);
+    if (obj2.isNum()) {
+      tmp.y1 = obj2.getNum();
+    } else {
+      ok = gFalse;
+    }
+    obj2.free();
+    obj1.arrayGet(2, &obj2);
+    if (obj2.isNum()) {
+      tmp.x2 = obj2.getNum();
+    } else {
+      ok = gFalse;
+    }
+    obj2.free();
+    obj1.arrayGet(3, &obj2);
+    if (obj2.isNum()) {
+      tmp.y2 = obj2.getNum();
+    } else {
+      ok = gFalse;
+    }
+    obj2.free();
+    if (ok) {
+      *box = tmp;
+    }
+  } else {
+    ok = gFalse;
+  }
+  obj1.free();
+  return ok;
+}
+
 //------------------------------------------------------------------------
 // Page
 //------------------------------------------------------------------------
 
-Page::Page(int num1, Dict *pageDict, PageAttrs *attrs1) {
+Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
+          GBool printCommandsA) {
 
   ok = gTrue;
-  num = num1;
+  xref = xrefA;
+  num = numA;
+  printCommands = printCommandsA;
 
   // get attributes
-  attrs = attrs1;
+  attrs = attrsA;
 
   // annotations
   pageDict->lookupNF("Annots", &annots);
@@ -185,18 +205,22 @@ Page::~Page() {
 void Page::display(OutputDev *out, double dpi, int rotate,
                   Links *links, Catalog *catalog) {
 #ifndef PDF_PARSER_ONLY
+  PDFRectangle *box, *cropBox;
   Gfx *gfx;
   Object obj;
   Link *link;
   int i;
   FormWidgets *formWidgets;
 
+  box = getBox();
+  cropBox = getCropBox();
+
   if (printCommands) {
     printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
-          getX1(), getY1(), getX2(), getY2());
+          box->x1, box->y1, box->x2, box->y2);
     if (isCropped()) {
       printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
-            getCropX1(), getCropY1(), getCropX2(), getCropY2());
+            cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
     }
     printf("***** Rotate = %d\n", attrs->getRotate());
   }
@@ -207,10 +231,9 @@ void Page::display(OutputDev *out, double dpi, int rotate,
   } else if (rotate < 0) {
     rotate += 360;
   }
-  gfx = new Gfx(out, num, attrs->getResourceDict(),
-               dpi, getX1(), getY1(), getX2(), getY2(), isCropped(),
-               getCropX1(), getCropY1(), getCropX2(), getCropY2(), rotate);
-  contents.fetch(&obj);
+  gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
+               dpi, box, isCropped(), cropBox, rotate, printCommands);
+  contents.fetch(xref, &obj);
   if (!obj.isNull()) {
     gfx->display(&obj);
   }
@@ -227,7 +250,7 @@ void Page::display(OutputDev *out, double dpi, int rotate,
 
   // draw AcroForm widgets
   //~ need to reset CTM ???
-  formWidgets = new FormWidgets(annots.fetch(&obj));
+  formWidgets = new FormWidgets(xref, annots.fetch(xref, &obj));
   obj.free();
   if (printCommands && formWidgets->getNumWidgets() > 0) {
     printf("***** AcroForm widgets\n");
index a144d2cfa7195f5cf3cf757d7257d20eecffa326..a40974cfc4a3c920ac6a4e2cf5fce84d5984f5fe 100644 (file)
@@ -21,6 +21,12 @@ class OutputDev;
 class Links;
 class Catalog;
 
+//------------------------------------------------------------------------
+
+struct PDFRectangle {
+  double x1, y1, x2, y2;
+};
+
 //------------------------------------------------------------------------
 // PageAttrs
 //------------------------------------------------------------------------
@@ -37,24 +43,28 @@ public:
   ~PageAttrs();
 
   // Accessors.
-  double getX1() { return limitToCropBox ? cropX1 : x1; }
-  double getY1() { return limitToCropBox ? cropY1 : y1; }
-  double getX2() { return limitToCropBox ? cropX2 : x2; }
-  double getY2() { return limitToCropBox ? cropY2 : y2; }
-  GBool isCropped() { return cropX2 > cropX1; }
-  double getCropX1() { return cropX1; }
-  double getCropY1() { return cropY1; }
-  double getCropX2() { return cropX2; }
-  double getCropY2() { return cropY2; }
+  PDFRectangle *getBox() { return limitToCropBox ? &cropBox : &mediaBox; }
+  PDFRectangle *getMediaBox() { return &mediaBox; }
+  PDFRectangle *getCropBox() { return &cropBox; }
+  GBool isCropped() { return haveCropBox; }
+  PDFRectangle *getBleedBox() { return &bleedBox; }
+  PDFRectangle *getTrimBox() { return &trimBox; }
+  PDFRectangle *getArtBox() { return &artBox; }
   int getRotate() { return rotate; }
   Dict *getResourceDict()
     { return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
 
 private:
 
-  double x1, y1, x2, y2;
-  double cropX1, cropY1, cropX2, cropY2;
+  GBool readBox(Dict *dict, char *key, PDFRectangle *box);
+
+  PDFRectangle mediaBox;
+  PDFRectangle cropBox;
+  GBool haveCropBox;
   GBool limitToCropBox;
+  PDFRectangle bleedBox;
+  PDFRectangle trimBox;
+  PDFRectangle artBox;
   int rotate;
   Object resources;
 };
@@ -67,7 +77,8 @@ class Page {
 public:
 
   // Constructor.
-  Page(int num1, Dict *pageDict, PageAttrs *attrs1);
+  Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
+       GBool printCommandsA);
 
   // Destructor.
   ~Page();
@@ -76,27 +87,25 @@ public:
   GBool isOk() { return ok; }
 
   // Get page parameters.
-  double getX1() { return attrs->getX1(); }
-  double getY1() { return attrs->getY1(); }
-  double getX2() { return attrs->getX2(); }
-  double getY2() { return attrs->getY2(); }
+  PDFRectangle *getBox() { return attrs->getBox(); }
+  PDFRectangle *getMediaBox() { return attrs->getMediaBox(); }
+  PDFRectangle *getCropBox() { return attrs->getCropBox(); }
   GBool isCropped() { return attrs->isCropped(); }
-  double getCropX1() { return attrs->getCropX1(); }
-  double getCropY1() { return attrs->getCropY1(); }
-  double getCropX2() { return attrs->getCropX2(); }
-  double getCropY2() { return attrs->getCropY2(); }
-  double getWidth() { return attrs->getX2() - attrs->getX1(); }
-  double getHeight() { return attrs->getY2() - attrs->getY1(); }
+  double getWidth() { return attrs->getBox()->x2 - attrs->getBox()->x1; }
+  double getHeight() { return attrs->getBox()->y2 - attrs->getBox()->y1; }
+  PDFRectangle *getBleedBox() { return attrs->getBleedBox(); }
+  PDFRectangle *getTrimBox() { return attrs->getTrimBox(); }
+  PDFRectangle *getArtBox() { return attrs->getArtBox(); }
   int getRotate() { return attrs->getRotate(); }
 
   // Get resource dictionary.
   Dict *getResourceDict() { return attrs->getResourceDict(); }
 
   // Get annotations array.
-  Object *getAnnots(Object *obj) { return annots.fetch(obj); }
+  Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
 
   // Get contents.
-  Object *getContents(Object *obj) { return contents.fetch(obj); }
+  Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
 
   // Display a page.
   void display(OutputDev *out, double dpi, int rotate,
@@ -104,10 +113,12 @@ public:
 
 private:
 
+  XRef *xref;                  // the xref table for this PDF file
   int num;                     // page number
   PageAttrs *attrs;            // page attributes
   Object annots;               // annotations array
   Object contents;             // page contents
+  GBool printCommands;         // print the drawing commands (for debugging)
   GBool ok;                    // true if page is valid
 };
 
index efed572435162f8238f474c9a9f3a62d4df5ddf1..8536da20d3c80d2f147e2083f20587b763f89102 100644 (file)
 #include "gfile.h"
 #include "Params.h"
 
-const char **fontPath = NULL;
+char **fontPath = NULL;
 static int fontPathLen, fontPathSize;
 
 DevFontMapEntry *devFontMap = NULL;
 static int devFontMapLen, devFontMapSize;
 
-void initParams(const char *configFile) {
+void initParams(char *userConfigFile, char *sysConfigFile) {
   GString *fileName;
   FILE *f;
   char buf[256];
   char *p, *q;
 
   // initialize font path and font map
-  fontPath = (const char **)gmalloc((fontPathSize = 8) * sizeof(const char *));
+  fontPath = (char **)gmalloc((fontPathSize = 8) * sizeof(char *));
   fontPath[fontPathLen = 0] = NULL;
   devFontMap = (DevFontMapEntry *)gmalloc((devFontMapSize = 8) *
                                          sizeof(DevFontMapEntry));
   devFontMap[devFontMapLen = 0].pdfFont = NULL;
 
   // read config file
-  fileName = appendToPath(getHomeDir(), configFile);
-  if ((f = fopen(fileName->getCString(), "r"))) {
+  fileName = appendToPath(getHomeDir(), userConfigFile);
+  if (!(f = fopen(fileName->getCString(), "r"))) {
+    f = fopen(sysConfigFile, "r");
+  }
+  if (f) {
     while (fgets(buf, sizeof(buf)-1, f)) {
       buf[sizeof(buf)-1] = '\0';
       p = strtok(buf, " \t\n\r");
       if (p && !strcmp(p, "fontpath")) {
        if (fontPathLen+1 >= fontPathSize)
-         fontPath = (const char **)
-             grealloc(fontPath, (fontPathSize += 8) * sizeof(const char *));
+         fontPath = (char **)
+             grealloc(fontPath, (fontPathSize += 8) * sizeof(char *));
        p = strtok(NULL, " \t\n\r");
        fontPath[fontPathLen++] = copyString(p);
       } else if (p && !strcmp(p, "fontmap")) {
@@ -74,14 +77,14 @@ void freeParams() {
 
   if (fontPath) {
     for (i = 0; i < fontPathLen; ++i)
-      gfree((void *)fontPath[i]);
-    gfree((void *)fontPath);
+      gfree(fontPath[i]);
+    gfree(fontPath);
   }
   if (devFontMap) {
     for (i = 0; i < devFontMapLen; ++i) {
-      gfree((void *)devFontMap[i].pdfFont);
-      gfree((void *)devFontMap[i].devFont);
+      gfree(devFontMap[i].pdfFont);
+      gfree(devFontMap[i].devFont);
     }
-    gfree((void *)devFontMap);
+    gfree(devFontMap);
   }
 }
index 2c5936a3f4b28a3ceb98df863d621e038e7d02bd..1d8ce382823f2c94cd1ab9db241aa840bc352922 100644 (file)
@@ -9,27 +9,28 @@
 #ifndef PARAMS_H
 #define PARAMS_H
 
-// Print commands as they're executed.
-extern GBool printCommands;
+#include "gtypes.h"
 
 // If this is set, error messages will be silently discarded.
 extern GBool errQuiet;
 
 // Font search path.
-extern const char **fontPath;
+extern char **fontPath;
 
 // Mapping from PDF font name to device font name.
 struct DevFontMapEntry {
-  const char *pdfFont;
-  const char *devFont;
+  char *pdfFont;
+  char *devFont;
 };
 extern DevFontMapEntry *devFontMap;
 
 //------------------------------------------------------------------------
 
-// Initialize font path and font map, and read configuration file,
-// if present.
-extern void initParams(const char *configFile);
+// Initialize font path and font map, and read configuration file.  If
+// <userConfigFile> exists, read it; else if <sysConfigFile> exists,
+// read it.  <userConfigFile> is relative to the user's home
+// directory; <sysConfigFile> should be an absolute path.
+extern void initParams(char *userConfigFile, char *sysConfigFile);
 
 // Free memory used for font path and font map.
 extern void freeParams();
index 6ad0c5a7816afa4cb55fd565dfa3f6073669af76..57ba05061eae0ea74abb2223c4969f1f75fa4913 100644 (file)
@@ -21,8 +21,9 @@
 #include "Decrypt.h"
 #endif
 
-Parser::Parser(Lexer *lexer1) {
-  lexer = lexer1;
+Parser::Parser(XRef *xrefA, Lexer *lexerA) {
+  xref = xrefA;
+  lexer = lexerA;
   inlineImg = 0;
   lexer->getObj(&buf1);
   lexer->getObj(&buf2);
@@ -36,7 +37,8 @@ Parser::~Parser() {
 
 #ifndef NO_DECRYPTION
 Object *Parser::getObj(Object *obj,
-                      Guchar *fileKey, int objNum, int objGen) {
+                      Guchar *fileKey, int keyLength,
+                      int objNum, int objGen) {
 #else
 Object *Parser::getObj(Object *obj) {
 #endif
@@ -63,10 +65,10 @@ Object *Parser::getObj(Object *obj) {
   // array
   if (buf1.isCmd("[")) {
     shift();
-    obj->initArray();
+    obj->initArray(xref);
     while (!buf1.isCmd("]") && !buf1.isEOF())
 #ifndef NO_DECRYPTION
-      obj->arrayAdd(getObj(&obj2, fileKey, objNum, objGen));
+      obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
 #else
       obj->arrayAdd(getObj(&obj2));
 #endif
@@ -77,7 +79,7 @@ Object *Parser::getObj(Object *obj) {
   // dictionary or stream
   } else if (buf1.isCmd("<<")) {
     shift();
-    obj->initDict();
+    obj->initDict(xref);
     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
       if (!buf1.isName()) {
        error(getPos(), "Dictionary key must be a name object");
@@ -88,7 +90,7 @@ Object *Parser::getObj(Object *obj) {
        if (buf1.isEOF() || buf1.isError())
          break;
 #ifndef NO_DECRYPTION
-       obj->dictAdd(key, getObj(&obj2, fileKey, objNum, objGen));
+       obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
 #else
        obj->dictAdd(key, getObj(&obj2));
 #endif
@@ -101,7 +103,8 @@ Object *Parser::getObj(Object *obj) {
        obj->initStream(str);
 #ifndef NO_DECRYPTION
        if (fileKey) {
-         str->getBaseStream()->doDecryption(fileKey, objNum, objGen);
+         str->getBaseStream()->doDecryption(fileKey, keyLength,
+                                            objNum, objGen);
        }
 #endif
       } else {
@@ -129,7 +132,7 @@ Object *Parser::getObj(Object *obj) {
   } else if (buf1.isString() && fileKey) {
     buf1.copy(obj);
     s = obj->getString();
-    decrypt = new Decrypt(fileKey, objNum, objGen);
+    decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
     for (i = 0, p = obj->getString()->getCString();
         i < s->getLength();
         ++i, ++p) {
index 6e6184499e8003608af38c14b2df965d604cc610..463d99827d81118321a3ef185c34630662442953 100644 (file)
@@ -23,7 +23,7 @@ class Parser {
 public:
 
   // Constructor.
-  Parser(Lexer *lexer1);
+  Parser(XRef *xrefA, Lexer *lexerA);
 
   // Destructor.
   ~Parser();
@@ -31,7 +31,8 @@ public:
   // Get the next object from the input stream.
 #ifndef NO_DECRYPTION
   Object *getObj(Object *obj,
-                Guchar *fileKey = NULL, int objNum = 0, int objGen = 0);
+                Guchar *fileKey = NULL, int keyLength = 0,
+                int objNum = 0, int objGen = 0);
 #else
   Object *getObj(Object *obj);
 #endif
@@ -44,6 +45,7 @@ public:
 
 private:
 
+  XRef *xref;                  // the xref table for this PDF file
   Lexer *lexer;                        // input stream
   Object buf1, buf2;           // next two tokens
   int inlineImg;               // set when inline image data is encountered
index f6bc9ebee0610be7b54862546d165cf10443a6e6..4835a82f827cf0e8248553b5be3e26599f01b831 100644 (file)
@@ -1,11 +1,11 @@
-xpdf
+Xpdf
 ====
 
-version 0.90
-99-aug-02
+version 0.93
+2001-oct-25
 
-The xpdf software and documentation are
-copyright 1996-1999 Derek B. Noonburg.
+The Xpdf software and documentation are
+copyright 1996-2001 Derek B. Noonburg.
 
 Email: derekn@foolabs.com
 WWW: http://www.foolabs.com/xpdf/
@@ -14,7 +14,7 @@ The PDF data structures, operators, and specification are
 copyright 1995 Adobe Systems Inc.
 
 
-What is xpdf?
+What is Xpdf?
 -------------
 
 Xpdf is a viewer for Portable Document Format (PDF) files.  (These are
@@ -24,8 +24,8 @@ OS/2.  The non-X components of the package (pdftops, pdftotext, etc.)
 also run on Win32 systems and should run on pretty much any system
 with a decent C++ compiler.
 
-Xpdf is designed to be small and efficient.  It does not use the Motif
-or Xt libraries.  It can use standard X fonts.
+Xpdf is designed to be small and efficient.  It can use Type 1,
+TrueType, or standard X fonts.
 
 
 Distribution
@@ -39,16 +39,16 @@ confusing, the basic idea is good.
 In order to cut down on the confusion a little bit, here are some
 informal clarifications:
 
-- I don't mind if you redistribute xpdf in source and/or binary form,
+- I don't mind if you redistribute Xpdf in source and/or binary form,
   as long as you include all of the documentation: README, man pages
   (or help files), and COPYING.  (Note that the README file contains a
   pointer to a web page with the source code.)
 
-- Selling a CD-ROM that contains xpdf is fine with me, as long as it
+- Selling a CD-ROM that contains Xpdf is fine with me, as long as it
   includes the documentation.  I wouldn't mind receiving a sample
   copy, but it's not necessary.
 
-- If you make useful changes to xpdf, please make the source code
+- If you make useful changes to Xpdf, please make the source code
   available -- post it on a web site, email it to me, whatever.
 
 If you're interested in commercial licensing, please contact me by
@@ -58,7 +58,7 @@ email: derekn@foolabs.com .
 Compatibility
 -------------
 
-Xpdf is developed and tested on a Linux 2.0 x86 system.
+Xpdf is developed and tested on a Linux 2.2 x86 system.
 
 In addition, it has been compiled by others on Solaris, AIX, HP-UX,
 SCO UnixWare, Digital Unix, Irix, and numerous other Unix
@@ -66,24 +66,24 @@ implementations, as well as VMS and OS/2.  It should work on pretty
 much any system which runs X11 and has Unix-like libraries.  You'll
 need ANSI C++ and C compilers to compile it.
 
-The non-X components of xpdf (pdftops, pdftotext, pdfinfo, pdfimages)
-can also be compiled on Win32 systems.  See the xpdf web page for
+The non-X components of Xpdf (pdftops, pdftotext, pdfinfo, pdfimages)
+can also be compiled on Win32 systems.  See the Xpdf web page for
 details.
 
-If you compiled xpdf for a system not listed on the web page, please
+If you compile Xpdf for a system not listed on the web page, please
 let me know.  If you're willing to make your binary available by ftp
-or on the web, I'll be happy to add a link from the xpdf web page.  I
+or on the web, I'll be happy to add a link from the Xpdf web page.  I
 have decided not to host any binaries I didn't compile myself (for
 disk space and support reasons).
 
-If you can't get xpdf to compile on your system, send me email and
+If you can't get Xpdf to compile on your system, send me email and
 I'll try to help.
 
-Xpdf has been ported to the Acorn, Amiga, and BeOS.  See the xpdf web
-page for links.
+Xpdf has been ported to the Acorn, Amiga, BeOS, and EPOC.  See the
+Xpdf web page for links.
 
 
-Getting xpdf
+Getting Xpdf
 ------------
 
 The latest version is available from:
@@ -102,7 +102,7 @@ list of people.  If you'd like to receive email notification of new
 versions, just let me know.
 
 
-Running xpdf
+Running Xpdf
 ------------
 
 To run xpdf, simply type:
@@ -168,7 +168,22 @@ For Japanese support, you will need a Japanese font of the form:
 
     -*-fixed-medium-r-normal-*-NN-*-*-*-*-*-jisx0208.1983-0
 
-and an X server that can handle 16-bit fonts.
+and an X server that can handle 16-bit fonts.  You can also set this
+font using the xpdf.japaneseFont resource.
+
+For Chinese GB (simplified Chinese) support, you will need a font of
+the form:
+
+    -*-fangsong ti-medium-r-normal-*-%s-*-*-*-*-*-gb2312.1980-0
+
+You can replace this font using the xpdf.chineseGBFont resource.
+
+For Chinese CNS (traditional Chinese) support, you will need a font of
+the form:
+
+    -*-fixed-medium-r-normal--*-%s-*-*-*-*-big5-0
+
+You can replace this font using the xpdf.chineseCNSFont resource.
 
 If compiled with t1lib support, xpdf will use t1lib to render embedded
 Type 1 and Type 1C fonts.  In addition, xpdf can be configured to use
@@ -191,6 +206,28 @@ example:
     xpdf.t1Symbol:               /usr/local/fonts/Symbol.pfa
     xpdf.t1ZapfDingbats:         /usr/local/fonts/ZapfDingbats.pfa
 
+Ghostscript comes with a set of free, high-quality Type 1 fonts,
+donated by URW++ Design and Development Incorporated.  The xpdf X
+resources needed for these fonts are:
+
+    xpdf.t1TimesRoman:           /usr/ghostscript/fonts/n021003l.pfb
+    xpdf.t1TimesItalic:          /usr/ghostscript/fonts/n021023l.pfb
+    xpdf.t1TimesBold:            /usr/ghostscript/fonts/n021004l.pfb
+    xpdf.t1TimesBoldItalic:      /usr/ghostscript/fonts/n021024l.pfb
+    xpdf.t1Helvetica:            /usr/ghostscript/fonts/n019003l.pfb
+    xpdf.t1HelveticaOblique:     /usr/ghostscript/fonts/n019023l.pfb
+    xpdf.t1HelveticaBold:        /usr/ghostscript/fonts/n019004l.pfb
+    xpdf.t1HelveticaBoldOblique: /usr/ghostscript/fonts/n019024l.pfb
+    xpdf.t1Courier:              /usr/ghostscript/fonts/n022003l.pfb
+    xpdf.t1CourierOblique:       /usr/ghostscript/fonts/n022023l.pfb
+    xpdf.t1CourierBold:          /usr/ghostscript/fonts/n022004l.pfb
+    xpdf.t1CourierBoldOblique:   /usr/ghostscript/fonts/n022024l.pfb
+    xpdf.t1Symbol:               /usr/ghostscript/fonts/s050000l.pfb
+    xpdf.t1ZapfDingbats:         /usr/ghostscript/fonts/d050000l.pfb
+
+You will obviously need to replace '/usr/ghostscript/fonts' with the
+appropriate path on your system.
+
 
 The Unisys LZW Patent
 ---------------------
@@ -198,13 +235,13 @@ The Unisys LZW Patent
 Nearly all PDF files include data which has been compressed with the
 LZW compression algorithm.  Unfortunately, LZW is covered by a
 software patent which is owned by Unisys Corporation.  Unisys refuses
-to license this patent for PDF-related use in software such as xpdf
+to license this patent for PDF-related use in software such as Xpdf
 which is released for free and which may be freely redistributed.
 (This is same algorithm which is used by GIF.  However, Unisys is not
 doing licensing for free PDF viwers in the same way as for free GIF
 viewers.)
 
-As a workaround, xpdf converts PDF-format LZW data to compress-format
+As a workaround, Xpdf converts PDF-format LZW data to compress-format
 LZW data.  (The standard UNIX compress utility also uses LZW, but with
 a slightly different file format.)  This conversion does *not*
 decompress the data; it simply converts it to a different file format.
@@ -221,7 +258,7 @@ For Unisys's slant on things (mostly regarding GIF), see
 an email address for feedback.
 
 
-Compiling xpdf
+Compiling Xpdf
 --------------
 
 See the separate file, INSTALL.
@@ -230,10 +267,9 @@ See the separate file, INSTALL.
 Bugs
 ----
 
-This release of xpdf should improve the situation with embedded
-fonts.  However, Type 3 and TrueType fonts are still not handled.
+Type 3 fonts are still not well supported by Xpdf.
 
-If you find a bug in xpdf, i.e., if it prints an error message,
+If you find a bug in Xpdf, i.e., if it prints an error message,
 crashes, or incorrectly displays a document, and you don't see that
 bug listed here, please send me email, with a pointer (URL, ftp site,
 etc.) to the PDF file.
@@ -245,7 +281,8 @@ Acknowledgments
 Thanks to:
 
 * Patrick Voigt for help with the remote server code.
-* Patrick Moreau and Martin P.J. Zinser for the VMS port.
+* Patrick Moreau, Martin P.J. Zinser, and David Mathog for the VMS
+  port.
 * David Boldt and Rick Rodgers for sample man pages.
 * Brendan Miller for the icon idea.
 * Olly Betts for help testing pdftotext.
@@ -255,40 +292,73 @@ Thanks to:
 * Leo Smiers for the decryption patches.
 * Rainer Menzner for creating t1lib, and for helping me adapt it to
   xpdf.
+* Pine Tree Systems A/S for funding the OPI and EPS support in
+  pdftops.
+* Easy Software Products for funding the "sh" operator support.
 
 
 References
 ----------
 
-Adobe Systems Inc., _Portable Document Format Reference Manual_.
-Addison-Wesley, 1993, ISBN 0-201-62628-4.
-[The printed manual for PDF version 1.0.]
+Adobe Systems Inc., _PDF Reference_, 2nd ed.
+Addison-Wesley, 2000, ISBN 0-201-61588-6.
+[The printed manual for PDF version 1.3.]
 
-Adobe Systems Inc., _Portable Document Format Reference Manual_,
-Version 1.3.  March 11, 1999.
-http://partners.adobe.com/asn/developer/PDFS/TN/PDFSPEC.PDF
-[Updated manual for PDF 1.3.]
+Adobe Systems Inc., _Portable Document Format: Changes from Version
+1.3 to 1.4_, Adobe Developer Support Technical Note #5409.
+June 11, 2001.
+http://partners.adobe.com/asn/developer/acrosdk/docs/filefmtspecs/PDF14Deltas.pdf
+[Updates for PDF 1.4.]
 
-Adobe Systems Inc., _PostScript Language Reference Manual_, 2nd ed.
-Addison-Wesley, 1990, ISBN 0-201-18127-4.
+Adobe Systems Inc., _PostScript Language Reference_, 3rd ed.
+Addison-Wesley, 1999, ISBN 0-201-37922-8.
 [The official PostScript manual.]
 
+Adobe Systems, Inc., _The Type 42 Font Format Specification_,
+Adobe Developer Support Technical Specification #5012.  1998.
+http://partners.adobe.com/asn/developer/pdfs/tn/5012.Type42_Spec.pdf
+[Type 42 is the format used to embed TrueType fonts in PostScript
+files.]
+
 Adobe Systems, Inc., _Adobe CMap and CIDFont Files Specification_,
 Adobe Developer Support Technical Specification #5014.  1995.
 http://www.adobe.com/supportservice/devrelations/PDFS/TN/5014.CIDFont_Spec.pdf
-[CMap file format needed for Japanese font support.]
+[CMap file format needed for Japanese and Chinese font support.]
 
 Adobe Systems, Inc., _Adobe-Japan1-2 Character Collection for
-CID-Keyed Fonts_ (Bitmap Character Image Version), Adobe Developer
-Support Technical Note #5078-b.  1994. 
-http://www.adobe.com/supportservice/devrelations/PDFS/TN/5078b.pdf
-[The complete Adobe Japanese character set.]
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5078.
+1994.
+http://partners.adobe.com/asn/developer/PDFS/TN/5078.CID_Glyph.pdf
+[The Adobe Japanese character set.]
+
+Adobe Systems, Inc., _Adobe-GB1-3 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5079.
+1998.
+http://partners.adobe.com/asn/developer/PDFS/TN/5079.GB_CharColl.pdf
+[The Adobe Chinese GB character set.]
+
+Adobe Systems, Inc., _Adobe-CNS1-3 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5080.
+2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5080.CNS_CharColl.pdf
+[The Adobe Chinese CNS character set.]
 
 Adobe Systems Inc., _Supporting the DCT Filters in PostScript Level
 2_, Adobe Developer Support Technical Note #5116.  1992.
 http://www.adobe.com/supportservice/devrelations/PDFS/TN/5116.PS2_DCT.PDF
 [Description of the DCTDecode filter parameters.]
 
+Adobe Systems Inc., _Open Prepress Interface (OPI) Specification -
+Version 2.0_, Adobe Developer Support Technical Note #5660.  2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5660.OPI_2.0.pdf
+
+Adobe Systems Inc., CMap files.
+ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/
+[The actual CMap files for the 16-bit CJK encodings.]
+
+Aldus Corp., _OPI: Open Prepress Interface Specification 1.3_.  1993.
+http://partners.adobe.com/asn/developer/PDFS/TN/OPI_13.pdf
+
 Anonymous, RC4 source code.
 ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz
 ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz
@@ -329,6 +399,14 @@ Fast 1-D DCT Algorithms with 11 Multiplications".  IEEE Intl. Conf. on
 Acoustics, Speech & Signal Processing, 1989, 988-991.
 [The fast IDCT algorithm used in the DCTDecode filter.]
 
+Microsoft, _TrueType 1.0 Font Files_, rev. 1.66.  1995.
+http://www.microsoft.com/typography/tt/tt.htm
+[The TrueType font spec (in MS Word format, naturally).]
+
+Charles Poynton, "Color FAQ".
+http://www.inforamp.net/~poynton/ColorFAQ.html
+[The mapping from the CIE 1931 (XYZ) color space to RGB.]
+
 R. Rivest, "The MD5 Message-Digest Algorithm".  RFC 1321.
 [MD5 is used in PDF document encryption.]
 
index 4758664fa1327d817bcc4a02a3e492eb9282e8f1..cab17961e262e9159af1a692bed314dd87a8baa2 100644 (file)
@@ -22,8 +22,8 @@
 class SFontEngine {
 public:
 
-  SFontEngine(Display *display, Visual *visual, int depth,
-             Colormap colormap);
+  SFontEngine(Display *displayA, Visual *visualA, int depthA,
+             Colormap colormapA);
   virtual ~SFontEngine();
 
   // Use a TrueColor visual.  Pixel values are computed as:
@@ -32,8 +32,8 @@ public:
   //
   // where r, g, and b are scaled to the ranges [0,rMax], [0,gMax],
   // and [0,bMax], respectively.
-  virtual void useTrueColor(int rMax, int rShift, int gMax, int gShift,
-                           int bMax, int bShift);
+  virtual void useTrueColor(int rMaxA, int rShiftA, int gMaxA, int gShiftA,
+                           int bMaxA, int bShiftA);
 
   // Use an RGB color cube.  <colors> is an array containing
   // <nRGB>*<nRGB>*<nRGB> pixel values in red,green,blue order, e.g.,
@@ -53,7 +53,7 @@ public:
   //
   // The <colors> array is not copied and must remain valid for the
   // lifetime of this SFont object.
-  virtual void useColorCube(Gulong *colors, int nRGB);
+  virtual void useColorCube(Gulong *colorsA, int nRGBA);
 
 protected:
 
index 4b3e43539aa5954b04ef6c21a4b4c112061a0374..0db033f6bd59cf7339c932ff2839763b26c359d4 100644 (file)
@@ -16,7 +16,7 @@
 //------------------------------------------------------------------------
 
 #define type1StdEncodingSize 256
-static const char *type1StdEncodingNames[type1StdEncodingSize] = {
+static char *type1StdEncodingNames[type1StdEncodingSize] = {
   NULL,
   NULL,
   NULL,
@@ -282,7 +282,7 @@ static FontEncoding type1StdEncoding(type1StdEncodingNames,
 //------------------------------------------------------------------------
 
 #define type1ExpertEncodingSize 256
-static const char *type1ExpertEncodingNames[type1ExpertEncodingSize] = {
+static char *type1ExpertEncodingNames[type1ExpertEncodingSize] = {
   NULL,
   NULL,
   NULL,
index 5677dff9d9ce931814a8ad7dd88f339caa85ea9d..a8a88e623d9ac30aac6e5384f9aae7cc51ff097c 100644 (file)
@@ -88,9 +88,7 @@ char *Stream::getLine(char *buf, int size) {
   return buf;
 }
 
-GString *Stream::getPSFilter(const char *indent) {
-  (void)indent;
-
+GString *Stream::getPSFilter(char *indent) {
   return new GString();
 }
 
@@ -138,7 +136,7 @@ Stream *Stream::addFilters(Object *dict) {
   return str;
 }
 
-Stream *Stream::makeFilter(const char *name, Stream *str, Object *params) {
+Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
   int pred;                    // parameters
   int colors;
   int bits;
@@ -267,8 +265,8 @@ Stream *Stream::makeFilter(const char *name, Stream *str, Object *params) {
 // BaseStream
 //------------------------------------------------------------------------
 
-BaseStream::BaseStream(Object *ndict) {
-  dict = *ndict;
+BaseStream::BaseStream(Object *dictA) {
+  dict = *dictA;
 #ifndef NO_DECRYPTION
   decrypt = NULL;
 #endif
@@ -283,8 +281,9 @@ BaseStream::~BaseStream() {
 }
 
 #ifndef NO_DECRYPTION
-void BaseStream::doDecryption(Guchar *fileKey, int objNum, int objGen) {
-  decrypt = new Decrypt(fileKey, objNum, objGen);
+void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
+                             int objNum, int objGen) {
+  decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
 }
 #endif
 
@@ -292,8 +291,8 @@ void BaseStream::doDecryption(Guchar *fileKey, int objNum, int objGen) {
 // FilterStream
 //------------------------------------------------------------------------
 
-FilterStream::FilterStream(Stream *nstr) {
-  str = nstr;
+FilterStream::FilterStream(Stream *strA) {
+  str = strA;
 }
 
 FilterStream::~FilterStream() {
@@ -304,8 +303,6 @@ void FilterStream::close() {
 }
 
 void FilterStream::setPos(int pos) {
-  (void)pos;
-
   error(-1, "Internal: called setPos() on FilterStream");
 }
 
@@ -313,13 +310,13 @@ void FilterStream::setPos(int pos) {
 // ImageStream
 //------------------------------------------------------------------------
 
-ImageStream::ImageStream(Stream *nstr, int nwidth, int nnComps, int nnBits) {
+ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
   int imgLineSize;
 
-  str = nstr;
-  width = nwidth;
-  nComps = nnComps;
-  nBits = nnBits;
+  str = strA;
+  width = widthA;
+  nComps = nCompsA;
+  nBits = nBitsA;
 
   nVals = width * nComps;
   if (nBits == 1) {
@@ -400,13 +397,13 @@ void ImageStream::skipLine() {
 // StreamPredictor
 //------------------------------------------------------------------------
 
-StreamPredictor::StreamPredictor(Stream *nstr, int npredictor,
-                                int nwidth, int nnComps, int nnBits) {
-  str = nstr;
-  predictor = npredictor;
-  width = nwidth;
-  nComps = nnComps;
-  nBits = nnBits;
+StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
+                                int widthA, int nCompsA, int nBitsA) {
+  str = strA;
+  predictor = predictorA;
+  width = widthA;
+  nComps = nCompsA;
+  nBits = nBitsA;
 
   nVals = width * nComps;
   pixBytes = (nComps * nBits + 7) >> 3;
@@ -556,11 +553,11 @@ GBool StreamPredictor::getNextLine() {
 // FileStream
 //------------------------------------------------------------------------
 
-FileStream::FileStream(FILE *nf, int nstart, int nlength, Object *dict):
-    BaseStream(dict) {
-  f = nf;
-  start = nstart;
-  length = nlength;
+FileStream::FileStream(FILE *fA, int startA, int lengthA, Object *dictA):
+    BaseStream(dictA) {
+  f = fA;
+  start = startA;
+  length = lengthA;
   bufPtr = bufEnd = buf;
   bufPos = start;
   savePos = -1;
@@ -570,8 +567,8 @@ FileStream::~FileStream() {
   close();
 }
 
-Stream *FileStream::makeSubStream(int nstart, int nlength, Object *ndict) {
-  return new FileStream(f, nstart, nlength, ndict);
+Stream *FileStream::makeSubStream(int startA, int lengthA, Object *dictA) {
+  return new FileStream(f, startA, lengthA, dictA);
 }
 
 void FileStream::reset() {
@@ -623,25 +620,29 @@ GBool FileStream::fillBuf() {
   return gTrue;
 }
 
-void FileStream::setPos(int pos1) {
+void FileStream::setPos(int pos) {
   long size;
 
-  if (pos1 >= 0) {
-    fseek(f, pos1, SEEK_SET);
-    bufPos = pos1;
+  if (pos >= 0) {
+    fseek(f, pos, SEEK_SET);
+    bufPos = pos;
   } else {
     fseek(f, 0, SEEK_END);
     size = ftell(f);
-    if (pos1 < -size)
-      pos1 = (int)(-size);
-    fseek(f, pos1, SEEK_END);
+    if (pos < -size)
+      pos = (int)(-size);
+#ifdef __CYGWIN32__
+    //~ work around a bug in cygwin's implementation of fseek
+    rewind(f);
+#endif
+    fseek(f, pos, SEEK_END);
     bufPos = (int)ftell(f);
   }
   bufPtr = bufEnd = buf;
 }
 
 void FileStream::moveStart(int delta) {
-  this->start += delta;
+  start += delta;
   bufPtr = bufEnd = buf;
   bufPos = start;
 }
@@ -650,26 +651,20 @@ void FileStream::moveStart(int delta) {
 // EmbedStream
 //------------------------------------------------------------------------
 
-EmbedStream::EmbedStream(Stream *nstr, Object *ndict):
-    BaseStream(ndict) {
-  str = nstr;
+EmbedStream::EmbedStream(Stream *strA, Object *dictA):
+    BaseStream(dictA) {
+  str = strA;
 }
 
 EmbedStream::~EmbedStream() {
 }
 
-Stream *EmbedStream::makeSubStream(int start, int length, Object *ndict) {
-  (void)start;
-  (void)length;
-  (void)ndict;
-
+Stream *EmbedStream::makeSubStream(int start, int length, Object *dictA) {
   error(-1, "Internal: called makeSubStream() on EmbedStream");
   return NULL;
 }
 
 void EmbedStream::setPos(int pos) {
-  (void)pos;
-
   error(-1, "Internal: called setPos() on EmbedStream");
 }
 
@@ -679,8 +674,6 @@ int EmbedStream::getStart() {
 }
 
 void EmbedStream::moveStart(int start) {
-  (void)start;
-
   error(-1, "Internal: called moveStart() on EmbedStream");
 }
 
@@ -688,8 +681,8 @@ void EmbedStream::moveStart(int start) {
 // ASCIIHexStream
 //------------------------------------------------------------------------
 
-ASCIIHexStream::ASCIIHexStream(Stream *str):
-    FilterStream(str) {
+ASCIIHexStream::ASCIIHexStream(Stream *strA):
+    FilterStream(strA) {
   buf = EOF;
   eof = gFalse;
 }
@@ -757,17 +750,17 @@ int ASCIIHexStream::lookChar() {
   return buf;
 }
 
-GString *ASCIIHexStream::getPSFilter(const char *indent) {
+GString *ASCIIHexStream::getPSFilter(char *indent) {
   GString *s;
 
-  s = str->getPSFilter(indent);
+  if (!(s = str->getPSFilter(indent))) {
+    return NULL;
+  }
   s->append(indent)->append("/ASCIIHexDecode filter\n");
   return s;
 }
 
 GBool ASCIIHexStream::isBinary(GBool last) {
-  (void)last;
-
   return str->isBinary(gFalse);
 }
 
@@ -775,8 +768,8 @@ GBool ASCIIHexStream::isBinary(GBool last) {
 // ASCII85Stream
 //------------------------------------------------------------------------
 
-ASCII85Stream::ASCII85Stream(Stream *str):
-    FilterStream(str) {
+ASCII85Stream::ASCII85Stream(Stream *strA):
+    FilterStream(strA) {
   index = n = 0;
   eof = gFalse;
 }
@@ -835,17 +828,17 @@ int ASCII85Stream::lookChar() {
   return b[index];
 }
 
-GString *ASCII85Stream::getPSFilter(const char *indent) {
+GString *ASCII85Stream::getPSFilter(char *indent) {
   GString *s;
 
-  s = str->getPSFilter(indent);
+  if (!(s = str->getPSFilter(indent))) {
+    return NULL;
+  }
   s->append(indent)->append("/ASCII85Decode filter\n");
   return s;
 }
 
 GBool ASCII85Stream::isBinary(GBool last) {
-  (void)last;
-
   return str->isBinary(gFalse);
 }
 
@@ -853,15 +846,15 @@ GBool ASCII85Stream::isBinary(GBool last) {
 // LZWStream
 //------------------------------------------------------------------------
 
-LZWStream::LZWStream(Stream *str, int predictor1, int columns1, int colors1,
-                    int bits1, int early1):
-    FilterStream(str) {
-  if (predictor1 != 1) {
-    pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1);
+LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
+                    int bits, int earlyA):
+    FilterStream(strA) {
+  if (predictor != 1) {
+    pred = new StreamPredictor(this, predictor, columns, colors, bits);
   } else {
     pred = NULL;
   }
-  early = early1;
+  early = earlyA;
   zPipe = NULL;
   bufPtr = bufEnd = buf;
 }
@@ -1149,20 +1142,20 @@ GBool LZWStream::fillBuf() {
   return n > 0;
 }
 
-GString *LZWStream::getPSFilter(const char *indent) {
+GString *LZWStream::getPSFilter(char *indent) {
   GString *s;
 
   if (pred) {
     return NULL;
   }
-  s = str->getPSFilter(indent);
+  if (!(s = str->getPSFilter(indent))) {
+    return NULL;
+  }
   s->append(indent)->append("/LZWDecode filter\n");
   return s;
 }
 
 GBool LZWStream::isBinary(GBool last) {
-  (void)last;
-
   return str->isBinary(gTrue);
 }
 
@@ -1170,8 +1163,8 @@ GBool LZWStream::isBinary(GBool last) {
 // RunLengthStream
 //------------------------------------------------------------------------
 
-RunLengthStream::RunLengthStream(Stream *str):
-    FilterStream(str) {
+RunLengthStream::RunLengthStream(Stream *strA):
+    FilterStream(strA) {
   bufPtr = bufEnd = buf;
   eof = gFalse;
 }
@@ -1186,17 +1179,17 @@ void RunLengthStream::reset() {
   eof = gFalse;
 }
 
-GString *RunLengthStream::getPSFilter(const char *indent) {
+GString *RunLengthStream::getPSFilter(char *indent) {
   GString *s;
 
-  s = str->getPSFilter(indent);
+  if (!(s = str->getPSFilter(indent))) {
+    return NULL;
+  }
   s->append(indent)->append("/RunLengthDecode filter\n");
   return s;
 }
 
 GBool RunLengthStream::isBinary(GBool last) {
-  (void)last;
-
   return str->isBinary(gTrue);
 }
 
@@ -1230,17 +1223,17 @@ GBool RunLengthStream::fillBuf() {
 // CCITTFaxStream
 //------------------------------------------------------------------------
 
-CCITTFaxStream::CCITTFaxStream(Stream *str, int nencoding, GBool nendOfLine,
-                              GBool nbyteAlign, int ncolumns, int nrows,
-                              GBool nendOfBlock, GBool nblack):
-    FilterStream(str) {
-  encoding = nencoding;
-  endOfLine = nendOfLine;
-  byteAlign = nbyteAlign;
-  columns = ncolumns;
-  rows = nrows;
-  endOfBlock = nendOfBlock;
-  black = nblack;
+CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
+                              GBool byteAlignA, int columnsA, int rowsA,
+                              GBool endOfBlockA, GBool blackA):
+    FilterStream(strA) {
+  encoding = encodingA;
+  endOfLine = endOfLineA;
+  byteAlign = byteAlignA;
+  columns = columnsA;
+  rows = rowsA;
+  endOfBlock = endOfBlockA;
+  black = blackA;
   refLine = (short *)gmalloc((columns + 3) * sizeof(short));
   codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
 
@@ -1736,11 +1729,13 @@ short CCITTFaxStream::lookBits(int n) {
   return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
 }
 
-GString *CCITTFaxStream::getPSFilter(const char *indent) {
+GString *CCITTFaxStream::getPSFilter(char *indent) {
   GString *s;
   char s1[50];
 
-  s = str->getPSFilter(indent);
+  if (!(s = str->getPSFilter(indent))) {
+    return NULL;
+  }
   s->append(indent)->append("<< ");
   if (encoding != 0) {
     sprintf(s1, "/K %d ", encoding);
@@ -1769,8 +1764,6 @@ GString *CCITTFaxStream::getPSFilter(const char *indent) {
 }
 
 GBool CCITTFaxStream::isBinary(GBool last) {
-  (void)last;
-
   return str->isBinary(gTrue);
 }
 
@@ -1832,8 +1825,8 @@ static int dctZigZag[64] = {
   63
 };
 
-DCTStream::DCTStream(Stream *str):
-    FilterStream(str) {
+DCTStream::DCTStream(Stream *strA):
+    FilterStream(strA) {
   int i, j;
 
   width = height = 0;
@@ -2729,17 +2722,17 @@ int DCTStream::read16() {
   return (c1 << 8) + c2;
 }
 
-GString *DCTStream::getPSFilter(const char *indent) {
+GString *DCTStream::getPSFilter(char *indent) {
   GString *s;
 
-  s = str->getPSFilter(indent);
+  if (!(s = str->getPSFilter(indent))) {
+    return NULL;
+  }
   s->append(indent)->append("<< >> /DCTDecode filter\n");
   return s;
 }
 
 GBool DCTStream::isBinary(GBool last) {
-  (void)last;
-
   return str->isBinary(gTrue);
 }
 
@@ -2816,11 +2809,11 @@ FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
   {13, 24577}
 };
 
-FlateStream::FlateStream(Stream *str, int predictor1, int columns1,
-                        int colors1, int bits1):
-    FilterStream(str) {
-  if (predictor1 != 1) {
-    pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1);
+FlateStream::FlateStream(Stream *strA, int predictor, int columns,
+                        int colors, int bits):
+    FilterStream(strA) {
+  if (predictor != 1) {
+    pred = new StreamPredictor(this, predictor, columns, colors, bits);
   } else {
     pred = NULL;
   }
@@ -2915,15 +2908,11 @@ int FlateStream::getRawChar() {
   return c;
 }
 
-GString *FlateStream::getPSFilter(const char *indent) {
-  (void)indent;
-
+GString *FlateStream::getPSFilter(char *indent) {
   return NULL;
 }
 
 GBool FlateStream::isBinary(GBool last) {
-  (void)last;
-
   return str->isBinary(gTrue);
 }
 
@@ -3252,8 +3241,8 @@ int FlateStream::getCodeWord(int bits) {
 // EOFStream
 //------------------------------------------------------------------------
 
-EOFStream::EOFStream(Stream *str):
-    FilterStream(str) {
+EOFStream::EOFStream(Stream *strA):
+    FilterStream(strA) {
 }
 
 EOFStream::~EOFStream() {
@@ -3264,9 +3253,9 @@ EOFStream::~EOFStream() {
 // FixedLengthEncoder
 //------------------------------------------------------------------------
 
-FixedLengthEncoder::FixedLengthEncoder(Stream *str, int length1):
-    FilterStream(str) {
-  length = length1;
+FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
+    FilterStream(strA) {
+  length = lengthA;
   count = 0;
 }
 
@@ -3300,8 +3289,8 @@ int FixedLengthEncoder::lookChar() {
 // ASCII85Encoder
 //------------------------------------------------------------------------
 
-ASCII85Encoder::ASCII85Encoder(Stream *str):
-    FilterStream(str) {
+ASCII85Encoder::ASCII85Encoder(Stream *strA):
+    FilterStream(strA) {
   bufPtr = bufEnd = buf;
   lineLen = 0;
   eof = gFalse;
@@ -3372,8 +3361,8 @@ GBool ASCII85Encoder::fillBuf() {
 // RunLengthEncoder
 //------------------------------------------------------------------------
 
-RunLengthEncoder::RunLengthEncoder(Stream *str):
-    FilterStream(str) {
+RunLengthEncoder::RunLengthEncoder(Stream *strA):
+    FilterStream(strA) {
   bufPtr = bufEnd = nextEnd = buf;
   eof = gFalse;
 }
@@ -3434,7 +3423,6 @@ GBool RunLengthEncoder::fillBuf() {
   c = 0; // make gcc happy
   if (c1 == c2) {
     n = 2;
-    c = 0; // suppress bogus compiler warning
     while (n < 128 && (c = str->getChar()) == c1)
       ++n;
     buf[0] = (char)(257 - n);
index f77bade5031496803cba99708e1f71d886a9d905..1f9c561d19b02cb5f77cb5905799df17ea95e10e 100644 (file)
@@ -79,10 +79,10 @@ public:
   virtual int getPos() = 0;
 
   // Go to a position in the stream.
-  virtual void setPos(int pos1) = 0;
+  virtual void setPos(int pos) = 0;
 
   // Get PostScript command for the filter(s).
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
 
   // Does this stream type potentially contain non-printable chars?
   virtual GBool isBinary(GBool last = gTrue) = 0;
@@ -102,7 +102,7 @@ public:
 
 private:
 
-  Stream *makeFilter(const char *name, Stream *str, Object *params);
+  Stream *makeFilter(char *name, Stream *str, Object *params);
 
   int ref;                     // reference count
 };
@@ -116,10 +116,10 @@ private:
 class BaseStream: public Stream {
 public:
 
-  BaseStream(Object *dict);
+  BaseStream(Object *dictA);
   virtual ~BaseStream();
   virtual Stream *makeSubStream(int start, int length, Object *dict) = 0;
-  virtual void setPos(int pos1) = 0;
+  virtual void setPos(int pos) = 0;
   virtual BaseStream *getBaseStream() { return this; }
   virtual Dict *getDict() { return dict.getDict(); }
 
@@ -129,7 +129,7 @@ public:
 
 #ifndef NO_DECRYPTION
   // Set decryption for this stream.
-  void doDecryption(Guchar *fileKey, int objNum, int objGen);
+  void doDecryption(Guchar *fileKey, int keyLength, int objNum, int objGen);
 #endif
 
 #ifndef NO_DECRYPTION
@@ -152,7 +152,7 @@ private:
 class FilterStream: public Stream {
 public:
 
-  FilterStream(Stream *str);
+  FilterStream(Stream *strA);
   virtual ~FilterStream();
   virtual void close();
   virtual int getPos() { return str->getPos(); }
@@ -175,7 +175,7 @@ public:
   // Create an image stream object for an image with the specified
   // parameters.  Note that these are the actual image parameters,
   // which may be different from the predictor parameters.
-  ImageStream(Stream *str, int width, int nComps, int nBits);
+  ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
 
   ~ImageStream();
 
@@ -209,8 +209,8 @@ public:
 
   // Create a predictor object.  Note that the parameters are for the
   // predictor, and may not match the actual image parameters.
-  StreamPredictor(Stream *str, int predictor,
-                 int width, int nComps, int nBits);
+  StreamPredictor(Stream *strA, int predictorA,
+                 int widthA, int nCompsA, int nBitsA);
 
   ~StreamPredictor();
 
@@ -242,9 +242,9 @@ private:
 class FileStream: public BaseStream {
 public:
 
-  FileStream(FILE *f, int start, int length, Object *dict);
+  FileStream(FILE *fA, int startA, int lengthA, Object *dictA);
   virtual ~FileStream();
-  virtual Stream *makeSubStream(int start, int length, Object *dict);
+  virtual Stream *makeSubStream(int startA, int lengthA, Object *dictA);
   virtual StreamKind getKind() { return strFile; }
   virtual void reset();
   virtual void close();
@@ -253,7 +253,7 @@ public:
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
   virtual int getPos() { return bufPos + (bufPtr - buf); }
-  virtual void setPos(int pos1);
+  virtual void setPos(int pos);
   virtual GBool isBinary(GBool last = gTrue) { return last; }
   virtual int getStart() { return start; }
   virtual void moveStart(int delta);
@@ -285,9 +285,9 @@ private:
 class EmbedStream: public BaseStream {
 public:
 
-  EmbedStream(Stream *str, Object *dict);
+  EmbedStream(Stream *strA, Object *dictA);
   virtual ~EmbedStream();
-  virtual Stream *makeSubStream(int start, int length, Object *dict);
+  virtual Stream *makeSubStream(int start, int length, Object *dictA);
   virtual StreamKind getKind() { return str->getKind(); }
   virtual void reset() {}
   virtual int getChar() { return str->getChar(); }
@@ -310,14 +310,14 @@ private:
 class ASCIIHexStream: public FilterStream {
 public:
 
-  ASCIIHexStream(Stream *str);
+  ASCIIHexStream(Stream *strA);
   virtual ~ASCIIHexStream();
   virtual StreamKind getKind() { return strASCIIHex; }
   virtual void reset();
   virtual int getChar()
     { int c = lookChar(); buf = EOF; return c; }
   virtual int lookChar();
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -333,14 +333,14 @@ private:
 class ASCII85Stream: public FilterStream {
 public:
 
-  ASCII85Stream(Stream *str);
+  ASCII85Stream(Stream *strA);
   virtual ~ASCII85Stream();
   virtual StreamKind getKind() { return strASCII85; }
   virtual void reset();
   virtual int getChar()
     { int ch = lookChar(); ++index; return ch; }
   virtual int lookChar();
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -358,15 +358,15 @@ private:
 class LZWStream: public FilterStream {
 public:
 
-  LZWStream(Stream *str, int predictor1, int columns1, int colors1,
-           int bits1, int early1);
+  LZWStream(Stream *strA, int predictor, int columns, int colors,
+           int bits, int earlyA);
   virtual ~LZWStream();
   virtual StreamKind getKind() { return strLZW; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -394,7 +394,7 @@ private:
 class RunLengthStream: public FilterStream {
 public:
 
-  RunLengthStream(Stream *str);
+  RunLengthStream(Stream *strA);
   virtual ~RunLengthStream();
   virtual StreamKind getKind() { return strRunLength; }
   virtual void reset();
@@ -402,7 +402,7 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -424,16 +424,16 @@ struct CCITTCodeTable;
 class CCITTFaxStream: public FilterStream {
 public:
 
-  CCITTFaxStream(Stream *str, int encoding, GBool endOfLine,
-                GBool byteAlign, int columns, int rows,
-                GBool endOfBlock, GBool black);
+  CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
+                GBool byteAlignA, int columnsA, int rowsA,
+                GBool endOfBlockA, GBool blackA);
   virtual ~CCITTFaxStream();
   virtual StreamKind getKind() { return strCCITTFax; }
   virtual void reset();
   virtual int getChar()
     { int c = lookChar(); buf = EOF; return c; }
   virtual int lookChar();
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -489,13 +489,13 @@ struct DCTHuffTable {
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *str);
+  DCTStream(Stream *strA);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
   virtual GBool isBinary(GBool last = gTrue);
   Stream *getRawStream() { return str; }
 
@@ -573,15 +573,15 @@ struct FlateDecode {
 class FlateStream: public FilterStream {
 public:
 
-  FlateStream(Stream *str, int predictor1, int columns1,
-             int colors1, int bits1);
+  FlateStream(Stream *strA, int predictor, int columns,
+             int colors, int bits);
   virtual ~FlateStream();
   virtual StreamKind getKind() { return strFlate; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
-  virtual GString *getPSFilter(const char *indent);
+  virtual GString *getPSFilter(char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -624,14 +624,14 @@ private:
 class EOFStream: public FilterStream {
 public:
 
-  EOFStream(Stream *str);
+  EOFStream(Stream *strA);
   virtual ~EOFStream();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset() {}
   virtual int getChar() { return EOF; }
   virtual int lookChar() { return EOF; }
-  virtual GString *getPSFilter(const char *indent)  { (void)indent; return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
+  virtual GString *getPSFilter(char *indent)  { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
 };
 
 //------------------------------------------------------------------------
@@ -641,15 +641,15 @@ public:
 class FixedLengthEncoder: public FilterStream {
 public:
 
-  FixedLengthEncoder(Stream *str, int length1);
+  FixedLengthEncoder(Stream *strA, int lengthA);
   ~FixedLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
   virtual void close();
   virtual int getChar();
   virtual int lookChar();
-  virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
+  virtual GString *getPSFilter(char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
@@ -665,7 +665,7 @@ private:
 class ASCII85Encoder: public FilterStream {
 public:
 
-  ASCII85Encoder(Stream *str);
+  ASCII85Encoder(Stream *strA);
   virtual ~ASCII85Encoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
@@ -674,8 +674,8 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
+  virtual GString *getPSFilter(char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
@@ -696,7 +696,7 @@ private:
 class RunLengthEncoder: public FilterStream {
 public:
 
-  RunLengthEncoder(Stream *str);
+  RunLengthEncoder(Stream *strA);
   virtual ~RunLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
@@ -705,8 +705,8 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
+  virtual GString *getPSFilter(char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
index 9ead397f62480b6a7605007a191d76c24c1ba4fb..846d253e9fe183c7fe6437c900b14e7e8f85e154 100644 (file)
@@ -26,8 +26,8 @@ class FontEncoding;
 class T1FontEngine: public SFontEngine {
 public:
 
-  T1FontEngine(Display *display, Visual *visual, int depth,
-              Colormap colormap, GBool aa, GBool aaHigh);
+  T1FontEngine(Display *displayA, Visual *visualA, int depthA,
+              Colormap colormapA, GBool aaA, GBool aaHighA);
   GBool isOk() { return ok; }
   virtual ~T1FontEngine();
 
@@ -35,7 +35,6 @@ private:
 
   GBool aa;                    // use anti-aliasing?
   GBool aaHigh;                        // use high-res anti-aliasing?
-  GBool bigEndian;
   GBool ok;
 
   friend class T1FontFile;
@@ -47,8 +46,8 @@ private:
 class T1FontFile: public SFontFile {
 public:
 
-  T1FontFile(T1FontEngine *engine, char *fontFileName,
-            FontEncoding *fontEnc);
+  T1FontFile(T1FontEngine *engineA, char *fontFileName,
+            FontEncoding *fontEnc, double *bboxA);
   GBool isOk() { return ok; }
   virtual ~T1FontFile();
 
@@ -58,6 +57,7 @@ private:
   int id;                      // t1lib font ID
   char **enc;
   char *encStr;
+  double bbox[4];
   GBool ok;
 
   friend class T1Font;
@@ -74,7 +74,7 @@ struct T1FontCacheTag {
 class T1Font: public SFont {
 public:
 
-  T1Font(T1FontFile *fontFile, double *m);
+  T1Font(T1FontFile *fontFileA, double *m);
   GBool isOk() { return ok; }
   virtual ~T1Font();
   virtual GBool drawChar(Drawable d, int w, int h, GC gc,
index 68e5d97364d14187a728394a43c1b148f9f95e2c..998087c9c791be14b88aed26919f09372c7b3a8e 100644 (file)
@@ -9,20 +9,18 @@
 #ifndef TTFONT_H
 #define TTFONT_H
 
-#if HAVE_FREETYPE_FREETYPE_H
+#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
 
 #ifdef __GNUC__
 #pragma interface
 #endif
 
-#ifdef VMS
-#include <freetype.h>
-#include <ftxpost.h>
-#else
-//~ This will be going away; the configure script will add
-//~ -I<something>/freetype to CFLAGS.
+#if HAVE_FREETYPE_FREETYPE_H
 #include <freetype/freetype.h>
 #include <freetype/ftxpost.h>
+#else
+#include <freetype.h>
+#include <ftxpost.h>
 #endif
 #include "SFont.h"
 
@@ -31,8 +29,8 @@
 class TTFontEngine: public SFontEngine {
 public:
 
-  TTFontEngine(Display *display, Visual *visual, int depth,
-              Colormap colormap, GBool aa);
+  TTFontEngine(Display *displayA, Visual *visualA, int depthA,
+              Colormap colormapA, GBool aaA);
   GBool isOk() { return ok; }
   virtual ~TTFontEngine();
 
@@ -52,7 +50,7 @@ private:
 class TTFontFile: public SFontFile {
 public:
 
-  TTFontFile(TTFontEngine *engine, char *fontFileName);
+  TTFontFile(TTFontEngine *engineA, char *fontFileName);
   GBool isOk() { return ok; }
   virtual ~TTFontFile();
 
@@ -77,7 +75,7 @@ struct TTFontCacheTag {
 class TTFont: public SFont {
 public:
 
-  TTFont(TTFontFile *fontFile, double *m);
+  TTFont(TTFontFile *fontFileA, double *m);
   GBool isOk() { return ok; }
   virtual ~TTFont();
   virtual GBool drawChar(Drawable d, int w, int h, GC gc,
@@ -101,6 +99,6 @@ private:
   GBool ok;
 };
 
-#endif // HAVE_FREETYPE_FREETYPE_H
+#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
 
 #endif
index d70b9f2097c48e6ce37fb9c1f12617b533be8c6b..de2db2f23b544d1ae6b09d55055021c05f1bdf9b 100644 (file)
 #define defPermFlags 0xfffc
 #endif
 
-//------------------------------------------------------------------------
-// The global xref table
-//------------------------------------------------------------------------
-
-XRef *xref = NULL;
-
 //------------------------------------------------------------------------
 // XRef
 //------------------------------------------------------------------------
 
-XRef::XRef(BaseStream *str, GString *userPassword) {
-  XRef *oldXref;
+XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
   int pos;
   int i;
 
@@ -64,13 +57,8 @@ XRef::XRef(BaseStream *str, GString *userPassword) {
   streamEnds = NULL;
   streamEndsLen = 0;
 
-  // get rid of old xref (otherwise it will try to fetch the Root object
-  // in the new document, using the old xref)
-  oldXref = xref;
-  xref = NULL;
-
   // read the trailer
-  this->str = str;
+  str = strA;
   start = str->getStart();
   pos = readTrailer();
 
@@ -78,7 +66,6 @@ XRef::XRef(BaseStream *str, GString *userPassword) {
   // try to reconstruct the xref table
   if (pos == 0) {
     if (!(ok = constructXRef())) {
-      xref = oldXref;
       return;
     }
 
@@ -98,22 +85,21 @@ XRef::XRef(BaseStream *str, GString *userPassword) {
       size = 0;
       entries = NULL;
       if (!(ok = constructXRef())) {
-       xref = oldXref;
        return;
       }
     }
   }
 
-  // set up new xref table
-  xref = this;
+  // now set the trailer dictionary's xref pointer so we can fetch
+  // indirect objects from it
+  trailerDict.getDict()->setXRef(this);
 
   // check for encryption
 #ifndef NO_DECRYPTION
   encrypted = gFalse;
 #endif
-  if (checkEncrypted(userPassword)) {
+  if (checkEncrypted(ownerPassword, userPassword)) {
     ok = gFalse;
-    xref = oldXref;
     return;
   }
 }
@@ -189,7 +175,8 @@ int XRef::readTrailer() {
 
   // read trailer dict
   obj.initNull();
-  parser = new Parser(new Lexer(str->makeSubStream(start + pos1, -1, &obj)));
+  parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(start + pos1,
+                                                              -1, &obj)));
   parser->getObj(&trailerDict);
   if (trailerDict.isDict()) {
     trailerDict.dictLookupNF("Size", &obj);
@@ -221,7 +208,7 @@ GBool XRef::readXRef(int *pos) {
   Object obj, obj2;
   char s[20];
   GBool more;
-  int first, n, i, j;
+  int first, newSize, n, i, j;
   int c;
 
   // seek to xref in stream
@@ -233,35 +220,56 @@ GBool XRef::readXRef(int *pos) {
   s[1] = (char)str->getChar();
   s[2] = (char)str->getChar();
   s[3] = (char)str->getChar();
-  if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f'))
+  if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f')) {
     goto err2;
+  }
 
   // read xref
   while (1) {
-    while ((c = str->lookChar()) != EOF && isspace(c))
+    while ((c = str->lookChar()) != EOF && isspace(c)) {
       str->getChar();
-    if (c == 't')
+    }
+    if (c == 't') {
       break;
-    for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i)
+    }
+    for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
       s[i] = (char)c;
-    if (i == 0)
+    }
+    if (i == 0) {
       goto err2;
+    }
     s[i] = '\0';
     first = atoi(s);
-    while ((c = str->lookChar()) != EOF && isspace(c))
+    while ((c = str->lookChar()) != EOF && isspace(c)) {
       str->getChar();
-    for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i)
+    }
+    for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
       s[i] = (char)c;
-    if (i == 0)
+    }
+    if (i == 0) {
       goto err2;
+    }
     s[i] = '\0';
     n = atoi(s);
-    while ((c = str->lookChar()) != EOF && isspace(c))
+    while ((c = str->lookChar()) != EOF && isspace(c)) {
       str->getChar();
+    }
+    // check for buggy PDF files with an incorrect (too small) xref
+    // table size
+    if (first + n > size) {
+      newSize = size + 256;
+      entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
+      for (i = size; i < newSize; ++i) {
+       entries[i].offset = -1;
+       entries[i].used = gFalse;
+      }
+      size = newSize;
+    }
     for (i = first; i < first + n; ++i) {
       for (j = 0; j < 20; ++j) {
-       if ((c = str->getChar()) == EOF)
+       if ((c = str->getChar()) == EOF) {
          goto err2;
+       }
        s[j] = (char)c;
       }
       if (entries[i].offset < 0) {
@@ -269,16 +277,16 @@ GBool XRef::readXRef(int *pos) {
        entries[i].offset = atoi(s);
        s[16] = '\0';
        entries[i].gen = atoi(&s[11]);
-       if (s[17] == 'n')
+       if (s[17] == 'n') {
          entries[i].used = gTrue;
-       else if (s[17] == 'f')
+       } else if (s[17] == 'f') {
          entries[i].used = gFalse;
-       else
+       } else {
          goto err2;
-#if 1 //~
-       //~ PDF files of patents from the IBM Intellectual Property
-       //~ Network have a bug: the xref table claims to start at 1
-       //~ instead of 0.
+       }
+       // PDF files of patents from the IBM Intellectual Property
+       // Network have a bug: the xref table claims to start at 1
+       // instead of 0.
        if (i == 1 && first == 1 &&
            entries[1].offset == 0 && entries[1].gen == 65535 &&
            !entries[1].used) {
@@ -286,21 +294,23 @@ GBool XRef::readXRef(int *pos) {
          entries[0] = entries[1];
          entries[1].offset = -1;
        }
-#endif
       }
     }
   }
 
   // read prev pointer from trailer dictionary
   obj.initNull();
-  parser = new Parser(new Lexer(str->makeSubStream(str->getPos(), -1, &obj)));
+  parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(str->getPos(),
+                                                              -1, &obj)));
   parser->getObj(&obj);
-  if (!obj.isCmd("trailer"))
+  if (!obj.isCmd("trailer")) {
     goto err1;
+  }
   obj.free();
   parser->getObj(&obj);
-  if (!obj.isDict())
+  if (!obj.isDict()) {
     goto err1;
+  }
   obj.getDict()->lookupNF("Prev", &obj2);
   if (obj2.isInt()) {
     *pos = obj2.getInt();
@@ -349,7 +359,7 @@ GBool XRef::constructXRef() {
     // got trailer dictionary
     if (!strncmp(p, "trailer", 7)) {
       obj.initNull();
-      parser = new Parser(new Lexer(
+      parser = new Parser(NULL, new Lexer(NULL,
                      str->makeSubStream(start + pos + 7, -1, &obj)));
       if (!trailerDict.isNone())
        trailerDict.free();
@@ -424,8 +434,9 @@ GBool XRef::constructXRef() {
 }
 
 #ifndef NO_DECRYPTION
-GBool XRef::checkEncrypted(GString *userPassword) {
-  Object encrypt, ownerKey, userKey, permissions, fileID, fileID1;
+GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
+  Object encrypt, filterObj, versionObj, revisionObj, lengthObj;
+  Object ownerKey, userKey, permissions, fileID, fileID1;
   GBool encrypted1;
   GBool ret;
 
@@ -435,35 +446,68 @@ GBool XRef::checkEncrypted(GString *userPassword) {
   trailerDict.dictLookup("Encrypt", &encrypt);
   if ((encrypted1 = encrypt.isDict())) {
     ret = gTrue;
-    encrypt.dictLookup("O", &ownerKey);
-    encrypt.dictLookup("U", &userKey);
-    encrypt.dictLookup("P", &permissions);
-    trailerDict.dictLookup("ID", &fileID);
-    if (ownerKey.isString() && ownerKey.getString()->getLength() == 32 &&
-       userKey.isString() && userKey.getString()->getLength() == 32 &&
-       permissions.isInt() &&
-       fileID.isArray()) {
-      permFlags = permissions.getInt();
-      fileID.arrayGet(0, &fileID1);
-      if (fileID1.isString()) {
-       if (Decrypt::makeFileKey(ownerKey.getString(), userKey.getString(),
-                                permFlags, fileID1.getString(),
-                                userPassword, fileKey)) {
-         ret = gFalse;
+    encrypt.dictLookup("Filter", &filterObj);
+    if (filterObj.isName("Standard")) {
+      encrypt.dictLookup("V", &versionObj);
+      encrypt.dictLookup("R", &revisionObj);
+      encrypt.dictLookup("Length", &lengthObj);
+      encrypt.dictLookup("O", &ownerKey);
+      encrypt.dictLookup("U", &userKey);
+      encrypt.dictLookup("P", &permissions);
+      trailerDict.dictLookup("ID", &fileID);
+      if (versionObj.isInt() &&
+         revisionObj.isInt() &&
+         ownerKey.isString() && ownerKey.getString()->getLength() == 32 &&
+         userKey.isString() && userKey.getString()->getLength() == 32 &&
+         permissions.isInt() &&
+         fileID.isArray()) {
+       encVersion = versionObj.getInt();
+       encRevision = revisionObj.getInt();
+       if (lengthObj.isInt()) {
+         keyLength = lengthObj.getInt() / 8;
+       } else {
+         keyLength = 5;
+       }
+       permFlags = permissions.getInt();
+       if (encVersion >= 1 && encVersion <= 2 &&
+           encRevision >= 2 && encRevision <= 3) {
+         fileID.arrayGet(0, &fileID1);
+         if (fileID1.isString()) {
+           if (Decrypt::makeFileKey(encVersion, encRevision, keyLength,
+                                    ownerKey.getString(), userKey.getString(),
+                                    permFlags, fileID1.getString(),
+                                    ownerPassword, userPassword, fileKey,
+                                    &ownerPasswordOk)) {
+             if (ownerPassword && !ownerPasswordOk) {
+               error(-1, "Incorrect owner password");
+             }
+             ret = gFalse;
+           } else {
+             error(-1, "Incorrect password");
+           }
+         } else {
+           error(-1, "Weird encryption info");
+         }
+         fileID1.free();
        } else {
-         error(-1, "Incorrect user password");
+         error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
+               encVersion, encRevision);
        }
       } else {
        error(-1, "Weird encryption info");
       }
-      fileID1.free();
+      fileID.free();
+      permissions.free();
+      userKey.free();
+      ownerKey.free();
+      lengthObj.free();
+      revisionObj.free();
+      versionObj.free();
     } else {
-      error(-1, "Weird encryption info");
+      error(-1, "Unknown security handler '%s'",
+           filterObj.isName() ? filterObj.getName() : "???");
     }
-    ownerKey.free();
-    userKey.free();
-    permissions.free();
-    fileID.free();
+    filterObj.free();
   }
   encrypt.free();
 
@@ -473,52 +517,50 @@ GBool XRef::checkEncrypted(GString *userPassword) {
   return ret;
 }
 #else
-GBool XRef::checkEncrypted(GString *userPassword) {
+GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
   Object obj;
   GBool encrypted;
 
   trailerDict.dictLookup("Encrypt", &obj);
   if ((encrypted = !obj.isNull())) {
-    error(-1, "PDF file is encrypted and cannot be displayed");
-    error(-1, "* Decryption support is currently not included in xpdf");
-    error(-1, "* due to legal restrictions: the U.S.A. still has bogus");
-    error(-1, "* export controls on cryptography software.");
+    error(-1, "PDF file is encrypted and this version of the Xpdf tools");
+    error(-1, "was built without decryption support.");
   }
   obj.free();
   return encrypted;
 }
 #endif
 
-GBool XRef::okToPrint() {
+GBool XRef::okToPrint(GBool ignoreOwnerPW) {
 #ifndef NO_DECRYPTION
-  if (!(permFlags & permPrint)) {
+  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permPrint)) {
     return gFalse;
   }
 #endif
   return gTrue;
 }
 
-GBool XRef::okToChange() {
+GBool XRef::okToChange(GBool ignoreOwnerPW) {
 #ifndef NO_DECRYPTION
-  if (!(permFlags & permChange)) {
+  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permChange)) {
     return gFalse;
   }
 #endif
   return gTrue;
 }
 
-GBool XRef::okToCopy() {
+GBool XRef::okToCopy(GBool ignoreOwnerPW) {
 #ifndef NO_DECRYPTION
-  if (!(permFlags & permCopy)) {
+  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permCopy)) {
     return gFalse;
   }
 #endif
   return gTrue;
 }
 
-GBool XRef::okToAddNotes() {
+GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {
 #ifndef NO_DECRYPTION
-  if (!(permFlags & permNotes)) {
+  if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permNotes)) {
     return gFalse;
   }
 #endif
@@ -539,7 +581,7 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
   e = &entries[num];
   if (e->gen == gen && e->offset >= 0) {
     obj1.initNull();
-    parser = new Parser(new Lexer(
+    parser = new Parser(this, new Lexer(this,
                   str->makeSubStream(start + e->offset, -1, &obj1)));
     parser->getObj(&obj1);
     parser->getObj(&obj2);
@@ -548,7 +590,8 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
        obj2.isInt() && obj2.getInt() == gen &&
        obj3.isCmd("obj")) {
 #ifndef NO_DECRYPTION
-      parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, num, gen);
+      parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
+                    num, gen);
 #else
       parser->getObj(obj);
 #endif
@@ -569,20 +612,20 @@ Object *XRef::getDocInfo(Object *obj) {
   return trailerDict.dictLookup("Info", obj);
 }
 
-int XRef::getStreamEnd(int start) {
+int XRef::getStreamEnd(int streamStart) {
   int a, b, m;
 
   if (streamEndsLen == 0 ||
-      start > streamEnds[streamEndsLen - 1]) {
+      streamStart > streamEnds[streamEndsLen - 1]) {
     return -1;
   }
 
   a = -1;
   b = streamEndsLen - 1;
-  // invariant: streamEnds[a] < start <= streamEnds[b]
+  // invariant: streamEnds[a] < streamStart <= streamEnds[b]
   while (b - a > 1) {
     m = (a + b) / 2;
-    if (start <= streamEnds[m]) {
+    if (streamStart <= streamEnds[m]) {
       b = m;
     } else {
       a = m;
index e2260d0c33cf9ded044ac83ee41d9f18ab74172b..35306bba835cab1f5ff405a5d8c5f1291c416324 100644 (file)
@@ -33,7 +33,7 @@ class XRef {
 public:
 
   // Constructor.  Read xref table from stream.
-  XRef(BaseStream *str, GString *userPassword);
+  XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword);
 
   // Destructor.
   ~XRef();
@@ -49,10 +49,10 @@ public:
 #endif
 
   // Check various permissions.
-  GBool okToPrint();
-  GBool okToChange();
-  GBool okToCopy();
-  GBool okToAddNotes();
+  GBool okToPrint(GBool ignoreOwnerPW = gFalse);
+  GBool okToChange(GBool ignoreOwnerPW = gFalse);
+  GBool okToCopy(GBool ignoreOwnerPW = gFalse);
+  GBool okToAddNotes(GBool ignoreOwnerPW = gFalse);
 
   // Get catalog object.
   Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); }
@@ -75,7 +75,7 @@ public:
 
   // Get end position for a stream in a damaged file.
   // Returns -1 if unknown or file is not damaged.
-  int getStreamEnd(int start);
+  int getStreamEnd(int streamStart);
 
 private:
 
@@ -93,20 +93,18 @@ private:
   int streamEndsLen;           // number of valid entries in streamEnds
 #ifndef NO_DECRYPTION
   GBool encrypted;             // true if file is encrypted
+  int encVersion;              // encryption algorithm
+  int encRevision;             // security handler revision
+  int keyLength;               // length of key, in bytes
   int permFlags;               // permission bits
   Guchar fileKey[16];          // file decryption key
+  GBool ownerPasswordOk;       // true if owner password is correct
 #endif
 
   int readTrailer();
   GBool readXRef(int *pos);
   GBool constructXRef();
-  GBool checkEncrypted(GString *userPassword);
+  GBool checkEncrypted(GString *ownerPassword, GString *userPassword);
 };
 
-//------------------------------------------------------------------------
-// The global xref table
-//------------------------------------------------------------------------
-
-extern XRef *xref;
-
 #endif
index ff79d1f88928ac6a8661973e2a0247e31abd9f7a..872aadfd03b3ce6c6e506d78cb6b2c2c3d7f000c 100644 (file)
 //------------------------------------------------------------------------
 
 // xpdf version
-#define xpdfVersion "0.92"
+#define xpdfVersion "0.93a"
 
 // supported PDF version
-#define supportedPDFVersionStr "1.3"
-#define supportedPDFVersionNum 1.3
+#define supportedPDFVersionStr "1.4"
+#define supportedPDFVersionNum 1.4
 
 // copyright notice
-#define xpdfCopyright "Copyright 1996-2000 Derek B. Noonburg"
+#define xpdfCopyright "Copyright 1996-2001 Derek B. Noonburg"
 
 // default paper size (in points) for PostScript output
 #ifdef A4_PAPER
 #define defPaperHeight 792
 #endif
 
-// config file name
+// user config file name, relative to the user's home directory
 #if defined(VMS)
-#define xpdfConfigFile "xpdfrc"
+#define xpdfUserConfigFile "xpdfrc"
 #else
-#define xpdfConfigFile ".xpdfrc"
+#define xpdfUserConfigFile ".xpdfrc"
 #endif
 
+#ifndef SYSTEM_XPDFRC
+#  define SYSTEM_XPDFRC        CUPS_SERVERROOT "/pdftops.conf"
+#endif // SYSTEM_XPDFRC
+
+// system config file name (set via the configure script)
+#define xpdfSysConfigFile SYSTEM_XPDFRC
+
+// Support Unicode/etc.
+#define JAPANESE_SUPPORT 1
+#define CHINESE_GB_SUPPORT 1
+#define CHINESE_CNS_SUPPORT 1
+
 //------------------------------------------------------------------------
 // X-related constants
 //------------------------------------------------------------------------
@@ -58,6 +70,9 @@
 // number of TrueType (FreeType) fonts to cache
 #define ttFontCacheSize 32
 
+// number of FreeType (TrueType and Type 1) fonts to cache
+#define ftFontCacheSize 32
+
 //------------------------------------------------------------------------
 // popen
 //------------------------------------------------------------------------
@@ -67,7 +82,7 @@
 #define pclose _pclose
 #endif
 
-#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(WIN32) || defined(__DJGPP__) || defined(__CYGWIN32) || defined(MACOS)
+#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(__CYGWIN32__) || defined(MACOS)
 #define POPEN_READ_MODE "rb"
 #else
 #define POPEN_READ_MODE "r"
diff --git a/pdftops/configure.in b/pdftops/configure.in
deleted file mode 100644 (file)
index 8ba7984..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-dnl Process this file with autoconf to produce a configure script.
-AC_INIT(xpdf/xpdf.cc)
-
-dnl ##### Optional features.
-OPTIONS=""
-AC_ARG_ENABLE(a4-paper,
-[  --enable-a4-paper       use A4 paper size instead of Letter for
-                          PostScript output],
-OPTIONS="$OPTIONS -DA4_PAPER")
-AC_ARG_ENABLE(japanese,
-[  --enable-japanese       enable Japanese font support],
-OPTIONS="$OPTIONS -DJAPANESE_SUPPORT")
-AC_ARG_ENABLE(no-text-select,
-[  --enable-no-text-select do not allow text selection],
-OPTIONS="$OPTIONS -DNO_TEXT_SELECT")
-AC_ARG_WITH(gzip,
-[  --with-gzip             use gzip instead of uncompress],
-OPTIONS="$OPTIONS -DUSE_GZIP")
-AC_SUBST(OPTIONS)
-
-dnl ##### Checks for programs.
-AC_PROG_CC
-AC_ISC_POSIX
-AM_PROG_CC_STDC
-#if test -z "$CXX" -a "$CC" = "gcc"; then
-#  CXX="gcc"
-#fi
-AC_PROG_CXX
-AC_PROG_INSTALL
-AC_PROG_RANLIB
-
-dnl ##### Default values for Unix.
-EXE=""
-LIBPREFIX="lib"
-AR="ar rc"
-UP_DIR=""
-
-dnl ##### Check for OS/2.
-AC_CACHE_CHECK([for OS/2 (with EMX)],
-xpdf_cv_sys_os2,
-[AC_TRY_COMPILE([],
-[__EMX__],
-xpdf_cv_sys_os2=yes, xpdf_cv_sys_os2=no)])
-if test "$xpdf_cv_sys_os2" = yes; then
-  EXE=".exe"
-  LIBPREFIX=""
-  AR="ar -rc"
-fi
-
-dnl ##### Check for DOS (with DJGPP).
-AC_CACHE_CHECK([for DOS (with DJGPP)],
-xpdf_cv_sys_dos,
-[AC_TRY_COMPILE([],
-[__DJGPP__],
-xpdf_cv_sys_dos=yes, xpdf_cv_sys_dos=no)])
-if test "$xpdf_cv_sys_dos" = yes; then
-  EXE=".exe"
-  LIBPREFIX="lib"
-  AR="ar -rc"
-  UP_DIR="../"
-fi
-
-dnl ##### Do substitutions.
-AC_SUBST(EXE)
-AC_SUBST(LIBPREFIX)
-AC_SUBST(AR)
-AC_SUBST(UP_DIR)
-
-dnl ##### Checks for header files.
-AC_PATH_XTRA
-AC_HEADER_DIRENT
-
-dnl ##### Look for header that defines fd_set.
-AC_MSG_CHECKING([fd_set and sys/select.h or sys/bsdtypes.h])
-AC_TRY_COMPILE([#include <sys/types.h>],
-  [fd_set fds;], xpdf_ok=yes, xpdf_ok=no)
-if test $xpdf_ok = yes; then
-  AC_MSG_RESULT([not needed])
-else
-  AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/select.h>],
-    [fd_set fds;], xpdf_ok=yes, xpdf_ok=no)
-  if test $xpdf_ok = yes; then
-    AC_DEFINE(HAVE_SYS_SELECT_H)
-    AC_MSG_RESULT([need sys/select.h])
-  else
-    AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/bsdtypes.h>],
-      [fd_set fds;], xpdf_ok=yes, xpdf_ok=no)
-    if test $xpdf_ok = yes; then
-      AC_DEFINE(HAVE_SYS_BSDTYPES_H)
-      AC_MSG_RESULT([need sys/bsdtypes.h])
-    else
-      AC_MSG_RESULT([problem])
-    fi
-  fi
-fi
-
-dnl ##### Look for header that defines FD_ZERO.
-AC_MSG_CHECKING([FD_ZERO and strings.h or bstring.h])
-AC_TRY_COMPILE([#include <sys/types.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif],
-[fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no)
-if test $xpdf_ok = yes; then
-  AC_MSG_RESULT([not needed])
-else
-  AC_TRY_COMPILE([#include <sys/types.h>
-#include <strings.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif],
-    [fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no)
-  if test $xpdf_ok = yes; then
-    AC_DEFINE(HAVE_STRINGS_H)
-    AC_MSG_RESULT([need strings.h])
-  else
-    AC_TRY_COMPILE([#include <sys/types.h>
-#include <bstring.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif],
-      [fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no)
-    if test $xpdf_ok = yes; then
-      AC_DEFINE(HAVE_BSTRING_H)
-      AC_MSG_RESULT([need bstring.h])
-    else
-      AC_MSG_RESULT([problem])
-    fi
-  fi
-fi
-
-dnl ##### Look for rewinddir.
-AC_CHECK_FUNCS(rewinddir)
-if test $ac_cv_func_rewinddir = no; then
-  AC_CHECK_LIB(cposix, rewinddir)
-fi
-
-dnl ##### Checks for library functions.
-AC_CHECK_FUNCS(popen)
-
-dnl ##### Check select argument type: on HP-UX before version 10, select
-dnl ##### takes (int *) instead of (fd_set *).
-AC_LANG_CPLUSPLUS
-AC_CACHE_CHECK([whether select takes fd_set arguments],
-xpdf_cv_func_select_arg,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/time.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif],
-[fd_set fds;
-select(1, &fds, &fds, &fds, 0);],
-xpdf_cv_func_select_arg=yes, xpdf_cv_func_select_arg=no)])
-if test "$xpdf_cv_func_select_arg" != yes; then
-  AC_DEFINE(SELECT_TAKES_INT)
-fi
-AC_LANG_C
-
-dnl ##### Check for libXpm.
-if test -z "$no_x"; then
-  smr_CHECK_LIB(Xpm, Xpm, [pixmap library, used only for icon], 
-                XpmCreatePixmapFromData, X11/xpm.h,
-                $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS, $X_CFLAGS)
-  AC_SUBST(Xpm_LIBS)
-  AC_SUBST(Xpm_CFLAGS)
-fi
-
-dnl ##### Check for t1lib.
-if test -z "$no_x"; then
-  smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer], 
-                T1_InitLib, t1lib.h,
-                $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm, $X_CFLAGS)
-  AC_SUBST(t1_LIBS)
-  AC_SUBST(t1_CFLAGS)
-  smr_CHECK_LIB(t1x, t1x, [Type 1 font rasterizer], 
-                T1_SetX11Params, t1libx.h,
-                $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $t1_LIBS -lm,
-                $X_CFLAGS $t1_CFLAGS)
-  AC_SUBST(t1x_LIBS)
-  AC_SUBST(t1x_CFLAGS)
-fi
-
-dnl ##### Disable X-specific stuff in top-level Makefile.
-if test -n "$no_x"; then
-  X="#"
-  XPDF_TARGET="all-no-x"
-else
-  X=""
-  XPDF_TARGET="all"
-fi
-AC_SUBST(X)
-AC_SUBST(XPDF_TARGET)
-
-dnl ##### Write the makefiles.
-AC_OUTPUT(Makefile xpdf/Makefile ltk/Makefile goo/Makefile)
-
-dnl ##### Warn user if X is missing.
-if test -n "$no_x"; then
-  AC_MSG_WARN([Couldn't find X -- you will be able to compile
-        pdftops, pdftotext, pdfinfo, and pdfimages, but not xpdf])
-fi
index 5e3781793edc37b257c27a334b872873c7e189a6..e6428b71b2ef77a0c6d7d1275cc8ff70e5315ad3 100644 (file)
 #  include <cups/cups.h>
 #endif // HAVE_LIBCUPS
 
+#ifdef __sun
+// Solaris doesn't define mkstemp()...
+extern "C" {
+extern int mkstemp(char *);
+}
+#endif // __sun
+
 // Some systems don't define this, so just make it something reasonably
 // large.
 #ifndef PATH_MAX
@@ -450,23 +457,7 @@ time_t getModTime(const char *fileName) {
 }
 
 GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext) {
-#ifdef HAVE_LIBCUPS
-  char filename[1024]; // Name of temporary file...
-  int  fd;             // File descriptor...
-
-
-  (void)ext;
-
-  // Use the CUPS temporary file function on all platforms...
-  if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
-    return (gFalse);
-
-  // Make the file descriptor a FILE *, and copy the temp filename...
-  *f    = fdopen(fd, mode);
-  *name = new GString(filename);
-
-  return (gTrue);
-#elif defined(VMS) || defined(__EMX__) || defined(WIN32) || defined(ACORN) || defined(MACOS)
+#if defined(VMS) || defined(__EMX__) || defined(WIN32) || defined(ACORN) || defined(MACOS)
   //---------- non-Unix ----------
   char *s;
 
@@ -488,10 +479,36 @@ GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext)
   return gTrue;
 #else
   //---------- Unix ----------
-  char *s, *p;
+  char *s;
   int fd;
 
+  // MRS: Currently there is no standard function for creating a temporary
+  //      file with an extension; this is required when uncompressing
+  //      LZW data using the uncompress program on some UNIX, which is
+  //      looking for a ".Z" extension on the temporary filename.  Sooo,
+  //      when you print an *OLD* PDF file that uses LZW compression,
+  //      the tmpnam() function is usually the one that is called to
+  //      create the temporary file.  Under *BSD, the safer mkstemps()
+  //      function is used instead.
+  //
+  //      That said, all CUPS filters are run with TMPDIR pointing to
+  //      a private temporary directory, which by default is only
+  //      accessible to the 'lp' user.  Also, most files use Flate
+  //      compression now and will be able to use the (safer)
+  //      mkstemp() function for any temporary files...
+
   if (ext) {
+#  if HAVE_MKSTEMPS
+    if ((s = getenv("TMPDIR"))) {
+      *name = new GString(s);
+    } else {
+      *name = new GString("/tmp");
+    }
+    (*name)->append("/XXXXXX");
+    (*name)->append(ext);
+    fd = mkstemps((*name)->getCString(), strlen(ext));
+# else // HAVE_MKSTEMPS
+  char *p;
     if (!(s = tmpnam(NULL))) {
       return gFalse;
     }
@@ -502,6 +519,7 @@ GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext)
     }
     (*name)->append(ext);
     fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+#  endif // HAVE_MKSTEMPS
   } else {
 #  if HAVE_MKSTEMP
     if ((s = getenv("TMPDIR"))) {
index 7002302a69de491cb15ecda635333d657981d00f..fe107f9450353938a352f63a48d998cfbec1d826 100644 (file)
 #include "Error.h"
 #include "config.h"
 
-#ifdef HAVE_LIBCUPS
-#  include <cups/cups.h>
-#endif /* HAVE_LIBCUPS */
-
-static int firstPage = 1;
-static int lastPage = 0;
-static GBool noEmbedFonts = gFalse;
-static GBool doForm = gFalse;
-static char userPassword[33] = "";
-static GBool printVersion = gFalse;
-static GBool printHelp = gFalse;
-
-static ArgDesc argDesc[] = {
-  {"-f",      argInt,      &firstPage,      0,
-   "first page to print"},
-  {"-l",      argInt,      &lastPage,       0,
-   "last page to print"},
-  {"-paperw", argInt,      &paperWidth,     0,
-   "paper width, in points"},
-  {"-paperh", argInt,      &paperHeight,    0,
-   "paper height, in points"},
-  {"-level1", argFlag,     &psOutLevel1,    0,
-   "generate Level 1 PostScript"},
-  {"-level1sep", argFlag,  &psOutLevel1Sep, 0,
-   "generate Level 1 separable PostScript"},
-  {"-eps",    argFlag,     &psOutEPS,       0,
-   "generate Encapsulated PostScript (EPS)"},
-#if OPI_SUPPORT
-  {"-opi",    argFlag,     &psOutOPI,       0,
-   "generate OPI comments"},
-#endif
-  {"-noemb",  argFlag,     &noEmbedFonts,   0,
-   "don't embed Type 1 fonts"},
-  {"-form",   argFlag,     &doForm,         0,
-   "generate a PostScript form"},
-  {"-upw",    argString,   userPassword,    sizeof(userPassword),
-   "user password (for encrypted files)"},
-  {"-q",      argFlag,     &errQuiet,       0,
-   "don't print any messages or errors"},
-  {"-v",      argFlag,     &printVersion,   0,
-   "print copyright and version info"},
-  {"-h",      argFlag,     &printHelp,      0,
-   "print usage information"},
-  {"-help",   argFlag,     &printHelp,      0,
-   "print usage information"},
-  {NULL}
-};
+#include <cups/cups.h>
 
 int main(int argc, char *argv[]) {
-  PDFDoc *doc;
-  GString *fileName;
-  GString *psFileName;
-  GString *userPW;
-  PSOutputDev *psOut;
-  GBool ok;
-  char *p;
-#ifdef HAVE_LIBCUPS
+  PDFDoc       *doc;
+  GString      *fileName;
+  GString      *psFileName;
+  PSOutLevel   level;
+  PSOutputDev  *psOut;
   int          num_options;
   cups_option_t        *options;
   ppd_file_t   *ppd;
@@ -92,68 +43,49 @@ int main(int argc, char *argv[]) {
   char         tempfile[1024];
   char         buffer[8192];
   int          bytes;
+  int          width, length;
 
 
-  // See if we are being run as a filter...
-  if (getenv("PPD") && getenv("SOFTWARE")) {
-    // Yes, make sure status messages are not buffered...
-    setbuf(stderr, NULL);
+  // Make sure status messages are not buffered...
+  setbuf(stderr, NULL);
 
-    // Send all error messages...
-    errQuiet = 0;
+  // Send all error messages...
+  errQuiet = 0;
+
+  // Make sure we have the right number of arguments for CUPS!
+  if (argc < 6 || argc > 7) {
+    fputs("Usage: pdftops job user title copies options [filename]\n", stderr);
+    return (1);
+  }
 
-    // Make sure we have the right number of arguments for CUPS!
-    if (argc < 6 || argc > 7) {
-      fputs("Usage: pdftops job user title copies options [filename]\n", stderr);
+  // Copy stdin if needed...
+  if (argc == 6) {
+    if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL) {
+      perror("ERROR: Unable to copy PDF file");
       return (1);
     }
 
-    // Copy stdin if needed...
-    if (argc == 6) {
-      if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL) {
-       perror("ERROR: Unable to copy PDF file");
-       return (1);
-      }
+    fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
+            tempfile);
 
-      fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
-              tempfile);
+    while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+      fwrite(buffer, 1, bytes, fp);
+    fclose(fp);
 
-      while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
-       fwrite(buffer, 1, bytes, fp);
-      fclose(fp);
-
-      fileName = new GString(tempfile);
-    } else {
-      fileName = new GString(argv[6]);
-      tempfile[0] = '\0';
-    }
+    fileName = new GString(tempfile);
   } else {
+    fileName = new GString(argv[6]);
     tempfile[0] = '\0';
-#endif // HAVE_LIBCUPS
-  // parse args
-  ok = parseArgs(argDesc, &argc, argv);
-  if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
-    fprintf(stderr, "pdftops version %s\n", xpdfVersion);
-    fprintf(stderr, "%s\n", xpdfCopyright);
-    if (!printVersion) {
-      printUsage("pdftops", "<PDF-file> [<PS-file>]", argDesc);
-    }
-    exit(1);
-  }
-  if (psOutLevel1 && psOutLevel1Sep) {
-    fprintf(stderr, "Error: use -level1 or -level1sep, not both.\n");
-    exit(1);
-  }
-  if (doForm && (psOutLevel1 || psOutLevel1Sep)) {
-    fprintf(stderr, "Error: forms are only available with Level 2 output.\n");
-    exit(1);
-  }
-  fileName = new GString(argv[1]);
-#ifdef HAVE_LIBCUPS
   }
 
+  // Default to "Universal" size - min of A4 and Letter...
+  width  = 595;
+  length = 792;
+  level  = psLevel2;
+
   // Get PPD and initialize options as needed...
-  if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL) {
+  if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
+  {
     fprintf(stderr, "DEBUG: pdftops - opened PPD file \"%s\"...\n", getenv("PPD"));
 
     ppdMarkDefaults(ppd);
@@ -161,103 +93,55 @@ int main(int argc, char *argv[]) {
     cupsMarkOptions(ppd, num_options, options);
     cupsFreeOptions(num_options, options);
 
-    if ((size = ppdPageSize(ppd, NULL)) != NULL) {
-      paperWidth  = (int)size->width;
-      paperHeight = (int)size->length;
+    if ((size = ppdPageSize(ppd, NULL)) != NULL)
+    {
+      width  = (int)size->width;
+      length = (int)size->length;
     }
 
-    psOutLevel1 = ppd->language_level == 1;
-
-    fprintf(stderr, "DEBUG: pdftops - psOutLevel1 = %d, paperWidth = %d, paperHeight = %d\n",
-            psOutLevel1, paperWidth, paperHeight);
+    level = ppd->language_level == 1 ? psLevel1 : psLevel2;
 
     ppdClose(ppd);
   }
-#endif // HAVE_LIBCUPS
+
+  fprintf(stderr, "DEBUG: pdftops - level = %d, width = %d, length = %d\n",
+          level, width, length);
 
   // init error file
   errorInit();
 
   // read config file
-#ifdef HAVE_LIBCUPS
-  if ((server_root = getenv("CUPS_SERVERROOT")) != NULL) {
-    sprintf(tempfile, "%s/pdftops.conf", server_root);
-    initParams(tempfile);
-  } else
-#endif /* HAVE_LIBCUPS */
-  initParams(xpdfConfigFile);
+  if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
+    server_root = CUPS_SERVERROOT;
+
+  sprintf(tempfile, "%s/pdftops.conf", server_root);
+  initParams("", tempfile);
 
   // open PDF file
-  xref = NULL;
-  if (userPassword[0]) {
-    userPW = new GString(userPassword);
-  } else {
-    userPW = NULL;
-  }
-  doc = new PDFDoc(fileName, userPW);
-  if (userPW) {
-    delete userPW;
-  }
-  if (!doc->isOk()) {
-    goto err1;
-  }
+  doc = new PDFDoc(fileName, NULL, NULL, getenv("DEBUG") != NULL);
 
   // check for print permission
-  if (!doc->okToPrint()) {
-    error(-1, "Printing this document is not allowed.");
-    goto err1;
-  }
-
-#ifdef HAVE_LIBCUPS
-  if (getenv("PPD") && getenv("SOFTWARE")) {
-    // CUPS always needs every page and writes to stdout...
+  if (doc->isOk() && doc->okToPrint())
+  {
+    // CUPS always writes to stdout...
     psFileName = new GString("-");
-    firstPage  = 1;
-    lastPage   = doc->getNumPages();
-  } else {
-#endif // HAVE_LIBCUPS
-
-  // construct PostScript file name
-  if (argc == 3) {
-    psFileName = new GString(argv[2]);
-  } else {
-    p = fileName->getCString() + fileName->getLength() - 4;
-    if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
-      psFileName = new GString(fileName->getCString(),
-                              fileName->getLength() - 4);
-    else
-      psFileName = fileName->copy();
-    psFileName->append(psOutEPS ? ".eps" : ".ps");
-  }
 
-  // get page range
-  if (firstPage < 1)
-    firstPage = 1;
-  if (lastPage < 1 || lastPage > doc->getNumPages())
-    lastPage = doc->getNumPages();
-  if (doForm)
-    lastPage = firstPage;
+    // write PostScript file
+    psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
+                            doc->getCatalog(), 1, doc->getNumPages(),
+                           level, psModePS, 0, 1, 1, width, length);
+    if (psOut->isOk())
+      doc->displayPages(psOut, 1, doc->getNumPages(), 72, 0, gFalse);
+    delete psOut;
 
-  // check for multi-page EPS
-  if (psOutEPS && firstPage != lastPage) {
-    error(-1, "EPS files can only contain one page.");
-    goto err2;
+    // clean up
+    delete psFileName;
   }
-#ifdef HAVE_LIBCUPS
+  else
+  {
+    error(-1, "Unable to print this document.");
   }
-#endif // HAVE_LIBCUPS
-
-  // write PostScript file
-  psOut = new PSOutputDev(psFileName->getCString(), doc->getCatalog(),
-                         firstPage, lastPage, !noEmbedFonts, doForm);
-  if (psOut->isOk())
-    doc->displayPages(psOut, firstPage, lastPage, 72, 0, gFalse);
-  delete psOut;
 
-  // clean up
- err2:
-  delete psFileName;
- err1:
   delete doc;
   freeParams();
 
@@ -265,11 +149,9 @@ int main(int argc, char *argv[]) {
   Object::memCheck(stderr);
   gMemReport(stderr);
 
-#ifdef HAVE_LIBCUPS
   // Remove temp file if needed...
   if (tempfile[0])
     unlink(tempfile);
-#endif /* HAVE_LIBCUPS */
 
   return 0;
 }
index 117df28abb642771a77946fe2da6902c23eb48d0..5230f5844353f8793bcb62b07389c4bc6c5f882b 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.8.2.1 2001/05/13 18:38:30 mike Exp $"
+# "$Id: Makefile,v 1.8.2.2 2001/12/26 16:52:47 mike Exp $"
 #
 #   PPD file makefile for the Common UNIX Printing System (CUPS).
 #
@@ -28,8 +28,9 @@ include ../Makedefs
 # PPD files...
 #
 
-FILES  =       deskjet.ppd deskjet2.ppd epson9.ppd epson24.ppd laserjet.ppd \
-               okidata9.ppd okidat24.ppd stcolor.ppd stphoto.ppd
+FILES  =       deskjet.ppd deskjet2.ppd dymo.ppd epson9.ppd epson24.ppd \
+               laserjet.ppd okidata9.ppd okidat24.ppd stcolor.ppd \
+               stcolor2.ppd stphoto.ppd stphoto2.ppd
 
 
 #
@@ -51,11 +52,12 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(DATADIR)/model
-       $(CHMOD) ugo+rx $(DATADIR)/model
-       $(INSTALL_DATA) $(FILES) $(DATADIR)/model
+       $(INSTALL_DIR) $(DATADIR)/model
+       for file in $(FILES); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/model; \
+       done
 
 
 #
-# End of "$Id: Makefile,v 1.8.2.1 2001/05/13 18:38:30 mike Exp $".
+# End of "$Id: Makefile,v 1.8.2.2 2001/12/26 16:52:47 mike Exp $".
 #
index d6f487b9ddabe87baa32277b60b4a62de99bfbff..8b86447a70b2ba9b33537930c1d8d333322939d6 100644 (file)
@@ -1,6 +1,6 @@
 *PPD-Adobe: "4.3"
 *%
-*% "$Id: deskjet2.ppd,v 1.1.2.1 2001/05/13 18:38:30 mike Exp $"
+*% "$Id: deskjet2.ppd,v 1.1.2.2 2001/12/26 16:52:47 mike Exp $"
 *%
 *%   Second sample HP DeskJet driver PPD file for the Common UNIX Printing
 *%   System (CUPS).
 *CloseUI: *ColorModel
 
 *OpenUI *Duplex/Double-Sided Printing: PickOne
-*OrderDependency: 20 AnySetup *Duplex
+*OrderDependency: 20 PageSetup *Duplex
 *DefaultDuplex: None
 *Duplex None/Off:      "<</Duplex false>>setpagedevice"
 *Duplex DuplexNoTumble/Long Edge (Standard):   "<</Duplex true/Tumble false>>setpagedevice"
 *Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
 *Font ZapfDingbats: Special "(001.004S)" Standard ROM
 *%
-*% End of "$Id: deskjet2.ppd,v 1.1.2.1 2001/05/13 18:38:30 mike Exp $".
+*% End of "$Id: deskjet2.ppd,v 1.1.2.2 2001/12/26 16:52:47 mike Exp $".
 *%
index cbc619809ea5254e24eaf17bec6e0fbb4195b9c6..b0ab6c9cbbe6fafe35f105de8b5977dd0064bec4 100644 (file)
@@ -1,6 +1,6 @@
 *PPD-Adobe: "4.3"
 *%
-*% "$Id: dymo.ppd,v 1.4 2001/07/18 18:18:30 mike Exp $"
+*% "$Id: dymo.ppd,v 1.4.2.1 2001/12/26 16:52:47 mike Exp $"
 *%
 *%   Sample DYMO label printer driver PPD file for the Common UNIX Printing
 *%   System (CUPS).
 *Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
 *Font ZapfDingbats: Special "(001.004S)" Standard ROM
 *%
-*% End of "$Id: dymo.ppd,v 1.4 2001/07/18 18:18:30 mike Exp $".
+*% End of "$Id: dymo.ppd,v 1.4.2.1 2001/12/26 16:52:47 mike Exp $".
 *%
index b3bffac57d1a41fcef61adb4737e8773891424c7..fbc39912e75f012a57fc860b7238ee13eeb49e7a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.31.2.1 2001/05/13 18:38:31 mike Exp $"
+# "$Id: Makefile,v 1.31.2.2 2001/12/26 16:52:48 mike Exp $"
 #
 #   GNU Ghostscript makefile for the Common UNIX Printing System (CUPS).
 #
@@ -376,14 +376,12 @@ clean:
 #
 
 install:       $(TARGETS)
-       -$(MKDIR) $(SERVERBIN)/filter
-       $(CHMOD) ugo+rx $(SERVERBIN)
-       $(CHMOD) ugo+rx $(SERVERBIN)/filter
+       $(INSTALL_DIR) $(SERVERBIN)/filter
        $(INSTALL_BIN) pstoraster $(SERVERBIN)/filter
-       -$(MKDIR) $(DATADIR)/pstoraster
-       $(CHMOD) ugo+rx $(DATADIR)
-       $(CHMOD) ugo+rx $(DATADIR)/pstoraster
-       $(INSTALL_DATA) $(DFILES) $(DATADIR)/pstoraster
+       $(INSTALL_DIR) $(DATADIR)/pstoraster
+       for file in $(DFILES); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/pstoraster; \
+       done
 
 
 #
@@ -419,6 +417,16 @@ pstoraster:        pstoraster.o libgs.a ../Makedefs ../cups/$(LIBCUPS)
                $(LINKCUPSIMAGE) $(IMGLIBS) $(DSOLIBS) $(LIBS) -lm
 
 
+#
+# purify - target to test Ghostscript to see how leaky it is...
+#
+
+purify:        pstoraster.o libgs.a ../Makedefs ../cups/$(LIBCUPS)
+       echo Linking $@...
+       purify $(CC) $(LDFLAGS) -o pstoraster.pure pstoraster.o libgs.a \
+               $(LINKCUPSIMAGE) $(IMGLIBS) $(DSOLIBS) $(LIBS) -lm
+
+
 #
 # Generate dependencies for Ghostscript source files...
 #
@@ -442,5 +450,5 @@ include Dependencies
 
 
 #
-# End of "$Id: Makefile,v 1.31.2.1 2001/05/13 18:38:31 mike Exp $".
+# End of "$Id: Makefile,v 1.31.2.2 2001/12/26 16:52:48 mike Exp $".
 #
index 187ec41de0aa07caac0e59f1d5573b2b98ee1950..d3e6147379b0d229aff603704abddce27b6a725e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: gdevcups.c,v 1.43 2001/03/29 14:58:54 mike Exp $"
+ * "$Id: gdevcups.c,v 1.43.2.1 2001/12/26 16:52:48 mike Exp $"
  *
  *   GNU Ghostscript raster output driver for the Common UNIX Printing
  *   System (CUPS).
@@ -324,8 +324,8 @@ cups_get_matrix(gx_device *pdev,    /* I - Device info */
     fprintf(stderr, "DEBUG: cups->ppd->flip_duplex = %d\n", cups->ppd->flip_duplex);
   }
 
-  if (cups->header.Duplex && cups->ppd && cups->ppd->flip_duplex &&
-      !(cups->page & 1))
+  if (cups->header.Duplex && !cups->header.Tumble &&
+      cups->ppd && cups->ppd->flip_duplex && !(cups->page & 1))
   {
     pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
     pmat->xy = 0.0;
@@ -1492,6 +1492,7 @@ cups_put_params(gx_device     *pdev,      /* I - Device info */
   gs_param_string      stringval;      /* String value */
   gs_param_float_array arrayval;       /* Float array value */
   int                  old_depth;      /* Old color depth */
+  int                  size_set;       /* Was the size set? */
   gdev_prn_space_params        sp;             /* Space parameter data */
 
 
@@ -1570,6 +1571,7 @@ cups_put_params(gx_device     *pdev,      /* I - Device info */
   }
 
   old_depth = pdev->color_info.depth;
+  size_set  = param_read_float_array(plist, "PageSize", &arrayval) == 0;
 
   stringoption(MediaClass, "MediaClass")
   stringoption(MediaColor, "MediaColor")
@@ -1701,6 +1703,20 @@ cups_put_params(gx_device     *pdev,     /* I - Device info */
   cups->header.PageSize[0] = pdev->PageSize[0];
   cups->header.PageSize[1] = pdev->PageSize[1];
 
+ /*
+  * Reallocate memory if the size or color depth was changed...
+  */
+
+  if (old_depth != pdev->color_info.depth || size_set)
+  {
+    fputs("DEBUG: Reallocating memory...\n", stderr);
+    sp = ((gx_device_printer *)pdev)->space_params;
+
+    if ((code = gdev_prn_reallocate_memory(pdev, &sp, pdev->width,
+                                           pdev->height)) < 0)
+      return (code);
+  }
+
 #ifdef DEBUG
   fprintf(stderr, "DEBUG: ppd = %8x\n", cups->ppd);
   fprintf(stderr, "DEBUG: PageSize = [ %.3f %.3f ]\n",
@@ -1974,12 +1990,14 @@ cups_print_chunked(gx_device_printer *pdev,     /* I - Printer device */
   int          flip;                           /* Flip scanline? */
 
 
-  if (cups->header.Duplex && cups->ppd && cups->ppd->flip_duplex &&
-      !(cups->page & 1))
+  if (cups->header.Duplex && !cups->header.Tumble &&
+      cups->ppd && cups->ppd->flip_duplex && !(cups->page & 1))
     flip = 1;
   else
     flip = 0;
 
+  fprintf(stderr, "DEBUG: cups_print_chunked - flip = %d\n", flip);
+
  /*
   * Loop through the page bitmap and write chunked pixels, reversing as
   * needed...
@@ -2120,12 +2138,14 @@ cups_print_banded(gx_device_printer *pdev,      /* I - Printer device */
   int          flip;                           /* Flip scanline? */
 
 
-  if (cups->header.Duplex && cups->ppd && cups->ppd->flip_duplex &&
-      !(cups->page & 1))
+  if (cups->header.Duplex && !cups->header.Tumble &&
+      cups->ppd && cups->ppd->flip_duplex && !(cups->page & 1))
     flip = 1;
   else
     flip = 0;
 
+  fprintf(stderr, "DEBUG: cups_print_banded - flip = %d\n", flip);
+
  /*
   * Loop through the page bitmap and write banded pixels...  We have
   * to separate each chunked color as needed...
@@ -2310,14 +2330,20 @@ cups_print_banded(gx_device_printer *pdev,      /* I - Printer device */
                       x > 0;
                       x --, srcptr ++)
                  {
+                   /*
+                    * Note: Because of the way the pointers are setup,
+                    *       the following code is correct even though
+                    *       the names don't match...
+                    */
+
                    if (*srcptr & 0x20)
-                     *kptr |= bit;
-                   if (*srcptr & 0x10)
                      *cptr |= bit;
-                   if (*srcptr & 0x08)
+                   if (*srcptr & 0x10)
                      *mptr |= bit;
-                   if (*srcptr & 0x04)
+                   if (*srcptr & 0x08)
                      *yptr |= bit;
+                   if (*srcptr & 0x04)
+                     *kptr |= bit;
                    if (*srcptr & 0x02)
                      *lcptr |= bit;
                    if (*srcptr & 0x01)
@@ -3035,5 +3061,5 @@ cups_print_planar(gx_device_printer *pdev,        /* I - Printer device */
 
 
 /*
- * End of "$Id: gdevcups.c,v 1.43 2001/03/29 14:58:54 mike Exp $".
+ * End of "$Id: gdevcups.c,v 1.43.2.1 2001/12/26 16:52:48 mike Exp $".
  */
index f04803f0cf959401b0049470b4a0dad03bebddea..c64e70338011443197be87fb32f93f515639e2da 100644 (file)
@@ -22,7 +22,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: gscrdp.c,v 1.2 2000/10/13 01:04:41 mike Exp $ */
+/*$Id: gscrdp.c,v 1.2.2.1 2001/12/26 16:52:49 mike Exp $ */
 /* CIE color rendering dictionary creation */
 #include "math_.h"
 #include "memory_.h"
@@ -34,6 +34,7 @@
 #include "gscolor2.h"          /* for gs_set/currentcolorrendering */
 #include "gscrdp.h"
 #include "gxarith.h"
+#include "gsmalloc.h"
 
 /* Define the CRD type that we use here. */
 #define CRD_TYPE 101
index e793af8d7f08c888e28d49ca87d726d4ae7d2434..f9553b0d5f7179a0dd95a70581860d77b9b7c711 100644 (file)
@@ -22,7 +22,7 @@
   GNU software to build or run it.
 */
 
-/*$Id: isave.c,v 1.2 2000/03/08 23:15:15 mike Exp $ */
+/*$Id: isave.c,v 1.2.2.1 2001/12/26 16:52:49 mike Exp $ */
 /* Save/restore manager for Ghostscript interpreter */
 #include "ghost.h"
 #include "memory_.h"
@@ -447,9 +447,11 @@ alloc_save_change(gs_dual_memory_t * dmem, const ref * pcont,
        gs_abort();
     }
     if (r_is_packed(where))
-       *(ref_packed *) & cp->contents = *where;
+       *(ref_packed *)(&(cp->contents)) = *where;
     else {
-       ref_assign_inline(&cp->contents, (ref *) where);
+/* MRS - the following inline assign didn't work...
+       ref_assign_inline(&cp->contents, (ref *) where);*/
+       ref_assign((&(cp->contents)), (ref *) where);
        r_set_attrs((ref *) where, l_new);
     }
     mem->changes = cp;
index 5b64b0d15219bb7cc6053933d8ac85ed3aae05a8..ea95d5ecab6edca6603b547f3d9d5dfb3438b51b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: pstoraster.c,v 1.19 2001/01/24 17:20:05 mike Exp $"
+ * "$Id: pstoraster.c,v 1.19.2.1 2001/12/26 16:52:49 mike Exp $"
  *
  *   PostScript RIP filter main entry for the Common UNIX Printing System
  *   (CUPS).
 #include <cups/string.h>
 #include <stdlib.h>
 
+#ifdef __sgi
+#  include <sys/sysmips.h>
+#endif /* __sgi */
+
 #undef bool
 #undef uchar
 #undef uint
@@ -100,6 +104,16 @@ main(int  argc,            /* I - Number of command-line arguments */
   const char           *fontpath;      /* CUPS_FONTPATH env variable */
 
 
+#ifdef __sgi
+ /*
+  * Force unaligned memory access handling on R12K processors...
+  * (this should be done by default...)  Ghostscript is not 64-bit
+  * safe...
+  */
+
+  sysmips(MIPS_FIXADE, 1, 0, 0);
+#endif /* __sgi */
+
  /*
   * Force the locale to "C" to avoid bugs...
   */
@@ -235,5 +249,5 @@ define_string(const char *name,     /* I - Variable to set */
 
 
 /*
- * End of "$Id: pstoraster.c,v 1.19 2001/01/24 17:20:05 mike Exp $".
+ * End of "$Id: pstoraster.c,v 1.19.2.1 2001/12/26 16:52:49 mike Exp $".
  */
index f335c29ee60d14e3fe59e6eaf744c9c404468298..fa470270810cb6d51f56d7fc4bc4bf764815d693 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.36 2001/02/21 17:01:16 mike Exp $"
+# "$Id: Makefile,v 1.36.2.1 2001/12/26 16:52:49 mike Exp $"
 #
 #   Scheduler Makefile for the Common UNIX Printing System (CUPS).
 #
@@ -52,25 +52,17 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(SBINDIR)
-       $(CHMOD) ugo+rx $(SBINDIR)
+       $(INSTALL_DIR) $(SBINDIR)
        $(INSTALL_BIN) cupsd $(SBINDIR)
-       -$(MKDIR) $(SERVERBIN)/daemon
-       $(CHMOD) ugo+rx $(SERVERBIN)/daemon
+       $(INSTALL_DIR) $(SERVERBIN)/daemon
        $(INSTALL_BIN) cups-lpd $(SERVERBIN)/daemon
        $(INSTALL_BIN) cups-polld $(SERVERBIN)/daemon
-       -$(MKDIR) $(SERVERROOT)/certs
-       $(CHMOD) ugo+x,go-rw $(SERVERROOT)/certs
-       -$(MKDIR) $(SERVERROOT)/interfaces
-       $(CHMOD) ugo+rx $(SERVERROOT)/interfaces
-       -$(MKDIR) $(SERVERROOT)/ppd
-       $(CHMOD) ugo+rx $(SERVERROOT)/ppd
-       -$(MKDIR) $(LOGDIR)
-       $(CHMOD) ugo+rx $(LOGDIR)
-       -$(MKDIR) $(REQUESTS)
-       $(CHMOD) u+rwx,go-rwx $(REQUESTS)
-       -$(MKDIR) $(REQUESTS)/tmp
-       $(CHMOD) u+rwx,go-rwx,+t $(REQUESTS)/tmp
+       $(INSTALL_DIR) -m 711 -o $(CUPS_USER) -g $(CUPS_GROUP) $(SERVERROOT)/certs
+       $(INSTALL_DIR) $(SERVERROOT)/interfaces
+       $(INSTALL_DIR) $(SERVERROOT)/ppd
+       $(INSTALL_DIR) $(LOGDIR)
+       $(INSTALL_DIR) -m 700 -o $(CUPS_USER) -g $(CUPS_GROUP) $(REQUESTS)
+       $(INSTALL_DIR) -m 1700 -o $(CUPS_USER) -g $(CUPS_GROUP) $(REQUESTS)/tmp
 
 
 #
@@ -80,7 +72,7 @@ install:
 cupsd: $(CUPSDOBJS) libmime.a ../cups/$(LIBCUPS)
        echo Linking $@...
        $(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) libmime.a \
-               $(LIBZ) $(SSLLIBS) $(LIBS) $(LIBMALLOC)
+               $(LIBZ) $(SSLLIBS) $(LIBSLP) $(PAMLIBS) $(LIBS) $(LIBMALLOC)
 
 $(CUPSDOBJS):  auth.h banners.h cert.h classes.h client.h conf.h \
                cupsd.h dirsvc.h job.h mime.h printers.h \
@@ -149,5 +141,5 @@ $(OBJS):    ../config.h ../Makedefs
 
 
 #
-# End of "$Id: Makefile,v 1.36 2001/02/21 17:01:16 mike Exp $".
+# End of "$Id: Makefile,v 1.36.2.1 2001/12/26 16:52:49 mike Exp $".
 #
index fc0e2d809c8423b1d71e8577f8faa9acafddabdc..e2420b104af4d92e04ed06c521305b31685c3716 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: auth.c,v 1.41.2.2 2001/05/13 18:38:33 mike Exp $"
+ * "$Id: auth.c,v 1.41.2.3 2001/12/26 16:52:50 mike Exp $"
  *
  *   Authorization routines for the Common UNIX Printing System (CUPS).
  *
  *   IsAuthorized()       - Check to see if the user is authorized...
  *   add_allow()          - Add an allow mask to the location.
  *   add_deny()           - Add a deny mask to the location.
+ *   cups_crypt()         - Encrypt the password using the DES or MD5
+ *                          algorithms, as needed.
  *   get_md5_passwd()     - Get an MD5 password.
  *   pam_func()           - PAM conversation function.
+ *   to64()               - Base64-encode an integer value...
  */
 
 /*
@@ -53,6 +56,7 @@
 #include "cupsd.h"
 #include <pwd.h>
 #include <grp.h>
+#include <cups/md5.h>
 #ifdef HAVE_SHADOW_H
 #  include <shadow.h>
 #endif /* HAVE_SHADOW_H */
 
 static authmask_t      *add_allow(location_t *loc);
 static authmask_t      *add_deny(location_t *loc);
+#if !HAVE_LIBPAM
+static char            *cups_crypt(const char *pw, const char *salt);
+#endif /* !HAVE_LIBPAM */
 static char            *get_md5_passwd(const char *username, const char *group,
                                        char passwd[33]);
 #if HAVE_LIBPAM
 static int             pam_func(int, const struct pam_message **,
                                 struct pam_response **, void *);
+#else
+static void            to64(char *s, unsigned long v, int n);
 #endif /* HAVE_LIBPAM */
 
 
@@ -515,7 +524,8 @@ DenyIP(location_t *loc,             /* I - Location to add to */
  */
 
 location_t *                   /* O - Location that matches */
-FindBest(client_t *con)                /* I - Connection */
+FindBest(const char   *path,   /* I - Resource path */
+         http_state_t state)   /* I - HTTP state/request */
 {
   int          i;              /* Looping var */
   location_t   *loc,           /* Current location */
@@ -541,11 +551,35 @@ FindBest(client_t *con)           /* I - Connection */
                };
 
 
+ /*
+  * First copy the connection URI to a local string so we have drop
+  * any .ppd extension from the pathname in /printers or /classes
+  * URIs...
+  */
+
+  strncpy(uri, path, sizeof(uri) - 1);
+  uri[sizeof(uri) - 1] = '\0';
+
+  if (strncmp(uri, "/printers/", 10) == 0 ||
+      strncmp(uri, "/classes/", 9) == 0)
+  {
+   /*
+    * Check if the URI has .ppd on the end...
+    */
+
+    uriptr = uri + strlen(uri) - 4; /* len > 4 if we get here... */
+
+    if (strcmp(uriptr, ".ppd") == 0)
+      *uriptr = '\0';
+  }
+
+  LogMessage(L_DEBUG2, "FindBest: uri = \"%s\"...", uri);
+
  /*
   * Loop through the list of locations to find a match...
   */
 
-  limit   = limits[con->http.state];
+  limit   = limits[state];
   best    = NULL;
   bestlen = 0;
 
@@ -612,7 +646,8 @@ IsAuthorized(client_t *con) /* I - Connection */
   struct group *grp;           /* Group data */
   char         nonce[HTTP_MAX_VALUE],
                                /* Nonce value from client */
-               md5[33];        /* MD5 password */
+               md5[33],        /* MD5 password */
+               basicmd5[33];   /* MD5 of Basic password */
 #if HAVE_LIBPAM
   pam_handle_t *pamh;          /* PAM authentication handle */
   int          pamerr;         /* PAM error code */
@@ -653,7 +688,7 @@ IsAuthorized(client_t *con) /* I - Connection */
   * not authorized...
   */
 
-  if ((best = FindBest(con)) == NULL)
+  if ((best = FindBest(con->uri, con->http.state)) == NULL)
     return (HTTP_FORBIDDEN);
 
  /*
@@ -702,6 +737,14 @@ IsAuthorized(client_t *con)        /* I - Connection */
 
     auth = AUTH_ALLOW;
   }
+  else if (best->num_allow == 0 && best->num_deny == 0)
+  {
+   /*
+    * No allow/deny lines - allow access...
+    */
+
+    auth = AUTH_ALLOW;
+  }
   else
   {
    /*
@@ -795,7 +838,10 @@ IsAuthorized(client_t *con)        /* I - Connection */
   LogMessage(L_DEBUG2, "IsAuthorized: Checking \"%s\", address = %08x, hostname = \"%s\"",
              con->username, address, con->http.hostname);
 
-  if (strcasecmp(con->http.hostname, "localhost") != 0 ||
+  pw = NULL;
+
+  if ((address != 0x7f000001 &&
+       strcasecmp(con->http.hostname, "localhost") != 0) ||
       strncmp(con->http.fields[HTTP_FIELD_AUTHORIZATION], "Local", 5) != 0)
   {
    /*
@@ -806,172 +852,243 @@ IsAuthorized(client_t *con)     /* I - Connection */
       return (HTTP_UNAUTHORIZED);
 
    /*
-    * See if we are doing Digest or Basic authentication...
+    * See what kind of authentication we are doing...
     */
 
-    if (best->type == AUTH_BASIC)
+    switch (best->type)
     {
+      case AUTH_BASIC :
+        /*
+         * Get the user info...
+         */
+
+         pw = getpwnam(con->username); /* Get the current password */
+         endpwent();                           /* Close the password file */
+
+         if (pw == NULL)                       /* No such user... */
+         {
+           LogMessage(L_WARN, "IsAuthorized: Unknown username \"%s\"; access denied.",
+                      con->username);
+           return (HTTP_UNAUTHORIZED);
+         }
+
 #if HAVE_LIBPAM
-     /*
-      * Only use PAM to do authentication.  This allows MD5 passwords, among
-      * other things...
-      */
+        /*
+         * Only use PAM to do authentication.  This allows MD5 passwords, among
+         * other things...
+         */
 
-      pamdata.conv        = pam_func;
-      pamdata.appdata_ptr = con;
+         pamdata.conv        = pam_func;
+         pamdata.appdata_ptr = con;
 
 #  ifdef __hpux
-     /*
-      * Workaround for HP-UX bug in pam_unix; see pam_conv() below for
-      * more info...
-      */
+        /*
+         * Workaround for HP-UX bug in pam_unix; see pam_conv() below for
+         * more info...
+         */
 
-      auth_client = con;
+         auth_client = con;
 #  endif /* __hpux */
 
-      DEBUG_printf(("IsAuthorized: Setting appdata_ptr = %p\n", con));
+         DEBUG_printf(("IsAuthorized: Setting appdata_ptr = %p\n", con));
 
-      pamerr = pam_start("cups", con->username, &pamdata, &pamh);
-      if (pamerr != PAM_SUCCESS)
-      {
-       LogMessage(L_ERROR, "IsAuthorized: pam_start() returned %d (%s)!\n",
-                  pamerr, pam_strerror(pamh, pamerr));
-       pam_end(pamh, 0);
-       return (HTTP_UNAUTHORIZED);
-      }
-
-      pamerr = pam_authenticate(pamh, PAM_SILENT);
-      if (pamerr != PAM_SUCCESS)
-      {
-       LogMessage(L_ERROR, "IsAuthorized: pam_authenticate() returned %d (%s)!\n",
-                  pamerr, pam_strerror(pamh, pamerr));
-       pam_end(pamh, 0);
-       return (HTTP_UNAUTHORIZED);
-      }
-
-      pamerr = pam_acct_mgmt(pamh, PAM_SILENT);
-      if (pamerr != PAM_SUCCESS)
-      {
-       LogMessage(L_ERROR, "IsAuthorized: pam_acct_mgmt() returned %d (%s)!\n",
-                  pamerr, pam_strerror(pamh, pamerr));
-       pam_end(pamh, 0);
-       return (HTTP_UNAUTHORIZED);
-      }
+         pamerr = pam_start("cups", con->username, &pamdata, &pamh);
+         if (pamerr != PAM_SUCCESS)
+         {
+           LogMessage(L_ERROR, "IsAuthorized: pam_start() returned %d (%s)!\n",
+                      pamerr, pam_strerror(pamh, pamerr));
+           pam_end(pamh, 0);
+           return (HTTP_UNAUTHORIZED);
+         }
+
+         pamerr = pam_authenticate(pamh, PAM_SILENT);
+         if (pamerr != PAM_SUCCESS)
+         {
+           LogMessage(L_ERROR, "IsAuthorized: pam_authenticate() returned %d (%s)!\n",
+                      pamerr, pam_strerror(pamh, pamerr));
+           pam_end(pamh, 0);
+           return (HTTP_UNAUTHORIZED);
+         }
+
+         pamerr = pam_acct_mgmt(pamh, PAM_SILENT);
+         if (pamerr != PAM_SUCCESS)
+         {
+           LogMessage(L_ERROR, "IsAuthorized: pam_acct_mgmt() returned %d (%s)!\n",
+                      pamerr, pam_strerror(pamh, pamerr));
+           pam_end(pamh, 0);
+           return (HTTP_UNAUTHORIZED);
+         }
 
-      pam_end(pamh, PAM_SUCCESS);
+         pam_end(pamh, PAM_SUCCESS);
 #elif defined(HAVE_USERSEC_H)
-     /*
-      * Use AIX authentication interface...
-      */
+        /*
+         * Use AIX authentication interface...
+         */
 
-      LogMessage(L_DEBUG, "IsAuthorized: AIX authenticate of username \"%s\"",
-                 con->username);
+         LogMessage(L_DEBUG, "IsAuthorized: AIX authenticate of username \"%s\"",
+                     con->username);
 
-      reenter = 1;
-      if (authenticate(con->username, con->password, &reenter, &authmsg) != 0)
-      {
-       LogMessage(L_DEBUG, "IsAuthorized: Unable to authenticate username \"%s\": %s",
-                  con->username, strerror(errno));
-       return (HTTP_UNAUTHORIZED);
-      }
+         reenter = 1;
+         if (authenticate(con->username, con->password, &reenter, &authmsg) != 0)
+         {
+           LogMessage(L_DEBUG, "IsAuthorized: Unable to authenticate username \"%s\": %s",
+                      con->username, strerror(errno));
+           return (HTTP_UNAUTHORIZED);
+         }
 #else
 #  ifdef HAVE_SHADOW_H
-      spw = getspnam(con->username);
-      endspent();
-
-      if (spw == NULL && strcmp(pw->pw_passwd, "x") == 0)
-      {                                        /* Don't allow blank passwords! */
-       LogMessage(L_WARN, "IsAuthorized: Username \"%s\" has no shadow password; access denied.",
-                  con->username);
-       return (HTTP_UNAUTHORIZED);             /* No such user or bad shadow file */
-      }
+         spw = getspnam(con->username);
+         endspent();
+
+         if (spw == NULL && strcmp(pw->pw_passwd, "x") == 0)
+         {                                     /* Don't allow blank passwords! */
+           LogMessage(L_WARN, "IsAuthorized: Username \"%s\" has no shadow password; access denied.",
+                      con->username);
+           return (HTTP_UNAUTHORIZED); /* No such user or bad shadow file */
+         }
 
 #    ifdef DEBUG
-      if (spw != NULL)
-       printf("spw->sp_pwdp = \"%s\"\n", spw->sp_pwdp);
-      else
-       puts("spw = NULL");
+         if (spw != NULL)
+           printf("spw->sp_pwdp = \"%s\"\n", spw->sp_pwdp);
+         else
+           puts("spw = NULL");
 #    endif /* DEBUG */
 
-      if (spw != NULL && spw->sp_pwdp[0] == '\0' && pw->pw_passwd[0] == '\0')
+         if (spw != NULL && spw->sp_pwdp[0] == '\0' && pw->pw_passwd[0] == '\0')
 #  else
-      if (pw->pw_passwd[0] == '\0')            /* Don't allow blank passwords! */
+         if (pw->pw_passwd[0] == '\0')
 #  endif /* HAVE_SHADOW_H */
-      {                                        /* Don't allow blank passwords! */
-       LogMessage(L_WARN, "IsAuthorized: Username \"%s\" has no password; access denied.",
-                  con->username);
-       return (HTTP_UNAUTHORIZED);
-      }
+         {                                     /* Don't allow blank passwords! */
+           LogMessage(L_WARN, "IsAuthorized: Username \"%s\" has no password; access denied.",
+                      con->username);
+           return (HTTP_UNAUTHORIZED);
+         }
 
-     /*
-      * OK, the password isn't blank, so compare with what came from the client...
-      */
+        /*
+         * OK, the password isn't blank, so compare with what came from the client...
+         */
 
-      LogMessage(L_DEBUG2, "IsAuthorized: pw_passwd = %s, crypt = %s",
-                pw->pw_passwd, crypt(con->password, pw->pw_passwd));
+         pass = cups_crypt(con->password, pw->pw_passwd);
 
-      pass = crypt(con->password, pw->pw_passwd);
+         LogMessage(L_DEBUG2, "IsAuthorized: pw_passwd = %s, crypt = %s",
+                    pw->pw_passwd, pass);
 
-      if (pass == NULL ||
-         strcmp(pw->pw_passwd, crypt(con->password, pw->pw_passwd)) != 0)
-      {
+         if (pass == NULL || strcmp(pw->pw_passwd, pass) != 0)
+         {
 #  ifdef HAVE_SHADOW_H
-       if (spw != NULL)
-       {
-         LogMessage(L_DEBUG2, "IsAuthorized: sp_pwdp = %s, crypt = %s",
-                    spw->sp_pwdp, crypt(con->password, spw->sp_pwdp));
+           if (spw != NULL)
+           {
+             pass = cups_crypt(con->password, spw->sp_pwdp);
 
-         pass = crypt(con->password, spw->sp_pwdp);
+             LogMessage(L_DEBUG2, "IsAuthorized: sp_pwdp = %s, crypt = %s",
+                        spw->sp_pwdp, pass);
 
-         if (pass == NULL ||
-              strcmp(spw->sp_pwdp, crypt(con->password, spw->sp_pwdp)) != 0)
-           return (HTTP_UNAUTHORIZED);
-       }
-       else
+             if (pass == NULL || strcmp(spw->sp_pwdp, pass) != 0)
+               return (HTTP_UNAUTHORIZED);
+           }
+           else
 #  endif /* HAVE_SHADOW_H */
-         return (HTTP_UNAUTHORIZED);
-      }
+             return (HTTP_UNAUTHORIZED);
+         }
 #endif /* HAVE_LIBPAM */
-    }
-    else
-    {
-     /*
-      * Do Digest authentication...
-      */
-
-      if (!httpGetSubField(&(con->http), HTTP_FIELD_WWW_AUTHENTICATE, "nonce",
-                           nonce))
-      {
-        LogMessage(L_ERROR, "IsAuthorized: No nonce value for Digest authentication!");
-        return (HTTP_UNAUTHORIZED);
-      }
-
-      if (strcmp(con->http.hostname, nonce) != 0)
-      {
-        LogMessage(L_ERROR, "IsAuthorized: Nonce value error!");
-        LogMessage(L_ERROR, "IsAuthorized: Expected \"%s\",",
-                  con->http.hostname);
-        LogMessage(L_ERROR, "IsAuthorized: Got \"%s\"!", nonce);
-        return (HTTP_UNAUTHORIZED);
-      }
+          break;
+      case AUTH_DIGEST :
+        /*
+         * Do Digest authentication...
+         */
 
-      if (!get_md5_passwd(con->username, best->names[0], md5))
-      {
-        LogMessage(L_ERROR, "IsAuthorized: No user:group for \"%s:%s\" in passwd.md5!",
-                  con->username, best->names[0]);
-        return (HTTP_UNAUTHORIZED);
-      }
+         if (!httpGetSubField(&(con->http), HTTP_FIELD_AUTHORIZATION, "nonce",
+                               nonce))
+         {
+            LogMessage(L_ERROR, "IsAuthorized: No nonce value for Digest authentication!");
+            return (HTTP_UNAUTHORIZED);
+         }
+
+         if (strcmp(con->http.hostname, nonce) != 0)
+         {
+            LogMessage(L_ERROR, "IsAuthorized: Nonce value error!");
+            LogMessage(L_ERROR, "IsAuthorized: Expected \"%s\",",
+                      con->http.hostname);
+            LogMessage(L_ERROR, "IsAuthorized: Got \"%s\"!", nonce);
+            return (HTTP_UNAUTHORIZED);
+         }
+
+         LogMessage(L_DEBUG2, "IsAuthorized: nonce = \"%s\"", nonce);
+
+         if (best->num_names && best->level == AUTH_GROUP)
+         {
+            for (i = 0; i < best->num_names; i ++)
+             if (get_md5_passwd(con->username, best->names[i], md5))
+               break;
+
+            if (i >= best->num_names)
+             md5[0] = '\0';
+         }
+         else if (!get_md5_passwd(con->username, NULL, md5))
+           md5[0] = '\0';
+
+
+         if (!md5[0])
+         {
+            LogMessage(L_ERROR, "IsAuthorized: No matching user:group for \"%s\" in passwd.md5!",
+                      con->username);
+            return (HTTP_UNAUTHORIZED);
+         }
+
+         httpMD5Final(nonce, states[con->http.state], con->uri, md5);
+
+         if (strcmp(md5, con->password) != 0)
+         {
+            LogMessage(L_ERROR, "IsAuthorized: MD5s \"%s\" and \"%s\" don't match!",
+                      md5, con->password);
+            return (HTTP_UNAUTHORIZED);
+         }
+          break;
 
-      httpMD5Final(nonce, states[con->http.state], con->uri, md5);
+      case AUTH_BASICDIGEST :
+         /*
+         * Do Basic authentication with the Digest password file...
+         */
 
-      if (strcmp(md5, con->password) != 0)
-      {
-        LogMessage(L_ERROR, "IsAuthorized: MD5s \"%s\" and \"%s\" don't match!",
-                  md5, con->password);
-        return (HTTP_UNAUTHORIZED);
-      }
+         if (best->num_names && best->level == AUTH_GROUP)
+         {
+            for (i = 0; i < best->num_names; i ++)
+             if (get_md5_passwd(con->username, best->names[i], md5))
+               break;
+
+            if (i >= best->num_names)
+             md5[0] = '\0';
+         }
+         else if (!get_md5_passwd(con->username, NULL, md5))
+           md5[0] = '\0';
+
+         if (!md5[0])
+         {
+            LogMessage(L_ERROR, "IsAuthorized: No matching user:group for \"%s\" in passwd.md5!",
+                      con->username);
+            return (HTTP_UNAUTHORIZED);
+         }
+
+         httpMD5(con->username, "CUPS", con->password, basicmd5);
+
+         if (strcmp(md5, basicmd5) != 0)
+         {
+            LogMessage(L_ERROR, "IsAuthorized: MD5s \"%s\" and \"%s\" don't match!",
+                      md5, basicmd5);
+            return (HTTP_UNAUTHORIZED);
+         }
+         break;
     }
   }
+  else
+  {
+   /*
+    * Get password entry for certificate-based auth...
+    */
+
+    pw = getpwnam(con->username);      /* Get the current password */
+    endpwent();                                /* Close the password file */
+  }
 
  /*
   * OK, the password is good.  See if we need normal user access, or group
@@ -1011,37 +1128,52 @@ IsAuthorized(client_t *con)     /* I - Connection */
 
   LogMessage(L_DEBUG2, "IsAuthorized: Checking group membership...");
 
-  for (i = 0; i < best->num_names; i ++)
+  if (best->type == AUTH_BASIC)
   {
-    grp = getgrnam(best->names[i]);
-    endgrent();
+   /*
+    * Check to see if this user is in any of the named groups...
+    */
+
+    LogMessage(L_DEBUG2, "IsAuthorized: Checking group membership...");
 
-    if (grp == NULL)                   /* No group by that name??? */
+    for (i = 0; i < best->num_names; i ++)
     {
-      LogMessage(L_WARN, "IsAuthorized: group name \"%s\" does not exist!",
-                best->names[i]);
-      return (HTTP_FORBIDDEN);
-    }
+      grp = getgrnam(best->names[i]);
+      endgrent();
+
+      if (grp == NULL)                 /* No group by that name??? */
+      {
+       LogMessage(L_WARN, "IsAuthorized: group name \"%s\" does not exist!",
+                  best->names[i]);
+       return (HTTP_FORBIDDEN);
+      }
 
-    for (j = 0; grp->gr_mem[j] != NULL; j ++)
-      if (strcmp(con->username, grp->gr_mem[j]) == 0)
+      for (j = 0; grp->gr_mem[j] != NULL; j ++)
+       if (strcmp(con->username, grp->gr_mem[j]) == 0)
+         return (HTTP_OK);
+
+     /*
+      * Check to see if the default group ID matches for the user...
+      */
+
+      if (grp->gr_gid == pw->pw_gid)
        return (HTTP_OK);
+    }
 
    /*
-    * Check to see if the default group ID matches for the user...
+    * The user isn't part of the specified group, so deny access...
     */
 
-    if (grp->gr_gid == pw->pw_gid)
-      return (HTTP_OK);
+    LogMessage(L_DEBUG2, "IsAuthorized: user not in group!");
+
+    return (HTTP_UNAUTHORIZED);
   }
 
  /*
-  * The user isn't part of the specified group, so deny access...
+  * All checks passed...
   */
 
-  LogMessage(L_DEBUG2, "IsAuthorized: user not in group!");
-
-  return (HTTP_UNAUTHORIZED);
+  return (HTTP_OK);
 }
 
 
@@ -1129,6 +1261,129 @@ add_deny(location_t *loc)       /* I - Location to add to */
 }
 
 
+#if !HAVE_LIBPAM
+/*
+ * 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms,
+ *                  as needed.
+ */
+
+static char *                  /* O - Encrypted password */
+cups_crypt(const char *pw,     /* I - Password string */
+           const char *salt)   /* I - Salt (key) string */
+{
+  if (strncmp(salt, "$1$", 3) == 0)
+  {
+   /*
+    * Use MD5 passwords without the benefit of PAM; this is for
+    * Slackware Linux, and the algorithm was taken from the
+    * old shadow-19990827/lib/md5crypt.c source code... :(
+    */
+
+    int                i;              /* Looping var */
+    unsigned long n;           /* Output number */
+    int                pwlen;          /* Length of password string */
+    const char *salt_end;      /* End of "salt" data for MD5 */
+    char       *ptr;           /* Pointer into result string */
+    md5_state_t state;         /* Primary MD5 state info */
+    md5_state_t state2;                /* Secondary MD5 state info */
+    md5_byte_t digest[16];     /* MD5 digest result */
+    static char        result[120];    /* Final password string */
+
+
+   /*
+    * Get the salt data between dollar signs, e.g. $1$saltdata$md5.
+    * Get a maximum of 8 characters of salt data after $1$...
+    */
+
+    for (salt_end = salt + 3; *salt_end && (salt_end - salt) < 11; salt_end ++)
+      if (*salt_end == '$')
+        break;
+
+   /*
+    * Compute the MD5 sum we need...
+    */
+
+    pwlen = strlen(pw);
+
+    md5_init(&state);
+    md5_append(&state, pw, pwlen);
+    md5_append(&state, salt, salt_end - salt);
+
+    md5_init(&state2);
+    md5_append(&state2, pw, pwlen);
+    md5_append(&state2, salt + 3, salt_end - salt - 3);
+    md5_append(&state2, pw, pwlen);
+    md5_finish(&state, digest);
+
+    for (i = pwlen; i > 0; i -= 16)
+      md5_append(&state, digest, i > 16 ? 16 : i);
+
+    for (i = pwlen; i > 0; i >>= 1)
+      md5_append(&state, (i & 1) ? "" : pw, 1);
+
+    md5_finish(&state, digest);
+
+    for (i = 0; i < 1000; i ++)
+    {
+      md5_init(&state);
+
+      if (i & 1)
+        md5_append(&state, pw, pwlen);
+      else
+        md5_append(&state, digest, 16);
+
+      if (i % 3)
+        md5_append(&state, salt + 3, salt_end - salt - 3);
+
+      if (i % 7)
+        md5_append(&state, pw, pwlen);
+
+      if (i & 1)
+        md5_append(&state, digest, 16);
+      else
+        md5_append(&state, pw, pwlen);
+
+      md5_finish(&state, digest);
+    }
+
+   /*
+    * Copy the final sum to the result string and return...
+    */
+
+    memcpy(result, salt, salt_end - salt);
+    ptr = result + (salt_end - salt);
+    *ptr++ = '$';
+
+    for (i = 0; i < 5; i ++, ptr += 4)
+    {
+      n = (((digest[i] << 8) | digest[i + 6]) << 8);
+
+      if (i < 4)
+        n |= digest[i + 12];
+      else
+        n |= digest[5];
+
+      to64(ptr, n, 4);
+    }
+
+    to64(ptr, digest[11], 2);
+    ptr += 2;
+    *ptr = '\0';
+
+    return (result);
+  }
+  else
+  {
+   /*
+    * Use the standard crypt() function...
+    */
+
+    return (crypt(pw, salt));
+  }
+}
+#endif /* !HAVE_LIBPAM */
+
+
 /*
  * 'get_md5_passwd()' - Get an MD5 password.
  */
@@ -1264,9 +1519,29 @@ pam_func(int                      num_msg,       /* I - Number of messages */
 
   return (PAM_SUCCESS);
 }
+#else
+
+
+/*
+ * 'to64()' - Base64-encode an integer value...
+ */
+
+static void
+to64(char          *s, /* O - Output string */
+     unsigned long v,  /* I - Value to encode */
+     int           n)  /* I - Number of digits */
+{
+  const char   *itoa64 = "./0123456789"
+                          "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                          "abcdefghijklmnopqrstuvwxyz";
+
+
+  for (; n > 0; n --, v >>= 6)
+    *s++ = itoa64[v & 0x3f];
+}
 #endif /* HAVE_LIBPAM */
 
 
 /*
- * End of "$Id: auth.c,v 1.41.2.2 2001/05/13 18:38:33 mike Exp $".
+ * End of "$Id: auth.c,v 1.41.2.3 2001/12/26 16:52:50 mike Exp $".
  */
index cf49207e7586c0e5afc6f08237dece1aa8e7573c..3cdf5884f0fe36daab508cc900c5915a164e7948 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: auth.h,v 1.16.2.1 2001/04/02 19:51:47 mike Exp $"
+ * "$Id: auth.h,v 1.16.2.2 2001/12/26 16:52:50 mike Exp $"
  *
  *   Authorization definitions for the Common UNIX Printing System (CUPS)
  *   scheduler.
@@ -30,6 +30,7 @@
 #define AUTH_NONE              0       /* No authentication */
 #define AUTH_BASIC             1       /* Basic authentication */
 #define AUTH_DIGEST            2       /* Digest authentication */
+#define AUTH_BASICDIGEST       3       /* Basic authentication w/passwd.md5 */
 
 #define AUTH_ANON              0       /* Anonymous access */
 #define AUTH_USER              1       /* Must have a valid username/password */
@@ -125,11 +126,11 @@ extern void               DeleteAllLocations(void);
 extern void            DenyHost(location_t *loc, char *name);
 extern void            DenyIP(location_t *loc, unsigned address[4],
                               unsigned netmask[4]);
-extern location_t      *FindBest(client_t *con);
+extern location_t      *FindBest(client_t *con, http_state_t state);
 extern location_t      *FindLocation(const char *location);
 extern http_status_t   IsAuthorized(client_t *con);
 
 
 /*
- * End of "$Id: auth.h,v 1.16.2.1 2001/04/02 19:51:47 mike Exp $".
+ * End of "$Id: auth.h,v 1.16.2.2 2001/12/26 16:52:50 mike Exp $".
  */
index dfe0b532def7592a78a201785cf2318f6477ca6c..49a74367ee60473e34648e9399c14a15df92c571 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: banners.c,v 1.5 2001/01/22 15:03:58 mike Exp $"
+ * "$Id: banners.c,v 1.5.2.1 2001/12/26 16:52:50 mike Exp $"
  *
  *   Banner routines for the Common UNIX Printing System (CUPS).
  *
@@ -91,7 +91,6 @@ AddBanner(const char *name,   /* I - Name of banner */
 
   memset(temp, 0, sizeof(banner_t));
   strncpy(temp->name, name, sizeof(temp->name) - 1);
-  strncpy(temp->filename, filename, sizeof(temp->filename) - 1);
   temp->filetype = filetype;
 }
 
@@ -213,5 +212,5 @@ compare(const banner_t *b0, /* I - First banner */
 
 
 /*
- * End of "$Id: banners.c,v 1.5 2001/01/22 15:03:58 mike Exp $".
+ * End of "$Id: banners.c,v 1.5.2.1 2001/12/26 16:52:50 mike Exp $".
  */
index c616643ba9cce5dc4186c64f23086d07af530721..5c7e39949dc188e0ae2ee0c23bf637c82e27b20d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: banners.h,v 1.2 2001/01/22 15:03:58 mike Exp $"
+ * "$Id: banners.h,v 1.2.2.1 2001/12/26 16:52:50 mike Exp $"
  *
  *   Banner definitions for the Common UNIX Printing System (CUPS).
  *
@@ -29,7 +29,6 @@
 typedef struct
 {
   char         name[256];      /* Name of banner */
-  char         filename[1024]; /* Full filename */
   mime_type_t  *filetype;      /* Filetype for banner */
 } banner_t;
 
@@ -54,5 +53,5 @@ extern void   LoadBanners(const char *d);
 
 
 /*
- * End of "$Id: banners.h,v 1.2 2001/01/22 15:03:58 mike Exp $".
+ * End of "$Id: banners.h,v 1.2.2.1 2001/12/26 16:52:50 mike Exp $".
  */
index 325fb1d813c24d4328dabe677286cf5a0df0897f..129a47a3e87103fc420e6d4974ed7236781dff47 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cert.c,v 1.7.2.1 2001/05/13 18:38:34 mike Exp $"
+ * "$Id: cert.c,v 1.7.2.2 2001/12/26 16:52:50 mike Exp $"
  *
  *   Authentication certificate routines for the Common UNIX
  *   Printing System (CUPS).
@@ -95,7 +95,7 @@ AddCert(int        pid,                       /* I - Process ID */
 
     fchmod(fileno(fp), 0440);
 
-    if ((grp = getgrnam(SystemGroup)) == NULL)
+    if ((grp = getgrnam(SystemGroups[0])) == NULL)
       fchown(fileno(fp), getuid(), 0);
     else
       fchown(fileno(fp), getuid(), grp->gr_gid);
@@ -271,5 +271,5 @@ InitCerts(void)
 
 
 /*
- * End of "$Id: cert.c,v 1.7.2.1 2001/05/13 18:38:34 mike Exp $".
+ * End of "$Id: cert.c,v 1.7.2.2 2001/12/26 16:52:50 mike Exp $".
  */
index f18442806da5bcf0136728b097182bfe65b41caa..973072bd5e95b81aee2e2df8bbab437317cf779b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: classes.c,v 1.34.2.1 2001/04/02 19:51:47 mike Exp $"
+ * "$Id: classes.c,v 1.34.2.2 2001/12/26 16:52:50 mike Exp $"
  *
  *   Printer class routines for the Common UNIX Printing System (CUPS).
  *
@@ -374,12 +374,12 @@ LoadAllClasses(void)
       continue;
 
    /*
-    * Strip trailing newline, if any...
+    * Strip trailing whitespace, if any...
     */
 
     len = strlen(line);
 
-    if (line[len - 1] == '\n')
+    while (len > 0 && isspace(line[len - 1]))
     {
       len --;
       line[len] = '\0';
@@ -600,8 +600,10 @@ SaveAllClasses(void)
 
     if (pclass->info[0])
       fprintf(fp, "Info %s\n", pclass->info);
-    if (pclass->more_info[0])
+
+    if (pclass->location[0])
       fprintf(fp, "Location %s\n", pclass->location);
+
     if (pclass->state == IPP_PRINTER_STOPPED)
     {
       fputs("State Stopped\n", fp);
@@ -609,6 +611,7 @@ SaveAllClasses(void)
     }
     else
       fputs("State Idle\n", fp);
+
     if (pclass->accepting)
       fputs("Accepting Yes\n", fp);
     else
@@ -617,12 +620,9 @@ SaveAllClasses(void)
     for (i = 0; i < pclass->num_printers; i ++)
       fprintf(fp, "Printer %s\n", pclass->printers[i]->name);
 
-    if (pclass->quota_period)
-    {
-      fprintf(fp, "QuotaPeriod %d\n", pclass->quota_period);
-      fprintf(fp, "PageLimit %d\n", pclass->page_limit);
-      fprintf(fp, "KLimit %d\n", pclass->k_limit);
-    }
+    fprintf(fp, "QuotaPeriod %d\n", pclass->quota_period);
+    fprintf(fp, "PageLimit %d\n", pclass->page_limit);
+    fprintf(fp, "KLimit %d\n", pclass->k_limit);
 
     for (i = 0; i < pclass->num_users; i ++)
       fprintf(fp, "%sUser %s\n", pclass->deny_users ? "Deny" : "Allow",
@@ -636,5 +636,5 @@ SaveAllClasses(void)
 
 
 /*
- * End of "$Id: classes.c,v 1.34.2.1 2001/04/02 19:51:47 mike Exp $".
+ * End of "$Id: classes.c,v 1.34.2.2 2001/12/26 16:52:50 mike Exp $".
  */
index 6fee41f9442383aee796aa933c4a561b02db6c8c..dc799158bf3249872cb0f2c781731142c77e000a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: client.c,v 1.91.2.3 2001/05/14 18:01:22 mike Exp $"
+ * "$Id: client.c,v 1.91.2.4 2001/12/26 16:52:50 mike Exp $"
  *
  *   Client routines for the Common UNIX Printing System (CUPS) scheduler.
  *
@@ -36,6 +36,7 @@
  *   check_if_modified()   - Decode an "If-Modified-Since" line.
  *   decode_auth()         - Decode an authorization string.
  *   get_file()            - Get a filename and state info.
+ *   install_conf_file()   - Install a configuration file.
  *   pipe_command()        - Pipe the output of a command to the remote client.
  */
 
  * Local functions...
  */
 
-static int     check_if_modified(client_t *con, struct stat *filestats);
-static void    decode_auth(client_t *con);
-static char    *get_file(client_t *con, struct stat *filestats);
-static int     pipe_command(client_t *con, int infile, int *outfile, char *command, char *options);
+static int             check_if_modified(client_t *con,
+                                         struct stat *filestats);
+static void            decode_auth(client_t *con);
+static char            *get_file(client_t *con, struct stat *filestats);
+static http_status_t   install_conf_file(client_t *con);
+static int             pipe_command(client_t *con, int infile, int *outfile,
+                                    char *command, char *options);
 
 
 /*
@@ -160,7 +164,7 @@ AcceptClient(listener_t *lis)       /* I - Listener socket */
     * Do double lookups as needed...
     */
 
-    if ((host = gethostbyname(con->http.hostname)) != NULL)
+    if ((host = httpGetHostByName(con->http.hostname)) != NULL)
     {
      /*
       * See if the hostname maps to the same IP address...
@@ -393,7 +397,7 @@ EncryptClient(client_t *con)        /* I - Client to encrypt */
 #ifdef HAVE_LIBSSL
   SSL_CTX      *context;       /* Context for encryption */
   SSL          *conn;          /* Connection for encryption */
-  int          error;          /* Error code */
+  unsigned long        error;          /* Error code */
 
 
  /*
@@ -432,7 +436,7 @@ EncryptClient(client_t *con)        /* I - Client to encrypt */
 int                            /* O - 1 on success, 0 on error */
 ReadClient(client_t *con)      /* I - Client to read from */
 {
-  char         line[8192],     /* Line from client... */
+  char         line[32768],    /* Line from client... */
                operation[64],  /* Operation code from socket */
                version[64];    /* HTTP version number string */
   int          major, minor;   /* HTTP version numbers */
@@ -519,7 +523,7 @@ ReadClient(client_t *con)   /* I - Client to read from */
              if (major < 2)
              {
                con->http.version = (http_version_t)(major * 100 + minor);
-               if (con->http.version == HTTP_1_1)
+               if (con->http.version == HTTP_1_1 && KeepAlive)
                  con->http.keep_alive = HTTP_KEEPALIVE_ON;
                else
                  con->http.keep_alive = HTTP_KEEPALIVE_OFF;
@@ -602,7 +606,8 @@ ReadClient(client_t *con)   /* I - Client to read from */
 
     decode_auth(con);
 
-    if (strncmp(con->http.fields[HTTP_FIELD_CONNECTION], "Keep-Alive", 10) == 0)
+    if (strncmp(con->http.fields[HTTP_FIELD_CONNECTION], "Keep-Alive", 10) == 0 &&
+        KeepAlive)
       con->http.keep_alive = HTTP_KEEPALIVE_ON;
 
     if (con->http.fields[HTTP_FIELD_HOST][0] == '\0' &&
@@ -624,7 +629,7 @@ ReadClient(client_t *con)   /* I - Client to read from */
       * Do OPTIONS command...
       */
 
-      if ((best = FindBest(con)) != NULL &&
+      if ((best = FindBest(con->uri, con->http.state)) != NULL &&
           best->type != AUTH_NONE)
       {
        if (!SendHeader(con, HTTP_UNAUTHORIZED, NULL))
@@ -669,7 +674,7 @@ ReadClient(client_t *con)   /* I - Client to read from */
        return (0);
       }
 
-      httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST\r\n");
+      httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST, PUT\r\n");
       httpPrintf(HTTP(con), "Content-Length: 0\r\n");
       httpPrintf(HTTP(con), "\r\n");
     }
@@ -764,7 +769,8 @@ ReadClient(client_t *con)   /* I - Client to read from */
              }
            }
 
-           if (strncmp(con->uri, "/admin", 6) == 0 ||
+           if ((strncmp(con->uri, "/admin", 6) == 0 &&
+                strncmp(con->uri, "/admin/conf/", 12) != 0) ||
                strncmp(con->uri, "/printers", 9) == 0 ||
                strncmp(con->uri, "/classes", 8) == 0 ||
                strncmp(con->uri, "/jobs", 5) == 0)
@@ -815,6 +821,23 @@ ReadClient(client_t *con)  /* I - Client to read from */
              if (con->http.version <= HTTP_1_0)
                con->http.keep_alive = HTTP_KEEPALIVE_OFF;
            }
+            else if (strncmp(con->uri, "/admin/conf/", 12) == 0 &&
+                    (strchr(con->uri + 12, '/') != NULL ||
+                     strlen(con->uri) == 12))
+           {
+            /*
+             * GET can only be done to configuration files under
+             * /admin/conf...
+             */
+
+             if (!SendError(con, HTTP_FORBIDDEN))
+             {
+               CloseClient(con);
+               return (0);
+             }
+
+             break;
+           }
            else
            {
             /*
@@ -887,7 +910,8 @@ ReadClient(client_t *con)   /* I - Client to read from */
 
            if (strcmp(con->http.fields[HTTP_FIELD_CONTENT_TYPE], "application/ipp") == 0)
               con->request = ippNew();
-           else if (strncmp(con->uri, "/admin", 6) == 0 ||
+           else if ((strncmp(con->uri, "/admin", 6) == 0 &&
+                     strncmp(con->uri, "/admin/conf/", 12) != 0) ||
                     strncmp(con->uri, "/printers", 9) == 0 ||
                     strncmp(con->uri, "/classes", 8) == 0 ||
                     strncmp(con->uri, "/jobs", 5) == 0)
@@ -938,6 +962,76 @@ ReadClient(client_t *con)  /* I - Client to read from */
            break;
 
        case HTTP_PUT_RECV :
+          /*
+           * Validate the resource name...
+           */
+
+            if (strncmp(con->uri, "/admin/conf/", 12) != 0 ||
+               strchr(con->uri + 12, '/') != NULL ||
+               strlen(con->uri) == 12)
+           {
+            /*
+             * PUT can only be done to configuration files under
+             * /admin/conf...
+             */
+
+             if (!SendError(con, HTTP_FORBIDDEN))
+             {
+               CloseClient(con);
+               return (0);
+             }
+
+             break;
+           }
+
+           /*
+           * See if the PUT request includes a Content-Length field, and if
+           * so check the length against any limits that are set...
+           */
+
+            LogMessage(L_DEBUG2, "PUT %s", con->uri);
+           LogMessage(L_DEBUG2, "CONTENT_TYPE = %s", con->http.fields[HTTP_FIELD_CONTENT_TYPE]);
+
+            if (con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] &&
+               atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) > MaxRequestSize &&
+               MaxRequestSize > 0)
+           {
+            /*
+             * Request too large...
+             */
+
+              if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+             {
+               CloseClient(con);
+               return (0);
+             }
+
+             break;
+            }
+
+           /*
+           * Open a temporary file to hold the request...
+           */
+
+            snprintf(con->filename, sizeof(con->filename), "%s/%08x",
+                    RequestRoot, request_id ++);
+           con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
+           fchmod(con->file, 0640);
+           fchown(con->file, User, Group);
+
+            LogMessage(L_DEBUG2, "ReadClient() %d REQUEST %s=%d", con->http.fd,
+                      con->filename, con->file);
+
+           if (con->file < 0)
+           {
+             if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+             {
+               CloseClient(con);
+               return (0);
+             }
+           }
+           break;
+
        case HTTP_DELETE :
        case HTTP_TRACE :
             SendError(con, HTTP_NOT_IMPLEMENTED);
@@ -969,7 +1063,8 @@ ReadClient(client_t *con)  /* I - Client to read from */
              }
            }
 
-           if (strncmp(con->uri, "/admin/", 7) == 0 ||
+           if ((strncmp(con->uri, "/admin/", 7) == 0 &&
+                strncmp(con->uri, "/admin/conf/", 12) != 0) ||
                strncmp(con->uri, "/printers/", 10) == 0 ||
                strncmp(con->uri, "/classes/", 9) == 0 ||
                strncmp(con->uri, "/jobs/", 6) == 0)
@@ -992,6 +1087,23 @@ ReadClient(client_t *con) /* I - Client to read from */
 
               LogRequest(con, HTTP_OK);
            }
+            else if (strncmp(con->uri, "/admin/conf/", 12) == 0 &&
+                    (strchr(con->uri + 12, '/') != NULL ||
+                     strlen(con->uri) == 12))
+           {
+            /*
+             * HEAD can only be done to configuration files under
+             * /admin/conf...
+             */
+
+             if (!SendError(con, HTTP_FORBIDDEN))
+             {
+               CloseClient(con);
+               return (0);
+             }
+
+             break;
+           }
            else if ((filename = get_file(con, &filestats)) == NULL)
            {
              if (!SendHeader(con, HTTP_NOT_FOUND, "text/html"))
@@ -1037,8 +1149,8 @@ ReadClient(client_t *con) /* I - Client to read from */
                return (0);
              }
 
-             if (httpPrintf(HTTP(con), "Content-Length: %d\r\n",
-                            filestats.st_size) < 0)
+             if (httpPrintf(HTTP(con), "Content-Length: %lu\r\n",
+                            (unsigned long)filestats.st_size) < 0)
              {
                CloseClient(con);
                return (0);
@@ -1069,6 +1181,90 @@ ReadClient(client_t *con)        /* I - Client to read from */
   switch (con->http.state)
   {
     case HTTP_PUT_RECV :
+        LogMessage(L_DEBUG2, "ReadClient() %d con->data_encoding = %s, con->data_remaining = %d, con->file = %d",
+                  con->http.fd,
+                  con->http.data_encoding == HTTP_ENCODE_CHUNKED ? "chunked" : "length",
+                  con->http.data_remaining, con->file);
+
+        if ((bytes = httpRead(HTTP(con), line, sizeof(line))) < 0)
+       {
+         CloseClient(con);
+         return (0);
+       }
+       else if (bytes > 0)
+       {
+         con->bytes += bytes;
+
+          LogMessage(L_DEBUG2, "ReadClient() %d writing %d bytes to %d",
+                    con->http.fd, bytes, con->file);
+
+          if (write(con->file, line, bytes) < bytes)
+         {
+            LogMessage(L_ERROR, "ReadClient: Unable to write %d bytes to %s: %s",
+                      bytes, con->filename, strerror(errno));
+
+           close(con->file);
+           con->file = 0;
+           unlink(con->filename);
+           con->filename[0] = '\0';
+
+            if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+           {
+             CloseClient(con);
+             return (0);
+           }
+         }
+       }
+
+        if (con->http.state == HTTP_WAITING)
+       {
+        /*
+         * End of file, see how big it is...
+         */
+
+         fstat(con->file, &filestats);
+
+          LogMessage(L_DEBUG2, "ReadClient() %d Closing data file %d, size = %d.",
+                     con->http.fd, con->file, filestats.st_size);
+
+         close(con->file);
+         con->file = 0;
+
+          if (filestats.st_size > MaxRequestSize &&
+             MaxRequestSize > 0)
+         {
+          /*
+           * Request is too big; remove it and send an error...
+           */
+
+            LogMessage(L_DEBUG2, "ReadClient() %d Removing temp file %s",
+                      con->http.fd, con->filename);
+           unlink(con->filename);
+           con->filename[0] = '\0';
+
+            if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+           {
+             CloseClient(con);
+             return (0);
+           }
+         }
+
+         /*
+         * Install the configuration file...
+         */
+
+          status = install_conf_file(con);
+
+         /*
+         * Return the status to the client...
+         */
+
+          if (!SendError(con, status))
+         {
+           CloseClient(con);
+           return (0);
+         }
+       }
         break;
 
     case HTTP_POST_RECV :
@@ -1143,6 +1339,7 @@ ReadClient(client_t *con) /* I - Client to read from */
              close(con->file);
              con->file = 0;
              unlink(con->filename);
+             con->filename[0] = '\0';
 
               if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
              {
@@ -1180,6 +1377,7 @@ ReadClient(client_t *con) /* I - Client to read from */
               LogMessage(L_DEBUG2, "ReadClient() %d Removing temp file %s",
                         con->http.fd, con->filename);
              unlink(con->filename);
+             con->filename[0] = '\0';
 
              if (con->request)
              {
@@ -1305,7 +1503,7 @@ SendError(client_t      *con,     /* I - Connection */
   if (con->operation > HTTP_WAITING)
     LogRequest(con, code);
 
-  LogMessage(L_DEBUG2, "SendError() %d code=%d", con->http.fd, code);
+  LogMessage(L_DEBUG, "SendError() %d code=%d", con->http.fd, code);
 
  /*
   * To work around bugs in some proxies, don't use Keep-Alive for some
@@ -1396,7 +1594,8 @@ SendFile(client_t    *con,
 
   if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n", httpGetDateString(filestats->st_mtime)) < 0)
     return (0);
-  if (httpPrintf(HTTP(con), "Content-Length: %d\r\n", filestats->st_size) < 0)
+  if (httpPrintf(HTTP(con), "Content-Length: %lu\r\n",
+                 (unsigned long)filestats->st_size) < 0)
     return (0);
   if (httpPrintf(HTTP(con), "\r\n") < 0)
     return (0);
@@ -1441,9 +1640,13 @@ SendHeader(client_t    *con,     /* I - Client to send to */
 
   if (code == HTTP_UNAUTHORIZED)
   {
-    loc = FindBest(con); /* This already succeeded in IsAuthorized */
+   /*
+    * This already succeeded in IsAuthorized...
+    */
+
+    loc = FindBest(con->uri, con->http.state);
 
-    if (loc->type == AUTH_BASIC)
+    if (loc->type != AUTH_DIGEST)
     {
       if (httpPrintf(HTTP(con), "WWW-Authenticate: Basic realm=\"CUPS\"\r\n") < 0)
        return (0);
@@ -1609,6 +1812,7 @@ WriteClient(client_t *con)                /* I - Client connection */
       LogMessage(L_DEBUG2, "WriteClient() %d Removing temp file %s",
                  con->http.fd, con->filename);
       unlink(con->filename);
+      con->filename[0] = '\0';
     }
 
     if (con->request != NULL)
@@ -1797,6 +2001,8 @@ get_file(client_t    *con,        /* I - Client connection */
 
   if (strncmp(con->uri, "/ppd/", 5) == 0)
     snprintf(filename, sizeof(filename), "%s%s", ServerRoot, con->uri);
+  else if (strncmp(con->uri, "/admin/conf/", 12) == 0)
+    snprintf(filename, sizeof(filename), "%s%s", ServerRoot, con->uri + 11);
   else if (con->language != NULL)
     snprintf(filename, sizeof(filename), "%s/%s%s", DocumentRoot, con->language->language,
             con->uri);
@@ -1817,7 +2023,8 @@ get_file(client_t    *con,        /* I - Client connection */
     * Drop the language prefix and try the current directory...
     */
 
-    if (strncmp(con->uri, "/ppd/", 5) != 0)
+    if (strncmp(con->uri, "/ppd/", 5) != 0 &&
+        strncmp(con->uri, "/admin/conf/", 12) != 0)
     {
       snprintf(filename, sizeof(filename), "%s%s", DocumentRoot, con->uri);
 
@@ -1851,6 +2058,160 @@ get_file(client_t    *con,      /* I - Client connection */
 }
 
 
+/*
+ * 'install_conf_file()' - Install a configuration file.
+ */
+
+static http_status_t                   /* O - Status */
+install_conf_file(client_t *con)       /* I - Connection */
+{
+  FILE         *in,                    /* Input file */
+               *out;                   /* Output file */
+  char         buffer[1024];           /* Copy buffer */
+  int          bytes;                  /* Number of bytes */
+  char         conffile[1024],         /* Configuration filename */
+               newfile[1024],          /* New config filename */
+               oldfile[1024];          /* Old config filename */
+  struct stat  confinfo;               /* Config file info */
+
+
+ /*
+  * First construct the filenames...
+  */
+
+  snprintf(conffile, sizeof(conffile), "%s%s", ServerRoot, con->uri + 11);
+  snprintf(newfile, sizeof(newfile), "%s%s.N", ServerRoot, con->uri + 11);
+  snprintf(oldfile, sizeof(oldfile), "%s%s.O", ServerRoot, con->uri + 11);
+
+  LogMessage(L_INFO, "Installing config file \"%s\"...", conffile);
+
+ /*
+  * Get the owner, group, and permissions of the configuration file.
+  * If it doesn't exist, assign it to the User and Group in the
+  * cupsd.conf file with mode 0640 permissions.
+  */
+
+  if (stat(conffile, &confinfo))
+  {
+    confinfo.st_uid  = User;
+    confinfo.st_gid  = Group;
+    confinfo.st_mode = 0640;
+  }
+
+ /*
+  * Open the request file and new config file...
+  */
+
+  if ((in = fopen(con->filename, "rb")) == NULL)
+  {
+    LogMessage(L_ERROR, "Unable to open request file \"%s\" - %s",
+               con->filename, strerror(errno));
+    return (HTTP_SERVER_ERROR);
+  }
+
+  if ((out = fopen(newfile, "wb")) == NULL)
+  {
+    fclose(in);
+    LogMessage(L_ERROR, "Unable to open config file \"%s\" - %s",
+               newfile, strerror(errno));
+    return (HTTP_SERVER_ERROR);
+  }
+
+  fchmod(fileno(out), confinfo.st_mode);
+  fchown(fileno(out), confinfo.st_uid, confinfo.st_gid);
+
+ /*
+  * Copy from the request to the new config file...
+  */
+
+  while ((bytes = fread(buffer, 1, sizeof(buffer), in)) > 0)
+    if (fwrite(buffer, 1, bytes, out) < bytes)
+    {
+      LogMessage(L_ERROR, "Unable to copy to config file \"%s\" - %s",
+                newfile, strerror(errno));
+
+      fclose(in);
+      fclose(out);
+      unlink(newfile);
+
+      return (HTTP_SERVER_ERROR);
+    }
+
+ /*
+  * Close the files...
+  */
+
+  fclose(in);
+  if (fclose(out))
+  {
+    LogMessage(L_ERROR, "Error file closing config file \"%s\" - %s",
+               newfile, strerror(errno));
+
+    unlink(newfile);
+
+    return (HTTP_SERVER_ERROR);
+  }
+
+ /*
+  * Remove the request file...
+  */
+
+  unlink(con->filename);
+  con->filename[0] = '\0';
+
+ /*
+  * Unlink the old backup, rename the current config file to the backup
+  * filename, and rename the new config file to the config file name...
+  */
+
+  if (unlink(oldfile))
+    if (errno != ENOENT)
+    {
+      LogMessage(L_ERROR, "Unable to remove backup config file \"%s\" - %s",
+                oldfile, strerror(errno));
+
+      unlink(newfile);
+
+      return (HTTP_SERVER_ERROR);
+    }
+
+  if (rename(conffile, oldfile))
+    if (errno != ENOENT)
+    {
+      LogMessage(L_ERROR, "Unable to rename old config file \"%s\" - %s",
+                conffile, strerror(errno));
+
+      unlink(newfile);
+
+      return (HTTP_SERVER_ERROR);
+    }
+
+  if (rename(newfile, conffile))
+  {
+    LogMessage(L_ERROR, "Unable to rename new config file \"%s\" - %s",
+               newfile, strerror(errno));
+
+    rename(oldfile, conffile);
+    unlink(newfile);
+
+    return (HTTP_SERVER_ERROR);
+  }
+
+ /*
+  * If the cupsd.conf file was updated, set the NeedReload flag...
+  */
+
+  if (strcmp(con->uri, "/admin/conf/cupsd.conf") == 0)
+    NeedReload = TRUE;
+
+ /*
+  * Return that the file was created successfully...
+  */
+
+  return (HTTP_CREATED);
+}
+
+
 /*
  * 'pipe_command()' - Pipe the output of a command to the remote client.
  */
@@ -2051,7 +2412,7 @@ pipe_command(client_t *con,       /* I - Client connection */
     if (getuid() == 0)
     {
      /*
-      * Running as root, so change to non-priviledged user...
+      * Running as root, so change to non-priviledged user...
       */
 
       if (setgid(Group))
@@ -2074,11 +2435,13 @@ pipe_command(client_t *con,     /* I - Client connection */
     if (infile)
     {
       close(0);
-      dup(infile);
+      if (dup(infile) < 0)
+       exit(errno);
     }
 
     close(1);
-    dup(fds[1]);
+    if (dup(fds[1]) < 0)
+      exit(errno);
 
    /*
     * Close extra file descriptors...
@@ -2098,7 +2461,6 @@ pipe_command(client_t *con,       /* I - Client connection */
     */
 
     execve(command, argv, envp);
-    perror("execve failed");
     exit(errno);
     return (0);
   }
@@ -2123,7 +2485,7 @@ pipe_command(client_t *con,       /* I - Client connection */
 
     AddCert(pid, con->username);
 
-    LogMessage(L_DEBUG, "CGI %s started - PID = %d", argv[0], pid);
+    LogMessage(L_DEBUG, "CGI %s started - PID = %d", command, pid);
 
     *outfile = fds[0];
     close(fds[1]);
@@ -2134,5 +2496,5 @@ pipe_command(client_t *con,       /* I - Client connection */
 
 
 /*
- * End of "$Id: client.c,v 1.91.2.3 2001/05/14 18:01:22 mike Exp $".
+ * End of "$Id: client.c,v 1.91.2.4 2001/12/26 16:52:50 mike Exp $".
  */
index c0fceaddc034558f76b34c2e6ace5cf734efc6bc..6da9c3b7fa7005b4c2318239ab94657e51b601f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: conf.c,v 1.77.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: conf.c,v 1.77.2.2 2001/12/26 16:52:51 mike Exp $"
  *
  *   Configuration routines for the Common UNIX Printing System (CUPS).
  *
@@ -85,6 +85,7 @@ static var_t  variables[] =
   { "BrowseTimeout",   &BrowseTimeout,         VAR_INTEGER,    0 },
   { "Browsing",                &Browsing,              VAR_BOOLEAN,    0 },
   { "Classification",  Classification,         VAR_STRING,     sizeof(Classification) },
+  { "ClassifyOverride",        &ClassifyOverride,      VAR_BOOLEAN,    0 },
   { "DataDir",         DataDir,                VAR_STRING,     sizeof(DataDir) },
   { "DefaultCharset",  DefaultCharset,         VAR_STRING,     sizeof(DefaultCharset) },
   { "DefaultLanguage", DefaultLanguage,        VAR_STRING,     sizeof(DefaultLanguage) },
@@ -92,7 +93,9 @@ static var_t  variables[] =
   { "ErrorLog",                ErrorLog,               VAR_STRING,     sizeof(ErrorLog) },
   { "FilterLimit",     &FilterLimit,           VAR_INTEGER,    0 },
   { "FontPath",                FontPath,               VAR_STRING,     sizeof(FontPath) },
+  { "HideImplicitMembers", &HideImplicitMembers, VAR_BOOLEAN,  0 },
   { "ImplicitClasses", &ImplicitClasses,       VAR_BOOLEAN,    0 },
+  { "ImplicitAnyClasses", &ImplicitAnyClasses, VAR_BOOLEAN,    0 },
   { "KeepAliveTimeout",        &KeepAliveTimeout,      VAR_INTEGER,    0 },
   { "KeepAlive",       &KeepAlive,             VAR_BOOLEAN,    0 },
   { "LimitRequestBody",        &MaxRequestSize,        VAR_INTEGER,    0 },
@@ -120,7 +123,6 @@ static var_t        variables[] =
 #endif /* HAVE_LIBSSL */
   { "ServerName",      ServerName,             VAR_STRING,     sizeof(ServerName) },
   { "ServerRoot",      ServerRoot,             VAR_STRING,     sizeof(ServerRoot) },
-  { "SystemGroup",     SystemGroup,            VAR_STRING,     sizeof(SystemGroup) },
   { "TempDir",         TempDir,                VAR_STRING,     sizeof(TempDir) },
   { "Timeout",         &Timeout,               VAR_INTEGER,    0 }
 };
@@ -158,7 +160,10 @@ ReadConfiguration(void)
   int          i;              /* Looping var */
   FILE         *fp;            /* Configuration file */
   int          status;         /* Return status */
-  char         directory[1024];/* Configuration directory */
+  char         directory[1024],/* Configuration directory */
+               *slash;         /* Directory separator */
+  char         type[MIME_MAX_SUPER + MIME_MAX_TYPE];
+                               /* MIME type name */
   struct rlimit        limit;          /* Runtime limit */
   char         *language;      /* Language string */
   struct passwd        *user;          /* Default user */
@@ -196,6 +201,14 @@ ReadConfiguration(void)
   if (MimeDatabase != NULL)
     mimeDelete(MimeDatabase);
 
+  if (NumMimeTypes)
+  {
+    for (i = 0; i < NumMimeTypes; i ++)
+      free((void *)MimeTypes[i]);
+
+    free(MimeTypes);
+  }
+
   for (i = 0; i < NumRelays; i ++)
     if (Relays[i].from.type == AUTH_NAME)
       free(Relays[i].from.mask.name.name);
@@ -214,7 +227,6 @@ ReadConfiguration(void)
 
   gethostname(ServerName, sizeof(ServerName));
   snprintf(ServerAdmin, sizeof(ServerAdmin), "root@%s", ServerName);
-  strcpy(ServerRoot, CUPS_SERVERROOT);
   strcpy(ServerBin, CUPS_SERVERBIN);
   strcpy(RequestRoot, CUPS_REQUESTS);
   strcpy(DocumentRoot, CUPS_DOCROOT);
@@ -226,7 +238,12 @@ ReadConfiguration(void)
   strcpy(FontPath, CUPS_FONTPATH);
   strcpy(RemoteRoot, "remroot");
 
+  strcpy(ServerRoot, ConfigurationFile);
+  if ((slash = strrchr(ServerRoot, '/')) != NULL)
+    *slash = '\0';
+
   Classification[0] = '\0';
+  ClassifyOverride  = 0;
 
 #ifdef HAVE_LIBSSL
   strcpy(ServerCertificate, "ssl/server.crt");
@@ -257,39 +274,30 @@ ReadConfiguration(void)
   * Find the default system group: "sys", "system", or "root"...
   */
 
-  group = getgrnam("sys");
+  group = getgrnam(CUPS_DEFAULT_GROUP);
   endgrent();
 
+  NumSystemGroups = 0;
+
   if (group != NULL)
   {
-    strcpy(SystemGroup, "sys");
+    strcpy(SystemGroups[0], CUPS_DEFAULT_GROUP);
     Group = group->gr_gid;
   }
   else
   {
-    group = getgrnam("system");
+    group = getgrgid(0);
     endgrent();
 
     if (group != NULL)
     {
-      strcpy(SystemGroup, "system");
-      Group = group->gr_gid;
+      strcpy(SystemGroups[0], group->gr_name);
+      Group = 0;
     }
     else
     {
-      group = getgrnam("root");
-      endgrent();
-
-      if (group != NULL)
-      {
-       strcpy(SystemGroup, "root");
-       Group = group->gr_gid;
-      }
-      else
-      {
-       strcpy(SystemGroup, "unknown");
-       Group = 0;
-      }
+      strcpy(SystemGroups[0], "unknown");
+      Group = 0;
     }
   }
 
@@ -297,7 +305,7 @@ ReadConfiguration(void)
   * Find the default user...
   */
 
-  if ((user = getpwnam("lp")) == NULL)
+  if ((user = getpwnam(CUPS_DEFAULT_USER)) == NULL)
     User = 1;  /* Force to a non-priviledged account */
   else
     User = user->pw_uid;
@@ -412,14 +420,56 @@ ReadConfiguration(void)
     ServerCertificate[sizeof(ServerCertificate) - 1] = '\0';
   }
 
+  chown(ServerCertificate, User, Group);
+  chmod(ServerCertificate, 0600);
+
   if (ServerKey[0] != '/')
   {
     snprintf(directory, sizeof(directory), "%s/%s", ServerRoot, ServerKey);
     strncpy(ServerKey, directory, sizeof(ServerKey) - 1);
     ServerKey[sizeof(ServerKey) - 1] = '\0';
   }
+
+  chown(ServerKey, User, Group);
+  chmod(ServerKey, 0600);
 #endif /* HAVE_LIBSSL */
 
+ /*
+  * Make sure that ServerRoot and the config files are owned and
+  * writable by the user and group in the cupsd.conf file...
+  */
+
+  chown(ServerRoot, User, Group);
+  chmod(ServerRoot, 0755);
+
+  snprintf(directory, sizeof(directory), "%s/certs", ServerRoot);
+  chown(directory, User, Group);
+  chmod(directory, 0711);
+
+  snprintf(directory, sizeof(directory), "%s/ppd", ServerRoot);
+  chown(directory, User, Group);
+  chmod(directory, 0755);
+
+  snprintf(directory, sizeof(directory), "%s/ssl", ServerRoot);
+  chown(directory, User, Group);
+  chmod(directory, 0700);
+
+  snprintf(directory, sizeof(directory), "%s/cupsd.conf", ServerRoot);
+  chown(directory, User, Group);
+  chmod(directory, 0600);
+
+  snprintf(directory, sizeof(directory), "%s/classes.conf", ServerRoot);
+  chown(directory, User, Group);
+  chmod(directory, 0600);
+
+  snprintf(directory, sizeof(directory), "%s/printers.conf", ServerRoot);
+  chown(directory, User, Group);
+  chmod(directory, 0600);
+
+  snprintf(directory, sizeof(directory), "%s/passwd.md5", ServerRoot);
+  chown(directory, User, Group);
+  chmod(directory, 0600);
+
  /*
   * Make sure the request and temporary directories have the right
   * permissions...
@@ -445,7 +495,7 @@ ReadConfiguration(void)
 
   getrlimit(RLIMIT_NOFILE, &limit);
 
-  if (MaxClients > (limit.rlim_max / 3))
+  if (MaxClients > (limit.rlim_max / 3) || MaxClients <= 0)
     MaxClients = limit.rlim_max / 3;
 
   if ((Clients = calloc(sizeof(client_t), MaxClients)) == NULL)
@@ -465,6 +515,12 @@ ReadConfiguration(void)
   if (MaxActiveJobs > (limit.rlim_max / 3))
     MaxActiveJobs = limit.rlim_max / 3;
 
+  if (strcasecmp(Classification, "none") == 0)
+    Classification[0] = '\0';
+
+  if (Classification[0])
+    LogMessage(L_INFO, "Security set to \"%s\"", Classification);
+
  /*
   * Read the MIME type and conversion database...
   */
@@ -472,6 +528,28 @@ ReadConfiguration(void)
   MimeDatabase = mimeNew();
   mimeMerge(MimeDatabase, ServerRoot);
 
+ /*
+  * Create a list of MIME types for the document-format-supported
+  * attribute...
+  */
+
+  NumMimeTypes = MimeDatabase->num_types;
+  if (!mimeType(MimeDatabase, "application", "octet-stream"))
+    NumMimeTypes ++;
+
+  MimeTypes = calloc(NumMimeTypes, sizeof(const char *));
+
+  for (i = 0; i < MimeDatabase->num_types; i ++)
+  {
+    snprintf(type, sizeof(type), "%s/%s", MimeDatabase->types[i]->super,
+             MimeDatabase->types[i]->type);
+
+    MimeTypes[i] = strdup(type);
+  }
+
+  if (i < NumMimeTypes)
+    MimeTypes[i] = strdup("application/octet-stream");
+
  /*
   * Load banners...
   */
@@ -526,6 +604,7 @@ read_configuration(FILE *fp)                /* I - File to read from */
                name[256],              /* Parameter name */
                *nameptr,               /* Pointer into name */
                *value;                 /* Pointer to value */
+  int          valuelen;               /* Length of value */
   var_t                *var;                   /* Current variable */
   unsigned     ip[4],                  /* Address value */
                mask[4];                /* Netmask value */
@@ -533,6 +612,15 @@ read_configuration(FILE *fp)               /* I - File to read from */
   dirsvc_poll_t        *poll;                  /* Polling data */
   http_addr_t  polladdr;               /* Polling address */
   location_t   *location;              /* Browse location */
+  FILE         *incfile;               /* Include file */
+  char         incname[1024];          /* Include filename */
+  static unsigned netmasks[4] =                /* Standard netmasks... */
+  {
+    0xff000000,
+    0xffff0000,
+    0xffffff00,
+    0xffffffff
+  };
 
 
  /*
@@ -553,12 +641,12 @@ read_configuration(FILE *fp)              /* I - File to read from */
       continue;
 
    /*
-    * Strip trailing newline, if any...
+    * Strip trailing whitespace, if any...
     */
 
     len = strlen(line);
 
-    if (line[len - 1] == '\n')
+    while (len > 0 && isspace(line[len - 1]))
     {
       len --;
       line[len] = '\0';
@@ -585,7 +673,30 @@ read_configuration(FILE *fp)               /* I - File to read from */
     * Decode the directive...
     */
 
-    if (strcasecmp(name, "<Location") == 0)
+    if (strcasecmp(name, "Include") == 0)
+    {
+     /*
+      * Include filename
+      */
+
+      if (value[0] == '/')
+      {
+        strncpy(incname, value, sizeof(incname) - 1);
+       incname[sizeof(incname) - 1] = '\0';
+      }
+      else
+        snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
+
+      if ((incfile = fopen(incname, "rb")) == NULL)
+        LogMessage(L_ERROR, "Unable to include config file \"%s\" - %s",
+                  incname, strerror(errno));
+      else
+      {
+        read_configuration(incfile);
+       fclose(incfile);
+      }
+    }
+    else if (strcasecmp(name, "<Location") == 0)
     {
      /*
       * <Location path>
@@ -726,6 +837,46 @@ read_configuration(FILE *fp)               /* I - File to read from */
         LogMessage(L_ERROR, "Unknown BrowseOrder value %s on line %d.",
                   value, linenum);
     }
+    else if (strcasecmp(name, "BrowseProtocols") == 0)
+    {
+     /*
+      * "BrowseProtocol name [... name]"
+      */
+
+      BrowseProtocols = 0;
+
+      for (; *value;)
+      {
+        for (valuelen = 0; value[valuelen]; valuelen ++)
+         if (isspace(value[valuelen]) || value[valuelen] == ',')
+           break;
+
+        if (value[valuelen])
+        {
+         value[valuelen] = '\0';
+         valuelen ++;
+       }
+
+        if (strcasecmp(value, "cups") == 0)
+         BrowseProtocols |= BROWSE_CUPS;
+        else if (strcasecmp(value, "slp") == 0)
+         BrowseProtocols |= BROWSE_SLP;
+        else if (strcasecmp(value, "ldap") == 0)
+         BrowseProtocols |= BROWSE_LDAP;
+        else if (strcasecmp(value, "all") == 0)
+         BrowseProtocols |= BROWSE_ALL;
+       else
+       {
+         LogMessage(L_ERROR, "Unknown browse protocol \"%s\" on line %d.",
+                    value, linenum);
+          break;
+       }
+
+        for (value += valuelen; *value; value ++)
+         if (!isspace(*value) || *value != ',')
+           break;
+      }
+    }
     else if (strcasecmp(name, "BrowseAllow") == 0 ||
              strcasecmp(name, "BrowseDeny") == 0)
     {
@@ -1048,6 +1199,34 @@ read_configuration(FILE *fp)             /* I - File to read from */
                     value);
       }
     }
+    else if (strcasecmp(name, "SystemGroup") == 0)
+    {
+     /*
+      * System (admin) group(s)...
+      */
+
+      char *valueptr; /* Pointer into value */
+
+
+      for (i = 0; i < MAX_SYSTEM_GROUPS; i ++)
+      {
+        for (valueptr = value; *valueptr; valueptr ++)
+         if (isspace(*valueptr) || *valueptr == ',')
+           break;
+
+        if (*valueptr)
+          *valueptr++ = '\0';
+
+        strncpy(SystemGroups[i], value, sizeof(SystemGroups[0]));
+       SystemGroups[i][sizeof(SystemGroups[0]) - 1] = '\0';
+
+        while (*value == ',' || isspace(*value))
+         value ++;
+      }
+
+      if (i)
+        NumSystemGroups = i;
+    }
     else if (strcasecmp(name, "HostNameLookups") == 0)
     {
      /*
@@ -1131,7 +1310,31 @@ read_configuration(FILE *fp)             /* I - File to read from */
       switch (var->type)
       {
         case VAR_INTEGER :
-           *((int *)var->ptr) = atoi(value);
+           {
+             float     n;              /* Number */
+             char      units[255];     /* Units */
+
+
+             switch (sscanf(value, "%f%254s", &n, units))
+             {
+               case 0 :
+                   n = 0.0;
+               case 1 :
+                   break;
+               case 2 :
+                   if (tolower(units[0]) == 'g')
+                     n *= 1024.0 * 1024.0 * 1024.0;
+                   else if (tolower(units[0]) == 'm')
+                     n *= 1024.0 * 1024.0;
+                   else if (tolower(units[0]) == 'k')
+                     n *= 1024.0;
+                   else if (tolower(units[0]) == 't')
+                     n *= 262144.0;
+                   break;
+             }
+
+             *((int *)var->ptr) = (int)n;
+           }
            break;
 
        case VAR_BOOLEAN :
@@ -1173,6 +1376,7 @@ read_location(FILE *fp,           /* I - Configuration file */
               char *location,  /* I - Location name/path */
              int  linenum)     /* I - Current line number */
 {
+  int          i;                      /* Looping var */
   location_t   *loc,                   /* New location */
                *parent;                /* Parent location */
   int          len;                    /* Length of line */
@@ -1203,12 +1407,12 @@ read_location(FILE *fp,         /* I - Configuration file */
       continue;
 
    /*
-    * Strip trailing newline, if any...
+    * Strip trailing whitespace, if any...
     */
 
     len = strlen(line);
 
-    if (line[len - 1] == '\n')
+    while (len > 0 && isspace(line[len - 1]))
     {
       len --;
       line[len] = '\0';
@@ -1290,7 +1494,12 @@ read_location(FILE *fp,          /* I - Configuration file */
       if (strcasecmp(value, "never") == 0)
         loc->encryption = HTTP_ENCRYPT_NEVER;
       else if (strcasecmp(value, "always") == 0)
-        loc->encryption = HTTP_ENCRYPT_ALWAYS;
+      {
+        LogMessage(L_ERROR, "Encryption value \"%s\" on line %d is invalid in this context. "
+                           "Using \"required\" instead.", value, linenum);
+
+        loc->encryption = HTTP_ENCRYPT_REQUIRED;
+      }
       else if (strcasecmp(value, "required") == 0)
         loc->encryption = HTTP_ENCRYPT_REQUIRED;
       else if (strcasecmp(value, "ifrequested") == 0)
@@ -1429,6 +1638,13 @@ read_location(FILE *fp,          /* I - Configuration file */
         if (loc->level == AUTH_ANON)
          loc->level = AUTH_USER;
       }
+      else if (strcasecmp(value, "basicdigest") == 0)
+      {
+       loc->type = AUTH_BASICDIGEST;
+
+        if (loc->level == AUTH_ANON)
+         loc->level = AUTH_USER;
+      }
       else
         LogMessage(L_WARN, "Unknown authorization type %s on line %d.",
                   value, linenum);
@@ -1451,7 +1667,9 @@ read_location(FILE *fp,           /* I - Configuration file */
       else if (strcasecmp(value, "system") == 0)
       {
         loc->level = AUTH_GROUP;
-       AddName(loc, SystemGroup);
+
+       for (i = 0; i < NumSystemGroups; i ++)
+         AddName(loc, SystemGroups[i]);
       }
       else
         LogMessage(L_WARN, "Unknown authorization class %s on line %d.",
@@ -1510,7 +1728,7 @@ read_location(FILE *fp,           /* I - Configuration file */
     {
       if (strcasecmp(value, "all") == 0)
         loc->satisfy = AUTH_SATISFY_ALL;
-      if (strcasecmp(value, "any") == 0)
+      else if (strcasecmp(value, "any") == 0)
         loc->satisfy = AUTH_SATISFY_ANY;
       else
         LogMessage(L_WARN, "Unknown Satisfy value %s on line %d.", value,
@@ -1599,11 +1817,11 @@ get_address(const char  *value,         /* I - Value string */
   * Decode the hostname and port number as needed...
   */
 
-  if (hostname[0] != '\0')
+  if (hostname[0] && strcmp(hostname, "*") != 0)
   {
-    if ((host = gethostbyname(hostname)) == NULL)
+    if ((host = httpGetHostByName(hostname)) == NULL)
     {
-      LogMessage(L_ERROR, "gethostbyname(\"%s\") failed - %s!", hostname,
+      LogMessage(L_ERROR, "httpGetHostByName(\"%s\") failed - %s!", hostname,
                  strerror(errno));
       return (0);
     }
@@ -1777,5 +1995,5 @@ get_addr_and_mask(const char *value,      /* I - String from config file */
 
 
 /*
- * End of "$Id: conf.c,v 1.77.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: conf.c,v 1.77.2.2 2001/12/26 16:52:51 mike Exp $".
  */
index c01210a206c5b567c8052e57344fac17f0e34a65..76790818a762e0e18e263004f665575ec369f261 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: conf.h,v 1.36 2001/03/14 13:45:34 mike Exp $"
+ * "$Id: conf.h,v 1.36.2.1 2001/12/26 16:52:51 mike Exp $"
  *
  *   Configuration file definitions for the Common UNIX Printing System (CUPS)
  *   scheduler.
@@ -64,10 +64,12 @@ VAR char            ConfigurationFile[256]  VALUE(CUPS_SERVERROOT "/cupsd.conf"),
                                        /* Root directory for binaries */
                        RequestRoot[1024]       VALUE(CUPS_REQUESTS),
                                        /* Directory for request files */
-                       DocumentRoot[1024]      VALUE(CUPS_DOCROOT),
+                       DocumentRoot[1024]      VALUE(CUPS_DOCROOT);
                                        /* Root directory for documents */
-                       SystemGroup[32],
-                                       /* System group name */
+VAR int                        NumSystemGroups         VALUE(0);
+                                       /* Number of system group names */
+VAR char               SystemGroups[MAX_SYSTEM_GROUPS][32],
+                                       /* System group names */
                        AccessLog[1024]         VALUE(CUPS_LOGDIR "/access_log"),
                                        /* Access log filename */
                        ErrorLog[1024]          VALUE(CUPS_LOGDIR "/error_log"),
@@ -92,7 +94,9 @@ VAR char              ConfigurationFile[256]  VALUE(CUPS_SERVERROOT "/cupsd.conf"),
                                        /* Remote root user */
                        Classification[IPP_MAX_NAME]    VALUE("");
                                        /* Classification of system */
-VAR int                        User                    VALUE(1),
+VAR int                        ClassifyOverride        VALUE(0),
+                                       /* Allow overrides? */
+                       User                    VALUE(1),
                                        /* User ID for server */
                        Group                   VALUE(0),
                                        /* Group ID for server */
@@ -114,6 +118,10 @@ VAR int                    User                    VALUE(1),
                                        /* Timeout between requests */
                        ImplicitClasses         VALUE(TRUE),
                                        /* Are classes implicitly created? */
+                       ImplicitAnyClasses      VALUE(FALSE),
+                                       /* Create AnyPrinter classes? */
+                       HideImplicitMembers     VALUE(TRUE),
+                                       /* Hide implicit class members? */
                        FilterLimit             VALUE(0),
                                        /* Max filter cost at any time */
                        FilterLevel             VALUE(0),
@@ -130,6 +138,10 @@ VAR FILE           *AccessFile             VALUE(NULL),
                                        /* Page log file */
 VAR mime_t             *MimeDatabase           VALUE(NULL);
                                        /* MIME type database */
+VAR int                        NumMimeTypes            VALUE(0);
+                                       /* Number of MIME types */
+VAR const char         **MimeTypes             VALUE(NULL);
+                                       /* Array of MIME types */
 
 #ifdef HAVE_LIBSSL
 VAR char               ServerCertificate[1024] VALUE("ssl/server.crt"),
@@ -151,5 +163,5 @@ extern int  LogPage(job_t *job, const char *page);
 
 
 /*
- * End of "$Id: conf.h,v 1.36 2001/03/14 13:45:34 mike Exp $".
+ * End of "$Id: conf.h,v 1.36.2.1 2001/12/26 16:52:51 mike Exp $".
  */
index 7d6a8e0464b61957e1309b44f3e473c7b219e82d..a76f0ae2747f2c13703c919fced76179ab59d5aa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cups-lpd.c,v 1.24.2.2 2001/05/13 18:38:34 mike Exp $"
+ * "$Id: cups-lpd.c,v 1.24.2.3 2001/12/26 16:52:51 mike Exp $"
  *
  *   Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
  *
@@ -43,6 +43,8 @@
 #include <errno.h>
 #include <syslog.h>
 #include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -228,28 +230,26 @@ main(int  argc,                   /* I - Number of command-line arguments */
 
     case 0x02 : /* Receive a printer job */
         syslog(LOG_INFO, "Receive print job for %s", dest);
-       putchar(0);
+        /* recv_print_job() sends initial status byte */
 
         status = recv_print_job(dest, num_defaults, defaults);
        break;
 
     case 0x03 : /* Send queue state (short) */
         syslog(LOG_INFO, "Send queue state (short) for %s %s", dest, list);
-       putchar(0);
+       /* send_state() sends initial status byte */
 
         status = send_state(dest, list, 0);
        break;
 
     case 0x04 : /* Send queue state (long) */
         syslog(LOG_INFO, "Send queue state (long) for %s %s", dest, list);
-       putchar(0);
+       /* send_state() sends initial status byte */
 
         status = send_state(dest, list, 1);
        break;
 
     case 0x05 : /* Remove jobs */
-       putchar(0);
-
        /*
         * Grab the agent and skip to the list of users and/or jobs.
        */
@@ -263,6 +263,8 @@ main(int  argc,                     /* I - Number of command-line arguments */
         syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent);
 
         status = remove_jobs(dest, agent, list);
+
+       putchar(status);
        break;
   }
 
@@ -282,7 +284,7 @@ print_file(const char    *name,             /* I - Printer or class name */
            const char    *file,                /* I - File to print */
            const char    *title,       /* I - Title of job */
            const char    *docname,     /* I - Name of job file */
-           const char    *user,                /* I - Title of job */
+           const char    *user,                /* I - Owner of job */
            int           num_options,  /* I - Number of options */
           cups_option_t *options)      /* I - Options */
 {
@@ -365,15 +367,21 @@ print_file(const char    *name,           /* I - Printer or class name */
   else
     jobid = attr->values[0].integer;
 
+  if (jobid)
+    syslog(LOG_INFO, "Print file - job ID = %d", jobid);
+  else if (response)
+    syslog(LOG_ERR, "Unable to print file - %s",
+           ippErrorString(response->request.status.status_code));
+  else
+    syslog(LOG_ERR, "Unable to print file - %s",
+           ippErrorString(cupsLastError()));
+
   if (response != NULL)
     ippDelete(response);
 
   httpClose(http);
   cupsLangFree(language);
 
-  if (jobid)
-    syslog(LOG_INFO, "Print file - job ID = %d", jobid);
-
   return (jobid);
 }
 
@@ -416,6 +424,9 @@ recv_print_job(const char    *dest, /* I - Destination */
 
   status   = 0;
   num_data = 0;
+  fd       = -1;
+
+  control[0] = '\0';
 
   strncpy(queue, dest, sizeof(queue) - 1);
   queue[sizeof(queue) - 1] = '\0';
@@ -432,8 +443,13 @@ recv_print_job(const char    *dest,        /* I - Destination */
       syslog(LOG_ERR, "Unknown destination %s!", queue);
 
     cupsFreeDests(num_dests, dests);
+
+    putchar(1);
+
     return (1);
   }
+  else
+    putchar(0);
 
   while (smart_gets(line, sizeof(line), stdin) != NULL)
   {
@@ -465,16 +481,38 @@ recv_print_job(const char    *dest,       /* I - Destination */
            break;
          }
 
-          if ((fd = cupsTempFd(control, sizeof(control))) < 0)
+          if (control[0])
          {
-           syslog(LOG_ERR, "Unable to open temporary control file - %s",
-                  strerror(errno));
-           putchar(1);
-           status = 1;
-           break;
-         }
+          /*
+           * Append to the existing control file - the LPD spec is
+           * not entirely clear, but at least the OS/2 LPD code sends
+           * multiple control files per connection...
+           */
+
+           if ((fd = open(control, O_WRONLY)) < 0)
+           {
+             syslog(LOG_ERR, "Unable to append to temporary control file - %s",
+                    strerror(errno));
+             putchar(1);
+             status = 1;
+             break;
+           }
 
-         strcpy(filename, control);
+           lseek(fd, 0, SEEK_END);
+          }
+         else
+         {
+           if ((fd = cupsTempFd(control, sizeof(control))) < 0)
+           {
+             syslog(LOG_ERR, "Unable to open temporary control file - %s",
+                    strerror(errno));
+             putchar(1);
+             status = 1;
+             break;
+           }
+
+           strcpy(filename, control);
+         }
          break;
       case 0x03 : /* Receive data file */
           if (strlen(name) < 2)
@@ -649,13 +687,14 @@ recv_print_job(const char    *dest,       /* I - Destination */
          case 't' : /* Print troff output file */
          case 'v' : /* Print raster file */
             /*
-             * Verify that we have a username...
+             * Check that we have a username...
              */
 
              if (!user[0])
              {
-               status = 1;
-               break;
+               syslog(LOG_WARNING, "No username specified by client! "
+                                   "Using \"anonymous\"...");
+               strcpy(user, "anonymous");
              }
 
              /*
@@ -765,7 +804,10 @@ remove_jobs(const char *dest,              /* I - Destination */
 
   if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
                                  cupsEncryption())) == NULL)
+  {
+    syslog(LOG_ERR, "Unable to connect to server: %s", strerror(errno));
     return (1);
+  }
 
   language = cupsLangDefault();
 
@@ -849,7 +891,7 @@ remove_jobs(const char *dest,               /* I - Destination */
 
 
 /*
- * 'send_short_state()' - Send the short queue state.
+ * 'send_state()' - Send the queue state.
  */
 
 int                                    /* O - Command status */
@@ -919,7 +961,11 @@ send_state(const char *dest,               /* I - Destination */
 
   if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
                                  cupsEncryption())) == NULL)
+  {
+    syslog(LOG_ERR, "Unable to connect to server: %s", strerror(errno));
+    putchar(1);
     return (1);
+  }
 
  /*
   * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
@@ -961,8 +1007,11 @@ send_state(const char *dest,              /* I - Destination */
       syslog(LOG_WARNING, "Unable to get printer list: %s\n",
              ippErrorString(response->request.status.status_code));
       ippDelete(response);
+      putchar(1);
       return (1);
     }
+    else
+      putchar(0);
 
     if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
       state = (ipp_pstate_t)attr->values[0].integer;
@@ -988,6 +1037,7 @@ send_state(const char *dest,               /* I - Destination */
   {
     syslog(LOG_WARNING, "Unable to get printer list: %s\n",
            ippErrorString(cupsLastError()));
+    putchar(1);
     return (1);
   }
 
@@ -1238,5 +1288,5 @@ smart_gets(char *s,       /* I - Pointer to line buffer */
 
 
 /*
- * End of "$Id: cups-lpd.c,v 1.24.2.2 2001/05/13 18:38:34 mike Exp $".
+ * End of "$Id: cups-lpd.c,v 1.24.2.3 2001/12/26 16:52:51 mike Exp $".
  */
index 6cbac566878131bb0b9454421a15146167ae60de..3932806a2f9de49bdb8bace592436a9f9cd764cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $"
+ * "$Id: cups-polld.c,v 1.5.2.2 2001/12/26 16:52:52 mike Exp $"
  *
  *   Polling daemon for the Common UNIX Printing System (CUPS).
  *
@@ -23,6 +23,8 @@
  *
  * Contents:
  *
+ *   main()        - Open socks and poll until we are killed...
+ *   poll_server() - Poll the server for the given set of printers or classes.
  */
 
 /*
@@ -118,11 +120,8 @@ main(int  argc,                            /* I - Number of command-line arguments */
 
   for (;;)
   {
-    if (poll_server(http, language, CUPS_GET_PRINTERS, sock, port))
-      continue;
-
-    if (poll_server(http, language, CUPS_GET_CLASSES, sock, port))
-      continue;
+    if (!poll_server(http, language, CUPS_GET_PRINTERS, sock, port))
+      poll_server(http, language, CUPS_GET_CLASSES, sock, port);
 
     sleep(interval);
   }
@@ -151,6 +150,15 @@ poll_server(http_t      *http,             /* I - HTTP connection */
   ipp_pstate_t         state;          /* printer-state */
   struct sockaddr_in   addr;           /* Broadcast address */
   char                 packet[1540];   /* Data packet */
+  static const char    *attrs[] =      /* Requested attributes */
+                       {
+                         "printer-info",
+                         "printer-location",
+                         "printer-make-and-model",
+                         "printer-state",
+                         "printer-type",
+                         "printer-uri-supported"
+                       };
 
 
  /*
@@ -180,6 +188,10 @@ poll_server(http_t      *http,             /* I - HTTP connection */
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
                "attributes-natural-language", NULL, language->language);
 
+  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+               "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
+              NULL, attrs);
+
  /*
   * Do the request and get back a response...
   */
@@ -305,5 +317,5 @@ poll_server(http_t      *http,              /* I - HTTP connection */
 
 
 /*
- * End of "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $".
+ * End of "$Id: cups-polld.c,v 1.5.2.2 2001/12/26 16:52:52 mike Exp $".
  */
index 73d64206146331bd645019de484f4d366f0bacd9..56400898008fb22913872549801904c22ee3b19b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cupsd.h,v 1.28 2001/02/21 17:01:17 mike Exp $"
+ * "$Id: cupsd.h,v 1.28.2.1 2001/12/26 16:52:52 mike Exp $"
  *
  *   Main header file for the Common UNIX Printing System (CUPS) scheduler.
  *
@@ -72,6 +72,7 @@
 #define MAX_LISTENERS          10      /* Maximum number of listener sockets */
 #define MAX_USERPASS           33      /* Maximum size of username/password */
 #define MAX_FILTERS            20      /* Maximum number of filters */
+#define MAX_SYSTEM_GROUPS      32      /* Maximum number of system groups */
 
 
 /*
 #define DEFAULT_TIMEOUT                300     /* Timeout during requests/updates */
 #define DEFAULT_KEEPALIVE      60      /* Timeout between requests */
 #define DEFAULT_INTERVAL       30      /* Interval between browse updates */
-#ifdef WIN32 /* Fix for broken Linux setlocale() */
-#  define DEFAULT_LANGUAGE     setlocale(LC_ALL,"")
+#define DEFAULT_LANGUAGE       setlocale(LC_ALL,"")
                                        /* Default language encoding */
-#else
-#  define DEFAULT_LANGUAGE     getenv("LANG")
-                                       /* Default language encoding */
-#endif /* !WIN32 */
-#define DEFAULT_CHARSET                "utf-8"
-                                       /* Default charset */
+#define DEFAULT_CHARSET                "utf-8" /* Default charset */
 
 
 /*
 #include "cert.h"
 #include "client.h"
 #include "auth.h"
-#include "dirsvc.h"
 #include "printers.h"
 #include "classes.h"
 #include "job.h"
 #include "conf.h"
 #include "banners.h"
+#include "dirsvc.h"
 
 
 /*
@@ -177,5 +172,5 @@ extern void StopServer(void);
 
 
 /*
- * End of "$Id: cupsd.h,v 1.28 2001/02/21 17:01:17 mike Exp $".
+ * End of "$Id: cupsd.h,v 1.28.2.1 2001/12/26 16:52:52 mike Exp $".
  */
index f6ac4556179e951d24f84ab39d67be8d1d8e5b77..3183200a743386dd22c36d7a8b677e6be56b4aec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: devices.c,v 1.14 2001/03/23 13:58:17 mike Exp $"
+ * "$Id: devices.c,v 1.14.2.1 2001/12/26 16:52:52 mike Exp $"
  *
  *   Device scanning routines for the Common UNIX Printing System (CUPS).
  *
@@ -184,10 +184,13 @@ LoadDevices(const char *d)        /* I - Directory to scan */
          * Bad format; strip trailing newline and write an error message.
          */
 
-         line[strlen(line) - 1] = '\0';
+          if (line[strlen(line) - 1] == '\n')
+           line[strlen(line) - 1] = '\0';
+
          LogMessage(L_ERROR, "LoadDevices: Bad line from \"%s\": %s",
                     dent->d_name, line);
           compat = 1;
+         break;
         }
        else
        {
@@ -475,5 +478,5 @@ sigalrm_handler(int sig)    /* I - Signal number */
 
 
 /*
- * End of "$Id: devices.c,v 1.14 2001/03/23 13:58:17 mike Exp $".
+ * End of "$Id: devices.c,v 1.14.2.1 2001/12/26 16:52:52 mike Exp $".
  */
index a3dc19fe7416107f8c989f69c2437ef46111836c..dfad0ea9485c1bc4270cb465870e62091cc9c40c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $"
+ * "$Id: dirsvc.c,v 1.73.2.3 2001/12/26 16:52:52 mike Exp $"
  *
  *   Directory services routines for the Common UNIX Printing System (CUPS).
  *
  *
  * Contents:
  *
- *   StartBrowsing()    - Start sending and receiving broadcast information.
- *   StopBrowsing()     - Stop sending and receiving broadcast information.
- *   UpdateBrowseList() - Update the browse lists for any new browse data.
- *   SendBrowseList()   - Send new browsing information.
- *   StartPolling()     - Start polling servers as needed.
- *   StopPolling()      - Stop polling servers as needed.
+ *   ProcessBrowseData() - Process new browse data.
+ *   SendBrowseList()    - Send new browsing information as necessary.
+ *   SendCUPSBrowse()    - Send new browsing information using the CUPS protocol.
+ *   StartBrowsing()     - Start sending and receiving broadcast information.
+ *   StartPolling()      - Start polling servers as needed.
+ *   StopBrowsing()      - Stop sending and receiving broadcast information.
+ *   StopPolling()       - Stop polling servers as needed.
+ *   UpdateCUPSBrowse()  - Update the browse lists using the CUPS protocol.
+ *   RegReportCallback() - Empty SLPRegReport.
+ *   SendSLPBrowse()     - Register the specified printer with SLP.
+ *   SLPDeregPrinter()   - SLPDereg() the specified printer
+ *   GetSlpAttrVal()     - Get an attribute from an SLP registration.
+ *   AttrCallback()      - SLP attribute callback 
+ *   SrvUrlCallback()    - SLP service url callback
+ *   UpdateSLPBrowse()   - Get browsing information via SLP.
  */
 
 /*
 #include <grp.h>
 
 
+/*
+ * 'ProcessBrowseData()' - Process new browse data.
+ */
+
+void
+ProcessBrowseData(const char   *uri,   /* I - URI of printer/class */
+                  cups_ptype_t type,   /* I - Printer type */
+                 ipp_pstate_t state,   /* I - Printer state */
+                  const char   *location,/* I - Printer location */
+                 const char   *info,   /* I - Printer information */
+                  const char   *make_model) /* I - Printer make and model */
+{
+  int          i;                      /* Looping var */
+  int          update;                 /* Update printer attributes? */
+  char         method[HTTP_MAX_URI],   /* Method portion of URI */
+               username[HTTP_MAX_URI], /* Username portion of URI */
+               host[HTTP_MAX_URI],     /* Host portion of URI */
+               resource[HTTP_MAX_URI]; /* Resource portion of URI */
+  int          port;                   /* Port portion of URI */
+  char         name[IPP_MAX_NAME],     /* Name of printer */
+               *hptr,                  /* Pointer into hostname */
+               *sptr;                  /* Pointer into ServerName */
+  char         local_make_model[IPP_MAX_NAME];
+                                       /* Local make and model */
+  printer_t    *p,                     /* Printer information */
+               *pclass,                /* Printer class */
+               *first,                 /* First printer in class */
+               *next;                  /* Next printer in list */
+  int          offset,                 /* Offset of name */
+               len;                    /* Length of name */
+
+
+ /*
+  * Pull the URI apart to see if this is a local or remote printer...
+  */
+
+  httpSeparate(uri, method, username, host, &port, resource);
+
+ /*
+  * OK, this isn't a local printer; see if we already have it listed in
+  * the Printers list, and add it if not...
+  */
+
+  update = 0;
+  hptr   = strchr(host, '.');
+  sptr   = strchr(ServerName, '.');
+
+  if (sptr != NULL && hptr != NULL)
+  {
+   /*
+    * Strip the common domain name components...
+    */
+
+    while (hptr != NULL)
+    {
+      if (strcasecmp(hptr, sptr) == 0)
+      {
+        *hptr = '\0';
+       break;
+      }
+      else
+        hptr = strchr(hptr + 1, '.');
+    }
+  }
+
+  if (type & CUPS_PRINTER_CLASS)
+  {
+   /*
+    * Remote destination is a class...
+    */
+
+    if (strncmp(resource, "/classes/", 9) == 0)
+      snprintf(name, sizeof(name), "%s@%s", resource + 9, host);
+    else
+      return;
+
+    if ((p = FindClass(name)) == NULL && BrowseShortNames)
+    {
+      if ((p = FindClass(resource + 9)) != NULL)
+      {
+        if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
+       {
+        /*
+         * Nope, this isn't the same host; if the hostname isn't the local host,
+         * add it to the other class and then find a class using the full host
+         * name...
+         */
+
+         if (p->type & CUPS_PRINTER_REMOTE)
+         {
+           /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+            strncat(p->name, "@", sizeof(p->name) - 1);
+           strncat(p->name, p->hostname, sizeof(p->name) - 1);
+           SetPrinterAttrs(p);
+           SortPrinters();
+         }
+
+          p = NULL;
+       }
+       else if (!p->hostname[0])
+       {
+         /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+          strncpy(p->hostname, host, sizeof(p->hostname) - 1);
+         strncpy(p->uri, uri, sizeof(p->uri) - 1);
+         strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
+          update = 1;
+        }
+      }
+      else
+      {
+        strncpy(name, resource + 9, sizeof(name) - 1);
+        name[sizeof(name) - 1] = '\0';
+      }
+    }
+    else if (p != NULL && !p->hostname[0])
+    {
+      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
+      strncpy(p->uri, uri, sizeof(p->uri) - 1);
+      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
+      update = 1;
+    }
+
+    if (p == NULL)
+    {
+     /*
+      * Class doesn't exist; add it...
+      */
+
+      p = AddClass(name);
+
+      LogMessage(L_INFO, "Added remote class \"%s\"...", name);
+
+     /*
+      * Force the URI to point to the real server...
+      */
+
+      p->type = type;
+      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+      strncpy(p->uri, uri, sizeof(p->uri) - 1);
+      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
+      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
+
+      update = 1;
+    }
+  }
+  else
+  {
+   /*
+    * Remote destination is a printer...
+    */
+
+    if (strncmp(resource, "/printers/", 10) == 0)
+      snprintf(name, sizeof(name), "%s@%s", resource + 10, host);
+    else
+      return;
+
+    if ((p = FindPrinter(name)) == NULL && BrowseShortNames)
+    {
+      if ((p = FindPrinter(resource + 10)) != NULL)
+      {
+        if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
+       {
+        /*
+         * Nope, this isn't the same host; if the hostname isn't the local host,
+         * add it to the other printer and then find a printer using the full host
+         * name...
+         */
+
+         if (p->type & CUPS_PRINTER_REMOTE)
+         {
+           /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+            strncat(p->name, "@", sizeof(p->name) - 1);
+           strncat(p->name, p->hostname, sizeof(p->name) - 1);
+           SetPrinterAttrs(p);
+           SortPrinters();
+         }
+
+          p = NULL;
+       }
+       else if (!p->hostname[0])
+       {
+         /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+          strncpy(p->hostname, host, sizeof(p->hostname) - 1);
+         strncpy(p->uri, uri, sizeof(p->uri) - 1);
+         strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
+          update = 1;
+        }
+      }
+      else
+      {
+        strncpy(name, resource + 10, sizeof(name) - 1);
+        name[sizeof(name) - 1] = '\0';
+      }
+    }
+    else if (p != NULL && !p->hostname[0])
+    {
+      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
+      strncpy(p->uri, uri, sizeof(p->uri) - 1);
+      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
+      update = 1;
+    }
+
+    if (p == NULL)
+    {
+     /*
+      * Printer doesn't exist; add it...
+      */
+
+      p = AddPrinter(name);
+
+      LogMessage(L_INFO, "Added remote printer \"%s\"...", name);
+
+     /*
+      * Force the URI to point to the real server...
+      */
+
+      p->type = type;
+      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
+      strncpy(p->uri, uri, sizeof(p->uri) - 1);
+      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
+
+      update = 1;
+    }
+  }
+
+ /*
+  * Update the state...
+  */
+
+  p->state       = state;
+  p->accepting   = state != IPP_PRINTER_STOPPED;
+  p->browse_time = time(NULL);
+
+  if (p->type != type)
+  {
+    p->type = type;
+    update  = 1;
+  }
+
+  if (strcmp(p->location, location))
+  {
+    /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+    strncpy(p->location, location, sizeof(p->location) - 1);
+    update = 1;
+  }
+
+  if (strcmp(p->info, info))
+  {
+    /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+    strncpy(p->info, info, sizeof(p->info) - 1);
+    update = 1;
+  }
+
+  if (!make_model[0])
+  {
+    if (type & CUPS_PRINTER_CLASS)
+      snprintf(local_make_model, sizeof(local_make_model),
+               "Remote Class on %s", host);
+    else
+      snprintf(local_make_model, sizeof(local_make_model),
+               "Remote Printer on %s", host);
+  }
+  else
+    snprintf(local_make_model, sizeof(local_make_model),
+             "%s on %s", make_model, host);
+
+  if (strcmp(p->make_model, local_make_model))
+  {
+    /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
+    strncpy(p->make_model, local_make_model, sizeof(p->make_model) - 1);
+    update = 1;
+  }
+
+  if (update)
+    SetPrinterAttrs(p);
+
+ /*
+  * See if we have a default printer...  If not, make the first printer the
+  * default.
+  */
+
+  if (DefaultPrinter == NULL && Printers != NULL)
+    DefaultPrinter = Printers;
+
+ /*
+  * Do auto-classing if needed...
+  */
+
+  if (ImplicitClasses)
+  {
+   /*
+    * Loop through all available printers and create classes as needed...
+    */
+
+    for (p = Printers, len = 0, offset = 0, first = NULL;
+         p != NULL;
+        p = next)
+    {
+     /*
+      * Get next printer in list...
+      */
+
+      next = p->next;
+
+     /*
+      * Skip classes...
+      */
+
+      if (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS))
+      {
+        len = 0;
+        continue;
+      }
+
+     /*
+      * If len == 0, get the length of this printer name up to the "@"
+      * sign (if any).
+      */
+
+      if (len > 0 &&
+         strncasecmp(p->name, name + offset, len) == 0 &&
+         (p->name[len] == '\0' || p->name[len] == '@'))
+      {
+       /*
+       * We have more than one printer with the same name; see if
+       * we have a class, and if this printer is a member...
+       */
+
+        if ((pclass = FindPrinter(name)) == NULL)
+       {
+        /*
+         * Need to add the class...
+         */
+
+         pclass = AddPrinter(name);
+         pclass->type      |= CUPS_PRINTER_IMPLICIT;
+         pclass->accepting = 1;
+         pclass->state     = IPP_PRINTER_IDLE;
+
+          SetPrinterAttrs(pclass);
+
+          LogMessage(L_INFO, "Added implicit class \"%s\"...", name);
+       }
+
+        if (first != NULL)
+       {
+          for (i = 0; i < pclass->num_printers; i ++)
+           if (pclass->printers[i] == first)
+             break;
+
+          if (i >= pclass->num_printers)
+           AddPrinterToClass(pclass, first);
+
+         first = NULL;
+       }
+
+        for (i = 0; i < pclass->num_printers; i ++)
+         if (pclass->printers[i] == p)
+           break;
+
+        if (i >= pclass->num_printers)
+         AddPrinterToClass(pclass, p);
+      }
+      else
+      {
+       /*
+        * First time around; just get name length and mark it as first
+       * in the list...
+       */
+
+       if ((hptr = strchr(p->name, '@')) != NULL)
+         len = hptr - p->name;
+       else
+         len = strlen(p->name);
+
+        strncpy(name, p->name, len);
+       name[len] = '\0';
+       offset    = 0;
+
+       if ((pclass = FindPrinter(name)) != NULL &&
+           !(pclass->type & CUPS_PRINTER_IMPLICIT))
+       {
+        /*
+         * Can't use same name as a local printer; add "Any" to the
+         * front of the name, unless we have explicitly disabled
+         * the "ImplicitAnyClasses"...
+         */
+
+          if (ImplicitAnyClasses)
+         {
+          /*
+           * Add "Any" to the class name...
+           */
+
+            strcpy(name, "Any");
+            strncpy(name + 3, p->name, len);
+           name[len + 3] = '\0';
+           offset        = 3;
+         }
+         else
+         {
+          /*
+           * Don't create an implicit class if we have a local printer
+           * with the same name...
+           */
+
+           len = 0;
+           continue;
+         }
+       }
+
+       first = p;
+      }
+    }
+  }
+}
+
+
+/*
+ * 'SendBrowseList()' - Send new browsing information as necessary.
+ */
+
+void
+SendBrowseList(void)
+{
+  printer_t            *p,     /* Current printer */
+                       *np;    /* Next printer */
+  time_t               ut,     /* Minimum update time */
+                       to;     /* Timeout time */
+
+
+  if (!Browsing || !(BrowseProtocols & BROWSE_CUPS))
+    return;
+
+ /*
+  * Compute the update and timeout times...
+  */
+
+  ut = time(NULL) - BrowseInterval;
+  to = time(NULL) - BrowseTimeout;
+
+ /*
+  * Loop through all of the printers and send local updates as needed...
+  */
+
+  for (p = Printers; p != NULL; p = np)
+  {
+    np = p->next;
+
+    if (p->type & CUPS_PRINTER_REMOTE)
+    {
+     /*
+      * See if this printer needs to be timed out...
+      */
+
+      if (p->browse_time < to)
+      {
+        LogMessage(L_INFO, "Remote destination \"%s\" has timed out; deleting it...",
+                  p->name);
+        DeletePrinter(p);
+      }
+    }
+    else if (p->browse_time < ut &&  BrowseInterval > 0 &&
+            !(p->type & CUPS_PRINTER_IMPLICIT))
+    {
+     /*
+      * Need to send an update...
+      */
+
+      p->browse_time = time(NULL);
+
+      if (BrowseProtocols & BROWSE_CUPS)
+        SendCUPSBrowse(p);
+
+#ifdef HAVE_LIBSLP
+      if (BrowseProtocols & BROWSE_SLP)
+        SendSLPBrowse(p);
+#endif /* HAVE_LIBSLP */
+    }
+  }
+}
+
+
+/*
+ * 'SendCUPSBrowse()' - Send new browsing information using the CUPS protocol.
+ */
+
+void
+SendCUPSBrowse(printer_t *p)   /* I - Printer to send */
+{
+  int                  i;      /* Looping var */
+  int                  bytes;  /* Length of packet */
+  char                 packet[1453];
+                               /* Browse data packet */
+
+
+  snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
+           p->type | CUPS_PRINTER_REMOTE, p->state, p->uri,
+          p->location, p->info, p->make_model);
+
+  bytes = strlen(packet);
+  LogMessage(L_DEBUG2, "SendBrowseList: (%d bytes) %s", bytes, packet);
+
+ /*
+  * Send a packet to each browse address...
+  */
+
+  for (i = 0; i < NumBrowsers; i ++)
+    if (sendto(BrowseSocket, packet, bytes, 0,
+              (struct sockaddr *)Browsers + i, sizeof(Browsers[0])) <= 0)
+    {
+      LogMessage(L_ERROR, "SendBrowseList: sendto failed for browser %d - %s.",
+                i + 1, strerror(errno));
+      LogMessage(L_ERROR, "Browsing turned off.");
+
+      StopBrowsing();
+      Browsing = 0;
+      return;
+    }
+}
+
+
 /*
  * 'StartBrowsing()' - Start sending and receiving broadcast information.
  */
@@ -53,112 +587,243 @@ StartBrowsing(void)
   if (!Browsing)
     return;
 
- /*
-  * Create the broadcast socket...
-  */
+  if (BrowseProtocols & BROWSE_CUPS)
+  {
+   /*
+    * Create the broadcast socket...
+    */
+
+    if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+    {
+      LogMessage(L_ERROR, "StartBrowsing: Unable to create broadcast socket - %s.",
+                strerror(errno));
+      Browsing = 0;
+      return;
+    }
+
+   /*
+    * Set the "broadcast" flag...
+    */
+
+    val = 1;
+    if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
+    {
+      LogMessage(L_ERROR, "StartBrowsing: Unable to set broadcast mode - %s.",
+                strerror(errno));
+
+  #if defined(WIN32) || defined(__EMX__)
+      closesocket(BrowseSocket);
+  #else
+      close(BrowseSocket);
+  #endif /* WIN32 || __EMX__ */
+
+      BrowseSocket = -1;
+      Browsing     = 0;
+      return;
+    }
+
+   /*
+    * Bind the socket to browse port...
+    */
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    addr.sin_family      = AF_INET;
+    addr.sin_port        = htons(BrowsePort);
+
+    if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr)))
+    {
+      LogMessage(L_ERROR, "StartBrowsing: Unable to bind broadcast socket - %s.",
+                strerror(errno));
 
-  if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+  #if defined(WIN32) || defined(__EMX__)
+      closesocket(BrowseSocket);
+  #else
+      close(BrowseSocket);
+  #endif /* WIN32 || __EMX__ */
+
+      BrowseSocket = -1;
+      Browsing     = 0;
+      return;
+    }
+
+   /*
+    * Finally, add the socket to the input selection set...
+    */
+
+    LogMessage(L_DEBUG2, "StartBrowsing: Adding fd %d to InputSet...",
+               BrowseSocket);
+
+    FD_SET(BrowseSocket, &InputSet);
+  }
+
+#ifdef HAVE_LIBSLP
+  if (BrowseProtocols & BROWSE_SLP)
   {
-    LogMessage(L_ERROR, "StartBrowsing: Unable to create broadcast socket - %s.",
-               strerror(errno));
-    Browsing = 0;
-    return;
+   /* 
+    * Open SLP handle...
+    */
+
+    if (SLPOpen("en", SLP_FALSE, &BrowseSLPHandle) != SLP_OK)
+    {
+      LogMessage(L_ERROR, "Unable to open an SLP handle; disabling SLP browsing!");
+      BrowseProtocols &= ~BROWSE_SLP;
+    }
+
+    BrowseSLPRefresh = 0;
   }
+}
 
- /*
-  * Set the "broadcast" flag...
-  */
 
-  val = 1;
-  if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
+/*
+ * 'StartPolling()' - Start polling servers as needed.
+ */
+
+void
+StartPolling(void)
+{
+  int          i;              /* Looping var */
+  dirsvc_poll_t        *poll;          /* Current polling server */
+  int          pid;            /* New process ID */
+  char         sport[10];      /* Server port */
+  char         bport[10];      /* Browser port */
+  char         interval[10];   /* Poll interval */
+
+
+  sprintf(bport, "%d", BrowsePort);
+
+  if (BrowseInterval)
+    sprintf(interval, "%d", BrowseInterval);
+  else
+    strcpy(interval, "30");
+
+  for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
   {
-    LogMessage(L_ERROR, "StartBrowsing: Unable to set broadcast mode - %s.",
-               strerror(errno));
+    sprintf(sport, "%d", poll->port);
 
-#if defined(WIN32) || defined(__EMX__)
-    closesocket(BrowseSocket);
-#else
-    close(BrowseSocket);
-#endif /* WIN32 || __EMX__ */
+    if ((pid = fork()) == 0)
+    {
+     /*
+      * Child...
+      */
 
-    BrowseSocket = -1;
-    Browsing     = 0;
-    return;
+      if (getuid() == 0)
+      {
+       /*
+       * Running as root, so change to non-priviledged user...
+       */
+
+       if (setgid(Group))
+          exit(errno);
+
+       if (setuid(User))
+          exit(errno);
+      }
+
+     /*
+      * Reset group membership to just the main one we belong to.
+      */
+
+      setgroups(0, NULL);
+
+     /*
+      * Execute the polling daemon...
+      */
+
+      execl(CUPS_SERVERBIN "/daemon/cups-polld", "cups-polld", poll->hostname,
+            sport, interval, bport, NULL);
+      exit(errno);
+    }
+    else if (pid < 0)
+    {
+      LogMessage(L_ERROR, "StartPolling: Unable to fork polling daemon - %s",
+                 strerror(errno));
+      poll->pid = 0;
+      break;
+    }
+    else
+    {
+      poll->pid = pid;
+      LogMessage(L_DEBUG, "StartPolling: Started polling daemon for %s:%d, pid = %d",
+                 poll->hostname, poll->port, pid);
+    }
   }
+>>>>>>> 1.86
+}
 
- /*
-  * Bind the socket to browse port...
-  */
 
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_addr.s_addr = htonl(INADDR_ANY);
-  addr.sin_family      = AF_INET;
-  addr.sin_port        = htons(BrowsePort);
+/*
+ * 'StopBrowsing()' - Stop sending and receiving broadcast information.
+ */
+
+void
+StopBrowsing(void)
+{
+  if (!Browsing)
+    return;
 
-  if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr)))
+  if (BrowseProtocols & BROWSE_CUPS)
   {
-    LogMessage(L_ERROR, "StartBrowsing: Unable to bind broadcast socket - %s.",
-               strerror(errno));
+   /*
+    * Close the socket and remove it from the input selection set.
+    */
 
+    if (BrowseSocket >= 0)
+    {
 #if defined(WIN32) || defined(__EMX__)
-    closesocket(BrowseSocket);
+      closesocket(BrowseSocket);
 #else
-    close(BrowseSocket);
+      close(BrowseSocket);
 #endif /* WIN32 || __EMX__ */
 
-    BrowseSocket = -1;
-    Browsing     = 0;
-    return;
+      LogMessage(L_DEBUG2, "StopBrowsing: Removing fd %d from InputSet...",
+                BrowseSocket);
+
+      FD_CLR(BrowseSocket, &InputSet);
+      BrowseSocket = 0;
+    }
   }
 
- /*
-  * Finally, add the socket to the input selection set...
-  */
+#ifdef HAVE_LIBSLP
+  if (BrowseProtocols & BROWSE_SLP)
+  {
+   /* 
+    * Close SLP handle...
+    */
 
-  FD_SET(BrowseSocket, &InputSet);
+    SLPClose(BrowseSLPHandle);
+  }
+#endif /* HAVE_LIBSLP */
 }
 
 
 /*
- * 'StopBrowsing()' - Stop sending and receiving broadcast information.
+ * 'StopPolling()' - Stop polling servers as needed.
  */
 
 void
-StopBrowsing(void)
+StopPolling(void)
 {
-  if (!Browsing)
-    return;
-
- /*
-  * Close the socket and remove it from the input selection set.
-  */
+  int          i;              /* Looping var */
+  dirsvc_poll_t        *poll;          /* Current polling server */
 
-  if (BrowseSocket >= 0)
-  {
-#if defined(WIN32) || defined(__EMX__)
-    closesocket(BrowseSocket);
-#else
-    close(BrowseSocket);
-#endif /* WIN32 || __EMX__ */
 
-    FD_CLR(BrowseSocket, &InputSet);
-    BrowseSocket = 0;
-  }
+  for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
+    if (poll->pid)
+      kill(poll->pid, SIGTERM);
 }
 
 
 /*
- * 'UpdateBrowseList()' - Update the browse lists for any new browse data.
+ * 'UpdateCUPSBrowse()' - Update the browse lists using the CUPS protocol.
  */
 
 void
-UpdateBrowseList(void)
+UpdateCUPSBrowse(void)
 {
   int          i;                      /* Looping var */
-  int          update;                 /* Update printer attributes? */
   int          auth;                   /* Authorization status */
-  int          len,                    /* Length of name string */
-               offset;                 /* Offset in name string */
+  int          len;                    /* Length of name string */
   int          bytes;                  /* Number of bytes left */
   char         packet[1540],           /* Broadcast packet */
                *pptr;                  /* Pointer into packet */
@@ -177,13 +842,6 @@ UpdateBrowseList(void)
                location[IPP_MAX_NAME], /* Location string */
                make_model[IPP_MAX_NAME];/* Make and model string */
   int          port;                   /* Port portion of URI */
-  char         name[IPP_MAX_NAME],     /* Name of printer */
-               *hptr,                  /* Pointer into hostname */
-               *sptr;                  /* Pointer into ServerName */
-  printer_t    *p,                     /* Printer information */
-               *pclass,                /* Printer class */
-               *first,                 /* First printer in class */
-               *next;                  /* Next printer in list */
 
 
  /*
@@ -251,7 +909,7 @@ UpdateBrowseList(void)
   * Do ACL stuff...
   */
 
-  if (BrowseACL)
+  if (BrowseACL && (BrowseACL->num_allow || BrowseACL->num_deny))
   {
     if (httpAddrLocalhost(&srcaddr) || strcasecmp(srcname, "localhost") == 0)
     {
@@ -316,8 +974,6 @@ UpdateBrowseList(void)
   * Parse packet...
   */
 
-  update = 0;
-
   if (sscanf(packet, "%x%x%1023s", (unsigned *)&type, (unsigned *)&state,
              uri) < 3)
   {
@@ -412,553 +1068,521 @@ UpdateBrowseList(void)
       }
 
  /*
-  * OK, this isn't a local printer; see if we already have it listed in
-  * the Printers list, and add it if not...
+  * Process the browse data...
   */
 
-  hptr = strchr(host, '.');
-  sptr = strchr(ServerName, '.');
-
-  if (sptr != NULL && hptr != NULL)
-  {
-   /*
-    * Strip the common domain name components...
-    */
-
-    while (hptr != NULL)
-    {
-      if (strcasecmp(hptr, sptr) == 0)
-      {
-        *hptr = '\0';
-       break;
-      }
-      else
-        hptr = strchr(hptr + 1, '.');
-    }
-  }
-
-  if (type & CUPS_PRINTER_CLASS)
-  {
-   /*
-    * Remote destination is a class...
-    */
-
-    if (strncmp(resource, "/classes/", 9) == 0)
-      snprintf(name, sizeof(name), "%s@%s", resource + 9, host);
-    else
-      return;
-
-    if ((p = FindClass(name)) == NULL && BrowseShortNames)
-    {
-      if ((p = FindClass(resource + 9)) != NULL)
-      {
-        if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
-       {
-        /*
-         * Nope, this isn't the same host; if the hostname isn't the local host,
-         * add it to the other class and then find a class using the full host
-         * name...
-         */
-
-         if (p->type & CUPS_PRINTER_REMOTE)
-         {
-           /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-            strncat(p->name, "@", sizeof(p->name) - 1);
-           strncat(p->name, p->hostname, sizeof(p->name) - 1);
-           SetPrinterAttrs(p);
-           SortPrinters();
-         }
+  ProcessBrowseData(uri, type, state, location, info, make_model);
+}
 
-          p = NULL;
-       }
-       else if (!p->hostname[0])
-       {
-         /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-          strncpy(p->hostname, host, sizeof(p->hostname) - 1);
-         strncpy(p->uri, uri, sizeof(p->uri) - 1);
-         strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
-         strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
-          update = 1;
-        }
-      }
-      else
-      {
-        strncpy(name, resource + 9, sizeof(name) - 1);
-        name[sizeof(name) - 1] = '\0';
-      }
-    }
-    else if (!p->hostname[0])
-    {
-      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
-      strncpy(p->uri, uri, sizeof(p->uri) - 1);
-      strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
-      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
-      update = 1;
-    }
 
-    if (p == NULL)
-    {
-     /*
-      * Class doesn't exist; add it...
-      */
+/***********************************************************************
+ **** SLP Support Code *************************************************
+ ***********************************************************************/
 
-      p = AddClass(name);
+#ifdef HAVE_LIBSLP 
+/*
+ * SLP service name for CUPS...
+ */
 
-     /*
-      * Force the URI to point to the real server...
-      */
+#  define SLP_CUPS_SRVTYPE     "service:printer"
+#  define SLP_CUPS_SRVLEN      15
 
-      p->type = type;
-      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-      strncpy(p->uri, uri, sizeof(p->uri) - 1);
-      strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
-      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
-      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
+typedef struct _slpsrvurl
+{
+  struct _slpsrvurl    *next;
+  char                 url[HTTP_MAX_URI];
+} slpsrvurl_t;
 
-      update = 1;
-    }
-  }
-  else
-  {
-   /*
-    * Remote destination is a printer...
-    */
 
-    if (strncmp(resource, "/printers/", 10) == 0)
-      snprintf(name, sizeof(name), "%s@%s", resource + 10, host);
-    else
-      return;
+/*
+ * 'RegReportCallback()' - Empty SLPRegReport.
+ */
 
-    if ((p = FindPrinter(name)) == NULL && BrowseShortNames)
-    {
-      if ((p = FindPrinter(resource + 10)) != NULL)
-      {
-        if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
-       {
-        /*
-         * Nope, this isn't the same host; if the hostname isn't the local host,
-         * add it to the other printer and then find a printer using the full host
-         * name...
-         */
+void
+RegReportCallback(SLPHandle hslp,
+                  SLPError  errcode,
+                 void      *cookie)
+{
+  (void)hslp;
+  (void)errcode;
+  (void)cookie;
 
-         if (p->type & CUPS_PRINTER_REMOTE)
-         {
-           /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-            strncat(p->name, "@", sizeof(p->name) - 1);
-           strncat(p->name, p->hostname, sizeof(p->name) - 1);
-           SetPrinterAttrs(p);
-           SortPrinters();
-         }
+  return;
+}
 
-          p = NULL;
-       }
-       else if (!p->hostname[0])
-       {
-         /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-          strncpy(p->hostname, host, sizeof(p->hostname) - 1);
-         strncpy(p->uri, uri, sizeof(p->uri) - 1);
-         strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
-         strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
-          update = 1;
-        }
-      }
-      else
-      {
-        strncpy(name, resource + 10, sizeof(name) - 1);
-        name[sizeof(name) - 1] = '\0';
-      }
-    }
-    else if (!p->hostname[0])
-    {
-      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
-      strncpy(p->uri, uri, sizeof(p->uri) - 1);
-      strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
-      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
-      update = 1;
-    }
 
-    if (p == NULL)
-    {
-     /*
-      * Printer doesn't exist; add it...
-      */
+/*
+ * 'SendSLPBrowse()' - Register the specified printer with SLP.
+ */
 
-      p = AddPrinter(name);
+void 
+SendSLPBrowse(printer_t *p)            /* I - Printer to register */
+{
+  char         srvurl[HTTP_MAX_URI],   /* Printer service URI */
+               attrs[8192],            /* Printer attributes */
+               finishings[1024],       /* Finishings to support */
+               make_model[IPP_MAX_NAME * 2],
+                                       /* Make and model, quoted */
+               location[IPP_MAX_NAME * 2],
+                                       /* Location, quoted */
+               info[IPP_MAX_NAME * 2],
+                                       /* Info, quoted */
+               *src,                   /* Pointer to original string */
+               *dst;                   /* Pointer to destination string */
+  ipp_attribute_t *authentication;     /* uri-authentication-supported value */
+  SLPError     error;                  /* SLP error, if any */
+
+
+  LogMessage(L_DEBUG, "SendSLPBrowse(%p = \"%s\")", p, p->name);
 
-     /*
-      * Force the URI to point to the real server...
-      */
+ /*
+  * Make the SLP service URL that conforms to the IANA 
+  * 'printer:' template.
+  */
 
-      p->type = type;
-      /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-      strncpy(p->hostname, host, sizeof(p->hostname) - 1);
-      strncpy(p->uri, uri, sizeof(p->uri) - 1);
-      strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
-      strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
+  snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
 
-      update = 1;
-    }
-  }
+  LogMessage(L_DEBUG2, "Service URL = \"%s\"", srvurl);
 
  /*
-  * Update the state...
+  * Figure out the finishings string...
   */
 
-  p->state       = state;
-  p->accepting   = state != IPP_PRINTER_STOPPED;
-  p->browse_time = time(NULL);
+  if (p->type & CUPS_PRINTER_STAPLE)
+    strcpy(finishings, "staple");
+  else
+    finishings[0] = '\0';
 
-  if (p->type != type)
+  if (p->type & CUPS_PRINTER_BIND)
   {
-    p->type = type;
-    update  = 1;
+    if (finishings[0])
+      strncat(finishings, ",bind", sizeof(finishings) - 1);
+    else
+      strcpy(finishings, "bind");
   }
 
-  if (strcmp(p->location, location))
+  if (p->type & CUPS_PRINTER_PUNCH)
   {
-    /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-    strncpy(p->location, location, sizeof(p->location) - 1);
-    update = 1;
+    if (finishings[0])
+      strncat(finishings, ",punch", sizeof(finishings) - 1);
+    else
+      strcpy(finishings, "punch");
   }
 
-  if (strcmp(p->info, info))
+  if (p->type & CUPS_PRINTER_COVER)
   {
-    /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-    strncpy(p->info, info, sizeof(p->info) - 1);
-    update = 1;
+    if (finishings[0])
+      strncat(finishings, ",cover", sizeof(finishings) - 1);
+    else
+      strcpy(finishings, "cover");
   }
 
-  if (!make_model[0])
+  if (p->type & CUPS_PRINTER_SORT)
   {
-    if (type & CUPS_PRINTER_CLASS)
-      snprintf(make_model, sizeof(p->make_model), "Remote Class on %s",
-               host);
+    if (finishings[0])
+      strncat(finishings, ",sort", sizeof(finishings) - 1);
     else
-      snprintf(make_model, sizeof(p->make_model), "Remote Printer on %s",
-               host);
+      strcpy(finishings, "sort");
   }
-  else
+
+  if (!finishings[0])
+    strcpy(finishings, "none");
+
+  finishings[sizeof(finishings) - 1] = '\0';
+
+ /*
+  * Quote any commas in the make and model, location, and info strings
+  * (local strings are twice the size of the ones in the printer_t
+  * structure, so no buffer overflow is possible...)
+  */
+
+  for (src = p->make_model, dst = make_model; *src;)
+  {
+    if (*src == ',' || *src == '\\' || *src == ')')
+      *dst++ = '\\';
+
+    *dst++ = *src++;
+  }
+
+  *dst = '\0';
+
+  if (!make_model[0])
+    strcpy(make_model, "Unknown");
+
+  for (src = p->location, dst = location; *src;)
   {
-    strncat(make_model, " on ", sizeof(make_model) - 1);
-    strncat(make_model, host, sizeof(make_model) - 1);
-    make_model[sizeof(make_model) - 1] = '\0';
+    if (*src == ',' || *src == '\\' || *src == ')')
+      *dst++ = '\\';
+
+    *dst++ = *src++;
   }
 
-  if (strcmp(p->make_model, make_model))
+  *dst = '\0';
+
+  if (!location[0])
+    strcpy(location, "Unknown");
+
+  for (src = p->info, dst = info; *src;)
   {
-    /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
-    strncpy(p->make_model, make_model, sizeof(p->make_model) - 1);
-    update = 1;
+    if (*src == ',' || *src == '\\' || *src == ')')
+      *dst++ = '\\';
+
+    *dst++ = *src++;
   }
 
-  if (update)
-    SetPrinterAttrs(p);
+  *dst = '\0';
+
+  if (!info[0])
+    strcpy(info, "Unknown");
+
+ /*
+  * Get the authentication value...
+  */
+
+  authentication = ippFindAttribute(p->attrs, "uri-authentication-supported",
+                                    IPP_TAG_KEYWORD);
 
  /*
-  * See if we have a default printer...  If not, make the first printer the
-  * default.
+  * Make the SLP attribute string list that conforms to
+  * the IANA 'printer:' template.
   */
 
-  if (DefaultPrinter == NULL && Printers != NULL)
-    DefaultPrinter = Printers;
+  snprintf(attrs, sizeof(attrs),
+           "(printer-uri-supported=%s),"
+           "(uri-authentication-supported=%s>),"
+#ifdef HAVE_LIBSSL
+           "(uri-security-supported=tls>),"
+#else
+           "(uri-security-supported=none>),"
+#endif /* HAVE_LIBSSL */
+           "(printer-name=%s),"
+           "(printer-location=%s),"
+           "(printer-info=%s),"
+           "(printer-more-info=%s),"
+           "(printer-make-and-model=%s),"
+          "(charset-supported=utf-8),"
+          "(natural-language-configured=%s),"
+          "(natural-language-supported=de,en,es,fr,it),"
+           "(color-supported=%s),"
+           "(finishings-supported=%s),"
+           "(sides-supported=one-sided%s),"
+          "(multiple-document-jobs-supported=true)"
+          "(ipp-versions-supported=1.0,1.1)",
+          p->uri, authentication->values[0].string.text, p->name, location,
+          info, p->uri, make_model, DefaultLanguage,
+           p->type & CUPS_PRINTER_COLOR ? "true" : "false",
+           finishings,
+           p->type & CUPS_PRINTER_DUPLEX ?
+              ",two-sided-long-edge,two-sided-short-edge" : "");
+
+  LogMessage(L_DEBUG2, "Attributes = \"%s\"", attrs);
 
  /*
-  * Do auto-classing if needed...
+  * Register the printer with the SLP server...
   */
 
-  if (ImplicitClasses)
+  error = SLPReg(BrowseSLPHandle, srvurl, BrowseTimeout,
+                SLP_CUPS_SRVTYPE, attrs, SLP_TRUE, RegReportCallback, 0);
+
+  if (error != SLP_OK)
+    LogMessage(L_ERROR, "SLPReg of \"%s\" failed with status %d!", p->name,
+               error);
+}
+
+
+/*
+ * 'SLPDeregPrinter()' - SLPDereg() the specified printer
+ */
+
+void 
+SLPDeregPrinter(printer_t *p)
+{
+  char srvurl[HTTP_MAX_URI];   /* Printer service URI */
+
+
+  if((p->type & CUPS_PRINTER_REMOTE) == 0)
   {
    /*
-    * Loop through all available printers and create classes as needed...
+    * Make the SLP service URL that conforms to the IANA 
+    * 'printer:' template.
     */
 
-    for (p = Printers, len = 0, offset = 0, first = NULL;
-         p != NULL;
-        p = next)
-    {
-     /*
-      * Get next printer in list...
-      */
+    snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
 
-      next = p->next;
+   /*
+    * Deregister the printer...
+    */
 
-     /*
-      * Skip classes...
-      */
+    SLPDereg(BrowseSLPHandle, srvurl, RegReportCallback, 0);
+  }
+}
 
-      if (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS))
-      {
-        len = 0;
-        continue;
-      }
 
-     /*
-      * If len == 0, get the length of this printer name up to the "@"
-      * sign (if any).
-      */
+/*
+ * 'GetSlpAttrVal()' - Get an attribute from an SLP registration.
+ */
 
-      if (len > 0 &&
-         strncasecmp(p->name, name + offset, len) == 0 &&
-         (p->name[len] == '\0' || p->name[len] == '@'))
+int                                    /* O - 0 on success */
+GetSlpAttrVal(const char *attrlist,    /* I - Attribute list string */
+              const char *tag,         /* I - Name of attribute */
+              char       *valbuf,      /* O - Value */
+              int        valbuflen)    /* I - Max length of value */
+{
+  char *ptr1,                          /* Pointer into string */
+       *ptr2;                          /* ... */
+
+
+  valbuf[0] = '\0';
+
+  if ((ptr1 = strstr(attrlist, tag)) != NULL)
+  {
+    ptr1 += strlen(tag);
+
+    if ((ptr2 = strchr(ptr1,')')) != NULL)
+    {
+      if (valbuflen > (ptr2 - ptr1))
       {
        /*
-       * We have more than one printer with the same name; see if
-       * we have a class, and if this printer is a member...
+        * Copy the value...
        */
 
-        if ((pclass = FindPrinter(name)) == NULL)
-       {
-        /*
-         * Need to add the class...
-         */
+        strncpy(valbuf, ptr1, ptr2 - ptr1);
+       valbuf[ptr2 - ptr1] = '\0';
 
-         pclass = AddPrinter(name);
-         pclass->type      |= CUPS_PRINTER_IMPLICIT;
-         pclass->accepting = 1;
-         pclass->state     = IPP_PRINTER_IDLE;
+       /*
+        * Dequote the value...
+       */
 
-          SetPrinterAttrs(pclass);
+       for (ptr1 = valbuf; *ptr1; ptr1 ++)
+         if (*ptr1 == '\\' && ptr1[1])
+           strcpy(ptr1, ptr1 + 1);
 
-          DEBUG_printf(("Added new class \"%s\", type = %x\n", name,
-                       pclass->type));
-       }
+        return (0);
+      }
+    }
+  }
 
-        if (first != NULL)
-       {
-          for (i = 0; i < pclass->num_printers; i ++)
-           if (pclass->printers[i] == first)
-             break;
+  return (-1);
+}
 
-          if (i >= pclass->num_printers)
-           AddPrinterToClass(pclass, first);
 
-         first = NULL;
-       }
+/*
+ * 'AttrCallback()' - SLP attribute callback 
+ */
 
-        for (i = 0; i < pclass->num_printers; i ++)
-         if (pclass->printers[i] == p)
-           break;
+SLPBoolean
+AttrCallback(SLPHandle  hslp, 
+             const char *attrlist, 
+             SLPError   errcode, 
+             void       *cookie)
+{
+  char         tmp[IPP_MAX_NAME];
+  printer_t    *p = (printer_t*)cookie;
 
-        if (i >= pclass->num_printers)
-         AddPrinterToClass(pclass, p);
-      }
-      else
-      {
-       /*
-        * First time around; just get name length and mark it as first
-       * in the list...
-       */
 
-       if ((hptr = strchr(p->name, '@')) != NULL)
-         len = hptr - p->name;
-       else
-         len = strlen(p->name);
+ /*
+  * Let the compiler know we won't be using these...
+  */
 
-        strncpy(name, p->name, len);
-       name[len] = '\0';
-       offset    = 0;
+  (void)hslp;
 
-       if ((pclass = FindPrinter(name)) != NULL &&
-           !(pclass->type & CUPS_PRINTER_IMPLICIT))
-       {
-        /*
-         * Can't use same name as printer; add "Any" to the front of the
-         * name...
-         */
+ /*
+  * Bail if there was an error
+  */
 
-          strcpy(name, "Any");
-          strncpy(name + 3, p->name, len);
-         name[len + 3] = '\0';
-         offset        = 3;
-       }
+  if (errcode != SLP_OK)
+    return (SLP_TRUE);
 
-       first = p;
-      }
-    }
-  }
+ /*
+  * Parse the attrlist to obtain things needed to build CUPS browse packet
+  */
+
+  memset(p, 0, sizeof(printer_t));
+
+  p->type = CUPS_PRINTER_REMOTE;
+
+  if (GetSlpAttrVal(attrlist, "(printer-location=", p->location,
+                    sizeof(p->location)))
+    return (SLP_FALSE);
+  if (GetSlpAttrVal(attrlist, "(printer-make-and-model=", p->make_model,
+                    sizeof(p->make_model)))
+    return (SLP_FALSE);
+
+  if (GetSlpAttrVal(attrlist, "(color-supported=", tmp, sizeof(tmp)))
+    return (SLP_FALSE);
+  if (strcasecmp(tmp, "true") == 0)
+    p->type |= CUPS_PRINTER_COLOR;
+
+  if (GetSlpAttrVal(attrlist, "(finishings-supported=", tmp, sizeof(tmp)))
+    return (SLP_FALSE);
+  if (strstr(tmp, "staple"))
+    p->type |= CUPS_PRINTER_STAPLE;
+  if (strstr(tmp, "bind"))
+    p->type |= CUPS_PRINTER_BIND;
+  if (strstr(tmp, "punch"))
+    p->type |= CUPS_PRINTER_PUNCH;
+
+  if (GetSlpAttrVal(attrlist, "(sides-supported=", tmp, sizeof(tmp)))
+    return (SLP_FALSE);
+  if (strstr(tmp,"two-sided"))
+    p->type |= CUPS_PRINTER_DUPLEX;
+
+  return (SLP_TRUE);
 }
 
 
 /*
- * 'SendBrowseList()' - Send new browsing information.
+ * 'SrvUrlCallback()' - SLP service url callback
  */
 
-void
-SendBrowseList(void)
+SLPBoolean                             /* O - TRUE = OK, FALSE = error */
+SrvUrlCallback(SLPHandle      hslp,    /* I - SLP handle */
+               const char     *srvurl,         /* I - URL of service */
+               unsigned short lifetime,        /* I - Life of service */
+               SLPError       errcode,         /* I - Existing error code */
+               void           *cookie) /* I - Pointer to service list */
 {
-  int                  i;      /* Looping var */
-  printer_t            *p,     /* Current printer */
-                       *np;    /* Next printer */
-  time_t               ut,     /* Minimum update time */
-                       to;     /* Timeout time */
-  int                  bytes;  /* Length of packet */
-  char                 packet[1453];
-                               /* Browse data packet */
+  slpsrvurl_t  *s,                     /* New service entry */
+               **head;                 /* Pointer to head of entry */
 
 
-  if (!Browsing)
-    return;
+ /*
+  * Let the compiler know we won't be using these vars...
+  */
+
+  (void)hslp;
+  (void)lifetime;
 
  /*
-  * Compute the update time...
+  * Bail if there was an error
   */
 
-  ut = time(NULL) - BrowseInterval;
-  to = time(NULL) - BrowseTimeout;
+  if (errcode != SLP_OK)
+    return (SLP_TRUE);
 
  /*
-  * Loop through all of the printers and send local updates as needed...
+  * Grab the head of the list...
   */
 
-  for (p = Printers; p != NULL; p = np)
-  {
-    np = p->next;
+  head = (slpsrvurl_t**)cookie;
 
-    if (p->type & CUPS_PRINTER_REMOTE)
-    {
-     /*
-      * See if this printer needs to be timed out...
-      */
+ /*
+  * Allocate a *temporary* slpsrvurl_t to hold this entry.
+  */
 
-      if (p->browse_time < to)
-      {
-        LogMessage(L_INFO, "Remote destination \"%s\" has timed out; deleting it...",
-                  p->name);
-        DeletePrinter(p);
-      }
-    }
-    else if (p->browse_time < ut && !(p->type & CUPS_PRINTER_IMPLICIT) &&
-             BrowseInterval > 0)
-    {
-     /*
-      * Need to send an update...
-      */
+  if ((s = (slpsrvurl_t *)calloc(1, sizeof(slpsrvurl_t))) == NULL)
+    return (SLP_FALSE);
 
-      p->browse_time = time(NULL);
+ /*
+  * Copy the SLP service URL...
+  */
 
-      snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
-               p->type | CUPS_PRINTER_REMOTE, p->state, p->uri,
-              p->location, p->info, p->make_model);
+  strncpy(s->url, srvurl, sizeof(s->url));
 
-      bytes = strlen(packet);
-      LogMessage(L_DEBUG2, "SendBrowseList: (%d bytes) %s", bytes, packet);
+ /* 
+  * Link the SLP service URL into the head of the list
+  */
 
-     /*
-      * Send a packet to each browse address...
-      */
+  if (*head)
+    s->next = *head;
 
-      for (i = 0; i < NumBrowsers; i ++)
-       if (sendto(BrowseSocket, packet, bytes, 0,
-                  (struct sockaddr *)Browsers + i, sizeof(Browsers[0])) <= 0)
-       {
-         LogMessage(L_ERROR, "SendBrowseList: sendto failed for browser %d - %s.",
-                    i + 1, strerror(errno));
-         LogMessage(L_ERROR, "Browsing turned off.");
+  *head = s;
 
-         StopBrowsing();
-         Browsing = 0;
-         return;
-       }
-    }
-  }
+  return (SLP_TRUE);
 }
 
 
 /*
- * 'StartPolling()' - Start polling servers as needed.
+ * 'UpdateSLPBrowse()' - Get browsing information via SLP.
  */
 
 void
-StartPolling(void)
+UpdateSLPBrowse(void)
 {
-  int          i;              /* Looping var */
-  dirsvc_poll_t        *poll;          /* Current polling server */
-  int          pid;            /* New process ID */
-  char         sport[10];      /* Server port */
-  char         bport[10];      /* Browser port */
-  char         interval[10];   /* Poll interval */
+  slpsrvurl_t  *s,                     /* Temporary list of service URLs */
+               *next;                  /* Next service in list */
+  printer_t    p;                      /* Printer information */
+  const char   *uri;                   /* Pointer to printer URI */
+  char         method[HTTP_MAX_URI],   /* Method portion of URI */
+               username[HTTP_MAX_URI], /* Username portion of URI */
+               host[HTTP_MAX_URI],     /* Host portion of URI */
+               resource[HTTP_MAX_URI]; /* Resource portion of URI */
+  int          port;                   /* Port portion of URI */
 
 
-  sprintf(bport, "%d", BrowsePort);
+  LogMessage(L_DEBUG, "UpdateSLPBrowse() Start...");
 
-  if (BrowseInterval)
-    sprintf(interval, "%d", BrowseInterval);
-  else
-    strcpy(interval, "30");
+ /*
+  * Reset the refresh time...
+  */
 
-  for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
-  {
-    sprintf(sport, "%d", poll->port);
+  BrowseSLPRefresh = time(NULL) + BrowseTimeout - BrowseInterval;
 
-    if ((pid = fork()) == 0)
-    {
-     /*
-      * Child...
-      */
+ /* 
+  * Poll for remote printers using SLP...
+  */
 
-      if (getuid() == 0)
-      {
-       /*
-       * Running as root, so change to non-priviledged user...
-       */
+  s = NULL;
 
-       if (setgid(Group))
-          exit(errno);
+  SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "",
+             SrvUrlCallback, &s);
 
-       if (setuid(User))
-          exit(errno);
-      }
+ /*
+  * Loop through the list of available printers...
+  */
+
+  for (; s; s = next)
+  {
+   /* 
+    * Load a printer_t structure with the SLP service attributes...
+    */
+
+    SLPFindAttrs(BrowseSLPHandle, s->url, "", "", AttrCallback, &p);
+
+   /*
+    * Process this printer entry...
+    */
+
+    uri = s->url + SLP_CUPS_SRVLEN + 1;
 
+    if (strncmp(uri, "http://", 7) == 0 ||
+        strncmp(uri, "ipp://", 6) == 0)
+    {
      /*
-      * Reset group membership to just the main one we belong to.
+      * Pull the URI apart to see if this is a local or remote printer...
       */
 
-      setgroups(0, NULL);
+      httpSeparate(uri, method, username, host, &port, resource);
+
+      if (strcasecmp(host, ServerName) == 0)
+       continue;
 
      /*
-      * Execute the polling daemon...
+      * OK, at least an IPP printer, see if it is a CUPS printer or
+      * class...
       */
 
-      execl(CUPS_SERVERBIN "/daemon/cups-polld", "cups-polld", poll->hostname,
-            sport, interval, bport, NULL);
-      exit(errno);
-    }
-    else if (pid < 0)
-    {
-      LogMessage(L_ERROR, "StartPolling: Unable to fork polling daemon - %s",
-                 strerror(errno));
-      poll->pid = 0;
-      break;
-    }
-    else
-    {
-      poll->pid = pid;
-      LogMessage(L_DEBUG, "StartPolling: Started polling daemon for %s:%d, pid = %d",
-                 poll->hostname, poll->port, pid);
+      if (strstr(uri, "/printers/") != NULL)
+        ProcessBrowseData(uri, p.type, IPP_PRINTER_IDLE, p.location,
+                         p.info, p.make_model);
+      else if (strstr(uri, "/classes/") != NULL)
+        ProcessBrowseData(uri, p.type | CUPS_PRINTER_CLASS, IPP_PRINTER_IDLE,
+                         p.location, p.info, p.make_model);
     }
-  }
-}
-
-
-/*
- * 'StopPolling()' - Stop polling servers as needed.
- */
 
-void
-StopPolling(void)
-{
-  int          i;              /* Looping var */
-  dirsvc_poll_t        *poll;          /* Current polling server */
+   /*
+    * Save the "next" pointer and free this listing...
+    */
 
+    next = s->next;
+    free(s);
+  }       
 
-  for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
-    if (poll->pid)
-      kill(poll->pid, SIGTERM);
+  LogMessage(L_DEBUG, "UpdateSLPBrowse() End...");
 }
+#endif /* HAVE_LIBSLP */
 
 
 /*
- * End of "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $".
+ * End of "$Id: dirsvc.c,v 1.73.2.3 2001/12/26 16:52:52 mike Exp $".
  */
index ad5fe94055c83f3c2e9e9b094599d7006be7b62c..66990ffde44b02807f63d08dc1b8648df7646b77 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: dirsvc.h,v 1.12.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: dirsvc.h,v 1.12.2.2 2001/12/26 16:52:52 mike Exp $"
  *
  *   Directory services definitions for the Common UNIX Printing System
  *   (CUPS) scheduler.
  *         WWW: http://www.cups.org
  */
 
+/*
+ * Include necessary headers...
+ */
+
+#ifdef HAVE_LIBSLP
+#  include <slp.h>
+#endif /* HAVE_LIBSLP */
+
+
+/*
+ * Browse protocols...
+ */
+
+#define BROWSE_CUPS    1               /* CUPS */
+#define        BROWSE_SLP      2               /* SLPv2 */
+#define BROWSE_LDAP    4               /* LDAP (not supported yet) */
+#define BROWSE_ALL     7               /* All protocols */
+
+
 /*
  * Relay structure...
  */
@@ -52,6 +71,8 @@ typedef struct
 
 VAR int                        Browsing        VALUE(TRUE),
                                        /* Whether or not browsing is enabled */
+                       BrowseProtocols VALUE(BROWSE_ALL),
+                                       /* Protocols to support */
                        BrowseShortNames VALUE(TRUE),
                                        /* Short names for remote printers? */
                        BrowseSocket    VALUE(-1),
@@ -77,20 +98,32 @@ VAR int                     NumPolled       VALUE(0);
 VAR dirsvc_poll_t      Polled[MAX_BROWSERS];
                                        /* Polled servers */
 
+#ifdef HAVE_LIBSLP
+VAR SLPHandle          BrowseSLPHandle VALUE(NULL);
+                                       /* SLP API handle */
+VAR time_t             BrowseSLPRefresh VALUE(0);
+                                       /* Next SLP refresh time */
+#endif /* HAVE_LIBSLP */
+
 
 /*
  * Prototypes...
  */
 
-extern void    StartBrowsing(void);
-extern void    StopBrowsing(void);
-extern void    UpdateBrowseList(void);
+extern void    ProcessBrowseData(const char *uri, cups_ptype_t type,
+                                 ipp_pstate_t state, const char *location,
+                                 const char *info, const char *make_model);
 extern void    SendBrowseList(void);
-
+extern void    SendCUPSBrowse(printer_t *p);
+extern void    SendSLPBrowse(printer_t *p);
+extern void    StartBrowsing(void);
 extern void    StartPolling(void);
+extern void    StopBrowsing(void);
 extern void    StopPolling(void);
+extern void    UpdateCUPSBrowse(void);
+extern void    UpdateSLPBrowse(void);
 
 
 /*
- * End of "$Id: dirsvc.h,v 1.12.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: dirsvc.h,v 1.12.2.2 2001/12/26 16:52:52 mike Exp $".
  */
index cecd041b2cc4febdac6f08ca16720f7dfd1ab8ce..767d38a37b40fcbe8d4de9a74d6f79dc57f8d8c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c,v 1.127.2.2 2001/05/13 18:38:35 mike Exp $"
+ * "$Id: ipp.c,v 1.127.2.3 2001/12/26 16:52:53 mike Exp $"
  *
  *   IPP routines for the Common UNIX Printing System (CUPS) scheduler.
  *
@@ -53,7 +53,7 @@
  *   get_printer_attrs()         - Get printer attributes.
  *   get_printers()              - Get a list of printers.
  *   hold_job()                  - Hold a print job.
- *   move_job()                  - Move a job.
+ *   move_job()                  - Move a job to a new destination.
  *   print_job()                 - Print a file to a printer or class.
  *   reject_jobs()               - Reject print jobs to a printer.
  *   release_job()               - Release a held print job.
@@ -94,7 +94,8 @@ static void   add_queued_job_count(client_t *con, printer_t *p);
 static void    cancel_all_jobs(client_t *con, ipp_attribute_t *uri);
 static void    cancel_job(client_t *con, ipp_attribute_t *uri);
 static int     check_quotas(client_t *con, printer_t *p);
-static void    copy_attribute(ipp_t *to, ipp_attribute_t *attr);
+static void    copy_attribute(ipp_t *to, ipp_attribute_t *attr,
+                              int quickcopy);
 static void    copy_attrs(ipp_t *to, ipp_t *from, ipp_attribute_t *req,
                           ipp_tag_t group);
 static int     copy_banner(client_t *con, job_t *job, const char *name);
@@ -606,17 +607,22 @@ add_class(client_t        *con,           /* I - Client connection */
   else if (pclass->type & CUPS_PRINTER_IMPLICIT)
   {
    /*
-    * Rename the implicit class to "AnyClass"...
+    * Rename the implicit class to "AnyClass" or remove it...
     */
 
-    snprintf(pclass->name, sizeof(pclass->name), "Any%s", resource + 10);
-    SortPrinters();
+    if (ImplicitAnyClasses)
+    {
+      snprintf(pclass->name, sizeof(pclass->name), "Any%s", resource + 9);
+      SortPrinters();
+    }
+    else
+      DeletePrinter(pclass);
 
    /*
     * Add the class as a new local class...
     */
 
-    pclass = AddClass(resource + 10);
+    pclass = AddClass(resource + 9);
     modify = 0;
   }
   else if (pclass->type & CUPS_PRINTER_REMOTE)
@@ -626,7 +632,7 @@ add_class(client_t        *con,             /* I - Client connection */
     */
 
     DeletePrinterFilters(pclass);
-    snprintf(pclass->name, sizeof(pclass->name), "%s@%s", resource + 10,
+    snprintf(pclass->name, sizeof(pclass->name), "%s@%s", resource + 9,
              pclass->hostname);
     SetPrinterAttrs(pclass);
     SortPrinters();
@@ -635,7 +641,7 @@ add_class(client_t        *con,             /* I - Client connection */
     * Add the class as a new local class...
     */
 
-    pclass = AddClass(resource + 10);
+    pclass = AddClass(resource + 9);
     modify = 0;
   }
   else
@@ -657,12 +663,6 @@ add_class(client_t        *con,            /* I - Client connection */
     pclass->info[sizeof(pclass->info) - 1] = '\0';
   }
 
-  if ((attr = ippFindAttribute(con->request, "printer-more-info", IPP_TAG_URI)) != NULL)
-  {
-    strncpy(pclass->more_info, attr->values[0].string.text, sizeof(pclass->more_info) - 1);
-    pclass->more_info[sizeof(pclass->more_info) - 1] = '\0';
-  }
-
   if ((attr = ippFindAttribute(con->request, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN)) != NULL)
   {
     LogMessage(L_INFO, "Setting %s printer-is-accepting-jobs to %d (was %d.)",
@@ -695,7 +695,8 @@ add_class(client_t        *con,             /* I - Client connection */
             sizeof(pclass->state_message) - 1);
     pclass->state_message[sizeof(pclass->state_message) - 1] = '\0';
   }
-  if ((attr = ippFindAttribute(con->request, "job-sheets-default", IPP_TAG_ZERO)) != NULL)
+  if ((attr = ippFindAttribute(con->request, "job-sheets-default", IPP_TAG_ZERO)) != NULL &&
+      !Classification[0])
   {
     strncpy(pclass->job_sheets[0], attr->values[0].string.text,
             sizeof(pclass->job_sheets[0]) - 1);
@@ -704,24 +705,6 @@ add_class(client_t        *con,            /* I - Client connection */
               sizeof(pclass->job_sheets[1]) - 1);
     else
       strcpy(pclass->job_sheets[1], "none");
-
-   /*
-    * Enforce classification level if set...
-    */
-
-    if (Classification[0])
-    {
-      if (strcmp(pclass->job_sheets[0], Classification) != 0 &&
-          strcmp(pclass->job_sheets[1], Classification) != 0)
-      {
-       /*
-        * Force the leading banner to have the classification on it...
-       */
-
-        strcpy(pclass->job_sheets[0], Classification);
-      }
-    }
-
   }
   if ((attr = ippFindAttribute(con->request, "requesting-user-name-allowed",
                                IPP_TAG_ZERO)) != NULL)
@@ -1037,11 +1020,16 @@ add_printer(client_t        *con,       /* I - Client connection */
   else if (printer->type & CUPS_PRINTER_IMPLICIT)
   {
    /*
-    * Rename the implicit printer to "AnyPrinter"...
+    * Rename the implicit printer to "AnyPrinter" or delete it...
     */
 
-    snprintf(printer->name, sizeof(printer->name), "Any%s", resource + 10);
-    SortPrinters();
+    if (ImplicitAnyClasses)
+    {
+      snprintf(printer->name, sizeof(printer->name), "Any%s", resource + 10);
+      SortPrinters();
+    }
+    else
+      DeletePrinter(printer);
 
    /*
     * Add the printer as a new local printer...
@@ -1088,14 +1076,47 @@ add_printer(client_t        *con,       /* I - Client connection */
     printer->info[sizeof(printer->info) - 1] = '\0';
   }
 
-  if ((attr = ippFindAttribute(con->request, "printer-more-info", IPP_TAG_URI)) != NULL)
-  {
-    strncpy(printer->more_info, attr->values[0].string.text, sizeof(printer->more_info) - 1);
-    printer->more_info[sizeof(printer->more_info) - 1] = '\0';
-  }
-
   if ((attr = ippFindAttribute(con->request, "device-uri", IPP_TAG_URI)) != NULL)
   {
+    ipp_attribute_t    *device;        /* Current device */
+    int                        methodlen;      /* Length of method string */
+
+
+   /*
+    * Do we have a valid device URI?
+    */
+
+    httpSeparate(attr->values[0].string.text, method, username, host,
+                 &port, resource);
+    methodlen = strlen(method);
+
+    if (strcmp(method, "file") != 0)
+    {
+     /*
+      * See if the backend is listed as a device...
+      */
+
+      for (device = ippFindAttribute(Devices, "device-uri", IPP_TAG_URI);
+           device != NULL;
+          device = ippFindNextAttribute(Devices, "device-uri", IPP_TAG_URI))
+        if (strncmp(method, device->values[0].string.text, methodlen) == 0 &&
+           (device->values[0].string.text[methodlen] == ':' ||
+            device->values[0].string.text[methodlen] == '\0'))
+         break;
+
+      if (device == NULL)
+      {
+       /*
+        * Could not find device in list!
+       */
+
+       LogMessage(L_ERROR, "add_printer: bad device-uri attribute \'%s\'!",
+                  attr->values[0].string.text);
+       send_ipp_error(con, IPP_NOT_POSSIBLE);
+       return;
+      }
+    }
+
     LogMessage(L_INFO, "Setting %s device-uri to \"%s\" (was \"%s\".)",
                printer->name, attr->values[0].string.text, printer->device_uri);
 
@@ -1136,7 +1157,8 @@ add_printer(client_t        *con, /* I - Client connection */
             sizeof(printer->state_message) - 1);
     printer->state_message[sizeof(printer->state_message) - 1] = '\0';
   }
-  if ((attr = ippFindAttribute(con->request, "job-sheets-default", IPP_TAG_ZERO)) != NULL)
+  if ((attr = ippFindAttribute(con->request, "job-sheets-default", IPP_TAG_ZERO)) != NULL &&
+      !Classification[0])
   {
     strncpy(printer->job_sheets[0], attr->values[0].string.text,
             sizeof(printer->job_sheets[0]) - 1);
@@ -1145,23 +1167,6 @@ add_printer(client_t        *con,        /* I - Client connection */
               sizeof(printer->job_sheets[1]) - 1);
     else
       strcpy(printer->job_sheets[1], "none");
-
-   /*
-    * Force classification if necessary...
-    */
-
-    if (Classification[0])
-    {
-      if (strcmp(printer->job_sheets[0], Classification) != 0 &&
-          strcmp(printer->job_sheets[1], Classification) != 0)
-      {
-       /*
-        * Force the leading banner to have the classification on it...
-       */
-
-        strcpy(printer->job_sheets[0], Classification);
-      }
-    }
   }
   if ((attr = ippFindAttribute(con->request, "requesting-user-name-allowed",
                                IPP_TAG_ZERO)) != NULL)
@@ -1169,7 +1174,9 @@ add_printer(client_t        *con, /* I - Client connection */
     FreePrinterUsers(printer);
 
     printer->deny_users = 0;
-    if (attr->value_tag == IPP_TAG_NAME)
+    if (attr->value_tag == IPP_TAG_NAME &&
+        (attr->num_values > 1 ||
+        strcmp(attr->values[0].string.text, "all") != 0))
       for (i = 0; i < attr->num_values; i ++)
        AddPrinterUser(printer, attr->values[i].string.text);
   }
@@ -1179,7 +1186,9 @@ add_printer(client_t        *con, /* I - Client connection */
     FreePrinterUsers(printer);
 
     printer->deny_users = 1;
-    if (attr->value_tag == IPP_TAG_NAME)
+    if (attr->value_tag == IPP_TAG_NAME &&
+        (attr->num_values > 1 ||
+        strcmp(attr->values[0].string.text, "none") != 0))
       for (i = 0; i < attr->num_values; i ++)
        AddPrinterUser(printer, attr->values[i].string.text);
   }
@@ -1219,17 +1228,36 @@ add_printer(client_t        *con,       /* I - Client connection */
     srcfile[sizeof(srcfile) - 1] = '\0';
   }
   else if ((attr = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME)) != NULL)
-    snprintf(srcfile, sizeof(srcfile), "%s/model/%s", DataDir,
-             attr->values[0].string.text);
+  {
+    if (strcmp(attr->values[0].string.text, "raw") == 0)
+      strcpy(srcfile, "raw");
+    else
+      snprintf(srcfile, sizeof(srcfile), "%s/model/%s", DataDir,
+               attr->values[0].string.text);
+  }
   else
     srcfile[0] = '\0';
 
   LogMessage(L_DEBUG, "add_printer: srcfile = \"%s\"", srcfile);
 
+  if (strcmp(srcfile, "raw") == 0)
+  {
+   /*
+    * Raw driver, remove any existing PPD or interface script files.
+    */
+
+    snprintf(dstfile, sizeof(dstfile), "%s/interfaces/%s", ServerRoot,
+             printer->name);
+    unlink(dstfile);
+
+    snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot,
+             printer->name);
+    unlink(dstfile);
+  }
 #ifdef HAVE_LIBZ
-  if (srcfile[0] && (fp = gzopen(srcfile, "rb")) != NULL)
+  else if (srcfile[0] && (fp = gzopen(srcfile, "rb")) != NULL)
 #else
-  if (srcfile[0] && (fp = fopen(srcfile, "rb")) != NULL)
+  else if (srcfile[0] && (fp = fopen(srcfile, "rb")) != NULL)
 #endif /* HAVE_LIBZ */
   {
    /*
@@ -1771,7 +1799,7 @@ check_quotas(client_t  *con,      /* I - Client connection */
   if (p->num_users)
   {
     for (i = 0; i < p->num_users; i ++)
-      if (strcmp(username, p->users[i]) == 0)
+      if (strcasecmp(username, p->users[i]) == 0)
        break;
 
     if ((i < p->num_users) == p->deny_users)
@@ -1818,7 +1846,8 @@ check_quotas(client_t  *con,      /* I - Client connection */
 
 static void
 copy_attribute(ipp_t           *to,    /* O - Destination request/response */
-               ipp_attribute_t *attr)  /* I - Attribute to copy */
+               ipp_attribute_t *attr,  /* I - Attribute to copy */
+               int             quickcopy)/* I - Do a quick copy? */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *toattr;        /* Destination attribute */
@@ -1827,7 +1856,7 @@ copy_attribute(ipp_t           *to,       /* O - Destination request/response */
   LogMessage(L_DEBUG2, "copy_attribute(%p, %s)\n", to,
              attr->name ? attr->name : "(null)");
 
-  switch (attr->value_tag)
+  switch (attr->value_tag & ~IPP_TAG_COPY)
   {
     case IPP_TAG_ZERO :
         ippAddSeparator(to);
@@ -1860,12 +1889,19 @@ copy_attribute(ipp_t           *to,     /* O - Destination request/response */
     case IPP_TAG_LANGUAGE :
     case IPP_TAG_MIMETYPE :
         toattr = ippAddStrings(to, attr->group_tag,
-                              (ipp_tag_t)(attr->value_tag | IPP_TAG_COPY),
-                              attr->name, attr->num_values, NULL,
-                              NULL);
+                              (ipp_tag_t)(attr->value_tag | quickcopy),
+                              attr->name, attr->num_values, NULL, NULL);
 
-        for (i = 0; i < attr->num_values; i ++)
-         toattr->values[i].string.text = attr->values[i].string.text;
+        if (quickcopy)
+       {
+          for (i = 0; i < attr->num_values; i ++)
+           toattr->values[i].string.text = attr->values[i].string.text;
+        }
+       else
+       {
+          for (i = 0; i < attr->num_values; i ++)
+           toattr->values[i].string.text = strdup(attr->values[i].string.text);
+       }
         break;
 
     case IPP_TAG_DATE :
@@ -1900,13 +1936,30 @@ copy_attribute(ipp_t           *to,     /* O - Destination request/response */
     case IPP_TAG_TEXTLANG :
     case IPP_TAG_NAMELANG :
         toattr = ippAddStrings(to, attr->group_tag,
-                              (ipp_tag_t)(attr->value_tag | IPP_TAG_COPY),
+                              (ipp_tag_t)(attr->value_tag | quickcopy),
                               attr->name, attr->num_values, NULL, NULL);
 
-        for (i = 0; i < attr->num_values; i ++)
+        if (quickcopy)
+       {
+          for (i = 0; i < attr->num_values; i ++)
+         {
+            toattr->values[i].string.charset = attr->values[i].string.charset;
+           toattr->values[i].string.text    = attr->values[i].string.text;
+          }
+        }
+       else
        {
-          toattr->values[i].string.charset = attr->values[i].string.charset;
-         toattr->values[i].string.text    = attr->values[i].string.text;
+          for (i = 0; i < attr->num_values; i ++)
+         {
+           if (!i)
+              toattr->values[i].string.charset =
+                 strdup(attr->values[i].string.charset);
+           else
+              toattr->values[i].string.charset =
+                 toattr->values[0].string.charset;
+
+           toattr->values[i].string.text = strdup(attr->values[i].string.text);
+          }
         }
         break;
 
@@ -1975,7 +2028,7 @@ copy_attrs(ipp_t           *to,           /* I - Destination request */
         continue;
     }
 
-    copy_attribute(to, fromattr);
+    copy_attribute(to, fromattr, IPP_TAG_COPY);
   }
 }
 
@@ -2198,7 +2251,8 @@ create_job(client_t        *con,  /* I - Client connection */
   if (attr == NULL)
     attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
                         "job-hold-until", NULL, "no-hold");
-  if (attr != NULL && strcmp(attr->values[0].string.text, "no-hold") != 0)
+  if (attr != NULL && strcmp(attr->values[0].string.text, "no-hold") != 0 &&
+      !(printer->type & CUPS_PRINTER_REMOTE))
   {
    /*
     * Hold job until specified time...
@@ -2219,6 +2273,9 @@ create_job(client_t        *con,  /* I - Client connection */
 
     if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) == NULL)
     {
+      LogMessage(L_DEBUG, "Adding default job-sheets values \"%s,%s\"...",
+                 printer->job_sheets[0], printer->job_sheets[1]);
+
       attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
                            2, NULL, NULL);
       attr->values[0].string.text = strdup(printer->job_sheets[0]);
@@ -2233,9 +2290,35 @@ create_job(client_t        *con, /* I - Client connection */
 
     if (Classification[0])
     {
-      if (strcmp(attr->values[0].string.text, Classification) != 0 &&
-          (attr->num_values == 1 ||
-          strcmp(attr->values[1].string.text, Classification) != 0))
+      if (ClassifyOverride)
+      {
+        if (strcmp(attr->values[0].string.text, "none") == 0 &&
+           (attr->num_values == 1 ||
+            strcmp(attr->values[1].string.text, "none") == 0))
+        {
+        /*
+          * Force the leading banner to have the classification on it...
+         */
+
+          free(attr->values[0].string.text);
+         attr->values[0].string.text = strdup(Classification);
+       }
+       else if (attr->num_values == 2 &&
+                strcmp(attr->values[0].string.text, attr->values[1].string.text) != 0 &&
+                strcmp(attr->values[0].string.text, "none") != 0 &&
+                strcmp(attr->values[1].string.text, "none") != 0)
+        {
+        /*
+         * Can't put two different security markings on the same document!
+         */
+
+          free(attr->values[1].string.text);
+         attr->values[1].string.text = strdup(attr->values[0].string.text);
+       }
+      }
+      else if (strcmp(attr->values[0].string.text, Classification) != 0 &&
+               (attr->num_values == 1 ||
+              strcmp(attr->values[1].string.text, Classification) != 0))
       {
        /*
         * Force the leading banner to have the classification on it...
@@ -2254,6 +2337,8 @@ create_job(client_t        *con,  /* I - Client connection */
 
     UpdateQuota(printer, job->username, 0, kbytes);
   }
+  else if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
+    job->sheets = attr;
 
  /*
   * Save and log the job...
@@ -2345,7 +2430,49 @@ copy_banner(client_t   *con,     /* I - Client connection */
   fchmod(fileno(out), 0640);
   fchown(fileno(out), User, Group);
 
-  if ((in = fopen(banner->filename, "r")) == NULL)
+  if (con->language)
+  {
+   /*
+    * Try the localized banner file under the subdirectory...
+    */
+
+    snprintf(filename, sizeof(filename), "%s/banners/%s/%s", DataDir,
+             con->language->language, name);
+
+    if (access(filename, 0) && con->language->language[2])
+    {
+     /*
+      * Wasn't able to find "ll_CC" locale file; try the non-national
+      * localization banner directory.
+      */
+
+      attrname[0] = con->language->language[0];
+      attrname[1] = con->language->language[1];
+      attrname[2] = '\0';
+
+      snprintf(filename, sizeof(filename), "%s/banners/%s/%s", DataDir,
+               attrname, name);
+    }
+
+    if (access(filename, 0))
+    {
+     /*
+      * Use the non-localized banner file.
+      */
+
+      snprintf(filename, sizeof(filename), "%s/banners/%s", DataDir, name);
+    }
+  }
+  else
+  {
+   /*
+    * Use the non-localized banner file.
+    */
+
+    snprintf(filename, sizeof(filename), "%s/banners/%s", DataDir, name);
+  }
+
+  if ((in = fopen(filename, "r")) == NULL)
   {
     fclose(out);
     unlink(filename);
@@ -2367,35 +2494,60 @@ copy_banner(client_t   *con,    /* I - Client connection */
       */
 
       for (s = attrname; (ch = getc(in)) != EOF;)
-        if (ch == '}' || isspace(ch))
+        if (!isalpha(ch) && ch != '-' && ch != '?')
           break;
        else if (s < (attrname + sizeof(attrname) - 1))
           *s++ = ch;
+       else
+         break;
+
+      *s = '\0';
 
-      if (isspace(ch) && s == attrname)
+      if (ch != '}')
       {
        /*
-        * Ignore { followed by whitespace...
+        * Ignore { followed by stuff that is not an attribute name...
        */
 
         putc('{', out);
+       fputs(attrname, out);
        putc(ch, out);
        continue;
       }
 
-      *s = '\0';
-
      /*
       * See if it is defined...
       */
 
-      if (strcmp(attrname, "printer-name") == 0)
+      if (attrname[0] == '?')
+        s = attrname + 1;
+      else
+        s = attrname;
+
+      if (strcmp(s, "printer-name") == 0)
       {
         fputs(job->dest, out);
        continue;
       }
-      else if ((attr = ippFindAttribute(job->attrs, attrname, IPP_TAG_ZERO)) == NULL)
-        continue; /* Nope */
+      else if ((attr = ippFindAttribute(job->attrs, s, IPP_TAG_ZERO)) == NULL)
+      {
+       /*
+        * See if we have a leading question mark...
+       */
+
+       if (attrname[0] != '?')
+       {
+        /*
+          * Nope, write to file as-is; probably a PostScript procedure...
+         */
+
+         putc('{', out);
+         fputs(attrname, out);
+         putc('}', out);
+        }
+
+        continue;
+      }
 
      /*
       * Output value(s)...
@@ -2623,11 +2775,15 @@ delete_printer(client_t        *con,    /* I - Client connection */
     printer = FindPrinter(dest);
 
  /*
-  * Remove any old PPD or script files...
+  * Remove old jobs...
   */
 
   CancelJobs(dest);
 
+ /*
+  * Remove any old PPD or script files...
+  */
+
   snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot, dest);
   unlink(filename);
 
@@ -3130,6 +3286,10 @@ get_printers(client_t *con,              /* I - Client connection */
   int                  printer_type,   /* printer-type attribute */
                        printer_mask;   /* printer-type-mask attribute */
   char                 *location;      /* Location string */
+  char                 name[IPP_MAX_NAME],
+                                       /* Printer name */
+                       *nameptr;       /* Pointer into name */
+  printer_t            *iclass;        /* Implicit class */
 
 
   LogMessage(L_DEBUG2, "get_printers(%d, %x)\n", con->http.fd, type);
@@ -3178,6 +3338,45 @@ get_printers(client_t *con,              /* I - Client connection */
         (printer->type & printer_mask) == printer_type &&
        (location == NULL || strcasecmp(printer->location, location) == 0))
     {
+     /*
+      * If HideImplicitMembers is enabled, see if this printer or class
+      * is a member of an implicit class...
+      */
+
+      if (ImplicitClasses && HideImplicitMembers &&
+          (printer->type & CUPS_PRINTER_REMOTE))
+      {
+       /*
+        * Make a copy of the printer name...
+       *
+       * Note: name and printer->name are both IPP_MAX_NAME characters
+       *       in size, so strcpy() is safe...
+       */
+
+        strcpy(name, printer->name);
+
+       if ((nameptr = strchr(name, '@')) != NULL)
+       {
+        /*
+         * Strip trailing @server...
+         */
+
+         *nameptr = '\0';
+
+         /*
+         * Find the core printer, if any...
+         */
+
+          if ((iclass = FindPrinter(name)) != NULL &&
+             (iclass->type & CUPS_PRINTER_IMPLICIT))
+           continue;
+       }
+      }
+
+     /*
+      * Add the group separator as needed...
+      */
+
       if (count > 0)
         ippAddSeparator(con->response);
 
@@ -3372,7 +3571,7 @@ hold_job(client_t        *con,    /* I - Client connection */
 
 
 /*
- * 'move_job()' - Set job attributes.
+ * 'move_job()' - Move a job to a new destination.
  */
 
 static void
@@ -3869,7 +4068,8 @@ print_job(client_t        *con,           /* I - Client connection */
     attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
                         "job-hold-until", NULL, "no-hold");
 
-  if (attr != NULL && strcmp(attr->values[0].string.text, "no-hold") != 0)
+  if (attr != NULL && strcmp(attr->values[0].string.text, "no-hold") != 0 &&
+      !(printer->type & CUPS_PRINTER_REMOTE))
   {
    /*
     * Hold job until specified time...
@@ -3887,6 +4087,9 @@ print_job(client_t        *con,           /* I - Client connection */
 
     if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) == NULL)
     {
+      LogMessage(L_DEBUG, "Adding default job-sheets values \"%s,%s\"...",
+                 printer->job_sheets[0], printer->job_sheets[1]);
+
       attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
                            2, NULL, NULL);
       attr->values[0].string.text = strdup(printer->job_sheets[0]);
@@ -3901,9 +4104,35 @@ print_job(client_t        *con,          /* I - Client connection */
 
     if (Classification[0])
     {
-      if (strcmp(attr->values[0].string.text, Classification) != 0 &&
-          (attr->num_values == 1 ||
-          strcmp(attr->values[1].string.text, Classification) != 0))
+      if (ClassifyOverride)
+      {
+        if (strcmp(attr->values[0].string.text, "none") == 0 &&
+           (attr->num_values == 1 ||
+            strcmp(attr->values[1].string.text, "none") == 0))
+        {
+        /*
+          * Force the leading banner to have the classification on it...
+         */
+
+          free(attr->values[0].string.text);
+         attr->values[0].string.text = strdup(Classification);
+       }
+       else if (attr->num_values == 2 &&
+                strcmp(attr->values[0].string.text, attr->values[1].string.text) != 0 &&
+                strcmp(attr->values[0].string.text, "none") != 0 &&
+                strcmp(attr->values[1].string.text, "none") != 0)
+        {
+        /*
+         * Can't put two different security markings on the same document!
+         */
+
+          free(attr->values[1].string.text);
+         attr->values[1].string.text = strdup(attr->values[0].string.text);
+       }
+      }
+      else if (strcmp(attr->values[0].string.text, Classification) != 0 &&
+               (attr->num_values == 1 ||
+              strcmp(attr->values[1].string.text, Classification) != 0))
       {
        /*
         * Force the leading banner to have the classification on it...
@@ -3922,6 +4151,8 @@ print_job(client_t        *con,           /* I - Client connection */
 
     UpdateQuota(printer, job->username, 0, kbytes);
   }
+  else if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
+    job->sheets = attr;
    
  /*
   * Add the job file...
@@ -4981,7 +5212,7 @@ set_job_attrs(client_t        *con,       /* I - Client connection */
       * Then copy the attribute...
       */
 
-      copy_attribute(job->attrs, attr);
+      copy_attribute(job->attrs, attr, 0);
 
      /*
       * See if the job-name or job-hold-until is being changed.
@@ -5027,7 +5258,7 @@ set_job_attrs(client_t        *con,       /* I - Client connection */
       * Add new option by copying it...
       */
 
-      copy_attribute(job->attrs, attr);
+      copy_attribute(job->attrs, attr, 0);
     }
   }
 
@@ -5356,7 +5587,7 @@ validate_user(client_t   *con,            /* I - Client connection */
               char       *username,    /* O - Authenticated username */
              int        userlen)       /* I - Length of username */
 {
-  int                  i;              /* Looping var */
+  int                  i, j;           /* Looping vars */
   ipp_attribute_t      *attr;          /* requesting-user-name attribute */
   struct passwd                *user;          /* User info */
   struct group         *group;         /* System group info */
@@ -5389,7 +5620,7 @@ validate_user(client_t   *con,            /* I - Client connection */
   * Check the username against the owner...
   */
 
-  if (strcmp(username, owner) != 0 && strcmp(username, "root") != 0)
+  if (strcasecmp(username, owner) != 0 && strcasecmp(username, "root") != 0)
   {
    /*
     * Not the owner or root; check to see if the user is a member of the
@@ -5399,20 +5630,26 @@ validate_user(client_t   *con,          /* I - Client connection */
     user = getpwnam(username);
     endpwent();
 
-    group = getgrnam(SystemGroup);
-    endgrent();
-
-    if (group != NULL)
+    for (i = 0, j = 0, group = NULL; i < NumSystemGroups; i ++)
     {
-      for (i = 0; group->gr_mem[i]; i ++)
-        if (strcmp(username, group->gr_mem[i]) == 0)
+      group = getgrnam(SystemGroups[i]);
+      endgrent();
+
+      if (group != NULL)
+      {
+       for (j = 0; group->gr_mem[j]; j ++)
+          if (strcasecmp(username, group->gr_mem[j]) == 0)
+           break;
+
+        if (group->gr_mem[j])
          break;
+      }
+      else
+       j = 0;
     }
-    else
-      i = 0;
 
     if (user == NULL || group == NULL ||
-        (group->gr_mem[i] == NULL && group->gr_gid != user->pw_gid))
+        (group->gr_mem[j] == NULL && group->gr_gid != user->pw_gid))
     {
      /*
       * Username not found, group not found, or user is not part of the
@@ -5428,5 +5665,5 @@ validate_user(client_t   *con,            /* I - Client connection */
 
 
 /*
- * End of "$Id: ipp.c,v 1.127.2.2 2001/05/13 18:38:35 mike Exp $".
+ * End of "$Id: ipp.c,v 1.127.2.3 2001/12/26 16:52:53 mike Exp $".
  */
index e485662ff228b3b4269ae68c7942f6a1c9fba86a..33602ccf066cd7e394d803a1c60db771f9e78597 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: job.c,v 1.124.2.2 2001/05/13 18:38:36 mike Exp $"
+ * "$Id: job.c,v 1.124.2.3 2001/12/26 16:52:54 mike Exp $"
  *
  *   Job management routines for the Common UNIX Printing System (CUPS).
  *
@@ -282,8 +282,10 @@ CheckJobs(void)
 
         if (pclass->type & CUPS_PRINTER_REMOTE)
          printer = pclass;
-       else
+       else if (pclass->state != IPP_PRINTER_STOPPED)
          printer = FindAvailablePrinter(current->dest);
+       else
+         printer = NULL;
       }
       else
         printer = FindPrinter(current->dest);
@@ -294,8 +296,12 @@ CheckJobs(void)
         * Handle implicit classes...
        */
 
-        pclass  = printer;
-        printer = FindAvailablePrinter(current->dest);
+        pclass = printer;
+
+       if (pclass->state != IPP_PRINTER_STOPPED)
+         printer = FindAvailablePrinter(current->dest);
+       else
+         printer = NULL;
       }
 
       if (printer == NULL && pclass == NULL)
@@ -731,8 +737,11 @@ MoveJob(int        id,             /* I - Job ID */
   for (current = Jobs; current != NULL; current = current->next)
     if (current->id == id)
     {
-      if (current->state->values[0].integer == IPP_JOB_PENDING)
-        strncpy(current->dest, dest, sizeof(current->dest) - 1);
+      if (current->state->values[0].integer >= IPP_JOB_PROCESSING)
+        break;
+
+      strncpy(current->dest, dest, sizeof(current->dest) - 1);
+      current->dtype = p->type & CUPS_PRINTER_CLASS;
 
       if ((attr = ippFindAttribute(current->attrs, "job-printer-uri", IPP_TAG_URI)) != NULL)
       {
@@ -1072,7 +1081,7 @@ StartJob(int       id,            /* I - Job ID */
                path[1024],     /* PATH environment variable */
                language[255],  /* LANG environment variable */
                charset[255],   /* CHARSET environment variable */
-               classification[1024],   /* CLASSIFICATION environmeent variable */
+               classification[1024],   /* CLASSIFICATION environment variable */
                content_type[255],/* CONTENT_TYPE environment variable */
                device_uri[1024],/* DEVICE_URI environment variable */
                ppd[1024],      /* PPD environment variable */
@@ -1141,8 +1150,35 @@ StartJob(int       id,           /* I - Job ID */
       return;
     }
 
-    for (i = 0; i < num_filters; i ++)
-      current->cost += filters[i].cost;
+   /*
+    * Remove NULL ("-") filters...
+    */
+
+    for (i = 0; i < num_filters;)
+      if (strcmp(filters[i].filter, "-") == 0)
+      {
+        num_filters --;
+       if (i < num_filters)
+         memcpy(filters + i, filters + i + 1,
+                (num_filters - i) * sizeof(mime_filter_t));
+      }
+      else
+        i ++;
+
+    if (num_filters == 0)
+    {
+      free(filters);
+      filters = NULL;
+    }
+    else
+    {
+     /*
+      * Compute filter cost...
+      */
+
+      for (i = 0; i < num_filters; i ++)
+       current->cost += filters[i].cost;
+    }
   }
 
  /*
@@ -1188,7 +1224,12 @@ StartJob(int       id,           /* I - Job ID */
   */
 
   if (current->job_sheets == NULL)
+  {
     LogMessage(L_DEBUG, "No job-sheets attribute.");
+    if ((current->job_sheets =
+         ippFindAttribute(current->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
+      LogMessage(L_DEBUG, "... but someone added one without setting job_sheets!");
+  }
   else if (current->job_sheets->num_values == 1)
     LogMessage(L_DEBUG, "job-sheets=%s",
                current->job_sheets->values[0].string.text);
@@ -1421,8 +1462,19 @@ StartJob(int       id,           /* I - Job ID */
   snprintf(datadir, sizeof(datadir), "CUPS_DATADIR=%s", DataDir);
   snprintf(fontpath, sizeof(fontpath), "CUPS_FONTPATH=%s", FontPath);
   if (Classification[0] && !banner_page)
-    snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
-             Classification);
+  {
+    if ((attr = ippFindAttribute(current->attrs, "job-sheets",
+                                 IPP_TAG_NAME)) == NULL)
+      snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+               Classification);
+    else if (attr->num_values > 1 &&
+             strcmp(attr->values[1].string.text, "none") != 0)
+      snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+               attr->values[1].string.text);
+    else
+      snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+               attr->values[0].string.text);
+  }
   else
     classification[0] = '\0';
   if (getenv("LD_LIBRARY_PATH") != NULL)
@@ -1929,6 +1981,895 @@ UpdateJob(job_t *job)           /* I - Job to check */
 }
 
 
+/*
+ * 'ipp_read_file()' - Read an IPP request from a file.
+ */
+
+static ipp_state_t                     /* O - State */
+ipp_read_file(const char *filename,    /* I - File to read from */
+              ipp_t      *ipp)         /* I - Request to read into */
+{
+  int                  fd;             /* File descriptor for file */
+  int                  n;              /* Length of data */
+  unsigned char                buffer[8192],   /* Data buffer */
+                       *bufptr;        /* Pointer into buffer */
+  ipp_attribute_t      *attr;          /* Current attribute */
+  ipp_tag_t            tag;            /* Current tag */
+
+
+ /*
+  * Open the file if possible...
+  */
+
+  if (filename == NULL || ipp == NULL)
+    return (IPP_ERROR);
+
+  if ((fd = open(filename, O_RDONLY)) == -1)
+    return (IPP_ERROR);
+
+ /*
+  * Read the IPP request...
+  */
+
+  ipp->state = IPP_IDLE;
+
+  switch (ipp->state)
+  {
+    default :
+       break; /* anti-compiler-warning-code */
+
+    case IPP_IDLE :
+        ipp->state ++; /* Avoid common problem... */
+
+    case IPP_HEADER :
+       /*
+        * Get the request header...
+       */
+
+        if ((n = read(fd, buffer, 8)) < 8)
+       {
+         DEBUG_printf(("ipp_read_file: Unable to read header (%d bytes read)!\n", n));
+         close(fd);
+         return (n == 0 ? IPP_IDLE : IPP_ERROR);
+       }
+
+       /*
+        * Verify the major version number...
+       */
+
+       if (buffer[0] != 1)
+       {
+         DEBUG_printf(("ipp_read_file: version number (%d.%d) is bad.\n", buffer[0],
+                       buffer[1]));
+         close(fd);
+         return (IPP_ERROR);
+       }
+
+       /*
+        * Then copy the request header over...
+       */
+
+        ipp->request.any.version[0]  = buffer[0];
+        ipp->request.any.version[1]  = buffer[1];
+        ipp->request.any.op_status   = (buffer[2] << 8) | buffer[3];
+        ipp->request.any.request_id  = (((((buffer[4] << 8) | buffer[5]) << 8) |
+                                      buffer[6]) << 8) | buffer[7];
+
+        ipp->state   = IPP_ATTRIBUTE;
+       ipp->current = NULL;
+       ipp->curtag  = IPP_TAG_ZERO;
+
+    case IPP_ATTRIBUTE :
+        while (read(fd, buffer, 1) > 0)
+       {
+        /*
+         * Read this attribute...
+         */
+
+          tag = (ipp_tag_t)buffer[0];
+
+         if (tag == IPP_TAG_END)
+         {
+          /*
+           * No more attributes left...
+           */
+
+            DEBUG_puts("ipp_read_file: IPP_TAG_END!");
+
+           ipp->state = IPP_DATA;
+           break;
+         }
+          else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
+         {
+          /*
+           * Group tag...  Set the current group and continue...
+           */
+
+            if (ipp->curtag == tag)
+             ippAddSeparator(ipp);
+
+           ipp->curtag  = tag;
+           ipp->current = NULL;
+           DEBUG_printf(("ipp_read_file: group tag = %x\n", tag));
+           continue;
+         }
+
+          DEBUG_printf(("ipp_read_file: value tag = %x\n", tag));
+
+         /*
+         * Get the name...
+         */
+
+          if (read(fd, buffer, 2) < 2)
+         {
+           DEBUG_puts("ipp_read_file: unable to read name length!");
+           close(fd);
+           return (IPP_ERROR);
+         }
+
+          n = (buffer[0] << 8) | buffer[1];
+
+          DEBUG_printf(("ipp_read_file: name length = %d\n", n));
+
+          if (n == 0)
+         {
+          /*
+           * More values for current attribute...
+           */
+
+            if (ipp->current == NULL)
+           {
+             close(fd);
+              return (IPP_ERROR);
+           }
+
+            attr = ipp->current;
+
+           /*
+           * Finally, reallocate the attribute array as needed...
+           */
+
+           if ((attr->num_values % IPP_MAX_VALUES) == 0)
+           {
+             ipp_attribute_t   *temp,  /* Pointer to new buffer */
+                               *ptr;   /* Pointer in attribute list */
+
+
+             /*
+             * Reallocate memory...
+             */
+
+              if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
+                                       (attr->num_values + IPP_MAX_VALUES - 1) *
+                                       sizeof(ipp_value_t))) == NULL)
+             {
+               close(fd);
+               return (IPP_ERROR);
+             }
+
+             /*
+             * Reset pointers in the list...
+             */
+
+             for (ptr = ipp->attrs; ptr && ptr->next != attr; ptr = ptr->next);
+
+              if (ptr)
+               ptr->next = temp;
+             else
+               ipp->attrs = temp;
+
+              attr = ipp->current = ipp->last = temp;
+           }
+         }
+         else
+         {
+          /*
+           * New attribute; read the name and add it...
+           */
+
+           if (read(fd, buffer, n) < n)
+           {
+             DEBUG_puts("ipp_read_file: unable to read name!");
+             close(fd);
+             return (IPP_ERROR);
+           }
+
+           buffer[n] = '\0';
+           DEBUG_printf(("ipp_read_file: name = \'%s\'\n", buffer));
+
+           attr = ipp->current = _ipp_add_attr(ipp, IPP_MAX_VALUES);
+
+           attr->group_tag  = ipp->curtag;
+           attr->value_tag  = tag;
+           attr->name       = strdup((char *)buffer);
+           attr->num_values = 0;
+         }
+
+         if (read(fd, buffer, 2) < 2)
+         {
+           DEBUG_puts("ipp_read_file: unable to read value length!");
+           close(fd);
+           return (IPP_ERROR);
+         }
+
+         n = (buffer[0] << 8) | buffer[1];
+          DEBUG_printf(("ipp_read_file: value length = %d\n", n));
+
+         switch (tag)
+         {
+           case IPP_TAG_INTEGER :
+           case IPP_TAG_ENUM :
+               if (read(fd, buffer, 4) < 4)
+               {
+                 close(fd);
+                  return (IPP_ERROR);
+               }
+
+               n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+                   buffer[3];
+
+                attr->values[attr->num_values].integer = n;
+               break;
+           case IPP_TAG_BOOLEAN :
+               if (read(fd, buffer, 1) < 1)
+               {
+                 close(fd);
+                  return (IPP_ERROR);
+               }
+
+                attr->values[attr->num_values].boolean = buffer[0];
+               break;
+           case IPP_TAG_TEXT :
+           case IPP_TAG_NAME :
+           case IPP_TAG_KEYWORD :
+           case IPP_TAG_STRING :
+           case IPP_TAG_URI :
+           case IPP_TAG_URISCHEME :
+           case IPP_TAG_CHARSET :
+           case IPP_TAG_LANGUAGE :
+           case IPP_TAG_MIMETYPE :
+               if (read(fd, buffer, n) < n)
+               {
+                 close(fd);
+                  return (IPP_ERROR);
+               }
+
+                buffer[n] = '\0';
+               DEBUG_printf(("ipp_read_file: value = \'%s\'\n", buffer));
+
+                attr->values[attr->num_values].string.text = strdup((char *)buffer);
+               break;
+           case IPP_TAG_DATE :
+               if (read(fd, buffer, 11) < 11)
+               {
+                 close(fd);
+                  return (IPP_ERROR);
+               }
+
+                memcpy(attr->values[attr->num_values].date, buffer, 11);
+               break;
+           case IPP_TAG_RESOLUTION :
+               if (read(fd, buffer, 9) < 9)
+               {
+                 close(fd);
+                  return (IPP_ERROR);
+               }
+
+                attr->values[attr->num_values].resolution.xres =
+                   (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+                   buffer[3];
+                attr->values[attr->num_values].resolution.yres =
+                   (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
+                   buffer[7];
+                attr->values[attr->num_values].resolution.units =
+                   (ipp_res_t)buffer[8];
+               break;
+           case IPP_TAG_RANGE :
+               if (read(fd, buffer, 8) < 8)
+               {
+                 close(fd);
+                  return (IPP_ERROR);
+               }
+
+                attr->values[attr->num_values].range.lower =
+                   (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+                   buffer[3];
+                attr->values[attr->num_values].range.upper =
+                   (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
+                   buffer[7];
+               break;
+           case IPP_TAG_TEXTLANG :
+           case IPP_TAG_NAMELANG :
+               if (read(fd, buffer, n) < n)
+                 return (IPP_ERROR);
+
+                bufptr = buffer;
+
+              /*
+               * text-with-language and name-with-language are composite
+               * values:
+               *
+               *    charset-length
+               *    charset
+               *    text-length
+               *    text
+               */
+
+               n = (bufptr[0] << 8) | bufptr[1];
+
+                attr->values[attr->num_values].string.charset = calloc(n + 1, 1);
+
+               memcpy(attr->values[attr->num_values].string.charset,
+                      bufptr + 2, n);
+
+                bufptr += 2 + n;
+               n = (bufptr[0] << 8) | bufptr[1];
+
+                attr->values[attr->num_values].string.text = calloc(n + 1, 1);
+
+               memcpy(attr->values[attr->num_values].string.text,
+                      bufptr + 2, n);
+
+               break;
+
+            default : /* Other unsupported values */
+                attr->values[attr->num_values].unknown.length = n;
+               if (n > 0)
+               {
+                 attr->values[attr->num_values].unknown.data = malloc(n);
+                 if (read(fd, attr->values[attr->num_values].unknown.data, n) < n)
+                   return (IPP_ERROR);
+               }
+               else
+                 attr->values[attr->num_values].unknown.data = NULL;
+               break;
+         }
+
+          attr->num_values ++;
+       }
+        break;
+
+    case IPP_DATA :
+        break;
+  }
+
+ /*
+  * Close the file and return...
+  */
+
+  close(fd);
+
+  return (ipp->state);
+}
+
+
+/*
+ * 'ipp_write_file()' - Write an IPP request to a file.
+ */
+
+static ipp_state_t                     /* O - State */
+ipp_write_file(const char *filename,   /* I - File to write to */
+               ipp_t      *ipp)                /* I - Request to write */
+{
+  int                  fd;             /* File descriptor */
+  int                  i;              /* Looping var */
+  int                  n;              /* Length of data */
+  unsigned char                buffer[8192],   /* Data buffer */
+                       *bufptr;        /* Pointer into buffer */
+  ipp_attribute_t      *attr;          /* Current attribute */
+
+
+ /*
+  * Open the file if possible...
+  */
+
+  if (filename == NULL || ipp == NULL)
+    return (IPP_ERROR);
+
+  if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) == -1)
+    return (IPP_ERROR);
+
+  fchmod(fd, 0600);
+  fchown(fd, User, Group);
+
+ /*
+  * Write the IPP request...
+  */
+
+  ipp->state = IPP_IDLE;
+
+  switch (ipp->state)
+  {
+    default :
+       break; /* anti-compiler-warning-code */
+
+    case IPP_IDLE :
+        ipp->state ++; /* Avoid common problem... */
+
+    case IPP_HEADER :
+       /*
+        * Send the request header...
+       */
+
+        bufptr = buffer;
+
+       *bufptr++ = ipp->request.any.version[0];
+       *bufptr++ = ipp->request.any.version[1];
+       *bufptr++ = ipp->request.any.op_status >> 8;
+       *bufptr++ = ipp->request.any.op_status;
+       *bufptr++ = ipp->request.any.request_id >> 24;
+       *bufptr++ = ipp->request.any.request_id >> 16;
+       *bufptr++ = ipp->request.any.request_id >> 8;
+       *bufptr++ = ipp->request.any.request_id;
+
+        if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+       {
+         DEBUG_puts("ipp_write_file: Could not write IPP header...");
+         close(fd);
+         return (IPP_ERROR);
+       }
+
+        ipp->state   = IPP_ATTRIBUTE;
+       ipp->current = ipp->attrs;
+       ipp->curtag  = IPP_TAG_ZERO;
+
+    case IPP_ATTRIBUTE :
+        while (ipp->current != NULL)
+       {
+        /*
+         * Write this attribute...
+         */
+
+         bufptr = buffer;
+         attr   = ipp->current;
+
+         ipp->current = ipp->current->next;
+
+          if (ipp->curtag != attr->group_tag)
+         {
+          /*
+           * Send a group operation tag...
+           */
+
+           ipp->curtag = attr->group_tag;
+
+            if (attr->group_tag == IPP_TAG_ZERO)
+             continue;
+
+            DEBUG_printf(("ipp_write_file: wrote group tag = %x\n", attr->group_tag));
+           *bufptr++ = attr->group_tag;
+         }
+
+          if ((n = strlen(attr->name)) > (sizeof(buffer) - 3))
+           return (IPP_ERROR);
+
+          DEBUG_printf(("ipp_write_file: writing value tag = %x\n", attr->value_tag));
+          DEBUG_printf(("ipp_write_file: writing name = %d, \'%s\'\n", n, attr->name));
+
+          *bufptr++ = attr->value_tag;
+         *bufptr++ = n >> 8;
+         *bufptr++ = n;
+         memcpy(bufptr, attr->name, n);
+         bufptr += n;
+
+         switch (attr->value_tag)
+         {
+           case IPP_TAG_INTEGER :
+           case IPP_TAG_ENUM :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                  if ((sizeof(buffer) - (bufptr - buffer)) < 9)
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                 *bufptr++ = 0;
+                 *bufptr++ = 4;
+                 *bufptr++ = attr->values[i].integer >> 24;
+                 *bufptr++ = attr->values[i].integer >> 16;
+                 *bufptr++ = attr->values[i].integer >> 8;
+                 *bufptr++ = attr->values[i].integer;
+               }
+               break;
+
+           case IPP_TAG_BOOLEAN :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                  if ((sizeof(buffer) - (bufptr - buffer)) < 6)
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                 *bufptr++ = 0;
+                 *bufptr++ = 1;
+                 *bufptr++ = attr->values[i].boolean;
+               }
+               break;
+
+           case IPP_TAG_TEXT :
+           case IPP_TAG_NAME :
+           case IPP_TAG_KEYWORD :
+           case IPP_TAG_STRING :
+           case IPP_TAG_URI :
+           case IPP_TAG_URISCHEME :
+           case IPP_TAG_CHARSET :
+           case IPP_TAG_LANGUAGE :
+           case IPP_TAG_MIMETYPE :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                   DEBUG_printf(("ipp_write_file: writing value tag = %x\n",
+                                 attr->value_tag));
+                   DEBUG_printf(("ipp_write_file: writing name = 0, \'\'\n"));
+
+                    if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+                   {
+                      if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                     {
+                       DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                       return (IPP_ERROR);
+                     }
+
+                     bufptr = buffer;
+                   }
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                  n = strlen(attr->values[i].string.text);
+
+                  if (n > sizeof(buffer))
+                   return (IPP_ERROR);
+
+                  DEBUG_printf(("ipp_write_file: writing string = %d, \'%s\'\n", n,
+                               attr->values[i].string.text));
+
+                  if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ipp_write_file: Could not write IPP attribute...");
+                     close(fd);
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 *bufptr++ = n >> 8;
+                 *bufptr++ = n;
+                 memcpy(bufptr, attr->values[i].string.text, n);
+                 bufptr += n;
+               }
+               break;
+
+           case IPP_TAG_DATE :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                  if ((sizeof(buffer) - (bufptr - buffer)) < 16)
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                 *bufptr++ = 0;
+                 *bufptr++ = 11;
+                 memcpy(bufptr, attr->values[i].date, 11);
+                 bufptr += 11;
+               }
+               break;
+
+           case IPP_TAG_RESOLUTION :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                  if ((sizeof(buffer) - (bufptr - buffer)) < 14)
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                 *bufptr++ = 0;
+                 *bufptr++ = 9;
+                 *bufptr++ = attr->values[i].resolution.xres >> 24;
+                 *bufptr++ = attr->values[i].resolution.xres >> 16;
+                 *bufptr++ = attr->values[i].resolution.xres >> 8;
+                 *bufptr++ = attr->values[i].resolution.xres;
+                 *bufptr++ = attr->values[i].resolution.yres >> 24;
+                 *bufptr++ = attr->values[i].resolution.yres >> 16;
+                 *bufptr++ = attr->values[i].resolution.yres >> 8;
+                 *bufptr++ = attr->values[i].resolution.yres;
+                 *bufptr++ = attr->values[i].resolution.units;
+               }
+               break;
+
+           case IPP_TAG_RANGE :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                  if ((sizeof(buffer) - (bufptr - buffer)) < 13)
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                 *bufptr++ = 0;
+                 *bufptr++ = 8;
+                 *bufptr++ = attr->values[i].range.lower >> 24;
+                 *bufptr++ = attr->values[i].range.lower >> 16;
+                 *bufptr++ = attr->values[i].range.lower >> 8;
+                 *bufptr++ = attr->values[i].range.lower;
+                 *bufptr++ = attr->values[i].range.upper >> 24;
+                 *bufptr++ = attr->values[i].range.upper >> 16;
+                 *bufptr++ = attr->values[i].range.upper >> 8;
+                 *bufptr++ = attr->values[i].range.upper;
+               }
+               break;
+
+           case IPP_TAG_TEXTLANG :
+           case IPP_TAG_NAMELANG :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                    if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+                   {
+                      if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                     {
+                       DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                       return (IPP_ERROR);
+                     }
+
+                     bufptr = buffer;
+                   }
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                  n = strlen(attr->values[i].string.charset) +
+                     strlen(attr->values[i].string.text) +
+                     4;
+
+                  if (n > sizeof(buffer))
+                   return (IPP_ERROR);
+
+                  if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ipp_write_file: Could not write IPP attribute...");
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 /* Length of entire value */
+                 *bufptr++ = n >> 8;
+                 *bufptr++ = n;
+
+                 /* Length of charset */
+                  n = strlen(attr->values[i].string.charset);
+                 *bufptr++ = n >> 8;
+                 *bufptr++ = n;
+
+                 /* Charset */
+                 memcpy(bufptr, attr->values[i].string.charset, n);
+                 bufptr += n;
+
+                 /* Length of text */
+                  n = strlen(attr->values[i].string.text);
+                 *bufptr++ = n >> 8;
+                 *bufptr++ = n;
+
+                 /* Text */
+                 memcpy(bufptr, attr->values[i].string.text, n);
+                 bufptr += n;
+               }
+               break;
+
+            default :
+               for (i = 0; i < attr->num_values; i ++)
+               {
+                 if (i)
+                 {
+                  /*
+                   * Arrays and sets are done by sending additional
+                   * values with a zero-length name...
+                   */
+
+                    if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+                   {
+                      if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                     {
+                       DEBUG_puts("ippWrite: Could not write IPP attribute...");
+                       return (IPP_ERROR);
+                     }
+
+                     bufptr = buffer;
+                   }
+
+                    *bufptr++ = attr->value_tag;
+                   *bufptr++ = 0;
+                   *bufptr++ = 0;
+                 }
+
+                  n = attr->values[i].unknown.length;
+
+                  if (n > sizeof(buffer))
+                   return (IPP_ERROR);
+
+                  if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+                 {
+                    if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+                   {
+                     DEBUG_puts("ipp_write_file: Could not write IPP attribute...");
+                     return (IPP_ERROR);
+                   }
+
+                   bufptr = buffer;
+                 }
+
+                 /* Length of unknown value */
+                 *bufptr++ = n >> 8;
+                 *bufptr++ = n;
+
+                 /* Value */
+                 if (n > 0)
+                 {
+                   memcpy(bufptr, attr->values[i].unknown.data, n);
+                   bufptr += n;
+                 }
+               }
+               break;
+         }
+
+         /*
+         * Write the data out...
+         */
+
+          if (write(fd, (char *)buffer, bufptr - buffer) < 0)
+         {
+           DEBUG_puts("ipp_write_file: Could not write IPP attribute...");
+           close(fd);
+           return (IPP_ERROR);
+         }
+
+          DEBUG_printf(("ipp_write_file: wrote %d bytes\n", bufptr - buffer));
+       }
+
+       if (ipp->current == NULL)
+       {
+         /*
+         * Done with all of the attributes; add the end-of-attributes tag...
+         */
+
+          buffer[0] = IPP_TAG_END;
+         if (write(fd, (char *)buffer, 1) < 0)
+         {
+           DEBUG_puts("ipp_write_file: Could not write IPP end-tag...");
+           close(fd);
+           return (IPP_ERROR);
+         }
+
+         ipp->state = IPP_DATA;
+       }
+        break;
+
+    case IPP_DATA :
+        break;
+  }
+
+ /*
+  * Close the file and return...
+  */
+
+  close(fd);
+
+  return (ipp->state);
+}
+
+
 /*
  * 'set_time()' - Set one of the "time-at-xyz" attributes...
  */
@@ -2049,5 +2990,5 @@ start_process(const char *command,        /* I - Full path to command */
 
 
 /*
- * End of "$Id: job.c,v 1.124.2.2 2001/05/13 18:38:36 mike Exp $".
+ * End of "$Id: job.c,v 1.124.2.3 2001/12/26 16:52:54 mike Exp $".
  */
index a0c2549079be53c557db1f173ae9269e3f0b0112..3b565bf35b9a28fcb5a72d84ea32c167ccbb9a5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: listen.c,v 1.9.2.1 2001/04/02 19:51:50 mike Exp $"
+ * "$Id: listen.c,v 1.9.2.2 2001/12/26 16:52:54 mike Exp $"
  *
  *   Server listening routines for the Common UNIX Printing System (CUPS)
  *   scheduler.
@@ -107,7 +107,7 @@ StartListening(void)
 
   memset(&ServerAddr, 0, sizeof(ServerAddr));
 
-  if ((host = gethostbyname(ServerName)) != NULL)
+  if ((host = httpGetHostByName(ServerName)) != NULL)
   {
    /*
     * Found the server's address!
@@ -216,5 +216,5 @@ StopListening(void)
 
 
 /*
- * End of "$Id: listen.c,v 1.9.2.1 2001/04/02 19:51:50 mike Exp $".
+ * End of "$Id: listen.c,v 1.9.2.2 2001/12/26 16:52:54 mike Exp $".
  */
index 5a92b0ccfba17553dce0deaaa5ea2202c2c874e2..7ea92f3b0399b092f3c3fdb8540c6a6e871a0b7e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: log.c,v 1.19 2001/02/21 20:16:47 mike Exp $"
+ * "$Id: log.c,v 1.19.2.1 2001/12/26 16:52:54 mike Exp $"
  *
  *   Log file routines for the Common UNIX Printing System (CUPS).
  *
@@ -86,7 +86,7 @@ GetDateTime(time_t t)         /* I - Time value */
   * log files.  If you want GMT, set the TZ environment variable accordingly
   * before starting the scheduler.
   *
-  * (*BSD stores the timezone offset in the tm structure)
+  * (*BSD and Darwin store the timezone offset in the tm structure)
   */
 
   date = localtime(&t);
@@ -94,11 +94,11 @@ GetDateTime(time_t t)               /* I - Time value */
   snprintf(s, sizeof(s), "[%02d/%s/%04d:%02d:%02d:%02d %+03ld%02ld]",
           date->tm_mday, months[date->tm_mon], 1900 + date->tm_year,
           date->tm_hour, date->tm_min, date->tm_sec,
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+#ifdef HAVE_TM_GMTOFF
            -date->tm_gmtoff / 3600, (date->tm_gmtoff / 60) % 60);
 #else
            -timezone / 3600, (timezone / 60) % 60);
-#endif /* __*BSD__ */
+#endif /* HAVE_TM_GMTOFF */
  
   return (s);
 }
@@ -436,5 +436,5 @@ check_log_file(FILE       **log,    /* IO - Log file */
 
 
 /*
- * End of "$Id: log.c,v 1.19 2001/02/21 20:16:47 mike Exp $".
+ * End of "$Id: log.c,v 1.19.2.1 2001/12/26 16:52:54 mike Exp $".
  */
index 494a4b780532e7029bde98705d75aa674c572462..e143e3eef5789f153d33540e239768c32713822d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: main.c,v 1.57.2.1 2001/05/13 18:38:37 mike Exp $"
+ * "$Id: main.c,v 1.57.2.2 2001/12/26 16:52:55 mike Exp $"
  *
  *   Scheduler main loop for the Common UNIX Printing System (CUPS).
  *
@@ -446,7 +446,12 @@ main(int  argc,                    /* I - Number of command-line arguments */
     if (Browsing)
     {
       if (FD_ISSET(BrowseSocket, &input))
-        UpdateBrowseList();
+        UpdateCUPSBrowse();
+
+#ifdef HAVE_LIBSLP
+      if ((BrowseProtocols & BROWSE_SLP) && BrowseSLPRefresh <= time(NULL))
+        UpdateSLPBrowse();
+#endif /* HAVE_LIBSLP */
 
       SendBrowseList();
     }
@@ -740,5 +745,5 @@ usage(void)
 
 
 /*
- * End of "$Id: main.c,v 1.57.2.1 2001/05/13 18:38:37 mike Exp $".
+ * End of "$Id: main.c,v 1.57.2.2 2001/12/26 16:52:55 mike Exp $".
  */
index 578d5b610243a38fabd9cd4459d66087a9419f97..d17d6ff5545280cca5e737557ad2949dde354a84 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ppds.c,v 1.14.2.1 2001/05/13 18:38:38 mike Exp $"
+ * "$Id: ppds.c,v 1.14.2.2 2001/12/26 16:52:55 mike Exp $"
  *
  *   PPD scanning routines for the Common UNIX Printing System (CUPS).
  *
@@ -168,10 +168,26 @@ LoadPPDs(const char *d)           /* I - Directory to scan... */
 
   PPDs = ippNew();
 
+ /*
+  * First the raw driver...
+  */
+
+  ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+               "ppd-name", NULL, "raw");
+  ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+               "ppd-make", NULL, "Raw");
+  ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+               "ppd-make-and-model", NULL, "Raw Queue");
+  ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
+               "ppd-natural-language", NULL, "en");
+
+ /*
+  * Then the PPD files...
+  */
+
   for (i = num_ppds, ppd = ppds; i > 0; i --, ppd ++)
   {
-    if (i)
-      ippAddSeparator(PPDs);
+    ippAddSeparator(PPDs);
 
     ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_NAME,
                  "ppd-name", NULL, ppd->ppd_name);
@@ -399,11 +415,8 @@ static void
 load_ppds(const char *d,               /* I - Actual directory */
           const char *p)               /* I - Virtual path in name */
 {
-#ifdef HAVE_LIBZ
-  gzFile       fp;                     /* Pointer to file */
-#else
-  FILE         *fp;                    /* Pointer to file */
-#endif /* HAVE_LIBZ */
+  int          i;                      /* Looping var */
+  buf_t                fp;                     /* Pointer to file */
   DIR          *dir;                   /* Directory pointer */
   DIRENT       *dent;                  /* Directory entry */
   struct stat  fileinfo;               /* File information */
@@ -411,10 +424,37 @@ load_ppds(const char *d,          /* I - Actual directory */
                line[1024],             /* Line from backend */
                *ptr,                   /* Pointer into name */
                name[128],              /* Name of PPD file */
-               language[64],           /* Device class */
-               manufacturer[1024],     /* Manufacturer */
-               make_model[256];        /* Make and model */
-  ppd_info_t   *ppd;                   /* New PPD file */
+               language[64],           /* PPD language version */
+               country[64],            /* Country code */
+               manufacturer[256],      /* Manufacturer */
+               make_model[256],        /* Make and Model */
+               model_name[256],        /* ModelName */
+               nick_name[256];         /* NickName */
+  ppd_info_t   *ppd,                   /* New PPD file */
+               key;                    /* Search key */
+  int          new_ppd;                /* Is this a new PPD? */
+  struct                               /* LanguageVersion translation table */
+  {
+    const char *version,               /* LanguageVersion string */
+               *language;              /* Language code */
+  }            languages[] =
+  {
+    { "chinese",       "cn" },
+    { "english",       "en" },
+    { "french",                "fr" },
+    { "german",                "de" },
+    { "danish",                "da" },
+    { "finnish",       "fi" },
+    { "italian",       "it" },
+    { "dutch",         "du" },
+    { "japanese",      "jp" },
+    { "norwegian",     "no" },
+    { "polish",                "pl" },
+    { "portugese",     "pt" },
+    { "russian",       "ru" },
+    { "swedish",       "sv" },
+    { "turkish",       "tr" }
+  };
 
 
   if ((dir = opendir(d)) == NULL)
@@ -568,8 +608,9 @@ load_ppds(const char *d,            /* I - Actual directory */
        *ptr = '\0';
       else if (strncasecmp(manufacturer, "agfa", 4) == 0)
        strcpy(manufacturer, "AGFA");
-      else if (strncasecmp(manufacturer, "herk", 4) == 0)
-       strcpy(manufacturer, "Linotype");
+      else if (strncasecmp(manufacturer, "herk", 4) == 0 ||
+               strncasecmp(manufacturer, "linotype", 8) == 0)
+       strcpy(manufacturer, "LHAG");
       else
        strcpy(manufacturer, "Other");
 
@@ -595,24 +636,57 @@ load_ppds(const char *d,          /* I - Actual directory */
       else if (strcasecmp(manufacturer, "designjet") == 0)
        strcpy(manufacturer, "HP");
     }
+    else if (strncasecmp(manufacturer, "LHAG", 4) == 0 ||
+             strncasecmp(manufacturer, "linotype", 8) == 0)
+      strcpy(manufacturer, "LHAG");
 
    /*
     * Fix the language as needed...
     */
 
-    if (strcasecmp(language, "german") == 0)
-      strcpy(language, "de");
-    else if (strcasecmp(language, "spanish") == 0)
-      strcpy(language, "es");
-    else if (strlen(language) > 2)
+    if ((ptr = strchr(language, '-')) != NULL)
+      *ptr++ = '\0';
+    else if ((ptr = strchr(language, '_')) != NULL)
+      *ptr++ = '\0';
+
+    if (ptr)
+    {
+     /*
+      * Setup the country suffix...
+      */
+
+      country[0] = '_';
+      strcpy(country + 1, ptr);
+    }
+    else
+    {
+     /*
+      * No country suffix...
+      */
+
+      country[0] = '\0';
+    }
+
+    for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++)
+      if (strcasecmp(languages[i].version, language) == 0)
+        break;
+
+    if (i < (int)(sizeof(languages) / sizeof(languages[0])))
+    {
+     /*
+      * Found a known language...
+      */
+
+      snprintf(language, sizeof(language), "%s%s", languages[i].language, 
+               country);
+    }
+    else
     {
      /*
-      * en, fr, it, etc.
+      * Unknown language; use "xx"...
       */
 
-      language[0] = tolower(language[0]);
-      language[1] = tolower(language[1]);
-      language[2] = '\0';
+      strcpy(language, "xx");
     }
 
    /*
@@ -661,5 +735,5 @@ load_ppds(const char *d,            /* I - Actual directory */
 
 
 /*
- * End of "$Id: ppds.c,v 1.14.2.1 2001/05/13 18:38:38 mike Exp $".
+ * End of "$Id: ppds.c,v 1.14.2.2 2001/12/26 16:52:55 mike Exp $".
  */
index f2b34a6cffd12dcf1e5db2ede7a9884b85d4c459..05e0b2ff17697a92abd8e1096654dd669981fe4a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: printers.c,v 1.93.2.3 2001/05/13 18:38:38 mike Exp $"
+ * "$Id: printers.c,v 1.93.2.4 2001/12/26 16:52:55 mike Exp $"
  *
  *   Printer routines for the Common UNIX Printing System (CUPS).
  *
@@ -500,12 +500,12 @@ LoadAllPrinters(void)
       continue;
 
    /*
-    * Strip trailing newline, if any...
+    * Strip trailing whitespace, if any...
     */
 
     len = strlen(line);
 
-    if (line[len - 1] == '\n')
+    while (len > 0 && isspace(line[len - 1]))
     {
       len --;
       line[len] = '\0';
@@ -754,10 +754,13 @@ SaveAllPrinters(void)
 
     if (printer->info[0])
       fprintf(fp, "Info %s\n", printer->info);
-    if (printer->more_info[0])
+
+    if (printer->location[0])
       fprintf(fp, "Location %s\n", printer->location);
+
     if (printer->device_uri[0])
       fprintf(fp, "DeviceURI %s\n", printer->device_uri);
+
     if (printer->state == IPP_PRINTER_STOPPED)
     {
       fputs("State Stopped\n", fp);
@@ -765,19 +768,18 @@ SaveAllPrinters(void)
     }
     else
       fputs("State Idle\n", fp);
+
     if (printer->accepting)
       fputs("Accepting Yes\n", fp);
     else
       fputs("Accepting No\n", fp);
+
     fprintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
             printer->job_sheets[1]);
 
-    if (printer->quota_period)
-    {
-      fprintf(fp, "QuotaPeriod %d\n", printer->quota_period);
-      fprintf(fp, "PageLimit %d\n", printer->page_limit);
-      fprintf(fp, "KLimit %d\n", printer->k_limit);
-    }
+    fprintf(fp, "QuotaPeriod %d\n", printer->quota_period);
+    fprintf(fp, "PageLimit %d\n", printer->page_limit);
+    fprintf(fp, "KLimit %d\n", printer->k_limit);
 
     for (i = 0; i < printer->num_users; i ++)
       fprintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
@@ -807,8 +809,8 @@ SetPrinterAttrs(printer_t *p)               /* I - Printer to setup */
   char         filename[1024];         /* Name of PPD file */
   int          num_media;              /* Number of media options */
   location_t   *auth;                  /* Pointer to authentication element */
-  int          auth_len;               /* Length of class or printer resource */
   const char   *auth_supported;        /* Authentication supported */
+  cups_ptype_t printer_type;           /* Printer type data */
   ppd_file_t   *ppd;                   /* PPD file data */
   ppd_option_t *input_slot,            /* InputSlot options */
                *media_type,            /* MediaType options */
@@ -926,15 +928,9 @@ SetPrinterAttrs(printer_t *p)              /* I - Printer to setup */
   if (!(p->type & CUPS_PRINTER_REMOTE))
   {
     if (p->type & CUPS_PRINTER_CLASS)
-    {
-      auth_len = 8;
       snprintf(resource, sizeof(resource), "/classes/%s", p->name);
-    }
     else
-    {
-      auth_len = 9;
       snprintf(resource, sizeof(resource), "/printers/%s", p->name);
-    }
 
     for (i = NumLocations, auth = Locations; i > 0; i --, auth ++)
       if (strcmp(auth->location, resource) == 0)
@@ -987,7 +983,7 @@ SetPrinterAttrs(printer_t *p)               /* I - Printer to setup */
   ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
                NULL, p->info);
   ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info",
-               NULL, p->more_info);
+               NULL, p->uri);
   ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
                "pdl-override-supported", NULL, "not-attempted");
   ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
@@ -1013,8 +1009,9 @@ SetPrinterAttrs(printer_t *p)             /* I - Printer to setup */
                "generated-natural-language-supported", NULL, DefaultLanguage);
   ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
                "document-format-default", NULL, "application/octet-stream");
-  ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
-               "document-format-supported", NULL, "application/octet-stream");
+  ippAddStrings(p->attrs, IPP_TAG_PRINTER,
+                (ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
+                "document-format-supported", NumMimeTypes, NULL, MimeTypes);
   ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
                "compression-supported", NULL, "none");
   ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
@@ -1059,9 +1056,9 @@ SetPrinterAttrs(printer_t *p)             /* I - Printer to setup */
     * Setup the job-sheets-supported and job-sheets-default attributes...
     */
 
-    if (Classification[0])
-      attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
-                          "job-sheets-supported", 2, NULL, NULL);
+    if (Classification[0] && !ClassifyOverride)
+      attr = ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+                         "job-sheets-supported", NULL, Classification);
     else
       attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
                           "job-sheets-supported", NumBanners + 1, NULL, NULL);
@@ -1070,7 +1067,7 @@ SetPrinterAttrs(printer_t *p)             /* I - Printer to setup */
       LogMessage(L_EMERG, "SetPrinterAttrs: Unable to allocate memory for "
                           "job-sheets-supported attribute: %s!",
                 strerror(errno));
-    else
+    else if (!Classification[0] || ClassifyOverride)
     {
       attr->values[0].string.text = strdup("none");
 
@@ -1083,16 +1080,21 @@ SetPrinterAttrs(printer_t *p)           /* I - Printer to setup */
       }
     }
 
-    attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
-                        "job-sheets-default", 2, NULL, NULL);
-
-    if (attr != NULL)
+    if (!(p->type & CUPS_PRINTER_REMOTE))
     {
-      attr->values[0].string.text = strdup(p->job_sheets[0]);
-      attr->values[1].string.text = strdup(p->job_sheets[1]);
+      attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+                          "job-sheets-default", 2, NULL, NULL);
+
+      if (attr != NULL)
+      {
+       attr->values[0].string.text = strdup(p->job_sheets[0]);
+       attr->values[1].string.text = strdup(p->job_sheets[1]);
+      }
     }
   }
 
+  printer_type = p->type;
+
   if (p->type & CUPS_PRINTER_REMOTE)
   {
    /*
@@ -1216,7 +1218,12 @@ SetPrinterAttrs(printer_t *p)            /* I - Printer to setup */
        ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
                      "printer-make-and-model", NULL, ppd->nickname);
 
-        strncpy(p->make_model, ppd->nickname, sizeof(p->make_model) - 1);
+        if (ppd->nickname)
+          strncpy(p->make_model, ppd->nickname, sizeof(p->make_model) - 1);
+       else if (ppd->modelname)
+          strncpy(p->make_model, ppd->modelname, sizeof(p->make_model) - 1);
+       else
+         strcpy(p->make_model, "Bad PPD File");
 
        /*
        * Add media options from the PPD file...
@@ -1337,6 +1344,8 @@ SetPrinterAttrs(printer_t *p)             /* I - Printer to setup */
           AddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
 
        ppdClose(ppd);
+
+        printer_type = p->type;
       }
       else if (access(filename, 0) == 0)
       {
@@ -1365,6 +1374,38 @@ SetPrinterAttrs(printer_t *p)            /* I - Printer to setup */
                   ServerRoot, p->name);
          AddPrinterFilter(p, filename);
        }
+       else if (strncmp(p->device_uri, "ipp://", 6) == 0 &&
+                (strstr(p->device_uri, "/printers/") != NULL ||
+                 strstr(p->device_uri, "/classes/") != NULL))
+        {
+        /*
+         * Tell the client this is really a hard-wired remote printer.
+         */
+
+          printer_type |= CUPS_PRINTER_REMOTE;
+
+         /*
+         * Reset the printer-uri-supported attribute to point at the
+         * remote printer...
+         */
+
+         attr = ippFindAttribute(p->attrs, "printer-uri-supported", IPP_TAG_URI);
+         free(attr->values[0].string.text);
+         attr->values[0].string.text = strdup(p->device_uri);
+
+         /*
+         * Then set the make-and-model accordingly...
+         */
+
+         ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+                       "printer-make-and-model", NULL, "Remote Printer");
+
+         /*
+         * Print all files directly...
+         */
+
+         AddPrinterFilter(p, "*/* 0 -");
+       }
        else
        {
         /*
@@ -1390,7 +1431,8 @@ SetPrinterAttrs(printer_t *p)             /* I - Printer to setup */
   * Add the CUPS-specific printer-type attribute...
   */
 
-  ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", p->type);
+  ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type",
+                printer_type);
 
   DEBUG_printf(("SetPrinterAttrs: leaving name = %s, type = %x\n", p->name,
                 p->type));
@@ -1793,5 +1835,5 @@ write_printcap(void)
 
 
 /*
- * End of "$Id: printers.c,v 1.93.2.3 2001/05/13 18:38:38 mike Exp $".
+ * End of "$Id: printers.c,v 1.93.2.4 2001/12/26 16:52:55 mike Exp $".
  */
index fb0f550779a3f64ff062beb1e83ea17c57fa533e..5f2329a02360941ceade35c35d16df4a3081db75 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: printers.h,v 1.22 2001/01/22 15:04:01 mike Exp $"
+ * "$Id: printers.h,v 1.22.2.1 2001/12/26 16:52:55 mike Exp $"
  *
  *   Printer definitions for the Common UNIX Printing System (CUPS) scheduler.
  *
@@ -47,8 +47,7 @@ typedef struct printer_str
                name[IPP_MAX_NAME],     /* Printer name */
                location[IPP_MAX_NAME], /* Location code */
                make_model[IPP_MAX_NAME],/* Make and model */
-               info[IPP_MAX_NAME],     /* Description */
-               more_info[HTTP_MAX_URI];/* URL for site-specific info */
+               info[IPP_MAX_NAME];     /* Description */
   int          accepting;              /* Accepting jobs? */
   ipp_pstate_t state;                  /* Printer state */
   char         state_message[1024];    /* Printer state message */
@@ -114,5 +113,5 @@ extern const char   *ValidateDest(const char *hostname,
 
 
 /*
- * End of "$Id: printers.h,v 1.22 2001/01/22 15:04:01 mike Exp $".
+ * End of "$Id: printers.h,v 1.22.2.1 2001/12/26 16:52:55 mike Exp $".
  */
index f569bbd5572b3c84a491c51b3bef483b31fc287b..339a75c9f667b68301d8a2f3e5c43b9a0d0fefc2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: quotas.c,v 1.4 2001/01/22 15:04:01 mike Exp $"
+ * "$Id: quotas.c,v 1.4.2.1 2001/12/26 16:52:55 mike Exp $"
  *
  *   Quota routines for the Common UNIX Printing System (CUPS).
  *
@@ -182,7 +182,7 @@ UpdateQuota(printer_t  *p,          /* I - Printer */
     next = job->next;
 
     if (strcasecmp(job->dest, p->name) != 0 ||
-        strcmp(job->username, q->username) != 0)
+        strcasecmp(job->username, q->username) != 0)
       continue;
 
     if ((attr = ippFindAttribute(job->attrs, "time-at-completion",
@@ -227,10 +227,10 @@ static int                                /* O - Result of comparison */
 compare(const quota_t *q1,             /* I - First quota record */
         const quota_t *q2)             /* I - Second quota record */
 {
-  return (strcmp(q1->username, q2->username));
+  return (strcasecmp(q1->username, q2->username));
 }
 
 
 /*
- * End of "$Id: quotas.c,v 1.4 2001/01/22 15:04:01 mike Exp $".
+ * End of "$Id: quotas.c,v 1.4.2.1 2001/12/26 16:52:55 mike Exp $".
  */
index fcb444d23f6a6ec718c665aa8cfe6ed97c9b64da..c44f7c1c74338fc8c9f24a5e1725e50b8888ce4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: type.c,v 1.11 2001/02/07 19:41:38 mike Exp $"
+ * "$Id: type.c,v 1.11.2.1 2001/12/26 16:52:55 mike Exp $"
  *
  *   MIME typing routines for the Common UNIX Printing System (CUPS).
  *
@@ -902,7 +902,7 @@ checkrules(const char   *filename,  /* I - Filename */
          break;
 
       case MIME_MAGIC_LOCALE :
-          result = (strcmp(rules->value.localev, setlocale(LC_ALL, NULL)) == 0);
+          result = (strcmp(rules->value.localev, setlocale(LC_MESSAGES, NULL)) == 0);
          break;
 
       case MIME_MAGIC_CONTAINS :
@@ -1086,5 +1086,5 @@ patmatch(const char *s,           /* I - String to match against */
 
 
 /*
- * End of "$Id: type.c,v 1.11 2001/02/07 19:41:38 mike Exp $".
+ * End of "$Id: type.c,v 1.11.2.1 2001/12/26 16:52:55 mike Exp $".
  */
index 270277692ba6931ea364688b0f1c61cb5fb43a0f..7d9b1a5e7000dce945093b329eaca876ff9d79bd 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.23 2001/01/22 15:04:02 mike Exp $"
+# "$Id: Makefile,v 1.23.2.1 2001/12/26 16:52:56 mike Exp $"
 #
 #   System V commands makefile for the Common UNIX Printing System (CUPS).
 #
 
 include ../Makedefs
 
-TARGETS        =       accept cancel lp lpadmin lpinfo lpmove lpoptions lppasswd \
-               lpstat
-OBJS   =       accept.o cancel.o lp.o lpadmin.o lpinfo.o lpmove.o \
-               lpoptions.o lppasswd.o lpstat.o
+TARGETS        =       accept cancel cupsaddsmb lp lpadmin lpinfo lpmove \
+               lpoptions lppasswd lpstat
+OBJS   =       accept.o cancel.o cupsaddsmb.o lp.o lpadmin.o \
+               lpinfo.o lpmove.o lpoptions.o lppasswd.o lpstat.o
 
 
 #
@@ -49,30 +49,24 @@ clean:
 # Install all targets...
 #
 
-install:       $(INSTALL_SYSV)
-       -$(MKDIR) $(BINDIR)
-       $(CHMOD) ugo+rx $(BINDIR)
-       $(INSTALL_BIN) accept lpadmin lpinfo lpmove $(SBINDIR)
-       $(INSTALL_BIN) cancel lp lpoptions lppasswd lpstat $(BINDIR)
-       $(CHMOD) u+s $(BINDIR)/lppasswd
+install:
+       $(INSTALL_DIR) $(BINDIR)
+       $(INSTALL_BIN) accept $(SBINDIR)
        $(RM) $(SBINDIR)/reject
        $(LN) accept $(SBINDIR)/reject
+       $(INSTALL_BIN) cupsaddsmb $(SBINDIR)
+       $(INSTALL_BIN) lpadmin $(SBINDIR)
+       $(INSTALL_BIN) lpinfo $(SBINDIR)
+       $(INSTALL_BIN) lpmove $(SBINDIR)
+       $(INSTALL_BIN) cancel $(BINDIR)
        $(RM) $(BINDIR)/disable
        $(LN) ../sbin/accept $(BINDIR)/disable
        $(RM) $(BINDIR)/enable
        $(LN) ../sbin/accept $(BINDIR)/enable
-
-install-sysv:
-       -$(MKDIR) $(LIBDIR)
-       $(CHMOD) ugo+rx $(LIBDIR)
-       $(RM) $(LIBDIR)/lpadmin
-       $(LN) ../sbin/lpadmin $(LIBDIR)
-       $(RM) $(LIBDIR)/lpmove
-       $(LN) ../sbin/lpmove $(LIBDIR)
-       $(RM) $(LIBDIR)/accept
-       $(LN) ../sbin/accept $(LIBDIR)
-       $(RM) $(LIBDIR)/reject
-       $(LN) ../sbin/accept $(LIBDIR)/reject
+       $(INSTALL_BIN) lp $(BINDIR)
+       $(INSTALL_BIN) lpoptions $(BINDIR)
+       $(INSTALL_BIN) lpstat $(BINDIR)
+       $(INSTALL_BIN) -m 4755 -o $(CUPS_USER) -g $(CUPS_GROUP) lppasswd $(BINDIR)
 
 
 #
@@ -82,6 +76,10 @@ install-sysv:
 accept:        accept.o ../cups/$(LIBCUPS)
        echo Linking $@...
        $(CC) $(LDFLAGS) -o accept accept.o $(LIBS)
+       $(RM) reject enable disable
+       $(LN) accept reject
+       $(LN) accept enable
+       $(LN) accept disable
 
 accept.o:      ../cups/cups.h
 
@@ -97,6 +95,17 @@ cancel:      cancel.o ../cups/$(LIBCUPS)
 cancel.o:      ../cups/cups.h
 
 
+#
+# cupsaddsmb
+#
+
+cupsaddsmb:    cupsaddsmb.o ../cups/$(LIBCUPS)
+       echo Linking $@...
+       $(CC) $(LDFLAGS) -o cupsaddsmb cupsaddsmb.o $(LIBS)
+
+cupsaddsmb.o:  ../cups/cups.h ../cups/string.h
+
+
 #
 # lp
 #
@@ -177,5 +186,5 @@ lpstat.o:   ../cups/cups.h
 $(OBJS):       ../Makedefs
 
 #
-# End of "$Id: Makefile,v 1.23 2001/01/22 15:04:02 mike Exp $".
+# End of "$Id: Makefile,v 1.23.2.1 2001/12/26 16:52:56 mike Exp $".
 #
index 272098c15ca98fe6bfb675b122352a452e205dbf..e8726d064338938c868c6342b5ced50b293bd514 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: accept.c,v 1.11.2.1 2001/05/13 18:38:40 mike Exp $"
+ * "$Id: accept.c,v 1.11.2.2 2001/12/26 16:52:56 mike Exp $"
  *
  *   "accept", "disable", "enable", and "reject" commands for the Common
  *   UNIX Printing System (CUPS).
@@ -57,6 +57,7 @@ main(int  argc,                       /* I - Number of command-line arguments */
                                /* Name of printer or class */
                uri[1024],      /* Printer URI */
                *reason;        /* Reason for reject/disable */
+  const char   *server;        /* Server name */
   ipp_t                *request;       /* IPP request */
   ipp_t                *response;      /* IPP response */
   ipp_op_t     op;             /* Operation */
@@ -90,6 +91,7 @@ main(int  argc,                       /* I - Number of command-line arguments */
     return (1);
   }
 
+  server     = cupsServer();
   http       = NULL;
   reason     = NULL;
   encryption = cupsEncryption();
@@ -123,7 +125,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
              httpClose(http);
 
            if (argv[i][2] != '\0')
-             http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
+             server = argv[i] + 2;
            else
            {
              i ++;
@@ -134,9 +136,11 @@ main(int  argc,                    /* I - Number of command-line arguments */
                return (1);
              }
 
-             http = httpConnectEncrypt(argv[i], ippPort(), encryption);
+              server = argv[i];
            }
 
+            http = httpConnectEncrypt(server, ippPort(), encryption);
+
            if (http == NULL)
            {
              fputs(argv[0], stderr);
@@ -173,7 +177,10 @@ main(int  argc,                    /* I - Number of command-line arguments */
       */
 
       if (sscanf(argv[i], "%1023[^@]@%1023s", printer, hostname) == 1)
-       strcpy(hostname, "localhost");
+      {
+       strncpy(hostname, server, sizeof(hostname) - 1);
+       hostname[sizeof(hostname) - 1] = '\0';
+      }
 
       if (http != NULL && strcasecmp(http->hostname, hostname) != 0)
       {
@@ -304,5 +311,5 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
 
 /*
- * End of "$Id: accept.c,v 1.11.2.1 2001/05/13 18:38:40 mike Exp $".
+ * End of "$Id: accept.c,v 1.11.2.2 2001/12/26 16:52:56 mike Exp $".
  */
index d4876a089126e55bc1445ebb6bba9edaadc1f27f..3fffa42707fe196e2d8fe76920cda6d24379f665 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: cupsaddsmb.c,v 1.3 2001/12/18 21:08:21 mike Exp $"
+ * "$Id: cupsaddsmb.c,v 1.3.2.1 2001/12/26 16:52:56 mike Exp $"
  *
  *   "cupsaddsmb" command for the Common UNIX Printing System (CUPS).
  *
@@ -282,5 +282,5 @@ export_dest(const char *dest)       /* I - Destination to export */
 
 
 /*
- * End of "$Id: cupsaddsmb.c,v 1.3 2001/12/18 21:08:21 mike Exp $".
+ * End of "$Id: cupsaddsmb.c,v 1.3.2.1 2001/12/26 16:52:56 mike Exp $".
  */
index 902c0c1254b5139a8304fe5bec8feb73cc4e99bf..b1b7dedde430da67c838e332339afb503add3473 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lp.c,v 1.29.2.1 2001/05/13 18:38:40 mike Exp $"
+ * "$Id: lp.c,v 1.29.2.2 2001/12/26 16:52:56 mike Exp $"
  *
  *   "lp" command for the Common UNIX Printing System (CUPS).
  *
@@ -375,8 +375,9 @@ main(int  argc,             /* I - Number of command-line arguments */
            if (strcmp(val, "hold") == 0)
               num_options = cupsAddOption("job-hold-until", "indefinite",
                                          num_options, &options);
-           if (strcmp(val, "resume") == 0)
-              num_options = cupsAddOption("job-hold-until", "none",
+           else if (strcmp(val, "resume") == 0 ||
+                    strcmp(val, "release") == 0)
+              num_options = cupsAddOption("job-hold-until", "no-hold",
                                          num_options, &options);
            else if (strcmp(val, "immediate") == 0)
               num_options = cupsAddOption("job-priority", "100",
@@ -529,7 +530,7 @@ main(int  argc,             /* I - Number of command-line arguments */
       return (1);
     }
 
-    while ((i = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+    while ((i = read(0, buffer, sizeof(buffer))) > 0)
       write(temp, buffer, i);
 
     i = lseek(temp, 0, SEEK_CUR);
@@ -556,8 +557,7 @@ main(int  argc,             /* I - Number of command-line arguments */
     return (1);
   }
   else if (!silent)
-    fprintf(stderr, "request id is %s-%d (%d file(s))\n", printer, job_id,
-            num_files);
+    printf("request id is %s-%d (%d file(s))\n", printer, job_id, num_files);
 
   return (0);
 }
@@ -650,5 +650,5 @@ sighandler(int s)   /* I - Signal number */
 
 
 /*
- * End of "$Id: lp.c,v 1.29.2.1 2001/05/13 18:38:40 mike Exp $".
+ * End of "$Id: lp.c,v 1.29.2.2 2001/12/26 16:52:56 mike Exp $".
  */
index 11ae41aed592822960b4d79dc846557fa6d6b8ea..6432ce657d7c263dfee633c5da05569803affbdf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $"
+ * "$Id: lpadmin.c,v 1.22.2.2 2001/12/26 16:52:57 mike Exp $"
  *
  *   "lpadmin" command for the Common UNIX Printing System (CUPS).
  *
@@ -33,6 +33,7 @@
  *   set_printer_file()          - Set the interface script or PPD file.
  *   set_printer_info()          - Set the printer description string.
  *   set_printer_location()      - Set the printer location string.
+ *   set_printer_model()         - Set the driver model file.
  *   set_printer_options()       - Set the printer options.
  *   validate_name()             - Make sure the printer name only contains
  *                                 letters, numbers, and the underscore...
@@ -68,6 +69,7 @@ static void   set_printer_device(http_t *, char *, char *);
 static void    set_printer_file(http_t *, char *, char *);
 static void    set_printer_info(http_t *, char *, char *);
 static void    set_printer_location(http_t *, char *, char *);
+static void    set_printer_model(http_t *, char *, char *);
 static void    set_printer_options(http_t *, char *, int, cups_option_t *);
 static int     validate_name(const char *);
 
@@ -99,9 +101,6 @@ main(int  argc,                      /* I - Number of command-line arguments */
   options     = NULL;
   encryption  = cupsEncryption();
 
-  if ((datadir = getenv("CUPS_DATADIR")) == NULL)
-    datadir = CUPS_DATADIR;
-
   for (i = 1; i < argc; i ++)
     if (argv[i][0] == '-')
       switch (argv[i][1])
@@ -298,8 +297,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
            }
 
            if (argv[i][2])
-             snprintf(filename, sizeof(filename), "%s/model/%s", datadir,
-                      argv[i] + 2);
+             set_printer_model(http, printer, argv[i] + 2);
            else
            {
              i ++;
@@ -310,11 +308,8 @@ main(int  argc,                    /* I - Number of command-line arguments */
                return (1);
              }
 
-             snprintf(filename, sizeof(filename), "%s/model/%s", datadir,
-                      argv[i]);
+             set_printer_model(http, printer, argv[i]);
            }
-
-            set_printer_file(http, printer, filename);
            break;
 
         case 'o' : /* Set option */
@@ -1589,6 +1584,70 @@ set_printer_location(http_t *http,       /* I - Server connection */
 }
 
 
+/*
+ * 'set_printer_model()' - Set the driver model file.
+ */
+
+static void
+set_printer_model(http_t *http,                /* I - Server connection */
+                  char   *printer,     /* I - Printer */
+                 char   *model)        /* I - Driver model file */
+{
+  ipp_t                *request,               /* IPP Request */
+               *response;              /* IPP Response */
+  cups_lang_t  *language;              /* Default language */
+  char         uri[HTTP_MAX_URI];      /* URI for printer/class */
+
+
+ /*
+  * Build a CUPS_ADD_PRINTER request, which requires the following
+  * attributes:
+  *
+  *    attributes-charset
+  *    attributes-natural-language
+  *    printer-uri
+  *    ppd-name
+  */
+
+  snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+  request = ippNew();
+
+  request->request.op.operation_id = CUPS_ADD_PRINTER;
+  request->request.op.request_id   = 1;
+
+  language = cupsLangDefault();
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+               "attributes-charset", NULL, cupsLangEncoding(language));
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+               "attributes-natural-language", NULL, language->language);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+               "printer-uri", NULL, uri);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+               "ppd-name", NULL, model);
+
+ /*
+  * Do the request and get back a response...
+  */
+
+  if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+    fprintf(stderr, "lpadmin: add-printer failed: %s\n",
+            ippErrorString(cupsLastError()));
+  else
+  {
+    if (response->request.status.status_code > IPP_OK_CONFLICT)
+      fprintf(stderr, "lpadmin: add-printer failed: %s\n",
+              ippErrorString(response->request.status.status_code));
+
+    ippDelete(response);
+  }
+}
+
+
 /*
  * 'set_printer_options()' - Set the printer options.
  */
@@ -1770,5 +1829,5 @@ validate_name(const char *name)   /* I - Name to check */
 
 
 /*
- * End of "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $".
+ * End of "$Id: lpadmin.c,v 1.22.2.2 2001/12/26 16:52:57 mike Exp $".
  */
index 46ea7f60178d16c2134db5275d80cca2d8925f73..d439eda9ba9e8ae276c359493cf723719be228c3 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.6 2001/01/22 15:04:03 mike Exp $"
+# "$Id: Makefile,v 1.6.2.1 2001/12/26 16:52:57 mike Exp $"
 #
 #   Template makefile for the Common UNIX Printing System (CUPS).
 #
@@ -51,6 +51,7 @@ FILES =       add-class.tmpl \
                job-cancel.tmpl \
                job-hold.tmpl \
                job-release.tmpl \
+               job-restart.tmpl \
                modify-class.tmpl \
                modify-printer.tmpl \
                option-boolean.tmpl \
@@ -91,12 +92,12 @@ clean:
 #
 
 install:
-       -$(MKDIR) $(DATADIR)/templates
-       $(CHMOD) ugo+rx $(DATADIR)
-       $(CHMOD) ugo+rx $(DATADIR)/templates
-       $(INSTALL_DATA) $(FILES) $(DATADIR)/templates
+       $(INSTALL_DIR) $(DATADIR)/templates
+       for file in $(FILES); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/templates; \
+       done
 
 
 #
-# End of "$Id: Makefile,v 1.6 2001/01/22 15:04:03 mike Exp $".
+# End of "$Id: Makefile,v 1.6.2.1 2001/12/26 16:52:57 mike Exp $".
 #
index a432d99ca6a47265cd529f455529271c8391b8dc..63bee8529b9666196448b51bf51114e687c7a0b2 100644 (file)
        <TD></TD>
        <TD></TD>
        <TD>Examples:
-       <UL>
-               <PRE>file:/path/to/filename.prn</PRE>
-               <PRE>http://hostname:631/ipp/port1</PRE>
-               <PRE>ipp://hostname/ipp/port1</PRE>
-               <PRE>lpd://hostname/queue</PRE>
-               <PRE>socket://hostname</PRE>
-               <PRE>socket://hostname:9100</PRE>
-       </UL>
+       <PRE>
+    file:/path/to/filename.prn
+    http://hostname:631/ipp/port1
+    ipp://hostname/ipp/port1
+    lpd://hostname/queue
+    socket://hostname
+    socket://hostname:9100
+       </PRE>
        </TD>
 </TR>
 <TR>
index a32677b882c0f5de6e1f41024a19ca8a6dc7f4e6..d168cc1ae8ac9c4005211ff177dfc89b8d41c457 100644 (file)
@@ -2,27 +2,27 @@
 <TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
 <TR BGCOLOR="#999966">
        <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
-       <TH>ID</TH>
-       <TH>Name</TH>
-       <TH>User</TH>
-       <TH>Size</TH>
-       <TH>State</TH>
-       <TH>Control</TH>
+       <TH>ID&nbsp;</TH>
+       <TH>Name&nbsp;</TH>
+       <TH>User&nbsp;</TH>
+       <TH>Size&nbsp;</TH>
+       <TH>State&nbsp;</TH>
+       <TH>Control&nbsp;</TH>
        <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
 </TR>
 <TR>
        <TD HEIGHT="4"></TD>
 </TR>
 {[job_id]
-<TR>
+<TR VALIGN="TOP">
        <TD HEIGHT="28"></TD>
-       <TD>{job_id}</TD>
-       <TD>{?job_name=?Unknown:{job_name}}</TD>
-       <TD>{job_originating_user_name}</TD>
-       <TD>{job_k_octets}k</TD>
-       <TD>{job_state=3?pending:{job_state=4?held:
-       {job_state=5?processing:{job_state=6?stopped:
-       {job_state=7?cancelled:{job_state=8?aborted:completed}}}}}}</TD>
+       <TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+       <TD>{?job_name=?Unknown:{job_name}}&nbsp;</TD>
+       <TD>{job_originating_user_name}&nbsp;</TD>
+       <TD>{job_k_octets}k&nbsp;</TD>
+       <TD>{job_state=3?pending since<BR>{time_at_creation}:{job_state=4?held since<BR>{time_at_creation}:
+       {job_state=5?processing since<BR>{time_at_processing}:{job_state=6?stopped at<BR>{time_at_completed}:
+       {job_state=7?cancelled at<BR>{time_at_completed}:{job_state=8?aborted:completed at<BR>{time_at_completed}}}}}}}&nbsp;</TD>
        <TD>
        {job_state>5?
        {job_k_octets>0?
@@ -40,8 +40,7 @@
        <A HREF="/admin/?op=cancel-job&job_id={job_id}">
        <IMG SRC="/images/cancel-job.gif" ALT="Cancel Job" BORDER="0"></A>
        }
-       </FORM>
-       </TD>
+       &nbsp;</TD>
 </TR>
 }
 </TABLE>
index a23b1d2c1baded0565221b318193b05414931a28..23a904178dc5bbf2d8d4be8c235a3212fe8858fc 100644 (file)
@@ -1,6 +1,6 @@
 <TR>
        <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
-       <TH BGCOLOR="#999966" COLSPAN="2">{group}</A></TH>
+       <TH BGCOLOR="#999966" COLSPAN="2">{group}</TH>
        <TH><IMG SRC="/images/right.gif" ALT=""></TH>
 </TR>
 <TR>
index 23d8c2f3cdcd15089356e4143cfedefef38b36e9..3a269eb0dfffb63f1e89fed5a216c81bc790e1d0 100644 (file)
@@ -1 +1 @@
-<P>Printer {printer_name} is now accepting jobs.
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> is now accepting jobs.
index 6cf330c4c57ddd4ddfc9df9053c4a701cef54b2d..e73d87380d50b347416ed440542ebc5c36a39778 100644 (file)
@@ -1 +1 @@
-<P>Printer {printer_name} is no longer accepting jobs.
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> is no longer accepting jobs.
index dc01c3771e5e2d703bd5abcbdd68ca58001f2568..a584af72338e37373208be148a8e8b42a4a15463 100644 (file)
@@ -1,7 +1,7 @@
 <HR>
-<P>The Common UNIX Printing System, CUPS, and the CUPS logo are the
-trademark property of <A HREF="http://www.easysw.com">Easy Software
-Products</A>. CUPS is copyright 1997-2001 by Easy Software Products,
-All Rights Reserved.
+<P>Copyright 1993-2001 Easy Software Products, All Rights Reserved. 
+The Common UNIX Printing System, CUPS, and the CUPS logo
+are the trademark property of <A HREF="http://www.easysw.com">Easy Software Products</A>. 
+All other trademarks are the property of their respective owners.
 </BODY>
 </HTML>
index 97e41ebe5d3ff11478f236b36ddf508de0b1b630..50b7de9a90d6c8917ac04b4a5173e40ca9c44412 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$Id: Makefile,v 1.2 2001/01/22 15:04:04 mike Exp $"
+# "$Id: Makefile,v 1.2.2.1 2001/12/26 16:52:58 mike Exp $"
 #
 #   IPP test makefile for the Common UNIX Printing System (CUPS).
 #
@@ -59,5 +59,14 @@ ipptest.o:   ../cups/cups.h ../Makedefs
 
 
 #
-# End of "$Id: Makefile,v 1.2 2001/01/22 15:04:04 mike Exp $".
+# purify target for doing tests on the CUPS API...
+#
+
+purify:        ipptest.o ../cups/$(LIBCUPS)
+       echo Linking $@...
+       purify $(CC) $(LDFLAGS) -o ipptest.pure ipptest.o $(LIBS)
+
+
+#
+# End of "$Id: Makefile,v 1.2.2.1 2001/12/26 16:52:58 mike Exp $".
 #
index c8fee625fd8b68aa2b1fcf2dcd235b6d19f3fb83..3d9db3512699fbacf255a4c242dab3c4bfadd2f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: config.h,v 1.5 2001/03/02 22:34:21 andy Exp $"
+ * "$Id: config.h,v 1.5.2.1 2001/12/26 16:52:58 mike Exp $"
  *
  *   Configuration file for the Common UNIX Printing System (CUPS).
  *
@@ -28,7 +28,7 @@
  * Version of software...
  */
 
-#define CUPS_SVERSION  "CUPS v1.1.6"
+#define CUPS_SVERSION  "CUPS v1.2.0"
 
 /*
  * Where are files stored?
 
 
 /*
- * End of "$Id: config.h,v 1.5 2001/03/02 22:34:21 andy Exp $".
+ * End of "$Id: config.h,v 1.5.2.1 2001/12/26 16:52:58 mike Exp $".
  */