From a256ef2ad4b13f45c7d9bd1148ea277a664b3f8b Mon Sep 17 00:00:00 2001 From: msweet Date: Fri, 10 May 2013 18:56:23 +0000 Subject: [PATCH] Import cups.org releases git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/tags/release-1.1.17@4306 a1ca3aef-8c08-0410-bb20-df032aa958be --- .cvsignore | 33 + CHANGES.txt | 2528 + CREDITS.txt | 30 + ENCRYPTION.txt | 138 + INSTALL.txt | 190 + LICENSE.html | 957 + LICENSE.txt | 861 + Makedefs.in | 184 + Makefile | 170 + README.txt | 288 + backend/.cvsignore | 7 + backend/Dependencies | 15 + backend/Makefile | 155 + backend/betest.c | 87 + backend/ipp.c | 906 + backend/lpd.c | 928 + backend/parallel.c | 676 + backend/scsi-irix.c | 211 + backend/scsi-linux.c | 228 + backend/scsi.c | 223 + backend/serial.c | 991 + backend/socket.c | 367 + backend/usb.c | 789 + berkeley/.cvsignore | 4 + berkeley/Dependencies | 11 + berkeley/Makefile | 112 + berkeley/lpc.c | 482 + berkeley/lpq.c | 549 + berkeley/lpr.c | 433 + berkeley/lprm.c | 275 + cgi-bin/.cvsignore | 5 + cgi-bin/Dependencies | 20 + cgi-bin/Makefile | 123 + cgi-bin/admin.c | 1535 + cgi-bin/cgi.h | 86 + cgi-bin/classes.c | 360 + cgi-bin/html.c | 89 + cgi-bin/ipp-var.c | 304 + cgi-bin/ipp-var.h | 55 + cgi-bin/jobs.c | 259 + cgi-bin/printers.c | 360 + cgi-bin/template.c | 492 + cgi-bin/var.c | 672 + conf/Makefile | 76 + conf/classes.conf | 89 + conf/client.conf | 65 + conf/cupsd.conf.in | 765 + conf/mime.convs | 116 + conf/mime.types | 158 + conf/pam.conf.in | 2 + conf/pam.irix | 3 + conf/printcap | 2 + conf/printers.conf | 96 + config-scripts/cups-common.m4 | 174 + config-scripts/cups-compiler.m4 | 185 + config-scripts/cups-directories.m4 | 242 + config-scripts/cups-image.m4 | 82 + config-scripts/cups-libtool.m4 | 49 + config-scripts/cups-manpages.m4 | 104 + config-scripts/cups-network.m4 | 41 + config-scripts/cups-openslp.m4 | 48 + config-scripts/cups-openssl.m4 | 74 + config-scripts/cups-opsys.m4 | 90 + config-scripts/cups-pam.m4 | 71 + config-scripts/cups-sharedlibs.m4 | 149 + config.h.in | 240 + configure.in | 48 + cups-config.in | 134 + cups.dsw | 128 + cups.list.in | 472 + cups.plist | 7 + cups.sh.in | 211 + cups.spec | 207 + cups.strings | 9 + cups/.cvsignore | 11 + cups/Dependencies | 26 + cups/Makefile | 216 + cups/cups.dsp | 216 + cups/cups.h | 180 + cups/cups_C.h | 135 + cups/debug.h | 59 + cups/dest.c | 798 + cups/emit.c | 548 + cups/encode.c | 381 + cups/http-addr.c | 118 + cups/http-support.c | 317 + cups/http.c | 2007 + cups/http.h | 353 + cups/ipp-support.c | 175 + cups/ipp.c | 2067 + cups/ipp.h | 434 + cups/language.c | 427 + cups/language.h | 228 + cups/mark.c | 443 + cups/md5.c | 392 + cups/md5.h | 94 + cups/md5passwd.c | 150 + cups/options.c | 432 + cups/page.c | 191 + cups/ppd.c | 2291 + cups/ppd.h | 270 + cups/snprintf.c | 306 + cups/string.c | 210 + cups/string.h | 128 + cups/tempfile.c | 208 + cups/testhttp.c | 126 + cups/testlang.c | 96 + cups/testmime.dsp | 102 + cups/testppd.c | 197 + cups/testppd.dsp | 102 + cups/usersys.c | 460 + cups/util.c | 1771 + data/HPGLprolog | 37 + data/Makefile | 104 + data/classified | 277 + data/confidential | 277 + data/iso-8859-1 | 251 + data/iso-8859-10 | 251 + data/iso-8859-13 | 251 + data/iso-8859-14 | 251 + data/iso-8859-15 | 251 + data/iso-8859-2 | 253 + data/iso-8859-3 | 244 + data/iso-8859-4 | 251 + data/iso-8859-5 | 251 + data/iso-8859-6 | 206 + data/iso-8859-7 | 246 + data/iso-8859-8 | 214 + data/iso-8859-9 | 251 + data/koi8-r | 261 + data/koi8-u | 259 + data/psglyphs | 1051 + data/secret | 277 + data/standard | 261 + data/testprint.ps | 522 + data/topsecret | 277 + data/unclassified | 277 + data/utf-8 | 39 + data/windows-1250 | 254 + data/windows-1251 | 258 + data/windows-1252 | 254 + data/windows-1253 | 243 + data/windows-1254 | 252 + data/windows-1255 | 236 + data/windows-1256 | 259 + data/windows-1257 | 247 + data/windows-1258 | 250 + data/windows-874 | 228 + doc/Makefile | 242 + doc/cmp.html | 682 + doc/cmp.pdf | Bin 0 -> 55293 bytes doc/cmp.shtml | 595 + doc/cups.css | 4 + doc/cupsdoc.css | 9 + doc/documentation.html | 85 + doc/figures.sc | Bin 0 -> 75144 bytes doc/fr/Makefile | 190 + doc/fr/cups.css | 4 + doc/fr/cupsdoc.css | 9 + doc/fr/documentation.html | 81 + doc/fr/glossary.shtml | 73 + doc/fr/images/accept-jobs.gif | Bin 0 -> 295 bytes doc/fr/images/add-class.gif | Bin 0 -> 269 bytes doc/fr/images/add-printer.gif | Bin 0 -> 307 bytes doc/fr/images/cancel-job.gif | Bin 0 -> 272 bytes doc/fr/images/cancel-jobs.gif | Bin 0 -> 281 bytes doc/fr/images/cancel.gif | Bin 0 -> 212 bytes doc/fr/images/config-printer.gif | Bin 0 -> 334 bytes doc/fr/images/continue.gif | Bin 0 -> 229 bytes doc/fr/images/delete-class.gif | Bin 0 -> 293 bytes doc/fr/images/delete-printer.gif | Bin 0 -> 330 bytes doc/fr/images/hold-job.gif | Bin 0 -> 269 bytes doc/fr/images/manage-classes.gif | Bin 0 -> 312 bytes doc/fr/images/manage-jobs.gif | Bin 0 -> 316 bytes doc/fr/images/manage-printers.gif | Bin 0 -> 345 bytes doc/fr/images/modify-class.gif | Bin 0 -> 282 bytes doc/fr/images/modify-printer.gif | Bin 0 -> 316 bytes doc/fr/images/navbar.gif | Bin 0 -> 2429 bytes doc/fr/images/print-test-page.gif | Bin 0 -> 316 bytes doc/fr/images/reject-jobs.gif | Bin 0 -> 281 bytes doc/fr/images/release-job.gif | Bin 0 -> 271 bytes doc/fr/images/restart-job.gif | Bin 0 -> 312 bytes doc/fr/images/show-active.gif | Bin 0 -> 302 bytes doc/fr/images/show-completed.gif | Bin 0 -> 343 bytes doc/fr/images/start-class.gif | Bin 0 -> 282 bytes doc/fr/images/start-printer.gif | Bin 0 -> 324 bytes doc/fr/images/stop-class.gif | Bin 0 -> 260 bytes doc/fr/images/stop-printer.gif | Bin 0 -> 307 bytes doc/fr/index.html | 36 + doc/fr/overview.html | 503 + doc/fr/overview.pdf | Bin 0 -> 42834 bytes doc/fr/printing-overview.shtml | 125 + doc/fr/references.shtml | 42 + doc/fr/sam.html | 5229 ++ doc/fr/sam.pdf | Bin 0 -> 262538 bytes doc/fr/sam.shtml | 4607 ++ doc/fr/sum.html | 1770 + doc/fr/sum.pdf | Bin 0 -> 100039 bytes doc/fr/sum.shtml | 1596 + doc/fr/system-overview.shtml | 19 + doc/glossary.shtml | 73 + doc/idd.html | 1088 + doc/idd.pdf | Bin 0 -> 67423 bytes doc/idd.shtml | 1431 + doc/images/accept-jobs.gif | Bin 0 -> 259 bytes doc/images/add-class.gif | Bin 0 -> 242 bytes doc/images/add-printer.gif | Bin 0 -> 252 bytes doc/images/cancel-job.gif | Bin 0 -> 248 bytes doc/images/cancel-jobs.gif | Bin 0 -> 255 bytes doc/images/cancel.gif | Bin 0 -> 210 bytes doc/images/classes.gif | Bin 0 -> 591 bytes doc/images/config-printer.gif | Bin 0 -> 296 bytes doc/images/continue.gif | Bin 0 -> 224 bytes doc/images/cups-block-diagram.gif | Bin 0 -> 11637 bytes doc/images/cups-large.gif | Bin 0 -> 7457 bytes doc/images/cups-medium.gif | Bin 0 -> 3163 bytes doc/images/cups-small.gif | Bin 0 -> 1266 bytes doc/images/delete-class.gif | Bin 0 -> 259 bytes doc/images/delete-printer.gif | Bin 0 -> 267 bytes doc/images/draft.gif | Bin 0 -> 926 bytes doc/images/hold-job.gif | Bin 0 -> 228 bytes doc/images/left.gif | Bin 0 -> 110 bytes doc/images/logo.gif | Bin 0 -> 1958 bytes doc/images/manage-classes.gif | Bin 0 -> 289 bytes doc/images/manage-jobs.gif | Bin 0 -> 266 bytes doc/images/manage-printers.gif | Bin 0 -> 296 bytes doc/images/modify-class.gif | Bin 0 -> 267 bytes doc/images/modify-printer.gif | Bin 0 -> 277 bytes doc/images/navbar.gif | Bin 0 -> 2869 bytes doc/images/navbar.xcf.gz | Bin 0 -> 4253 bytes doc/images/print-test-page.gif | Bin 0 -> 288 bytes doc/images/printer-idle.gif | Bin 0 -> 706 bytes doc/images/printer-processing.gif | Bin 0 -> 805 bytes doc/images/printer-stopped.gif | Bin 0 -> 794 bytes doc/images/reject-jobs.gif | Bin 0 -> 252 bytes doc/images/release-job.gif | Bin 0 -> 255 bytes doc/images/restart-job.gif | Bin 0 -> 249 bytes doc/images/right.gif | Bin 0 -> 145 bytes doc/images/show-active.gif | Bin 0 -> 303 bytes doc/images/show-completed.gif | Bin 0 -> 337 bytes doc/images/start-class.gif | Bin 0 -> 238 bytes doc/images/start-printer.gif | Bin 0 -> 255 bytes doc/images/stop-class.gif | Bin 0 -> 245 bytes doc/images/stop-printer.gif | Bin 0 -> 252 bytes doc/index.html | 36 + doc/ipp.html | 1552 + doc/ipp.pdf | Bin 0 -> 107159 bytes doc/ipp.shtml | 2077 + doc/overview.html | 500 + doc/overview.pdf | Bin 0 -> 37837 bytes doc/printing-overview.shtml | 125 + doc/references.shtml | 43 + doc/sam.html | 6041 ++ doc/sam.pdf | Bin 0 -> 305416 bytes doc/sam.shtml | 5882 ++ doc/sdd.html | 596 + doc/sdd.pdf | Bin 0 -> 64258 bytes doc/sdd.shtml | 564 + doc/spm.html | 8920 +++ doc/spm.pdf | Bin 0 -> 679448 bytes doc/spm.shtml | 10202 ++++ doc/sps.html | 302 + doc/sps.pdf | Bin 0 -> 33900 bytes doc/sps.shtml | 457 + doc/ssr.html | 280 + doc/ssr.pdf | Bin 0 -> 32595 bytes doc/ssr.shtml | 167 + doc/stp.html | 267 + doc/stp.pdf | Bin 0 -> 36056 bytes doc/stp.shtml | 144 + doc/sum.html | 1754 + doc/sum.pdf | Bin 0 -> 100081 bytes doc/sum.shtml | 956 + doc/svd.html | 301 + doc/svd.pdf | Bin 0 -> 38326 bytes doc/svd.shtml | 212 + doc/system-overview.shtml | 19 + doc/translation.html | 610 + doc/translation.pdf | Bin 0 -> 43482 bytes doc/translation.shtml | 734 + filter/.cvsignore | 31 + filter/Dependencies | 75 + filter/Makefile | 263 + filter/common.c | 479 + filter/common.h | 92 + filter/form-main.c | 62 + filter/form-ps.c | 49 + filter/form-tree.c | 624 + filter/form.h | 177 + filter/hpgl-attr.c | 454 + filter/hpgl-char.c | 502 + filter/hpgl-config.c | 643 + filter/hpgl-input.c | 234 + filter/hpgl-main.c | 267 + filter/hpgl-polygon.c | 382 + filter/hpgl-prolog.c | 408 + filter/hpgl-vector.c | 733 + filter/hpgltops.dsp | 130 + filter/hpgltops.h | 235 + filter/image-bmp.c | 512 + filter/image-colorspace.c | 1485 + filter/image-gif.c | 662 + filter/image-jpeg.c | 296 + filter/image-photocd.c | 325 + filter/image-pix.c | 225 + filter/image-png.c | 252 + filter/image-pnm.c | 290 + filter/image-sgi.c | 269 + filter/image-sgi.h | 96 + filter/image-sgilib.c | 859 + filter/image-sun.c | 390 + filter/image-tiff.c | 1720 + filter/image-zoom.c | 329 + filter/image.c | 775 + filter/image.h | 243 + filter/imagetops.c | 915 + filter/imagetoraster.c | 4545 ++ filter/pstops.c | 1671 + filter/pstops.dsp | 107 + filter/raster.c | 254 + filter/raster.h | 263 + filter/rastertodymo.c | 363 + filter/rastertoepson.c | 1137 + filter/rastertohp.c | 808 + filter/testimage.c | 101 + filter/textcommon.c | 1185 + filter/textcommon.h | 122 + filter/texttops.c | 1311 + filter/texttops.dsp | 98 + fonts/Courier | 1494 + fonts/Courier-Bold | 1652 + fonts/Courier-BoldOblique | 1686 + fonts/Courier-Oblique | 1448 + fonts/Makefile | 62 + fonts/Symbol | 1150 + install-sh | 251 + locale/C/cups_C | 135 + locale/Makefile | 77 + locale/be/cups_be | 134 + locale/cs/cups_cs | 135 + locale/de/cups_de | 136 + locale/en/cups_en | 135 + locale/es/cups_es | 135 + locale/fr/cups_fr | 135 + locale/he/cups_he | 135 + locale/it/cups_it | 135 + locale/locale.txt | 32 + locale/ru_RU.cp1251/cups_ru_RU.cp1251 | 134 + locale/ru_RU.koi8r/cups_ru_RU.koi8r | 134 + locale/sv/cups_sv | 135 + locale/translate.c | 259 + locale/uk/cups_uk | 134 + locale/uk_UA.cp1251/cups_uk_UA.cp1251 | 134 + locale/zh_CN/cups_zh_CN | 135 + man/.cvsignore | 7 + man/Makefile | 123 + man/Makefile.common | 84 + man/accept.man | 60 + man/backend.man | 115 + man/classes.conf.man | 72 + man/cups-config.man | 95 + man/cups-lpd.man | 107 + man/cups-polld.man | 46 + man/cupsaddsmb.man | 164 + man/cupsd.conf.man | 359 + man/cupsd.man | 61 + man/enable.man | 67 + man/filter.man | 122 + man/fr/.cvsignore | 7 + man/fr/Makefile | 111 + man/fr/accept.man | 62 + man/fr/backend.man | 113 + man/fr/classes.conf.man | 75 + man/fr/cups-config.man | 98 + man/fr/cups-lpd.man | 94 + man/fr/cups-polld.man | 49 + man/fr/cupsaddsmb.man | 117 + man/fr/cupsd.conf.man | 255 + man/fr/cupsd.man | 49 + man/fr/enable.man | 67 + man/fr/filter.man | 119 + man/fr/lp.man | 163 + man/fr/lpadmin.man | 162 + man/fr/lpc.man | 82 + man/fr/lpinfo.man | 63 + man/fr/lpmove.man | 57 + man/fr/lpoptions.man | 117 + man/fr/lppasswd.man | 63 + man/fr/lpq.man | 59 + man/fr/lpr.man | 106 + man/fr/lprm.man | 56 + man/fr/lpstat.man | 134 + man/fr/mime.convs.man | 59 + man/fr/mime.types.man | 104 + man/fr/printers.conf.man | 75 + man/lp.man | 168 + man/lpadmin.man | 157 + man/lpc.man | 80 + man/lpinfo.man | 60 + man/lpmove.man | 53 + man/lpoptions.man | 128 + man/lppasswd.man | 61 + man/lpq.man | 57 + man/lpr.man | 101 + man/lprm.man | 54 + man/lpstat.man | 139 + man/mime.convs.man | 54 + man/mime.types.man | 98 + man/printers.conf.man | 73 + pdftops/.cvsignore | 1 + pdftops/Annot.cxx | 138 + pdftops/Annot.h | 67 + pdftops/Array.cxx | 53 + pdftops/Array.h | 56 + pdftops/BuiltinFont.cxx | 64 + pdftops/BuiltinFont.h | 55 + pdftops/BuiltinFontTables.cxx | 3366 + pdftops/BuiltinFontTables.h | 23 + pdftops/CMap.cxx | 359 + pdftops/CMap.h | 93 + pdftops/CNS13CMapInfo.h | 47771 +++++++++++++++ pdftops/COPYING | 339 + pdftops/Catalog.cxx | 341 + pdftops/Catalog.h | 85 + pdftops/CharCodeToUnicode.cxx | 390 + pdftops/CharCodeToUnicode.h | 88 + pdftops/CharTypes.h | 24 + pdftops/CompactFontTables.h | 464 + pdftops/Decrypt.cxx | 385 + pdftops/Decrypt.h | 59 + pdftops/Dependencies | 87 + pdftops/Dict.cxx | 90 + pdftops/Dict.h | 75 + pdftops/DisplayFontTable.h | 29 + pdftops/Error.cxx | 37 + pdftops/Error.h | 21 + pdftops/ErrorCodes.h | 24 + pdftops/FontEncoding.cxx | 143 + pdftops/FontEncoding.h | 64 + pdftops/FontEncodingTables.cxx | 1824 + pdftops/FontEncodingTables.h | 20 + pdftops/FontFile.cxx | 3682 ++ pdftops/FontFile.h | 215 + pdftops/FormWidget.h | 67 + pdftops/Function.cxx | 1520 + pdftops/Function.h | 181 + pdftops/GB12CMapInfo.h | 50880 ++++++++++++++++ pdftops/GHash.cxx | 240 + pdftops/GHash.h | 67 + pdftops/GList.cxx | 91 + pdftops/GList.h | 89 + pdftops/GString.cxx | 224 + pdftops/GString.h | 95 + pdftops/Gfx.cxx | 2765 + pdftops/Gfx.h | 252 + pdftops/GfxFont.cxx | 1285 + pdftops/GfxFont.h | 298 + pdftops/GfxState.cxx | 2330 + pdftops/GfxState.h | 957 + pdftops/GlobalParams.cxx | 1065 + pdftops/GlobalParams.h | 273 + pdftops/Japan12CMapInfo.h | 31362 ++++++++++ pdftops/Japan12ToRKSJ.h | 1038 + pdftops/Lexer.cxx | 473 + pdftops/Lexer.h | 75 + pdftops/Link.cxx | 630 + pdftops/Link.h | 334 + pdftops/Makefile | 122 + pdftops/NameToCharCode.cxx | 115 + pdftops/NameToCharCode.h | 40 + pdftops/NameToUnicodeTable.h | 1055 + pdftops/Object.cxx | 223 + pdftops/Object.h | 299 + pdftops/OutputDev.cxx | 102 + pdftops/OutputDev.h | 158 + pdftops/PDFDoc.cxx | 259 + pdftops/PDFDoc.h | 146 + pdftops/PSOutputDev.cxx | 3185 + pdftops/PSOutputDev.h | 228 + pdftops/PSTokenizer.cxx | 133 + pdftops/PSTokenizer.h | 39 + pdftops/Page.cxx | 281 + pdftops/Page.h | 151 + pdftops/Params.cxx | 90 + pdftops/Params.h | 38 + pdftops/Parser.cxx | 214 + pdftops/Parser.h | 58 + pdftops/README | 426 + pdftops/Stream-CCITT.h | 459 + pdftops/Stream.cxx | 3627 ++ pdftops/Stream.h | 800 + pdftops/UTF8.h | 56 + pdftops/UnicodeMap.cxx | 260 + pdftops/UnicodeMap.h | 110 + pdftops/UnicodeMapTables.h | 361 + pdftops/XRef.cxx | 665 + pdftops/XRef.h | 116 + pdftops/config.h | 152 + pdftops/gfile.cxx | 715 + pdftops/gfile.h | 139 + pdftops/gmem.c | 204 + pdftops/gmem.h | 53 + pdftops/gmempp.cxx | 32 + pdftops/gtypes.h | 31 + pdftops/parseargs.c | 190 + pdftops/parseargs.h | 71 + pdftops/pdftops.cxx | 193 + ppd/Makefile | 63 + ppd/deskjet.ppd | 198 + ppd/deskjet2.ppd | 217 + ppd/dymo.ppd | 155 + ppd/epson24.ppd | 138 + ppd/epson9.ppd | 136 + ppd/laserjet.ppd | 200 + ppd/okidat24.ppd | 128 + ppd/okidata9.ppd | 126 + ppd/stcolor.ppd | 132 + ppd/stcolor2.ppd | 132 + ppd/stphoto.ppd | 132 + ppd/stphoto2.ppd | 132 + pstoraster/.cvsignore | 3 + pstoraster/README.pstoraster | 63 + pstoraster/cups.mak | 48 + pstoraster/gdevcups.c | 3644 ++ pstoraster/ghostscript-705.patch | 4563 ++ pstoraster/pstoraster | 52 + pstoraster/pstoraster.convs | 29 + pstoraster/pstoraster.in | 59 + scheduler/.cvsignore | 5 + scheduler/Dependencies | 95 + scheduler/Makefile | 142 + scheduler/auth.c | 1631 + scheduler/auth.h | 139 + scheduler/banners.c | 215 + scheduler/banners.h | 57 + scheduler/cert.c | 292 + scheduler/cert.h | 60 + scheduler/classes.c | 695 + scheduler/classes.h | 43 + scheduler/client.c | 2623 + scheduler/client.h | 105 + scheduler/conf.c | 1894 + scheduler/conf.h | 183 + scheduler/cups-lpd.c | 1293 + scheduler/cups-polld.c | 383 + scheduler/cups.pam | 2 + scheduler/cupsd.dsp | 173 + scheduler/cupsd.h | 177 + scheduler/devices.c | 482 + scheduler/dirsvc.c | 1834 + scheduler/dirsvc.h | 143 + scheduler/filter.c | 320 + scheduler/ipp.c | 6006 ++ scheduler/job.c | 3260 + scheduler/job.h | 108 + scheduler/listen.c | 222 + scheduler/log.c | 445 + scheduler/main.c | 920 + scheduler/mime.c | 600 + scheduler/mime.h | 143 + scheduler/network.c | 476 + scheduler/network.h | 63 + scheduler/ppds.c | 897 + scheduler/printers.c | 2085 + scheduler/printers.h | 119 + scheduler/quotas.c | 235 + scheduler/server.c | 150 + scheduler/testmime.c | 241 + scheduler/testspeed.c | 126 + scheduler/type.c | 1096 + ...-ietf-ipp-finishings-fold-trim-bale-00.txt | 585 + ...aft-ietf-ipp-implementers-guide-v11-02.txt | 5046 ++ standards/draft-ietf-ipp-indp-method-04.txt | 1768 + standards/draft-ietf-ipp-install-02.txt | 1426 + .../draft-ietf-ipp-ldap-printer-schema-04.txt | 1456 + standards/draft-ietf-ipp-not-05.txt | 928 + standards/draft-ietf-ipp-not-over-snmp-04.txt | 9 + standards/draft-ietf-ipp-not-spec-06.txt | 4988 ++ standards/draft-ietf-ipp-notify-get-02.txt | 1711 + standards/draft-ietf-ipp-notify-mailto-03.txt | 1740 + standards/draft-ietf-ipp-notify-poll-02.txt | 9 + standards/draft-ietf-ipp-ops-admin-req-00.txt | 9 + standards/draft-ietf-ipp-ops-set2-02.txt | 9 + standards/draft-ietf-ipp-url-scheme-02.txt | 899 + standards/pwg5100.1.pdf | Bin 0 -> 37359 bytes standards/pwg5100.2.pdf | Bin 0 -> 37360 bytes standards/pwg5100.3.pdf | Bin 0 -> 262279 bytes standards/pwg5100.4.pdf | Bin 0 -> 150078 bytes standards/rfc1179.txt | 787 + standards/rfc1321.txt | 1179 + standards/rfc2246.txt | 4483 ++ standards/rfc2396.txt | 2243 + standards/rfc2487.txt | 451 + standards/rfc2565.txt | 2075 + standards/rfc2566.txt | 9691 +++ standards/rfc2567.txt | 2411 + standards/rfc2568.txt | 563 + standards/rfc2569.txt | 1571 + standards/rfc2595.txt | 843 + standards/rfc2616.txt | 9859 +++ standards/rfc2617.txt | 1907 + standards/rfc2639.txt | 3587 ++ standards/rfc2712.txt | 395 + standards/rfc2817.txt | 731 + standards/rfc2818.txt | 395 + standards/rfc2821.txt | 4427 ++ standards/rfc2822.txt | 2859 + standards/rfc2910.txt | 2579 + standards/rfc2911.txt | 12547 ++++ standards/rfc3380.txt | 3307 + standards/rfc3381.txt | 955 + standards/rfc3382.txt | 2131 + systemv/.cvsignore | 10 + systemv/Dependencies | 26 + systemv/Makefile | 185 + systemv/accept.c | 286 + systemv/cancel.c | 292 + systemv/cupsaddsmb.c | 532 + systemv/lp.c | 662 + systemv/lpadmin.c | 2022 + systemv/lpinfo.c | 454 + systemv/lpmove.c | 235 + systemv/lpoptions.c | 448 + systemv/lppasswd.c | 405 + systemv/lpstat.c | 2118 + templates/Makefile | 107 + templates/add-class.tmpl | 33 + templates/add-printer.tmpl | 33 + templates/admin-op.tmpl | 1 + templates/admin.tmpl | 57 + templates/choose-device.tmpl | 32 + templates/choose-make.tmpl | 35 + templates/choose-members.tmpl | 30 + templates/choose-model.tmpl | 35 + templates/choose-serial.tmpl | 56 + templates/choose-uri.tmpl | 43 + templates/class-added.tmpl | 2 + templates/class-confirm.tmpl | 6 + templates/class-deleted.tmpl | 1 + templates/class-modified.tmpl | 2 + templates/classes.tmpl | 51 + templates/config-printer.tmpl | 6 + templates/config-printer2.tmpl | 2 + templates/error.tmpl | 3 + templates/fr/Makefile | 105 + templates/fr/add-class.tmpl | 33 + templates/fr/add-printer.tmpl | 33 + templates/fr/admin-op.tmpl | 1 + templates/fr/admin.tmpl | 57 + templates/fr/choose-device.tmpl | 32 + templates/fr/choose-make.tmpl | 35 + templates/fr/choose-members.tmpl | 30 + templates/fr/choose-model.tmpl | 35 + templates/fr/choose-serial.tmpl | 56 + templates/fr/choose-uri.tmpl | 43 + templates/fr/class-added.tmpl | 2 + templates/fr/class-confirm.tmpl | 6 + templates/fr/class-deleted.tmpl | 1 + templates/fr/class-modified.tmpl | 2 + templates/fr/classes.tmpl | 51 + templates/fr/config-printer.tmpl | 6 + templates/fr/config-printer2.tmpl | 2 + templates/fr/error.tmpl | 3 + templates/fr/header.tmpl | 23 + templates/fr/job-cancel.tmpl | 1 + templates/fr/job-hold.tmpl | 1 + templates/fr/job-op.tmpl | 1 + templates/fr/job-release.tmpl | 2 + templates/fr/job-restart.tmpl | 1 + templates/fr/jobs.tmpl | 54 + templates/fr/modify-class.tmpl | 34 + templates/fr/modify-printer.tmpl | 36 + templates/fr/option-boolean.tmpl | 7 + templates/fr/option-conflict.tmpl | 7 + templates/fr/option-header.tmpl | 8 + templates/fr/option-pickmany.tmpl | 7 + templates/fr/option-pickone.tmpl | 7 + templates/fr/option-trailer.tmpl | 8 + templates/fr/printer-accept.tmpl | 2 + templates/fr/printer-added.tmpl | 1 + templates/fr/printer-configured.tmpl | 2 + templates/fr/printer-confirm.tmpl | 6 + templates/fr/printer-deleted.tmpl | 1 + templates/fr/printer-modified.tmpl | 1 + templates/fr/printer-purge.tmpl | 1 + templates/fr/printer-reject.tmpl | 1 + templates/fr/printer-start.tmpl | 1 + templates/fr/printer-stop.tmpl | 1 + templates/fr/printers.tmpl | 57 + templates/fr/test-page.tmpl | 2 + templates/fr/trailer.tmpl | 7 + templates/header.tmpl | 23 + templates/job-cancel.tmpl | 1 + templates/job-hold.tmpl | 1 + templates/job-op.tmpl | 1 + templates/job-release.tmpl | 1 + templates/job-restart.tmpl | 1 + templates/jobs.tmpl | 54 + templates/modify-class.tmpl | 34 + templates/modify-printer.tmpl | 36 + templates/option-boolean.tmpl | 7 + templates/option-conflict.tmpl | 7 + templates/option-header.tmpl | 8 + templates/option-pickmany.tmpl | 7 + templates/option-pickone.tmpl | 7 + templates/option-trailer.tmpl | 8 + templates/printer-accept.tmpl | 1 + templates/printer-added.tmpl | 2 + templates/printer-configured.tmpl | 2 + templates/printer-confirm.tmpl | 6 + templates/printer-deleted.tmpl | 1 + templates/printer-modified.tmpl | 2 + templates/printer-purge.tmpl | 1 + templates/printer-reject.tmpl | 1 + templates/printer-start.tmpl | 2 + templates/printer-stop.tmpl | 2 + templates/printers.tmpl | 57 + templates/test-page.tmpl | 2 + templates/trailer.tmpl | 7 + test/.cvsignore | 1 + test/4.1-requests.test | 140 + test/4.2-cups-printer-ops.test | 214 + test/4.3-job-ops.test | 297 + test/5.1-lpadmin.sh | 64 + test/5.2-lpc.sh | 40 + test/5.3-lpq.sh | 40 + test/5.4-lpstat.sh | 40 + test/5.5-lp.sh | 71 + test/5.6-lpr.sh | 71 + test/5.7-lprm.sh | 52 + test/5.8-cancel.sh | 52 + test/5.9-lpinfo.sh | 52 + test/Dependencies | 4 + test/Makefile | 85 + test/create-job-format.test | 56 + test/create-job-sheets.test | 55 + test/create-job-timeout.test | 55 + test/create-job.test | 54 + test/get-devices.test | 21 + test/get-job-attributes.test | 27 + test/get-job-attributes2.test | 29 + test/get-ppds.test | 21 + test/get-printer-attributes.test | 44 + test/ipptest.c | 826 + test/print-job-hold.test | 33 + test/print-job.test | 33 + test/run-stp-tests.sh | 425 + test/set-attrs-hold.test | 180 + test/str-header.html | 35 + test/str-trailer.html | 5 + test/testfile.jpg | Bin 0 -> 598930 bytes test/testfile.pdf | Bin 0 -> 36613 bytes test/testfile.ps | 512 + test/testfile.txt | 60 + test/testhp.ppd | 195 + test/testps.ppd | 192 + visualc/config.h | 247 + visualc/jpeg.dsp | 284 + visualc/libpng.dsp | 149 + visualc/zlib.dsp | 141 + 760 files changed, 471669 insertions(+) create mode 100644 .cvsignore create mode 100644 CHANGES.txt create mode 100644 CREDITS.txt create mode 100644 ENCRYPTION.txt create mode 100644 INSTALL.txt create mode 100644 LICENSE.html create mode 100644 LICENSE.txt create mode 100644 Makedefs.in create mode 100644 Makefile create mode 100644 README.txt create mode 100644 backend/.cvsignore create mode 100644 backend/Dependencies create mode 100644 backend/Makefile create mode 100644 backend/betest.c create mode 100644 backend/ipp.c create mode 100644 backend/lpd.c create mode 100644 backend/parallel.c create mode 100644 backend/scsi-irix.c create mode 100644 backend/scsi-linux.c create mode 100644 backend/scsi.c create mode 100644 backend/serial.c create mode 100644 backend/socket.c create mode 100644 backend/usb.c create mode 100644 berkeley/.cvsignore create mode 100644 berkeley/Dependencies create mode 100644 berkeley/Makefile create mode 100644 berkeley/lpc.c create mode 100644 berkeley/lpq.c create mode 100644 berkeley/lpr.c create mode 100644 berkeley/lprm.c create mode 100644 cgi-bin/.cvsignore create mode 100644 cgi-bin/Dependencies create mode 100644 cgi-bin/Makefile create mode 100644 cgi-bin/admin.c create mode 100644 cgi-bin/cgi.h create mode 100644 cgi-bin/classes.c create mode 100644 cgi-bin/html.c create mode 100644 cgi-bin/ipp-var.c create mode 100644 cgi-bin/ipp-var.h create mode 100644 cgi-bin/jobs.c create mode 100644 cgi-bin/printers.c create mode 100644 cgi-bin/template.c create mode 100644 cgi-bin/var.c create mode 100644 conf/Makefile create mode 100644 conf/classes.conf create mode 100644 conf/client.conf create mode 100644 conf/cupsd.conf.in create mode 100644 conf/mime.convs create mode 100644 conf/mime.types create mode 100644 conf/pam.conf.in create mode 100644 conf/pam.irix create mode 100644 conf/printcap create mode 100644 conf/printers.conf create mode 100644 config-scripts/cups-common.m4 create mode 100644 config-scripts/cups-compiler.m4 create mode 100644 config-scripts/cups-directories.m4 create mode 100644 config-scripts/cups-image.m4 create mode 100644 config-scripts/cups-libtool.m4 create mode 100644 config-scripts/cups-manpages.m4 create mode 100644 config-scripts/cups-network.m4 create mode 100644 config-scripts/cups-openslp.m4 create mode 100644 config-scripts/cups-openssl.m4 create mode 100644 config-scripts/cups-opsys.m4 create mode 100644 config-scripts/cups-pam.m4 create mode 100644 config-scripts/cups-sharedlibs.m4 create mode 100644 config.h.in create mode 100644 configure.in create mode 100755 cups-config.in create mode 100644 cups.dsw create mode 100644 cups.list.in create mode 100644 cups.plist create mode 100755 cups.sh.in create mode 100644 cups.spec create mode 100644 cups.strings create mode 100644 cups/.cvsignore create mode 100644 cups/Dependencies create mode 100644 cups/Makefile create mode 100644 cups/cups.dsp create mode 100644 cups/cups.h create mode 100644 cups/cups_C.h create mode 100644 cups/debug.h create mode 100644 cups/dest.c create mode 100644 cups/emit.c create mode 100644 cups/encode.c create mode 100644 cups/http-addr.c create mode 100644 cups/http-support.c create mode 100644 cups/http.c create mode 100644 cups/http.h create mode 100644 cups/ipp-support.c create mode 100644 cups/ipp.c create mode 100644 cups/ipp.h create mode 100644 cups/language.c create mode 100644 cups/language.h create mode 100644 cups/mark.c create mode 100644 cups/md5.c create mode 100644 cups/md5.h create mode 100644 cups/md5passwd.c create mode 100644 cups/options.c create mode 100644 cups/page.c create mode 100644 cups/ppd.c create mode 100644 cups/ppd.h create mode 100644 cups/snprintf.c create mode 100644 cups/string.c create mode 100644 cups/string.h create mode 100644 cups/tempfile.c create mode 100644 cups/testhttp.c create mode 100644 cups/testlang.c create mode 100644 cups/testmime.dsp create mode 100644 cups/testppd.c create mode 100644 cups/testppd.dsp create mode 100644 cups/usersys.c create mode 100644 cups/util.c create mode 100644 data/HPGLprolog create mode 100644 data/Makefile create mode 100644 data/classified create mode 100644 data/confidential create mode 100644 data/iso-8859-1 create mode 100644 data/iso-8859-10 create mode 100644 data/iso-8859-13 create mode 100644 data/iso-8859-14 create mode 100644 data/iso-8859-15 create mode 100644 data/iso-8859-2 create mode 100644 data/iso-8859-3 create mode 100644 data/iso-8859-4 create mode 100644 data/iso-8859-5 create mode 100644 data/iso-8859-6 create mode 100644 data/iso-8859-7 create mode 100644 data/iso-8859-8 create mode 100644 data/iso-8859-9 create mode 100644 data/koi8-r create mode 100644 data/koi8-u create mode 100644 data/psglyphs create mode 100644 data/secret create mode 100644 data/standard create mode 100644 data/testprint.ps create mode 100644 data/topsecret create mode 100644 data/unclassified create mode 100644 data/utf-8 create mode 100644 data/windows-1250 create mode 100644 data/windows-1251 create mode 100644 data/windows-1252 create mode 100644 data/windows-1253 create mode 100644 data/windows-1254 create mode 100644 data/windows-1255 create mode 100644 data/windows-1256 create mode 100644 data/windows-1257 create mode 100644 data/windows-1258 create mode 100644 data/windows-874 create mode 100644 doc/Makefile create mode 100644 doc/cmp.html create mode 100644 doc/cmp.pdf create mode 100644 doc/cmp.shtml create mode 100644 doc/cups.css create mode 100644 doc/cupsdoc.css create mode 100644 doc/documentation.html create mode 100644 doc/figures.sc create mode 100644 doc/fr/Makefile create mode 100644 doc/fr/cups.css create mode 100644 doc/fr/cupsdoc.css create mode 100644 doc/fr/documentation.html create mode 100644 doc/fr/glossary.shtml create mode 100644 doc/fr/images/accept-jobs.gif create mode 100644 doc/fr/images/add-class.gif create mode 100644 doc/fr/images/add-printer.gif create mode 100644 doc/fr/images/cancel-job.gif create mode 100644 doc/fr/images/cancel-jobs.gif create mode 100644 doc/fr/images/cancel.gif create mode 100644 doc/fr/images/config-printer.gif create mode 100644 doc/fr/images/continue.gif create mode 100644 doc/fr/images/delete-class.gif create mode 100644 doc/fr/images/delete-printer.gif create mode 100644 doc/fr/images/hold-job.gif create mode 100644 doc/fr/images/manage-classes.gif create mode 100644 doc/fr/images/manage-jobs.gif create mode 100644 doc/fr/images/manage-printers.gif create mode 100644 doc/fr/images/modify-class.gif create mode 100644 doc/fr/images/modify-printer.gif create mode 100644 doc/fr/images/navbar.gif create mode 100644 doc/fr/images/print-test-page.gif create mode 100644 doc/fr/images/reject-jobs.gif create mode 100644 doc/fr/images/release-job.gif create mode 100644 doc/fr/images/restart-job.gif create mode 100644 doc/fr/images/show-active.gif create mode 100644 doc/fr/images/show-completed.gif create mode 100644 doc/fr/images/start-class.gif create mode 100644 doc/fr/images/start-printer.gif create mode 100644 doc/fr/images/stop-class.gif create mode 100644 doc/fr/images/stop-printer.gif create mode 100644 doc/fr/index.html create mode 100644 doc/fr/overview.html create mode 100644 doc/fr/overview.pdf create mode 100644 doc/fr/printing-overview.shtml create mode 100644 doc/fr/references.shtml create mode 100644 doc/fr/sam.html create mode 100644 doc/fr/sam.pdf create mode 100644 doc/fr/sam.shtml create mode 100644 doc/fr/sum.html create mode 100644 doc/fr/sum.pdf create mode 100644 doc/fr/sum.shtml create mode 100644 doc/fr/system-overview.shtml create mode 100644 doc/glossary.shtml create mode 100644 doc/idd.html create mode 100644 doc/idd.pdf create mode 100644 doc/idd.shtml create mode 100644 doc/images/accept-jobs.gif create mode 100644 doc/images/add-class.gif create mode 100644 doc/images/add-printer.gif create mode 100644 doc/images/cancel-job.gif create mode 100644 doc/images/cancel-jobs.gif create mode 100644 doc/images/cancel.gif create mode 100644 doc/images/classes.gif create mode 100644 doc/images/config-printer.gif create mode 100644 doc/images/continue.gif create mode 100644 doc/images/cups-block-diagram.gif create mode 100644 doc/images/cups-large.gif create mode 100644 doc/images/cups-medium.gif create mode 100644 doc/images/cups-small.gif create mode 100644 doc/images/delete-class.gif create mode 100644 doc/images/delete-printer.gif create mode 100644 doc/images/draft.gif create mode 100644 doc/images/hold-job.gif create mode 100644 doc/images/left.gif create mode 100644 doc/images/logo.gif create mode 100644 doc/images/manage-classes.gif create mode 100644 doc/images/manage-jobs.gif create mode 100644 doc/images/manage-printers.gif create mode 100644 doc/images/modify-class.gif create mode 100644 doc/images/modify-printer.gif create mode 100644 doc/images/navbar.gif create mode 100644 doc/images/navbar.xcf.gz create mode 100644 doc/images/print-test-page.gif create mode 100644 doc/images/printer-idle.gif create mode 100644 doc/images/printer-processing.gif create mode 100644 doc/images/printer-stopped.gif create mode 100644 doc/images/reject-jobs.gif create mode 100644 doc/images/release-job.gif create mode 100644 doc/images/restart-job.gif create mode 100644 doc/images/right.gif create mode 100644 doc/images/show-active.gif create mode 100644 doc/images/show-completed.gif create mode 100644 doc/images/start-class.gif create mode 100644 doc/images/start-printer.gif create mode 100644 doc/images/stop-class.gif create mode 100644 doc/images/stop-printer.gif create mode 100644 doc/index.html create mode 100644 doc/ipp.html create mode 100644 doc/ipp.pdf create mode 100644 doc/ipp.shtml create mode 100644 doc/overview.html create mode 100644 doc/overview.pdf create mode 100644 doc/printing-overview.shtml create mode 100644 doc/references.shtml create mode 100644 doc/sam.html create mode 100644 doc/sam.pdf create mode 100644 doc/sam.shtml create mode 100644 doc/sdd.html create mode 100644 doc/sdd.pdf create mode 100644 doc/sdd.shtml create mode 100644 doc/spm.html create mode 100644 doc/spm.pdf create mode 100644 doc/spm.shtml create mode 100644 doc/sps.html create mode 100644 doc/sps.pdf create mode 100644 doc/sps.shtml create mode 100644 doc/ssr.html create mode 100644 doc/ssr.pdf create mode 100644 doc/ssr.shtml create mode 100644 doc/stp.html create mode 100644 doc/stp.pdf create mode 100644 doc/stp.shtml create mode 100644 doc/sum.html create mode 100644 doc/sum.pdf create mode 100644 doc/sum.shtml create mode 100644 doc/svd.html create mode 100644 doc/svd.pdf create mode 100644 doc/svd.shtml create mode 100644 doc/system-overview.shtml create mode 100644 doc/translation.html create mode 100644 doc/translation.pdf create mode 100644 doc/translation.shtml create mode 100644 filter/.cvsignore create mode 100644 filter/Dependencies create mode 100644 filter/Makefile create mode 100644 filter/common.c create mode 100644 filter/common.h create mode 100644 filter/form-main.c create mode 100644 filter/form-ps.c create mode 100644 filter/form-tree.c create mode 100644 filter/form.h create mode 100644 filter/hpgl-attr.c create mode 100644 filter/hpgl-char.c create mode 100644 filter/hpgl-config.c create mode 100644 filter/hpgl-input.c create mode 100644 filter/hpgl-main.c create mode 100644 filter/hpgl-polygon.c create mode 100644 filter/hpgl-prolog.c create mode 100644 filter/hpgl-vector.c create mode 100644 filter/hpgltops.dsp create mode 100644 filter/hpgltops.h create mode 100644 filter/image-bmp.c create mode 100644 filter/image-colorspace.c create mode 100644 filter/image-gif.c create mode 100644 filter/image-jpeg.c create mode 100644 filter/image-photocd.c create mode 100644 filter/image-pix.c create mode 100644 filter/image-png.c create mode 100644 filter/image-pnm.c create mode 100644 filter/image-sgi.c create mode 100644 filter/image-sgi.h create mode 100644 filter/image-sgilib.c create mode 100644 filter/image-sun.c create mode 100644 filter/image-tiff.c create mode 100644 filter/image-zoom.c create mode 100644 filter/image.c create mode 100644 filter/image.h create mode 100644 filter/imagetops.c create mode 100644 filter/imagetoraster.c create mode 100644 filter/pstops.c create mode 100644 filter/pstops.dsp create mode 100644 filter/raster.c create mode 100644 filter/raster.h create mode 100644 filter/rastertodymo.c create mode 100644 filter/rastertoepson.c create mode 100644 filter/rastertohp.c create mode 100644 filter/testimage.c create mode 100644 filter/textcommon.c create mode 100644 filter/textcommon.h create mode 100644 filter/texttops.c create mode 100644 filter/texttops.dsp create mode 100644 fonts/Courier create mode 100644 fonts/Courier-Bold create mode 100644 fonts/Courier-BoldOblique create mode 100644 fonts/Courier-Oblique create mode 100644 fonts/Makefile create mode 100644 fonts/Symbol create mode 100755 install-sh create mode 100644 locale/C/cups_C create mode 100644 locale/Makefile create mode 100644 locale/be/cups_be create mode 100644 locale/cs/cups_cs create mode 100644 locale/de/cups_de create mode 100644 locale/en/cups_en create mode 100644 locale/es/cups_es create mode 100644 locale/fr/cups_fr create mode 100644 locale/he/cups_he create mode 100644 locale/it/cups_it create mode 100644 locale/locale.txt create mode 100644 locale/ru_RU.cp1251/cups_ru_RU.cp1251 create mode 100644 locale/ru_RU.koi8r/cups_ru_RU.koi8r create mode 100644 locale/sv/cups_sv create mode 100644 locale/translate.c create mode 100644 locale/uk/cups_uk create mode 100644 locale/uk_UA.cp1251/cups_uk_UA.cp1251 create mode 100644 locale/zh_CN/cups_zh_CN create mode 100644 man/.cvsignore create mode 100644 man/Makefile create mode 100644 man/Makefile.common create mode 100644 man/accept.man create mode 100644 man/backend.man create mode 100644 man/classes.conf.man create mode 100644 man/cups-config.man create mode 100644 man/cups-lpd.man create mode 100644 man/cups-polld.man create mode 100644 man/cupsaddsmb.man create mode 100644 man/cupsd.conf.man create mode 100644 man/cupsd.man create mode 100644 man/enable.man create mode 100644 man/filter.man create mode 100644 man/fr/.cvsignore create mode 100644 man/fr/Makefile create mode 100644 man/fr/accept.man create mode 100644 man/fr/backend.man create mode 100644 man/fr/classes.conf.man create mode 100644 man/fr/cups-config.man create mode 100644 man/fr/cups-lpd.man create mode 100644 man/fr/cups-polld.man create mode 100644 man/fr/cupsaddsmb.man create mode 100644 man/fr/cupsd.conf.man create mode 100644 man/fr/cupsd.man create mode 100644 man/fr/enable.man create mode 100644 man/fr/filter.man create mode 100644 man/fr/lp.man create mode 100644 man/fr/lpadmin.man create mode 100644 man/fr/lpc.man create mode 100644 man/fr/lpinfo.man create mode 100644 man/fr/lpmove.man create mode 100644 man/fr/lpoptions.man create mode 100644 man/fr/lppasswd.man create mode 100644 man/fr/lpq.man create mode 100644 man/fr/lpr.man create mode 100644 man/fr/lprm.man create mode 100644 man/fr/lpstat.man create mode 100644 man/fr/mime.convs.man create mode 100644 man/fr/mime.types.man create mode 100644 man/fr/printers.conf.man create mode 100644 man/lp.man create mode 100644 man/lpadmin.man create mode 100644 man/lpc.man create mode 100644 man/lpinfo.man create mode 100644 man/lpmove.man create mode 100644 man/lpoptions.man create mode 100644 man/lppasswd.man create mode 100644 man/lpq.man create mode 100644 man/lpr.man create mode 100644 man/lprm.man create mode 100644 man/lpstat.man create mode 100644 man/mime.convs.man create mode 100644 man/mime.types.man create mode 100644 man/printers.conf.man create mode 100644 pdftops/.cvsignore create mode 100644 pdftops/Annot.cxx create mode 100644 pdftops/Annot.h create mode 100644 pdftops/Array.cxx create mode 100644 pdftops/Array.h create mode 100644 pdftops/BuiltinFont.cxx create mode 100644 pdftops/BuiltinFont.h create mode 100644 pdftops/BuiltinFontTables.cxx create mode 100644 pdftops/BuiltinFontTables.h create mode 100644 pdftops/CMap.cxx create mode 100644 pdftops/CMap.h create mode 100644 pdftops/CNS13CMapInfo.h create mode 100644 pdftops/COPYING create mode 100644 pdftops/Catalog.cxx create mode 100644 pdftops/Catalog.h create mode 100644 pdftops/CharCodeToUnicode.cxx create mode 100644 pdftops/CharCodeToUnicode.h create mode 100644 pdftops/CharTypes.h create mode 100644 pdftops/CompactFontTables.h create mode 100644 pdftops/Decrypt.cxx create mode 100644 pdftops/Decrypt.h create mode 100644 pdftops/Dependencies create mode 100644 pdftops/Dict.cxx create mode 100644 pdftops/Dict.h create mode 100644 pdftops/DisplayFontTable.h create mode 100644 pdftops/Error.cxx create mode 100644 pdftops/Error.h create mode 100644 pdftops/ErrorCodes.h create mode 100644 pdftops/FontEncoding.cxx create mode 100644 pdftops/FontEncoding.h create mode 100644 pdftops/FontEncodingTables.cxx create mode 100644 pdftops/FontEncodingTables.h create mode 100644 pdftops/FontFile.cxx create mode 100644 pdftops/FontFile.h create mode 100644 pdftops/FormWidget.h create mode 100644 pdftops/Function.cxx create mode 100644 pdftops/Function.h create mode 100644 pdftops/GB12CMapInfo.h create mode 100644 pdftops/GHash.cxx create mode 100644 pdftops/GHash.h create mode 100644 pdftops/GList.cxx create mode 100644 pdftops/GList.h create mode 100644 pdftops/GString.cxx create mode 100644 pdftops/GString.h create mode 100644 pdftops/Gfx.cxx create mode 100644 pdftops/Gfx.h create mode 100644 pdftops/GfxFont.cxx create mode 100644 pdftops/GfxFont.h create mode 100644 pdftops/GfxState.cxx create mode 100644 pdftops/GfxState.h create mode 100644 pdftops/GlobalParams.cxx create mode 100644 pdftops/GlobalParams.h create mode 100644 pdftops/Japan12CMapInfo.h create mode 100644 pdftops/Japan12ToRKSJ.h create mode 100644 pdftops/Lexer.cxx create mode 100644 pdftops/Lexer.h create mode 100644 pdftops/Link.cxx create mode 100644 pdftops/Link.h create mode 100644 pdftops/Makefile create mode 100644 pdftops/NameToCharCode.cxx create mode 100644 pdftops/NameToCharCode.h create mode 100644 pdftops/NameToUnicodeTable.h create mode 100644 pdftops/Object.cxx create mode 100644 pdftops/Object.h create mode 100644 pdftops/OutputDev.cxx create mode 100644 pdftops/OutputDev.h create mode 100644 pdftops/PDFDoc.cxx create mode 100644 pdftops/PDFDoc.h create mode 100644 pdftops/PSOutputDev.cxx create mode 100644 pdftops/PSOutputDev.h create mode 100644 pdftops/PSTokenizer.cxx create mode 100644 pdftops/PSTokenizer.h create mode 100644 pdftops/Page.cxx create mode 100644 pdftops/Page.h create mode 100644 pdftops/Params.cxx create mode 100644 pdftops/Params.h create mode 100644 pdftops/Parser.cxx create mode 100644 pdftops/Parser.h create mode 100644 pdftops/README create mode 100644 pdftops/Stream-CCITT.h create mode 100644 pdftops/Stream.cxx create mode 100644 pdftops/Stream.h create mode 100644 pdftops/UTF8.h create mode 100644 pdftops/UnicodeMap.cxx create mode 100644 pdftops/UnicodeMap.h create mode 100644 pdftops/UnicodeMapTables.h create mode 100644 pdftops/XRef.cxx create mode 100644 pdftops/XRef.h create mode 100644 pdftops/config.h create mode 100644 pdftops/gfile.cxx create mode 100644 pdftops/gfile.h create mode 100644 pdftops/gmem.c create mode 100644 pdftops/gmem.h create mode 100644 pdftops/gmempp.cxx create mode 100644 pdftops/gtypes.h create mode 100644 pdftops/parseargs.c create mode 100644 pdftops/parseargs.h create mode 100644 pdftops/pdftops.cxx create mode 100644 ppd/Makefile create mode 100644 ppd/deskjet.ppd create mode 100644 ppd/deskjet2.ppd create mode 100644 ppd/dymo.ppd create mode 100644 ppd/epson24.ppd create mode 100644 ppd/epson9.ppd create mode 100644 ppd/laserjet.ppd create mode 100644 ppd/okidat24.ppd create mode 100644 ppd/okidata9.ppd create mode 100644 ppd/stcolor.ppd create mode 100644 ppd/stcolor2.ppd create mode 100644 ppd/stphoto.ppd create mode 100644 ppd/stphoto2.ppd create mode 100644 pstoraster/.cvsignore create mode 100644 pstoraster/README.pstoraster create mode 100644 pstoraster/cups.mak create mode 100644 pstoraster/gdevcups.c create mode 100644 pstoraster/ghostscript-705.patch create mode 100755 pstoraster/pstoraster create mode 100644 pstoraster/pstoraster.convs create mode 100755 pstoraster/pstoraster.in create mode 100644 scheduler/.cvsignore create mode 100644 scheduler/Dependencies create mode 100644 scheduler/Makefile create mode 100644 scheduler/auth.c create mode 100644 scheduler/auth.h create mode 100644 scheduler/banners.c create mode 100644 scheduler/banners.h create mode 100644 scheduler/cert.c create mode 100644 scheduler/cert.h create mode 100644 scheduler/classes.c create mode 100644 scheduler/classes.h create mode 100644 scheduler/client.c create mode 100644 scheduler/client.h create mode 100644 scheduler/conf.c create mode 100644 scheduler/conf.h create mode 100644 scheduler/cups-lpd.c create mode 100644 scheduler/cups-polld.c create mode 100644 scheduler/cups.pam create mode 100644 scheduler/cupsd.dsp create mode 100644 scheduler/cupsd.h create mode 100644 scheduler/devices.c create mode 100644 scheduler/dirsvc.c create mode 100644 scheduler/dirsvc.h create mode 100644 scheduler/filter.c create mode 100644 scheduler/ipp.c create mode 100644 scheduler/job.c create mode 100644 scheduler/job.h create mode 100644 scheduler/listen.c create mode 100644 scheduler/log.c create mode 100644 scheduler/main.c create mode 100644 scheduler/mime.c create mode 100644 scheduler/mime.h create mode 100644 scheduler/network.c create mode 100644 scheduler/network.h create mode 100644 scheduler/ppds.c create mode 100644 scheduler/printers.c create mode 100644 scheduler/printers.h create mode 100644 scheduler/quotas.c create mode 100644 scheduler/server.c create mode 100644 scheduler/testmime.c create mode 100644 scheduler/testspeed.c create mode 100644 scheduler/type.c create mode 100644 standards/draft-ietf-ipp-finishings-fold-trim-bale-00.txt create mode 100644 standards/draft-ietf-ipp-implementers-guide-v11-02.txt create mode 100644 standards/draft-ietf-ipp-indp-method-04.txt create mode 100644 standards/draft-ietf-ipp-install-02.txt create mode 100644 standards/draft-ietf-ipp-ldap-printer-schema-04.txt create mode 100644 standards/draft-ietf-ipp-not-05.txt create mode 100644 standards/draft-ietf-ipp-not-over-snmp-04.txt create mode 100644 standards/draft-ietf-ipp-not-spec-06.txt create mode 100644 standards/draft-ietf-ipp-notify-get-02.txt create mode 100644 standards/draft-ietf-ipp-notify-mailto-03.txt create mode 100644 standards/draft-ietf-ipp-notify-poll-02.txt create mode 100644 standards/draft-ietf-ipp-ops-admin-req-00.txt create mode 100644 standards/draft-ietf-ipp-ops-set2-02.txt create mode 100644 standards/draft-ietf-ipp-url-scheme-02.txt create mode 100644 standards/pwg5100.1.pdf create mode 100644 standards/pwg5100.2.pdf create mode 100644 standards/pwg5100.3.pdf create mode 100644 standards/pwg5100.4.pdf create mode 100644 standards/rfc1179.txt create mode 100644 standards/rfc1321.txt create mode 100644 standards/rfc2246.txt create mode 100644 standards/rfc2396.txt create mode 100644 standards/rfc2487.txt create mode 100644 standards/rfc2565.txt create mode 100644 standards/rfc2566.txt create mode 100644 standards/rfc2567.txt create mode 100644 standards/rfc2568.txt create mode 100644 standards/rfc2569.txt create mode 100644 standards/rfc2595.txt create mode 100644 standards/rfc2616.txt create mode 100644 standards/rfc2617.txt create mode 100644 standards/rfc2639.txt create mode 100644 standards/rfc2712.txt create mode 100644 standards/rfc2817.txt create mode 100644 standards/rfc2818.txt create mode 100644 standards/rfc2821.txt create mode 100644 standards/rfc2822.txt create mode 100644 standards/rfc2910.txt create mode 100644 standards/rfc2911.txt create mode 100644 standards/rfc3380.txt create mode 100644 standards/rfc3381.txt create mode 100644 standards/rfc3382.txt create mode 100644 systemv/.cvsignore create mode 100644 systemv/Dependencies create mode 100644 systemv/Makefile create mode 100644 systemv/accept.c create mode 100644 systemv/cancel.c create mode 100644 systemv/cupsaddsmb.c create mode 100644 systemv/lp.c create mode 100644 systemv/lpadmin.c create mode 100644 systemv/lpinfo.c create mode 100644 systemv/lpmove.c create mode 100644 systemv/lpoptions.c create mode 100644 systemv/lppasswd.c create mode 100644 systemv/lpstat.c create mode 100644 templates/Makefile create mode 100644 templates/add-class.tmpl create mode 100644 templates/add-printer.tmpl create mode 100644 templates/admin-op.tmpl create mode 100644 templates/admin.tmpl create mode 100644 templates/choose-device.tmpl create mode 100644 templates/choose-make.tmpl create mode 100644 templates/choose-members.tmpl create mode 100644 templates/choose-model.tmpl create mode 100644 templates/choose-serial.tmpl create mode 100644 templates/choose-uri.tmpl create mode 100644 templates/class-added.tmpl create mode 100644 templates/class-confirm.tmpl create mode 100644 templates/class-deleted.tmpl create mode 100644 templates/class-modified.tmpl create mode 100644 templates/classes.tmpl create mode 100644 templates/config-printer.tmpl create mode 100644 templates/config-printer2.tmpl create mode 100644 templates/error.tmpl create mode 100644 templates/fr/Makefile create mode 100644 templates/fr/add-class.tmpl create mode 100644 templates/fr/add-printer.tmpl create mode 100644 templates/fr/admin-op.tmpl create mode 100644 templates/fr/admin.tmpl create mode 100644 templates/fr/choose-device.tmpl create mode 100644 templates/fr/choose-make.tmpl create mode 100644 templates/fr/choose-members.tmpl create mode 100644 templates/fr/choose-model.tmpl create mode 100644 templates/fr/choose-serial.tmpl create mode 100644 templates/fr/choose-uri.tmpl create mode 100644 templates/fr/class-added.tmpl create mode 100644 templates/fr/class-confirm.tmpl create mode 100644 templates/fr/class-deleted.tmpl create mode 100644 templates/fr/class-modified.tmpl create mode 100644 templates/fr/classes.tmpl create mode 100644 templates/fr/config-printer.tmpl create mode 100644 templates/fr/config-printer2.tmpl create mode 100644 templates/fr/error.tmpl create mode 100644 templates/fr/header.tmpl create mode 100644 templates/fr/job-cancel.tmpl create mode 100644 templates/fr/job-hold.tmpl create mode 100644 templates/fr/job-op.tmpl create mode 100644 templates/fr/job-release.tmpl create mode 100644 templates/fr/job-restart.tmpl create mode 100644 templates/fr/jobs.tmpl create mode 100644 templates/fr/modify-class.tmpl create mode 100644 templates/fr/modify-printer.tmpl create mode 100644 templates/fr/option-boolean.tmpl create mode 100644 templates/fr/option-conflict.tmpl create mode 100644 templates/fr/option-header.tmpl create mode 100644 templates/fr/option-pickmany.tmpl create mode 100644 templates/fr/option-pickone.tmpl create mode 100644 templates/fr/option-trailer.tmpl create mode 100644 templates/fr/printer-accept.tmpl create mode 100644 templates/fr/printer-added.tmpl create mode 100644 templates/fr/printer-configured.tmpl create mode 100644 templates/fr/printer-confirm.tmpl create mode 100644 templates/fr/printer-deleted.tmpl create mode 100644 templates/fr/printer-modified.tmpl create mode 100644 templates/fr/printer-purge.tmpl create mode 100644 templates/fr/printer-reject.tmpl create mode 100644 templates/fr/printer-start.tmpl create mode 100644 templates/fr/printer-stop.tmpl create mode 100644 templates/fr/printers.tmpl create mode 100644 templates/fr/test-page.tmpl create mode 100644 templates/fr/trailer.tmpl create mode 100644 templates/header.tmpl create mode 100644 templates/job-cancel.tmpl create mode 100644 templates/job-hold.tmpl create mode 100644 templates/job-op.tmpl create mode 100644 templates/job-release.tmpl create mode 100644 templates/job-restart.tmpl create mode 100644 templates/jobs.tmpl create mode 100644 templates/modify-class.tmpl create mode 100644 templates/modify-printer.tmpl create mode 100644 templates/option-boolean.tmpl create mode 100644 templates/option-conflict.tmpl create mode 100644 templates/option-header.tmpl create mode 100644 templates/option-pickmany.tmpl create mode 100644 templates/option-pickone.tmpl create mode 100644 templates/option-trailer.tmpl create mode 100644 templates/printer-accept.tmpl create mode 100644 templates/printer-added.tmpl create mode 100644 templates/printer-configured.tmpl create mode 100644 templates/printer-confirm.tmpl create mode 100644 templates/printer-deleted.tmpl create mode 100644 templates/printer-modified.tmpl create mode 100644 templates/printer-purge.tmpl create mode 100644 templates/printer-reject.tmpl create mode 100644 templates/printer-start.tmpl create mode 100644 templates/printer-stop.tmpl create mode 100644 templates/printers.tmpl create mode 100644 templates/test-page.tmpl create mode 100644 templates/trailer.tmpl create mode 100644 test/.cvsignore create mode 100644 test/4.1-requests.test create mode 100644 test/4.2-cups-printer-ops.test create mode 100644 test/4.3-job-ops.test create mode 100755 test/5.1-lpadmin.sh create mode 100755 test/5.2-lpc.sh create mode 100755 test/5.3-lpq.sh create mode 100755 test/5.4-lpstat.sh create mode 100755 test/5.5-lp.sh create mode 100755 test/5.6-lpr.sh create mode 100755 test/5.7-lprm.sh create mode 100755 test/5.8-cancel.sh create mode 100755 test/5.9-lpinfo.sh create mode 100644 test/Dependencies create mode 100644 test/Makefile create mode 100644 test/create-job-format.test create mode 100644 test/create-job-sheets.test create mode 100644 test/create-job-timeout.test create mode 100644 test/create-job.test create mode 100644 test/get-devices.test create mode 100644 test/get-job-attributes.test create mode 100644 test/get-job-attributes2.test create mode 100644 test/get-ppds.test create mode 100644 test/get-printer-attributes.test create mode 100644 test/ipptest.c create mode 100644 test/print-job-hold.test create mode 100644 test/print-job.test create mode 100755 test/run-stp-tests.sh create mode 100644 test/set-attrs-hold.test create mode 100644 test/str-header.html create mode 100644 test/str-trailer.html create mode 100644 test/testfile.jpg create mode 100644 test/testfile.pdf create mode 100644 test/testfile.ps create mode 100644 test/testfile.txt create mode 100644 test/testhp.ppd create mode 100644 test/testps.ppd create mode 100644 visualc/config.h create mode 100644 visualc/jpeg.dsp create mode 100644 visualc/libpng.dsp create mode 100644 visualc/zlib.dsp diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000000..c0b24b8fd2 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,33 @@ +config.cache +config.h +config.log +config.status +configure +cups-config +cups.list +cups.sh +make.log +printpro.common +printpro.version +Makedefs +aix-4.3-powerpc +darwin-5.2-powerpc +darwin-5.3-powerpc +darwin-6.0-powerpc +freebsd-4.5-intel +hpux-10.20-hppa +hpux-11.00-hppa +irix-5.3-mips +irix-6.5-mips +linux-2.0-intel +linux-2.2-intel +linux-2.4-intel +solaris-2.5-intel +solaris-2.5-sparc +solaris-2.7-intel +solaris-2.7-sparc +solaris-2.8-intel +solaris-2.8-sparc +solaris-2.9-intel +solaris-2.9-sparc +tru64-4.0-alpha diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000000..8a1f227cb2 --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1,2528 @@ +CHANGES.txt - 11/27/2002 +------------------------ + +CHANGES IN CUPS V1.1.17 + + - The "manual_copies" option did not work when the LPD + backend had to retry a print job. + - The image filters did not convert GIF images properly. + - The RunAsUser option was incompatible with the new + daemon-mode code in 1.1.16. + - Fixed a problem with the Set-Job-Attributes and + PostScript job ticket code in the scheduler - the + "last" attribute pointer was never updated, which + could cause the scheduler to crash when applying job + ticket data. + - Fixed a problem in the scheduler that caused it to + continue processing HTTP requests on a connection + after it was shutdown. + - The scheduler now allows accounts authenticated via + PAM to not have a corresponding UNIX account, but + group membership still requires the account name to be + listed in the UNIX group file(s)... + - The scheduler used a fixed-size (16k) buffer for + encoding job options for filters; it now dynamically + allocates and expands the buffer as needed depending + on the options that are sent in a job. + - The pdftops filter didn't support all of the MacOS + characters for MacRoman encoded fonts. + - The cupsEncodeOptions() and cupsParseOptions() + functions now conform to the grammer defined by the + current draft of the PAPI specification. The main + difference is that option=yes and option=no are no + longer treated as boolean options. + - The IPP backend didn't honor the encryption settings + in /etc/cups/client.conf. + - Fixed a potential bug in the HTTP code which was + caused by servers sending the status line and + newline(s) in separate packets. + - User-defined classification strings are now printed + verbatim - previously the classification box would be + empty. + - Re-added Spanish to the list of PPD languages that + CUPS supports. + - CUPS API library user and temp file updates for + Windows. + - The image filters did not properly handle grayscale + printing of Sun Raster images. + - The scheduler never reset the NumJobs variable before + loading the job list (previously this only happened on + a full start, so the problem was never apparent...) + - The HTTP and IPP read/write code didn't handle EINTR + (interrupted system call) errors. + - When under high load, the scheduler could abort due to + the wrong errno value after a select() call. This was + caused by the child signal handler. + - Added new load tests to the test target to verify that + cupsd can handle hundreds of simultaneous jobs without + error. + - The Solaris USB backend now supports the new device + URI syntax. + - The ppdOpen*() functions now reset the numeric locale + settings while loading a PPD file. + - Fixed the libtool build rules. + - The manpage make rules didn't use $(MAKE) and + $(MFLAGS) for the language subdirectories. + - Now set the LC_TIME locale category to get the + properly localized time string. + - Fixed a problem in the scheduler that would cause the + web interface problems when adding, modifying, or + configuring a printer or class. + - The backends now ignore SIGPIPE so that failed job + filters will not stop a print queue. + - The lpstat command did not allow for destination lists + ("lpstat -v printer1,printer2") + - Fixed parsing of long filter status messages in the + scheduler. + - Added some startup performance enhancements to the + scheduler so that the printer object information is + regenerated fewer times and the MIME type database is + not filled with lots of empty filters for raw/direct + queues. + - The LPD backend now sends the job title as the print + filename. + - Added support for variable sizes in the EPSON dot + matrix printer drivers. This allows for pages as + short as 1/2" (1 row of labels) and does not do an + automatic form feed. + - French translation updates. + - The filters did not quote the page label string when + embedding it in PostScript output. + - The serial backend now enumerates serial ports under + MacOS X. + - The pdftops filter contained font rasterizer code that + wasn't being used and that depended on X11. This code + has been removed. + + +CHANGES IN CUPS V1.1.16 + + - The cancel and lprm commands now both display an error + message and return a non-zero exit status if an + attempt is made to cancel a job on a non-existent + printer. + - The lpoptions command incorrectly complained if a + request to delete a non-existent printer was made. + - If the client.conf file defines an alternate server + name, the "configure printer" action in the web + interface might not work. + - The lpstat command now supports a "-W" option so that + you can display completed jobs as well as + not-completed (pending) jobs. + - The lp and lpr commands did not return an error when + one or more files in a set of files for printing could + not be printed. + - The lp, lpadmin, and lpstat commands now consistently + return with a non-zero exit status when an error + occurs. + - The scheduler would not accept print jobs sent to a + stopped remote printer. + - The texttops filter incorrectly converted the page + numbers in the prettyprint header to double-byte + characters when printing a non-Unicode text file. This + caused an extra space to appear between each digit in + the page number. + - The scheduler did not use a case-insensitive + comparison when adding filters for a printer. + - Upgraded the pdftops filter to Xpdf 1.01. + - The scheduler no longer passes the page-border and + number-up-layout attributes to filters when printing + banner pages. + - The LPD backend now uses a 30-second timeout when + sending commands and control files, and a 30-second + timeout when retrieving responses from an LPD server. + If a timeout occurs, it retries indefinitely. This + helps to make LPD printing over VPNs work more + reliably. + - The USB backend now supports device URIs based on the + printer serial number and/or model number under Linux. + This avoids the "wrong device filename" problem when + using more than one USB printer. + - Now just shutdown the receiving end of a client + connection when sending an error that requires the + server to disconnect from the client afterwards. This + fixes a problem when doing remote administration with + encryption enabled. + - The scheduler did not send a printer-state-message + attribute if the string was empty; it now always sends + this attribute. This caused the printer message to be + displayed for other printers in the web interface. + - The LPD backend now supports a "manual_copies" option, + e.g.: "lpd://server/queue?manual_copies=no", in order + to handle copies for raw jobs to printers that don't + implement the LPD protocol properly... + - The "mirror" option was not being handled by the + PostScript or image filters. + - Updated the cupsaddsmb command to support the new CUPS + driver for Windows NT/2k/XP. + - Filter status lines longer than 1023 characters could + cause the scheduler to get into an infinite loop. + - The scheduler didn't reset the job state to pending + when modifying an active printer. + - Now limit the maximum number of recursion steps when + searching for a filter for a job, in case a user + defines a circular filter rule. + - The PostScript filter would embed an invalid + requirements comment in some cases. + - Added support for embedded job tickets in PostScript + files. + - The PostScript filter now detects EPS files and should + better handle printing EPS files. + - The cancel command now ignores a trailing destination + name when cancelling a specific job ID (Solaris + compatibility). + - The scheduler now rejects jobs with copies outside the + range of 1 to MaxCopies, inclusive. + - Added new MaxCopies directive to set the maximum + number of copies that a user can request. + - The scheduler didn't block signals while it processed + others and when it forked processes. + - The scheduler checked for new jobs to print when + stopping a job. This caused jobs to restart before a + shutdown. + - Updated the CUPS startup script to better support + different timezones and to support the RedHat/Mandrake + init script functions, if available. + - The scheduler did not properly handle backslashes in + banner files; it incorrectly assumed that "\c" should + always be replaced by "c", instead of only looking for + "\{" and replacing it by "{". + - The texttops filter didn't handle prettyprint=no. + - The text and HP-GL/2 filters didn't check for other + common duplex option names like cupsMarkOptions() did. + - "lpoptions -x printer" no longer clears the "default + printer" status of the printer. + - cupsTempFd() now stops trying to create a temporary + file after 1000 tries, and aborts on any error other + than EEXIST. This should prevent lp/lpr hangs due to + a bad or missing temporary directory. + - The lpadmin command did not send the right URI to the + scheduler when setting options on classes. This + caused a client-error-bad-request error. + - The CUPS API convenience functions would attempt to + connect to the remote server name in a + "printer@server" printer name instead of dealing with + the default (usually local) server. Aside from + causing user confusion, the remote server name might + not be resolved properly, causing further problems. + - "lp -q" would cause the "lp" command to segfault, as + the program would try to print the option letter that + caused the error using the wrong index into the + command-line; bugfix from Debian. + - Fixed a minor inconsistancy in the encoding of boolean + attributes from printer options in + cupsEncodeOptions(). + - Added a FilterNice directive which sets the priority + of job filter processes that are run by the scheduler. + - Added Solaris x86 USB printer support. + - The USB backend now reports both the ulpt and unlpt + devices under *BSD. + - The "lpstat -o" command would truncate the + "printer-jobid" string if it was longer than 21 + characters. + - The PJL-based MIME type rules now look in the first + 1024 bytes instead of just the first 512 bytes to find + the language mode. + - The image file types are now listed explicitly in the + mime.convs file so that additional image file formats + do not use the standard CUPS image filters by default. + - Updated the Software Programmers Manual to include + all of the CUPS API functions. + - ppdOpen*() no longer sorts choices for an option. + - The web interface now enforces constraints in PPD + files when configuring a printer. + - When stopping a printer, the scheduler didn't set the + printer state before stopping the current job. + - The cupsaddsmb utility now lists all data files for + Win9x and WinMe clients when installing that Windows + driver. + - Jobs submitted to a class now bounce immediately to + the next available printer rather than waiting until + that printer is available. + - Filters and backends now also get the CLASS + environment variable set when a job is printed to a + printer class instead of a normal printer. + - Added French translations of the web interface, CUPS + Overview, Software Administrators Manual, and Software + Users Manual contributed by Marian REYT-LLABRES. + - Added several "hint" messages for common configuration + problems that are stored in the error_log file. + - httpSeparate() now unquotes %xx characters in the + username:password field of a URI. + - When starting the scheduler in daemon mode, the parent + process now waits for the child to signal it is ready + to accept connections. + - Added -F option to cupsd to run cupsd in the + foreground but detach from the controlling terminal + and current directory. + - The scheduler did not reload jobs when receiving a HUP + signal; this would cause problems since the pointers + into the file type database would no longer be valid + for existing jobs. + - The scheduler did not save the network interface list + update time, thus no caching of the network data was + actually provided. + - Updated the SuSE PAM configuration file. + - The LPD backend now supports a "reserve" option and no + longer reserves a priviledged port by default. + - The cupsaddsmb command now continues past printers + that do not have a PPD file to export. + - The lpstat command didn't treat printer names as + case-insensitive. + - The lpstat command now reports the printer location + attribute with "lpstat -l -p". + - Fixed a bug in the vsnprintf() emulation function, + which was used on old versions of HP-UX, IRIX, and + Solaris. + - The number-up option was incorrectly being used when + printing banner pages. + - Added support for Greek and Slovak PPD files. + - CUPS now supports printer names containing any + printable character, e.g. "123-abc", "foo-bar", etc. + - The null filter was not supported in mime.convs due to + a bug in the filter validation code. + - Changes in the default printer and printer attributes + were not always reflected in the generated printcap + file. + - Implicit classes did not inherit the location or + description from member printers. + - The httpGetHostByName() function did not handle + hostnames that started with a number. + - Updated the filters to use the %cupsRotation comment + instead of %%Orientation to auto-rotate pages, since + the use of %%Orientation is inconsistent. + - Added the RootCertDuration directive to control how + often the root authentication certificate is updated. + - Increased the size of the IPP write buffer to 32k to + allow for larger attribute values and to provide more + efficient output of large numbers of attributes. + - The polling daemon now retries the initial connection + to the remote server; this fixes a problem when the + remote server is unavailable when the scheduler starts + up... + - The scheduler didn't validate Digest users against the + system group(s), so Digest and BasicDigest + authentication didn't work for administration + operations. + - The scheduler now passes the SHLIB_PATH environment + variable to child processes (HP-UX shared libraries) + - The scheduler now maps accesses from the loopback + interface to "localhost". + - The cups-lpd mini-daemon sent a status code byte in + response to queue state commands, but those commands + only return textual data. + + +CHANGES IN CUPS V1.1.15-1 + + - The lpc and lprm sources didn't include the CUPS + string function header, which is required on systems + that don't have their own snprintf() function. + - The French manpage Makefile tried to install the + language subdirectories when it (obviously) didn't + have to. + + +CHANGES IN CUPS V1.1.15 + + - Updated the CUPS license agreement for the new MacOS + and OpenSSL license exceptions. + - The printer-info attribute now defaults to the printer + name if no value has been set. + - ppdOpen() and friends now add an "Auto" InputSlot + option if none is provided to automatically select the + correct tray. + - Updated the ppdEmit() and ppdEmitFd() functions to + (re)mark the correct PageSize or PageRegion option + depending on the selected ManualFeed or InputSlot + options. + - ppdEmitFd() didn't handle custom page sizes. + - Darwin uses instead of + . + - The jobs.cgi web interface now handles all job + operations, allowing the administrator to allow "job + administrators" or operators to manage jobs (but not + queues) on the server. + - The cupsDoFileRequest() function now checks if the + filename passed into the function is a directory, and + returns the IPP_NOT_POSSIBLE error if so. + - New SCSI printer backend. + - Cleaned up handling of locales with trailing character + set definitions. + - Fixed handling of invalid PPD attributes inside + OpenUI/CloseUI. + - Fixed a problem with SSL and the job, printer, and + admin CGIs on ports other than 443. + - The scheduler didn't handle AuthClass properly. + - Added French translation of man pages. + - Updated the text filter to support the const_cast, + dynamic_cast, and static_cast keywords in ISO C++. + - Now use strlcat() and strlcpy() (or emulation + functions) for easier string/buffer protection. + - The auto-generated printcap/printers.conf files now + have a small comment header explaining where the file + comes from... + - The PostScript filter now supports 6, 9, and 16-up + output, as well as new page-border and + number-up-layout options. + - The lpoptions command didn't set options properly when + using the default printer. + - Added ConfigFilePerm and LogFilePerm directives. + - Increased maximum size of MIME types to IPP_MAX_NAME + to allow for longer printer names. + - No longer create remote printers when loading job + history data. + - The printer-make-and-model attribute wasn't set when + the PPD file didn't contain a NickName attribute. + - Now handle PPD files with translation strings longer + than 80 bytes - they are truncated if they go over... + - The scheduler didn't handle signals until after it + loaded the configuration files the first time; this + caused problems on some installations that would + restart the scheduler as the system booted into run + level 3. + - Now throttle broadcasts like we do for polling. + - Fixed a bug in the reading of PPD files using CR's + instead of CR LF's or LF's. + - The scheduler would crash if cupsd.conf contained a + BrowseProtocols line with no protocols listed. + - The HTML job operation templates now link back to the + destination printer or class. + - The serial backend now detects USB serial devices. + - The LPD mini-daemon (cups-lpd) now passes the + job-originating-host-name attribute to the scheduler + (cupsd). + - Updated the IPP backend to reconnect after downgrading + from IPP/1.1 to 1.0, and when sending requests to HP + JetDirect interfaces that don't support HTTP + Keep-Alive like they should. + - Now pass NLSPATH and DYLD_LIBRARY_PATH environment + variables, if defined, to CGI and job processes. + - Removed the pstoraster filter (based on GNU + Ghostscript 5.50) and now provide the raster "driver" + and patch file necessary to use the current GNU + Ghostscript 7.05 release. + - Removed unnecessary fonts and updated the Courier and + Symbol fonts to the latest versions to better support + non-ISOLatin1 text. + - The text filter now always embeds the Courier and + Symbol fonts to ensure that they contain the full set + of glyphs. + - The lp and lpr commands now only override the SIGINT + handler if it is not being ignored (patch from Robert + Ambrose for some interactive software that catches + SIGINT and will gracefully cancel the print...) + - The PostScript image filter (imagetops) now supports + printing CMYK images using the CMYK colorspace. + - The image filters now support CMYK JPEG files, and + correctly handles the inverted files from Photoshop + (which seems to save RGBW data, not CMYK...) + - Added a "check" target to the top-level makefile to + conform with GNU standards (same as "test"). + - The IPP code didn't always map the POSIX locale "C" to + the proper IPP language code. + - The cupsaddsmb program was updated to use the + setdriver command instead of addprinter. + - Banner pages were not handled properly for implicit + classes. + - When tunneling to a remote system using SSH, the + printer URIs for local printers on the remote system + did not reflect the correct port number. + - The Allow, Deny, BrowseAllow, BrowseDeny, and + BrowseAddress directives now support the network + interface names "@LOCAL" and "@IF(name)" for access + control and browsing based on the current interface + addresses instead of fixed names or IP addresses. + - The texttops filter did not properly recognize the + "nowrap" (wrap=false) option. + - The InstallableOptions group name in a PPD file is now + translated separately (CUPS_MSG_OPTIONS_INSTALLED) so + that UIs can accurately detect the presence of this + group. + - The scheduler no longer keeps job history data for + remote printers on the client (just on the server.) + - The parallel and USB backends now retry if the backend + detects that the printer is not connected to the + system (rather than stopping the queue...) + - The network backends now retry if the backend detects + that the printer is not connected to the network or is + unreachable (rather than stopping the queue...) + - The cupsGetDests() function no longer lists options + and instances for printers that no longer exist. + - The scheduler now converts the document language to + the correct LANG string. + - The cupsaddsmb program now supports alternative CUPS + and SAMBA server names. + - The PostScript filter now supports the Orientation + comment and rotates the page as needed automatically. + - Revamped the makefiles slightly to use automatically + generated dependencies. + - Build fixes for OS X. + - The TIFF reading code depended on the newest version + of libtiff; now conditionally compile that portion of + the loader. + - The PPD code now decodes all JCL options in the + JCLSetup group, not just those options that start with + the prefix "JCL". + - The backends now read print data using the read() + system call to ensure that the current page is printed + while the next page is being processed. + - The pdftops filter did not support shading type 3 + (radial fill) for the "sh" operator. + - The cups-polld program now throttles the local + broadcasts of polled printers and classes so that the + local system is not overwhelmed with hundreds of + printers and classes all at once. + - Updated the serial backend to support 230,400 baud for + the Linux PPC port. + - The cupsGetJobs() function wouldn't report completed + jobs that did not have a document-format attribute + value. + - The cupsEncodeOptions() function now maintains a table + of known boolean and numeric options, and encodes all + other options as strings. + - Now add a newline before the end-of-page code in the + PostScript filter; this fixes a problem with files + that don't end with a newline. + - The image filters looked for the "orientation" option + instead of the correctly named "orientation-requested" + option. + - The cupsEncodeOptions() function now handles mixed + integers and ranges. + - New translation guide for developers to provide native + language support for CUPS. + + +CHANGES IN CUPS V1.1.14 + + - The ippRead() function did not verify that the + attribute name length or string with language value + was not larger than the read buffer. + - The scheduler set the signal handlers before loading + the configuration files the first time; this prevented + the RunAsUser directive from blocking server reloads. + - Added Swedish message catalog. + - The parallel backend now recognizes the /dev/printers + device directory under Linux 2.4.x. + - MacOS X fixes. + - The cupsaddsmb utility sent the server name after the + user information when executing the rpcclient program. + This caused problems with some versions of SAMBA + 2.2.x. + - The IPP backend did not pass the requesting user name + when checking on the print job status. This prevented + it from waiting for the job to complete when + communicating with some IPP implementations that + require it. + + +CHANGES IN CUPS V1.1.13 + + - The lpstat command did not report jobs submitted to + regular printer classes. + - The texttops filter didn't use sufficient precision + when positioning text with some values of cpi and lpi. + This could cause the alignment of text to stray. + - cupsGetDests() didn't merge the options from the + /etc/cups/lpoptions file with ~/.lpoptions - options + in ~/.lpoptions overrode them completely. + - Added support for KOI8-R and KOI8-U character sets, + and added several Russian message catalogs. + - The scheduler put the wrong timezone offset in the log + files (e.g. +0500 instead of -0500 for EST...) + - The scheduler did not ignore trailing whitespace in + *.convs files. + - The scheduler now forces all processes to exit (kill + -9) when it is stopped. This prevents parallel and + USB devices from running in the background after cupsd + goes away. + - The cupsParseOptions() function didn't skip trailing + whitespace after quoted values. + - More changes to support CUPS on OS/2. + - Added Simplified Chinese message catalog. + - Added PAM support for IRIX. + - The cupsGetPPD() function didn't remove the @server + portion of the printer name, and since it would + connect immediately to the remote server instead of + the local server, the printer would not be found. + - Classification and page labels were not rotated to + match the page orientation. + - Now set the TCP "no delay" option on network + connections to improve performance/response time. + - Improved the IRIX printing tools support with patches + from Andrea Suatoni. + - Added a new PrintcapGUI directive to specify the GUI + option panel program to use for the IRIX printing + tools support. + - The cupsGetDests() function did not check to see if a + user-defined default printer (set via lpoptions) still + existed. + - The pstops filter no longer assumes that the default + dictionary is writable when doing N-up processing. + - The pstops filter now supports printing N-up with the + page-set option. + - The imagetoraster filter now supports direct printing + of CMYK image data without conversion/correction. + - The IPP backend now reports printer state/error + conditions when possible (toner low, media empty, + etc.) + - The lpstat command now supports the (undocumented) + IRIX -l option ("-lprintername") for a compact job + listing for a printer. + - The lpstat command now includes printer date/time + information in the output (always Jan 01 00:00) to + make third-party tools happy. + - The text filter now supports non-integer cpi and lpi + values. + - The Margins field in the CUPS raster header was not + initialized by the pstoraster filter. + - Added --with-optim="flags" option to configure script. + - Updated the Italian message translations. + - Updated the cups.list file to install the correct + files. + - The pstoraster filter accessed the third element of a + 2 element array. + - The scheduler did not setup a status pipe for polling + processes, so error messages went to whatever file + descriptor 2 was pointing to when they were started. + - The httpMD5Final() function didn't put a colon between + the password and nonce strings. + - The pstops filter did not default to Binary data for + "%%BeginData:". + - The pstops filter did not stop processing when a line + containing a CTRL-D is seen. + - The scheduler no longer replaces the JobSheets values + from the printers.conf and classes.conf files with the + classification level, if set. This way the original + banner settings are preserved when classification + levels are changed or turned off. + - The serial backend didn't drain the output queue, nor + did it restore the original settings. + - Updated the default system group under MacOS X. + - If no SystemGroup was defined in cupsd.conf, the + system default group was not used. + - 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... + - The cups-config script reported the wrong version + number. + - The cups-config script was installed in $(bindir) + instead of $(BINDIR). + - The init script did not correctly check for a running + cupsd under IRIX 5.x. + + +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 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 configure script to check for /etc/pam.d and + to only set PAMDIR if it exists. + - Updated spec file to generate separate cups-pstoraster + package for pstoraster. + - The spec file wasn't setting LOGDIR in the install. + - The scheduler might restart a stopped printer after + stopping a print job. Thanks to Florent + Guiliani for finding this bug! + - The init script showed run level 0 for the Red Hat + chkconfig program. This is incorrect because Red Hat + doesn't use run level 0 for shutdown scripts. + - The IPP backend did not handle the + client-error-not-found error when checking the status + of the job that was sent. This caused remote queues + to stop on client machines when the server had job + history disabled. + - Added httpConnectEncrypt() function to avoid + performance penalty for setting up encrypted + connections initially. + - Use httpConnectEncrypt() in all client apps and in the + CUPS API to ensure consistent usage of encryption + throughout. + - Jobs weren't queued to remote classes (fix from + Richard Begg.) + - AIX changes from Richard Begg. + - Fixed the pstops fix for GNOME output - no longer use + the page numbers in the %%Page: comment since GNOME + puts a filename instead (!?@!#?!). There is still an + issue with N-up printing since GNOME defines its fonts + in the first page instead of the document setup section + (pages must be independent according to the DSC spec) + People with GNOME printing problems should consult bug + #54489... + - The imagetops filter produced PAGE: messages when + generating PostScript for a non-PostScript printer + (only affects page-label and Classification + options.) + - The updated pdftops filter was looking for an options + file called xpdf.conf instead of pdftops.conf. + - The scheduler would not force the default job sheets + for printers to the current classification setting. + - Added a new ippFindNextAttribute() function to the + CUPS API. + - ppdEmitJCL() now strips any leading path info from + the title string. This is only an issue for non-CUPS + clients that don't do this already... + - Other pstops fixed from Helge Blischke for printing + non-conforming documents. + - The MaxJobs parameter was not reset when loading the + cupsd.conf file. + + +CHANGES IN CUPS V1.1.7 + + - Configuration script changes, including new + "--with-docdir=/dir" option to relocate CUPS + documentation and web content according to your + favorite version of the FHS. + - Documentation updates for encryption, SLP, etc. + - New Software Test Plan and automated test script to + test CUPS prior to installation. + - All scheduler configuration files are now case + insensitive to match Apache. + - Added support for Apache ListenBackLog, Require, + Satisfy, , , and LimitRequestSize + directives. + - Added support for all Apache log levels... + - Added support for "double" HostNameLookups. + - Added new "RunAsUser" directive to support non-root + configurations on the standard (priviledged) ports. + - Added support for non-root invocation of the lpd + backend (does no reserve a priviledged port, which + might not work with some LPD servers...) + - Added new PrintcapFormat directive to control the + output format of the printcap file (BSD or Solaris + formats are supported at present.) + - The CUPS directory service routines now handle + ECONNREFUSED errors gracefully rather than shutting + all browsing off. + - ippErrorString() now returns the recommended error + messages from the IPP/1.1 Model and Semantics + document. + - Fixed a minor IPP compliance issue with responses + to requests without the attributes-charset or + attributes-natural-language attributes. + - Sun fix: need httpFlush() call for chunked IPP + requests in cupsDoFileRequest(). + - httpConnect() now looks up "localhost" by name and + by address (127.0.0.1) for users the go to the + trouble of removing the required localhost entry + in /etc/hosts or on their DNS server... + - Added support for Linux 2.4.x devfs parallel port + filenames (/dev/parallel/N). + - cupsDo[File]Request() and cupsGetPPD() no longer + block trying to reconnect to a crashed or inaccessable + server. + - Added new ppdEmitJCL() function to better handle + PJL commands from PPD files. + - A bug in UpdateJob() would cause the scheduler to + consume 100% CPU until another request was submitted. + - The cancel command did not support the "-" option to + cancel all jobs on all printers. + - The cancel and lprm commands did not support cancelling + the next/current job in the queue. + - The pdftops and pstoraster filters were using unsafe + temporary file functions; while this is not a problem + in normal configurations (the CUPS temporary directory + is restricted), they now use the cupsTempFd() function. + - The mime.types file was missing the recognition rule + for Sun Raster images. + - The admin CGI was passing a printer make string to + ippSetCGIVars() that was being replaced in that + function. + - "lpoptions -l" would resave the options... + - The EPSON drivers now send the "end packet mode" + command when printing to USB devices. + - The scheduler initialized certificates before loading + the cupsd.conf file. + - The scheduler used /dev/random to collect random data, + which could block if insufficient entropy information + had been collected by the kernel. Now use + /dev/urandom. + - Fixed a bug in the whitespace skipping code in + httpGetSubField(). + - The LPD backend now supports a new "order" option: + "lpd://server/queue?order=control,data" (default) and + "lpd://server/queue?order=data,control". + - The scheduler enforced a 30 second timeout on all + clients regardless of the Timeout directive and if a + CGI was currently running. + - cupsParseOptions() now sets boolean options to + option=true or option=false. + - The "percent complete" calculations in the LPD backend + could overflow on large files, causing the percentage + to wrap to 0 every 40MB or so. + - Fixed a memory reallocation bug in pstoraster that + could cause it to crash. + - The LPD backend now sanitizes the job title to avoid + potential problems on remote LPD servers. + - The lp command did not send the requesting-user-name + attribute when altering a job. + - The pstops filter did not handle PostScript files with + lines longer than 8191 bytes. + - The scheduler no longer uses inet_addr() to convert IP + addresses in dot format (mmm.nnn.ooo.ppp) to the + 32-bit format, since it will not work for IPv6 + addresses. + - New "Classification" directive to force labeling of + the current classification on each page. + - New "page-label" attribute to add per-page labels + ("For Official Use Only", "Draft", etc.) + - The scheduler now sets the HTTPS environment variable + for CGI programs when a client connects using + encryption. + - Fixed a recursion bug in the scheduler that could + cause cupsd to crash when a printer was removed. + - The LPDEST and PRINTER environment variables didn't + support instances. + - Dropped the "file" backend from the device list that + is reported, since it is only available for *testing* + and should never be used in a production environment. + The file: device can still be used, but it won't show + up in the list of devices from lpinfo or the web + interface. + - Added support for /dev/lpa# parallel ports under *BSD. + - Added META variables to the CGI header template to + prevent caching of the results. + - Fixed an unaligned memory buffer for the pstoraster + clist states; this caused bus errors for some + combinations of printers, drivers, and options. + - Re-added black reduction for colorful colors; this + helps to prevent dark colors from getting desaturated. + (only used when converting RGB to CMYK) + - Added two new directives - MaxJobsPerPrinter and + MaxJobsPerUser - to allow an administrator to set + the maximum number of pending jobs in a queue or + submitted by a user. + - The scheduler no longer stops a printer if it can't + create the status pipe or run the filters or backend. + This will allow heavily loaded servers to service + clients or start print jobs as the load allows. + - Fixed a bug in the Set-Job-Attributes code that could + crash the scheduler (patch from Martin Zielinski) + - cupsSetDests() did not quote option values with + embedded spaces. + - Added support for the Enable-Printer and + Disable-Printer extension operations (same as + CUPS-Accept-Jobs and CUPS-Reject-Jobs.) + - The AppSocket and IPP backends now wait for the print + job to be finished before exiting; this should prevent + the loss of print jobs with older JetDirect firmware + and make consecutive print jobs print faster. + - The BMP loading code did not handle resolution values + of 0. This is a problem with BMP image files produced + by the GIMP. + - The HTTP Upgrade code (upgrade to TLS encryption) + bypassed the authentication checks. + - The HTTP Upgrade code did not send a 426 status code + to the client and end the current request. This caused + a race condition between the client and server for the + upgrade to TLS. + - Fixed a bug in the EOF and Trailer detection code in + the pstops filter. + - The imagetoraster filter did not add the margins to + the custom page size in the raster header. + - The imagetops filter did not adjust the custom page + size to the size of the printed image. + - The imagetops filter did not include DSC comments + which are required by some printers. + - The imagetops filter did not insert newlines in + Base85 encoded output, causing files to contain + lines longer than 255 characters (violation of the + DSC). + - Added support for the DeskJet 900 series duplexer + and CRET color modes in the HP driver. + - Added support for PPD-defined margins in the HP + driver. + - Fixed the debugging output from pstoraster - the + font list was not terminated by a newline. + - Some versions of the HP-UX pam_unix authentication + module apparently do not pass the appdata_ptr argument + to the conversation function, preventing the scheduler + from authenticating users using PAM under HP-UX. A + workaround using a static variable has been added to + address this problem. + - Fixed a bug in the scheduler SortPrinters() function + that could cause printers to disappear or the + scheduler to crash when adding a printer. + - Changed the pstops filter to not do per-page filtering + if the file does not conform to at least version 3.0 + of the document structuring conventions. This seems + to "fix" printing with broken apps. + - The image filters did not handle older TIFF files that + lacked the samples-per-pixel and bits-per-pixel tags. + - Added new cupsGetJobs() and cupsFreeJobs() functions + to manage print jobs. + - cupsEncodeOptions() would encode names of 0 length and + cupsAddOption() and cupsParseOptions() would add names + of 0 length. + - The scheduler might block waiting for status messages + after starting a new print job. Thanks to Florent + Guiliani for finding this bug! + + +CHANGES IN CUPS V1.1.6-3 + + - The configure script put the JPEG library before the + TIFF library; this caused problems in some + configurations since the TIFF library also supports + JPEG compression of TIFF images. + - Updated the configure script and makefiles to handle + admin man pages with the "1m" extension (HP-UX, IRIX, + Solaris, Tru64) and in odd directories (IRIX) + - The updated cupsTempFile() function did not return + the filename when called with a filename buffer of + NULL (previously it used a static buffer.) + - FreeBSD uses /dev/unlptN, but NetBSD and OpenBSD use + /dev/ulptN. + - DeletePrinter() didn't remove the printer from any + classes it was a member of. + - DeletePrinterFromClass() didn't preserve the + implicit status of a class. + - DeletePrinterFromClasses() didn't remove printers + from implicit classes. + - StartJob() didn't send the job-sheets, job-priority, + and job-hold-until attributes to remote printers. + - LoadAllJobs() was looking for job-sheets-completed + instead of job-media-sheets-completed. This would + prevent accumulation of page data after a restart + of the scheduler. + - The pstops and imagetops filters now generate copies + using the appropriate method for a Level 1, 2, or 3 + printer since some Level 2/3 printers don't support + the /#copies variable anymore. + - The man page for cups-lpd did not mention the "-o" + option. + - The IPP backend didn't handle version-not-supported + errors and revert to IPP/1.0 (previously it only checked + for a bad-request error) + - Caldera fix: lpc now reports unimplemented commands as + unimplemented, not invalid. + - Caldera fix: lpq didn't recognize BSD lpq "-a" option. + - Caldera fix: lpr didn't recognize BSD lpr "-1", "-2", + "-3", "-4", "-q", or "-U" options. + - RedHat fixes: patches to GNU Ghostscript + - SuSE fix: temp file creation patch to GNU Ghostscript + (pstoraster). + - SuSE fix: remove cgi-bin/abort.c and cgi-bin/email.c, + which are not used. + - SuSE fix: missing NULL check in cgi_initialize_post(). + - SuSE fix: potential buffer overflows in + cgi_initialize_string(). + - SuSE fix: potential buffer overflows in + ippSetCGIVars() + - SuSE fix: more NULL checks in ppdOpen(); also make + sure that all memory is freed on error to avoid memory + leaks. + - SuSE fix: Exit from child if setgid() or setuid() + fails. + - SuSE fix: Added setgroups() calls after setgid() and + setuid() calls. + - SuSE fix: potential buffer overflows in httpEncode64() + calls. + - SuSE fix: potential buffer overflows in httpSeparate() + - SuSE fix: potential buffer overflows in ippWrite() for + bad input. + - SuSE fix: potential nul skip in ppd_decode() for + missing hex digits. + + +CHANGES IN CUPS V1.1.6-2 + + - Added changes to support NetBSD startup scripts. + - Added separate compiler options for pstoraster + (Ghostscript) to avoid compiler-induced errors + from Ghostscript's twisted code. + - The mime.types file contained syntax errors. + - Updated the *BSD USB device filenames to use + the /dev/unlptN files so that the USB device + is not reset prior to printing (causes print + corruption on many printers) + - Added new cupsTempFd() function to avoid serious + security bug in glibc fopen() function. The glibc + fopen() function unlinks a file before creating it, + which opens up possible symlink attacks. + - Now reject 0-length names in add-printer and add-class + requests. + - Fix for pstoraster when ZLIB is not available. + - cupsGetPPD() didn't reconnect when a HTTP connection + was lost. + - SuSE fix: httpConnect() didn't check that the + value from gethostbyname() was a valid IPv4 address. + - SuSE fix: httpConnect() didn't allow file descriptor 0 + to be used for a socket. + - SuSE fix: ippRead() didn't confirm that all values in + a set were numeric or string types. + - SuSE fix: lppasswd race condition fixes. + - SuSE fix: directive names could overflow buffer when + reading *.conf files. + - SuSE fix: HEAD requests for PPD files did not use the + same logic as GET requests. + - SuSE fix: possible buffer overflow when adding + /index.html to requested directory name. + - SuSE fix: possible buffer overflow when converting + IPP attributes to string options for filters. + - SuSE fix: creating file: device output with mode 0666 + instead of mode 0600. + - SuSE fix: creating job info files with mode 0640 + instead of 0600. + - SuSE fix: don't rely on snprintf() for including + system name in log filenames. + - SuSE fix: add bounds checking when copying quoted + and hex strings. + + +CHANGES IN CUPS V1.1.6-1 + + - Added configure check for getting the correct + strftime() format string; %c is not Y2k safe, + and %KC and NULL are not universally supported. + + +CHANGES IN CUPS V1.1.6 + + - Fixed another possible DoS attack in httpGets() + - Added check for "LANGUAGE = PCL" and "LANGUAGE = + POSTSCRIPT" in mime.types. + - Resolution options were not being passed into the + filter programs properly. + - The default compiler options for GCC no longer include + "-g3", which apparently is deprecated in newer + versions of GCC. + - CheckJobs() could cause cupsd to crash if a job is + cancelled in StartJob(). + - The printers.conf and classes.conf files are now + written with restricted permissions. + - The round-robin algorithm used by FindAvailablePrinter() + had problems; fixes contributed by Joel Fredrikson. + - If LoadAllJobs() is unable to determine the file type + of a print job, assume "application/vnd.cups-raw". + - The web interface now provides a job_printer_name + value for any corresponding job_printer_uri value. + - The cups-lpd mini-daemon now logs the client address + and hostname as well as all commands and errors in the + syslog file. + - The IPP backend now detects the supported file formats + and only specifies the document format if it is + supported. This makes IPP printing to network print + servers and cards more reliable without affecting the + capabilities of CUPS servers. + - The time_at_xyz attributes are now converted to human- + readable dates and times for the web interfaces. + - The HP and EPSON sample drivers now correctly catch + signals and eject the current page when a job is + cancelled. + - Fixed bug in CGI code - did not ignore control + characters (e.g. newlines) in form data. This caused + sporatic web interface problems. + - The file type logging code in the scheduler referenced + the optional document-format attribute; the new code + uses the resolved MIME type instead. + - The client.conf parsing code now removes trailing + whitespace. + - The MaxJobs directive was being treated as a boolean + instead of an integer. + - The scheduler would not timeout remote printers if + BrowseInterval was set to 0. + - The lpadmin command now supports setting of options + and user-level access control. + - Added "-E" option to all printing commands to force + encryption. + - The client code did not consume the response to the + OPTIONS request when switching to secure mode. + - The scheduler did not output a Content-Length field + when responding to an OPTIONS request. + - Added documentation on using cups-lpd with xinetd + to the man page. + - The socket backend now starts retries at 5 seconds and + increases the interval to 30 seconds. This should + provide faster printing when multiple jobs/files are + queued for a printer. + - The filters and backends no longer buffer output to + stderr. This should provide much more accurate status + reporting. + + +CHANGES IN CUPS V1.1.5-2 + + - Fixed configure check for OpenSSL to work with RSA + code. + - Added configure check for , and use this + check in backend/serial.c. + - Updated configure script handling of data, + configuration, and state directories to use datadir, + sysconfdir, and localstatedir variables. + - NetBSD uses different serial port filenames than + FreeBSD and OpenBSD. + - The pdftops filter didn't need some X-specific files. + - The scheduler makefile doesn't do a chown anymore when + installing (cupsd did this automatically on startup + anyways) + + +CHANGES IN CUPS V1.1.5-1 + + - There was a typo in the top-level Makefile + - The top-level Makefile did not install an init script + for run level 5. + - The configure script did not add the "crypto" library + when checking for the OpenSSL library. + - The OKIDATA PPD files were missing. + - The config.h.in file defined the wrong version number. + - The serial backend did not define "funky_hex" under *BSD. + - Updated the Visual C++ project files and some of the + CUPS API sources to compile under Windows again. + + +CHANGES IN CUPS V1.1.5 + + - Security updates - new default configuration does + not broadcast printer information and only allows + access from the local system. + - EXPERIMENTAL encryption support - CUPS now optionally + supports TLS/SSL encryption via the OpenSSL library. + - Documentation updates. + - Makefile/configure script updates. + - The RPM spec file didn't work out-of-the-box under + RedHat or Mandrake. + - Minor code cleanup to remove extraneous compiler + warnings. + - cupsTempFile() was using %p for the temporary + filename; this should have been %08x (just 8 digit + hex) + - Deleting a printer with active print jobs would still + crash the server. + - ippWrite() and ipp_write_file() didn't send the + correct value length for name-with-language and + text-with-language attributes. + - Updated IPP code to support copied strings (that + should not be freed); this provides slightly more + efficient IPP server performance. + - Updated PDF filter to Xpdf 0.91. + - httpGets() could go into an infinite loop if a line + longer than the input buffer size was sent by a + client. This could be used in a Denial-of-Service + attack. + - The lpstat and CUPS API functions now request only the + data required when getting the list of printer or + class information. This should improve performance + with large numbers of printers on slower machines. + - The scheduler was always enforcing the FilterLimit, + even if FilterLimit was set to 0. + - Updated the Linux USB backend to support Mandrake's + /dev/usb/usblp# filenames. + - The PRINTER and LPDEST environment variables did not + override the lpoptions default printer. + - The PPD read functions incorrectly included trailing + characters (usually whitespace) after quoted string + attributes. + - The multiple-document-handling attribute handling code + did not check for the correct value for collated + copies (separate-documents-uncollated-copies). + - The EPSON driver did not work with OKIDATA printers in + EPSON emulation mode (needed change-emulation command) + - The HP-GL/2 filter did not scale the plot properly in + scale mode 2. + - Added PPD files for 9-pin and 24-pin OKIDATA printers. + - The httpSeparate() function didn't handle passwords + that started with a number. + - ippDelete() could free the character set string + multiple times in name-with-language and + text-with-language attributes. + - The scheduler would access freed memory right after + freeing it (for debug messages); these parts of the + code have been reordered to avoid this situation + which was causing sporatic errors and crashes. + - The ppdClose() function didn't free all of the strings + in the ppd_file_t structure. + - The LoadAllJobs() function in the scheduler did not + close the spool directory. + - Changed all sprintf's that use string formats to + snprintf's, even if the destination buffer is + larger than the source string(s); this protects + against buffer overflows caused outside of CUPS... + - Changed all strcpy's to strncpy's between local and + global variables, even if the destination buffer is + larger than the source string; this protects + against buffer overflows caused outside of CUPS... + - The CUPS certificate functions didn't use the + CUPS_SERVERROOT environment variable when set. + - The directory services code was copying instead of + comparing the remote printer info, resulting in + unnecessary updates of the printer attributes for + remote printers. + - Added new mime.types rules to allow automatic raw + printing of PCL and ESC/P files; PJL headers are + parsed to differentiate between PostScript and + PCL job files. This should eliminate a lot of + the reports of SAMBA printing problems due to + the missing "-oraw" or "-l" options. + - The mimeLoadType() function didn't handle the + 3-argument contains() function. + - The LoadPPDs() function in the scheduler didn't + properly set the alloc_ppds variable or handle a PPD + database containing 0 printers. + - The scheduler FindAvailablePrinter() function didn't + use the same queuing logic as the CheckJobs() + function. This caused classes to stall if a remote + printer was always busy. + - Jobs are now assigned to printers in a class + round-robin style. This should prevent the first + server in the class from bearing the brunt of the + jobs. + - The scheduler's LoadAllJobs() function didn't always + restore remote printers for queued jobs on startup. + - The serial backend didn't support the higher baud + rates with the old termios interface. It now supports + 57600 and 115200 baud. + - The serial backend now supports different types of + flow control; previously it ignored the flow=XYZ + option in the device URI. + - The serial backend now supports DTR/DSR flow control, + which is popular on dot-matrix printers (access with + "flow=dtrdsr" in the device URI) + - Added new job-originating-host-name attribute for + jobs. The new attribute provides the hostname or + IP address of the machine that submitted the job. + - The set-job-attributes code no longer allows read-only + job attributes to be changed. + - Expanded the click area for the navigation bar in the + web interface. + - Updated the lp and cancel commands to support all of + the Solaris print options (some are simply ignored + since they do not map) + - Updated the scheduler to limit the number of file + descriptors to the maximum select() set size. This + was causing problems on Solaris systems where the + max FD count was increased beyond 1024. + - The scheduler's LoadDevices() function was getting + interrupted by the SIGCHLD signal handler; now ignore + child signals while loading devices. + - Added quota and allow/deny user support for printers + and classes. + - Removed black/CMY adjustment code from the PS and + image file RIPs; it was interfering with some CUPS + driver dithering code. + - The lpc program stopped listing the queue statuses + after the first active printer. + - The cups-lpd program used an output format that the + Solaris printing system did not understand. + - Updated the lpq program to use the Solaris format + except under Tru64 UNIX. + - Some DEC PPD files incorrectly use "Off" for the null + value in UI constraints. Added "Off" to the list of + accepted null values. + - Changed the *BSD define constants to __*BSD__ in all + of the backends. + - Added support for "lpstat printername", which is an + undocumented feature in Solaris. + - The HP-GL/2 filter now only sets the plot size if it + is set in the plot file. + - The lpmove command wasn't sending the requesting + user name, causing it to always fail. + - Updated the cupsTempFile() code to use GetTempPath() + under Windows. + - The cups-lpd mini-daemon didn't limit the number of + data files accepted, didn't use cupsTempFile(), + didn't handle control file job information in any + order, and didn't free job options after printing + a file. + - The scheduler copy_banner() function did not + explicitly set the owner and permissions of the banner + files, which could prevent the banner pages from + printing on some systems. + - The lpstat program wasn't listing remote classes. + - The scheduler did not verify that the printer-uri + attribute was specified in all requests that required + it. + + +CHANGES IN CUPS v1.1.4 + + - Makefile and configure script fixes. + - **** Changed the default Printcap setting **** to + /etc/printcap. There are just too many people asking + why application XYZ doesn't see their printers! + - The web admin interface now displays an error if it + can't get the list of printer drivers from cupsd. + - The IPP backend was putting the copies option before + the other job options were set. This caused the IPP + request to contain attribute groups in the wrong + order, which prevented remote printing. + - Added checks in scheduler to free memory used for + IPP requests and language information when closing + a client connection. + - Fixed the duplex option in the HP LaserJet driver. It + should now work with all LaserJet printers (and + compatibles) + - The add-printer web interface didn't initialize the + "old info" data pointer, which caused random crashes + on many OS's. + - Fixed many page sizes defined in the Level 1 + compatibility file "gs_statd.ps" to match reality. + - Fixed another bug in the setpagedevice "code" in + Ghostscript. It should now accept all standard + Adobe attributes on all platforms. + - Fixed pstoraster so that it reallocates memory for + color depth changes as well as size/resolution + changes. This removes an ordering constraint on + the color, page size, and resolution options in + PPD files. + - The IPP backend didn't use the job's character set + when the destination printer supported it. This + caused problems when printing text files to other + CUPS servers. + - Updated the logic used to determine when to rebuild + the PPD file database. The scheduler now checks the + dates and the number of PPD files (was just checking + the dates.) + - Updated the ippSetCGIVars() function (used by the + web interfaces) to only filter valid string values. + - The PostScript filter was scaling 2-up pages + incorrectly. This caused the edges of some pages to + be clipped. + + +CHANGES IN CUPS v1.1.3 + + - Makefile fixes. + - RPM spec file changes. + - Documentation updates. + - Enabled pstoraster debug messages for everything + (only logged when LogLevel set to "debug"...) + - Changed the Input/OutputAttributes fix in + pstoraster so that it works on all platforms. + - The HP-GL/2 filter didn't set the right green + color value in encoded polylines or text. + - Updated the "fitplot" code to handle plot sizes + specified as "PSwidth,length" and "PSlength,width". + - Updated the Linux parallel and USB backends to open + the device files prior to looking in /proc for + autoprobe info. This makes sure that loadable device + driver modules are in fact loaded... + - Added new FilterLimit directive to limit the number + of processing jobs/filters on a system. + - set-job-attributes didn't change the job-state to + held/pending when the job-hold-until attribute was + specified. + - set-job-attributes didn't save the new job attributes. + - Now change the "requesting-user-name" attribute in + requests from remote systems to "remroot" when an + unauthenticated "root" user is sent. This can be + changed using the new RemoteRoot directive in + cupsd.conf. + - The cancel-job, hold-job, release-job, and restart-job + operations didn't log the authenticated username. + - The cups-lpd mini-daemon now checks for a + document-format option before forcing raw mode with + filter mode 'l'. + - The cups-lpd mini-daemon now supports "-o" options + on the command-line (passed by inetd) to set global + defaults for all print queues. + - The pstops filter assumed that a file with a Trailer + comment would also have an EOF comment. + - Added new cupsSetPasswordCB(), cupsSetServer(), + cupsSetUser(), and ippSetPort() functions to better + support client applications (especially GUIs...) + - The CUPS-add-class and CUPS-add-printer operations + didn't reset the printer-name attribute on remote + print queues that had to be renamed when a local + printer was defined with the same name. + - The lpoptions command now supports a "-r" option to + remove options for a printer or instance. + - The lpadmin and admin.cgi programs no longer allow + class and printer names to begin with a number; this + caused the command-line utilities to become confused. + - The Linux USB backend now looks for both the parallel + and usblp driver names in the device list. + - Added a new FontPath directive to cupsd.conf, and also + a "--with-fontpath" option for the configure script to + specify alternate font paths for pstoraster. + - The CUPS-move-job operation didn't update the + job-printer-uri attribute. + - The scheduler only looked up printers and classes by + name in IPP requests, instead of using the full URI. + This caused problems with KUPS and friends with + remote printers. + - The scheduler now handles better localization of + hostnames (e.g. server is host.foo.com, remote is + host.subfoo.foo.com, localized is not host.subfoo...) + - The scheduler logging functions now use a common + log file checking/rotation function (courtesy of + Crutcher Dunnavant at Red Hat) + - The scheduler could accept more client connections + than it allocated for if more than one Port or Listen + line was present in cupsd.conf. + - Other minor scheduler performance tweeks. + - The lpq and lprm commands didn't support the default + printer set using lpoptions. + - The lpoptions command now supports a "-l" option to + list the printer-specific options and their current + settings. + - The web printer and class lists now show a link to the + default printer or class at the top of the page. + - The text filter now supports pretty printing of shell + and perl scripts as well as C/C++ source files. + - The top and bottom margins were reversed for landscape + text printing. + - The lpq and lprm commands didn't understand printer + instances. + - The scheduler only selected on the first 100 file + descriptors instead of the maximum file descriptor + limit. + - The scheduler client, listener, and mainline functions + now share code to disable and enable monitoring for + new client connections. + - The imagetoraster filter didn't support all of the + required pagedevice parameters. + - The serial backend now checks for 100 serial ports + under Linux. + - The scheduler used sscanf() to pull out the remote + printer location, description, and make/model strings, + but if any of these options was empty then sscanf() + would stop processing. + - Added "debug2" log level to provide a little less + verbose debugging information at the "debug" level. + - The scheduler would crash if you stopped a printer + that was currently printing a job. + - The scheduler incorrectly allowed jobs in the cancelled, + aborted, or completed state to be cancelled. + - The image filters did not load TIFF images properly + for bottom-to-top and right-to-left orientations. + - Added new cupsEncodeOptions() function to encode + CUPS options as IPP job attributes. + - The IPP backend, LPD mini-daemon, client commands, + and CUPS API did not properly encode multiple + option values separated by commas. + - Added new scheduler malloc logging in debug mode + (provides summary of total arena size, allocated, + and free bytes once a minute) + - The EPM-based distributions didn't install the + correct symlinks for a few man pages. + - Fixed a memory leak in the scheduler - wasn't + freeing old filters when deleting or renaming + printers. + - The scheduler now queries the primary IP address + for the name of the server and maps any incoming + requests from that address to the server name. + This fixes web admin mapping problems from + server.domain.com to localhost. + - The web printer modify interface now remembers + the previous device and driver settings (except + for serial ports.) + - The job-k-octets attribute is now stored as part of + the job attributes; this preserves the information + after a job is completed when job file history is + turned off. + - Dropped option sub-group parsing code for the moment, + since many Xerox PPD files abuse this feature in PPD + files and don't follow the hierarchy rules. + - Added new wrapper code around options so that duplex + options for some HP printers don't prevent prints. + - Added support for Digital UNIX/Tru64 UNIX/OSF/1 format + for "lpstat -v" output. + - Now show the URI for remote printers instead of + /dev/null in "lpstat -v" output. + - Creating classes and adding printers to a class with + the lpadmin command didn't work. + - The banner pages and test page should now format + correctly in both portrait and landscape orientations. + - Updated banner page substitution so that { can appear + by itself without quoting. + + +CHANGES IN CUPS v1.1.2 + + - Makefile/configure fixes + - RPM spec file and EPM list file fixes + - The cupsTempFile() function now uses a different + algorithm for generating temp files and "reserves" + them to avoid possible security exploitation. + - Now use /dev/random (if available) to seed the random + number generator for certificates. + - The /var/spool/cups and /var/spool/cups/tmp directories + were incorrectly owned by root; they are now owned by + the filter user, typically "lp". + - The scheduler now resets the permissions on the spool + and temp directories as needed to match the filter + user. + - Now expose ppdCollect() as an externally callable + function. + - The image filters now support filtering from the + standard input. + - The imagetoraster filter now collects all printer + options and job patch files and applies them to the + page header as needed. + - Added format and banner options to LPD backend. + - The send-document operation didn't start a job + immediately when last-document was true. + - The set-job-attributes operation didn't correctly + replace the current job-hold-until value. + - Removed the option wrapper code from ppdEmit() and + friends since it caused problems with Ghostscript + and many PS printers. + - Was setting TZ environment variable twice for job + filters. + - Added syslog logging in cups-lpd to aide in + debugging problems. + - The HP-UX parallel port backend did not list the + available parallel ports on some systems (printf + calling problem...) + - The lp and lpr commands overrode user options if + -d/-P were specified after -o. + - The scheduler would crash with a */* filter. + - Added support for a "default" filter for unknown file + types. The example provided in the mime.types and + mime.convs file prints unknown files as if "-oraw" was + specified for the job. This functionality is disabled + by default. + - The "compatibility" mode fix for older backends did not + work for smbspool. Added a workaround for it. + - The HP-GL/2 filter didn't perform the right pen scaling + with some files and the "fitplot" option. + - New Software Performance Specification document that + describes the memory, disk, and CPU usage of all the + CUPS software. + + +CHANGES IN CUPS v1.1.1 + + - The pstoraster Makefile still referenced one of the + old PDF filter files. + - The filter Makefile used INSTALL_DATA instead of + INSTALL_LIB to install the CUPS image library. + - The administration CGI didn't work properly with + network devices. + - The BrowseACL variable was not updated after the + cupsd.conf file was loaded. + - The lpd mini-daemon didn't support printer instances. + - Now use a default umask of 077 for child processes. + - Now put temp files in /var/spool/cups/tmp for child + processes and the root user, unless TMPDIR or TempDir + is defined otherwise. + - cupsGetPPD() no longer uses easy-to-guess filenames. + - The CUPS-Delete-Class and CUPS-Delete-Printer + operations now save classes.conf file as needed. + - The lppasswd command wouldn't add a user. + - The ppdOpen() function could cause a segfault if a + 0-length PPD file was read. + - The image filters were not handling images with + different X and Y resolutions properly. + - The imagetoraster filter defaulted to RGB output + instead of black output like pstoraster. + - The pstops filter didn't handle binary data properly. + - The pstops filter didn't handle copies properly for + PS files lacking DSC comments. + - The pstops filter now appends %%EOF to the end of + documents if they don't have it. + - The cupsGetPPD() function didn't work with remote + printers lacking the @server in the name. + - The configure script didn't work right when only + --prefix was specified. + - The ppdEmit() code now wraps all printer commands so + that buggy PostScript printers will still print a file + after receiving an option that isn't available. + - Fixed the DeskJet margin bug, and disabled 600dpi + color mode until it can be fixed. + - The cupsAddDest() function didn't sort instances + correctly in all cases. + - The time-at-xyz attributes now expand to the date and + time in banner files. + + +CHANGES IN CUPS v1.1 + + - Documentation updates. + - Configuration script updates. + - Didn't map charset and language value strings to lowercase + and _ to - as required by SLP and IPP. + - ppdLoadXYZ() didn't add the list of available fonts to the + ppd_file_t structure. + - The text filter common code was freeing the PPD file data + before it was used. + - The text filter now embeds missing fonts. + - The CGI interface now maps local access to the server to + the localhost address. + - The HP-GL/2 filter didn't use the specified (or default) + color ranges, resulting in strange colors. + - The HP-GL/2 filter didn't default to no input window, which + caused unnecessary clipping of plots. + - Integrated Xpdf's pdftops filter into CUPS, which is a + lightweight and reliable replacement for Ghostscript's + PDF support. + - Removed all PDF support from Ghostscript. + - Updated HP driver to set top margin; this seems to fix + the offset problem seen on HP DeskJet printers. + - Fixed dependencies on the ZLIB and JPEG libraries in + pstoraster. + - The lpr command wasn't using the lpoptions defined by + the user. + - The lpr command would segfault if the CUPS server was + not running. + - The top-level makefile was not installing the CUPS + initialization script. It now does so if it sees there + is an init.d directory in /sbin, /etc/rc.d, or /etc. + - "lpstat -v all" didn't work. + - pstoraster would crash on some platforms doing the + setpagedevice operator. + - The web administration interface now allows you to set + the default banner pages. + - Images can now be positioned on the page using the new + "position" option. + - The AccessLog, ErrorLog, and PageLog directives now + support "%s" to insert the server name. + - Added a new BrowseShortNames directive to allow for + short remote printer names ("printer" instead of + "printer@server") when possible. + - The scheduler could crash if given an invalid PPD file + with no PageSize attributes. + - Updated the serial, parallel, and usb backends to do + multiple writes and ignore ioctl() errors as needed; + this should fix problems with serial printing on old + serial drivers and with the UltraSPARC parallel port + driver under Solaris 2.7. + - Now propagate LD_LIBRARY_PATH to child processes from + cupsd. + - New DataDir directive for installing in alternate + locations. + - New CUPS_SERVERROOT and CUPS_DATADIR environment + variables to specify installation directories as + needed. + - Queued remote jobs recreate remote printers as needed + when the scheduler is started. + - Deleting a printer also purges all jobs on that + printer. + - Old job and control files that don't belong to a + printer are automatically deleted. + - Wasn't updating time-at-processing and + time-at-completed attributes in job. + - Didn't send required multiple-operation-time-out + attribute in response to a get-printer-attributes + request. + - cups-lpd now supports options set with lpoptions. + - The job-hold-until attribute is now provided with all + jobs. For jobs that are not currently held the value + is "no-hold". + - The scheduler was not sending "unknown" values in IPP + responses. + - The lpoptions command now accumulates options from + previous runs rather than replacing all options for a + printer. + - The IPP backend now switches to IPP/1.0 if a 1.1 + request fails. + - The lpadmin and admin.cgi programs now validate new + printer and class names. + - The access_log file now includes the number of IPP bytes + received in a POST request. + + +CHANGES IN CUPS v1.1b5 + + - Documentation updates. + - The pstoraster filter didn't compile without the JPEG library. + - The cupsd server didn't support the HTTP OPTIONS request + method. + - Dropped the "CLOSE" method supported by the cupsd server. + (not defined in HTTP specification) + - Makefile/configure script fixes. + - Missing the job-restart template. + - Added IPP test suite for testing. + - Missing IPP documentation from binary distributions. + - Fixed multiple-document handling code when last-document + not specified. + - Added more checks to IPP requests to prevent bad requests + from getting through. + - Not all of the Ghostscript error output was being sent to + stderr. + - The PostScript filter now added PJL commands to set the + job name and display string, if supported. + - The scheduler would crash if the browse socket could not + be bound. Now disables browsing if port 631 (reserved for + IPP) is being used by a misbehaving daemon. + - The USB backend now looks for the older Linux 2.2.x USB + printer device filenames as well as the newer ones. + - The IPP backend now uses the UTF-8 charset exclusively, + since apparently only CUPS handles more than US-ASCII and + UTF-8... + - Wasn't quoting ( in PostScript banners... + - Send-document requests with no document-format attribute + could cause cupsd to crash. + - Old jobs in the spool directory might cause cupsd to + crash. + - CUPS now supports all of the recommended job-hold-until + keywords as well as name values of the form "HH:MM" and + "HH:MM:SS". + - Added placeholder pointer for TLS encryption to the HTTP + connection structure. + - Fixed the "fast poll" bug reported by DISA - the + status pipe wasn't being closed for multi-file jobs. + - Revamped put_params code in pstoraster to fix bitmap + allocation bug with FrameMaker output. + - Ripped out filename, etc. code from pstoraster as it + is a potential security hole. + - Added support for RIP_CACHE environment variable in the + new pstoraster. + - Fixed USB device filenames for Linux; now support new + pre-2.4 devices (/dev/usb/lp#) and 2.2 devices + (/dev/usblp#) + - Fixed accept-jobs crash with classes. + - Didn't include dot-matrix EPSON drivers in previous + release. + + +CHANGES IN CUPS v1.1b4 + + - Documentation updates. + - Many makefile and configuration script fixes (should + now compile better under *BSD.) + - The MediaPosition attribute was being mishandled by + GhostScript, causing the RIP to fail whenever a paper + tray was selected. + - The scheduler now logs the final line of log information + from a filter, even if it doesn't end with a newline; this + primarily affects GhostScript error output. + - The scheduler was saving implicit classes, so after a few + restarts you'll end up with AnyPrinter, AnyAnyPrinter, etc. + - The JPEG autodetection didn't work with some JPEG files that + came from digital cameras (JPEG but not JFIF); the new + magic types should work with all images that the JPEG library + can handle. + - Fixed a bug in the new contains() MIME type rule that could + cause cupsd to crash. + - Switched to using strtol() in the MIME type code so that you + can use hex, octal, or decimal constants as desired in the + mime.types file. + - Banner files are now treated as templates, allowing any type + of file to be used as a banner. + - Added a 30-second timeout to backend device reports so that a + hung backend will not prevent the scheduler from starting. + - Backends are once again terminated when jobs are stopped; the + CUPS-supplied backends will stay alive until the downstream + filters have had a chance to clear out old page data. + - The charset lookup in the CUPS localization support was wrong + (iso8859-x instead of iso-8859-x) + - Changed the "cpNNNN" code page files to "windows-NNNN" to match + the IANA registrations. + - New PostScript banner pages. + - Added Windows BMP and Alias PIX image file support to the image + filter. + - The PNG reading coded didn't free all of its buffers. + - Added Digest authentication support to the client and server + code. + - Added Solaris options to System V commands. + - Now support the output-bin job template attribute. + - Now log the job-billing attribute in the page_log file, and + keep track of the total number of pages in the + job-media-sheets-completed attribute. + - The penwidth option is now in micrometers to support more + accurate width specification. + - The image filters now support interlaced and transparent PNG + files. + - Didn't handle Keep-Alive for HTTP/1.0 clients. + - The BrowsePoll support didn't handle when BrowseInterval + was set to 0 (now uses 30 seconds if BrowseInterval is 0) + - The DeskJet driver now supports 600 DPI color for printers + that support it. + - New lpinfo and lpmove commands. + - The lpq command now supports the Digital UNIX output format. + - The LPD mini-daemon now supports all required LPD operations. + - Implemented timeouts for multi-file documents. + - New cupsPrintFiles() function in the CUPS API library to + print multiple files using create-job and send-document + requests (1 job ID for multiple files) + - The lp command now sends multiple files as a single job, + matching the behavior of the System V command. + - The "cancel -a" command now purges job history files. + + +CHANGES IN CUPS v1.1b3 + + - Documentation updates. + - The startup script redirected stderr before stdout, + which caused problems with some versions of Bourne + shell and Bash. + - Fixed a bug in the scheduler's PPD language reading + code. + - Fixed a bug in the scheduler's check for the + manufacturer in the PPD. + - The pstoraster filter didn't allow some input and + output attributes to be set. + - Added banner page support. + - Added missing PAM configuration file. + - Configuration script fixes for Linux and *BSD. + - The log file code was using the wrong sign for the + timezone offset. + - The default printcap file is now empty (no printcap + file is generated). + - The scheduler did not start jobs destined for remote + printers when they became available. + - The scheduler now sends jobs to remote printers + immediately. (when sending jobs to a class, the remote + printer is only used when it becomes available) + - The scheduler now supports printing of banner pages + via the job-sheets attribute (banner files go in + /usr/share/cups/banners) + - The cupsd process now forks itself into the background + (override with -f) + - Added several *BSD enhancements. + - Added UNSUPPORTED libtool option to configuration + script to allow the use of libtool. Note that this is + UNSUPPORTED by us, but added by request of the *BSD + folks. + - The parallel, serial, and usb backends now retry the + opening of their ports. This allows multiple print + queues to be associated with a single physical port, + and will allow CUPS to support several types of + parallel port auto-switches in the near future. + - Set-Job-Attributes now supports adding, changing, and + deleting job template attributes, and no longer allows + job-printer-uri to be set (see CUPS-Move-Job) + - Added CUPS-Move-Job operation to support moving of jobs. + - The CGI template functionality now supports multiple + languages (still only have templates for English) + - The CUPS-Get-Printers and CUPS-Get-Classes operations + now support filtering as defined in the IDD. + - The Get-Jobs, CUPS-Get-Printers, and CUPS-Get-Classes + operations no longer limit themselves to 1000 jobs, + printers, or classes (believe it or not, this is + needed for some sites) + - The web interfaces now support language-specific + templates. + - The web admin interface now supports class management. + - The web admin interface now shows a list of + manufacturers before selecting the PPD/driver for a + specific printer. + - The web admin interface now supports configuration of + the default printer options in the PPD file. + - The web interface now uses printer/class + authentication for the test page instead of admin + authentication. + - Updated the RPM spec file for the current release. + - Updated language support for Windows code pages. + - 8-bit character set files can now use multiple fonts + (needed for Arabic, Greek, Hebrew, etc.) + - Added basic right-to-left text support in the text + filter. + - The POSIX locale now uses ISO-8859-1 instead of + US-ASCII. + - Fixed PDF printing problems. + - Fixed PostScript RIP page device dictionary elements + that weren't getting passed in cups_get_params(). + - Added a new "contains" rule for the magic file typing. + - The "printable" rule now accepts characters from 128 to 255 + (needed for Microsoft character sets) + - Added support for ~/.cupsrc as well as /etc/cups/client.conf + so that the default server can be configured on a per-user + basis without environment variables. + - Added LPD mini-daemon to support incoming LPD jobs. + + +CHANGES IN CUPS v1.1b2 + + - Documentation updates. + - The lp command didn't always load the user-defined + destinations, preventing it from seeing the default + printer. + - Many configure script and makefile fixes. + - The Microsoft code page files were missing from the + distribution. + - Added a workaround for the HP IPP client (which is sending + an invalid printer-uri in requests) + - Fixed the encoding of text-with-language and name-with-language + to match the IPP spec. + - Added support for unknown value tags in the IPP routines + (previously they would be ignored) + - Integrated GNU GhostScript 5.50 into the pstoraster filter. + - Client hostname resolution was broken on little-endian + machines. + - Now look at client.conf file for client's default server + and printer. + - The cupsServer() function did not close the client.conf file + if it contained a ServerName directive. + - Added BrowseAllow, BrowseDeny, BrowseOrder, BrowsePoll, and + BrowseRelay directives. + - BrowseInterval 0 disables advertising of local printers, but + still receives information on remote printers. + - New browse polling daemon (for polling servers on different + networks) + - New PPD cache file for faster startup times with large numbers + of PPD files. + - The Host: field was incorrectly required for HTTP/1.0 clients. + - New set-job-attributes operation now supported. + - The mime_load_types() and mime_load_convs() functions did not + close their input files. + + +CHANGES IN CUPS v1.1b1 + + - NEW web-based administration interface. + - NEW EPSON printer drivers. + - NEW user-defined printers and options. + - NEW persistent jobs and job history + - NEW IPP/1.1 support + - NEW template-based web interfaces. + - NEW CUPS-get-devices and CUPS-get-ppds operations. + - NEW support for create-job and send-file operations. + - NEW certificate-based authentication for local + administration. + - NEW USB backend. + - The lpr command now produces human-readable error messages. + - The lpq command now produces BSD standard format output + instead of OSF/1 output. This should resolve the SAMBA + print queue problems that have been reported. + - The IPP backend did not always detect when the "raw" option + was being used. + - The "lpstat -p" command would stop after the first active + printer. + - The "lpstat -v" command would stop before the first remote + printer. + + +CHANGES IN CUPS v1.0.5 + + - The HP-GL/2 filter did not correctly set the pen color + for pens other than #1. + - The scheduler would only accept 26 simultaneous jobs + under some OS releases (mkstemp() limitation.) It now + handles up to 2^32 simultaneous jobs. + - The PostScript filter loaded the printer's PPD file + twice. + - The PAM authentication code now uses pam_strerror() to + provide a textual error message in the error_log file. + - The scheduler now copies PPD and interface script + files instead of moving them; this fixes installations + with a separate requests directory. + - The PostScript RIP did not generate correct 6-color + output. + - Several filters were marking PPD options twice when + they didn't need to. + - The scheduler did not save the printer or class state + after an accept-jobs or reject-jobs operation. + - The cupsGetDefault() function now ignores the PRINTER + environment variable if it is set to "lp". + - New ippErrorString() function to get textual error + messages. + - Better error reporting in the System V commands. + - The lpadmin and lpstat commands always tried to + connect to the default server. + - The text filter didn't load the charset files from the + correct location. + - Wasn't sending a WWW-Authenticate: field to HTTP + clients when authentication was required. + - httpSeparate() didn't always set the default port + number for known methods. + - The HP-GL/2 filter now looks for "PSwidth,length" + instead of (the correct) "PSlength,width" as + documented by HP. It appears that many major CAD + applications are broken and this change allows the + auto-rotation to work with them. + - The IPP "printer-resolution" option was not being + translated. + - The charset files did not include the Microsoft + "standard" characters from 128 to 159 (unused by the + ISO-8859-x charsets) + - The scheduler was chunking the Content-Type field from + CGI programs; this problem was most noticeable with + Microsoft Internet Explorer 5. + - By popular demand, the printers, jobs, and classes + CGIs no longer force a reload of the page every 10/30 + seconds. + - The scheduler incorrectly required that the IPP client + provide a document-format attribute for the + validate-job operation. + - Clients that sent bad IPP requests without the + required attributes-natural-language and + attributes-charset attributes would crash the + scheduler. + + +CHANGES IN CUPS v1.0.4 + + - Documentation updates. + - Jobs would get stuck in the queue and wouldn't print + until you enabled the queue. + - The lp and lpr commands now catch SIGHUP and SIGINTR. + - The lp and lpr commands now use sigaction or sigset + when available. + - CUPS library updates for WIN32/OS-2 + + +CHANGES IN CUPS v1.0.3 + + - Documentation updates. + - The lpq man page was missing. + - The configure script was not properly detecting the + image libraries. + - The top-level makefile was calling "make" instead of + "$(MAKE)". + - PostScript filter fixes for number-up, OutputOrder, + and %Trailer. + - The imagetops filter didn't end the base-85 encoding + properly if the image data was not a multiple of 4 + bytes in length. + - The imagetoraster filter didn't generate good banded + RGB or CMY data (was dividing the line width by 4 + instead of 3...) + - The imagetoraster filter now records the bounding + box of the image on the page. + - The CUPS image library cache code wasn't working as + designed; images larger than the maximum RIP cache + would eventually thrash using the same cache tile. + - The CUPS image library TIFF loading code didn't + handle unknown resolution units properly; the fixed + code uses a default resolution of 128 PPI. + - cupsGetClasses() and cupsGetPrinters() did not free + existing strings if they ran out of memory. + - The scheduler logs incorrectly contained 3 digits for + the timezone offset instead of 4. + - The scheduler now does a lookup for the default user + and group ID; the previous hardcoded values caused + problems with the LPD backend. + - The cancel-job operation now allows any user in the + system group to cancel any job. + - The cancel-job operation stopped the print queue if + the job was being printed. + - Now only stop printers if the backend fails. If the + filter fails then the failure is noted in the + error_log and printing continues with the next file in + the queue. + - Now log whether a filter fails because of a signal + or because it returned a non-zero exit status. + - The root user now always passes the system group test. + - Printers with an interface script and remote printers + and classes didn't have a printer-make-and-model + attribute. + - Added logging of lost/timed-out remote printers. + - The HP-GL/2 filter was scaling the pen width twice. + - Updated the HP-GL/2 filter to use a single SP (Set + Pen) procedure. This makes the output smaller and is + more appropriate since the filter keeps track of the + pen states already. + - The scheduler didn't handle passwords with spaces. + - The IPP backend now does multiple copies and retries + if the destination server requires it (e.g. HP + JetDirect.) + - The disable command didn't implement the "-c" option + (cancel all jobs.) + - Changed the CMYK generation function for the image file + and PostScript RIPs. + - The lp command didn't support the "-h" option as + documented. + - The AppSocket, IPP, and LPD backends now retry on all + network errors. This should prevent stopped queues + caused by a printer being disconnected from the + network or powered off. + - The scheduler now restarts a job if the corresponding + printer is modified. + - The image RIPs now rotate the image if needed to fit + on the page. + + +CHANGES IN CUPS v1.0.2 + + - The HP-GL/2 filter didn't always scale the output + correctly. + - The HP-GL/2 filter now supports changing the page size + automatically when the "fitplot" option is not used. + - The cancel-job operation was expecting a resource name + of the form "/job/#" instead of "/jobs/#"; this + prevented the cancel and lprm commands from working. + - The backends didn't log pages when files were printed + using the "-oraw" option. + - The authorization code did not work with the Slackware + long shadow password package because its crypt() can + return NULL. + - The chunking code didn't work for reading the response + of a POST request. + - cupsGetPPD() now does authentication as needed. + - The N-up code in the PostScript filter didn't work + with some printers (grestoreall would restore the + default blank page and device settings). + - The N-up code in the PostScript filter didn't scale + the pages to fit within the imageable area of the + page. + - Wasn't doing an fchown() on the request files. This + caused problems when the default root account group + and CUPS group were not the same. + + +CHANGES IN CUPS v1.0.1 + + - Documentation updates. + - Fixed a bunch of possible buffer-overflow conditions. + - The scheduler now supports authentication using PAM. + - Updated the Italian message file. + - httpEncode64() didn't add an extra "=" if there was + only one byte in the last three-byte group. + - Now drop any trailing character set from the locale + string (e.g. "en_US.ISO_8859-1" becomes "en_US") + - Fixed "timezone" vs "tm_gmtoff" usage for BSD-based + operating systems. + - Updated IPP security so that "get" operations can be + done from any resource name; this allows the CGIs to + work with printer authentication enabled so long as + authentication isn't turned on for the whole "site". + - The IPP code didn't properly handle the "unsupported" + group; this caused problems with the HP JetDirect since + it doesn't seem to support the "copies" attribute. + - The HTTP chunking code was missing a CR LF pair at the + end of a 0-length chunk. + - The httpSeparate() function didn't handle embedded + usernames and passwords in the URI properly. + - Doing "lpadmin -p printer -E" didn't restart printing + if there were pending jobs. + - The cancel-job operation now requires either a + requesting-user-name attribute or an authenticated + username. + - The add-printer code did not report errors if the + interface script or PPD file could not be renamed. + - Request files are now created without world read + permissions. + - Added a cupsLastError() function to the CUPS API to + retrieve the IPP error code from the last request. + - Options are now case-insensitive. + - The lpq command now provides 10 characters for the + username instead of the original (Berkeley standard) + 7. + - The cancel command needed a local CUPS server to work + (or the appropriate ServerName in cupsd.conf) + - The cancel and lprm commands didn't report the IPP + error if the job could not be cancelled. + - The lp and lpr commands didn't intercept SIGTERM to + remove temporary files when printing from stdin. + - The lp and lpr commands didn't report the IPP error if + the job could not be printed. diff --git a/CREDITS.txt b/CREDITS.txt new file mode 100644 index 0000000000..7dbd5b96ed --- /dev/null +++ b/CREDITS.txt @@ -0,0 +1,30 @@ +CREDITS.txt - 12/02/2002 +------------------------ + +Few projects are completed by one person, and CUPS is no exception. We'd +like to thank the following individuals for their contributions: + + Nathaniel Barbour - Lots of testing and feedback. + N. Becker - setsid(). + Jean-Eric Cuendet - GhostScript filters for CUPS. + Van Dang - HTTP and IPP policeman. + Dr. ZP Han - setgid()/setuid(). + Guy Harris - *BSD shared libraries and lots of other fixes. + Wang Jian - CUPS RPM corrections. + Roderick Johnstone - Beta tester of the millenium. + Till Kamppeter - Bug fixes, beta testing, evangelism. + Sergey V. Kovalyov - ESP Print Pro and CUPS beta tester. + Mark Lawrence - Microsoft interoperability testing. + Jeff Licquia - Bug fixes, beta testing, evangelism. + Jason McMullan - Original CUPS RPM distributions. + Wes Morgan - *BSD fixes. + Ulrich Oldendorf - German locale. + Giulio Orsero - Bug fixes and testing. + Kurt Pfeifle - Bug fixes, beta testing, evangelism. + Petter Reinholdtsen - HP-UX compiler stuff. + Stuart Stevens - HP JetDirect IPP information. + Kiko - Bug fixes. + L. Peter Deutsch - MD5 code. + +If I've missed someone, please let me know by sending an email to +"mike@easysw.com". diff --git a/ENCRYPTION.txt b/ENCRYPTION.txt new file mode 100644 index 0000000000..5ec656ea5f --- /dev/null +++ b/ENCRYPTION.txt @@ -0,0 +1,138 @@ +ENCRYPTION - CUPS v1.1.7 - 02/21/2001 +------------------------------------- + +This file describes the encryption support provided by CUPS. + +WARNING: CLIENTS CURRENTLY TRUST ALL CERTIFICATES FROM SERVERS. +This makes the CUPS client applications vulnerable to "man in +the middle" attacks, so we don't recommend using this to do +remote administration over WANs at this time. + +Future versions of CUPS will keep track of server certificates +and provide a callback/confirmation interface for accepting new +certificates and warning when a certificate has changed. + + +LEGAL STUFF + +BEFORE USING THE ENCRYPTION SUPPORT, PLEASE VERIFY THAT IT IS +LEGAL TO DO SO IN YOUR COUNTRY. CUPS by itself doesn't include +any encryption code, but it can link against the OpenSSL library +which does. + + +OVERVIEW OF ENCRYPTION SUPPORT IN CUPS + +CUPS supports SSL/2.0, SSL/3.0, and TLS/1.0 encryption using +keys as large as 128-bits. Encryption support is provided via +the OpenSSL library and some new hooks in the CUPS code. + +CUPS provides support for dedicated (https) and "upgrade" (TLS) +encryption of sessions. The "HTTP Upgrade" method is described +in RFC 2817; basically, the client can be secure or unsecure, +and the client or server initiates an upgrade to a secure +connection via some new HTTP fields and status codes. The HTTP +Upgrade method is new and no browsers we know of support it yet. +Stick with "https" for web browsers. + +The current implementation is very basic. The CUPS client +software (lp, lpr, etc.) uses encryption as requested by the +user or server. + +The user can specify the "-E" option with the printing commands +to force encryption of the connection. Encryption can also be +specified using the Encryption directive in the client.conf file +or in the CUPS_ENCRYPTION environment variable: + + Never + + Never do encryption. + + Always + + Always do SSL/TLS encryption using the https scheme. + + IfRequested + + Upgrade to TLS encryption if the server asks for it. + This is the default setting. + + Required + + Always upgrade to TLS encryption as soon as the + connection is made. This is different than the "Always" + mode above since the connection is initially unsecure + and the client initiates the upgrade to TLS encryption. + (same as using the "-E" option) + +These keywords are also used in the cupsd.conf file to secure +particular locations. To secure all traffic on the server, listen +on port 443 (https port) instead of port 631 and change the "ipp" +service listing (or add it if you don't have one) in /etc/services +to 443. To provide both secure and normal methods, add a line +reading: + + SSLPort 443 + +to /etc/cups/cupsd.conf. + + +BEFORE YOU BEGIN + +You'll need the OpenSSL library from: + + http://www.openssl.org + + +CONFIGURING WITH ENCRYPTION SUPPORT + +Once you have the OpenSSL library installed, you'll need to +configure CUPS to use it with the "--enable-ssl" option: + + ./configure --enable-ssl + +If the OpenSSL stuff is not in a standard location, make sure to +define the CFLAGS, CXXFLAGS, and LDFLAGS environment variables +with the appropriate compiler and linker options first. + + +GENERATING A SERVER CERTIFICATE AND KEY + +The following OpenSSL command will generate a server certificate +and key that you can play with. Since the certificate is not +properly signed it will generate all kinds of warnings in +Netscape and MSIE: + + openssl req -new -x509 -keyout /etc/cups/ssl/server.key \ + -out /etc/cups/ssl/server.crt -days 365 -nodes + + chmod 600 /etc/cups/ssl/server.* + +The "-nodes" option prevents the certificate and key from being +encrypted. The cupsd process runs in the background, detached +from any input source; if you encrypt these files then cupsd +will not be able to load them! + +Send all rants about non-encrypted certificate and key files to +/dev/null. It makes sense to encrypt user files, but not for +files used by system processes/daemons... + + +REPORTING PROBLEMS + +If you have problems, READ THE DOCUMENTATION FIRST! If the +documentation does not solve your problems please send an email +to "cups-support@cups.org". Include your operating system and +version, compiler and version, and any errors or problems you've +run into. The "/var/log/cups/error_log" file should also be sent, +as it often helps to determine the cause of your problem. + +If you are running a version of Linux, be sure to provide the +Linux distribution you have, too. + +Please note that the "cups-support@cups.org" email address goes +to the CUPS developers; they are busy people, so your email may +go unanswered for days or weeks. In general, only general build +or distribution problems will actually get answered - for +end-user support see the "README.txt" for a summary of the +resources available. diff --git a/INSTALL.txt b/INSTALL.txt new file mode 100644 index 0000000000..6aec5a7d48 --- /dev/null +++ b/INSTALL.txt @@ -0,0 +1,190 @@ +INSTALL - CUPS v1.1.17 - 12/02/2002 +----------------------------------- + +This file describes how to compile and install CUPS from source +code. For more information on CUPS see the file called +"README.txt". A complete change log can be found in +"CHANGES.txt". + +**** IF YOU HAVE A NON-POSTSCRIPT PRINTER, YOU WILL ALSO **** +**** NEED TO INSTALL ESP GHOSTSCRIPT OR A PATCHED VERSION **** +**** OF THE STANDARD GHOSTSCRIPT RELEASES. **** + + +BEFORE YOU BEGIN + +You'll need ANSI-compliant C and C++ compilers, plus a make +program and Bourne shell. The GNU compiler tools work well - +we've tested the current CUPS code against GCC 2.95.x with +excellent results. + +The makefiles used by the project should work with all versions +of make. We've tested them with GNU make as well as the make +programs shipped by Compaq, HP, SGI, and Sun. FreeBSD users +should use GNU make (gmake). + +Besides these tools you'll want the following libraries: + + - JPEG 6b or higher + - PNG 1.0.6 or higher + - TIFF 3.4 or higher + - ZLIB 1.1.3 or higher + +CUPS will compile and run without these, however you'll miss out on +many of the features provided by CUPS. + +Also, please note that CUPS no longer includes the Ghostscript- +based pstoraster filter. You *must* download Ghostscript +separately and patch it using the files in the pstoraster +subdirectory, or download the ESP Ghostscript distribution from +the CUPS web site. For more information see the README file in +the pstoraster subdirectory. + + +COMPILING FROM CVS + +The CUPS CVS repository doesn't hold a copy of the pre-built +configure script. You'll need to run the GNU autoconf software +(2.52 or higher) before compiling the software from CVS: + + autoconf ENTER + + +CONFIGURATION + +CUPS uses GNU autoconf, so you should find the usual "configure" +script in the main CUPS source directory. To configure CUPS for +your system, type: + + ./configure ENTER + +The default installation will put the CUPS software in the +"/etc", "/usr", and "/var" directories on your system, which +will overwrite any existing printing commands on your system. +Use the "--prefix" option to install the CUPS software in +another location: + + ./configure --prefix=/some/directory ENTER + +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, 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 + +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 + +To enable support for encryption, you'll also want to add the +"--enable-ssl" option: + + ./configure --enable-ssl + +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. + +Once you have configured things, just type: + + make ENTER + +or if you have FreeBSD, NetBSD, or OpenBSD type: + + gmake ENTER + +to build the software. + + +INSTALLING THE SOFTWARE + +Once you have built the software you need to install it. The +"install" target provides a quick way to install the software on +your local system: + + make install ENTER + +or for FreeBSD, NetBSD, or OpenBSD: + + gmake install ENTER + +You can also build binary packages that can be installed on other +machines using the RPM spec file ("cups.spec") or EPM list file +("cups.list"). The latter also supports building of binary RPMs, +so it may be more convenient to use - we use EPM to build all of +our binary distributions. + +You can find the RPM software at: + + http://www.rpm.org + +The EPM software is at: + + http://www.easysw.com/epm/ + + +CREATING BINARY DISTRIBUTIONS WITH EPM + +The top level makefile supports generation of many types of binary +distributions using EPM. To build a binary distribution type: + + make ENTER + +or + + gmake ENTER + +for FreeBSD, NetBSD, and OpenBSD. The 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. + 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. + + +REPORTING PROBLEMS + +If you have problems, READ THE DOCUMENTATION FIRST! If the +documentation does not solve your problems please send an email +to "cups-support@cups.org". Include your operating system and +version, compiler and version, and any errors or problems you've +run into. The "/var/log/cups/error_log" file should also be sent, +as it often helps to determine the cause of your problem. + +If you are running a version of Linux, be sure to provide the +Linux distribution you have, too. + +Please note that the "cups-support@cups.org" email address goes +to the CUPS developers; they are busy people, so your email may +go unanswered for days or weeks. In general, only general build +or distribution problems will actually get answered - for +end-user support see the "README.txt" for a summary of the +resources available. diff --git a/LICENSE.html b/LICENSE.html new file mode 100644 index 0000000000..ad9a570b01 --- /dev/null +++ b/LICENSE.html @@ -0,0 +1,957 @@ + + + Software License Agreement - Common UNIX Printing System + + + + +

Common UNIX Printing System License Agreement

+ +

Copyright 1997-2002 by Easy Software Products
+44141 AIRPORT VIEW DR STE 204
+HOLLYWOOD, MARYLAND 20636-3111 USA
+
+Voice: +1.301.373.9600
+Email: cups-info@cups.org
+WWW: http://www.cups.org + +

Introduction

+ +

The Common UNIX Printing SystemTM, +("CUPSTM"), is provided under the GNU General Public +License ("GPL") and GNU Library General Public License ("LGPL"), +Version 2, with exceptions for Apple operating systems and the +OpenSSL toolkit. A copy of the exceptions and licenses follow +this introduction. + +

The GNU LGPL applies to the CUPS API library, located in the +"cups" subdirectory of the CUPS source distribution and in the +"cups" include directory and library files in the binary +distributions. The GNU GPL applies to the remainder of the CUPS +distribution, including the "pdftops" filter which is based upon +Xpdf and the CUPS imaging library. + +

For those not familiar with the GNU GPL, the license basically +allows you to: + +

    + +
  • Use the CUPS software at no charge.
  • + +
  • Distribute verbatim copies of the software in source + or binary form.
  • + +
  • Sell verbatim copies of the software for a media + fee, or sell support for the software.
  • + +
  • Distribute or sell printer drivers and filters that + use CUPS so long as source code is made available under + the GPL.
  • + +
+ +

What this license does not 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. The +only exceptions to this are the portions of the CUPS software +covered by the Apple operating system license exceptions +outlined later in this license agreement. + +

The GNU LGPL relaxes the "link-to" restriction, allowing you +to develop applications that use the CUPS API library under +other licenses and/or conditions as appropriate for your +application. + +

License Exceptions

+ +

In addition, as the copyright holder of CUPS, Easy Software +Products grants the following special exceptions: + +

    + +
  1. Apple Operating System Development License + Exception; + +
      + +
    1. Software that is developed by any person or + entity for an Apple Operating System ("Apple + OS-Developed Software"), including but not + limited to Apple and third party printer + drivers, filters, and backends for an Apple + Operating System, that is linked to the CUPS + imaging library or based on any sample filters + or backends provided with CUPS shall not be + considered to be a derivative work or collective + work based on the CUPS program and is exempt + from the mandatory source code release clauses + of the GNU GPL. You may therefore distribute + linked combinations of the CUPS imaging library + with Apple OS-Developed Software without + releasing the source code of the Apple + OS-Developed Software. You may also use sample + filters and backends provided with CUPS to + develop Apple OS-Developed Software without + releasing the source code of the Apple + OS-Developed Software.
    2. + +
    3. An Apple Operating System means any + operating system software developed and/or + marketed by Apple Computer, Inc., including but + not limited to all existing releases and + versions of Apple's Darwin, Mac OS X, and Mac OS + X Server products and all follow-on releases and + future versions thereof.
    4. + +
    5. This exception is only available for Apple + OS-Developed Software and does not apply to + software that is distributed for use on other + operating systems.
    6. + +
    7. All CUPS software that falls under this + license exception have the following text at the + top of each source file: + +
      This file is subject to the Apple + OS-Developed Software + exception.
    8. + +
    + +
  2. OpenSSL Toolkit License Exception; + +
      + +
    1. Easy Software Products explicitly allows the + compilation and distribution of the CUPS + software with the OpenSSL Toolkit.
    2. + +
    + +
+ +

No developer is required to provide these exceptions in a +derived work. + +

Trademarks

+ +

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. Please contract Easy Software Products for written +permission to use them in derivative products. 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. + +

Binary Distribution Rights

+ +

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. + +

The Common UNIX Printing System provides a "pdftops" filter +that is based on the Xpdf software. For binary distribution +licensing of this software, please contact: + +

+Derek B. Noonburg
+Email: derekn@foolabs.com
+WWW: http://www.foolabs.com/xpdf/ +
+ +

Support

+ +

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: + +

+ + +

GNU GENERAL PUBLIC LICENSE

+ +

Version 2, June 1991 + +

+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+ +

Preamble

+ +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

The precise terms and conditions for copying, distribution and +modification follow. + +

GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+ +
    + +
  1. 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 "Program", below, +refers to any such program or work, and a "work based on the Program" +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 "modification".) Each licensee is addressed as "you". + +

    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. + +

  2. 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. + +

    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. + +

  3. 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: + +
      + +
    1. You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + +
    2. 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. + +
    3. 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.) + +
    + +

    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. + +

    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. + +

    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. + +

  4. 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: + +
      + +
    1. 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, + +
    2. 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, + +
    3. 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.) + +
    + +

    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. + +

    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. + +

  5. 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. + +
  6. 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. + +
  7. 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. + +
  8. 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. + +

    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. + +

    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. + +

    This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +

  9. 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. + +
  10. 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. + +

    Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", 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. + +

  11. 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. + +
+ +

NO WARRANTY

+ +
    + +
  1. 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 "AS IS" 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. + +
  2. 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. + +
+ +

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+ +

Version 2, June 1991 + +

+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ +

Preamble

+ +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

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. + +

The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + +

Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + +

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+ +

0. +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 "this License"). Each licensee is +addressed as "you". + +

A "library" 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. + +

The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" 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 "modification".) + +

"Source code" 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. + +

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. + +

1. +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. + +

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. + +

2. +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: + +

    + +
  1. The modified work must itself be a software library. + +

    +

  2. You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + +

    +

  3. You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + +

    +

  4. 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. + +

    (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.) + +

+ +

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. + +

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. + +

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. + +

3. +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. + +

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. + +

This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + +

4. +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. + +

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. + +

5. +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 "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + +

However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + +

When a "work that uses the Library" 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. + +

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.) + +

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. + +

6. +As an exception to the Sections above, you may also compile or +link a "work that uses the Library" 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. + +

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: + +

    + +
  1. 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 "work that + uses the Library", 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.) + +

    +

  2. 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. + +

    +

  3. 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. + +

    +

  4. Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + +
+ +

For an executable, the required form of the "work that uses the +Library" 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. + +

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. + +

7. +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: + +

    + +
  1. 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. + +

    +

  2. 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. + +
+ +

8. +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. + +

9. +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. + +

10. +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. + +

11. +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. + +

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. + +

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. + +

This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +

12. +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. + +

13. +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. + +

Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", 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. + +

14. +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. + +

NO WARRANTY + +

15. +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 "AS IS" 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. + +

16. +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. + +

END OF TERMS AND CONDITIONS

+ + + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..c370d608fc --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,861 @@ + Common UNIX Printing System License Agreement + + Copyright 1997-2002 by Easy Software Products + 44141 AIRPORT VIEW DR STE 204 + HOLLYWOOD, MARYLAND 20636-3111 USA + + Voice: +1.301.373.9600 + Email: cups-info@cups.org + WWW: http://www.cups.org + + +INTRODUCTION + +The Common UNIX Printing System(tm), ("CUPS(tm)"), is provided +under the GNU General Public License ("GPL") and GNU Library +General Public License ("LGPL"), Version 2, with exceptions for +Apple operating systems and the OpenSSL toolkit. A copy of the +exceptions and licenses follow this introduction. + +The GNU LGPL applies to the CUPS API library, located in the +"cups" subdirectory of the CUPS source distribution and in the +"cups" include directory and library files in the binary +distributions. The GNU GPL applies to the remainder of the CUPS +distribution, including the "pdftops" filter which is based upon +Xpdf and the CUPS imaging library. + +For those not familiar with the GNU GPL, the license basically +allows you to: + + - Use the CUPS software at no charge. + - Distribute verbatim copies of the software in source or + binary form. + - Sell verbatim copies of the software for a media fee, or + sell support for the software. + - Distribute or sell printer drivers and filters that use + CUPS so long as source code is made available under the + GPL. + +What this license *does not* 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. The only +exceptions to this are the portions of the CUPS software covered +by the Apple operating system license exceptions outlined later +in this license agreement. + +The GNU LGPL relaxes the "link-to" restriction, allowing you to +develop applications that use the CUPS API library under other +licenses and/or conditions as appropriate for your application. + + +LICENSE EXCEPTIONS + +In addition, as the copyright holder of CUPS, Easy Software +Products grants the following special exceptions: + + 1. Apple Operating System Development License Exception; + + a. Software that is developed by any person or entity + for an Apple Operating System ("Apple OS-Developed + Software"), including but not limited to Apple and + third party printer drivers, filters, and backends + for an Apple Operating System, that is linked to the + CUPS imaging library or based on any sample filters + or backends provided with CUPS shall not be + considered to be a derivative work or collective work + based on the CUPS program and is exempt from the + mandatory source code release clauses of the GNU GPL. + You may therefore distribute linked combinations of + the CUPS imaging library with Apple OS-Developed + Software without releasing the source code of the + Apple OS-Developed Software. You may also use sample + filters and backends provided with CUPS to develop + Apple OS-Developed Software without releasing the + source code of the Apple OS-Developed Software. + + b. An Apple Operating System means any operating system + software developed and/or marketed by Apple Computer, + Inc., including but not limited to all existing + releases and versions of Apple's Darwin, Mac OS X, + and Mac OS X Server products and all follow-on + releases and future versions thereof. + + c. This exception is only available for Apple + OS-Developed Software and does not apply to software + that is distributed for use on other operating + systems. + + d. All CUPS software that falls under this license + exception have the following text at the top of each + source file: + + This file is subject to the Apple OS-Developed + Software exception. + + 2. OpenSSL Toolkit License Exception; + + a. Easy Software Products explicitly allows the + compilation and distribution of the CUPS software + with the OpenSSL Toolkit. + +No developer is required to provide these exceptions in a +derived work. + + +TRADEMARKS + +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. Please +contract Easy Software Products for written permission to use +them in derivative products. 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. + + +BINARY DISTRIBUTION RIGHTS + +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. + +The Common UNIX Printing System provides a "pdftops" filter that +is based on the Xpdf software. For binary distribution licensing +of this software, please contact: + + Derek B. Noonburg + Email: derekn@foolabs.com + WWW: http://www.foolabs.com/xpdf/ + + +SUPPORT + +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: + + http://www.easysw.com/ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. 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 "Program", below, +refers to any such program or work, and a "work based on the Program" +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 "modification".) Each licensee is addressed as "you". + +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. + + 1. 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. + +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. + + 2. 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: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) 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. + + c) 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.) + +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. + +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. + +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. + + 3. 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: + + a) 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, + + b) 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, + + c) 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.) + +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. + +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. + + 4. 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. + + 5. 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. + + 6. 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. + + 7. 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. + +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. + +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. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. 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. + + 9. 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. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", 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. + + 10. 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. + + NO WARRANTY + + 11. 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 "AS IS" 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. + + 12. 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. + + END OF TERMS AND CONDITIONS + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. 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 "this License"). Each licensee is +addressed as "you". + + A "library" 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. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" 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 "modification".) + + "Source code" 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. + + 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. + + 1. 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. + + 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. + + 2. 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: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) 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. + + (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.) + +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. + +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. + +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. + + 3. 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. + + 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. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. 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. + + 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. + + 5. 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 "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" 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. + + 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.) + + 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. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" 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. + + 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: + + a) 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 "work that + uses the Library", 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.) + + b) 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. + + c) 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. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" 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. + + 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. + + 7. 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: + + a) 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. + + b) 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. + + 8. 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. + + 9. 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. + + 10. 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. + + 11. 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. + +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. + +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. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. 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. + + 13. 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. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", 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. + + 14. 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. + + NO WARRANTY + + 15. 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 "AS IS" 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. + + 16. 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. + + END OF TERMS AND CONDITIONS diff --git a/Makedefs.in b/Makedefs.in new file mode 100644 index 0000000000..fad4ede678 --- /dev/null +++ b/Makedefs.in @@ -0,0 +1,184 @@ +# +# "$Id$" +# +# Common makefile definitions for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 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 +# + +# +# Programs... +# + +AR = @AR@ +AWK = @AWK@ +CC = @LIBTOOL@ @CC@ +CXX = @LIBTOOL@ @CXX@ +DSO = @DSO@ +HTMLDOC = @HTMLDOC@ +INSTALL = @INSTALL@ +LIBTOOL = @LIBTOOL@ +LN = /bin/ln -sf +MV = @MV@ +NROFF = @NROFF@ +RANLIB = @RANLIB@ +RM = @RM@ -f +SED = @SED@ +SHELL = /bin/sh +STRIP = @STRIP@ + +# +# Installation programs... +# + +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... +# + +LIBCUPS = @LIBCUPS@ +LIBCUPSIMAGE = @LIBCUPSIMAGE@ +LIBJPEG = @LIBJPEG@ +LIBMALLOC = @LIBMALLOC@ +LIBPNG = @LIBPNG@ +LIBSLP = @LIBSLP@ +LIBTIFF = @LIBTIFF@ +LIBZ = @LIBZ@ + +# +# Program options... +# +# OPTIM defines the common compiler optimization/debugging options. +# OPTIONS defines other compile-time options (currently only -dDEBUG for +# extra debug info) +# + +ARFLAGS = @ARFLAGS@ +BACKLIBS = @BACKLIBS@ +CFLAGS = $(RC_CFLAGS) @CFLAGS@ -I.. $(OPTIONS) +CXXFLAGS = $(RC_CFLAGS) @CXXFLAGS@ -I.. $(OPTIONS) +CXXLIBS = @CXXLIBS@ +DSOFLAGS = @DSOFLAGS@ +DSOLIBS = @DSOLIBS@ +IMGLIBS = @IMGLIBS@ -lm +LDFLAGS = -L../cups -L../filter $(RC_CFLAGS) @LDFLAGS@ $(OPTIM) +LINKCUPS = @LINKCUPS@ +LINKCUPSIMAGE = @LINKCUPSIMAGE@ +LIBS = $(LINKCUPS) $(NETLIBS) @LIBS@ +NETLIBS = @NETLIBS@ +OPTIM = @OPTIM@ +OPTIONS = +PAMLIBS = @PAMLIBS@ +SSLLIBS = @SSLLIBS@ + +# +# Directories... +# +# The first section uses the GNU names (which are *extremely* +# difficult to find in a makefile because they are lowercase...) +# We have to define these first because autoconf uses ${prefix} +# and ${exec_prefix} for most of the other directories... +# +# This is immediately followed by definition in ALL CAPS for the +# needed directories... +# + +bindir = @bindir@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +infodir = @infodir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +top_srcdir = @top_srcdir@ + +BUILDROOT = $(DSTROOT) + +AMANDIR = $(BUILDROOT)@AMANDIR@ +BINDIR = $(BUILDROOT)@bindir@ +DATADIR = $(BUILDROOT)@CUPS_DATADIR@ +DOCDIR = $(BUILDROOT)@CUPS_DOCROOT@ +INCLUDEDIR = $(BUILDROOT)$(includedir) +INITDIR = @INITDIR@ +INITDDIR = @INITDDIR@ +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 .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.3 .man.5 .man.8: + echo Formatting $<... + $(RM) $@ + -$(NROFF) -man $< >$@ +.man.z: + echo Formatting $<... + $(RM) $@ t.z + -$(NROFF) -man $< >t + pack -f t + $(MV) t.z $@ + +# +# End of "$Id$" +# diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..4ce49fae2c --- /dev/null +++ b/Makefile @@ -0,0 +1,170 @@ +# +# "$Id$" +# +# Top-level Makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 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 +# + +include Makedefs + +# +# Directories to make... +# + +DIRS = cups backend berkeley cgi-bin filter man pdftops \ + scheduler systemv + +# +# Make all targets... +# + +all: + chmod +x cups-config + for dir in $(DIRS); do\ + echo Making all in $$dir... ;\ + (cd $$dir ; $(MAKE) $(MFLAGS)) || exit 1;\ + done + +# +# Remove object and target files... +# + +clean: + for dir in $(DIRS); do\ + echo Cleaning in $$dir... ;\ + (cd $$dir; $(MAKE) $(MFLAGS) clean) || exit 1;\ + done + +# +# Make dependencies +# + +depend: + for dir in $(DIRS); do\ + echo Making dependencies in $$dir... ;\ + (cd $$dir; $(MAKE) $(MFLAGS) depend) || exit 1;\ + done + + +# +# Install object and target files... +# + +install: installhdrs + for dir in $(DIRS); do\ + echo Installing in $$dir... ;\ + (cd $$dir; $(MAKE) $(MFLAGS) install) || exit 1;\ + done + echo Installing in conf... + (cd conf; $(MAKE) $(MFLAGS) install) + echo Installing in data... + (cd data; $(MAKE) $(MFLAGS) install) + echo Installing in doc... + (cd doc; $(MAKE) $(MFLAGS) install) + echo Installing in fonts... + (cd fonts; $(MAKE) $(MFLAGS) install) + echo Installing in locale... + (cd locale; $(MAKE) $(MFLAGS) install) + echo Installing in ppd... + (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 \ + $(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 \ + $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR); \ + if test "$(INITDDIR)" = "/System/Library/StartupItems/PrintingServices"; then \ + $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDDIR)/PrintingServices; \ + $(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 + +# +# Install source and header files... +# + +installsrc: + gnutar --dereference --exclude=CVS -cf - . | gnutar -C $(SRCROOT) -xf - + +installhdrs: + (cd cups ; $(MAKE) $(MFLAGS) installhdrs) || exit 1;\ + (cd filter ; $(MAKE) $(MFLAGS) installhdrs) || exit 1; + + +# +# Run the test suite... +# + +check test: all + echo Running CUPS test suite... + cd test; ./run-stp-tests.sh + + +# +# Make software distributions using EPM (http://www.easysw.com/epm)... +# + +EPMFLAGS = -v + +aix: + epm $(EPMFLAGS) -f aix cups + +bsd: + epm $(EPMFLAGS) -f bsd cups + +epm: + epm $(EPMFLAGS) cups + +rpm: + epm $(EPMFLAGS) -f rpm cups + +deb: + epm $(EPMFLAGS) -f deb cups + +depot: + epm $(EPMFLAGS) -f depot cups + +pkg: + epm $(EPMFLAGS) -f pkg cups + +tardist: + epm $(EPMFLAGS) -f tardist cups + +# +# End of "$Id$". +# diff --git a/README.txt b/README.txt new file mode 100644 index 0000000000..c2c2c9de2c --- /dev/null +++ b/README.txt @@ -0,0 +1,288 @@ +README - CUPS v1.1.17 - 12/02/2002 +---------------------------------- + +Looking for compile instructions? Read the file "INSTALL.txt" +instead... + +**** IF YOU HAVE A NON-POSTSCRIPT PRINTER, YOU WILL ALSO **** +**** NEED TO INSTALL ESP GHOSTSCRIPT OR A PATCHED VERSION **** +**** OF THE STANDARD GHOSTSCRIPT RELEASES. **** + + +INTRODUCTION + +CUPS provides a portable printing layer for UNIX(r)-based +operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX +vendors and users. CUPS provides the System V and Berkeley +command-line interfaces. + +CUPS uses the Internet Printing Protocol ("IPP") as the basis +for managing print jobs and queues. The Line Printer Daemon +("LPD") Server Message Block ("SMB"), and AppSocket (a.k.a. +JetDirect) protocols are also supported with reduced +functionality. CUPS adds network printer browsing and +PostScript Printer Description ("PPD") based printing options to +support real-world printing under UNIX. + +CUPS includes an image file RIP that supports printing of image +files to non-PostScript printers. A customized version of GNU +Ghostscript 7.05 for CUPS called ESP Ghostscript is available +separately to support printing of PostScript files within the +CUPS driver framework. Sample drivers for Dymo, EPSON, HP, and +OKIDATA printers are included that use these filters. + +Drivers for thousands of printers are provided with our ESP +Print Pro software, available at: + + http://www.easysw.com/printpro + +CUPS is licensed under the GNU General Public License and GNU +Library General Public License. Please contact Easy Software +Products for commercial support and "binary distribution" +rights. + + +SYSTEM REQUIREMENTS + +Binary distributions require a minimum of 10MB of free disk +space. We do not recommend using CUPS on a workstation with less +than 32MB of RAM or a PC with less than 16MB of RAM. + +If you are installing from source you'll need ANSI-compliant C +and C++ compilers and optionally one or more image file support +libraries. Complete source installation instructions can be +found in the file "INSTALL.txt". + + +SOFTWARE REQUIREMENTS + +The following operating system software is required to install +one of the binary distributions from Easy Software Products: + + - 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 + - Solaris 2.5 or higher (SPARC or Intel) + + +INSTALLING "PORTABLE" CUPS DISTRIBUTIONS + +We are currently distributing "portable" CUPS binary +distributions in TAR format with installation and removal +scripts generated by our ESP Package Manager (EPM) software, +which is available from: + + http://www.easysw.com/epm + +WARNING: Installing CUPS will overwrite your existing printing +system. Backup files are made by the installation script and +restored by the removal script, so if you experience problems +you should be able to remove the CUPS software to restore your +previous configuration. However, Easy Software Products makes +no warranty for this and will not be liable for any lost +revenues, etc. + +To install the CUPS software you will need to be logged in as +root (doing an "su" is good enough). Once you are the root +user, run the installation script with: + + ./cups.install ENTER + +After asking you a few yes/no questions the CUPS software will +be installed and the scheduler will be started automatically. + + +INSTALLING HOST-SPECIFIC (RPM, DEBIAN, ETC.) DISTRIBUTIONS + +The host-specific distributions use the operating system +software installation tools. To install a host-specific +distribution please consult the CUPS Software Administrators +Manual or your operating system documentation. + + +READING THE DOCUMENTATION + +Once you have installed the software you can access the +documentation (and a bunch of other stuff) on-line at: + + http://localhost:631 + +If you're having trouble getting that far, the documentation is +located in the "/usr/share/doc/cups" directory in the binary +distributions, and under the "doc" directory in the source +archives. + +Please read the documentation before asking questions. + + +GETTING SUPPORT AND OTHER RESOURCES + +If you have problems, READ THE DOCUMENTATION FIRST! + +You can subscribe to the CUPS mailing list by sending a message +containing "subscribe cups" to majordomo@cups.org. This list is +provided to discuss problems, questions, and improvements to the +CUPS software. New releases of CUPS are announced to this list +as well. + +Commercial support (with a guaranteed response time) is +available from Easy Software Products. For more information +see: + + http://www.easysw.com/cups + +See the CUPS web site at "http://www.cups.org" for other site +links. + + +SETTING UP PRINTER QUEUES USING YOUR WEB BROWSER + +CUPS 1.1 includes a new web-based administration tool that +allows you to manage printers, classes, and jobs on your +server. To access the printer administration tools open the +following URL in your browser: + + http://localhost:631/admin + +You will be asked for the administration password (root or any +other user in the sys/system/root group on your system) and then +shown a menu of available functions. + +DO NOT use the hostname for your machine - it will not work with +the default CUPS configuration. To enable administration access +on other addresses, consult the CUPS Software Administrators +Manual. + + +SETTING UP PRINTER QUEUES FROM THE COMMAND-LINE + +CUPS works best with PPD (PostScript Printer Description) +files. In a pinch you can also use System V style printer +interface scripts. + +Six sample PPD files are provided with this distribution that +utilize the PostScript and image file RIPs and the sample EPSON +and HP printer drivers. To add the sample DeskJet driver to the +system for a printer connected to the parallel port, use one of +the following commands: + + Digital UNIX: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp0 -E + + HP-UX: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/c2t0d0_lp -E + + IRIX: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/plp -E + + Linux: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp0 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp1 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp2 -E + + Solaris: + + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/bpp0 -E + /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/ecpp0 -E + +Similarly, for the other sample drivers you can use: + + 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 +CUPS. For commercial printer drivers check out our ESP Print +Pro software at: + + http://www.easysw.com/printpro + + +PRINTING FILES + +CUPS provides both the System V "lp" and Berkeley "lpr" commands +for printing: + + lp filename + lpr filename + +Both the "lp" and "lpr" commands support printing options for +the driver: + + lp -omedia=A4 -oresolution=600dpi filename + lpr -omedia=A4 -oresolution=600dpi filename + +CUPS recognizes many types of images files as well as PDF, +PostScript, HP-GL/2, and text files, so you can print those +files directly rather than through an application. + +If you have an application that generates output specifically +for your printer then you need to use the "-oraw" or "-l" +options: + + lp -oraw filename + lpr -l filename + +This will prevent the filters from misinterpreting your print +file. + + +LEGAL STUFF + +CUPS is Copyright 1993-2002 by Easy Software Products. CUPS, +the CUPS logo, and the Common UNIX Printing System are the +trademark property of Easy Software Products. + +The MD5 Digest code is Copyright 1999 Aladdin Enterprises. + +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 1.01 software, +Copyright 1996-2002 by Derek B. Noonburg. + +This software is based in part on the work of the Independent +JPEG Group. + +CUPS is provided under the terms of the GNU General Public +License and GNU Library General Public License. This program is +distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the "LICENSE.html", +"LICENSE.txt", or "cups.license" files for more information. + +For commercial licensing information, please contact: + + Attn: CUPS Licensing Information + Easy Software Products + 44141 Airport View Drive, Suite 204 + Hollywood, Maryland 20636-3111 USA + + Voice: +1.301.373.9600 + Email: cups-info@cups.org + WWW: http://www.cups.org + +Note that commercial licensors may also require a license from +Artifex Software Inc. which handles commercial licensing of the +Ghostscript software, and from Derek B. Noonburg who developed +the Xpdf software used to print PDF files. diff --git a/backend/.cvsignore b/backend/.cvsignore new file mode 100644 index 0000000000..e78e89c089 --- /dev/null +++ b/backend/.cvsignore @@ -0,0 +1,7 @@ +ipp +lpd +usb +parallel +betest +serial +socket diff --git a/backend/Dependencies b/backend/Dependencies new file mode 100644 index 0000000000..17c91750e4 --- /dev/null +++ b/backend/Dependencies @@ -0,0 +1,15 @@ +# DO NOT DELETE + +betest.o: ../cups/string.h ../config.h +ipp.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +ipp.o: ../cups/ppd.h ../cups/language.h ../cups/string.h ../config.h +lpd.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +lpd.o: ../cups/ppd.h ../cups/string.h ../config.h +parallel.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +parallel.o: ../cups/ppd.h ../cups/string.h ../config.h +serial.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +serial.o: ../cups/ppd.h ../cups/string.h ../config.h +socket.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +socket.o: ../cups/ppd.h ../cups/string.h ../config.h +usb.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +usb.o: ../cups/ppd.h ../cups/string.h ../config.h diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000000..ba24081097 --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,155 @@ +# +# "$Id$" +# +# Backend makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 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 +# +# This file is subject to the Apple OS-Developed Software exception. +# + +include ../Makedefs + +BACKENDS = ipp lpd parallel scsi serial socket usb +TARGETS = betest $(BACKENDS) +OBJS = betest.o ipp.o lpd.o parallel.o scsi.o serial.o socket.o usb.o + + +# +# Make all targets... +# + +all: $(TARGETS) + + +# +# Clean all object files... +# + +clean: + $(RM) $(OBJS) $(TARGETS) http + + +# +# Update dependencies (without system header dependencies...) +# + +depend: + makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1 + + +# +# Install all targets... +# + +install: all + $(INSTALL_DIR) $(SERVERBIN)/backend + for file in $(BACKENDS); do \ + $(INSTALL_BIN) $$file $(SERVERBIN)/backend; \ + done + $(RM) $(SERVERBIN)/backend/http + $(LN) ipp $(SERVERBIN)/backend/http + + +# +# betest +# + +betest: betest.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o betest betest.o $(LIBS) + + +# +# ipp +# + +ipp: ipp.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o ipp ipp.o $(LIBS) + $(RM) http + $(LN) ipp http + + +# +# lpd +# + +lpd: lpd.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpd lpd.o $(LIBS) + + +# +# parallel +# + +parallel: parallel.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o parallel parallel.o $(LIBS) + + +# +# scsi +# + +scsi: scsi.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o scsi scsi.o $(LIBS) + +scsi.o: scsi.c scsi-irix.c scsi-linux.c + + +# +# serial +# + +serial: serial.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o serial serial.o $(BACKLIBS) $(LIBS) + + +# +# socket +# + +socket: socket.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o socket socket.o $(LIBS) + + +# +# usb +# + +usb: usb.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o usb usb.o $(BACKLIBS) $(LIBS) + + +# +# Dependencies... +# + +include Dependencies + + +# +# End of "$Id$". +# diff --git a/backend/betest.c b/backend/betest.c new file mode 100644 index 0000000000..7215eb97da --- /dev/null +++ b/backend/betest.c @@ -0,0 +1,87 @@ +/* + * "$Id$" + * + * Backend test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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" 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Run the named backend. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include + + +/* + * 'main()' - Run the named backend. + * + * Usage: + * + * betest device-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (7 or 8) */ + char *argv[]) /* I - Command-line arguments */ +{ + char backend[255]; /* Method in URI */ + + + if (argc < 7 || argc > 8) + { + fputs("Usage: betest device-uri job-id user title copies options [file]\n", + stderr); + return (1); + } + + /* + * Extract the method from the device-uri - that's the program we want to + * execute. + */ + + if (sscanf(argv[1], "%254[^:]", backend) != 1) + { + fputs("betest: Bad device-uri - no colon!\n", stderr); + return (1); + } + + /* + * Execute and return + */ + + execl(backend, argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], + NULL); + + return (1); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/ipp.c b/backend/ipp.c new file mode 100644 index 0000000000..68abfa1aa3 --- /dev/null +++ b/backend/ipp.c @@ -0,0 +1,906 @@ +/* + * "$Id$" + * + * IPP backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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" 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Send a file to the printer or server. + * password_cb() - Disable the password prompt for + * cupsDoFileRequest(). + * report_printer_state() - Report the printer state. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +const char *password_cb(const char *); +int report_printer_state(ipp_t *ipp); + + +/* + * Local globals... + */ + +char *password = NULL; + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + int num_options; /* Number of printer options */ + cups_option_t *options; /* Printer options */ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info */ + resource[1024], /* Resource info (printer name) */ + filename[1024]; /* File to print */ + int port; /* Port number (not used) */ + char uri[HTTP_MAX_URI];/* Updated URI without user/pass */ + ipp_status_t ipp_status; /* Status of IPP request */ + http_t *http; /* HTTP connection */ + ipp_t *request, /* IPP request */ + *response, /* IPP response */ + *supported; /* get-printer-attributes response */ + ipp_attribute_t *job_id_attr; /* job-id attribute */ + int job_id; /* job-id value */ + ipp_attribute_t *job_state; /* job-state attribute */ + ipp_attribute_t *copies_sup; /* copies-supported attribute */ + ipp_attribute_t *charset_sup; /* charset-supported attribute */ + ipp_attribute_t *format_sup; /* document-format-supported attribute */ + ipp_attribute_t *printer_state; + /* printer-state attribute */ + ipp_attribute_t *printer_accepting; + /* printer-is-accepting-jobs attribute */ + const char *charset; /* Character set to use */ + cups_lang_t *language; /* Default language */ + int copies; /* Number of copies remaining */ + const char *content_type; /* CONTENT_TYPE environment variable */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + int version; /* IPP version */ + int reasons; /* Number of printer-state-reasons shown */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) + { + char *s; + + if ((s = strrchr(argv[0], '/')) != NULL) + s ++; + else + s = argv[0]; + + printf("network %s \"Unknown\" \"Internet Printing Protocol (%s)\"\n", s, s); + return (0); + } + else if (argc < 6 || argc > 7) + { + fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", + argv[0]); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, copy stdin to a temporary file and print the temporary + * file. + */ + + if (argc == 6) + { + /* + * Copy stdin to a temporary file... + */ + + int fd; /* Temporary file */ + char buffer[8192]; /* Buffer for copying */ + int bytes; /* Number of bytes read */ + + + if ((fd = cupsTempFd(filename, sizeof(filename))) < 0) + { + perror("ERROR: unable to create temporary file"); + return (1); + } + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + if (write(fd, buffer, bytes) < bytes) + { + perror("ERROR: unable to write to temporary file"); + close(fd); + unlink(filename); + return (1); + } + + close(fd); + } + else + strlcpy(filename, argv[6], sizeof(filename)); + + /* + * Extract the hostname and printer name from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * Set the authentication info, if any... + */ + + cupsSetPasswordCB(password_cb); + + if (username[0]) + { + if ((password = strchr(username, ':')) != NULL) + *password++ = '\0'; + + cupsSetUser(username); + } + + /* + * Try connecting to the remote server... + */ + + do + { + fprintf(stderr, "INFO: Connecting to %s on port %d...\n", hostname, port); + + if ((http = httpConnectEncrypt(hostname, port, cupsEncryption())) == NULL) + { + if (getenv("CLASS") != NULL) + { + /* + * If the CLASS environment variable is set, the job was submitted + * to a class and not to a specific queue. In this case, we want + * to abort immediately so that the job can be requeued on the next + * available printer in the class. + */ + + fprintf(stderr, "INFO: Unable to queue job on %s, queuing on next printer in class...\n", + hostname); + + if (argc == 6) + unlink(filename); + + /* + * Sleep 5 seconds to keep the job from requeuing too rapidly... + */ + + sleep(5); + + return (1); + } + + if (errno == ECONNREFUSED || errno == EHOSTDOWN || + errno == EHOSTUNREACH) + { + fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in 30 seconds...", + hostname); + sleep(30); + } + else + { + perror("ERROR: Unable to connect to IPP host"); + sleep(30); + } + } + } + while (http == NULL); + + fprintf(stderr, "INFO: Connected to %s...\n", hostname); + + /* + * Build a URI for the printer and fill the standard IPP attributes for + * an IPP_PRINT_FILE request. We can't use the URI in argv[0] because it + * might contain username:password information... + */ + + snprintf(uri, sizeof(uri), "%s://%s:%d%s", method, hostname, port, resource); + + /* + * First validate the destination and see if the device supports multiple + * copies. We have to do this because some IPP servers (e.g. HP JetDirect) + * don't support the copies attribute... + */ + + language = cupsLangDefault(); + charset_sup = NULL; + copies_sup = NULL; + format_sup = NULL; + version = 1; + supported = NULL; + + do + { + /* + * Build the IPP request... + */ + + request = ippNew(); + request->request.op.version[1] = version; + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, "utf-8"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "en"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Do the request... + */ + + fputs("DEBUG: Getting supported attributes...\n", stderr); + + if ((supported = cupsDoRequest(http, request, resource)) == NULL) + ipp_status = cupsLastError(); + else + ipp_status = supported->request.status.status_code; + + if (ipp_status > IPP_OK_CONFLICT) + { + if (ipp_status == IPP_PRINTER_BUSY || + ipp_status == IPP_SERVICE_UNAVAILABLE) + { + fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr); + report_printer_state(supported); + sleep(10); + } + else if ((ipp_status == IPP_BAD_REQUEST || + ipp_status == IPP_VERSION_NOT_SUPPORTED) && version == 1) + { + /* + * Switch to IPP/1.0... + */ + + fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr); + version = 0; + httpReconnect(http); + } + else + fprintf(stderr, "ERROR: Unable to get printer status (%s)!\n", + ippErrorString(ipp_status)); + + if (supported) + ippDelete(supported); + + continue; + } + else if ((copies_sup = ippFindAttribute(supported, "copies-supported", + IPP_TAG_RANGE)) != NULL) + { + /* + * Has the "copies-supported" attribute - does it have an upper + * bound > 1? + */ + + if (copies_sup->values[0].range.upper <= 1) + copies_sup = NULL; /* No */ + } + + charset_sup = ippFindAttribute(supported, "charset-supported", + IPP_TAG_CHARSET); + format_sup = ippFindAttribute(supported, "document-format-supported", + IPP_TAG_MIMETYPE); + + if (format_sup) + { + fprintf(stderr, "DEBUG: document-format-supported (%d values)\n", + format_sup->num_values); + for (i = 0; i < format_sup->num_values; i ++) + fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i, + format_sup->values[i].string.text); + } + + report_printer_state(supported); + } + while (ipp_status > IPP_OK_CONFLICT); + + /* + * See if the printer is accepting jobs and is not stopped; if either + * condition is true and we are printing to a class, requeue the job... + */ + + if (getenv("CLASS") != NULL) + { + printer_state = ippFindAttribute(supported, "printer-state", + IPP_TAG_ENUM); + printer_accepting = ippFindAttribute(supported, "printer-is-accepting-jobs", + IPP_TAG_BOOLEAN); + + if (printer_state == NULL || + printer_state->values[0].integer > IPP_PRINTER_PROCESSING || + printer_accepting == NULL || + !printer_accepting->values[0].boolean) + { + /* + * If the CLASS environment variable is set, the job was submitted + * to a class and not to a specific queue. In this case, we want + * to abort immediately so that the job can be requeued on the next + * available printer in the class. + */ + + fprintf(stderr, "INFO: Unable to queue job on %s, queuing on next printer in class...\n", + hostname); + + ippDelete(supported); + httpClose(http); + + if (argc == 6) + unlink(filename); + + /* + * Sleep 5 seconds to keep the job from requeuing too rapidly... + */ + + sleep(5); + + return (1); + } + } + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (argc < 7) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + + /* + * See if the printer supports multiple copies... + */ + + if (copies_sup || argc < 7) + copies = 1; + else + copies = atoi(argv[4]); + + /* + * Figure out the character set to use... + */ + + charset = language ? cupsLangEncoding(language) : "us-ascii"; + + if (charset_sup) + { + /* + * See if IPP server supports the requested character set... + */ + + for (i = 0; i < charset_sup->num_values; i ++) + if (strcasecmp(charset, charset_sup->values[i].string.text) == 0) + break; + + /* + * If not, choose us-ascii or utf-8... + */ + + if (i >= charset_sup->num_values) + { + /* + * See if us-ascii is supported... + */ + + for (i = 0; i < charset_sup->num_values; i ++) + if (strcasecmp("us-ascii", charset_sup->values[i].string.text) == 0) + break; + + if (i < charset_sup->num_values) + charset = "us-ascii"; + else + charset = "utf-8"; + } + } + + /* + * Then issue the print-job request... + */ + + reasons = 0; + + while (copies > 0) + { + /* + * Build the IPP request... + */ + + request = ippNew(); + request->request.op.version[1] = version; + request->request.op.operation_id = IPP_PRINT_JOB; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, charset); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "en"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + fprintf(stderr, "DEBUG: printer-uri = \"%s\"\n", uri); + + 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]); + + 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]); + + /* + * Handle options on the command-line... + */ + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + 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) + break; + + if (i < format_sup->num_values) + num_options = cupsAddOption("document-format", content_type, + 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 aren't supported, then we are likely dealing with an HP + * JetDirect. The HP IPP implementation seems to close the connection + * after every request (that is, it does *not* implement HTTP Keep- + * Alive, which is REQUIRED by HTTP/1.1... + */ + + if (!copies_sup) + httpReconnect(http); + + /* + * Do the request... + */ + + if ((response = cupsDoFileRequest(http, request, resource, filename)) == NULL) + ipp_status = cupsLastError(); + else + ipp_status = response->request.status.status_code; + + if (ipp_status > IPP_OK_CONFLICT) + { + job_id = 0; + + if (ipp_status == IPP_SERVICE_UNAVAILABLE || + ipp_status == IPP_PRINTER_BUSY) + { + fputs("INFO: Printer is busy; retrying print job...\n", stderr); + sleep(10); + } + else + fprintf(stderr, "ERROR: Print file was not accepted (%s)!\n", + ippErrorString(ipp_status)); + } + else if ((job_id_attr = ippFindAttribute(response, "job-id", + IPP_TAG_INTEGER)) == NULL) + { + fputs("INFO: Print file accepted - job ID unknown.\n", stderr); + job_id = 0; + } + else + { + job_id = job_id_attr->values[0].integer; + fprintf(stderr, "INFO: Print file accepted - job ID %d.\n", job_id); + } + + if (response) + ippDelete(response); + + if (ipp_status <= IPP_OK_CONFLICT && argc > 6) + { + fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1); + copies --; + } + else if (ipp_status != IPP_SERVICE_UNAVAILABLE && + ipp_status != IPP_PRINTER_BUSY) + break; + + /* + * Wait for the job to complete... + */ + + if (!job_id) + continue; + + fputs("INFO: Waiting for job to complete...\n", stderr); + + for (;;) + { + /* + * Build an IPP_GET_JOB_ATTRIBUTES request... + */ + + request = ippNew(); + request->request.op.version[1] = version; + request->request.op.operation_id = IPP_GET_JOB_ATTRIBUTES; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, charset); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "en"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", + job_id); + + if (argv[2][0]) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, argv[2]); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", NULL, "job-state"); + + /* + * Do the request... + */ + + if (!copies_sup) + httpReconnect(http); + + if ((response = cupsDoRequest(http, request, resource)) == NULL) + ipp_status = cupsLastError(); + else + ipp_status = response->request.status.status_code; + + if (ipp_status == IPP_NOT_FOUND) + { + /* + * Job has gone away and/or the server has no job history... + */ + + ippDelete(response); + + ipp_status = IPP_OK; + break; + } + + if (ipp_status > IPP_OK_CONFLICT) + { + if (ipp_status != IPP_SERVICE_UNAVAILABLE && + ipp_status != IPP_PRINTER_BUSY) + { + if (response) + ippDelete(response); + + fprintf(stderr, "ERROR: Unable to get job %d attributes (%s)!\n", + job_id, ippErrorString(ipp_status)); + break; + } + } + else if ((job_state = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL) + { + /* + * Stop polling if the job is finished or pending-held... + */ + + if (job_state->values[0].integer > IPP_JOB_PROCESSING || + job_state->values[0].integer == IPP_JOB_HELD) + { + ippDelete(response); + break; + } + } + + if (response) + ippDelete(response); + + /* + * Now check on the printer state... + */ + + request = ippNew(); + request->request.op.version[1] = version; + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, charset); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "en"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + if (argv[2][0]) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, argv[2]); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", NULL, "printer-state-reasons"); + + /* + * Do the request... + */ + + if (!copies_sup) + httpReconnect(http); + + if ((response = cupsDoRequest(http, request, resource)) != NULL) + { + reasons = report_printer_state(response); + ippDelete(response); + } + + /* + * Wait 10 seconds before polling again... + */ + + sleep(10); + } + } + + /* + * Free memory... + */ + + httpClose(http); + + if (supported) + ippDelete(supported); + + /* + * Close and remove the temporary file if necessary... + */ + + if (argc < 7) + unlink(filename); + + /* + * Return the queue status... + */ + + if (ipp_status <= IPP_OK_CONFLICT && reasons == 0) + fputs("INFO: Ready to print.\n", stderr); + + return (ipp_status > IPP_OK_CONFLICT); +} + + +/* + * 'password_cb()' - Disable the password prompt for cupsDoFileRequest(). + */ + +const char * /* O - Password */ +password_cb(const char *prompt) /* I - Prompt (not used) */ +{ + (void)prompt; + + return (password); +} + + +/* + * 'report_printer_state()' - Report the printer state. + */ + +int /* O - Number of reasons shown */ +report_printer_state(ipp_t *ipp) /* I - IPP response */ +{ + int i; /* Looping var */ + int count; /* Count of reasons shown... */ + ipp_attribute_t *reasons; /* printer-state-reasons */ + const char *message; /* Message to show */ + char unknown[1024]; /* Unknown message string */ + + + if ((reasons = ippFindAttribute(ipp, "printer-state-reasons", + IPP_TAG_KEYWORD)) == NULL) + return (0); + + for (i = 0, count = 0; i < reasons->num_values; i ++) + { + message = NULL; + + if (strncmp(reasons->values[i].string.text, "media-needed", 12) == 0) + message = "Media tray needs to be filled."; + else if (strncmp(reasons->values[i].string.text, "media-jam", 9) == 0) + message = "Media jam!"; + else if (strncmp(reasons->values[i].string.text, "moving-to-paused", 16) == 0 || + strncmp(reasons->values[i].string.text, "paused", 6) == 0 || + strncmp(reasons->values[i].string.text, "shutdown", 8) == 0) + message = "Printer off-line."; + else if (strncmp(reasons->values[i].string.text, "toner-low", 9) == 0) + message = "Toner low."; + else if (strncmp(reasons->values[i].string.text, "toner-empty", 11) == 0) + message = "Out of toner!"; + else if (strncmp(reasons->values[i].string.text, "cover-open", 10) == 0) + message = "Cover open."; + else if (strncmp(reasons->values[i].string.text, "interlock-open", 14) == 0) + message = "Interlock open."; + else if (strncmp(reasons->values[i].string.text, "door-open", 9) == 0) + message = "Door open."; + else if (strncmp(reasons->values[i].string.text, "input-tray-missing", 18) == 0) + message = "Media tray missing!"; + else if (strncmp(reasons->values[i].string.text, "media-low", 9) == 0) + message = "Media tray almost empty."; + else if (strncmp(reasons->values[i].string.text, "media-empty", 11) == 0) + message = "Media tray empty!"; + else if (strncmp(reasons->values[i].string.text, "output-tray-missing", 19) == 0) + message = "Output tray missing!"; + else if (strncmp(reasons->values[i].string.text, "output-area-almost-full", 23) == 0) + message = "Output bin almost full."; + else if (strncmp(reasons->values[i].string.text, "output-area-full", 16) == 0) + message = "Output bin full!"; + else if (strncmp(reasons->values[i].string.text, "marker-supply-low", 17) == 0) + message = "Ink/toner almost empty."; + else if (strncmp(reasons->values[i].string.text, "marker-supply-empty", 19) == 0) + message = "Ink/toner empty!"; + else if (strncmp(reasons->values[i].string.text, "marker-waste-almost-full", 24) == 0) + message = "Ink/toner waste bin almost full."; + else if (strncmp(reasons->values[i].string.text, "marker-waste-full", 17) == 0) + message = "Ink/toner waste bin full!"; + else if (strncmp(reasons->values[i].string.text, "fuser-over-temp", 15) == 0) + message = "Fuser temperature high!"; + else if (strncmp(reasons->values[i].string.text, "fuser-under-temp", 16) == 0) + message = "Fuser temperature low!"; + else if (strncmp(reasons->values[i].string.text, "opc-near-eol", 12) == 0) + message = "OPC almost at end-of-life."; + else if (strncmp(reasons->values[i].string.text, "opc-life-over", 13) == 0) + message = "OPC at end-of-life!"; + else if (strncmp(reasons->values[i].string.text, "developer-low", 13) == 0) + message = "Developer almost empty."; + else if (strncmp(reasons->values[i].string.text, "developer-empty", 15) == 0) + message = "Developer empty!"; + else if (strstr(reasons->values[i].string.text, "error") != NULL) + { + message = unknown; + + snprintf(unknown, sizeof(unknown), "Unknown printer error (%s)!", + reasons->values[i].string.text); + } + + if (message) + { + count ++; + if (strstr(reasons->values[i].string.text, "error")) + fprintf(stderr, "ERROR: %s\n", message); + else if (strstr(reasons->values[i].string.text, "warning")) + fprintf(stderr, "WARNING: %s\n", message); + else + fprintf(stderr, "INFO: %s\n", message); + } + } + + return (count); +} + + + +/* + * End of "$Id$". + */ diff --git a/backend/lpd.c b/backend/lpd.c new file mode 100644 index 0000000000..a2e1a3a77e --- /dev/null +++ b/backend/lpd.c @@ -0,0 +1,928 @@ +/* + * "$Id$" + * + * Line Printer Daemon backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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" 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Send a file to the printer or server. + * lpd_command() - Send an LPR command sequence and wait for a reply. + * lpd_queue() - Queue a file using the Line Printer Daemon protocol. + * lpd_timeout() - Handle timeout alarms... + * lpd_write() - Write a buffer of data to an LPD server. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +# include +#else +# include +# include +# include +# include +#endif /* WIN32 */ + + +/* + * The order for control and data files in LPD requests... + */ + +#define ORDER_CONTROL_DATA 0 +#define ORDER_DATA_CONTROL 1 + + +/* + * It appears that rresvport() is never declared on most systems... + */ + +extern int rresvport(int *port); + + +/* + * Local functions... + */ + +static int lpd_command(int lpd_fd, char *format, ...); +static int lpd_queue(char *hostname, char *printer, char *filename, + int fromstdin, char *user, char *title, int copies, + int banner, int format, int order, int reserve, + int manual_copies); +static void lpd_timeout(int sig); +static int lpd_write(int lpd_fd, char *buffer, int length); + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024], /* Resource info (printer name) */ + *options, /* Pointer to options */ + name[255], /* Name of option */ + value[255], /* Value of option */ + *ptr, /* Pointer into name or value */ + filename[1024], /* File to print */ + title[256]; /* Title string */ + int port; /* Port number (not used) */ + int status; /* Status of LPD job */ + int banner; /* Print banner page? */ + int format; /* Print format */ + int order; /* Order of control/data files */ + int reserve; /* Reserve priviledged port? */ + int manual_copies, /* Do manual copies? */ + copies; /* Number of copies */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; + /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) + { + puts("network lpd \"Unknown\" \"LPD/LPR Host or Printer\""); + return (0); + } + else if (argc < 6 || argc > 7) + { + fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", + argv[0]); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, copy stdin to a temporary file and print the temporary + * file. + */ + + if (argc == 6) + { + /* + * Copy stdin to a temporary file... + */ + + int fd; /* Temporary file */ + char buffer[8192]; /* Buffer for copying */ + int bytes; /* Number of bytes read */ + + + if ((fd = cupsTempFd(filename, sizeof(filename))) < 0) + { + perror("ERROR: unable to create temporary file"); + return (1); + } + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + if (write(fd, buffer, bytes) < bytes) + { + perror("ERROR: unable to write to temporary file"); + close(fd); + unlink(filename); + return (1); + } + + close(fd); + } + else + strlcpy(filename, argv[6], sizeof(filename)); + + /* + * Extract the hostname and printer name from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * See if there are any options... + */ + + banner = 0; + format = 'l'; + order = ORDER_CONTROL_DATA; + reserve = 0; + manual_copies = 1; + + if ((options = strchr(resource, '?')) != NULL) + { + /* + * Yup, terminate the device name string and move to the first + * character of the options... + */ + + *options++ = '\0'; + + /* + * Parse options... + */ + + while (*options) + { + /* + * Get the name... + */ + + for (ptr = name; *options && *options != '=';) + *ptr++ = *options++; + *ptr = '\0'; + + if (*options == '=') + { + /* + * Get the value... + */ + + options ++; + + for (ptr = value; *options && *options != '+';) + *ptr++ = *options++; + *ptr = '\0'; + + if (*options == '+') + options ++; + } + else + value[0] = '\0'; + + /* + * Process the option... + */ + + if (strcasecmp(name, "banner") == 0) + { + /* + * Set the banner... + */ + + banner = !value[0] || + strcasecmp(value, "on") == 0 || + strcasecmp(value, "yes") == 0 || + strcasecmp(value, "true") == 0; + } + else if (strcasecmp(name, "format") == 0 && value[0]) + { + /* + * Set output format... + */ + + if (strchr("cdfglnoprtv", value[0]) != NULL) + format = value[0]; + else + fprintf(stderr, "ERROR: Unknown format character \"%c\"\n", value[0]); + } + else if (strcasecmp(name, "order") == 0 && value[0]) + { + /* + * Set control/data order... + */ + + if (strcasecmp(value, "control,data") == 0) + order = ORDER_CONTROL_DATA; + else if (strcasecmp(value, "data,control") == 0) + order = ORDER_DATA_CONTROL; + else + fprintf(stderr, "ERROR: Unknown file order \"%s\"\n", value); + } + else if (strcasecmp(name, "reserve") == 0) + { + /* + * Set port reservation mode... + */ + + reserve = !value[0] || + strcasecmp(value, "on") == 0 || + strcasecmp(value, "yes") == 0 || + strcasecmp(value, "true") == 0; + } + else if (strcasecmp(name, "manual_copies") == 0) + { + /* + * Set port reservation mode... + */ + + manual_copies = !value[0] || + strcasecmp(value, "on") == 0 || + strcasecmp(value, "yes") == 0 || + strcasecmp(value, "true") == 0; + } + } + } + + /* + * Sanitize the document title... + */ + + strlcpy(title, argv[3], sizeof(title)); + + for (ptr = title; *ptr; ptr ++) + if (!isalnum(*ptr) && !isspace(*ptr)) + *ptr = '_'; + + /* + * Queue the job... + */ + + if (argc > 6) + { + if (manual_copies) + { + manual_copies = atoi(argv[4]); + copies = 1; + } + else + { + manual_copies = 1; + copies = atoi(argv[4]); + } + + status = lpd_queue(hostname, resource + 1, filename, 0, + argv[2] /* user */, title, copies, + banner, format, order, reserve, manual_copies); + + if (!status) + fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4])); + } + else + status = lpd_queue(hostname, resource + 1, filename, 1, + argv[2] /* user */, title, 1, + banner, format, order, reserve, 1); + + /* + * Remove the temporary file if necessary... + */ + + if (argc < 7) + unlink(filename); + + /* + * Return the queue status... + */ + + return (status); +} + + +/* + * 'lpd_command()' - Send an LPR command sequence and wait for a reply. + */ + +static int /* O - Status of command */ +lpd_command(int fd, /* I - Socket connection to LPD host */ + char *format, /* I - printf()-style format string */ + ...) /* I - Additional args as necessary */ +{ + va_list ap; /* Argument pointer */ + char buf[1024]; /* Output buffer */ + int bytes; /* Number of bytes to output */ + char status; /* Status from command */ + + + /* + * Format the string... + */ + + va_start(ap, format); + bytes = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + fprintf(stderr, "DEBUG: lpd_command %2.2x %s", buf[0], buf + 1); + + /* + * Send the command... + */ + + fprintf(stderr, "DEBUG: Sending command string (%d bytes)...\n", bytes); + + alarm(30); + + if (lpd_write(fd, buf, bytes) < bytes) + return (-1); + + /* + * Read back the status from the command and return it... + */ + + fprintf(stderr, "DEBUG: Reading command status...\n"); + + alarm(30); + + if (recv(fd, &status, 1, 0) < 1) + status = errno; + + alarm(0); + + fprintf(stderr, "DEBUG: lpd_command returning %d\n", status); + + return (status); +} + + +/* + * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol. + */ + +static int /* O - Zero on success, non-zero on failure */ +lpd_queue(char *hostname, /* I - Host to connect to */ + char *printer, /* I - Printer/queue name */ + char *filename, /* I - File to print */ + int fromstdin, /* I - Printing from stdin? */ + char *user, /* I - Requesting user */ + char *title, /* I - Job title */ + int copies, /* I - Number of copies */ + int banner, /* I - Print LPD banner? */ + int format, /* I - Format specifier */ + int order, /* I - Order of data/control files */ + int reserve, /* I - Reserve ports? */ + int manual_copies) /* I - Do copies by hand... */ +{ + FILE *fp; /* Job file */ + char localhost[255]; /* Local host name */ + int error; /* Error number */ + struct stat filestats; /* File statistics */ + int port; /* LPD connection port */ + int fd; /* LPD socket */ + char control[10240], /* LPD control 'file' */ + *cptr; /* Pointer into control file string */ + char status; /* Status byte from command */ + struct sockaddr_in addr; /* Socket address */ + struct hostent *hostaddr; /* Host address */ + int copy; /* Copies written */ + size_t nbytes, /* Number of bytes written */ + tbytes; /* Total bytes written */ + char buffer[8192]; /* Output buffer */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Setup an alarm handler for timeouts... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGALRM, lpd_timeout); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = lpd_timeout; + sigaction(SIGALRM, &action, NULL); +#else + signal(SIGALRM, lpd_timeout); +#endif /* HAVE_SIGSET */ + + /* + * Loop forever trying to print the file... + */ + + for (;;) /* FOREVER */ + { + /* + * First try to reserve a port for this connection... + */ + + if ((hostaddr = httpGetHostByName(hostname)) == NULL) + { + fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n", + hostname, strerror(errno)); + return (1); + } + + fprintf(stderr, "INFO: Attempting to connect to host %s for printer %s\n", + hostname, printer); + + memset(&addr, 0, sizeof(addr)); + memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length); + addr.sin_family = hostaddr->h_addrtype; + addr.sin_port = htons(515); /* LPD/printer service */ + + for (port = 732;;) + { + if (getuid() || !reserve) + { + /* + * Just create a regular socket... + */ + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("ERROR: Unable to create socket"); + return (1); + } + + port = 515; + } + else + { + /* + * We're running as root and want to comply with RFC 1179. Reserve a + * priviledged port between 721 and 732... + */ + + if ((fd = rresvport(&port)) < 0) + { + perror("ERROR: Unable to reserve port"); + sleep(30); + continue; + } + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + error = errno; + close(fd); + fd = -1; + + if (error == ECONNREFUSED || error == EHOSTDOWN || + error == EHOSTUNREACH) + { + fprintf(stderr, "WARNING: Network host \'%s\' is busy, down, or unreachable; will retry in 30 seconds...\n", + hostname); + sleep(30); + } + else if (error == EADDRINUSE) + { + port --; + if (port < 721) + port = 732; + } + else + { + perror("ERROR: Unable to connect to printer"); + sleep(30); + } + } + else + break; + } + + fprintf(stderr, "INFO: Connected from port %d...\n", port); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (fromstdin) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + + /* + * Next, open the print file and figure out its size... + */ + + if (stat(filename, &filestats)) + { + perror("ERROR: unable to stat print file"); + return (1); + } + + filestats.st_size *= manual_copies; + + if ((fp = fopen(filename, "rb")) == NULL) + { + perror("ERROR: unable to open print file for reading"); + return (1); + } + + /* + * Send a job header to the printer, specifying no banner page and + * literal output... + */ + + lpd_command(fd, "\002%s\n", printer); /* Receive print job(s) */ + + gethostname(localhost, sizeof(localhost)); + localhost[31] = '\0'; /* RFC 1179, Section 7.2 - host name < 32 chars */ + + snprintf(control, sizeof(control), "H%s\nP%s\nJ%s\n", localhost, user, title); + cptr = control + strlen(control); + + if (banner) + { + snprintf(cptr, sizeof(control) - (cptr - control), "L%s\n", user); + cptr += strlen(cptr); + } + + while (copies > 0) + { + snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%s\n", format, + getpid() % 1000, localhost); + cptr += strlen(cptr); + copies --; + } + + snprintf(cptr, sizeof(control) - (cptr - control), + "UdfA%03d%s\nN%s\n", + getpid() % 1000, localhost, title); + + fprintf(stderr, "DEBUG: Control file is:\n%s", control); + + if (order == ORDER_CONTROL_DATA) + { + lpd_command(fd, "\002%d cfA%03.3d%s\n", strlen(control), getpid() % 1000, + localhost); + + fprintf(stderr, "INFO: Sending control file (%lu bytes)\n", + (unsigned long)strlen(control)); + + alarm(30); + + if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) + { + status = errno; + perror("ERROR: Unable to write control file"); + } + else + { + alarm(30); + + if (read(fd, &status, 1) < 1) + status = errno; + + alarm(0); + } + + if (status != 0) + fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n", + status); + else + fputs("INFO: Control file sent successfully\n", stderr); + } + else + status = 0; + + if (status == 0) + { + /* + * Send the print file... + */ + + lpd_command(fd, "\003%u dfA%03.3d%s\n", (unsigned)filestats.st_size, + getpid() % 1000, localhost); + + fprintf(stderr, "INFO: Sending data file (%u bytes)\n", + (unsigned)filestats.st_size); + + tbytes = 0; + for (copy = 0; copy < manual_copies; copy ++) + { + rewind(fp); + + while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) + { + fprintf(stderr, "INFO: Spooling LPR job, %u%% complete...\n", + (unsigned)(100.0f * tbytes / filestats.st_size)); + + if (lpd_write(fd, buffer, nbytes) < nbytes) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + else + tbytes += nbytes; + } + } + + if (tbytes < filestats.st_size) + status = errno; + else if (lpd_write(fd, "", 1) < 1) + status = errno; + else + { + alarm(30); + + if (recv(fd, &status, 1, 0) < 1) + status = errno; + + alarm(0); + } + + if (status != 0) + fprintf(stderr, "ERROR: Remote host did not accept data file (%d)\n", + status); + else + fputs("INFO: Data file sent successfully\n", stderr); + } + + if (status == 0 && order == ORDER_DATA_CONTROL) + { + lpd_command(fd, "\002%d cfA%03.3d%s\n", strlen(control), getpid() % 1000, + localhost); + + fprintf(stderr, "INFO: Sending control file (%lu bytes)\n", + (unsigned long)strlen(control)); + + alarm(30); + + if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) + { + status = errno; + perror("ERROR: Unable to write control file"); + } + else + { + alarm(30); + + if (read(fd, &status, 1) < 1) + status = errno; + + alarm(0); + } + + if (status != 0) + fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n", + status); + else + fputs("INFO: Control file sent successfully\n", stderr); + } + + /* + * Close the socket connection and input file... + */ + + close(fd); + fclose(fp); + + if (status == 0) + return (0); + + /* + * Restore the SIGTERM handler if we are waiting for a retry... + */ + + if (fromstdin) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_DFL); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_DFL; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_DFL); +#endif /* HAVE_SIGSET */ + } + + sleep(30); + } +} + + +/* + * 'lpd_timeout()' - Handle timeout alarms... + */ + +static void +lpd_timeout(int sig) /* I - Signal number */ +{ + (void)sig; + +#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION) + signal(SIGALRM, lpd_timeout); +#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */ +} + + +/* + * 'lpd_write()' - Write a buffer of data to an LPD server. + */ + +static int /* O - Number of bytes written or -1 on error */ +lpd_write(int lpd_fd, /* I - LPD socket */ + char *buffer, /* I - Buffer to write */ + int length) /* I - Number of bytes to write */ +{ + int bytes, /* Number of bytes written */ + total; /* Total number of bytes written */ + + + total = 0; + while ((bytes = send(lpd_fd, buffer, length - total, 0)) >= 0) + { + total += bytes; + buffer += bytes; + + if (total == length) + break; + } + + if (bytes < 0) + return (-1); + else + return (length); +} + + +#ifndef HAVE_RRESVPORT +/* + * 'rresvport()' - A simple implementation of rresvport(). + */ + +int /* O - Socket or -1 on error */ +rresvport(int *port) /* IO - Port number to bind to */ +{ + struct sockaddr_in addr; /* Socket address */ + int fd; /* Socket file descriptor */ + + + /* + * Try to create an IPv4 socket... + */ + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return (-1); + + /* + * Initialize the address buffer... + */ + + memset(&addr, 0, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + + /* + * Try to bind the socket to a reserved port; unlike the standard + * BSD rresvport(), we limit the port number to 721 through 732 + * (instead of 512 to 1023) since RFC 1179 defines the local port + * number between 721 and 732... + */ + + while (*port > 720) + { + /* + * Set the port number... + */ + + addr.sin_port = htons(*port); + + /* + * Try binding the port to the socket; return if all is OK... + */ + + if (!bind(fd, (struct sockaddr *)&addr, sizeof(addr))) + return (fd); + + /* + * Stop if we have any error other than "address already in use"... + */ + + if (errno != EADDRINUSE) + { +# ifdef WIN32 + closesocket(fd); +# else + close(fd); +# endif /* WIN32 */ + + return (-1); + } + + /* + * Try the next port... + */ + + (*port)--; + } + + /* + * Wasn't able to bind to a reserved port, so close the socket and return + * -1... + */ + +# ifdef WIN32 + closesocket(fd); +# else + close(fd); +# endif /* WIN32 */ + + return (-1); +} +#endif /* !HAVE_RRESVPORT */ + +/* + * End of "$Id$". + */ diff --git a/backend/parallel.c b/backend/parallel.c new file mode 100644 index 0000000000..e762364db9 --- /dev/null +++ b/backend/parallel.c @@ -0,0 +1,676 @@ +/* + * "$Id$" + * + * Parallel port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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" 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Send a file to the specified parallel port. + * list_devices() - List all parallel devices. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +# include +#else +# include +# include +# include +#endif /* WIN32 */ + +#ifdef __sgi +# include +# ifndef INV_EPP_ECP_PLP +# define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */ +# define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */ +# define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */ +# define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */ +# define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */ +# endif /* !INV_EPP_ECP_PLP */ +#endif /* __sgi */ + + +/* + * Local functions... + */ + +void list_devices(void); + + +/* + * 'main()' - Send a file to the specified parallel port. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024], /* Resource info (device and options) */ + *options; /* Pointer to options */ + int port; /* Port number (not used) */ + int fp; /* Print file */ + int copies; /* Number of copies to print */ + int fd; /* Parallel device */ + int wbytes; /* Number of bytes written */ + size_t nbytes, /* Number of bytes read */ + tbytes; /* Total number of bytes written */ + char buffer[8192], /* Output buffer */ + *bufptr; /* Pointer into buffer */ + struct termios opts; /* Parallel port options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) + { + list_devices(); + return (0); + } + else if (argc < 6 || argc > 7) + { + fputs("Usage: parallel job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + { + fp = 0; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = open(argv[6], O_RDONLY)) < 0) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * Extract the device name and options from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * See if there are any options... + */ + + if ((options = strchr(resource, '?')) != NULL) + { + /* + * Yup, terminate the device name string and move to the first + * character of the options... + */ + + *options++ = '\0'; + } + + /* + * Open the parallel port device... + */ + + do + { + if ((fd = open(resource, O_WRONLY | O_EXCL)) == -1) + { + if (errno == EBUSY) + { + fputs("INFO: Parallel port busy; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else if (errno == ENXIO || errno == EIO || errno == ENOENT) + { + fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else + { + fprintf(stderr, "ERROR: Unable to open parallel port device file \"%s\": %s\n", + resource, strerror(errno)); + return (1); + } + } + } + while (fd < 0); + + /* + * Set any options provided... + */ + + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + /**** No options supported yet ****/ + + tcsetattr(fd, TCSANOW, &opts); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (argc < 7) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + + /* + * Finally, send the print file... + */ + + while (copies > 0) + { + copies --; + + if (fp != 0) + { + fputs("PAGE: 1 1\n", stderr); + lseek(fp, 0, SEEK_SET); + } + + tbytes = 0; + while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0) + { + /* + * Write the print data to the printer... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + if ((wbytes = write(fd, bufptr, nbytes)) < 0) + if (errno == ENOTTY) + wbytes = write(fd, bufptr, nbytes); + + if (wbytes < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + if (argc > 6) + fprintf(stderr, "INFO: Sending print file, %lu bytes...\n", + (unsigned long)tbytes); + } + } + + /* + * Close the socket connection and input file and return... + */ + + close(fd); + if (fp != 0) + close(fp); + + fputs("INFO: Ready to print.\n", stderr); + + return (0); +} + + +/* + * 'list_devices()' - List all parallel devices. + */ + +void +list_devices(void) +{ +#if defined(__hpux) || defined(__sgi) || defined(__sun) + static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz"; + /* Funky hex numbering used for some devices */ +#endif /* __hpux || __sgi || __sun */ + +#ifdef __linux + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255], /* Device filename */ + probefile[255], /* Probe filename */ + basedevice[255]; /* Base device filename for ports */ + FILE *probe; /* /proc/parport/n/autoprobe file */ + char line[1024], /* Line from file */ + *delim, /* Delimiter in file */ + make[IPP_MAX_NAME], /* Make from file */ + model[IPP_MAX_NAME]; /* Model from file */ + + + for (i = 0; i < 4; i ++) + { + /* + * First open the device to make sure the driver module is loaded... + */ + + if ((fd = open("/dev/parallel/0", O_WRONLY)) >= 0) + { + close(fd); + strcpy(basedevice, "/dev/parallel/"); + } + else + { + sprintf(device, "/dev/lp%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + strcpy(basedevice, "/dev/lp"); + } + else + { + sprintf(device, "/dev/par%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + strcpy(basedevice, "/dev/par"); + } + else + { + sprintf(device, "/dev/printers/%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + strcpy(basedevice, "/dev/printers/"); + } + else + strcpy(basedevice, "/dev/unknown-parallel"); + } + } + } + + /* + * Then try looking at the probe file... + */ + + sprintf(probefile, "/proc/parport/%d/autoprobe", i); + if ((probe = fopen(probefile, "r")) == NULL) + { + /* + * Linux 2.4 kernel has different path... + */ + + sprintf(probefile, "/proc/sys/dev/parport/parport%d/autoprobe", i); + probe = fopen(probefile, "r"); + } + + if (probe != NULL) + { + /* + * Found a probe file! + */ + + memset(make, 0, sizeof(make)); + memset(model, 0, sizeof(model)); + strcpy(model, "Unknown"); + + while (fgets(line, sizeof(line), probe) != NULL) + { + /* + * Strip trailing ; and/or newline. + */ + + if ((delim = strrchr(line, ';')) != NULL) + *delim = '\0'; + else if ((delim = strrchr(line, '\n')) != NULL) + *delim = '\0'; + + /* + * Look for MODEL and MANUFACTURER lines... + */ + + if (strncmp(line, "MODEL:", 6) == 0 && + strncmp(line, "MODEL:Unknown", 13) != 0) + strlcpy(model, line + 6, sizeof(model)); + else if (strncmp(line, "MANUFACTURER:", 13) == 0 && + strncmp(line, "MANUFACTURER:Unknown", 20) != 0) + strlcpy(make, line + 13, sizeof(make)); + } + + fclose(probe); + + if (make[0]) + printf("direct parallel:%s%d \"%s %s\" \"Parallel Port #%d\"\n", + basedevice, i, make, model, i + 1); + else + printf("direct parallel:%s%d \"%s\" \"Parallel Port #%d\"\n", + basedevice, i, model, i + 1); + } + else if (fd >= 0) + { + /* + * No probe file, but we know the port is there... + */ + + printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1); + } + } +#elif defined(__sgi) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + inventory_t *inv; /* Hardware inventory info */ + + + /* + * IRIX maintains a hardware inventory of most devices... + */ + + setinvent(); + + while ((inv = getinvent()) != NULL) + { + if (inv->inv_class == INV_PARALLEL && + (inv->inv_type == INV_ONBOARD_PLP || + inv->inv_type == INV_EPP_ECP_PLP)) + { + /* + * Standard parallel port... + */ + + puts("direct parallel:/dev/plp \"Unknown\" \"Onboard Parallel Port\""); + } + else if (inv->inv_class == INV_PARALLEL && + inv->inv_type == INV_EPC_PLP) + { + /* + * EPC parallel port... + */ + + printf("direct parallel:/dev/plp%d \"Unknown\" \"Integral EPC parallel port, Ebus slot %d\"\n", + inv->inv_controller, inv->inv_controller); + } + } + + endinvent(); + + /* + * Central Data makes serial and parallel "servers" that can be + * connected in a number of ways. Look for ports... + */ + + for (i = 0; i < 10; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/lpn%d%c", j, funky_hex[n]); + else if (i == 9) /* PCI */ + sprintf(device, "/dev/lpp%d%c", j, funky_hex[n]); + else /* SCSI */ + sprintf(device, "/dev/lp%d%d%c", i, j, funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n", + device, j, n); + else if (i == 9) + printf("direct parallel:%s \"Unknown\" \"Central Data PCI Parallel Port, ID %d, port %d\"\n", + device, j, n); + else + printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__sun) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + + + /* + * Standard parallel ports... + */ + + for (i = 0; i < 10; i ++) + { + sprintf(device, "/dev/ecpp%d", i); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"Sun IEEE-1284 Parallel Port #%d\"\n", + device, i + 1); + } + + for (i = 0; i < 10; i ++) + { + sprintf(device, "/dev/bpp%d", i); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"Sun Standard Parallel Port #%d\"\n", + device, i + 1); + } + + for (i = 0; i < 3; i ++) + { + sprintf(device, "/dev/lp%d", i); + + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"PC Parallel Port #%d\"\n", + device, i + 1); + } + + /* + * MAGMA parallel ports... + */ + + for (i = 0; i < 40; i ++) + { + sprintf(device, "/dev/pm%02d", i); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"MAGMA Parallel Board #%d Port #%d\"\n", + device, (i / 10) + 1, (i % 10) + 1); + } + + /* + * Central Data parallel ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/sts/lpN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/sts/lp%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n", + device, j, n); + else + printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__hpux) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + + + /* + * Standard parallel ports... + */ + + if (access("/dev/rlp", 0) == 0) + puts("direct parallel:/dev/rlp \"Unknown\" \"Standard Parallel Port (/dev/rlp)\""); + + for (i = 0; i < 7; i ++) + for (j = 0; j < 7; j ++) + { + sprintf(device, "/dev/c%dt%dd0_lp", i, j); + if (access(device, 0) == 0) + printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d,%d\"\n", + device, i, j); + } + + /* + * Central Data parallel ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/lpN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/lp%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n", + device, j, n); + else + printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__osf__) + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 3; 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); + } + } +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 3; i ++) + { + sprintf(device, "/dev/lpt%d", i); + if ((fd = open(device, O_WRONLY)) >= 0) + { + close(fd); + 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); + } + } +#endif +} + + +/* + * End of "$Id$". + */ diff --git a/backend/scsi-irix.c b/backend/scsi-irix.c new file mode 100644 index 0000000000..1c2f9943c5 --- /dev/null +++ b/backend/scsi-irix.c @@ -0,0 +1,211 @@ +/* + * "$Id$" + * + * IRIX SCSI printer support for the Common UNIX Printing System (CUPS). + * + * Copyright 2002 by Easy Software Products, all rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use + * of this software must display the following + * acknowledgement: + * + * This product includes software developed by Easy + * Software Products. + * + * 4. The name of Easy Software Products may not be used to + * endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Contents: + * + * list_devices() - List the available SCSI printer devices. + * print_device() - Print a file to a SCSI device. + */ + +/* + * Include necessary headers. + */ + +#include /* memcpy() and friends */ +#include /* SCSI interface stuff */ + + +/* + * 'list_devices()' - List the available SCSI printer devices. + */ + +void +list_devices(void) +{ + puts("direct scsi \"Unknown\" \"SCSI Printer\""); +} + + +/* + * 'print_device()' - Print a file to a SCSI device. + */ + +int /* O - Print status */ +print_device(const char *resource, /* I - SCSI device */ + int fd, /* I - File to print */ + int copies) /* I - Number of copies to print */ +{ + int scsi_fd; /* SCSI file descriptor */ + char buffer[8192]; /* Data buffer */ + int bytes; /* Number of bytes */ + int try; /* Current try */ + dsreq_t scsi_req; /* SCSI request */ + char scsi_cmd[6], /* SCSI command data */ + scsi_sense[32]; /* SCSI sense data */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure we have a valid resource name... + */ + + if (strncmp(resource, "/dev/scsi/", 10) != 0) + { + fprintf(stderr, "ERROR: Bad SCSI device file \"%s\"!\n", resource); + return (1); + } + + /* + * Open the SCSI device file... + */ + + do + { + if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1) + { + if (errno != EAGAIN && errno != EBUSY) + { + fprintf(stderr, "ERROR: Unable to open SCSI device \"%s\" - %s\n", + resource, strerror(errno)); + return (1); + } + else + { + fprintf(stderr, "INFO: SCSI device \"%s\" busy; retrying...\n", + resource); + sleep(30); + } + } + } + while (scsi_fd == -1); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (fd != 0) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + + /* + * Copy the print file to the device... + */ + + while (copies > 0) + { + if (fd != 0) + lseek(fd, 0, SEEK_SET); + + while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) + { + memset(&scsi_req, 0, sizeof(scsi_req)); + + scsi_req.ds_flags = DSRQ_WRITE; + scsi_req.ds_time = 60 * 1000; + scsi_req.ds_cmdbuf = scsi_cmd; + scsi_req.ds_cmdlen = 6; + scsi_req.ds_databuf = buffer; + scsi_req.ds_datalen = bytes; + + scsi_cmd[0] = 0x0a; /* Group 0 print command */ + scsi_cmd[1] = 0x00; + scsi_cmd[2] = bytes / 65536; + scsi_cmd[3] = bytes / 256; + scsi_cmd[4] = bytes; + scsi_cmd[5] = 0x00; + + for (try = 0; try < 10; try ++) + if (ioctl(scsi_fd, DS_ENTER, &scsi_req) < 0 || + scsi_req.ds_status != 0) + { + fprintf(stderr, "WARNING: SCSI command timed out (%d); retrying...\n", + scsi_req.ds_status); + sleep(try + 1); + } + else + break; + + if (try >= 10) + { + fprintf(stderr, "ERROR: Unable to send print data (%d)\n", + scsi_req.ds_status); + close(scsi_fd); + return (1); + } + } + + copies --; + } + + /* + * Close the device and return... + */ + + close(fd); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/scsi-linux.c b/backend/scsi-linux.c new file mode 100644 index 0000000000..66fdd9c88c --- /dev/null +++ b/backend/scsi-linux.c @@ -0,0 +1,228 @@ +/* + * "$Id$" + * + * Linux SCSI printer support for the Common UNIX Printing System (CUPS). + * + * Copyright 2002 by Easy Software Products, all rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use + * of this software must display the following + * acknowledgement: + * + * This product includes software developed by Easy + * Software Products. + * + * 4. The name of Easy Software Products may not be used to + * endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Contents: + * + * list_devices() - List the available SCSI printer devices. + * print_device() - Print a file to a SCSI device. + */ + +/* + * Include necessary headers. + */ + +#include + + +/* + * We currently only support the Linux 2.4 generic SCSI interface. + */ + +#ifndef SG_DXFER_TO_DEV +/* + * Dummy functions that do nothing on unsupported platforms... + */ +void list_devices(void) {} +int print_device(const char *resource, int fd, int copies) { return (1); } +#else + + +/* + * 'list_devices()' - List the available SCSI printer devices. + */ + +void +list_devices(void) +{ + puts("direct scsi \"Unknown\" \"SCSI Printer\""); +} + + +/* + * 'print_device()' - Print a file to a SCSI device. + */ + +int /* O - Print status */ +print_device(const char *resource, /* I - SCSI device */ + int fd, /* I - File to print */ + int copies) /* I - Number of copies to print */ +{ + int scsi_fd; /* SCSI file descriptor */ + char buffer[8192]; /* Data buffer */ + int bytes; /* Number of bytes */ + int try; /* Current try */ + sg_io_hdr_t scsi_req; /* SCSI request */ + char scsi_cmd[6], /* SCSI command data */ + scsi_sense[32]; /* SCSI sense data */ +# if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +# endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure we have a valid resource name... + */ + + if (strncmp(resource, "/dev/sg", 7) != 0) + { + fprintf(stderr, "ERROR: Bad SCSI device file \"%s\"!\n", resource); + return (1); + } + + /* + * Open the SCSI device file... + */ + + do + { + if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1) + { + if (errno != EAGAIN && errno != EBUSY) + { + fprintf(stderr, "ERROR: Unable to open SCSI device \"%s\" - %s\n", + resource, strerror(errno)); + return (1); + } + else + { + fprintf(stderr, "INFO: SCSI device \"%s\" busy; retrying...\n", + resource); + sleep(30); + } + } + } + while (scsi_fd == -1); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (fd != 0) + { +# ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +# elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +# else + signal(SIGTERM, SIG_IGN); +# endif /* HAVE_SIGSET */ + } + + /* + * Copy the print file to the device... + */ + + while (copies > 0) + { + if (fd != 0) + lseek(fd, 0, SEEK_SET); + + while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) + { + memset(&scsi_req, 0, sizeof(scsi_req)); + + scsi_req.interface_id = 'S'; + scsi_req.dxfer_direction = SG_DXFER_TO_DEV; + scsi_req.cmd_len = 6; + scsi_req.mx_sb_len = sizeof(scsi_sense); + scsi_req.iovec_count = 0; + scsi_req.dxfer_len = bytes; + scsi_req.dxferp = buffer; + scsi_req.cmdp = scsi_cmd; + scsi_req.sbp = scsi_sense; + scsi_req.timeout = 60 * 1000; + + scsi_cmd[0] = 0x0a; /* Group 0 print command */ + scsi_cmd[1] = 0x00; + scsi_cmd[2] = bytes / 65536; + scsi_cmd[3] = bytes / 256; + scsi_cmd[4] = bytes; + scsi_cmd[5] = 0x00; + + for (try = 0; try < 10; try ++) + if (ioctl(scsi_fd, SG_IO, &scsi_req) < 0 || + scsi_req.status != 0) + { + fprintf(stderr, "WARNING: SCSI command timed out (%d); retrying...\n", + scsi_req.status); + sleep(try + 1); + } + else + break; + + if (try >= 10) + { + fprintf(stderr, "ERROR: Unable to send print data (%d)\n", + scsi_req.status); + close(scsi_fd); + return (1); + } + } + + copies --; + } + + /* + * Close the device and return... + */ + + close(fd); + + return (0); +} +#endif /* !SG_DXFER_TO_DEV */ + + +/* + * End of "$Id$". + */ diff --git a/backend/scsi.c b/backend/scsi.c new file mode 100644 index 0000000000..44fd6b4350 --- /dev/null +++ b/backend/scsi.c @@ -0,0 +1,223 @@ +/* + * "$Id$" + * + * SCSI printer backend for the Common UNIX Printing System (CUPS). + * + * Copyright 2002 by Easy Software Products, all rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use + * of this software must display the following + * acknowledgement: + * + * This product includes software developed by Easy + * Software Products. + * + * 4. The name of Easy Software Products may not be used to + * endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Contents: + * + * main() - Send a file to the specified SCSI printer. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +# include +#else +# include +# include +# ifdef HAVE_SYS_IOCTL_H +# include +# endif /* HAVE_SYS_IOCTL_H */ +#endif /* WIN32 */ + + +/* + * Local functions... + */ + +void list_devices(void); +int print_device(const char *resource, int fd, int copies); + + +#ifdef __linux__ +# include "scsi-linux.c" +#elif defined(__sgi) +# include "scsi-irix.c" +#else +/* + * Dummy functions that do nothing on unsupported platforms... + */ +void list_devices(void) {} +int print_device(const char *resource, int fd, int copies) { return (1); } +#endif /* __linux */ + + +/* + * 'main()' - Send a file to the specified SCSI printer. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024], /* Resource info (device and options) */ + *options; /* Pointer to options */ + int port; /* Port number (not used) */ + int fp; /* Print file */ + int copies; /* Number of copies to print */ + int status; /* Exit status */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) + { + list_devices(); + return (0); + } + else if (argc < 6 || argc > 7) + { + fputs("Usage: scsi:/dev/file job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + { + fp = 0; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = open(argv[6], O_RDONLY)) < 0) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * Extract the device name and options from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * See if there are any options... + */ + + if ((options = strchr(resource, '?')) != NULL) + { + /* + * Yup, terminate the device name string and move to the first + * character of the options... + */ + + *options++ = '\0'; + } + + /* + * Finally, send the print file... + */ + + status = print_device(resource, fp, copies); + + /* + * Close input file and return... + */ + + if (fp != 0) + close(fp); + + if (!status) + fputs("INFO: Ready to print.\n", stderr); + + return (status); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/serial.c b/backend/serial.c new file mode 100644 index 0000000000..0f142bc0c3 --- /dev/null +++ b/backend/serial.c @@ -0,0 +1,991 @@ +/* + * "$Id$" + * + * Serial port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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" 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Send a file to the printer or server. + * list_devices() - List all serial devices. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __hpux +# include +#endif /* __hpux */ + +#ifdef WIN32 +# include +#else +# include +# include +# include +# ifdef HAVE_SYS_IOCTL_H +# include +# endif /* HAVE_SYS_IOCTL_H */ +#endif /* WIN32 */ + +#ifdef __sgi +# include +# ifndef INV_EPP_ECP_PLP +# define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */ +# define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */ +# define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */ +# define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */ +# define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */ +# endif /* !INV_EPP_ECP_PLP */ +#endif /* __sgi */ + +#ifndef CRTSCTS +# ifdef CNEW_RTSCTS +# define CRTSCTS CNEW_RTSCTS +# else +# define CRTSCTS 0 +# endif /* CNEW_RTSCTS */ +#endif /* !CRTSCTS */ + +#if defined(__APPLE__) +# include +# include +# include +# include +#endif /* __APPLE__ */ + + +/* + * Local functions... + */ + +void list_devices(void); + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024], /* Resource info (device and options) */ + *options, /* Pointer to options */ + name[255], /* Name of option */ + value[255], /* Value of option */ + *ptr; /* Pointer into name or value */ + int port; /* Port number (not used) */ + int fp; /* Print file */ + int copies; /* Number of copies to print */ + int fd; /* Parallel device */ + int wbytes; /* Number of bytes written */ + size_t nbytes, /* Number of bytes read */ + tbytes; /* Total number of bytes written */ + int dtrdsr; /* Do dtr/dsr flow control? */ + int bufsize; /* Size of output buffer for writes */ + char buffer[8192], /* Output buffer */ + *bufptr; /* Pointer into buffer */ + struct termios opts; /* Serial port options */ + struct termios origopts; /* Original port options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) + { + list_devices(); + return (0); + } + else if (argc < 6 || argc > 7) + { + fputs("Usage: serial job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + { + fp = 0; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = open(argv[6], O_RDONLY)) < 0) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * Extract the device name and options from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * See if there are any options... + */ + + if ((options = strchr(resource, '?')) != NULL) + { + /* + * Yup, terminate the device name string and move to the first + * character of the options... + */ + + *options++ = '\0'; + } + + /* + * Open the serial port device... + */ + + do + { + if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL | O_NDELAY)) == -1) + { + if (errno == EBUSY) + { + fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else + { + fprintf(stderr, "ERROR: Unable to open serial port device file \"%s\": %s\n", + resource, strerror(errno)); + return (1); + } + } + } + while (fd < 0); + + /* + * Set any options provided... + */ + + tcgetattr(fd, &origopts); + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + opts.c_oflag &= ~OPOST; /* Don't post-process */ + + bufsize = 96; /* 9600 baud / 10 bits/char / 10Hz */ + dtrdsr = 0; /* No dtr/dsr flow control */ + + if (options != NULL) + while (*options) + { + /* + * Get the name... + */ + + for (ptr = name; *options && *options != '=';) + *ptr++ = *options++; + *ptr = '\0'; + + if (*options == '=') + { + /* + * Get the value... + */ + + options ++; + + for (ptr = value; *options && *options != '+';) + *ptr++ = *options++; + *ptr = '\0'; + + if (*options == '+') + options ++; + } + else + value[0] = '\0'; + + /* + * Process the option... + */ + + if (strcasecmp(name, "baud") == 0) + { + /* + * Set the baud rate... + */ + + bufsize = atoi(value) / 100; + +#if B19200 == 19200 + cfsetispeed(&opts, atoi(value)); + cfsetospeed(&opts, atoi(value)); +#else + switch (atoi(value)) + { + case 1200 : + cfsetispeed(&opts, B1200); + cfsetospeed(&opts, B1200); + break; + case 2400 : + cfsetispeed(&opts, B2400); + cfsetospeed(&opts, B2400); + break; + case 4800 : + cfsetispeed(&opts, B4800); + cfsetospeed(&opts, B4800); + break; + case 9600 : + cfsetispeed(&opts, B9600); + cfsetospeed(&opts, B9600); + break; + case 19200 : + cfsetispeed(&opts, B19200); + cfsetospeed(&opts, B19200); + break; + case 38400 : + cfsetispeed(&opts, B38400); + cfsetospeed(&opts, B38400); + break; +# ifdef B57600 + case 57600 : + cfsetispeed(&opts, B57600); + cfsetospeed(&opts, B57600); + break; +# endif /* B57600 */ +# ifdef B115200 + case 115200 : + cfsetispeed(&opts, B115200); + cfsetospeed(&opts, B115200); + break; +# endif /* B115200 */ +# ifdef B230400 + case 230400 : + cfsetispeed(&opts, B230400); + cfsetospeed(&opts, B230400); + break; +# endif /* B230400 */ + default : + fprintf(stderr, "WARNING: Unsupported baud rate %s!\n", value); + break; + } +#endif /* B19200 == 19200 */ + } + else if (strcasecmp(name, "bits") == 0) + { + /* + * Set number of data bits... + */ + + switch (atoi(value)) + { + case 7 : + opts.c_cflag &= ~CSIZE; + opts.c_cflag |= CS7; + opts.c_cflag |= PARENB; + opts.c_cflag &= ~PARODD; + break; + case 8 : + opts.c_cflag &= ~CSIZE; + opts.c_cflag |= CS8; + opts.c_cflag &= ~PARENB; + break; + } + } + else if (strcasecmp(name, "parity") == 0) + { + /* + * Set parity checking... + */ + + if (strcasecmp(value, "even") == 0) + { + opts.c_cflag |= PARENB; + opts.c_cflag &= ~PARODD; + } + else if (strcasecmp(value, "odd") == 0) + { + opts.c_cflag |= PARENB; + opts.c_cflag |= PARODD; + } + else if (strcasecmp(value, "none") == 0) + opts.c_cflag &= ~PARENB; + } + else if (strcasecmp(name, "flow") == 0) + { + /* + * Set flow control... + */ + + if (strcasecmp(value, "none") == 0) + { + opts.c_iflag &= ~(IXON | IXOFF | IXANY); + opts.c_cflag &= ~CRTSCTS; + } + else if (strcasecmp(value, "soft") == 0) + { + opts.c_iflag |= IXON | IXOFF | IXANY; + opts.c_cflag &= ~CRTSCTS; + } + else if (strcasecmp(value, "hard") == 0 || + strcasecmp(value, "rtscts") == 0) + { + opts.c_iflag &= ~(IXON | IXOFF | IXANY); + opts.c_cflag |= CRTSCTS; + } + else if (strcasecmp(value, "dtrdsr") == 0) + { + opts.c_iflag &= ~(IXON | IXOFF | IXANY); + opts.c_cflag &= ~CRTSCTS; + + dtrdsr = 1; + } + } + } + + tcsetattr(fd, TCSANOW, &opts); + fcntl(fd, F_SETFL, 0); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (argc < 7) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + + /* + * Finally, send the print file... + */ + + if (bufsize > sizeof(buffer)) + bufsize = sizeof(buffer); + + while (copies > 0) + { + copies --; + + if (fp != 0) + { + fputs("PAGE: 1 1\n", stderr); + lseek(fp, 0, SEEK_SET); + } + + if (dtrdsr) + { + /* + * Check the port and sleep until DSR is set... + */ + + int status; + + + if (!ioctl(fd, TIOCMGET, &status)) + if (!(status & TIOCM_DSR)) + { + /* + * Wait for DSR to go high... + */ + + fputs("DEBUG: DSR is low; waiting for device...\n", stderr); + + do + { + sleep(1); + if (ioctl(fd, TIOCMGET, &status)) + break; + } + while (!(status & TIOCM_DSR)); + + fputs("DEBUG: DSR is high; writing to device...\n", stderr); + } + } + + tbytes = 0; + while ((nbytes = read(fp, buffer, bufsize)) > 0) + { + /* + * Write the print data to the printer... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + if ((wbytes = write(fd, bufptr, nbytes)) < 0) + if (errno == ENOTTY) + wbytes = write(fd, bufptr, nbytes); + + if (wbytes < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + if (argc > 6) + fprintf(stderr, "INFO: Sending print file, %lu bytes...\n", + (unsigned long)tbytes); + } + } + + /* + * Close the serial port and input file and return... + */ + + tcsetattr(fd, TCSADRAIN, &origopts); + + close(fd); + if (fp != 0) + close(fp); + + fputs("INFO: Ready to print.\n", stderr); + + return (0); +} + + +/* + * 'list_devices()' - List all serial devices. + */ + +void +list_devices(void) +{ +#if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) + static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz"; + /* Funky hex numbering used for some devices */ +#endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */ + +#if defined(__linux) || defined(linux) || defined(__linux__) + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 100; i ++) + { + sprintf(device, "/dev/ttyS%d", i); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); +# if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc) + printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); +# else + printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); +# endif // _ARCH_PPC || powerpc || __powerpc + } + } + + for (i = 0; i < 16; i ++) + { + sprintf(device, "/dev/usb/ttyUSB%d", i); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n", + device, i + 1); + } + } +#elif defined(__sgi) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + inventory_t *inv; /* Hardware inventory info */ + + + /* + * IRIX maintains a hardware inventory of most devices... + */ + + setinvent(); + + while ((inv = getinvent()) != NULL) + { + if (inv->inv_class == INV_SERIAL) + { + /* + * Some sort of serial port... + */ + + if (inv->inv_type == INV_CDSIO || inv->inv_type == INV_CDSIO_E) + { + /* + * CDSIO port... + */ + + for (n = 0; n < 6; n ++) + printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n", + n + 5 + 8 * inv->inv_controller, inv->inv_controller, n + 1); + } + else if (inv->inv_type == INV_EPC_SERIAL) + { + /* + * Everest serial port... + */ + + if (inv->inv_unit == 0) + i = 1; + else + i = 41 + 4 * (int)inv->inv_controller; + + for (n = 0; n < (int)inv->inv_state; n ++) + printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n", + n + i, n + 1, (int)inv->inv_controller); + } + else if (inv->inv_state > 1) + { + /* + * Standard serial port under IRIX 6.4 and earlier... + */ + + for (n = 0; n < (int)inv->inv_state; n ++) + printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"Onboard Serial Port %d\"\n", + n + (int)inv->inv_unit + 1, n + (int)inv->inv_unit + 1); + } + else + { + /* + * Standard serial port under IRIX 6.5 and beyond... + */ + + printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n", + (int)inv->inv_controller, (int)inv->inv_controller); + } + } + } + + endinvent(); + + /* + * Central Data makes serial and parallel "servers" that can be + * connected in a number of ways. Look for ports... + */ + + for (i = 0; i < 10; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/ttydn%d%c", j, funky_hex[n]); + else if (i == 9) /* PCI */ + sprintf(device, "/dev/ttydp%d%c", j, funky_hex[n]); + else /* SCSI */ + sprintf(device, "/dev/ttyd%d%d%c", i, j, funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n", + device, j, n); + else if (i == 9) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n", + device, j, n); + else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__sun) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 26; i ++) + { + sprintf(device, "/dev/cua/%c", 'a' + i); + if (access(device, 0) == 0) +#ifdef B115200 + printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); +#else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); +#endif /* B115200 */ + } + + /* + * MAGMA serial ports... + */ + + for (i = 0; i < 40; i ++) + { + sprintf(device, "/dev/term/%02d", i); + if (access(device, 0) == 0) + printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n", + device, (i / 10) + 1, (i % 10) + 1); + } + + /* + * Central Data serial ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/sts/ttyN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/sts/tty%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n", + device, j, n); + else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__hpux) + int i, j, n; /* Looping vars */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 10; i ++) + { + sprintf(device, "/dev/tty%dp0", i); + if (access(device, 0) == 0) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } + + /* + * Central Data serial ports... + */ + + for (i = 0; i < 9; i ++) + for (j = 0; j < 8; j ++) + for (n = 0; n < 32; n ++) + { + if (i == 8) /* EtherLite */ + sprintf(device, "/dev/ttyN%d%c", j, funky_hex[n]); + else + sprintf(device, "/dev/tty%c%d%c", i + 'C', j, + funky_hex[n]); + + if (access(device, 0) == 0) + { + if (i == 8) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n", + device, j, n); + else + printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n", + device, i, j, n); + } + } +#elif defined(__osf__) + int i; /* Looping var */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 100; i ++) + { + sprintf(device, "/dev/tty%02d", i); + if (access(device, 0) == 0) + printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } +#elif defined(__FreeBSD__) || defined(__OpenBSD__) + int i, j; /* Looping vars */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + /* + * SIO ports... + */ + + for (i = 0; i < 32; i ++) + { + sprintf(device, "/dev/ttyd%c", funky_hex[i]); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n", + device, i + 1); + } + } + + /* + * Cyclades ports... + */ + + for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */ + for (j = 0; j < 32; j ++) + { + sprintf(device, "/dev/ttyc%d%c", i, funky_hex[j]); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n", + device, i, j + 1); + } + } + + /* + * Digiboard ports... + */ + + for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */ + for (j = 0; j < 32; j ++) + { + sprintf(device, "/dev/ttyD%d%c", i, funky_hex[j]); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n", + device, i, j + 1); + } + } + + /* + * Stallion ports... + */ + + for (i = 0; i < 32; i ++) + { + sprintf(device, "/dev/ttyE%c", funky_hex[i]); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n", + device, i + 1); + } + } + + /* + * SX ports... + */ + + for (i = 0; i < 128; i ++) + { + sprintf(device, "/dev/ttyA%d", i + 1); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n", + device, i + 1); + } + } +#elif defined(__NetBSD__) + int i, j; /* Looping vars */ + int fd; /* File descriptor */ + char device[255]; /* Device filename */ + + + /* + * Standard serial ports... + */ + + for (i = 0; i < 4; i ++) + { + sprintf(device, "/dev/tty%02d", i); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n", + device, i + 1); + } + } + + /* + * Cyclades-Z ports... + */ + + for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */ + for (j = 0; j < 64; j ++) + { + sprintf(device, "/dev/ttyCZ%02d%02d", i, j); + if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) + { + close(fd); + printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n", + device, i, j + 1); + } + } +#elif defined(__APPLE__) + /* + * Standard serial ports on MacOS X... + */ + + kern_return_t kernResult; + mach_port_t masterPort; + io_iterator_t serialPortIterator; + CFMutableDictionaryRef classesToMatch; + io_object_t serialService; + + printf("serial serial \"Unknown\" \"Serial Printer (serial)\"\n"); + + kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); + if (KERN_SUCCESS != kernResult) + return; + + /* + * Serial devices are instances of class IOSerialBSDClient. + */ + + classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch != NULL) + { + CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), + CFSTR(kIOSerialBSDRS232Type)); + + kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, + &serialPortIterator); + if (kernResult == KERN_SUCCESS) + { + while ((serialService = IOIteratorNext(serialPortIterator))) + { + CFTypeRef serialNameAsCFString; + CFTypeRef bsdPathAsCFString; + char serialName[128]; + char bsdPath[1024]; + Boolean result; + + + serialNameAsCFString = + IORegistryEntryCreateCFProperty(serialService, + CFSTR(kIOTTYDeviceKey), + kCFAllocatorDefault, 0); + if (serialNameAsCFString) + { + result = CFStringGetCString(serialNameAsCFString, serialName, + sizeof(serialName), + kCFStringEncodingASCII); + CFRelease(serialNameAsCFString); + + if (result) + { + bsdPathAsCFString = + IORegistryEntryCreateCFProperty(serialService, + CFSTR(kIOCalloutDeviceKey), + kCFAllocatorDefault, 0); + if (bsdPathAsCFString) + { + result = CFStringGetCString(bsdPathAsCFString, bsdPath, + sizeof(bsdPath), + kCFStringEncodingASCII); + CFRelease(bsdPathAsCFString); + + if (result) + printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", bsdPath, + serialName); + } + } + } + + IOObjectRelease(serialService); + } + + IOObjectRelease(serialPortIterator); /* Release the iterator. */ + } + } +#endif +} + + +/* + * End of "$Id$". + */ diff --git a/backend/socket.c b/backend/socket.c new file mode 100644 index 0000000000..02b1e3fe2e --- /dev/null +++ b/backend/socket.c @@ -0,0 +1,367 @@ +/* + * "$Id$" + * + * AppSocket backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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" 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Send a file to the printer or server. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +# include +#else +# include +# include +# include +# include +# include +# include +#endif /* WIN32 */ + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024]; /* Resource info (not used) */ + int fp; /* Print file */ + int copies; /* Number of copies to print */ + int port; /* Port number */ + int delay; /* Delay for retries... */ + int fd; /* AppSocket */ + int error; /* Error code (if any) */ + struct sockaddr_in addr; /* Socket address */ + struct hostent *hostaddr; /* Host address */ + int wbytes; /* Number of bytes written */ + size_t nbytes, /* Number of bytes read */ + tbytes; /* Total number of bytes written */ + char buffer[8192], /* Output buffer */ + *bufptr; /* Pointer into buffer */ + struct timeval timeout; /* Timeout for select() */ + fd_set input; /* Input set for select() */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) + { + puts("network socket \"Unknown\" \"AppSocket/HP JetDirect\""); + return (0); + } + else if (argc < 6 || argc > 7) + { + fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", + argv[0]); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + { + fp = 0; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = open(argv[6], O_RDONLY)) < 0) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * Extract the hostname and port number from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + if (port == 0) + port = 9100; /* Default to HP JetDirect/Tektronix PhaserShare */ + + /* + * Then try to connect to the remote host... + */ + + if ((hostaddr = httpGetHostByName(hostname)) == NULL) + { + fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n", + hostname, strerror(errno)); + return (1); + } + + fprintf(stderr, "INFO: Attempting to connect to host %s on port %d\n", + hostname, port); + + memset(&addr, 0, sizeof(addr)); + memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length); + addr.sin_family = hostaddr->h_addrtype; + addr.sin_port = htons(port); + + while (copies > 0) + { + for (delay = 5;;) + { + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("ERROR: Unable to create socket"); + return (1); + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + error = errno; + close(fd); + fd = -1; + + if (error == ECONNREFUSED || error == EHOSTDOWN || + error == EHOSTUNREACH) + { + fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n", + hostname, delay); + sleep(delay); + + if (delay < 30) + delay += 5; + } + else + { + perror("ERROR: Unable to connect to printer (retrying in 30 seconds)"); + sleep(30); + } + } + else + break; + } + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (argc < 7) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + + /* + * Finally, send the print file... + */ + + copies --; + + if (fp != 0) + { + fputs("PAGE: 1 1\n", stderr); + lseek(fp, 0, SEEK_SET); + } + + fputs("INFO: Connected to host, sending print job...\n", stderr); + + tbytes = 0; + while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0) + { + /* + * Write the print data to the printer... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + if ((wbytes = send(fd, bufptr, nbytes, 0)) < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + /* + * Check for possible data coming back from the printer... + */ + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + FD_ZERO(&input); + FD_SET(fd, &input); +#ifdef __hpux + if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0) +#else + if (select(fd + 1, &input, NULL, NULL, &timeout) > 0) +#endif /* __hpux */ + { + /* + * Grab the data coming back and spit it out to stderr... + */ + + if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0) + fprintf(stderr, "INFO: Received %lu bytes of back-channel data!\n", + (unsigned long)nbytes); + } + else if (argc > 6) + fprintf(stderr, "INFO: Sending print file, %lu bytes...\n", + (unsigned long)tbytes); + } + + /* + * Shutdown the socket and wait for the other end to finish... + */ + + fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr); + + shutdown(fd, 1); + + for (;;) + { + /* + * Wait a maximum of 90 seconds for backchannel data or a closed + * connection... + */ + + timeout.tv_sec = 90; + timeout.tv_usec = 0; + + FD_ZERO(&input); + FD_SET(fd, &input); + +#ifdef __hpux + if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0) +#else + if (select(fd + 1, &input, NULL, NULL, &timeout) > 0) +#endif /* __hpux */ + { + /* + * Grab the data coming back and spit it out to stderr... + */ + + if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0) + fprintf(stderr, "INFO: Received %lu bytes of back-channel data!\n", + (unsigned long)nbytes); + else + break; + } + else + break; + } + + /* + * Close the socket connection... + */ + + close(fd); + } + + /* + * Close the input file and return... + */ + + if (fp != 0) + close(fp); + + fputs("INFO: Ready to print.\n", stderr); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/usb.c b/backend/usb.c new file mode 100644 index 0000000000..a29f657b17 --- /dev/null +++ b/backend/usb.c @@ -0,0 +1,789 @@ +/* + * "$Id$" + * + * USB port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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" 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Send a file to the specified USB port. + * list_devices() - List all USB devices. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +# include +#else +# include +# include +# include +#endif /* WIN32 */ + +#ifdef __linux +# include +# include +# define IOCNR_GET_DEVICE_ID 1 + +/* + * Get device_id string + */ +# define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) +#endif /* __linux */ + +#ifdef __sun +# include +#endif /* __sun */ + + +/* + * Local functions... + */ + +void decode_device_id(int port, const char *device_id, + char *make_model, int mmsize, + char *uri, int urisize); +void list_devices(void); +int open_device(const char *uri); + + +/* + * 'main()' - Send a file to the specified USB port. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + int fp; /* Print file */ + int copies; /* Number of copies to print */ + int fd; /* Parallel device */ + int wbytes; /* Number of bytes written */ + size_t nbytes, /* Number of bytes read */ + tbytes; /* Total number of bytes written */ + char buffer[8192], /* Output buffer */ + *bufptr; /* Pointer into buffer */ + struct termios opts; /* Parallel port options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ +#ifdef __linux + unsigned char status; /* Port status (off-line, out-of-paper, etc.) */ +#endif /* __linux */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) + { + list_devices(); + return (0); + } + else if (argc < 6 || argc > 7) + { + fputs("Usage: USB job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + { + fp = 0; + copies = 1; + } + else + { + /* + * Try to open the print file... + */ + + if ((fp = open(argv[6], O_RDONLY)) < 0) + { + perror("ERROR: unable to open print file"); + return (1); + } + + copies = atoi(argv[4]); + } + + /* + * Open the USB port device... + */ + + do + { + if ((fd = open_device(argv[0])) == -1) + { + if (errno == EBUSY) + { + fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else if (errno == ENXIO || errno == EIO || errno == ENOENT) + { + fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr); + sleep(30); + } + else + { + fprintf(stderr, "ERROR: Unable to open USB device \"%s\": %s\n", + argv[0], strerror(errno)); + return (1); + } + } + } + while (fd < 0); + + /* + * Set any options provided... + */ + + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + /**** No options supported yet ****/ + + tcsetattr(fd, TCSANOW, &opts); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (argc < 7) + { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + +#ifdef __linux + /* + * Show the printer status before we send the file; normally, we'd + * do this while we write data to the printer, however at least some + * Linux kernels have buggy USB drivers which don't like to be + * queried while sending data to the printer... + */ + + if (ioctl(fd, LPGETSTATUS, &status) == 0) + { + fprintf(stderr, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status); + + if (status & LP_NOPA) + fputs("WARNING: Media tray empty!\n", stderr); + else if (status & LP_ERR) + fputs("WARNING: Printer fault!\n", stderr); + else if (status & LP_OFFL) + fputs("WARNING: Printer off-line.\n", stderr); + } +#endif /* __linux */ + + /* + * Finally, send the print file... + */ + + while (copies > 0) + { + copies --; + + if (fp != 0) + { + fputs("PAGE: 1 1\n", stderr); + lseek(fp, 0, SEEK_SET); + } + + tbytes = 0; + while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0) + { + /* + * Write the print data to the printer... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + + if ((wbytes = write(fd, bufptr, nbytes)) < 0) + if (errno == ENOTTY) + wbytes = write(fd, bufptr, nbytes); + + if (wbytes < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + if (argc > 6) + fprintf(stderr, "INFO: Sending print file, %lu bytes...\n", + (unsigned long)tbytes); + } + } + + /* + * Close the socket connection and input file and return... + */ + + close(fd); + if (fp != 0) + close(fp); + + fputs("INFO: Ready to print.\n", stderr); + + return (0); +} + + +/* + * 'decode_device_id()' - Decode the IEEE-1284 device ID string. + */ + +void +decode_device_id(int port, /* I - Port number */ + const char *device_id, /* I - 1284 device ID string */ + char *make_model, /* O - Make/model */ + int mmsize, /* I - Size of buffer */ + char *uri, /* O - Device URI */ + int urisize) /* I - Size of buffer */ +{ + char *attr, /* 1284 attribute */ + *delim, /* 1284 delimiter */ + *uriptr, /* Pointer into URI */ + line[1024]; /* Line from devices file */ + FILE *fp; /* /proc/bus/usb/devices file */ + int current; /* Current printer port */ + char serial_number[1024], /* Serial number string */ + temp[1024]; /* Temporary string */ + + + /* + * Look for the description field... + */ + + if ((attr = strstr(device_id, "DES:")) != NULL) + attr += 4; + else if ((attr = strstr(device_id, "DESCRIPTION:")) != NULL) + attr += 12; + + if (attr) + { + if (strncasecmp(attr, "Hewlett-Packard ", 16) == 0) + { + strlcpy(make_model, "HP ", mmsize); + strlcpy(make_model + 3, attr + 16, mmsize - 3); + } + else + { + strlcpy(make_model, attr, mmsize); + } + + if ((delim = strchr(make_model, ';')) != NULL) + *delim = '\0'; + } + else + strlcpy(make_model, "Unknown", mmsize); + + /* + * Look for the serial number field... + */ + + if ((attr = strstr(device_id, "SERN:")) != NULL) + attr += 5; + else if ((attr = strstr(device_id, "SERIALNUMBER:")) != NULL) + attr += 13; + + if (attr) + { + strlcpy(serial_number, attr, sizeof(serial_number)); + + if ((delim = strchr(serial_number, ';')) != NULL) + *delim = '\0'; + } + else if ((fp = fopen("/proc/bus/usb/devices", "r")) != NULL) + { + serial_number[0] = '\0'; + + for (current = 0; fgets(line, sizeof(line), fp) != NULL;) + { + if (line[0] == 'S' && (attr = strstr(line, "SerialNumber=")) != NULL) + { + /* + * Copy serial number from line... + */ + + strlcpy(temp, attr + 13, sizeof(temp)); + if ((delim = strchr(temp, '\n')) != NULL) + *delim = '\0'; + } + else if (line[0] == 'I' && strstr(line, "Driver=usblp") != NULL && + strstr(line, "Prot=02") != NULL) + { + /* + * Found printer device; if current == port, then use it! + */ + + if (current == port) + { + strlcpy(serial_number, temp, sizeof(serial_number)); + break; + } + + current ++; + } + } + + fclose(fp); + } + + /* + * Generate the device URI from the make_model and serial number strings. + */ + + strlcpy(uri, "usb://", urisize); + for (uriptr = uri + 6, delim = make_model; + *delim && uriptr < (uri + urisize - 1); + delim ++) + if (*delim == ' ') + { + delim ++; + *uriptr++ = '/'; + break; + } + else + *uriptr++ = *delim; + + for (; *delim && uriptr < (uri + urisize - 3); delim ++) + if (*delim == ' ') + { + *uriptr++ = '%'; + *uriptr++ = '2'; + *uriptr++ = '0'; + } + else + *uriptr++ = *delim; + + *uriptr = '\0'; + + if (serial_number[0]) + { + /* + * Add the serial number to the URI... + */ + + strlcat(uri, "?serial=", urisize); + strlcat(uri, serial_number, urisize); + } +} + + +/* + * 'list_devices()' - List all USB devices. + */ + +void +list_devices(void) +{ +#ifdef __linux + int i; /* Looping var */ + int length; /* Length of device ID info */ + int fd; /* File descriptor */ + char format[255], /* Format for device filename */ + device[255], /* Device filename */ + device_id[1024], /* Device ID string */ + device_uri[1024], /* Device URI string */ + make_model[1024]; /* Make and model */ + + + /* + * First figure out which USB printer filename to use... + */ + + if (access("/dev/usb/lp0", 0) == 0) + strcpy(format, "/dev/usb/lp%d"); + else if (access("/dev/usb/usblp0", 0) == 0) + strcpy(format, "/dev/usb/usblp%d"); + else + strcpy(format, "/dev/usblp%d"); + + /* + * Then open each USB device... + */ + + for (i = 0; i < 16; i ++) + { + sprintf(device, format, i); + + if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) + { + if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0) + { + length = (((unsigned)device_id[0] & 255) << 8) + + ((unsigned)device_id[1] & 255); + + /* + * Check to see if the length is larger than our buffer; first + * assume that the vendor incorrectly implemented the 1284 spec, + * and then limit the length to the size of our buffer... + */ + + if (length > (sizeof(device_id) - 2)) + length = (((unsigned)device_id[1] & 255) << 8) + + ((unsigned)device_id[0] & 255); + + if (length > (sizeof(device_id) - 2)) + length = sizeof(device_id) - 2; + + memcpy(device_id, device_id + 2, length); + device_id[length] = '\0'; + } + else + device_id[0] = '\0'; + + close(fd); + } + else + device_id[0] = '\0'; + + if (device_id[0]) + { + decode_device_id(i, device_id, make_model, sizeof(make_model), + device_uri, sizeof(device_uri)); + + printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri, + make_model, i + 1); + } + else + printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); + } +#elif defined(__sgi) +#elif defined(__sun) + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255], /* Device filename */ + device_id[1024], /* Device ID string */ + device_uri[1024], /* Device URI string */ + make_model[1024]; /* Make and model */ +# ifdef ECPPIOC_GETDEVID + struct ecpp_device_id did; /* Device ID buffer */ +# endif /* ECPPIOC_GETDEVID */ + + + /* + * Open each USB device... + */ + + for (i = 0; i < 8; i ++) + { + sprintf(device, "/dev/usb/printer%d", i); + +# ifndef ECPPIOC_GETDEVID + if (!access(device, 0)) + printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); +# else + if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) + { + did.mode = ECPP_CENTRONICS; + did.len = sizeof(device_id); + did.rlen = 0; + did.addr = device_id; + + if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0) + { + if (did.rlen < (sizeof(device_id) - 1)) + device_id[did.rlen] = '\0'; + else + device_id[sizeof(device_id) - 1] = '\0'; + } + else + device_id[0] = '\0'; + + close(fd); + } + else + device_id[0] = '\0'; + + if (device_id[0]) + { + decode_device_id(i, device_id, make_model, sizeof(make_model), + device_uri, sizeof(device_uri)); + + printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri, + make_model, i + 1); + } + else + printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); +# endif /* !ECPPIOC_GETDEVID */ + } +#elif defined(__hpux) +#elif defined(__osf) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + int i; /* Looping var */ + char device[255]; /* Device filename */ + + + for (i = 0; i < 8; i ++) + { + sprintf(device, "/dev/ulpt%d", i); + if (!access(device, 0)) + printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); + + sprintf(device, "/dev/unlpt%d", i); + if (!access(device, 0)) + printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device, i + 1); + } +#endif +} + + +/* + * 'open_device()' - Open a USB device... + */ + +int /* O - File descriptor or -1 on error */ +open_device(const char *uri) /* I - Device URI */ +{ + /* + * The generic implementation just treats the URI as a device filename... + * Specific operating systems may also support using the device serial + * number and/or make/model. + */ + + if (strncmp(uri, "usb:/dev/", 9) == 0) + return (open(uri + 4, O_RDWR | O_EXCL)); +#ifdef __linux + else if (strncmp(uri, "usb://", 6) == 0) + { + /* + * For Linux, try looking up the device serial number or model... + */ + + int i; /* Looping var */ + int length; /* Length of device ID info */ + int fd; /* File descriptor */ + char format[255], /* Format for device filename */ + device[255], /* Device filename */ + device_id[1024], /* Device ID string */ + make_model[1024], /* Make and model */ + device_uri[1024]; /* Device URI string */ + + + /* + * First figure out which USB printer filename to use... + */ + + if (access("/dev/usb/lp0", 0) == 0) + strcpy(format, "/dev/usb/lp%d"); + else if (access("/dev/usb/usblp0", 0) == 0) + strcpy(format, "/dev/usb/usblp%d"); + else + strcpy(format, "/dev/usblp%d"); + + /* + * Then find the correct USB device... + */ + + for (i = 0; i < 16; i ++) + { + sprintf(device, format, i); + + if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) + { + if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0) + { + length = (((unsigned)device_id[0] & 255) << 8) + + ((unsigned)device_id[1] & 255); + memcpy(device_id, device_id + 2, length); + device_id[length] = '\0'; + } + else + device_id[0] = '\0'; + } + else + device_id[0] = '\0'; + + if (device_id[0]) + { + /* + * Got the device ID - is this the one? + */ + + decode_device_id(i, device_id, make_model, sizeof(make_model), + device_uri, sizeof(device_uri)); + + if (strcmp(uri, device_uri) == 0) + return (fd); /* Yes, return this file descriptor... */ + } + + /* + * This wasn't the one... + */ + + close(fd); + } + + /* + * Couldn't find the printer, return "no such device or address"... + */ + + errno = ENODEV; + + return (-1); + } +#elif defined(__sun) && defined(ECPPIOC_GETDEVID) + else if (strncmp(uri, "usb://", 6) == 0) + { + /* + * For Solaris, try looking up the device serial number or model... + */ + + int i; /* Looping var */ + int fd; /* File descriptor */ + char device[255], /* Device filename */ + device_id[1024], /* Device ID string */ + make_model[1024], /* Make and model */ + device_uri[1024]; /* Device URI string */ + struct ecpp_device_id did; /* Device ID buffer */ + + + /* + * Find the correct USB device... + */ + + for (i = 0; i < 8; i ++) + { + sprintf(device, "/dev/usb/printer%d", i); + + if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) + { + did.mode = ECPP_CENTRONICS; + did.len = sizeof(device_id); + did.rlen = 0; + did.addr = device_id; + + if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0) + { + if (did.rlen < (sizeof(device_id) - 1)) + device_id[did.rlen] = '\0'; + else + device_id[sizeof(device_id) - 1] = '\0'; + } + else + device_id[0] = '\0'; + } + else + device_id[0] = '\0'; + + if (device_id[0]) + { + /* + * Got the device ID - is this the one? + */ + + decode_device_id(i, device_id, make_model, sizeof(make_model), + device_uri, sizeof(device_uri)); + + if (strcmp(uri, device_uri) == 0) + return (fd); /* Yes, return this file descriptor... */ + } + + /* + * This wasn't the one... + */ + + close(fd); + } + + /* + * Couldn't find the printer, return "no such device or address"... + */ + + errno = ENODEV; + + return (-1); + } +#endif /* __linux */ + else + { + errno = ENODEV; + return (-1); + } +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/.cvsignore b/berkeley/.cvsignore new file mode 100644 index 0000000000..3ff70bf386 --- /dev/null +++ b/berkeley/.cvsignore @@ -0,0 +1,4 @@ +lpc +lpq +lpr +lprm diff --git a/berkeley/Dependencies b/berkeley/Dependencies new file mode 100644 index 0000000000..0915065b5d --- /dev/null +++ b/berkeley/Dependencies @@ -0,0 +1,11 @@ +# DO NOT DELETE + +lpc.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +lpc.o: ../cups/ppd.h ../cups/language.h ../cups/debug.h +lpq.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h +lpq.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h +lpq.o: ../cups/debug.h +lpr.o: ../config.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +lpr.o: ../cups/ppd.h +lprm.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +lprm.o: ../cups/ppd.h ../cups/language.h diff --git a/berkeley/Makefile b/berkeley/Makefile new file mode 100644 index 0000000000..07d05243ce --- /dev/null +++ b/berkeley/Makefile @@ -0,0 +1,112 @@ +# +# "$Id$" +# +# Berkeley commands makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 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 +# + +include ../Makedefs + +TARGETS = lpc lpq lpr lprm +OBJS = lpc.o lpq.o lpr.o lprm.o + + +# +# Make all targets... +# + +all: $(TARGETS) + + +# +# Clean all object files... +# + +clean: + $(RM) $(OBJS) $(TARGETS) + + +# +# Update dependencies (without system header dependencies...) +# + +depend: + makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1 + + +# +# Install all targets... +# + +install: all + $(INSTALL_DIR) $(BINDIR) + $(INSTALL_BIN) lpq $(BINDIR) + $(INSTALL_BIN) lpr $(BINDIR) + $(INSTALL_BIN) lprm $(BINDIR) + $(INSTALL_DIR) $(SBINDIR) + $(INSTALL_BIN) lpc $(SBINDIR) + + +# +# lpc +# + +lpc: lpc.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpc lpc.o $(LIBS) + + +# +# lpq +# + +lpq: lpq.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpq lpq.o $(LIBS) + + +# +# lpr +# + +lpr: lpr.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lpr lpr.o $(LIBS) + + +# +# lprm +# + +lprm: lprm.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o lprm lprm.o $(LIBS) + + +# +# Dependencies... +# + +include Dependencies + + +# +# End of "$Id$". +# diff --git a/berkeley/lpc.c b/berkeley/lpc.c new file mode 100644 index 0000000000..e027db846d --- /dev/null +++ b/berkeley/lpc.c @@ -0,0 +1,482 @@ +/* + * "$Id$" + * + * "lpc" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Parse options and commands. + * compare_strings() - Compare two command-line strings. + * do_command() - Do an lpc command... + * show_help() - Show help messages. + * show_status() - Show printers. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +static int compare_strings(char *, char *, int); +static void do_command(http_t *, char *, char *); +static void show_help(char *); +static void show_status(http_t *, char *); + + +/* + * 'main()' - Parse options and commands. + */ + +int +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + http_t *http; /* Connection to server */ + char line[1024], /* Input line from user */ + *params; /* Pointer to parameters */ + + + /* + * Connect to the scheduler... + */ + + http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); + + if (argc > 1) + { + /* + * Process a single command on the command-line... + */ + + do_command(http, argv[1], argv[2]); + } + else + { + /* + * Do the command prompt thing... + */ + + printf("lpc> "); + while (fgets(line, sizeof(line), stdin) != NULL) + { + /* + * Strip the trailing newline... + */ + + line[strlen(line) - 1] = '\0'; + + /* + * Find any options in the string... + */ + + while (isspace(line[0])) + strcpy(line, line + 1); + + for (params = line; *params != '\0'; params ++) + if (isspace(*params)) + break; + + /* + * Remove whitespace between the command and parameters... + */ + + while (isspace(*params)) + *params++ = '\0'; + + /* + * The "quit" and "exit" commands exit; otherwise, process as needed... + */ + + if (compare_strings(line, "quit", 1) == 0 || + compare_strings(line, "exit", 2) == 0) + break; + + if (*params == '\0') + do_command(http, line, NULL); + else + do_command(http, line, params); + + /* + * Put another prompt out to the user... + */ + + printf("lpc> "); + } + } + + /* + * Close the connection to the server and return... + */ + + httpClose(http); + + return (0); +} + + +/* + * 'compare_strings()' - Compare two command-line strings. + */ + +static int /* O - -1 or 1 = no match, 0 = match */ +compare_strings(char *s, /* I - Command-line string */ + char *t, /* I - Option string */ + int tmin) /* I - Minimum number of unique chars in option */ +{ + int slen; /* Length of command-line string */ + + + slen = strlen(s); + if (slen < tmin) + return (-1); + else + return (strncmp(s, t, slen)); +} + + +/* + * 'do_command()' - Do an lpc command... + */ + +static void +do_command(http_t *http, /* I - HTTP connection to server */ + char *command, /* I - Command string */ + char *params) /* I - Parameters for command */ +{ + if (compare_strings(command, "status", 4) == 0) + show_status(http, params); + else if (compare_strings(command, "help", 1) == 0 || + strcmp(command, "?") == 0) + show_help(params); + else + printf("%s is not implemented by the CUPS version of lpc.\n", command); +} + + +/* + * 'show_help()' - Show help messages. + */ + +static void +show_help(char *command) /* I - Command to describe or NULL */ +{ + if (command == NULL) + { + puts("Commands may be abbreviated. Commands are:"); + puts(""); + puts("exit help quit status ?"); + } + else if (compare_strings(command, "help", 1) == 0 || + strcmp(command, "?") == 0) + puts("help\t\tget help on commands"); + else if (compare_strings(command, "status", 4) == 0) + puts("status\t\tshow status of daemon and queue"); + else + puts("?Invalid help command unknown"); +} + + +/* + * 'show_status()' - Show printers. + */ + +static void +show_status(http_t *http, /* I - HTTP connection to server */ + char *dests) /* I - Destinations */ +{ + ipp_t *request, /* IPP Request */ + *response, /* IPP Response */ + *jobs; /* IPP Get Jobs response */ + ipp_attribute_t *attr, /* Current attribute */ + *jattr; /* Current job attribute */ + cups_lang_t *language; /* Default language */ + char *printer, /* Printer name */ + *device; /* Device URI */ + ipp_pstate_t pstate; /* Printer state */ + int accepting; /* Is printer accepting jobs? */ + int jobcount; /* Count of current jobs */ + char *dptr, /* Pointer into destination list */ + *ptr; /* Pointer into printer name */ + int match; /* Non-zero if this job matches */ + char printer_uri[HTTP_MAX_URI]; + /* Printer URI */ + static const char *requested[] = + { /* Requested attributes */ + "printer-name", + "device-uri", + "printer-state", + "printer-is-accepting-jobs" + }; + + + DEBUG_printf(("show_status(%08x, %08x)\n", http, dests)); + + if (http == NULL) + return; + + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + 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(requested) / sizeof(requested[0]), + NULL, requested); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/printers/")) != NULL) + { + DEBUG_puts("show_status: request succeeded..."); + + /* + * Loop through the printers returned in the list and display + * their status... + */ + + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + /* + * Skip leading attributes until we hit a job... + */ + + while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Pull the needed attributes from this job... + */ + + printer = NULL; + device = "file:/dev/null"; + pstate = IPP_PRINTER_IDLE; + jobcount = 0; + accepting = 1; + + while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) + { + if (strcmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + printer = attr->values[0].string.text; + + if (strcmp(attr->name, "device-uri") == 0 && + attr->value_tag == IPP_TAG_URI) + device = attr->values[0].string.text; + + if (strcmp(attr->name, "printer-state") == 0 && + attr->value_tag == IPP_TAG_ENUM) + pstate = (ipp_pstate_t)attr->values[0].integer; + + if (strcmp(attr->name, "printer-is-accepting-jobs") == 0 && + attr->value_tag == IPP_TAG_BOOLEAN) + accepting = attr->values[0].boolean; + + attr = attr->next; + } + + /* + * See if we have everything needed... + */ + + if (printer == NULL) + { + if (attr == NULL) + break; + else + continue; + } + + /* + * See if this is a printer we're interested in... + */ + + match = dests == NULL; + + if (dests != NULL) + { + for (dptr = dests; *dptr != '\0';) + { + /* + * Skip leading whitespace and commas... + */ + + while (isspace(*dptr) || *dptr == ',') + dptr ++; + + if (*dptr == '\0') + break; + + /* + * Compare names... + */ + + for (ptr = printer; + *ptr != '\0' && *dptr != '\0' && *ptr == *dptr; + ptr ++, dptr ++); + + if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr))) + { + match = 1; + break; + } + + /* + * Skip trailing junk... + */ + + while (!isspace(*dptr) && *dptr != '\0') + dptr ++; + while (isspace(*dptr) || *dptr == ',') + dptr ++; + + if (*dptr == '\0') + break; + } + } + + /* + * Display the printer entry if needed... + */ + + if (match) + { + /* + * If the printer state is "IPP_PRINTER_PROCESSING", then grab the + * current job for the printer. + */ + + if (pstate == IPP_PRINTER_PROCESSING) + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * limit + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_JOBS; + 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); + + snprintf(printer_uri, sizeof(printer_uri), + "ipp://localhost/printers/%s", printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, printer_uri); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", NULL, "job-id"); + + if ((jobs = cupsDoRequest(http, request, "/jobs/")) != NULL) + { + for (jattr = jobs->attrs; jattr != NULL; jattr = jattr->next) + if (jattr->name && strcmp(jattr->name, "job-id") == 0) + jobcount ++; + + ippDelete(jobs); + } + } + + /* + * Display it... + */ + + printf("%s:\n", printer); + if (strncmp(device, "file:", 5) == 0) + printf("\tprinter is on device \'%s\' speed -1\n", device + 5); + else + { + /* + * Just show the method... + */ + + *strchr(device, ':') = '\0'; + printf("\tprinter is on device \'%s\' speed -1\n", device); + } + + printf("\tqueuing is %sabled\n", accepting ? "en" : "dis"); + printf("\tprinting is %sabled\n", + pstate == IPP_PRINTER_STOPPED ? "dis" : "en"); + if (jobcount == 0) + puts("\tno entries"); + else + printf("\t%d entries\n", jobcount); + puts("\tdaemon present"); + } + + if (attr == NULL) + break; + } + + ippDelete(response); + } +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lpq.c b/berkeley/lpq.c new file mode 100644 index 0000000000..2db23aa073 --- /dev/null +++ b/berkeley/lpq.c @@ -0,0 +1,549 @@ +/* + * "$Id$" + * + * "lpq" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Parse options and commands. + * show_jobs() - Show jobs. + * show_printer() - Show printer status. + */ + +/* + * Include necessary headers... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +static int show_jobs(http_t *, const char *, const char *, const int, + const int); +static void show_printer(http_t *, const char *); + + +/* + * 'main()' - Parse options and commands. + */ + +int +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + http_t *http; /* Connection to server */ + const char *dest, /* Desired printer */ + *user; /* Desired user */ + char *instance; /* Printer instance */ + int id, /* Desired job ID */ + interval, /* Reporting interval */ + 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 */ + + + /* + * Connect to the scheduler... + */ + + if ((http = httpConnectEncrypt(cupsServer(), ippPort(), + cupsEncryption())) == NULL) + { + fputs("lpq: Unable to contact server!\n", stderr); + return (1); + } + + /* + * Check for command-line options... + */ + + dest = NULL; + user = NULL; + id = 0; + interval = 0; + longstatus = 0; + + num_dests = cupsGetDests(&dests); + + for (i = 0; i < num_dests; i ++) + if (dests[i].is_default) + dest = dests[i].name; + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '+') + interval = atoi(argv[i] + 1); + else if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'E' : /* Encrypt */ +#ifdef HAVE_LIBSSL + encryption = HTTP_ENCRYPT_REQUIRED; + + if (http) + httpEncryption(http, encryption); +#else + fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n", + argv[0]); +#endif /* HAVE_LIBSSL */ + break; + + case 'P' : /* Printer */ + if (argv[i][2]) + dest = argv[i] + 2; + else + { + i ++; + dest = argv[i]; + } + + if ((instance = strchr(dest, '/')) != NULL) + *instance++ = '\0'; + + if (cupsGetDest(dest, instance, num_dests, dests) == NULL) + { + if (instance) + fprintf(stderr, "lpq: Unknown destination \"%s/%s\"!\n", + dest, instance); + else + fprintf(stderr, "lpq: Unknown destination \"%s\"!\n", dest); + + return (1); + } + break; + + case 'a' : /* All printers */ + dest = NULL; + break; + + case 'l' : /* Long status */ + longstatus = 1; + break; + + default : + fputs("Usage: lpq [-P dest] [-l] [+interval]\n", stderr); + httpClose(http); + cupsFreeDests(num_dests, dests); + return (1); + } + } + else if (isdigit(argv[i][0])) + id = atoi(argv[i]); + else + user = argv[i]; + + /* + * Show the status in a loop... + */ + + for (;;) + { + if (dest) + show_printer(http, dest); + + i = show_jobs(http, dest, user, id, longstatus); + + if (i && interval) + { + fflush(stdout); + sleep(interval); + } + else + break; + } + + /* + * Close the connection to the server and return... + */ + + cupsFreeDests(num_dests, dests); + httpClose(http); + + return (0); +} + + +/* + * 'show_jobs()' - Show jobs. + */ + +static int /* O - Number of jobs in queue */ +show_jobs(http_t *http, /* I - HTTP connection to server */ + const char *dest, /* I - Destination */ + const char *user, /* I - User */ + const int id, /* I - Job ID */ + const int longstatus)/* I - 1 if long report desired */ +{ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + const char *jobdest, /* Pointer into job-printer-uri */ + *jobuser, /* Pointer to job-originating-user-name */ + *jobname; /* Pointer to job-name */ + ipp_jstate_t jobstate; /* job-state */ + int jobid, /* job-id */ + jobsize, /* job-k-octets */ +#ifdef __osf__ + jobpriority, /* job-priority */ +#endif /* __osf__ */ + jobcount, /* Number of jobs */ + jobcopies, /* Number of copies */ + rank; /* Rank of job */ + char resource[1024]; /* Resource string */ + char rankstr[255]; /* Rank string */ + char namestr[1024]; /* Job name string */ + static const char *ranks[10] =/* Ranking strings */ + { + "th", + "st", + "nd", + "rd", + "th", + "th", + "th", + "th", + "th", + "th" + }; + + + DEBUG_printf(("show_jobs(%08x, %08x, %08x, %d, %d)\n", http, dest, user, id, + longstatus)); + + if (http == NULL) + return (0); + + /* + * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires + * the following attributes: + * + * attributes-charset + * attributes-natural-language + * job-uri or printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + if (dest == NULL) + { + if (id) + sprintf(resource, "ipp://localhost/jobs/%d", id); + else + strcpy(resource, "ipp://localhost/jobs"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", + NULL, resource); + } + else + { + snprintf(resource, sizeof(resource), "ipp://localhost/printers/%s", dest); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, resource); + } + + if (user) + { + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requesting-user-name", NULL, user); + ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); + } + + /* + * Do the request and get back a response... + */ + + jobcount = 0; + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if (response->request.status.status_code > IPP_OK_CONFLICT) + { + fprintf(stderr, "lpq: get-jobs failed: %s\n", + ippErrorString(response->request.status.status_code)); + ippDelete(response); + return (0); + } + + rank = 1; + + /* + * Loop through the job list and display them... + */ + + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + /* + * Skip leading attributes until we hit a job... + */ + + while (attr != NULL && attr->group_tag != IPP_TAG_JOB) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Pull the needed attributes from this job... + */ + + jobid = 0; + jobsize = 0; +#ifdef __osf__ + jobpriority = 50; +#endif /* __osf__ */ + jobstate = IPP_JOB_PENDING; + jobname = "untitled"; + jobuser = NULL; + jobdest = NULL; + jobcopies = 1; + + while (attr != NULL && attr->group_tag == IPP_TAG_JOB) + { + if (strcmp(attr->name, "job-id") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobid = attr->values[0].integer; + + if (strcmp(attr->name, "job-k-octets") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobsize = attr->values[0].integer * 1024; + +#ifdef __osf__ + if (strcmp(attr->name, "job-priority") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobpriority = attr->values[0].integer; +#endif /* __osf__ */ + + if (strcmp(attr->name, "job-state") == 0 && + attr->value_tag == IPP_TAG_ENUM) + jobstate = (ipp_jstate_t)attr->values[0].integer; + + if (strcmp(attr->name, "job-printer-uri") == 0 && + attr->value_tag == IPP_TAG_URI) + if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL) + jobdest ++; + + if (strcmp(attr->name, "job-originating-user-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + jobuser = attr->values[0].string.text; + + if (strcmp(attr->name, "job-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + jobname = attr->values[0].string.text; + + if (strcmp(attr->name, "copies") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobcopies = attr->values[0].integer; + + attr = attr->next; + } + + /* + * See if we have everything needed... + */ + + if (jobdest == NULL || jobid == 0) + { + if (attr == NULL) + break; + else + continue; + } + + if (!longstatus && jobcount == 0) +#ifdef __osf__ + puts("Rank Owner Pri Job Files Total Size"); +#else + puts("Rank Owner Job File(s) Total Size"); +#endif /* __osf__ */ + + jobcount ++; + + /* + * Display the job... + */ + + if (jobstate == IPP_JOB_PROCESSING) + strcpy(rankstr, "active"); + else + { + snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]); + rank ++; + } + + if (longstatus) + { + puts(""); + + if (jobcopies > 1) + snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies, + jobname); + else + strlcpy(namestr, jobname, sizeof(namestr)); + + printf("%s: %-34.34s[job %d localhost]\n", jobuser, rankstr, jobid); + printf(" %-40.40s%d bytes\n", namestr, jobsize); + } + else +#ifdef __osf__ + printf("%-6s %-10.10s %-4d %-10d %-27.27s %d bytes\n", rankstr, jobuser, + jobpriority, jobid, jobname, jobsize); +#else + printf("%-7s %-8.8s%-8d%-32.32s%d bytes\n", rankstr, jobuser, + jobid, jobname, jobsize); +#endif /* __osf */ + + if (attr == NULL) + break; + } + + ippDelete(response); + } + else + { + fprintf(stderr, "lpq: get-jobs failed: %s\n", ippErrorString(cupsLastError())); + return (0); + } + + if (jobcount == 0) + puts("no entries"); + + return (jobcount); +} + + +/* + * 'show_printer()' - Show printer status. + */ + +static void +show_printer(http_t *http, /* I - HTTP connection to server */ + const char *dest) /* I - Destination */ +{ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + ipp_pstate_t state; /* Printer state */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + + + if (http == NULL) + return; + + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", dest); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if (response->request.status.status_code > IPP_OK_CONFLICT) + { + fprintf(stderr, "lpq: get-printer-attributes failed: %s\n", + ippErrorString(response->request.status.status_code)); + ippDelete(response); + return; + } + + if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) + state = (ipp_pstate_t)attr->values[0].integer; + else + state = IPP_PRINTER_STOPPED; + + switch (state) + { + case IPP_PRINTER_IDLE : + printf("%s is ready\n", dest); + break; + case IPP_PRINTER_PROCESSING : + printf("%s is ready and printing\n", dest); + break; + case IPP_PRINTER_STOPPED : + printf("%s is not ready\n", dest); + break; + } + + ippDelete(response); + } + else + fprintf(stderr, "lpq: get-printer-attributes failed: %s\n", + ippErrorString(cupsLastError())); +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lpr.c b/berkeley/lpr.c new file mode 100644 index 0000000000..fc4b91027d --- /dev/null +++ b/berkeley/lpr.c @@ -0,0 +1,433 @@ +/* + * "$Id$" + * + * "lpr" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Parse options and send files for printing. + * sighandler() - Signal catcher for when we print from stdin... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include + +#include +#include + + +#ifndef WIN32 +# include +# include + + +/* + * Local functions. + */ + +void sighandler(int); +#endif /* !WIN32 */ + + +/* + * Globals... + */ + +char tempfile[1024]; /* Temporary file for printing from stdin */ + + +/* + * 'main()' - Parse options and send files for printing. + */ + +int +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i, j; /* Looping var */ + int job_id; /* Job ID */ + char ch; /* Option character */ + char *printer, /* Destination printer or class */ + *instance; /* Instance */ + const char *title; /* Job title */ + int num_copies; /* Number of copies per file */ + int num_files; /* Number of files to print */ + const char *files[1000]; /* Files to print */ + int num_dests; /* Number of destinations */ + cups_dest_t *dests, /* Destinations */ + *dest; /* Selected destination */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ + int deletefile; /* Delete file after print? */ + char buffer[8192]; /* Copy buffer */ + int temp; /* Temporary file descriptor */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Signal action */ + struct sigaction oldaction; /* Old signal action */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + deletefile = 0; + printer = NULL; + num_dests = 0; + dests = NULL; + num_options = 0; + options = NULL; + num_files = 0; + title = NULL; + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '-') + switch (ch = argv[i][1]) + { + case 'E' : /* Encrypt */ +#ifdef HAVE_LIBSSL + cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); +#else + fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n", + argv[0]); +#endif /* HAVE_LIBSSL */ + break; + + case '1' : /* TROFF font set 1 */ + case '2' : /* TROFF font set 2 */ + case '3' : /* TROFF font set 3 */ + case '4' : /* TROFF font set 4 */ + case 'i' : /* indent */ + case 'w' : /* width */ + if (argv[i][2] == '\0') + { + i ++; + + if (i >= argc) + { + fprintf(stderr, "lpr: Expected value after -%c option!\n", ch); + return (1); + } + } + + case 'c' : /* CIFPLOT */ + case 'd' : /* DVI */ + case 'f' : /* FORTRAN */ + case 'g' : /* plot */ + case 'n' : /* Ditroff */ + case 't' : /* Troff */ + case 'v' : /* Raster image */ + fprintf(stderr, "Warning: \'%c\' format modifier not supported - output may not be correct!\n", + ch); + break; + + case 'o' : /* Option */ + if (argv[i][2] != '\0') + num_options = cupsParseOptions(argv[i] + 2, num_options, &options); + else + { + i ++; + if (i >= argc) + { + fputs("lpr: Expected option=value after -o option!\n", stderr); + return (1); + } + + num_options = cupsParseOptions(argv[i], num_options, &options); + } + break; + + case 'l' : /* Literal/raw */ + num_options = cupsAddOption("raw", "", num_options, &options); + break; + + case 'p' : /* Prettyprint */ + num_options = cupsAddOption("prettyprint", "", num_options, &options); + break; + + case 'h' : /* Suppress burst page */ + num_options = cupsAddOption("job-sheets", "none", num_options, &options); + break; + + case 's' : /* Don't use symlinks */ + break; + + case 'm' : /* Mail on completion */ + fputs("Warning: email notification is not supported!\n", stderr); + break; + + case 'q' : /* Queue file but don't print */ + num_options = cupsAddOption("job-hold-until", "indefinite", + num_options, &options); + break; + + case 'r' : /* Remove file after printing */ + deletefile = 1; + break; + + case 'P' : /* Destination printer or class */ + if (argv[i][2] != '\0') + printer = argv[i] + 2; + else + { + i ++; + if (i >= argc) + { + fputs("lpr: Expected destination after -P option!\n", stderr); + return (1); + } + + printer = argv[i]; + } + + if ((instance = strrchr(printer, '/')) != NULL) + *instance++ = '\0'; + + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL) + { + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + } + break; + + case '#' : /* Number of copies */ + if (argv[i][2] != '\0') + num_copies = atoi(argv[i] + 2); + else + { + i ++; + if (i >= argc) + { + fputs("lpr: Expected copy count after -# option!\n", stderr); + return (1); + } + + num_copies = atoi(argv[i]); + } + + sprintf(buffer, "%d", num_copies); + num_options = cupsAddOption("copies", buffer, num_options, &options); + break; + + case 'C' : /* Class */ + case 'J' : /* Job name */ + case 'T' : /* Title */ + if (argv[i][2] != '\0') + title = argv[i] + 2; + else + { + i ++; + if (i >= argc) + { + fprintf(stderr, "lpr: Expected name after -%c option!\n", ch); + return (1); + } + + title = argv[i]; + } + break; + + case 'U' : /* User */ + if (argv[i][2] != '\0') + cupsSetUser(argv[i] + 2); + else + { + i ++; + if (i >= argc) + { + fputs("lpr: Expected username after -U option!\n", stderr); + return (1); + } + + cupsSetUser(argv[i]); + } + break; + + default : + fprintf(stderr, "lpr: Unknown option \'%c\'!\n", argv[i][1]); + return (1); + } + else if (num_files < 1000) + { + /* + * Print a file... + */ + + if (access(argv[i], R_OK) != 0) + { + fprintf(stderr, "lpr: Unable to access \"%s\" - %s\n", argv[i], + strerror(errno)); + return (1); + } + + files[num_files] = argv[i]; + num_files ++; + + if (title == NULL) + { + if ((title = strrchr(argv[i], '/')) != NULL) + title ++; + else + title = argv[i]; + } + } + else + fprintf(stderr, "lpr: Too many files - \"%s\"\n", argv[i]); + /* + * See if we have any files to print; if not, print from stdin... + */ + + if (printer == NULL) + { + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + for (j = 0, dest = dests; j < num_dests; j ++, dest ++) + if (dest->is_default) + { + printer = dests[j].name; + + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + break; + } + } + + if (printer == NULL) + { + fputs("lpr: error - no default destination available.\n", stderr); + return (1); + } + + if (num_files > 0) + { + job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options); + + if (deletefile) + { + /* + * Delete print files after printing... + */ + + for (i = 0; i < num_files; i ++) + unlink(files[i]); + } + } + else + { + num_files = 1; + +#ifndef WIN32 +# if defined(HAVE_SIGSET) + sigset(SIGHUP, sighandler); + if (sigset(SIGINT, sighandler) == SIG_IGN) + sigset(SIGINT, SIG_IGN); + sigset(SIGTERM, sighandler); +# elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + action.sa_handler = sighandler; + + sigaction(SIGHUP, &action, NULL); + sigaction(SIGINT, NULL, &oldaction); + if (oldaction.sa_handler != SIG_IGN) + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); +# else + signal(SIGHUP, sighandler); + if (signal(SIGINT, sighandler) == SIG_IGN) + signal(SIGINT, SIG_IGN); + signal(SIGTERM, sighandler); +# endif +#endif /* !WIN32 */ + + if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0) + { + fputs("lpr: unable to create temporary file.\n", stderr); + return (1); + } + + while ((i = read(0, buffer, sizeof(buffer))) > 0) + write(temp, buffer, i); + + i = lseek(temp, 0, SEEK_CUR); + close(temp); + + if (i == 0) + { + fputs("lpr: stdin is empty, so no job has been sent.\n", stderr); + return (1); + } + + if (title) + job_id = cupsPrintFile(printer, tempfile, title, num_options, options); + else + job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options); + + unlink(tempfile); + } + + if (job_id < 1) + { + fprintf(stderr, "lpr: unable to print file: %s\n", + ippErrorString(cupsLastError())); + return (1); + } + + return (0); +} + + +#ifndef WIN32 +/* + * 'sighandler()' - Signal catcher for when we print from stdin... + */ + +void +sighandler(int s) /* I - Signal number */ +{ + /* + * Remove the temporary file we're using to print from stdin... + */ + + unlink(tempfile); + + /* + * Exit... + */ + + exit(s); +} +#endif /* !WIN32 */ + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lprm.c b/berkeley/lprm.c new file mode 100644 index 0000000000..c27842cc14 --- /dev/null +++ b/berkeley/lprm.c @@ -0,0 +1,275 @@ +/* + * "$Id$" + * + * "lprm" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Parse options and cancel jobs. + */ + +/* + * Include necessary headers... + */ + +#include +#include + +#include +#include +#include + + +/* + * 'main()' - Parse options and cancel jobs. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + http_t *http; /* HTTP connection to server */ + int i; /* Looping var */ + int job_id; /* Job ID */ + const char *dest; /* Destination printer */ + char *instance; /* Pointer to instance name */ + char uri[1024]; /* Printer or job URI */ + ipp_t *request; /* IPP request */ + ipp_t *response; /* IPP response */ + ipp_op_t op; /* Operation */ + cups_lang_t *language; /* Language */ + int num_dests; /* Number of destinations */ + cups_dest_t *dests; /* Destinations */ + http_encryption_t encryption; /* Encryption? */ + + + /* + * Setup to cancel individual print jobs... + */ + + op = IPP_CANCEL_JOB; + job_id = 0; + dest = NULL; + response = NULL; + http = NULL; + encryption = cupsEncryption(); + + num_dests = cupsGetDests(&dests); + + for (i = 0; i < num_dests; i ++) + if (dests[i].is_default) + dest = dests[i].name; + + /* + * Open a connection to the server... + */ + + if ((http = httpConnectEncrypt(cupsServer(), ippPort(), encryption)) == NULL) + { + fputs("lprm: Unable to contact server!\n", stderr); + cupsFreeDests(num_dests, dests); + return (1); + } + + /* + * Process command-line arguments... + */ + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '-' && argv[i][1] != '\0') + switch (argv[i][1]) + { + case 'E' : /* Encrypt */ +#ifdef HAVE_LIBSSL + encryption = HTTP_ENCRYPT_REQUIRED; + + httpEncryption(http, encryption); +#else + fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n", + argv[0]); +#endif /* HAVE_LIBSSL */ + break; + + case 'P' : /* Cancel jobs on a printer */ + if (argv[i][2]) + dest = argv[i] + 2; + else + { + i ++; + dest = argv[i]; + } + + if ((instance = strchr(dest, '/')) != NULL) + *instance = '\0'; + + if (cupsGetDest(dest, NULL, num_dests, dests) == NULL) + { + fprintf(stderr, "lprm: Unknown destination \"%s\"!\n", dest); + cupsFreeDests(num_dests, dests); + httpClose(http); + return(1); + } + break; + + default : + fprintf(stderr, "lprm: Unknown option \'%c\'!\n", argv[i][1]); + cupsFreeDests(num_dests, dests); + httpClose(http); + return (1); + } + else + { + /* + * Cancel a job or printer... + */ + + if (isdigit(argv[i][0]) && cupsGetDest(argv[i], NULL, num_dests, dests) == NULL) + { + dest = NULL; + op = IPP_CANCEL_JOB; + job_id = atoi(argv[i]); + } + else if (strcmp(argv[i], "-") == 0) + { + /* + * Cancel all jobs + */ + + op = IPP_PURGE_JOBS; + } + else + { + dest = argv[i]; + job_id = 0; + } + + /* + * Build an IPP request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + job-id *or* job-uri + * [requesting-user-name] + */ + + 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); + + if (dest) + { + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", dest); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", + job_id); + } + else + { + sprintf(uri, "ipp://localhost/jobs/%d", job_id); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, + uri); + } + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requesting-user-name", NULL, cupsUser()); + + /* + * Do the request and get back a response... + */ + + if (op == IPP_PURGE_JOBS) + response = cupsDoRequest(http, request, "/admin/"); + else + response = cupsDoRequest(http, request, "/jobs/"); + + if (response != NULL) + { + switch (response->request.status.status_code) + { + case IPP_NOT_FOUND : + fputs("lprm: Job or printer not found!\n", stderr); + break; + case IPP_NOT_AUTHORIZED : + fputs("lprm: Not authorized to lprm job(s)!\n", stderr); + break; + case IPP_FORBIDDEN : + fprintf(stderr, "lprm: You don't own job ID %d!\n", job_id); + break; + default : + if (response->request.status.status_code > IPP_OK_CONFLICT) + fputs("lprm: Unable to lprm job(s)!\n", stderr); + break; + } + + if (response->request.status.status_code > IPP_OK_CONFLICT) + { + ippDelete(response); + cupsFreeDests(num_dests, dests); + httpClose(http); + return (1); + } + + ippDelete(response); + } + else + { + fputs("lprm: Unable to cancel job(s)!\n", stderr); + cupsFreeDests(num_dests, dests); + httpClose(http); + return (1); + } + } + + /* + * If nothing has been cancelled yet, cancel the current job on the specified + * (or default) printer... + */ + + if (response == NULL) + if (!cupsCancelJob(dest, 0)) + { + fputs("lprm: Unable to cancel job(s)!\n", stderr); + cupsFreeDests(num_dests, dests); + httpClose(http); + return (1); + } + + cupsFreeDests(num_dests, dests); + httpClose(http); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/.cvsignore b/cgi-bin/.cvsignore new file mode 100644 index 0000000000..77c74e4335 --- /dev/null +++ b/cgi-bin/.cvsignore @@ -0,0 +1,5 @@ +admin.cgi +classes.cgi +jobs.cgi +libcgi.a +printers.cgi diff --git a/cgi-bin/Dependencies b/cgi-bin/Dependencies new file mode 100644 index 0000000000..d69abebfa0 --- /dev/null +++ b/cgi-bin/Dependencies @@ -0,0 +1,20 @@ +# DO NOT DELETE + +html.o: cgi.h ../cups/string.h ../config.h +ipp-var.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +ipp-var.o: ../cups/md5.h ../cups/ppd.h ../cups/debug.h ../cups/language.h +ipp-var.o: ../cups/string.h ../config.h cgi.h +template.o: cgi.h ../cups/string.h ../config.h +var.o: cgi.h ../cups/string.h ../config.h +admin.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +admin.o: ../cups/ppd.h ../cups/debug.h ../cups/language.h ../cups/string.h +admin.o: ../config.h cgi.h +classes.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +classes.o: ../cups/md5.h ../cups/ppd.h ../cups/debug.h ../cups/language.h +classes.o: ../cups/string.h ../config.h cgi.h +jobs.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +jobs.o: ../cups/ppd.h ../cups/debug.h ../cups/language.h ../cups/string.h +jobs.o: ../config.h cgi.h +printers.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +printers.o: ../cups/md5.h ../cups/ppd.h ../cups/debug.h ../cups/language.h +printers.o: ../cups/string.h ../config.h cgi.h diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile new file mode 100644 index 0000000000..85237077d4 --- /dev/null +++ b/cgi-bin/Makefile @@ -0,0 +1,123 @@ +# +# "$Id$" +# +# CGI makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 by Easy Software Products. +# +# 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 +# + +include ../Makedefs + +CGIS = admin.cgi classes.cgi jobs.cgi printers.cgi +TARGETS = libcgi.a $(CGIS) +LIBOBJS = html.o ipp-var.o template.o var.o +OBJS = $(LIBOBJS) admin.o classes.o jobs.o printers.o + + +# +# Make all targets... +# + +all: $(TARGETS) + + +# +# Clean all object files... +# + +clean: + $(RM) $(OBJS) $(TARGETS) + + +# +# Update dependencies (without system header dependencies...) +# + +depend: + makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1 + + +# +# Install all targets... +# + +install: all + $(INSTALL_DIR) $(SERVERBIN)/cgi-bin + for file in $(CGIS); do \ + $(INSTALL_BIN) $$file $(SERVERBIN)/cgi-bin; \ + done + + +# +# libcgi.a +# + +libcgi.a: $(LIBOBJS) + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + + +# +# admin.cgi +# + +admin.cgi: admin.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ admin.o libcgi.a $(LIBS) + + +# +# classes.cgi +# + +classes.cgi: classes.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ classes.o libcgi.a $(LIBS) + + +# +# jobs.cgi +# + +jobs.cgi: jobs.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ jobs.o libcgi.a $(LIBS) + + +# +# printers.cgi +# + +printers.cgi: printers.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ printers.o libcgi.a $(LIBS) + + +# +# Dependencies... +# + +include Dependencies + + +# +# End of "$Id$". +# diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c new file mode 100644 index 0000000000..c3c92fd0f7 --- /dev/null +++ b/cgi-bin/admin.c @@ -0,0 +1,1535 @@ +/* + * "$Id$" + * + * Administration CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Main entry for CGI. + * do_am_class() - Add or modify a class. + * do_am_printer() - Add or modify a printer. + * do_config_printer() - Configure the default options for a printer. + * do_delete_class() - Delete a class... + * do_delete_printer() - Delete a printer... + * do_printer_op() - Do a printer operation. + * get_line() - Get a line that is terminated by a LF, CR, or CR LF. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" +#include +#include + + +/* + * Local functions... + */ + +static void do_am_class(http_t *http, cups_lang_t *language, int modify); +static void do_am_printer(http_t *http, cups_lang_t *language, int modify); +static void do_config_printer(http_t *http, cups_lang_t *language); +static void do_delete_class(http_t *http, cups_lang_t *language); +static void do_delete_printer(http_t *http, cups_lang_t *language); +static void do_printer_op(http_t *http, cups_lang_t *language, ipp_op_t op); +static char *get_line(char *buf, int length, FILE *fp); + + +/* + * 'main()' - Main entry for CGI. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + cups_lang_t *language; /* Language information */ + http_t *http; /* Connection to the server */ + const char *op; /* Operation name */ + + + /* + * Get the request language... + */ + + language = cupsLangDefault(); + + /* + * Send a standard header... + */ + + printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language)); + + cgiSetVariable("TITLE", "Admin"); + ippSetServerVersion(); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + /* + * See if we have form data... + */ + + if (!cgiInitialize()) + { + /* + * Nope, send the administration menu... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "admin.tmpl", getenv("LANG")); + } + else if ((op = cgiGetVariable("OP")) != NULL) + { + /* + * Connect to the HTTP server... + */ + + http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption()); + + /* + * Do the operation... + */ + + if (strcmp(op, "start-printer") == 0) + do_printer_op(http, language, IPP_RESUME_PRINTER); + else if (strcmp(op, "stop-printer") == 0) + do_printer_op(http, language, IPP_PAUSE_PRINTER); + else if (strcmp(op, "accept-jobs") == 0) + do_printer_op(http, language, CUPS_ACCEPT_JOBS); + else if (strcmp(op, "reject-jobs") == 0) + do_printer_op(http, language, CUPS_REJECT_JOBS); + else if (strcmp(op, "purge-jobs") == 0) + do_printer_op(http, language, IPP_PURGE_JOBS); + else if (strcmp(op, "add-class") == 0) + do_am_class(http, language, 0); + else if (strcmp(op, "add-printer") == 0) + do_am_printer(http, language, 0); + else if (strcmp(op, "modify-class") == 0) + do_am_class(http, language, 1); + else if (strcmp(op, "modify-printer") == 0) + do_am_printer(http, language, 1); + else if (strcmp(op, "delete-class") == 0) + do_delete_class(http, language); + else if (strcmp(op, "delete-printer") == 0) + do_delete_printer(http, language); + else if (strcmp(op, "config-printer") == 0) + do_config_printer(http, language); + else + { + /* + * Bad operation code... Display an error... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "admin-op.tmpl", getenv("LANG")); + } + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + } + else + { + /* + * Form data but no operation code... Display an error... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "admin-op.tmpl", getenv("LANG")); + } + + /* + * Send the standard trailer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * Free the request language... + */ + + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * 'do_am_class()' - Add or modify a class. + */ + +static void +do_am_class(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + int modify) /* I - Modify the printer? */ +{ + int i, j; /* Looping vars */ + int element; /* Element number */ + int num_printers; /* Number of printers */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* member-uris attribute */ + ipp_status_t status; /* Request status */ + char uri[HTTP_MAX_URI]; /* Device or printer URI */ + const char *name, /* Pointer to class name */ + *ptr; /* Pointer to CGI variable */ + + + if (cgiGetVariable("PRINTER_LOCATION") == NULL) + { + if (modify) + { + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the + * following attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response, NULL, NULL); + ippDelete(response); + } + + /* + * Update the location and description of an existing printer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "modify-class.tmpl", getenv("LANG")); + } + else + { + /* + * Get the name, location, and description for a new printer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "add-class.tmpl", getenv("LANG")); + } + + return; + } + + name = cgiGetVariable("PRINTER_NAME"); + for (ptr = name; *ptr; ptr ++) + if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/') + break; + + if (*ptr || ptr == name || strlen(name) > 127) + { + cgiSetVariable("ERROR", "The class name may only contain up to 127 printable " + "characters."); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + if (cgiGetVariable("MEMBER_URIS") == NULL) + { + /* + * Build a CUPS_GET_PRINTERS request, which requires the + * following attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + + 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, "ipp://localhost/printers"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + /* + * Create MEMBER_URIS and MEMBER_NAMES arrays... + */ + + for (element = 0, attr = response->attrs; + attr != NULL; + attr = attr->next) + if (attr->name && strcmp(attr->name, "printer-uri-supported") == 0) + { + cgiSetArray("MEMBER_URIS", element, attr->values[0].string.text); + element ++; + } + + for (element = 0, attr = response->attrs; + attr != NULL; + attr = attr->next) + if (attr->name && strcmp(attr->name, "printer-name") == 0) + { + cgiSetArray("MEMBER_NAMES", element, attr->values[0].string.text); + element ++; + } + + num_printers = cgiGetSize("MEMBER_URIS"); + + ippDelete(response); + } + else + num_printers = 0; + + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the + * following attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) + { + /* + * Mark any current members in the class... + */ + + for (j = 0; j < num_printers; j ++) + cgiSetArray("MEMBER_SELECTED", j, ""); + + for (i = 0; i < attr->num_values; i ++) + for (j = 0; j < num_printers; j ++) + if (strcmp(attr->values[i].string.text, cgiGetArray("MEMBER_URIS", j)) == 0) + { + cgiSetArray("MEMBER_SELECTED", j, "SELECTED"); + break; + } + } + + ippDelete(response); + } + + /* + * Let the user choose... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-members.tmpl", getenv("LANG")); + } + else + { + /* + * Build a CUPS_ADD_CLASS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * printer-location + * printer-info + * printer-is-accepting-jobs + * printer-state + * member-uris + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_ADD_CLASS; + request->request.op.request_id = 1; + + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", + NULL, cgiGetVariable("PRINTER_LOCATION")); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", + NULL, cgiGetVariable("PRINTER_INFO")); + + ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1); + + ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", + IPP_PRINTER_IDLE); + + if ((num_printers = cgiGetSize("MEMBER_URIS")) > 0) + { + attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", + num_printers, NULL, NULL); + for (i = 0; i < num_printers; i ++) + attr->values[i].string.text = strdup(cgiGetArray("MEMBER_URIS", i)); + } + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + ippDelete(response); + } + else + status = cupsLastError(); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (modify) + cgiCopyTemplateLang(stdout, TEMPLATES, "class-modified.tmpl", getenv("LANG")); + else + cgiCopyTemplateLang(stdout, TEMPLATES, "class-added.tmpl", getenv("LANG")); + } +} + + +/* + * 'do_am_printer()' - Add or modify a printer. + */ + +static void +do_am_printer(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + int modify) /* I - Modify the printer? */ +{ + int i; /* Looping var */ + int element; /* Element number */ + ipp_attribute_t *attr, /* Current attribute */ + *last; /* Last attribute */ + ipp_t *request, /* IPP request */ + *response, /* IPP response */ + *oldinfo; /* Old printer information */ + ipp_status_t status; /* Request status */ + const char *var; /* CGI variable */ + char uri[HTTP_MAX_URI], /* Device or printer URI */ + *uriptr; /* Pointer into URI */ + int maxrate; /* Maximum baud rate */ + char baudrate[255]; /* Baud rate string */ + char make[255]; /* Make string */ + const char *name, /* Pointer to class name */ + *ptr; /* Pointer to CGI variable */ + static int baudrates[] = /* Baud rates */ + { + 1200, + 2400, + 4800, + 9600, + 19200, + 38400, + 57600, + 115200, + 230400, + 460800 + }; + + + if (modify) + { + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the + * following attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + oldinfo = cupsDoRequest(http, request, "/"); + } + else + oldinfo = NULL; + + if ((name = cgiGetVariable("PRINTER_NAME")) == NULL || + cgiGetVariable("PRINTER_LOCATION") == NULL) + { + if (modify) + { + /* + * Update the location and description of an existing printer... + */ + + if (oldinfo) + ippSetCGIVars(oldinfo, NULL, NULL); + + cgiCopyTemplateLang(stdout, TEMPLATES, "modify-printer.tmpl", getenv("LANG")); + } + else + { + /* + * Get the name, location, and description for a new printer... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "add-printer.tmpl", getenv("LANG")); + } + + if (oldinfo) + ippDelete(oldinfo); + + return; + } + + for (ptr = name; *ptr; ptr ++) + if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/') + break; + + if (*ptr || ptr == name || strlen(name) > 127) + { + cgiSetVariable("ERROR", "The printer name may only contain up to 127 printable " + "characters."); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + if ((var = cgiGetVariable("DEVICE_URI")) == NULL) + { + /* + * Build a CUPS_GET_DEVICES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_DEVICES; + request->request.op.request_id = 1; + + 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, "ipp://localhost/printers/"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response, NULL, NULL); + ippDelete(response); + } + + /* + * Let the user choose... + */ + + if (oldinfo && + (attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL) + { + strlcpy(uri, attr->values[0].string.text, sizeof(uri)); + if ((uriptr = strchr(uri, ':')) != NULL && strncmp(uriptr, "://", 3) == 0) + *uriptr = '\0'; + + cgiSetVariable("CURRENT_DEVICE_URI", uri); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-device.tmpl", getenv("LANG")); + } + else if (strchr(var, '/') == NULL) + { + if (oldinfo && + (attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL) + { + /* + * Set the current device URI for the form to the old one... + */ + + if (strncmp(attr->values[0].string.text, var, strlen(var)) == 0) + cgiSetVariable("DEVICE_URI", attr->values[0].string.text); + } + + /* + * User needs to set the full URI... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-uri.tmpl", getenv("LANG")); + } + else if (strncmp(var, "serial:", 7) == 0 && cgiGetVariable("BAUDRATE") == NULL) + { + /* + * Need baud rate, parity, etc. + */ + + if ((var = strchr(var, '?')) != NULL && + strncmp(var, "?baud=", 6) == 0) + maxrate = atoi(var + 6); + else + maxrate = 19200; + + for (i = 0; i < 10; i ++) + if (baudrates[i] > maxrate) + break; + else + { + sprintf(baudrate, "%d", baudrates[i]); + cgiSetArray("BAUDRATES", i, baudrate); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-serial.tmpl", getenv("LANG")); + } + else if ((var = cgiGetVariable("PPD_NAME")) == NULL) + { + if (modify) + { + /* + * Get the PPD file... + */ + + int fd; /* PPD file */ + char filename[1024]; /* PPD filename */ + ppd_file_t *ppd; /* PPD information */ + char buffer[1024]; /* Buffer */ + int bytes; /* Number of bytes */ + + + snprintf(uri, sizeof(uri), "/printers/%s.ppd", name); + + if (httpGet(http, uri)) + httpGet(http, uri); + + while (httpUpdate(http) == HTTP_CONTINUE); + + if ((fd = cupsTempFd(filename, sizeof(filename))) >= 0) + { + while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0) + write(fd, buffer, bytes); + + close(fd); + + if ((ppd = ppdOpenFile(filename)) != NULL) + { + if (ppd->manufacturer) + cgiSetVariable("CURRENT_MAKE", ppd->manufacturer); + if (ppd->nickname) + cgiSetVariable("CURRENT_MAKE_AND_MODEL", ppd->nickname); + + ppdClose(ppd); + } + + unlink(filename); + } + else + httpFlush(http); + } + + /* + * Build a CUPS_GET_PPDS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PPDS; + request->request.op.request_id = 1; + + 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, "ipp://localhost/printers/"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if ((var = cgiGetVariable("PPD_MAKE")) == NULL) + { + /* + * Let the user choose a make... + */ + + for (element = 0, attr = response->attrs, last = NULL; + attr != NULL; + attr = attr->next) + if (attr->name && strcmp(attr->name, "ppd-make") == 0) + if (last == NULL || + strcasecmp(last->values[0].string.text, + attr->values[0].string.text) != 0) + { + cgiSetArray("PPD_MAKE", element, attr->values[0].string.text); + element ++; + last = attr; + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-make.tmpl", + getenv("LANG")); + } + else + { + /* + * Let the user choose a model... + */ + + strlcpy(make, var, sizeof(make)); + + ippSetCGIVars(response, "ppd-make", make); + cgiCopyTemplateLang(stdout, TEMPLATES, "choose-model.tmpl", + getenv("LANG")); + } + + ippDelete(response); + } + else + { + char message[1024]; + + + snprintf(message, sizeof(message), "Unable to get list of printer drivers: %s", + ippErrorString(cupsLastError())); + cgiSetVariable("ERROR", message); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + } + else + { + /* + * Build a CUPS_ADD_PRINTER request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * printer-location + * printer-info + * ppd-name + * device-uri + * printer-is-accepting-jobs + * printer-state + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_ADD_PRINTER; + request->request.op.request_id = 1; + + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", + NULL, cgiGetVariable("PRINTER_LOCATION")); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", + NULL, cgiGetVariable("PRINTER_INFO")); + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name", + NULL, cgiGetVariable("PPD_NAME")); + + strlcpy(uri, cgiGetVariable("DEVICE_URI"), sizeof(uri)); + if (strncmp(uri, "serial:", 7) == 0) + { + /* + * Update serial port URI to include baud rate, etc. + */ + + if ((uriptr = strchr(uri, '?')) == NULL) + uriptr = uri + strlen(uri); + + snprintf(uriptr, sizeof(uri) - (uriptr - uri), + "?baud=%s+bits=%s+parity=%s+flow=%s", + cgiGetVariable("BAUDRATE"), cgiGetVariable("BITS"), + cgiGetVariable("PARITY"), cgiGetVariable("FLOW")); + } + + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", + NULL, uri); + + ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1); + + ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", + IPP_PRINTER_IDLE); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + ippDelete(response); + } + else + status = cupsLastError(); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (modify) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-modified.tmpl", getenv("LANG")); + else + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-added.tmpl", getenv("LANG")); + } + + if (oldinfo) + ippDelete(oldinfo); +} + + +/* + * 'do_config_printer()' - Configure the default options for a printer. + */ + +static void +do_config_printer(http_t *http, /* I - HTTP connection */ + cups_lang_t *language)/* I - Client's language */ +{ + int i, j, k; /* Looping vars */ + int have_options; /* Have options? */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP attribute */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *var; /* Variable value */ + const char *printer; /* Printer printer name */ + ipp_status_t status; /* Operation status... */ + const char *filename; /* PPD filename */ + char tempfile[1024]; /* Temporary filename */ + FILE *in, /* Input file */ + *out; /* Output file */ + int outfd; /* Output file descriptor */ + char line[1024]; /* Line from PPD file */ + char keyword[1024], /* Keyword from Default line */ + *keyptr; /* Pointer into keyword... */ + ppd_file_t *ppd; /* PPD file */ + ppd_group_t *group; /* Option group */ + ppd_option_t *option; /* Option */ + + + /* + * Get the printer name... + */ + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + /* + * Get the PPD file... + */ + + cupsSetServer("localhost"); + + if ((filename = cupsGetPPD(printer)) == NULL) + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + ppd = ppdOpenFile(filename); + + if (cgiGetVariable("job_sheets_start") != NULL || + cgiGetVariable("job_sheets_end") != NULL) + have_options = 1; + else + have_options = 0; + + ppdMarkDefaults(ppd); + + DEBUG_printf(("

ppd->num_groups = %d\n" + "

    \n", ppd->num_groups)); + + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + { + DEBUG_printf(("
  • %s
      \n", group->text)); + + for (j = group->num_options, option = group->options; j > 0; j --, option ++) + if ((var = cgiGetVariable(option->keyword)) != NULL) + { + DEBUG_printf(("
    • %s = \"%s\"
    • \n", option->keyword, var)); + have_options = 1; + ppdMarkOption(ppd, option->keyword, var); + } +#ifdef DEBUG + else + printf("
    • %s not defined!
    • \n", option->keyword); +#endif /* DEBUG */ + + DEBUG_puts("
  • "); + } + + DEBUG_printf(("
\n" + "

ppdConflicts(ppd) = %d\n", ppdConflicts(ppd))); + + if (!have_options || ppdConflicts(ppd)) + { + /* + * Show the options to the user... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "config-printer.tmpl", + getenv("LANG")); + + if (ppdConflicts(ppd)) + { + for (i = ppd->num_groups, k = 0, group = ppd->groups; i > 0; i --, group ++) + for (j = group->num_options, option = group->options; j > 0; j --, option ++) + if (option->conflicted) + { + cgiSetArray("ckeyword", k, option->keyword); + cgiSetArray("ckeytext", k, option->text); + k ++; + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-conflict.tmpl", + getenv("LANG")); + } + + for (i = ppd->num_groups, group = ppd->groups; + i > 0; + i --, group ++) + { + if (strcmp(group->text, "InstallableOptions") == 0) + cgiSetVariable("GROUP", + cupsLangString(language, CUPS_MSG_OPTIONS_INSTALLED)); + else + cgiSetVariable("GROUP", group->text); + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-header.tmpl", + getenv("LANG")); + + for (j = group->num_options, option = group->options; + j > 0; + j --, option ++) + { + if (strcmp(option->keyword, "PageRegion") == 0) + continue; + + cgiSetVariable("KEYWORD", option->keyword); + cgiSetVariable("KEYTEXT", option->text); + + if (option->conflicted) + cgiSetVariable("CONFLICTED", "1"); + else + cgiSetVariable("CONFLICTED", "0"); + + cgiSetSize("CHOICES", option->num_choices); + cgiSetSize("TEXT", option->num_choices); + for (k = 0; k < option->num_choices; k ++) + { + cgiSetArray("CHOICES", k, option->choices[k].choice); + cgiSetArray("TEXT", k, option->choices[k].text); + + if (option->choices[k].marked) + cgiSetVariable("DEFCHOICE", option->choices[k].choice); + } + + switch (option->ui) + { + case PPD_UI_BOOLEAN : + cgiCopyTemplateLang(stdout, TEMPLATES, "option-boolean.tmpl", + getenv("LANG")); + break; + case PPD_UI_PICKONE : + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl", + getenv("LANG")); + break; + case PPD_UI_PICKMANY : + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickmany.tmpl", + getenv("LANG")); + break; + } + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-trailer.tmpl", + getenv("LANG")); + } + + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the + * following attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if ((attr = ippFindAttribute(response, "job-sheets-supported", IPP_TAG_ZERO)) != NULL) + { + /* + * Add the job sheets options... + */ + + cgiSetVariable("GROUP", "Banners"); + cgiCopyTemplateLang(stdout, TEMPLATES, "option-header.tmpl", + getenv("LANG")); + + cgiSetSize("CHOICES", attr->num_values); + cgiSetSize("TEXT", attr->num_values); + for (k = 0; k < attr->num_values; k ++) + { + cgiSetArray("CHOICES", k, attr->values[k].string.text); + cgiSetArray("TEXT", k, attr->values[k].string.text); + } + + attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO); + + cgiSetVariable("KEYWORD", "job_sheets_start"); + cgiSetVariable("KEYTEXT", "Starting Banner"); + cgiSetVariable("DEFCHOICE", attr == NULL ? + "" : attr->values[0].string.text); + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl", + getenv("LANG")); + + cgiSetVariable("KEYWORD", "job_sheets_end"); + cgiSetVariable("KEYTEXT", "Ending Banner"); + cgiSetVariable("DEFCHOICE", attr == NULL && attr->num_values > 1 ? + "" : attr->values[1].string.text); + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl", + getenv("LANG")); + + cgiCopyTemplateLang(stdout, TEMPLATES, "option-trailer.tmpl", + getenv("LANG")); + } + + ippDelete(response); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "config-printer2.tmpl", + getenv("LANG")); + } + else + { + /* + * Set default options... + */ + + outfd = cupsTempFd(tempfile, sizeof(tempfile)); + in = fopen(filename, "rb"); + out = fdopen(outfd, "wb"); + + if (outfd < 0 || in == NULL || out == NULL) + { + cgiSetVariable("ERROR", strerror(errno)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + unlink(filename); + return; + } + + while (get_line(line, sizeof(line), in) != NULL) + { + if (strncmp(line, "*Default", 8) != 0) + fprintf(out, "%s\n", line); + else + { + /* + * Get default option name... + */ + + strlcpy(keyword, line + 8, sizeof(keyword)); + + for (keyptr = keyword; *keyptr; keyptr ++) + if (*keyptr == ':' || isspace(*keyptr)) + break; + + *keyptr = '\0'; + + if (strcmp(keyword, "PageRegion") == 0) + var = cgiGetVariable("PageSize"); + else + var = cgiGetVariable(keyword); + + if (var != NULL) + fprintf(out, "*Default%s: %s\n", keyword, var); + else + fprintf(out, "%s\n", line); + } + } + + fclose(in); + fclose(out); + close(outfd); + + /* + * Build a CUPS_ADD_PRINTER request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * job-sheets-default + * [ppd file] + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_ADD_PRINTER; + request->request.op.request_id = 1; + + 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); + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", + cgiGetVariable("PRINTER_NAME")); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME, + "job-sheets-default", 2, NULL, NULL); + attr->values[0].string.text = strdup(cgiGetVariable("job_sheets_start")); + attr->values[1].string.text = strdup(cgiGetVariable("job_sheets_end")); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoFileRequest(http, request, "/admin/", tempfile)) != NULL) + { + status = response->request.status.status_code; + ippDelete(response); + } + else + status = cupsLastError(); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-configured.tmpl", getenv("LANG")); + + unlink(tempfile); + } + + unlink(filename); +} + + +/* + * 'do_delete_class()' - Delete a class... + */ + +static void +do_delete_class(http_t *http, /* I - HTTP connection */ + cups_lang_t *language) /* I - Client's language */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *pclass; /* Printer class name */ + ipp_status_t status; /* Operation status... */ + + + if (cgiGetVariable("CONFIRM") == NULL) + { + cgiCopyTemplateLang(stdout, TEMPLATES, "class-confirm.tmpl", getenv("LANG")); + return; + } + + if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + /* + * Build a CUPS_DELETE_CLASS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_DELETE_CLASS; + request->request.op.request_id = 1; + + 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); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = cupsLastError(); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "class-deleted.tmpl", getenv("LANG")); +} + + +/* + * 'do_delete_printer()' - Delete a printer... + */ + +static void +do_delete_printer(http_t *http, /* I - HTTP connection */ + cups_lang_t *language)/* I - Client's language */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *printer; /* Printer printer name */ + ipp_status_t status; /* Operation status... */ + + + if (cgiGetVariable("CONFIRM") == NULL) + { + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-confirm.tmpl", getenv("LANG")); + return; + } + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + /* + * Build a CUPS_DELETE_PRINTER request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_DELETE_PRINTER; + request->request.op.request_id = 1; + + 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); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = cupsLastError(); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-deleted.tmpl", getenv("LANG")); +} + + +/* + * 'do_printer_op()' - Do a printer operation. + */ + +static void +do_printer_op(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + ipp_op_t op) /* I - Operation to perform */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Printer URI */ + const char *printer; /* Printer name (purge-jobs) */ + ipp_status_t status; /* Operation status... */ + + + if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + /* + * Build a printer request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = op; + request->request.op.request_id = 1; + + 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); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = cupsLastError(); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (op == IPP_PAUSE_PRINTER) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-stop.tmpl", getenv("LANG")); + else if (op == IPP_RESUME_PRINTER) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-start.tmpl", getenv("LANG")); + else if (op == CUPS_ACCEPT_JOBS) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-accept.tmpl", getenv("LANG")); + else if (op == CUPS_REJECT_JOBS) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-reject.tmpl", getenv("LANG")); + else if (op == IPP_PURGE_JOBS) + cgiCopyTemplateLang(stdout, TEMPLATES, "printer-purge.tmpl", getenv("LANG")); +} + + +/* + * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF. + */ + +static char * /* O - Pointer to buf or NULL on EOF */ +get_line(char *buf, /* I - Line buffer */ + int length, /* I - Length of buffer */ + FILE *fp) /* I - File to read from */ +{ + char *bufptr; /* Pointer into buffer */ + int ch; /* Character from file */ + + + length --; + bufptr = buf; + + while ((ch = getc(fp)) != EOF) + { + if (ch == '\n') + break; + else if (ch == '\r') + { + /* + * Look for LF... + */ + + ch = getc(fp); + if (ch != '\n' && ch != EOF) + ungetc(ch, fp); + + break; + } + + *bufptr++ = ch; + length --; + if (length == 0) + break; + } + + *bufptr = '\0'; + + if (ch == EOF) + return (NULL); + else + return (buf); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/cgi.h b/cgi-bin/cgi.h new file mode 100644 index 0000000000..14c41f3df0 --- /dev/null +++ b/cgi-bin/cgi.h @@ -0,0 +1,86 @@ +/* + * "$Id$" + * + * CGI support library definitions. + * + * Copyright 1997-2002 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CGI_H_ +# define _CGI_H_ + +# include +# include +# include + +# include + +# ifdef WIN32 +# include +# include +# include +# else +# include +# endif /* WIN32 */ + + +/* + * Prototypes... + */ + +extern int cgiInitialize(void); +extern void cgiAbort(const char *title, const char *stylesheet, + const char *format, ...); +extern int cgiCheckVariables(const char *names); +extern const char *cgiGetArray(const char *name, int element); +extern int cgiGetSize(const char *name); +extern void cgiSetSize(const char *name, int size); +extern const char *cgiGetVariable(const char *name); +extern void cgiSetArray(const char *name, int element, + const char *value); +extern void cgiSetVariable(const char *name, const char *value); +extern void cgiCopyTemplateFile(FILE *out, const char *tmpl); +extern void cgiCopyTemplateLang(FILE *out, const char *directory, + const char *tmpl, const char *lang); + +extern void cgiStartHTML(FILE *out, const char *author, + const char *stylesheet, + const char *keywords, + const char *description, + const char *title, ...); +extern void cgiEndHTML(FILE *out); + +extern FILE *cgiEMailOpen(const char *from, const char *to, + const char *cc, const char *subject, + int multipart); +extern void cgiEMailPart(FILE *mail, const char *type, + const char *charset, const char *encoding); +extern void cgiEMailClose(FILE *mail); + +extern char *cgiGetCookie(const char *name, char *buf, int buflen); +extern void cgiSetCookie(const char *name, const char *value, + const char *path, const char *domain, + time_t expires, int secure); + +# define cgiGetUser() getenv("REMOTE_USER") +# define cgiGetHost() (getenv("REMOTE_HOST") == NULL ? getenv("REMOTE_ADDR") : getenv("REMOTE_HOST")) + +#endif /* !_CGI_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/classes.c b/cgi-bin/classes.c new file mode 100644 index 0000000000..16a17b18c0 --- /dev/null +++ b/cgi-bin/classes.c @@ -0,0 +1,360 @@ +/* + * "$Id$" + * + * Class status CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Main entry for CGI. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * 'main()' - Main entry for CGI. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + cups_lang_t *language; /* Language information */ + char *pclass; /* Printer class name */ + http_t *http; /* Connection to the server */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP attribute */ + ipp_status_t status; /* Operation status... */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + const char *which_jobs; /* Which jobs to show */ + const char *op; /* Operation to perform, if any */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + op = cgiGetVariable("OP"); + + /* + * Get the request language... + */ + + language = cupsLangDefault(); + + /* + * Connect to the HTTP server... + */ + + http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption()); + + /* + * Tell the client to expect HTML... + */ + + printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language)); + + /* + * See if we need to show a list of printers or the status of a + * single printer... + */ + + ippSetServerVersion(); + + pclass = argv[0]; + if (strcmp(pclass, "/") == 0 || strcmp(pclass, "classes.cgi") == 0) + { + pclass = NULL; + cgiSetVariable("TITLE", cupsLangString(language, CUPS_MSG_CLASS)); + } + else + cgiSetVariable("TITLE", pclass); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + if (op == NULL || strcasecmp(op, "print-test-page") != 0) + { + /* + * Get the default destination... + */ + + request = ippNew(); + request->request.op.operation_id = CUPS_GET_DEFAULT; + request->request.op.request_id = 1; + + 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); + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) + cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text); + + if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) + { + char method[HTTP_MAX_URI], + username[HTTP_MAX_URI], + hostname[HTTP_MAX_URI], + resource[HTTP_MAX_URI], + uri[HTTP_MAX_URI]; + int port; /* URI data */ + const char *server; /* Name of server */ + + + /* + * Map localhost access to localhost... + */ + + server = getenv("SERVER_NAME"); + + httpSeparate(attr->values[0].string.text, method, username, + hostname, &port, resource); + + if (strcasecmp(hostname, server) == 0 && + (strcmp(getenv("REMOTE_HOST"), "127.0.0.1") == 0 || + strcmp(getenv("REMOTE_HOST"), "localhost") == 0 || + strcmp(getenv("REMOTE_HOST"), server) == 0)) + strcpy(hostname, "localhost"); + + /* + * Rewrite URI with HTTP address... + */ + + snprintf(uri, sizeof(uri), "http://%s:%d%s", hostname, port, + resource); + + cgiSetVariable("DEFAULT_URI", uri); + } + + ippDelete(response); + } + + /* + * Get the class info... + */ + + request = ippNew(); + + 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); + + if (pclass == NULL) + { + /* + * Build a CUPS_GET_CLASSES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request->request.op.operation_id = CUPS_GET_CLASSES; + request->request.op.request_id = 1; + } + else + { + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/classes/%s", getenv("SERVER_NAME"), + pclass); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, + uri); + } + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response, NULL, NULL); + ippDelete(response); + } + + /* + * Write the report... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "classes.tmpl", getenv("LANG")); + + /* + * Get jobs for the specified class if a class has been chosen... + */ + + if (pclass != NULL) + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + 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); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/classes/%s", getenv("SERVER_NAME"), + pclass); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, + uri); + + if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", + NULL, which_jobs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response, NULL, NULL); + ippDelete(response); + + cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG")); + } + } + } + else + { + /* + * Print a test page... + */ + + snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass); + + /* + * Build an IPP_PRINT_JOB request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * requesting-user-name + * document-format + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_PRINT_JOB; + request->request.op.request_id = 1; + + 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); + + if (getenv("REMOTE_USER") != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, getenv("REMOTE_USER")); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, "root"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", + NULL, "Test Page"); + + ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/postscript"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoFileRequest(http, request, uri + 15, + CUPS_DATADIR "/data/testprint.ps")) != NULL) + { + status = response->request.status.status_code; + ippSetCGIVars(response, NULL, NULL); + + ippDelete(response); + } + else + status = IPP_GONE; + + cgiSetVariable("PRINTER_NAME", pclass); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "test-page.tmpl", getenv("LANG")); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/html.c b/cgi-bin/html.c new file mode 100644 index 0000000000..ac2291ee41 --- /dev/null +++ b/cgi-bin/html.c @@ -0,0 +1,89 @@ +/* + * "$Id$" + * + * CGI HTML functions. + * + * Copyright 1997-2002 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contents: + * + * cgiStartHTML() - Start an HTML document stream. + * cgiEndHTML() - End an HTML document stream. + */ + +#include "cgi.h" +#include + + +/* + * 'cgiStartHTML()' - Start an HTML document stream. + */ + +void +cgiStartHTML(FILE *out, /* I - Output file to use */ + const char *stylesheet, /* I - Stylesheet to use */ + const char *author, /* I - Author name */ + const char *keywords, /* I - Search keywords */ + const char *description, /* I - Description of document */ + const char *title, /* I - Title for page */ + ...) /* I - Any addition args for title */ +{ + va_list ap; /* Argument pointer */ + + + fputs("Content-type: text/html\n\n", out); + fputs("\n", out); + fputs("\n", out); + fputs("\n", out); + + fputs("\t\n", out); + va_start(ap, title); + vfprintf(out, title, ap); + va_end(ap); + fputs("\n", out); + + if (stylesheet) + fprintf(out, "\t\n", + stylesheet); + if (author) + fprintf(out, "\t\n", author); + if (keywords) + fprintf(out, "\t\n", keywords); + if (description) + fprintf(out, "\t\n", description); + + fputs("\n", out); + fputs("\n", out); +} + + +/* + * 'cgiEndHTML()' - End an HTML document stream. + */ + +void +cgiEndHTML(FILE *out) /* I - Output file to use */ +{ + fputs("\n", out); + fputs("\n", out); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c new file mode 100644 index 0000000000..fd13126551 --- /dev/null +++ b/cgi-bin/ipp-var.c @@ -0,0 +1,304 @@ +/* + * "$Id$" + * + * IPP variable routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * ippGetTemplateDir() - Get the templates directory... + * ippSetServerVersion() - Set the server name and CUPS version... + * ippSetCGIVars() - Set CGI variables from an IPP response. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * 'ippGetTemplateDir()' - Get the templates directory... + */ + +char * /* O - Template directory */ +ippGetTemplateDir(void) +{ + const char *datadir; /* CUPS_DATADIR env var */ + static char templates[1024] = ""; /* Template directory */ + + + if (!templates[0]) + { + /* + * Build the template directory pathname... + */ + + if ((datadir = getenv("CUPS_DATADIR")) == NULL) + datadir = CUPS_DATADIR; + + snprintf(templates, sizeof(templates), "%s/templates", datadir); + } + + return (templates); +} + + +/* + * 'ippSetServerVersion()' - Set the server name and CUPS version... + */ + +void +ippSetServerVersion(void) +{ + cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME")); + cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER")); + cgiSetVariable("CUPS_VERSION", CUPS_SVERSION); + +#ifdef LC_TIME + setlocale(LC_TIME, ""); +#endif /* LC_TIME */ +} + + +/* + * 'ippSetCGIVars()' - Set CGI variables from an IPP response. + */ + +void +ippSetCGIVars(ipp_t *response, /* I - Response data to be copied... */ + const char *filter_name, /* I - Filter name */ + const char *filter_value) /* I - Filter value */ +{ + int element; /* Element in CGI array */ + ipp_attribute_t *attr, /* Attribute in response... */ + *filter; /* Filtering attribute */ + int i; /* Looping var */ + char name[1024], /* Name of attribute */ + value[16384], /* Value(s) */ + *valptr; /* Pointer into value */ + char method[HTTP_MAX_URI], + username[HTTP_MAX_URI], + hostname[HTTP_MAX_URI], + resource[HTTP_MAX_URI], + uri[HTTP_MAX_URI]; + int port; /* URI data */ + int ishttps; /* Using encryption? */ + const char *server; /* Name of server */ + struct tm *date; /* Date information */ + + + ippSetServerVersion(); + + server = getenv("SERVER_NAME"); + ishttps = getenv("HTTPS") != NULL; + + for (attr = response->attrs; + attr && attr->group_tag == IPP_TAG_OPERATION; + attr = attr->next); + + for (element = 0; attr != NULL; attr = attr->next, element ++) + { + /* + * Copy attributes to a separator... + */ + + if (filter_name) + { + for (filter = attr; + filter != NULL && filter->group_tag != IPP_TAG_ZERO; + filter = filter->next) + if (filter->name && strcmp(filter->name, filter_name) == 0 && + (filter->value_tag == IPP_TAG_STRING || + (filter->value_tag >= IPP_TAG_TEXTLANG && + filter->value_tag <= IPP_TAG_MIMETYPE)) && + filter->values[0].string.text != NULL && + strcasecmp(filter->values[0].string.text, filter_value) == 0) + break; + + if (!filter) + return; + + if (filter->group_tag == IPP_TAG_ZERO) + { + attr = filter; + element --; + continue; + } + } + + for (; attr != NULL && attr->group_tag != IPP_TAG_ZERO; attr = attr->next) + { + /* + * Copy the attribute name, substituting "_" for "-"... + */ + + if (attr->name == NULL) + continue; + + for (i = 0; attr->name[i]; i ++) + if (attr->name[i] == '-') + name[i] = '_'; + else + name[i] = attr->name[i]; + + name[i] = '\0'; + + /* + * Add "job_printer_name" variable if we have a "job_printer_uri" + * attribute... + */ + + if (strcmp(name, "job_printer_uri") == 0) + { + if ((valptr = strrchr(attr->values[0].string.text, '/')) == NULL) + valptr = "unknown"; + else + valptr ++; + + cgiSetArray("job_printer_name", element, valptr); + } + + /* + * Copy values... + */ + + value[0] = '\0'; /* Initially an empty string */ + valptr = value; /* Start at the beginning */ + + for (i = 0; i < attr->num_values; i ++) + { + if (i) + strlcat(valptr, ",", sizeof(value) - (valptr - value)); + + valptr += strlen(valptr); + + switch (attr->value_tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + if (strncmp(name, "time_at_", 8) == 0) + { + date = localtime((time_t *)&(attr->values[i].integer)); + strftime(valptr, sizeof(value) - (valptr - value), + CUPS_STRFTIME_FORMAT, date); + } + else + snprintf(valptr, sizeof(value) - (valptr - value), + "%d", attr->values[i].integer); + break; + + case IPP_TAG_BOOLEAN : + snprintf(valptr, sizeof(value) - (valptr - value), + "%d", attr->values[i].boolean); + break; + + case IPP_TAG_NOVALUE : + strlcat(valptr, "novalue", sizeof(value) - (valptr - value)); + break; + + case IPP_TAG_RANGE : + snprintf(valptr, sizeof(value) - (valptr - value), + "%d-%d", attr->values[i].range.lower, + attr->values[i].range.upper); + break; + + case IPP_TAG_RESOLUTION : + snprintf(valptr, sizeof(value) - (valptr - value), + "%dx%d%s", attr->values[i].resolution.xres, + attr->values[i].resolution.yres, + attr->values[i].resolution.units == IPP_RES_PER_INCH ? + "dpi" : "dpc"); + break; + + case IPP_TAG_URI : + if (strchr(attr->values[i].string.text, ':') != NULL) + { + httpSeparate(attr->values[i].string.text, method, username, + hostname, &port, resource); + + if (strcmp(method, "ipp") == 0 || + strcmp(method, "http") == 0) + { + /* + * Map localhost access to localhost and local port... + */ + + if (strcasecmp(hostname, server) == 0) + { + /* + * Make URI relative to the current server... + */ + + strlcpy(uri, resource, sizeof(uri)); + } + else + { + /* + * Rewrite URI with HTTP address... + */ + + if (username[0]) + snprintf(uri, sizeof(uri), "%s://%s@%s:%d%s", + ishttps ? "https" : "http", + username, hostname, port, resource); + else + snprintf(uri, sizeof(uri), "%s://%s:%d%s", + ishttps ? "https" : "http", + hostname, port, resource); + } + + strlcat(valptr, uri, sizeof(value) - (valptr - value)); + break; + } + } + + case IPP_TAG_STRING : + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + strlcat(valptr, attr->values[i].string.text, + sizeof(value) - (valptr - value)); + break; + + default : + break; /* anti-compiler-warning-code */ + } + } + + /* + * Add the element... + */ + + cgiSetArray(name, element, value); + } + + if (attr == NULL) + break; + } +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/ipp-var.h b/cgi-bin/ipp-var.h new file mode 100644 index 0000000000..0ce4163a99 --- /dev/null +++ b/cgi-bin/ipp-var.h @@ -0,0 +1,55 @@ +/* + * "$Id$" + * + * IPP variable definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include "cgi.h" + + +/* + * Definitions... + */ + +#define TEMPLATES ippGetTemplateDir() + + +/* + * Prototype... + */ + +extern char *ippGetTemplateDir(void); +extern void ippSetServerVersion(void); +extern void ippSetCGIVars(ipp_t *, const char *, const char *); + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/jobs.c b/cgi-bin/jobs.c new file mode 100644 index 0000000000..15f768b484 --- /dev/null +++ b/cgi-bin/jobs.c @@ -0,0 +1,259 @@ +/* + * "$Id$" + * + * Job status CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Main entry for CGI. + * do_job_op() - Do a job operation. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * Local functions... + */ + +static void do_job_op(http_t *http, cups_lang_t *language, ipp_op_t op); + + +/* + * 'main()' - Main entry for CGI. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + cups_lang_t *language; /* Language information */ + http_t *http; /* Connection to the server */ + const char *which_jobs; /* Which jobs to show */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + const char *op; /* Operation name */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + + /* + * Get the request language... + */ + + language = cupsLangDefault(); + + /* + * Connect to the HTTP server... + */ + + http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption()); + + /* + * Tell the client to expect HTML... + */ + + printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language)); + + cgiSetVariable("TITLE", "Jobs"); + + ippSetServerVersion(); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + if ((op = cgiGetVariable("OP")) != NULL) + { + /* + * Do the operation... + */ + + if (strcmp(op, "cancel-job") == 0) + do_job_op(http, language, IPP_CANCEL_JOB); + else if (strcmp(op, "hold-job") == 0) + do_job_op(http, language, IPP_HOLD_JOB); + else if (strcmp(op, "release-job") == 0) + do_job_op(http, language, IPP_RELEASE_JOB); + else if (strcmp(op, "restart-job") == 0) + do_job_op(http, language, IPP_RESTART_JOB); + else + { + /* + * Bad operation code... Display an error... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "job-op.tmpl", getenv("LANG")); + } + } + else + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + 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); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, + "ipp://localhost/jobs"); + + if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", + NULL, which_jobs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response, NULL, NULL); + ippDelete(response); + + cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG")); + } + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * 'do_job_op()' - Do a job operation. + */ + +static void +do_job_op(http_t *http, /* I - HTTP connection */ + cups_lang_t *language, /* I - Client's language */ + ipp_op_t op) /* I - Operation to perform */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + char uri[HTTP_MAX_URI]; /* Job URI */ + const char *job; /* Job ID */ + ipp_status_t status; /* Operation status... */ + + + if ((job = cgiGetVariable("JOB_ID")) != NULL) + snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%s", job); + else + { + cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + return; + } + + /* + * Build a job request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * job-uri or printer-uri (purge-jobs) + * requesting-user-name + */ + + request = ippNew(); + + request->request.op.operation_id = op; + request->request.op.request_id = 1; + + 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, "job-uri", + NULL, uri); + + if (getenv("REMOTE_USER") != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, getenv("REMOTE_USER")); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, "unknown"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) + { + status = response->request.status.status_code; + + ippDelete(response); + } + else + status = IPP_GONE; + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else if (op == IPP_CANCEL_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-cancel.tmpl", getenv("LANG")); + else if (op == IPP_HOLD_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-hold.tmpl", getenv("LANG")); + else if (op == IPP_RELEASE_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-release.tmpl", getenv("LANG")); + else if (op == IPP_RESTART_JOB) + cgiCopyTemplateLang(stdout, TEMPLATES, "job-restart.tmpl", getenv("LANG")); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/printers.c b/cgi-bin/printers.c new file mode 100644 index 0000000000..1bdaad10a5 --- /dev/null +++ b/cgi-bin/printers.c @@ -0,0 +1,360 @@ +/* + * "$Id$" + * + * Printer status CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * Contents: + * + * main() - Main entry for CGI. + */ + +/* + * Include necessary headers... + */ + +#include "ipp-var.h" + + +/* + * 'main()' - Main entry for CGI. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + cups_lang_t *language; /* Language information */ + char *printer; /* Printer name */ + http_t *http; /* Connection to the server */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP attribute */ + ipp_status_t status; /* Operation status... */ + char uri[HTTP_MAX_URI]; + /* Printer URI */ + const char *which_jobs; /* Which jobs to show */ + const char *op; /* Operation to perform, if any */ + + + /* + * Get any form variables... + */ + + cgiInitialize(); + op = cgiGetVariable("OP"); + + /* + * Get the request language... + */ + + language = cupsLangDefault(); + + /* + * Connect to the HTTP server... + */ + + http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption()); + + /* + * Tell the client to expect HTML... + */ + + printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language)); + + /* + * See if we need to show a list of printers or the status of a + * single printer... + */ + + ippSetServerVersion(); + + printer = argv[0]; + if (strcmp(printer, "/") == 0 || strstr(printer, "printers.cgi") != NULL) + { + printer = NULL; + cgiSetVariable("TITLE", cupsLangString(language, CUPS_MSG_PRINTER)); + } + else + cgiSetVariable("TITLE", printer); + + cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG")); + + if (op == NULL || strcasecmp(op, "print-test-page") != 0) + { + /* + * Get the default destination... + */ + + request = ippNew(); + request->request.op.operation_id = CUPS_GET_DEFAULT; + request->request.op.request_id = 1; + + 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); + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) + cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text); + + if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) + { + char method[HTTP_MAX_URI], + username[HTTP_MAX_URI], + hostname[HTTP_MAX_URI], + resource[HTTP_MAX_URI], + uri[HTTP_MAX_URI]; + int port; /* URI data */ + const char *server; /* Name of server */ + + + /* + * Map localhost access to localhost... + */ + + server = getenv("SERVER_NAME"); + + httpSeparate(attr->values[0].string.text, method, username, + hostname, &port, resource); + + if (strcasecmp(hostname, server) == 0 && + (strcmp(getenv("REMOTE_HOST"), "127.0.0.1") == 0 || + strcmp(getenv("REMOTE_HOST"), "localhost") == 0 || + strcmp(getenv("REMOTE_HOST"), server) == 0)) + strcpy(hostname, "localhost"); + + /* + * Rewrite URI with HTTP address... + */ + + snprintf(uri, sizeof(uri), "http://%s:%d%s", hostname, port, + resource); + + cgiSetVariable("DEFAULT_URI", uri); + } + + ippDelete(response); + } + + /* + * Get the printer info... + */ + + request = ippNew(); + + 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); + + if (printer == NULL) + { + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + } + else + { + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/printers/%s", getenv("SERVER_NAME"), + printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, + uri); + } + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response, NULL, NULL); + ippDelete(response); + } + + /* + * Write the report... + */ + + cgiCopyTemplateLang(stdout, TEMPLATES, "printers.tmpl", getenv("LANG")); + + /* + * Get jobs for the specified printer if a printer has been chosen... + */ + + if (printer != NULL) + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + 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); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s/printers/%s", getenv("SERVER_NAME"), + printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, + uri); + + if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", + NULL, which_jobs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + ippSetCGIVars(response, NULL, NULL); + ippDelete(response); + + cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG")); + } + } + } + else + { + /* + * Print a test page... + */ + + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer); + + /* + * Build an IPP_PRINT_JOB request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * requesting-user-name + * document-format + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_PRINT_JOB; + request->request.op.request_id = 1; + + 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); + + if (getenv("REMOTE_USER") != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, getenv("REMOTE_USER")); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, "root"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", + NULL, "Test Page"); + + ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/postscript"); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoFileRequest(http, request, uri + 15, + CUPS_DATADIR "/data/testprint.ps")) != NULL) + { + status = response->request.status.status_code; + ippSetCGIVars(response, NULL, NULL); + + ippDelete(response); + } + else + status = IPP_GONE; + + cgiSetVariable("PRINTER_NAME", printer); + + if (status > IPP_OK_CONFLICT) + { + cgiSetVariable("ERROR", ippErrorString(status)); + cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG")); + } + else + cgiCopyTemplateLang(stdout, TEMPLATES, "test-page.tmpl", getenv("LANG")); + } + + cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG")); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/template.c b/cgi-bin/template.c new file mode 100644 index 0000000000..598cc52352 --- /dev/null +++ b/cgi-bin/template.c @@ -0,0 +1,492 @@ +/* + * "$Id$" + * + * CGI template function. + * + * Copyright 1997-2002 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contents: + * + * cgiCopyTemplateFile() - Copy a template file and replace all the + * '{variable}' strings with the variable value. + * cgiCopyTemplateLang() - Copy a template file using a language... + * cgi_copy() - Copy the template file, substituting as needed... + * cgi_puts() - Put a string to the output file, quoting as + * needed... + */ + +#include "cgi.h" + + +/* + * Local functions... + */ + +static void cgi_copy(FILE *out, FILE *in, int element, char term); +static void cgi_puts(const char *s, FILE *out); + + +/* + * 'cgiCopyTemplateFile()' - Copy a template file and replace all the + * '{variable}' strings with the variable value. + */ + +void +cgiCopyTemplateFile(FILE *out, /* I - Output file */ + const char *tmpl) /* I - Template file to read */ +{ + FILE *in; /* Input file */ + + + /* + * Open the template file... + */ + + if ((in = fopen(tmpl, "r")) == NULL) + return; + + /* + * Parse the file to the end... + */ + + cgi_copy(out, in, 0, 0); + + /* + * Close the template file and return... + */ + + fclose(in); +} + + +/* + * 'cgiCopyTemplateLang()' - Copy a template file using a language... + */ + +void +cgiCopyTemplateLang(FILE *out, /* I - Output file */ + const char *directory, /* I - Directory */ + const char *tmpl, /* I - Base filename */ + const char *lang) /* I - Language */ +{ + int i; /* Looping var */ + char filename[1024], /* Filename */ + locale[16]; /* Locale name */ + FILE *in; /* Input file */ + + + /* + * Convert the language to a locale name... + */ + + if (lang != NULL) + { + for (i = 0; lang[i] && i < 15; i ++) + if (isalnum(lang[i])) + locale[i] = tolower(lang[i]); + else + locale[i] = '_'; + + locale[i] = '\0'; + } + else + locale[0] = '\0'; + + /* + * See if we have a template file for this language... + */ + + snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl); + if (access(filename, 0)) + { + locale[2] = '\0'; + + snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl); + if (access(filename, 0)) + snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl); + } + + /* + * Open the template file... + */ + + if ((in = fopen(filename, "r")) == NULL) + return; + + /* + * Parse the file to the end... + */ + + cgi_copy(out, in, 0, 0); + + /* + * Close the template file and return... + */ + + fclose(in); +} + + +/* + * 'cgi_copy()' - Copy the template file, substituting as needed... + */ + +static void +cgi_copy(FILE *out, /* I - Output file */ + FILE *in, /* I - Input file */ + int element, /* I - Element number (0 to N) */ + char term) /* I - Terminating character */ +{ + int ch; /* Character from file */ + char op; /* Operation */ + char name[255], /* Name of variable */ + *nameptr, /* Pointer into name */ + innername[255], /* Inner comparison name */ + *innerptr, /* Pointer into inner name */ + *s; /* String pointer */ + const char *value; /* Value of variable */ + const char *innerval; /* Inner value */ + const char *outptr; /* Output string pointer */ + char outval[1024], /* Formatted output string */ + compare[1024]; /* Comparison string */ + int result; /* Result of comparison */ + + + /* + * Parse the file to the end... + */ + + while ((ch = getc(in)) != EOF) + if (ch == term) + break; + else if (ch == '{') + { + /* + * Get a variable name... + */ + + for (s = name; (ch = getc(in)) != EOF;) + if (strchr("}]<>=! \t\n", ch)) + break; + else if (s > name && ch == '?') + break; + else if (s < (name + sizeof(name) - 1)) + *s++ = ch; + + *s = '\0'; + + if (s == name && isspace(ch)) + { + if (out) + { + putc('{', out); + putc(ch, out); + } + + continue; + } + + /* + * See if it has a value... + */ + + if (name[0] == '?') + { + /* + * Insert value only if it exists... + */ + + if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1])) + { + *nameptr++ = '\0'; + + if ((value = cgiGetArray(name + 1, atoi(nameptr) - 1)) != NULL) + outptr = value; + else + { + outval[0] = '\0'; + outptr = outval; + } + } + if ((value = cgiGetArray(name + 1, element)) != NULL) + outptr = value; + else + { + outval[0] = '\0'; + outptr = outval; + } + } + else if (name[0] == '#') + { + /* + * Insert count... + */ + + if (name[1]) + sprintf(outval, "%d", cgiGetSize(name + 1)); + else + sprintf(outval, "%d", element + 1); + + outptr = outval; + } + else if (name[0] == '[') + { + /* + * Loop for # of elements... + */ + + int i; /* Looping var */ + long pos; /* File position */ + int count; /* Number of elements */ + + + if (isdigit(name[1])) + count = atoi(name + 1); + else + count = cgiGetSize(name + 1); + + pos = ftell(in); + + if (count > 0) + { + for (i = 0; i < count; i ++) + { + fseek(in, pos, SEEK_SET); + cgi_copy(out, in, i, '}'); + } + } + else + cgi_copy(NULL, in, 0, '}'); + + continue; + } + else + { + /* + * Insert variable or variable name (if element is NULL)... + */ + + if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1])) + { + *nameptr++ = '\0'; + if ((value = cgiGetArray(name, atoi(nameptr) - 1)) == NULL) + { + snprintf(outval, sizeof(outval), "{%s}", name); + outptr = outval; + } + else + outptr = value; + } + else if ((value = cgiGetArray(name, element)) == NULL) + { + snprintf(outval, sizeof(outval), "{%s}", name); + outptr = outval; + } + else + outptr = value; + } + + /* + * See if the terminating character requires another test... + */ + + if (ch == '}') + { + /* + * End of substitution... + */ + + if (out) + cgi_puts(outptr, out); + + continue; + } + + /* + * OK, process one of the following checks: + * + * {name?exist:not-exist} Exists? + * {name=value?true:false} Equal + * {namevalue?true:false} Greater than + * {name!value?true:false} Not equal + */ + + if (ch == '?') + { + /* + * Test for existance... + */ + + result = cgiGetArray(name, element) != NULL && outval[0]; + } + else + { + /* + * Compare to a string... + */ + + op = ch; + + for (s = compare; (ch = getc(in)) != EOF;) + if (ch == '?') + break; + else if (s >= (compare + sizeof(compare) - 1)) + continue; + else if (ch == '#') + { + sprintf(s, "%d", element + 1); + s += strlen(s); + } + else if (ch == '{') + { + /* + * Grab the value of a variable... + */ + + innerptr = innername; + while ((ch = getc(in)) != EOF && ch != '}') + if (innerptr < (innername + sizeof(innername) - 1)) + *innerptr++ = ch; + *innerptr = '\0'; + + if (innername[0] == '#') + sprintf(s, "%d", cgiGetSize(innername + 1)); + else if ((innerptr = strrchr(innername, '-')) != NULL && + isdigit(innerptr[1])) + { + *innerptr++ = '\0'; + if ((innerval = cgiGetArray(innername, atoi(innerptr) - 1)) == NULL) + *s = '\0'; + else + strlcpy(s, innerval, sizeof(compare) - (s - compare)); + } + else if (innername[0] == '?') + { + if ((innerval = cgiGetArray(innername + 1, element)) == NULL) + *s = '\0'; + else + strlcpy(s, innerval, sizeof(compare) - (s - compare)); + } + else if ((innerval = cgiGetArray(innername, element)) == NULL) + snprintf(s, sizeof(s), "{%s}", innername); + else + strlcpy(s, innerval, sizeof(compare) - (s - compare)); + + s += strlen(s); + } + else if (ch == '\\') + *s++ = getc(in); + else + *s++ = ch; + + *s = '\0'; + + if (ch != '?') + return; + + /* + * Do the comparison... + */ + + switch (op) + { + case '<' : + result = strcasecmp(outptr, compare) < 0; + break; + case '>' : + result = strcasecmp(outptr, compare) > 0; + break; + case '=' : + result = strcasecmp(outptr, compare) == 0; + break; + case '!' : + result = strcasecmp(outptr, compare) != 0; + break; + default : + result = 1; + break; + } + } + + if (result) + { + /* + * Comparison true; output first part and ignore second... + */ + + cgi_copy(out, in, element, ':'); + cgi_copy(NULL, in, element, '}'); + } + else + { + /* + * Comparison false; ignore first part and output second... + */ + + cgi_copy(NULL, in, element, ':'); + cgi_copy(out, in, element, '}'); + } + } + else if (ch == '\\') /* Quoted char */ + { + if (out) + putc(getc(in), out); + else + getc(in); + } + else if (out) + putc(ch, out); + + /* + * Flush any pending output... + */ + + if (out) + fflush(out); +} + + +/* + * 'cgi_puts()' - Put a string to the output file, quoting as needed... + */ + +static void +cgi_puts(const char *s, + FILE *out) +{ + while (*s) + { + if (s[0] == '<') + fputs("<", out); + else if (s[0] == '>') + fputs(">", out); + else if (*s == '\"') + fputs(""", out); + else if (s[0] == '&') + fputs("&", out); + else + putc(*s, out); + + s ++; + } +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/var.c b/cgi-bin/var.c new file mode 100644 index 0000000000..0c291a26e9 --- /dev/null +++ b/cgi-bin/var.c @@ -0,0 +1,672 @@ +/* + * "$Id$" + * + * CGI form variable and array functions. + * + * Copyright 1997-2002 by Easy Software Products. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contents: + * + * cgiInitialize() - Initialize the CGI variable "database"... + * cgiCheckVariables() - Check for the presence of "required" variables. + * cgiGetArray() - Get an element from a form array... + * cgiGetSize() - Get the size of a form array value. + * cgiGetVariable() - Get a CGI variable from the database... + * cgiSetArray() - Set array element N to the specified string. + * cgiSetVariable() - Set a CGI variable in the database... + * cgi_add_variable() - Add a form variable. + * cgi_compare_variables() - Compare two variables. + * cgi_find_variable() - Find a variable... + * cgi_initialize_get() - Initialize form variables using the GET method. + * cgi_initialize_post() - Initialize variables using the POST method. + * cgi_initialize_string() - Initialize form variables from a string. + * cgi_sort_variables() - Sort all form variables for faster lookup. + */ + +/*#define DEBUG*/ +#include "cgi.h" +#include +#include + + +/* + * Data structure to hold all the CGI form variables and arrays... + */ + +typedef struct +{ + const char *name; /* Name of variable */ + int nvalues, /* Number of values */ + avalues; /* Number of values allocated */ + const char **values; /* Value(s) of variable */ +} var_t; + + +/* + * Local globals... + */ + +static int form_count = 0, /* Form variable count */ + form_alloc = 0; /* Number of variables allocated */ +static var_t *form_vars = NULL; /* Form variables */ + + +/* + * Local functions... + */ + +static void cgi_add_variable(const char *name, int element, + const char *value); +static int cgi_compare_variables(const var_t *v1, const var_t *v2); +static var_t *cgi_find_variable(const char *name); +static int cgi_initialize_get(void); +static int cgi_initialize_post(void); +static int cgi_initialize_string(const char *data); +static void cgi_sort_variables(void); + + +/* + * 'cgiInitialize()' - Initialize the CGI variable "database"... + */ + +int /* O - Non-zero if there was form data */ +cgiInitialize(void) +{ + char *method; /* Form posting method */ + + +#ifdef DEBUG + setbuf(stdout, NULL); + puts("Content-type: text/plain\n"); +#endif /* DEBUG */ + + method = getenv("REQUEST_METHOD"); + + if (method == NULL) + return (0); + + if (strcasecmp(method, "GET") == 0) + return (cgi_initialize_get()); + else if (strcasecmp(method, "POST") == 0) + return (cgi_initialize_post()); + else + return (0); +} + + +/* + * 'cgiCheckVariables()' - Check for the presence of "required" variables. + * + * Names may be separated by spaces and/or commas. + */ + +int /* O - 1 if all variables present, 0 otherwise */ +cgiCheckVariables(const char *names) /* I - Variables to look for */ +{ + char name[255], /* Current variable name */ + *s; /* Pointer in string */ + const char *val; /* Value of variable */ + int element; /* Array element number */ + + + if (names == NULL) + return (1); + + while (*names != '\0') + { + while (*names == ' ' || *names == ',') + names ++; + + for (s = name; *names != '\0' && *names != ' ' && *names != ','; s ++, names ++) + *s = *names; + + *s = 0; + if (name[0] == '\0') + break; + + if ((s = strrchr(name, '-')) != NULL) + { + *s = '\0'; + element = atoi(s + 1) - 1; + val = cgiGetArray(name, element); + } + else + val = cgiGetVariable(name); + + if (val == NULL) + return (0); + + if (*val == '\0') + return (0); /* Can't be blank, either! */ + } + + return (1); +} + + +/* + * 'cgiGetArray()' - Get an element from a form array... + */ + +const char * /* O - Element value or NULL */ +cgiGetArray(const char *name, /* I - Name of array variable */ + int element) /* I - Element number (0 to N) */ +{ + var_t *var; /* Pointer to variable */ + + + if ((var = cgi_find_variable(name)) == NULL) + return (NULL); + + if (var->nvalues == 1) + return (var->values[0]); + + if (element < 0 || element >= var->nvalues) + return (NULL); + + return (var->values[element]); +} + + +/* + * 'cgiGetSize()' - Get the size of a form array value. + */ + +int /* O - Number of elements */ +cgiGetSize(const char *name) /* I - Name of variable */ +{ + var_t *var; /* Pointer to variable */ + + + if ((var = cgi_find_variable(name)) == NULL) + return (0); + + return (var->nvalues); +} + + +/* + * 'cgiGetVariable()' - Get a CGI variable from the database... + * + * Returns NULL if the variable doesn't exist... If the variable is an + * array of values, returns the last element... + */ + +const char * /* O - Value of variable */ +cgiGetVariable(const char *name)/* I - Name of variable */ +{ + const var_t *var; /* Returned variable */ + + + var = cgi_find_variable(name); + +#ifdef DEBUG + if (var == NULL) + printf("cgiGetVariable(\"%s\") is returning NULL...\n", name); + else + printf("cgiGetVariable(\"%s\") is returning \"%s\"...\n", name, + var->values[var->nvalues - 1]); +#endif /* DEBUG */ + + return ((var == NULL) ? NULL : var->values[var->nvalues - 1]); +} + + +/* + * 'cgiSetArray()' - Set array element N to the specified string. + * + * If the variable array is smaller than (element + 1), the intervening + * elements are set to NULL. + */ + +void +cgiSetArray(const char *name, /* I - Name of variable */ + int element, /* I - Element number (0 to N) */ + const char *value) /* I - Value of variable */ +{ + int i; /* Looping var */ + var_t *var; /* Returned variable */ + + + if (name == NULL || value == NULL || element < 0) + return; + + if ((var = cgi_find_variable(name)) == NULL) + { + cgi_add_variable(name, element, value); + cgi_sort_variables(); + } + else + { + if (element >= var->avalues) + { + var->avalues = element + 16; + var->values = (const char **)realloc((void *)(var->values), + sizeof(char *) * var->avalues); + } + + if (element >= var->nvalues) + { + for (i = var->nvalues; i < element; i ++) + var->values[i] = NULL; + + var->nvalues = element + 1; + } + else if (var->values[element]) + free((char *)var->values[element]); + + var->values[element] = strdup(value); + } +} + + +/* + * 'cgiSetSize()' - Set the array size. + */ + +void +cgiSetSize(const char *name, /* I - Name of variable */ + int size) /* I - Number of elements (0 to N) */ +{ + int i; /* Looping var */ + var_t *var; /* Returned variable */ + + + if (name == NULL || size < 0) + return; + + if ((var = cgi_find_variable(name)) == NULL) + return; + + if (size >= var->avalues) + { + var->avalues = size + 16; + var->values = (const char **)realloc((void *)(var->values), + sizeof(char *) * var->avalues); + } + + if (size > var->nvalues) + { + for (i = var->nvalues; i < size; i ++) + var->values[i] = NULL; + } + else if (size < var->nvalues) + { + for (i = size; i < var->nvalues; i ++) + if (var->values[i]) + free((void *)(var->values[i])); + } + + var->nvalues = size; +} + + +/* + * 'cgiSetVariable()' - Set a CGI variable in the database... + * + * If the variable is an array, this truncates the array to a single element. + */ + +void +cgiSetVariable(const char *name, /* I - Name of variable */ + const char *value) /* I - Value of variable */ +{ + int i; /* Looping var */ + var_t *var; /* Returned variable */ + + + if (name == NULL || value == NULL) + return; + + if ((var = cgi_find_variable(name)) == NULL) + { + cgi_add_variable(name, 0, value); + cgi_sort_variables(); + } + else + { + for (i = 0; i < var->nvalues; i ++) + if (var->values[i]) + free((char *)var->values[i]); + + var->values[0] = strdup(value); + var->nvalues = 1; + } +} + + +/* + * 'cgi_add_variable()' - Add a form variable. + */ + +static void +cgi_add_variable(const char *name, /* I - Variable name */ + int element, /* I - Array element number */ + const char *value) /* I - Variable value */ +{ + var_t *var; /* New variable */ + + + if (name == NULL || value == NULL) + return; + +#ifdef DEBUG + printf("Adding variable \'%s\' with value \'%s\'...\n", name, value); +#endif /* DEBUG */ + + if (form_count >= form_alloc) + { + if (form_alloc == 0) + form_vars = malloc(sizeof(var_t) * 16); + else + form_vars = realloc(form_vars, (form_alloc + 16) * sizeof(var_t)); + + form_alloc += 16; + } + + var = form_vars + form_count; + var->name = strdup(name); + var->nvalues = element + 1; + var->avalues = element + 1; + var->values = calloc(element + 1, sizeof(char *)); + var->values[element] = strdup(value); + + form_count ++; +} + + +/* + * 'cgi_compare_variables()' - Compare two variables. + */ + +static int /* O - Result of comparison */ +cgi_compare_variables(const var_t *v1, /* I - First variable */ + const var_t *v2) /* I - Second variable */ +{ + return (strcasecmp(v1->name, v2->name)); +} + + +/* + * 'cgi_find_variable()' - Find a variable... + */ + +static var_t * /* O - Variable pointer or NULL */ +cgi_find_variable(const char *name) /* I - Name of variable */ +{ + var_t key; /* Search key */ + + + if (form_count < 1 || name == NULL) + return (NULL); + + key.name = name; + + return ((var_t *)bsearch(&key, form_vars, form_count, sizeof(var_t), + (int (*)(const void *, const void *))cgi_compare_variables)); +} + + +/* + * 'cgi_initialize_get()' - Initialize form variables using the GET method. + */ + +static int /* O - 1 if form data read */ +cgi_initialize_get(void) +{ + char *data; /* Pointer to form data string */ + + +#ifdef DEBUG + puts("Initializing variables using GET method..."); +#endif /* DEBUG */ + + /* + * Check to see if there is anything for us to read... + */ + + data = getenv("QUERY_STRING"); + if (data == NULL || strlen(data) == 0) + return (0); + + /* + * Parse it out and return... + */ + + return (cgi_initialize_string(data)); +} + + +/* + * 'cgi_initialize_post()' - Initialize variables using the POST method. + */ + +static int /* O - 1 if form data was read */ +cgi_initialize_post(void) +{ + char *content_length, /* Length of input data (string) */ + *data; /* Pointer to form data string */ + int length, /* Length of input data */ + nbytes, /* Number of bytes read this read() */ + tbytes, /* Total number of bytes read */ + status; /* Return status */ + + +#ifdef DEBUG + puts("Initializing variables using POST method..."); +#endif /* DEBUG */ + + /* + * Check to see if there is anything for us to read... + */ + + content_length = getenv("CONTENT_LENGTH"); + if (content_length == NULL || atoi(content_length) <= 0) + return (0); + + /* + * Get the length of the input stream and allocate a buffer for it... + */ + + length = atoi(content_length); + data = malloc(length + 1); + + if (data == NULL) + return (0); + + /* + * Read the data into the buffer... + */ + + for (tbytes = 0; tbytes < length; tbytes += nbytes) + if ((nbytes = read(0, data + tbytes, length - tbytes)) < 0) + if (errno != EAGAIN) + { + free(data); + return (0); + } + + data[length] = '\0'; + + /* + * Parse it out... + */ + + status = cgi_initialize_string(data); + + /* + * Free the data and return... + */ + + free(data); + + return (status); +} + + +/* + * 'cgi_initialize_string()' - Initialize form variables from a string. + */ + +static int +cgi_initialize_string(const char *data) /* I - Form data string */ +{ + int done; /* True if we're done reading a form variable */ + char *s, /* Pointer to current form string */ + ch, /* Temporary character */ + name[255], /* Name of form variable */ + value[65536]; /* Variable value... */ + + + /* + * Check input... + */ + + if (data == NULL) + return (0); + + /* + * Loop until we've read all the form data... + */ + + while (*data != '\0') + { + /* + * Get the variable name... + */ + + for (s = name; *data != '\0'; data ++) + if (*data == '=') + break; + else if (*data >= ' ' && s < (name + sizeof(name) - 1)) + *s++ = *data; + + *s = '\0'; + if (*data == '=') + data ++; + else + return (0); + + /* + * Read the variable value... + */ + + for (s = value, done = 0; !done && *data != '\0'; data ++) + switch (*data) + { + case '&' : /* End of data... */ + done = 1; + break; + + case '+' : /* Escaped space character */ + if (s < (value + sizeof(value) - 1)) + *s++ = ' '; + break; + + case '%' : /* Escaped control character */ + /* + * Read the hex code... + */ + + if (s < (value + sizeof(value) - 1)) + { + data ++; + ch = *data - '0'; + if (ch > 9) + ch -= 7; + *s = ch << 4; + + data ++; + ch = *data - '0'; + if (ch > 9) + ch -= 7; + *s++ |= ch; + } + else + data += 2; + break; + + default : /* Other characters come straight through */ + if (*data >= ' ' && s < (value + sizeof(value) - 1)) + *s++ = *data; + break; + } + + *s = '\0'; /* nul terminate the string */ + + /* + * Remove trailing whitespace... + */ + + if (s > value) + s --; + + while (s >= value && *s == ' ') + *s-- = '\0'; + + /* + * Add the string to the variable "database"... + */ + + if ((s = strrchr(name, '-')) != NULL && isdigit(s[1])) + { + *s++ = '\0'; + if (value[0]) + cgiSetArray(name, atoi(s) - 1, value); + } + else if (cgiGetVariable(name) != NULL) + cgiSetArray(name, cgiGetSize(name), value); + else + cgiSetVariable(name, value); + } + + return (1); +} + + +/* + * 'cgi_sort_variables()' - Sort all form variables for faster lookup. + */ + +static void +cgi_sort_variables(void) +{ +#ifdef DEBUG + int i; + + + puts("Sorting variables..."); +#endif /* DEBUG */ + + if (form_count < 2) + return; + + qsort(form_vars, form_count, sizeof(var_t), + (int (*)(const void *, const void *))cgi_compare_variables); + +#ifdef DEBUG + puts("Sorted variable list is:"); + for (i = 0; i < form_count; i ++) + printf("%d: %s (%d) = \"%s\" ...\n", i, form_vars[i].name, + form_vars[i].nvalues, form_vars[i].values[0]); +#endif /* DEBUG */ +} + + +/* + * End of "$Id$". + */ diff --git a/conf/Makefile b/conf/Makefile new file mode 100644 index 0000000000..22d98771f4 --- /dev/null +++ b/conf/Makefile @@ -0,0 +1,76 @@ +# +# "$Id$" +# +# Configuration file makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-2002 by Easy Software Products. +# +# 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 +# + +include ../Makedefs + +# +# Config files... +# + +KEEP = classes.conf client.conf cupsd.conf printers.conf +REPLACE = mime.convs mime.types + + +# +# Make everything... +# + +all: + + +# +# Clean all config and object files... +# + +clean: + + +# +# Install files... +# + +install: + $(INSTALL_DIR) $(SERVERROOT) + for file in $(KEEP); do \ + if test -r $(SERVERROOT)/$$file ; then \ + $(INSTALL_DATA) $$file $(SERVERROOT)/$$file.N ; \ + else \ + $(INSTALL_DATA) $$file $(SERVERROOT) ; \ + fi ; \ + done + for file in $(REPLACE); do \ + if test -r $(SERVERROOT)/$$file ; then \ + $(MV) $(SERVERROOT)/$$file $(SERVERROOT)/$$file.O ; \ + fi ; \ + $(INSTALL_DATA) $$file $(SERVERROOT) ; \ + done + -if test x$(PAMDIR) != x$(BUILDROOT); then \ + $(INSTALL_DIR) $(PAMDIR); \ + $(INSTALL_DATA) pam.conf $(PAMDIR)/cups; \ + fi + + +# +# End of "$Id$". +# diff --git a/conf/classes.conf b/conf/classes.conf new file mode 100644 index 0000000000..05526a605b --- /dev/null +++ b/conf/classes.conf @@ -0,0 +1,89 @@ +# +# "$Id: classes.conf 2010 2002-01-02 17:59:21Z mike $" +# +# Sample class configuration file for the Common UNIX Printing System +# (CUPS) scheduler. +# +# Copyright 1997-2002 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 +# + +######################################################################## +# # +# This is a sample class configuration file. This file is included # +# from the main configuration file (cups.conf) and lists all of the # +# printer classes known to the system. # +# # +######################################################################## + +# +# Each class starts with a definition. Class names +# can be up to 128 characters in length and are *not* case sensitive. +# +# One entry can appear in this file; if you don't +# define a default destination, the first printer or class becomes +# the default. +# + +# +# +# Info: the description for the class. +# + +#Info Acme LaserPrint 1000 Printers + +# +# Location: the location of the printer. +# + +#Location Room 101 in the activities building + +# +# State: sets the initial state of the class. Can be one of the +# following: +# +# Idle - Class is available to print new jobs. +# Stopped - Class is disabled but accepting new jobs. +# + +#State Idle + +# +# StateMessage: sets the printer-state-message attribute for the class. +# + +#StateMessage Class is idle. + +# +# Accepting: is the class accepting jobs? +# +#Accepting Yes +#Accepting No +# + +# +# Printer: adds a printer to the class. +# + +#Printer sample +#Printer sample@host2 +# + +# +# End of "$Id: classes.conf 2010 2002-01-02 17:59:21Z mike $". +# diff --git a/conf/client.conf b/conf/client.conf new file mode 100644 index 0000000000..244b5e1fea --- /dev/null +++ b/conf/client.conf @@ -0,0 +1,65 @@ +# +# "$Id: client.conf 2010 2002-01-02 17:59:21Z mike $" +# +# Sample client configuration file for the Common UNIX Printing System +# (CUPS). +# +# Copyright 1997-2002 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 +# + +######################################################################## +# # +# This is the CUPS client configuration file. This file is used to # +# define client-specific parameters, such as the default server or # +# default encryption settings. # +# # +######################################################################## + +# +# ServerName: the hostname of your server. By default CUPS will use the +# hostname of the system or the value of the CUPS_SERVER environment +# variable. +# + +#ServerName myhost.domain.com + +# +# Encryption: whether or not to use encryption; this depends on having +# the OpenSSL library linked into the CUPS library. +# +# Possible values: +# +# Always - Always use encryption (SSL) +# Never - Never use encryption +# Required - Use TLS encryption upgrade +# IfRequested - Use encryption if the server requests it +# +# The default value is "IfRequested". This parameter can also be set +# using the CUPS_ENCRYPTION environment variable. +# + +#Encryption Always +#Encryption Never +#Encryption Required +#Encryption IfRequested + + +# +# End of "$Id: client.conf 2010 2002-01-02 17:59:21Z mike $". +# diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in new file mode 100644 index 0000000000..46723336d5 --- /dev/null +++ b/conf/cupsd.conf.in @@ -0,0 +1,765 @@ +# +# "$Id$" +# +# Sample configuration file for the Common UNIX Printing System (CUPS) +# scheduler. +# +# Copyright 1997-2002 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 +# + +######################################################################## +# # +# This is the CUPS configuration file. If you are familiar with # +# Apache or any of the other popular web servers, we've followed the # +# same format. Any configuration variable used here has the same # +# semantics as the corresponding variable in Apache. If we need # +# different functionality then a different name is used to avoid # +# confusion... # +# # +######################################################################## + + +######## +######## Server Identity +######## + +# +# ServerName: the hostname of your server, as advertised to the world. +# By default CUPS will use the hostname of the system. +# +# To set the default server used by clients, see the client.conf file. +# + +#ServerName myhost.domain.com + +# +# ServerAdmin: the email address to send all complaints/problems to. +# By default CUPS will use "root@hostname". +# + +#ServerAdmin root@your.domain.com + + +######## +######## Server Options +######## + +# +# AccessLog: the access log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "@CUPS_LOGDIR@/access_log" +# +# You can also use the special name "syslog" to send the output to the +# syslog file or daemon. +# + +#AccessLog @CUPS_LOGDIR@/access_log + +# +# 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 secret +#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 "@CUPS_DATADIR@". +# + +#DataDir @CUPS_DATADIR@ + +# +# DefaultCharset: the default character set to use. If not specified, +# defaults to "utf-8". Note that this can also be overridden in +# HTML documents... +# + +#DefaultCharset utf-8 + +# +# DefaultLanguage: the default language if not specified by the browser. +# If not specified, the current locale is used. +# + +#DefaultLanguage en + +# +# DocumentRoot: the root directory for HTTP documents that are served. +# By default "@CUPS_DOCROOT@". +# + +#DocumentRoot @CUPS_DOCROOT@ + +# +# ErrorLog: the error log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "@CUPS_LOGDIR@/error_log" +# +# You can also use the special name "syslog" to send the output to the +# syslog file or daemon. +# + +#ErrorLog @CUPS_LOGDIR@/error_log + +# +# FontPath: the path to locate all font files (currently only for pstoraster) +# By default "@CUPS_FONTPATH@". +# + +#FontPath @CUPS_FONTPATH@ + +# +# LogLevel: controls the number of messages logged to the ErrorLog +# file and can be one of the following: +# +# debug2 Log everything. +# debug Log almost everything. +# info Log all requests and state changes. +# warn Log errors and warnings. +# error Log only errors. +# none Log nothing. +# + +LogLevel info + +# +# MaxLogSize: controls the maximum size of each log file before they are +# rotated. Defaults to 1048576 (1MB). Set to 0 to disable log rotating. +# + +#MaxLogSize 0 + +# +# PageLog: the page log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "@CUPS_LOGDIR@/page_log" +# +# You can also use the special name "syslog" to send the output to the +# syslog file or daemon. +# + +#PageLog @CUPS_LOGDIR@/page_log + +# +# PreserveJobHistory: whether or not to preserve the job history after a +# job is completed, cancelled, or stopped. Default is Yes. +# + +#PreserveJobHistory Yes + +# +# PreserveJobFiles: whether or not to preserve the job files after a +# job is completed, cancelled, or stopped. Default is No. +# + +#PreserveJobFiles No + +# +# AutoPurgeJobs: automatically purge jobs when not needed for quotas. +# Default is No. +# + +#AutoPurgeJobs No + +# +# MaxCopies: maximum number of copies that a user can request. Default is +# 100. +# + +#MaxCopies 100 + +# +# MaxJobs: maximum number of jobs to keep in memory (active and completed.) +# Default is 500; the value 0 is used for no limit. +# + +#MaxJobs 500 + +# +# Printcap: the name of the printcap file. Default is /etc/printcap. +# Leave blank to disable printcap file generation. +# + +#Printcap /etc/printcap + +# +# PrintcapFormat: the format of the printcap file, currently either +# BSD or Solaris. The default is "BSD". +# + +#PrintcapFormat BSD +#PrintcapFormat Solaris + +# +# PrintcapGUI: the name of the GUI options panel program to associate +# with print queues under IRIX. The default is "/usr/bin/glpoptions" +# from ESP Print Pro. +# +# This option is only used under IRIX; the options panel program +# must accept the "-d printer" and "-o options" options and write +# the selected printer options back to stdout on completion. +# + +#PrintcapGUI /usr/bin/glpoptions + +# +# RequestRoot: the directory where request files are stored. +# By default "@CUPS_REQUESTS@". +# + +#RequestRoot @CUPS_REQUESTS@ + +# +# RemoteRoot: the name of the user assigned to unauthenticated accesses +# from remote systems. By default "remroot". +# + +#RemoteRoot remroot + +# +# ServerBin: the root directory for the scheduler executables. +# By default "@CUPS_SERVERBIN@". +# + +#ServerBin @CUPS_SERVERBIN@ + +# +# ServerRoot: the root directory for the scheduler. +# By default "@CUPS_SERVERROOT@". +# + +#ServerRoot @CUPS_SERVERROOT@ + + +######## +######## Encryption Support +######## + +# +# ServerCertificate: the file to read containing the server's certificate. +# Defaults to "@CUPS_SERVERROOT@/ssl/server.crt". +# + +#ServerCertificate @CUPS_SERVERROOT@/ssl/server.crt + +# +# ServerKey: the file to read containing the server's key. +# Defaults to "@CUPS_SERVERROOT@/ssl/server.key". +# + +#ServerKey @CUPS_SERVERROOT@/ssl/server.key + + +######## +######## Filter Options +######## + +# +# User/Group: the user and group the server runs under. Normally this +# must be @CUPS_USER@ and @CUPS_GROUP@, however you can configure things for another +# user or group as needed. +# +# Note: the server must be run initially as root to support the +# default IPP port of 631. It changes users whenever an external +# program is run, or if the RunAsUser directive is specified... +# + +#User @CUPS_USER@ +#Group @CUPS_GROUP@ + +# +# RIPCache: the amount of memory that each RIP should use to cache +# bitmaps. The value can be any real number followed by "k" for +# kilobytes, "m" for megabytes, "g" for gigabytes, or "t" for tiles +# (1 tile = 256x256 pixels.) Defaults to "8m" (8 megabytes). +# + +#RIPCache 8m + +# +# TempDir: the directory to put temporary files in. This directory must be +# writable by the user defined above! Defaults to "@CUPS_REQUESTS@/tmp" or +# the value of the TMPDIR environment variable. +# + +#TempDir @CUPS_REQUESTS@/tmp + +# +# FilterLimit: sets the maximum cost of all job filters that can be run +# at the same time. A limit of 0 means no limit. A typical job may need +# a filter limit of at least 200; limits less than the minimum required +# by a job force a single job to be printed at any time. +# +# The default limit is 0 (unlimited). +# + +#FilterLimit 0 + +######## +######## Network Options +######## + +# +# Ports/addresses that we listen to. The default port 631 is reserved +# for the Internet Printing Protocol (IPP) and is what we use here. +# +# You can have multiple Port/Listen lines to listen to more than one +# port or address, or to restrict access: +# +# Port 80 +# Port 631 +# Listen hostname +# Listen hostname:80 +# Listen hostname:631 +# Listen 1.2.3.4 +# Listen 1.2.3.4:631 +# +# NOTE: Unfortunately, most web browsers don't support TLS or HTTP Upgrades +# for encryption. If you want to support web-based encryption you'll +# probably need to listen on port 443 (the "https" port...) +# + +#Port 80 +#Port 443 +Port 631 + +# +# HostNameLookups: whether or not to do lookups on IP addresses to get a +# fully-qualified hostname. This defaults to Off for performance reasons... +# + +#HostNameLookups On + +# +# KeepAlive: whether or not to support the Keep-Alive connection +# option. Default is on. +# + +#KeepAlive On + +# +# KeepAliveTimeout: the timeout before Keep-Alive connections are +# automatically closed. Default is 60 seconds. +# + +#KeepAliveTimeout 60 + +# +# MaxClients: controls the maximum number of simultaneous clients that +# will be handled. Defaults to 100. +# + +#MaxClients 100 + +# +# MaxRequestSize: controls the maximum size of HTTP requests and print files. +# Set to 0 to disable this feature (defaults to 0.) +# + +#MaxRequestSize 0 + +# +# Timeout: the timeout before requests time out. Default is 300 seconds. +# + +#Timeout 300 + + +######## +######## Browsing Options +######## + +# +# Browsing: whether or not to broadcast and/or listen for CUPS printer +# information on the network. Enabled by default. +# + +#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! +# +# Note: HP-UX does not properly handle broadcast unless you have a +# Class A, B, C, or D netmask (i.e. no CIDR support). +# +# Note: Using the "global" broadcast address (255.255.255.255) will +# activate a Linux demand-dial link with the default configuration. +# If you have a LAN as well as the dial-up link, use the LAN's +# broadcast address. +# +# The @LOCAL address broadcasts to all non point-to-point interfaces. +# For example, if you have a LAN and a dial-up link, @LOCAL would +# send printer updates to the LAN but not to the dial-up link. +# Similarly, the @IF(name) address sends to the named network +# interface, e.g. @IF(eth0) under Linux. Interfaces are refreshed +# automatically (no more than once every 60 seconds), so they can +# be used on dynamically-configured interfaces, e.g. PPP, 802.11, etc. +# + +#BrowseAddress x.y.z.255 +#BrowseAddress x.y.255.255 +#BrowseAddress x.255.255.255 +#BrowseAddress 255.255.255.255 +#BrowseAddress @LOCAL +#BrowseAddress @IF(name) + +# +# BrowseShortNames: whether or not to use "short" names for remote printers +# when possible (e.g. "printer" instead of "printer@host".) Enabled by +# default. +# + +#BrowseShortNames Yes + +# +# BrowseAllow: specifies an address mask to allow for incoming browser +# packets. The default is to allow packets from all addresses. +# +# BrowseDeny: specifies an address mask to deny for incoming browser +# packets. The default is to deny packets from no addresses. +# +# Both "BrowseAllow" and "BrowseDeny" accept the following notations for +# addresses: +# +# All +# None +# *.domain.com +# .domain.com +# host.domain.com +# nnn.* +# nnn.nnn.* +# nnn.nnn.nnn.* +# nnn.nnn.nnn.nnn +# nnn.nnn.nnn.nnn/mm +# nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm +# @LOCAL +# @IF(name) +# +# The hostname/domainname restrictions only work if you have turned hostname +# lookups on! +# + +#BrowseAllow address +#BrowseDeny address + +# +# BrowseInterval: the time between browsing updates in seconds. Default +# is 30 seconds. +# +# Note that browsing information is sent whenever a printer's state changes +# as well, so this represents the maximum time between updates. +# +# Set this to 0 to disable outgoing broadcasts so your local printers are +# not advertised but you can still see printers on other hosts. +# + +#BrowseInterval 30 + +# +# BrowseOrder: specifies the order of BrowseAllow/BrowseDeny comparisons. +# + +#BrowseOrder allow,deny +#BrowseOrder deny,allow + +# +# BrowsePoll: poll the named server(s) for printers +# + +#BrowsePoll address:port + +# +# BrowsePort: the port used for UDP broadcasts. By default this is +# the IPP port; if you change this you need to do it on all servers. +# Only one BrowsePort is recognized. +# + +#BrowsePort 631 + +# +# BrowseRelay: relay browser packets from one address/network to another. +# + +#BrowseRelay source-address destination-address +#BrowseRelay @IF(src) @IF(dst) + +# +# BrowseTimeout: the timeout for network printers - if we don't +# get an update within this time the printer will be removed +# from the printer list. This number definitely should not be +# less the BrowseInterval value for obvious reasons. Defaults +# to 300 seconds. +# + +#BrowseTimeout 300 + +# +# ImplicitClasses: whether or not to use implicit classes. +# +# Printer classes can be specified explicitly in the classes.conf +# file, implicitly based upon the printers available on the LAN, or +# both. +# +# When ImplicitClasses is On, printers on the LAN with the same name +# (e.g. Acme-LaserPrint-1000) will be put into a class with the same +# name. This allows you to setup multiple redundant queues on a LAN +# without a lot of administrative difficulties. If a user sends a +# job to Acme-LaserPrint-1000, the job will go to the first available +# queue. +# +# Enabled by default. +# + +#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 +######## + +# +# SystemGroup: the group name for "System" (printer administration) +# access. The default varies depending on the operating system, but +# will be "sys", "system", or "root" (checked for in that order.) +# + +#SystemGroup @CUPS_GROUP@ + +# +# RootCertDuration: How frequently the root certificate is regenerated. +# Defaults to 300 seconds. +# + +#RootCertDuration 300 + +# +# Access permissions for each directory served by the scheduler. +# Locations are relative to DocumentRoot... +# +# AuthType: the authorization to use: +# +# None - Perform no authentication +# Basic - Perform authentication using the HTTP Basic method. +# Digest - Perform authentication using the HTTP Digest method. +# +# (Note: local certificate authentication can be substituted by +# the client for Basic or Digest when connecting to the +# localhost interface) +# +# AuthClass: the authorization class; currently only "Anonymous", "User", +# "System" (valid user belonging to group SystemGroup), and "Group" +# (valid user belonging to the specified group) are supported. +# +# AuthGroupName: the group name for "Group" authorization. +# +# Order: the order of Allow/Deny processing. +# +# Allow: allows access from the specified hostname, domain, IP address, +# network, or interface. +# +# Deny: denies access from the specified hostname, domain, IP address, +# network, or interface. +# +# Both "Allow" and "Deny" accept the following notations for addresses: +# +# All +# None +# *.domain.com +# .domain.com +# host.domain.com +# nnn.* +# nnn.nnn.* +# nnn.nnn.nnn.* +# nnn.nnn.nnn.nnn +# nnn.nnn.nnn.nnn/mm +# nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm +# @LOCAL +# @IF(name) +# +# The host and domain address require that you enable hostname lookups +# with "HostNameLookups On" above. +# +# The @LOCAL address allows or denies from all non point-to-point +# interfaces. For example, if you have a LAN and a dial-up link, +# @LOCAL could allow connections from the LAN but not from the dial-up +# link. Similarly, the @IF(name) address allows or denies from the +# named network interface, e.g. @IF(eth0) under Linux. Interfaces are +# refreshed automatically (no more than once every 60 seconds), so +# they can be used on dynamically-configured interfaces, e.g. PPP, +# 802.11, etc. +# +# Encryption: whether or not to use encryption; this depends on having +# the OpenSSL library linked into the CUPS library and scheduler. +# +# Possible values: +# +# Always - Always use encryption (SSL) +# Never - Never use encryption +# Required - Use TLS encryption upgrade +# IfRequested - Use encryption if the server requests it +# +# The default value is "IfRequested". +# + + +Order Deny,Allow +Deny From All +Allow From 127.0.0.1 + + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# +# + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# +# + +# +# +# You may wish to limit access to job operations, either with Allow +# and Deny lines, or by requiring a username and password. +# +# + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# +# + +# +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# + +## Anonymous access (default) +#AuthType None + +## Require a username and password (Basic authentication) +#AuthType Basic +#AuthClass User + +## Require a username and password (Digest/MD5 authentication) +#AuthType Digest +#AuthClass User + +## Restrict access to local domain +#Order Deny,Allow +#Deny From All +#Allow From .mydomain.com +# + + +# +# You definitely will want to limit access to the administration functions. +# The default configuration requires a local connection from a user who +# is a member of the system group to do any admin tasks. You can change +# the group name using the SystemGroup directive. +# + +AuthType Basic +AuthClass System + +## Restrict access to local domain +Order Deny,Allow +Deny From All +Allow From 127.0.0.1 + +#Encryption Required + + +# +# End of "$Id$". +# diff --git a/conf/mime.convs b/conf/mime.convs new file mode 100644 index 0000000000..07ececd380 --- /dev/null +++ b/conf/mime.convs @@ -0,0 +1,116 @@ +# +# "$Id: mime.convs 2599 2002-08-09 00:00:55Z mike $" +# +# MIME converts file for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 by Easy Software Products. +# +# 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 +# + +######################################################################## +# +# Format of Lines: +# +# source/type destination/type cost filter +# +# General Notes: +# +# The "cost" field is used to find the least costly filters to run +# when converting a job file to a printable format. +# +# All filters *must* accept the standard command-line arguments +# (job-id, user, title, copies, options, [filename or stdin]) to +# work with CUPS. +# + +######################################################################## +# +# PostScript filters +# + +application/pdf application/postscript 33 pdftops +application/postscript application/vnd.cups-postscript 66 pstops +application/vnd.hp-HPGL application/postscript 66 hpgltops +application/x-cshell application/postscript 33 texttops +application/x-perl application/postscript 33 texttops +application/x-shell application/postscript 33 texttops +text/plain application/postscript 33 texttops +text/html application/postscript 33 texttops +image/gif application/vnd.cups-postscript 66 imagetops +image/png application/vnd.cups-postscript 66 imagetops +image/jpeg application/vnd.cups-postscript 66 imagetops +image/tiff application/vnd.cups-postscript 66 imagetops +image/x-photocd application/vnd.cups-postscript 66 imagetops +image/x-portable-anymap application/vnd.cups-postscript 66 imagetops +image/x-portable-bitmap application/vnd.cups-postscript 66 imagetops +image/x-portable-graymap application/vnd.cups-postscript 66 imagetops +image/x-portable-pixmap application/vnd.cups-postscript 66 imagetops +image/x-sgi-rgb application/vnd.cups-postscript 66 imagetops +image/x-xbitmap application/vnd.cups-postscript 66 imagetops +image/x-xpixmap application/vnd.cups-postscript 66 imagetops +image/x-xwindowdump application/vnd.cups-postscript 66 imagetops +image/x-sun-raster application/vnd.cups-postscript 66 imagetops + + +######################################################################## +# +# Form filter... +# +# This filter does not currently exist, but the file format is defined +# in the IDD and registered with the IANA for future use... +# + +#application/vnd.cups-form application/vnd.cups-postscript 33 formtops + +######################################################################## +# +# Raster filters... +# + +image/gif application/vnd.cups-raster 100 imagetoraster +image/png application/vnd.cups-raster 100 imagetoraster +image/jpeg application/vnd.cups-raster 100 imagetoraster +image/tiff application/vnd.cups-raster 100 imagetoraster +image/x-photocd application/vnd.cups-raster 100 imagetoraster +image/x-portable-anymap application/vnd.cups-raster 100 imagetoraster +image/x-portable-bitmap application/vnd.cups-raster 100 imagetoraster +image/x-portable-graymap application/vnd.cups-raster 100 imagetoraster +image/x-portable-pixmap application/vnd.cups-raster 100 imagetoraster +image/x-sgi-rgb application/vnd.cups-raster 100 imagetoraster +image/x-xbitmap application/vnd.cups-raster 100 imagetoraster +image/x-xpixmap application/vnd.cups-raster 100 imagetoraster +image/x-xwindowdump application/vnd.cups-raster 100 imagetoraster +image/x-sun-raster application/vnd.cups-raster 100 imagetoraster + +# pstoraster is now part of ESP Ghostscript... +#application/vnd.cups-postscript application/vnd.cups-raster 100 pstoraster + +######################################################################## +# +# Raw filter... +# +# Uncomment the following filter and the application/octet-stream type +# in mime.types to allow printing of arbitrary files without the -oraw +# option. +# + +#application/octet-stream application/vnd.cups-raw 0 - + +# +# End of "$Id: mime.convs 2599 2002-08-09 00:00:55Z mike $". +# diff --git a/conf/mime.types b/conf/mime.types new file mode 100644 index 0000000000..47d90939db --- /dev/null +++ b/conf/mime.types @@ -0,0 +1,158 @@ +# +# "$Id: mime.types 2982 2002-11-24 22:32:01Z mike $" +# +# MIME types file for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 by Easy Software Products. +# +# 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 +# + +######################################################################## +# +# Format of Lines: +# +# super/type rules +# +# "rules" can be any combination of: +# +# ( expr ) Parenthesis for expression grouping +# + Logical AND +# , or whitespace Logical OR +# ! Logical NOT +# match("pattern") Pattern match on filename +# extension Pattern match on "*.extension" +# ascii(offset,length) True if bytes are valid printable ASCII +# (CR, NL, TAB, BS, 32-126) +# printable(offset,length) True if bytes are printable 8-bit chars +# (CR, NL, TAB, BS, 32-126, 128-254) +# string(offset,"string") True if bytes are identical to string +# char(offset,value) True if byte is identical +# short(offset,value) True if 16-bit integer is identical +# int(offset,value) True if 32-bit integer is identical +# locale("string") True if current locale matches string +# contains(offset,range,"string") True if the range contains the string +# +# General Notes: +# +# MIME type names are case-insensitive. Internally they are converted +# to lowercase. Multiple occurrences of a type will cause the provided +# rules to be appended to the existing definition. Type names are sorted +# in ascending order, so if two types use the same rules to resolve a type +# (e.g. doc extension for two types), the returned type will be the first +# type in the sorted list. +# +# The "printable" rule differs from the "ascii" rule in that it also +# accepts 8-bit characters in the range 128-255. +# +# String constants must be surrounded by "" if they contain whitespace. +# To insert binary data into a string, use the notation. +# + +######################################################################## +# +# Application-generated files... +# + +application/msword doc string(0,) +application/pdf pdf string(0,%PDF) +application/postscript ai eps ps string(0,%!) string(0,<04>%!) +application/vnd.hp-HPGL hpgl string(0,<1B>&)\ + string(0,<1B>E<1B>%0B) \ + string(0,<1B>%-1B) string(0,<201B>)\ + string(0,BP;) string(0,IN;) string(0,DF;) \ + string(0,BPINPS;) \ + (contains(0,128,<1B>%-12345X) + \ + (contains(0,1024,"LANGUAGE=HPGL") \ + contains(0,1024,"LANGUAGE = HPGL"))) + +######################################################################## +# +# Image files... +# + +image/gif gif string(0,GIF87a) string(0,GIF89a) +image/png png string(0,<89>PNG) +image/jpeg jpeg jpg jpe string(0,) &&\ + (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\ + char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\ + char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\ + char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef)) +image/tiff tiff tif string(0,MM) string(0,II) +image/x-photocd pcd string(2048,PCD_IPI) +image/x-portable-anymap pnm +image/x-portable-bitmap pbm string(0,P1) string(0,P4) +image/x-portable-graymap pgm string(0,P2) string(0,P5) +image/x-portable-pixmap ppm string(0,P3) string(0,P6) +image/x-sgi-rgb rgb sgi bw icon short(0,474) +image/x-xbitmap xbm +image/x-xpixmap xpm ascii(0,1024) + string(3,"XPM") +image/x-xwindowdump xwd string(4,<00000007>) +image/x-sun-raster ras string(0,<59a66a95>) + +#image/fpx fpx +image/x-alias pix short(8,8) short(8,24) +image/x-bitmap bmp string(0,BM) && !printable(2,14) + +######################################################################## +# +# Text files... +# + +text/html html htm printable(0,1024) +\ + (string(0,"") string(0,"") +application/vnd.cups-postscript contains(0,128,<1B>%-12345X) + \ + (contains(0,1024,"LANGUAGE=POSTSCRIPT") \ + contains(0,1024,"LANGUAGE = Postscript") \ + contains(0,1024,"LANGUAGE = POSTSCRIPT")) +application/vnd.cups-raster string(0,"RaSt") string(0,"tSaR") +application/vnd.cups-raw (string(0,<1B>E) + !string(2,<1B>%0B)) \ + string(0,<1B>@) \ + (contains(0,128,<1B>%-12345X) + \ + (contains(0,1024,"LANGUAGE=PCL") \ + contains(0,1024,"LANGUAGE = PCL"))) + +######################################################################## +# +# Raw print file support... +# +# Uncomment the following type and the application/octet-stream +# filter line in mime.convs to allow raw file printing without the +# -oraw option. +# + +#application/octet-stream + +# +# End of "$Id: mime.types 2982 2002-11-24 22:32:01Z mike $". +# diff --git a/conf/pam.conf.in b/conf/pam.conf.in new file mode 100644 index 0000000000..3ddcdd0d35 --- /dev/null +++ b/conf/pam.conf.in @@ -0,0 +1,2 @@ +auth required @PAMMOD@ nullok shadow +account required @PAMMOD@ diff --git a/conf/pam.irix b/conf/pam.irix new file mode 100644 index 0000000000..476383acb5 --- /dev/null +++ b/conf/pam.irix @@ -0,0 +1,3 @@ +#%PAM-1.0 +auth required pam_unix.so shadow nodelay nullok +account required pam_unix.so diff --git a/conf/printcap b/conf/printcap new file mode 100644 index 0000000000..230c3017d6 --- /dev/null +++ b/conf/printcap @@ -0,0 +1,2 @@ +# This is a dummy printcap file that is automatically generated by the +# CUPS software for old applications that rely on it. diff --git a/conf/printers.conf b/conf/printers.conf new file mode 100644 index 0000000000..c690675698 --- /dev/null +++ b/conf/printers.conf @@ -0,0 +1,96 @@ +# +# "$Id: printers.conf 2010 2002-01-02 17:59:21Z mike $" +# +# Sample printer configuration file for the Common UNIX Printing System +# (CUPS) scheduler. +# +# Copyright 1997-2002 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 +# + +######################################################################## +# # +# This is a sample printer configuration file. This file is included # +# from the main configuration file (cups.conf) and lists all of the # +# printers known to the system. # +# # +######################################################################## + +# +# Each printer starts with a definition. Printer names +# can be up to 128 characters in length and are *not* case sensitive. +# +# One entry can appear in this file; if you don't +# define a default destination, the first printer or class becomes the +# default. +# + +# +# +# Info: the description for the printer. +# + +#Info Acme LaserPrint 1000 + +# +# Location: the location of the printer. +# + +#Location Room 101 in the activities building + +# +# DeviceURI: the device URI for this printer. +# + +#DeviceURI parallel:/dev/plp +#DeviceURI serial:/dev/ttyd1?baud=38400+size=8+parity=none+flow=soft +#DeviceURI scsi:/dev/scsi/sc1d6l0 +#DeviceURI socket://hostname:port +#DeviceURI tftp://hostname/path +#DeviceURI ftp://hostname/path +#DeviceURI http://hostname[:port]/path +#DeviceURI ipp://hostname/path +#DeviceURI smb://hostname/printer + +# +# State: sets the initial state of the printer. Can be one of the +# following: +# +# Idle - Printer is available to print new jobs. +# Stopped - Printer is disabled but accepting new jobs. +# + +#State Idle + +# +# StateMessage: sets the printer-state-message attribute for the printer. +# + +#StateMessage Printer is idle. + +# +# Accepting: is the printer accepting jobs? +# +#Accepting Yes +#Accepting No + +# + +# +# End of "$Id: printers.conf 2010 2002-01-02 17:59:21Z mike $". +# diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 new file mode 100644 index 0000000000..387a8c6cb2 --- /dev/null +++ b/config-scripts/cups-common.m4 @@ -0,0 +1,174 @@ +dnl +dnl "$Id: cups-common.m4 2893 2002-10-15 13:59:06Z mike $" +dnl +dnl Common configuration stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +dnl We need at least autoconf 2.50... +AC_PREREQ(2.50) + +dnl Set the name of the config header file... +AC_CONFIG_HEADER(config.h) + +dnl Default compiler flags... +CFLAGS="${CFLAGS:=}" +CPPFLAGS="${CPPFLAGS:=}" +CXXFLAGS="${CXXFLAGS:=}" +LDFLAGS="${LDFLAGS:=}" + +dnl Checks for programs... +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CXX +AC_PROG_CPP +AC_PROG_INSTALL +if test "$INSTALL" = "$ac_install_sh"; then + # Use full path to install-sh script... + INSTALL="`pwd`/install-sh -c" +fi +AC_PROG_RANLIB +AC_PATH_PROG(AR,ar) +AC_PATH_PROG(HTMLDOC,htmldoc) +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(RM,rm) +AC_PATH_PROG(SED,sed) +AC_PATH_PROG(STRIP,strip) + +dnl Architecture checks... +AC_C_BIGENDIAN + +dnl Check for libraries... +AC_SEARCH_LIBS(crypt, crypt) +AC_SEARCH_LIBS(getspent, sec gen) + +LIBMALLOC="" +AC_ARG_ENABLE(mallinfo, [ --enable-mallinfo turn on malloc debug information, default=no]) + +if test x$enable_mallinfo = xyes; then + 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 +fi + +AC_SUBST(LIBMALLOC) + +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(string.h,AC_DEFINE(HAVE_STRING_H)) +AC_CHECK_HEADER(strings.h,AC_DEFINE(HAVE_STRINGS_H)) +AC_CHECK_HEADER(bstring.h,AC_DEFINE(HAVE_BSTRING_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 strcasecmp strncasecmp strlcat strlcpy) +if test "$uname" = "HP-UX" -a "$uversion" = "1020"; then + echo Forcing snprintf emulation for HP-UX. +else + AC_CHECK_FUNCS(snprintf 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 mkstemp and mkstemps functions. +AC_CHECK_FUNCS(mkstemp mkstemps) + +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 See if the tm structure has the tm_gmtoff member... +AC_MSG_CHECKING(for tm_gmtoff member in tm structure) +AC_TRY_COMPILE([#include ],[struct tm t; + int o = t.tm_gmtoff;], + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_TM_GMTOFF), + AC_MSG_RESULT(no)) + +dnl Flags for "ar" command... +case $uname in + Darwin* | *BSD*) + ARFLAGS="-rcv" + ;; + *) + ARFLAGS="crvs" + ;; +esac + +AC_SUBST(ARFLAGS) + +dnl Libraries for the backends... +case $uname in + Darwin*) + BACKLIBS="-framework CoreFoundation -framework IOKit" + ;; + *) + BACKLIBS="" + ;; +esac + +AC_SUBST(BACKLIBS) + +dnl +dnl End of "$Id: cups-common.m4 2893 2002-10-15 13:59:06Z mike $". +dnl diff --git a/config-scripts/cups-compiler.m4 b/config-scripts/cups-compiler.m4 new file mode 100644 index 0000000000..fe43b33c9f --- /dev/null +++ b/config-scripts/cups-compiler.m4 @@ -0,0 +1,185 @@ +dnl +dnl "$Id: cups-compiler.m4 2966 2002-11-13 19:12:18Z mike $" +dnl +dnl Common configuration stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl +dnl Clear the debugging and non-shared library options unless the user asks +dnl for them... + +OPTIM="" +AC_SUBST(OPTIM) + +AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging, default=no], + [if test x$enable_debug = xyes; then + OPTIM="-g" + fi]) + +AC_ARG_WITH(optim, [ --with-optim="flags" set optimization flags ]) + +dnl Update compiler options... +CXXLIBS="" +AC_SUBST(CXXLIBS) + +if test -n "$GCC"; then + # Starting with GCC 3.0, you must link C++ programs against either + # libstdc++ (shared by default), or libsupc++ (always static). If + # you care about binary portability between Linux distributions, + # you need to either 1) build your own GCC with static C++ libraries + # or 2) link using gcc and libsupc++. We choose the latter since + # CUPS doesn't (currently) use any of the stdc++ library. + # + # Also, GCC 3.0.x still has problems compiling some code. You may + # or may not have success with it. USE 3.0.x WITH EXTREME CAUTION! + # + # Previous versions of GCC do not have the reliance on the stdc++ + # or g++ libraries, so the extra supc++ library is not needed. + + AC_MSG_CHECKING(if libsupc++ is required) + + SUPC="`$CXX -print-file-name=libsupc++.a 2>/dev/null`" + case "$SUPC" in + libsupc++.a*) + # Library not found, so this is and older GCC... + AC_MSG_RESULT(no) + ;; + *) + # This is gcc 3.x, and it knows of libsupc++, so we need it + CXXLIBS="-lsupc++" + AC_MSG_RESULT(yes) + ;; + esac + + CXX="$CC" + + if test -z "$OPTIM"; then + if test "x$with_optim" = x; then + if test $uname = HP-UX; then + # GCC under HP-UX has bugs with -O2 + OPTIM="-O1" + else + OPTIM="-O2" + fi + else + OPTIM="$with_optim $OPTIM" + fi + fi + + if test $PICFLAG = 1 -a $uname != AIX; then + OPTIM="-fPIC $OPTIM" + fi + + if test "x$with_optim" = x; then + OPTIM="-Wall $OPTIM" + fi +else + case $uname in + AIX*) + if test -z "$OPTIM"; then + if test "x$with_optim" = x; then + OPTIM="-O2 -qmaxmem=6000" + else + OPTIM="$with_optim $OPTIM" + fi + fi + ;; + HP-UX*) + if test -z "$OPTIM"; then + if test "x$with_optim" = x; then + OPTIM="+O2" + else + OPTIM="$with_optim $OPTIM" + fi + fi + + CFLAGS="-Ae $CFLAGS" + + if test "x$with_optim" = x; then + OPTIM="+DAportable $OPTIM" + fi + + if test $PICFLAG = 1; then + OPTIM="+z $OPTIM" + fi + ;; + IRIX*) + if test -z "$OPTIM"; then + if test "x$with_optim" = x; then + OPTIM="-O2" + else + OPTIM="$with_optim $OPTIM" + fi + fi + + if test $uversion -ge 62 -a "x$with_optim" = x; then + OPTIM="$OPTIM -n32 -mips3" + fi + + if test "x$with_optim" = x; then + OPTIM="-fullwarn $OPTIM" + fi + ;; + SunOS*) + # Solaris + if test -z "$OPTIM"; then + if test "x$with_optim" = x; then + OPTIM="-xO4" + else + OPTIM="$with_optim $OPTIM" + fi + fi + + if test "x$with_optim" = x; then + OPTIM="$OPTIM -xarch=generic" + fi + + if test $PICFLAG = 1; then + OPTIM="-KPIC $OPTIM" + fi + ;; + UNIX_SVR*) + # UnixWare + if test -z "$OPTIM"; then + if test "x$with_optim" = x; then + OPTIM="-O" + else + OPTIM="$with_optim $OPTIM" + fi + fi + + 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-bugs@cups.org with uname and compiler options needed" + echo "for your platform, or set the CFLAGS and CXXFLAGS" + echo "environment variable before running configure." + ;; + esac +fi + +dnl +dnl End of "$Id: cups-compiler.m4 2966 2002-11-13 19:12:18Z mike $". +dnl diff --git a/config-scripts/cups-directories.m4 b/config-scripts/cups-directories.m4 new file mode 100644 index 0000000000..fdc0278eef --- /dev/null +++ b/config-scripts/cups-directories.m4 @@ -0,0 +1,242 @@ +dnl +dnl "$Id: cups-directories.m4 2914 2002-10-17 17:05:39Z mike $" +dnl +dnl Directory stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +AC_PREFIX_DEFAULT(/) + +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="") +AC_ARG_WITH(rcdir, [ --with-rcdir set path for rc scripts],rcdir="$withval",rcdir="") + +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 "$libdir" = "\${exec_prefix}/lib"; then + libdir="$exec_prefix/lib" +fi + +if test "$uname" = "IRIX" -a $uversion -ge 62; then + libdir="$exec_prefix/lib32" +fi + +dnl Fix "fontpath" variable... +if test "x$fontpath" = "x"; then + fontpath="$datadir/cups/fonts" +fi + +dnl Setup init.d locations... +if test x$rcdir = x; then + case "$uname" in + FreeBSD* | OpenBSD*) + # FreeBSD and OpenBSD + INITDIR="" + INITDDIR="" + ;; + + NetBSD*) + # NetBSD + INITDIR="" + INITDDIR="/etc/rc.d" + ;; + + Darwin*) + # Darwin and MacOS X... + INITDIR="" + INITDDIR="/System/Library/StartupItems/PrintingServices" + ;; + + 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 +else + INITDIR="" + INITDDIR="$rcdir" +fi + +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 + *BSD* | Darwin*) + # *BSD and Darwin (MacOS X) + 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="$libdir/cups" + AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$libdir/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* | *BSD* | Darwin*) + 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... +CUPS_FONTPATH="$fontpath" +AC_SUBST(CUPS_FONTPATH) +AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$fontpath") + +dnl +dnl End of "$Id: cups-directories.m4 2914 2002-10-17 17:05:39Z mike $". +dnl diff --git a/config-scripts/cups-image.m4 b/config-scripts/cups-image.m4 new file mode 100644 index 0000000000..8c2d6a9486 --- /dev/null +++ b/config-scripts/cups-image.m4 @@ -0,0 +1,82 @@ +dnl +dnl "$Id: cups-image.m4 2491 2002-06-06 19:39:37Z mike $" +dnl +dnl Image library stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +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_HEADER(jpeglib.h, + AC_CHECK_LIB(jpeg, jpeg_destroy_decompress, + AC_DEFINE(HAVE_LIBJPEG) + LIBJPEG="-ljpeg" + LIBS="$LIBS -ljpeg")) + +AC_CHECK_HEADER(zlib.h, + 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_HEADER(png.h, + AC_CHECK_LIB(png, png_set_tRNS_to_alpha, + AC_DEFINE(HAVE_LIBPNG) + LIBPNG="-lpng -lm")) + +AC_CHECK_HEADER(tiff.h, + AC_CHECK_LIB(tiff, TIFFReadScanline, + AC_DEFINE(HAVE_LIBTIFF) + LIBTIFF="-ltiff")) + +dnl Restore original LIBS settings... +LIBS="$SAVELIBS" + +EXPORT_LIBJPEG="$LIBJPEG" +EXPORT_LIBPNG="$LIBPNG" +EXPORT_LIBTIFF="$LIBTIFF" +EXPORT_LIBZ="$LIBZ" + +AC_SUBST(EXPORT_LIBJPEG) +AC_SUBST(EXPORT_LIBPNG) +AC_SUBST(EXPORT_LIBTIFF) +AC_SUBST(EXPORT_LIBZ) + +AC_CHECK_HEADER(stdlib.h,AC_DEFINE(HAVE_STDLIB_H)) + +dnl +dnl End of "$Id: cups-image.m4 2491 2002-06-06 19:39:37Z mike $". +dnl diff --git a/config-scripts/cups-libtool.m4 b/config-scripts/cups-libtool.m4 new file mode 100644 index 0000000000..a9cc379677 --- /dev/null +++ b/config-scripts/cups-libtool.m4 @@ -0,0 +1,49 @@ +dnl +dnl "$Id: cups-libtool.m4 2476 2002-06-04 20:58:55Z mike $" +dnl +dnl Libtool stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +AC_ARG_ENABLE(libtool_unsupported, [ --enable-libtool-unsupported=LIBTOOL_PATH + turn on building with libtool (UNSUPPORTED!), default=no], + [if 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]) + +AC_SUBST(LIBTOOL) + +if test x$LIBTOOL != x; then + LIBCUPS="libcups.la" + LIBCUPSIMAGE="libcupsimage.la" + LINKCUPS="../cups/\$(LIBCUPS)" + LINKCUPSIMAGE="../filter/\$(LIBCUPSIMAGE)" + DSO="\$(CC)" +fi + +dnl +dnl End of "$Id: cups-libtool.m4 2476 2002-06-04 20:58:55Z mike $". +dnl diff --git a/config-scripts/cups-manpages.m4 b/config-scripts/cups-manpages.m4 new file mode 100644 index 0000000000..9253d13056 --- /dev/null +++ b/config-scripts/cups-manpages.m4 @@ -0,0 +1,104 @@ +dnl +dnl "$Id: cups-manpages.m4 2013 2002-01-02 18:50:43Z mike $" +dnl +dnl Manpage stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +dnl Fix "mandir" variable... +if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/"; then + case "$uname" in + Darwin* | Linux* | *BSD* | AIX*) + # Darwin, MacOS X, Linux, *BSD, and AIX + mandir="/usr/share/man" + AMANDIR="/usr/share/man" + PMANDIR="/usr/share/man" + ;; + IRIX*) + # SGI IRIX + mandir="/usr/share/catman/u_man" + AMANDIR="/usr/share/catman/a_man" + PMANDIR="/usr/share/catman/p_man" + ;; + *) + # All others + mandir="/usr/man" + AMANDIR="/usr/man" + PMANDIR="/usr/man" + ;; + esac +else + AMANDIR="$mandir" + PMANDIR="$mandir" +fi + +AC_SUBST(AMANDIR) +AC_SUBST(PMANDIR) + +dnl Setup manpage extensions... +case "$uname" in + *BSD* | Darwin*) + # *BSD + CAT1EXT=0 + CAT3EXT=0 + CAT5EXT=0 + CAT8EXT=0 + MAN8EXT=8 + MAN8DIR=8 + ;; + IRIX*) + # SGI IRIX + CAT1EXT=z + CAT3EXT=z + CAT5EXT=z + CAT8EXT=z + MAN8EXT=1m + MAN8DIR=1 + ;; + SunOS* | HP-UX*) + # Solaris and HP-UX + CAT1EXT=1 + CAT3EXT=3 + CAT5EXT=5 + CAT8EXT=1m + MAN8EXT=1m + MAN8DIR=1m + ;; + *) + # All others + CAT1EXT=1 + CAT3EXT=3 + CAT5EXT=5 + CAT8EXT=8 + MAN8EXT=8 + MAN8DIR=8 + ;; +esac + +AC_SUBST(CAT1EXT) +AC_SUBST(CAT3EXT) +AC_SUBST(CAT5EXT) +AC_SUBST(CAT8EXT) +AC_SUBST(MAN8EXT) +AC_SUBST(MAN8DIR) + +dnl +dnl End of "$Id: cups-manpages.m4 2013 2002-01-02 18:50:43Z mike $". +dnl diff --git a/config-scripts/cups-network.m4 b/config-scripts/cups-network.m4 new file mode 100644 index 0000000000..dcd86a8e21 --- /dev/null +++ b/config-scripts/cups-network.m4 @@ -0,0 +1,41 @@ +dnl +dnl "$Id: cups-network.m4 2309 2002-03-28 22:13:20Z mike $" +dnl +dnl Networking stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +NETLIBS="" + +if test "$uname" != "IRIX"; then + AC_CHECK_LIB(socket,socket,NETLIBS="-lsocket") + AC_CHECK_LIB(nsl,gethostbyaddr,NETLIBS="$NETLIBS -lnsl") +fi + +AC_CHECK_FUNCS(rresvport getifaddrs) + +AC_CHECK_MEMBER(struct sockaddr.sa_len,,,[#include ]) +AC_CHECK_HEADER(sys/sockio.h,AC_DEFINE(HAVE_SYS_SOCKIO_H)) + +AC_SUBST(NETLIBS) + +dnl +dnl End of "$Id: cups-network.m4 2309 2002-03-28 22:13:20Z mike $". +dnl diff --git a/config-scripts/cups-openslp.m4 b/config-scripts/cups-openslp.m4 new file mode 100644 index 0000000000..8126e59235 --- /dev/null +++ b/config-scripts/cups-openslp.m4 @@ -0,0 +1,48 @@ +dnl +dnl "$Id: cups-openslp.m4 2476 2002-06-04 20:58:55Z mike $" +dnl +dnl OpenSLP configuration stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +AC_ARG_ENABLE(slp, [ --enable-slp turn on SLP support, default=yes]) +AC_ARG_WITH(openslp-libs, [ --with-openslp-libs set directory for OpenSLP library], + LDFLAGS="-L$withval $LDFLAGS" + DSOFLAGS="-L$withval $DSOFLAGS",) +AC_ARG_WITH(openslp-includes, [ --with-openslp-includes set directory for OpenSLP includes], + CFLAGS="-I$withval $CFLAGS" + CXXFLAGS="-I$withval $CXXFLAGS" + CPPFLAGS="-I$withval $CPPFLAGS",) + +LIBSLP="" + +if test x$enable_slp != xno; then + AC_CHECK_HEADER(slp.h, + AC_CHECK_LIB(slp, SLPOpen, + AC_DEFINE(HAVE_LIBSLP) + LIBSLP="-lslp")) +fi + +AC_SUBST(LIBSLP) + + +dnl +dnl End of "$Id: cups-openslp.m4 2476 2002-06-04 20:58:55Z mike $". +dnl diff --git a/config-scripts/cups-openssl.m4 b/config-scripts/cups-openssl.m4 new file mode 100644 index 0000000000..58e382400b --- /dev/null +++ b/config-scripts/cups-openssl.m4 @@ -0,0 +1,74 @@ +dnl +dnl "$Id: cups-openssl.m4 2491 2002-06-06 19:39:37Z mike $" +dnl +dnl OpenSSL stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +AC_ARG_ENABLE(ssl, [ --enable-ssl turn on SSL/TLS support, default=yes]) +AC_ARG_WITH(openssl-libs, [ --with-openssl-libs set directory for OpenSSL library], + LDFLAGS="-L$withval $LDFLAGS" + DSOFLAGS="-L$withval $DSOFLAGS",) +AC_ARG_WITH(openssl-includes, [ --with-openssl-includes set directory for OpenSSL includes], + CFLAGS="-I$withval $CFLAGS" + CXXFLAGS="-I$withval $CXXFLAGS" + CPPFLAGS="-I$withval $CPPFLAGS",) + +SSLLIBS="" + +if test x$enable_ssl != xno; then + AC_CHECK_HEADER(openssl/ssl.h, + 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 + +AC_SUBST(SSLLIBS) + +EXPORT_SSLLIBS="$SSLLIBS" +AC_SUBST(EXPORT_SSLLIBS) + + +dnl +dnl End of "$Id: cups-openssl.m4 2491 2002-06-06 19:39:37Z mike $". +dnl diff --git a/config-scripts/cups-opsys.m4 b/config-scripts/cups-opsys.m4 new file mode 100644 index 0000000000..61bb266a36 --- /dev/null +++ b/config-scripts/cups-opsys.m4 @@ -0,0 +1,90 @@ +dnl +dnl "$Id: cups-opsys.m4 2193 2002-03-08 19:49:00Z mike $" +dnl +dnl Operating system stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +dnl Get the operating system and version number... +uname=`uname` +uversion=`uname -r | sed -e '1,$s/[[^0-9]]//g'` +if test x$uname = xIRIX64; then + uname="IRIX" +fi + +dnl Determine the correct username and group for this OS... +AC_ARG_WITH(cups-user, [ --with-cups-user set default user for CUPS], + CUPS_USER="$withval", + AC_MSG_CHECKING(for default print user) + if test -f /etc/passwd; then + CUPS_USER="" + for user in lp lpd guest daemon nobody; do + if test "`grep \^${user}: /etc/passwd`" != ""; then + CUPS_USER="$user" + AC_MSG_RESULT($user) + break; + fi + done + + if test x$CUPS_USER = x; then + CUPS_USER="${USER:=nobody}" + AC_MSG_RESULT(not found, using "$CUPS_USER") + fi + else + CUPS_USER="${USER:=nobody}" + AC_MSG_RESULT(no password file, using "$CUPS_USER") + fi) + +AC_ARG_WITH(cups-group, [ --with-cups-group set default group for CUPS], + CUPS_GROUP="$withval", + AC_MSG_CHECKING(for default print group) + if test x$uname = xDarwin; then + CUPS_GROUP="admin" + AC_MSG_RESULT(Darwin, using "$CUPS_GROUP") + else + if test -f /etc/group; then + CUPS_GROUP="" + for group in sys system root; do + if test "`grep \^${group}: /etc/group`" != ""; then + CUPS_GROUP="$group" + AC_MSG_RESULT($group) + break; + fi + done + + if test x$CUPS_GROUP = x; then + CUPS_GROUP="${GROUP:=nobody}" + AC_MSG_RESULT(not found, using "$CUPS_GROUP") + fi + else + CUPS_GROUP="${GROUP:=nobody}" + AC_MSG_RESULT(no group file, using "$CUPS_GROUP") + fi + fi) + +AC_SUBST(CUPS_USER) +AC_SUBST(CUPS_GROUP) + +AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USER, "$CUPS_USER") +AC_DEFINE_UNQUOTED(CUPS_DEFAULT_GROUP, "$CUPS_GROUP") + +dnl +dnl "$Id: cups-opsys.m4 2193 2002-03-08 19:49:00Z mike $" +dnl diff --git a/config-scripts/cups-pam.m4 b/config-scripts/cups-pam.m4 new file mode 100644 index 0000000000..636680babe --- /dev/null +++ b/config-scripts/cups-pam.m4 @@ -0,0 +1,71 @@ +dnl +dnl "$Id: cups-pam.m4 2756 2002-08-30 20:56:45Z mike $" +dnl +dnl PAM stuff for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +AC_ARG_ENABLE(pam, [ --enable-pam turn on PAM support, default=yes]) + +dnl Don't use PAM with AIX... +if test $uname = AIX; then + enable_pam=no +fi + +PAMDIR="" +PAMLIBS="" +PAMMOD="pam_unknown.so" + +if test x$enable_pam != xno; then + SAVELIBS="$LIBS" + + AC_CHECK_LIB(dl,dlopen) + AC_CHECK_LIB(pam,pam_start) + AC_CHECK_HEADER(pam/pam_appl.h,AC_DEFINE(HAVE_PAM_PAM_APPL_H)) + + if test x$ac_cv_lib_pam_pam_start != xno; then + if test x$ac_cv_lib_dl_dlopen != xno; then + PAMLIBS="-lpam -ldl" + else + PAMLIBS="-lpam" + fi + if test -d /etc/pam.d; then + PAMDIR="/etc/pam.d" + fi + fi + + LIBS="$SAVELIBS" + + # This test might need to be updated as Linux distributors move + # things around... + for mod in pam_unix2.so pam_unix.so pam_pwdb.so; do + if test -f /lib/security/$mod; then + PAMMOD="$mod" + fi + done +fi + +AC_SUBST(PAMDIR) +AC_SUBST(PAMLIBS) +AC_SUBST(PAMMOD) + +dnl +dnl End of "$Id: cups-pam.m4 2756 2002-08-30 20:56:45Z mike $". +dnl diff --git a/config-scripts/cups-sharedlibs.m4 b/config-scripts/cups-sharedlibs.m4 new file mode 100644 index 0000000000..8e351c1652 --- /dev/null +++ b/config-scripts/cups-sharedlibs.m4 @@ -0,0 +1,149 @@ +dnl +dnl "$Id: cups-sharedlibs.m4 2501 2002-06-07 21:02:33Z mike $" +dnl +dnl Shared library support for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +PICFLAG=1 +DSOFLAGS="${DSOFLAGS:=}" + +AC_ARG_ENABLE(shared, [ --enable-shared turn on shared libraries, default=yes]) + +if test x$enable_shared != xno; then + case "$uname" in + SunOS* | UNIX_S*) + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC)" + DSOFLAGS="$DSOFLAGS -Wl,-h,\$@ -G \$(OPTIM)" + ;; + HP-UX*) + LIBCUPS="libcups.sl.2" + LIBCUPSIMAGE="libcupsimage.sl.2" + DSO="ld" + DSOFLAGS="$DSOFLAGS -b -z +h \$@" + ;; + IRIX*) + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC)" + DSOFLAGS="$DSOFLAGS -Wl,-rpath,\$(libdir),-set_version,sgi2.4,-soname,\$@ -shared \$(OPTIM)" + ;; + OSF1* | Linux* | *BSD*) + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC)" + DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)" + ;; + Darwin*) + LIBCUPS="libcups.2.dylib" + LIBCUPSIMAGE="libcupsimage.2.dylib" + DSO="\$(CC)" + DSOFLAGS="$DSOFLAGS \$(RC_CFLAGS) -dynamiclib -lc" + ;; + AIX*) + LIBCUPS="libcups_s.a" + LIBCUPSIMAGE="libcupsimage_s.a" + DSO="\$(CC)" + DSOFLAGS="$DSOFLAGS -Wl,-bexpall,-bM:SRE,-bnoentry" + ;; + *) + echo "Warning: shared libraries may not be supported. Trying -shared" + echo " option with compiler." + LIBCUPS="libcups.so.2" + LIBCUPSIMAGE="libcupsimage.so.2" + DSO="\$(CC)" + DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)" + ;; + esac +else + PICFLAG=0 + LIBCUPS="libcups.a" + LIBCUPSIMAGE="libcupsimage.a" + DSO=":" +fi + +AC_SUBST(DSO) +AC_SUBST(DSOFLAGS) +AC_SUBST(LIBCUPS) +AC_SUBST(LIBCUPSIMAGE) + +if test x$enable_shared = xno; then + LINKCUPS="-lcups \$(SSLLIBS)" + LINKCUPSIMAGE="-lcupsimage" +else + if test $uname = AIX; then + LINKCUPS="-lcups_s" + LINKCUPSIMAGE="-lcupsimage_s" + else + LINKCUPS="-lcups" + LINKCUPSIMAGE="-lcupsimage" + fi +fi + +AC_SUBST(LINKCUPS) +AC_SUBST(LINKCUPSIMAGE) + +dnl Update libraries for DSOs... +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="+s +b $libdir $DSOFLAGS" + LDFLAGS="$LDFLAGS -Wl,+s,+b,$libdir" + ;; + SunOS*) + # Solaris + DSOFLAGS="-R$libdir $DSOFLAGS" + LDFLAGS="$LDFLAGS -R$libdir" + ;; + *BSD*) + # *BSD + DSOFLAGS="-Wl,-R$libdir $DSOFLAGS" + LDFLAGS="$LDFLAGS -Wl,-R$libdir" + ;; + Linux*) + # Linux + DSOFLAGS="-Wl,-rpath,$libdir $DSOFLAGS" + LDFLAGS="$LDFLAGS -Wl,-rpath,$libdir" + ;; + esac +else + DSOLIBS="" + IMGLIBS="\$(LIBPNG) \$(LIBTIFF) \$(LIBJPEG) \$(LIBZ)" +fi + +AC_SUBST(DSOLIBS) +AC_SUBST(IMGLIBS) + +dnl +dnl End of "$Id: cups-sharedlibs.m4 2501 2002-06-07 21:02:33Z mike $". +dnl diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..253cffc054 --- /dev/null +++ b/config.h.in @@ -0,0 +1,240 @@ +/* + * "$Id$" + * + * Configuration file for the Common UNIX Printing System (CUPS). + * + * @configure_input@ + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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-9600 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +/* + * Version of software... + */ + +#define CUPS_SVERSION "CUPS v1.1.17" + + +/* + * Default user and group... + */ + +#define CUPS_DEFAULT_USER "lp" +#define CUPS_DEFAULT_GROUP "sys" + + +/* + * Where are files stored? + */ + +#define CUPS_LOCALEDIR "/usr/share/locale" +#define CUPS_SERVERROOT "/etc/cups" +#define CUPS_SERVERBIN "/usr/lib/cups" +#define CUPS_DOCROOT "/usr/share/doc/cups" +#define CUPS_REQUESTS "/var/spool/cups" +#define CUPS_LOGDIR "/var/logs/cups" +#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_LIBPNG +#undef HAVE_LIBZ +#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? + */ + +#undef HAVE_DIRENT_H +#undef HAVE_SYS_DIR_H +#undef HAVE_SYS_NDIR_H +#undef HAVE_NDIR_H + + +/* + * Do we have PAM stuff? + */ + +#ifndef HAVE_LIBPAM +#define HAVE_LIBPAM 0 +#endif /* !HAVE_LIBPAM */ + +#undef HAVE_PAM_PAM_APPL_H + + +/* + * Do we have ? + */ + +#undef HAVE_SHADOW_H + + +/* + * Do we have ? + */ + +#undef HAVE_CRYPT_H + + +/* + * Use , , and/or ? + */ + +#undef HAVE_STRING_H +#undef HAVE_STRINGS_H +#undef HAVE_BSTRING_H + + +/* + * Do we have the strXXX() functions? + */ + +#undef HAVE_STRDUP +#undef HAVE_STRCASECMP +#undef HAVE_STRNCASECMP +#undef HAVE_STRLCAT +#undef HAVE_STRLCPY + + +/* + * 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 ? + */ + +#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 + + +/* + * Do we have rresvport()? + */ + +#undef HAVE_RRESVPORT + + +/* + * Do we have getifaddrs()? + */ + +#undef HAVE_GETIFADDRS + + +/* + * Do we have the header file? + */ + +#undef HAVE_SYS_SOCKIO_H + + +/* + * Does the sockaddr structure contain an sa_len parameter? + */ + +#undef HAVE_STRUCT_SOCKADDR_SA_LEN + + +/* + * End of "$Id$". + */ diff --git a/configure.in b/configure.in new file mode 100644 index 0000000000..7755aa33f6 --- /dev/null +++ b/configure.in @@ -0,0 +1,48 @@ +dnl +dnl "$Id$" +dnl +dnl Configuration script for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-2002 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44141 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +AC_INIT(cups/cups.h) + +sinclude(config-scripts/cups-opsys.m4) +sinclude(config-scripts/cups-common.m4) +sinclude(config-scripts/cups-directories.m4) +sinclude(config-scripts/cups-manpages.m4) + +sinclude(config-scripts/cups-sharedlibs.m4) +sinclude(config-scripts/cups-libtool.m4) +sinclude(config-scripts/cups-compiler.m4) + +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) + +AC_OUTPUT(Makedefs cups.list cups.sh cups-config conf/cupsd.conf conf/pam.conf) + +chmod +x cups-config + +dnl +dnl End of "$Id$". +dnl diff --git a/cups-config.in b/cups-config.in new file mode 100755 index 0000000000..1eb0cd42e8 --- /dev/null +++ b/cups-config.in @@ -0,0 +1,134 @@ +#!/bin/sh +# +# "$Id$" +# +# CUPS configuration utility. +# +# Copyright 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 +# + +VERSION="1.1.17" +APIVERSION="1.1" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +includedir=@includedir@ +libdir=@libdir@ +datadir=@datadir@ +sysconfdir=@sysconfdir@ +cups_datadir=@CUPS_DATADIR@ +cups_serverbin=@CUPS_SERVERBIN@ +cups_serverroot=@CUPS_SERVERROOT@ + +# flags for C++ compiler: +CFLAGS="" +LDFLAGS="" +LIBS="@EXPORT_SSLLIBS@ @NETLIBS@" +IMGLIBS="@EXPORT_LIBTIFF@ @EXPORT_LIBJPEG@ @EXPORT_LIBPNG@ @EXPORT_LIBZ@" + +if test $includedir != /usr/include; then + CFLAGS="$CFLAGS -I$includedir" +fi + +if test $libdir != /usr/lib -a $libdir != /usr/lib32; then + LDFLAGS="$LDFLAGS -L$libdir" +fi + +usage () +{ + echo "Usage: cups-config --api-version" + echo " cups-config --cflags" + echo " cups-config --datadir" + echo " cups-config --help" + echo " cups-config --ldflags" + echo " cups-config [--image] [--static] --libs" + echo " cups-config --serverbin" + echo " cups-config --serverroot" + echo " cups-config --version" + + exit $1 +} + +if test $# -eq 0; then + usage 1 +fi + +# Parse command line options +static=no +image=no + +while test $# -gt 0; do + case $1 in + --api-version) + echo $APIVERSION + ;; + --cflags) + echo $CFLAGS + ;; + --datadir) + echo $cups_datadir + ;; + --help) + usage 0 + ;; + --image) + image=yes + ;; + --ldflags) + echo $LDFLAGS + ;; + --libs) + if test $static = no; then + if test $image = no; then + echo -lcups $LIBS + else + echo -lcupsimage $IMGLIBS -lcups $LIBS + fi + else + if test $image = no; then + echo $libdir/libcups.a $LIBS + else + echo $libdir/libcupsimage.a $IMGLIBS $libdir/libcups.a $LIBS + fi + fi + ;; + --serverbin) + echo $cups_serverbin + ;; + --serverroot) + echo $cups_serverroot + ;; + --static) + static=yes + ;; + --version) + echo $VERSION + ;; + *) + usage 1 + ;; + esac + + shift +done + +# +# End of "$Id$". +# diff --git a/cups.dsw b/cups.dsw new file mode 100644 index 0000000000..e4208fda21 --- /dev/null +++ b/cups.dsw @@ -0,0 +1,128 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "cups"=.\cups\cups.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "enumports"=.\visualc\enumports.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "fltk"="..\fltk-1.1\visualc\fltk.lib.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "fltkimages"="..\fltk-1.1\visualc\fltkimages.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gui"=.\gui\gui.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "printers"=.\gui\printers.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cups + End Project Dependency + Begin Project Dependency + Project_Dep_Name fltk + End Project Dependency + Begin Project Dependency + Project_Dep_Name gui + End Project Dependency + Begin Project Dependency + Project_Dep_Name fltkimages + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "restartspooler"=.\visualc\restartspooler.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "zlib"="..\htmldoc-1.8\visualc\zlib.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/cups.list.in b/cups.list.in new file mode 100644 index 0000000000..482603f444 --- /dev/null +++ b/cups.list.in @@ -0,0 +1,472 @@ +# +# "$Id$" +# +# ESP Package Manager (EPM) file list for the Common UNIX Printing +# System (CUPS). +# +# Copyright 1997-2002 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-2002 by Easy Software Products, All Rights Reserved. +%vendor Easy Software Products +%license LICENSE.txt +%readme README.txt +%version 1.1.17 +%provides cupsys +%provides cups-devel +%provides cupsys-devel +%provides libcups1 +%provides libcups.so.2 + +# +# GNU variables... +# + +$prefix=@prefix@ +$exec_prefix=@exec_prefix@ +$bindir=@bindir@ +$datadir=@datadir@ +$includedir=@includedir@ +$infodir=@infodir@ +$libdir=@libdir@ +$libexecdir=@libexecdir@ +$localstatedir=@localstatedir@ +$mandir=@mandir@ +$oldincludedir=@oldincludedir@ +$sbindir=@sbindir@ +$sharedstatedir=@sharedstatedir@ +$srcdir=@srcdir@ +$sysconfdir=@sysconfdir@ +$top_srcdir=@top_srcdir@ + +# +# ESP variables... +# + +$AMANDIR=@AMANDIR@ +$BINDIR=@bindir@ +$DATADIR=@CUPS_DATADIR@ +$DOCDIR=@CUPS_DOCROOT@ +$INCLUDEDIR=${includedir} +$INITDIR=@INITDIR@ +$INITDDIR=@INITDDIR@ +$LIBDIR=${libdir} +$LOCALEDIR=@CUPS_LOCALEDIR@ +$LOGDIR=@CUPS_LOGDIR@ +$MANDIR=@mandir@ +$PAMDIR=@PAMDIR@ +$PMANDIR=@PMANDIR@ +$REQUESTS=@CUPS_REQUESTS@ +$SBINDIR=@sbindir@ +$SERVERBIN=@CUPS_SERVERBIN@ +$SERVERROOT=@CUPS_SERVERROOT@ + +$CUPS_USER=@CUPS_USER@ +$CUPS_GROUP=@CUPS_GROUP@ + +$CAT1EXT=@CAT1EXT@ +$CAT3EXT=@CAT3EXT@ +$CAT5EXT=@CAT5EXT@ +$CAT8EXT=@CAT8EXT@ +$MAN8EXT=@MAN8EXT@ +$MAN8DIR=@MAN8DIR@ + +# Make sure the MD5 password file is now owned by CUPS_USER... +%postinstall if test -f $SERVERROOT/passwd.md5; then +%postinstall chown $CUPS_USER $SERVERROOT/passwd.md5 +%postinstall fi + +# Make sure the shared libraries are refreshed... +%system linux +%postinstall ldconfig +%system all + +# 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/scsi backend/scsi +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/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/rastertodymo filter/rastertodymo +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/cupsaddsmb systemv/cupsaddsmb +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 $CUPS_USER 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 aix +f 0555 root sys $LIBDIR/libcups_s.a cups/libcups_s.a +f 0555 root sys $LIBDIR/libcupsimage_s.a filter/libcupsimage_s.a +%system darwin +f 0555 root sys $LIBDIR/libcups.2.dylib cups/libcups.2.dylib +l 0555 root sys $LIBDIR/libcups.dylib libcups.2.dylib +f 0555 root sys $LIBDIR/libcupsimage.2.dylib filter/libcupsimage.2.dylib +l 0555 root sys $LIBDIR/libcupsimage.dylib libcupsimage.2.dylib +%system !hpux !aix !darwin +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 $CUPS_USER sys $REQUESTS - +d 1700 $CUPS_USER sys $REQUESTS/tmp - + +# Data files +f 0444 root sys $LOCALEDIR/C/cups_C locale/C/cups_C +f 0444 root sys $LOCALEDIR/be/cups_be locale/be/cups_be +f 0444 root sys $LOCALEDIR/cs/cups_cs locale/cs/cups_cs +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 +f 0444 root sys $LOCALEDIR/ru_RU.cp1251/cups_ru_RU.cp1251 locale/ru_RU.cp1251/cups_ru_RU.cp1251 +f 0444 root sys $LOCALEDIR/ru_RU.koi8r/cups_ru_RU.koi8r locale/ru_RU.koi8r/cups_ru_RU.koi8r +f 0444 root sys $LOCALEDIR/sv/cups_sv locale/sv/cups_sv +f 0444 root sys $LOCALEDIR/uk/cups_uk locale/uk/cups_uk +f 0444 root sys $LOCALEDIR/uk_UA.cp1251/cups_uk_UA.cp1251 locale/uk_UA.cp1251/cups_uk_UA.cp1251 +f 0444 root sys $LOCALEDIR/zh_CN/cups_zh_CN locale/zh_CN/cups_zh_CN + +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-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/iso-8859-10 data/iso-8859-10 +f 0444 root sys $DATADIR/charsets/iso-8859-13 data/iso-8859-13 +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/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/Courier* +f 0444 root sys $DATADIR/fonts/Symbol fonts/Symbol + +d 0555 root sys $DATADIR/model - +f 0444 root sys $DATADIR/model ppd/*.ppd + +d 0555 root sys $DATADIR/templates - +c 0444 root sys $DATADIR/templates templates/*.tmpl + +d 0555 root sys $DATADIR/templates/fr - +c 0444 root sys $DATADIR/templates/fr templates/fr/*.tmpl + +# Config files +d 0555 root sys $SERVERROOT - +d 0711 $CUPS_USER $CUPS_GROUP $SERVERROOT/certs - +d 0755 root sys $SERVERROOT/interfaces - +d 0755 root sys $SERVERROOT/ppd - +c 0600 root sys $SERVERROOT conf/*.conf +c 0600 root sys $SERVERROOT/mime.convs conf/mime.convs +c 0600 root sys $SERVERROOT/mime.types conf/mime.types + +%system linux +d 0555 root sys $PAMDIR - +c 0644 root sys $PAMDIR/cups conf/pam.conf + +# IRIX doesn't normally support PAM, but the freeware project +# includes a version of PAM that can be used... +%system irix +d 0555 root sys $PAMDIR - +c 0644 root sys $PAMDIR/cups data/cups.irix + +%system all + +# Developer files +f 0555 root sys $BINDIR/cups-config cups-config +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 doc/*.css +f 0444 root sys $DOCDIR doc/*.html +f 0444 root sys $DOCDIR doc/*.pdf +d 0555 root sys $DOCDIR/fr - +f 0444 root sys $DOCDIR/fr doc/fr/*.css +f 0444 root sys $DOCDIR/fr doc/fr/*.html +f 0444 root sys $DOCDIR/fr doc/fr/*.pdf +d 0555 root sys $DOCDIR/images - +f 0444 root sys $DOCDIR/images doc/images/*.gif + +# Man pages +d 0555 root sys $AMANDIR - +d 0555 root sys $AMANDIR/cat$MAN8DIR - +d 0555 root sys $AMANDIR/man$MAN8DIR - +d 0555 root sys $MANDIR - +d 0555 root sys $MANDIR/cat1 - +d 0555 root sys $MANDIR/cat5 - +d 0555 root sys $MANDIR/man1 - +d 0555 root sys $MANDIR/man5 - +d 0555 root sys $PMANDIR - +d 0555 root sys $PMANDIR/cat3 - +d 0555 root sys $PMANDIR/man3 - + +f 0444 root sys $MANDIR/cat1/backend.$CAT1EXT man/backend.$CAT1EXT +f 0444 root sys $MANDIR/cat1/filter.$CAT1EXT man/filter.$CAT1EXT +f 0444 root sys $MANDIR/cat1/lpoptions.$CAT1EXT man/lpoptions.$CAT1EXT +f 0444 root sys $MANDIR/cat1/lppasswd.$CAT1EXT man/lppasswd.$CAT1EXT +f 0444 root sys $MANDIR/cat1/lpq.$CAT1EXT man/lpq.$CAT1EXT +f 0444 root sys $MANDIR/cat1/lprm.$CAT1EXT man/lprm.$CAT1EXT +f 0444 root sys $MANDIR/cat1/lpr.$CAT1EXT man/lpr.$CAT1EXT +f 0444 root sys $MANDIR/cat1/lpstat.$CAT1EXT man/lpstat.$CAT1EXT +f 0444 root sys $MANDIR/cat1/lp.$CAT1EXT man/lp.$CAT1EXT +l 0444 root sys $MANDIR/cat1/cancel.$CAT1EXT lp.$CAT1EXT + +f 0444 root sys $PMANDIR/cat3/cups-config.$CAT3EXT man/cups-config.$CAT3EXT + +f 0444 root sys $MANDIR/cat5/classes.conf.$CAT5EXT man/classes.conf.$CAT5EXT +f 0444 root sys $MANDIR/cat5/cupsd.conf.$CAT5EXT man/cupsd.conf.$CAT5EXT +f 0444 root sys $MANDIR/cat5/mime.convs.$CAT5EXT man/mime.convs.$CAT5EXT +f 0444 root sys $MANDIR/cat5/mime.types.$CAT5EXT man/mime.types.$CAT5EXT +f 0444 root sys $MANDIR/cat5/printers.conf.$CAT5EXT man/printers.conf.$CAT5EXT + +f 0444 root sys $AMANDIR/cat$MAN8DIR/accept.$CAT8EXT man/accept.$CAT8EXT +l 0444 root sys $AMANDIR/cat$MAN8DIR/reject.$CAT8EXT accept.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/cupsaddsmb.$CAT8EXT man/cupsaddsmb.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/cups-lpd.$CAT8EXT man/cups-lpd.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/cups-polld.$CAT8EXT man/cups-polld.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/cupsd.$CAT8EXT man/cupsd.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/enable.$CAT8EXT man/enable.$CAT8EXT +l 0444 root sys $AMANDIR/cat$MAN8DIR/disable.$CAT8EXT enable.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/lpadmin.$CAT8EXT man/lpadmin.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/lpc.$CAT8EXT man/lpc.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/lpinfo.$CAT8EXT man/lpinfo.$CAT8EXT +f 0444 root sys $AMANDIR/cat$MAN8DIR/lpmove.$CAT8EXT man/lpmove.$CAT8EXT + +f 0444 root sys $MANDIR/man1/backend.$MAN1EXT man/backend.man +f 0444 root sys $MANDIR/man1/filter.$MAN1EXT man/filter.man +f 0444 root sys $MANDIR/man1/lpoptions.$MAN1EXT man/lpoptions.man +f 0444 root sys $MANDIR/man1/lppasswd.$MAN1EXT man/lppasswd.man +f 0444 root sys $MANDIR/man1/lpq.$MAN1EXT man/lpq.man +f 0444 root sys $MANDIR/man1/lprm.$MAN1EXT man/lprm.man +f 0444 root sys $MANDIR/man1/lpr.$MAN1EXT man/lpr.man +f 0444 root sys $MANDIR/man1/lpstat.$MAN1EXT man/lpstat.man +f 0444 root sys $MANDIR/man1/lp.$MAN1EXT man/lp.man +l 0444 root sys $MANDIR/man1/cancel.$MAN1EXT lp.$MAN1EXT + +f 0444 root sys $PMANDIR/man3/cups-config.$MAN3EXT man/cups-config.man + +f 0444 root sys $MANDIR/man5/classes.conf.$MAN5EXT man/classes.conf.man +f 0444 root sys $MANDIR/man5/cupsd.conf.$MAN5EXT man/cupsd.conf.man +f 0444 root sys $MANDIR/man5/mime.convs.$MAN5EXT man/mime.convs.man +f 0444 root sys $MANDIR/man5/mime.types.$MAN5EXT man/mime.types.man +f 0444 root sys $MANDIR/man5/printers.conf.$MAN5EXT man/printers.conf.man + +f 0444 root sys $AMANDIR/man$MAN8DIR/accept.$MAN8EXT man/accept.man +l 0444 root sys $AMANDIR/man$MAN8DIR/reject.$MAN8EXT accept.$MAN8EXT +f 0444 root sys $AMANDIR/man$MAN8DIR/cupsaddsmb.$MAN8EXT man/cupsaddsmb.man +f 0444 root sys $AMANDIR/man$MAN8DIR/cups-lpd.$MAN8EXT man/cups-lpd.man +f 0444 root sys $AMANDIR/man$MAN8DIR/cups-polld.$MAN8EXT man/cups-polld.man +f 0444 root sys $AMANDIR/man$MAN8DIR/cupsd.$MAN8EXT man/cupsd.man +f 0444 root sys $AMANDIR/man$MAN8DIR/enable.$MAN8EXT man/enable.man +l 0444 root sys $AMANDIR/man$MAN8DIR/disable.$MAN8EXT enable.$MAN8EXT +f 0444 root sys $AMANDIR/man$MAN8DIR/lpadmin.$MAN8EXT man/lpadmin.man +f 0444 root sys $AMANDIR/man$MAN8DIR/lpc.$MAN8EXT man/lpc.man +f 0444 root sys $AMANDIR/man$MAN8DIR/lpinfo.$MAN8EXT man/lpinfo.man +f 0444 root sys $AMANDIR/man$MAN8DIR/lpmove.$MAN8EXT man/lpmove.man + +d 0555 root sys $AMANDIR/fr - +d 0555 root sys $AMANDIR/fr/cat$MAN8DIR - +d 0555 root sys $AMANDIR/fr/man$MAN8DIR - +d 0555 root sys $MANDIR/fr - +d 0555 root sys $MANDIR/fr/cat1 - +d 0555 root sys $MANDIR/fr/cat5 - +d 0555 root sys $MANDIR/fr/man1 - +d 0555 root sys $MANDIR/fr/man5 - +d 0555 root sys $PMANDIR/fr - +d 0555 root sys $PMANDIR/fr/cat3 - +d 0555 root sys $PMANDIR/fr/man3 - + +f 0444 root sys $MANDIR/fr/cat1/backend.$CAT1EXT man/backend.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/filter.$CAT1EXT man/filter.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/lpoptions.$CAT1EXT man/lpoptions.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/lppasswd.$CAT1EXT man/lppasswd.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/lpq.$CAT1EXT man/lpq.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/lprm.$CAT1EXT man/lprm.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/lpr.$CAT1EXT man/lpr.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/lpstat.$CAT1EXT man/lpstat.$CAT1EXT +f 0444 root sys $MANDIR/fr/cat1/lp.$CAT1EXT man/lp.$CAT1EXT +l 0444 root sys $MANDIR/fr/cat1/cancel.$CAT1EXT lp.$CAT1EXT + +f 0444 root sys $PMANDIR/fr/cat3/cups-config.$CAT3EXT man/cups-config.$CAT3EXT + +f 0444 root sys $MANDIR/fr/cat5/classes.conf.$CAT5EXT man/classes.conf.$CAT5EXT +f 0444 root sys $MANDIR/fr/cat5/cupsd.conf.$CAT5EXT man/cupsd.conf.$CAT5EXT +f 0444 root sys $MANDIR/fr/cat5/mime.convs.$CAT5EXT man/mime.convs.$CAT5EXT +f 0444 root sys $MANDIR/fr/cat5/mime.types.$CAT5EXT man/mime.types.$CAT5EXT +f 0444 root sys $MANDIR/fr/cat5/printers.conf.$CAT5EXT man/printers.conf.$CAT5EXT + +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/accept.$CAT8EXT man/accept.$CAT8EXT +l 0444 root sys $AMANDIR/fr/cat$MAN8DIR/reject.$CAT8EXT accept.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cupsaddsmb.$CAT8EXT man/cupsaddsmb.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cups-lpd.$CAT8EXT man/cups-lpd.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cups-polld.$CAT8EXT man/cups-polld.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cupsd.$CAT8EXT man/cupsd.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/enable.$CAT8EXT man/enable.$CAT8EXT +l 0444 root sys $AMANDIR/fr/cat$MAN8DIR/disable.$CAT8EXT enable.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpadmin.$CAT8EXT man/lpadmin.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpc.$CAT8EXT man/lpc.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpinfo.$CAT8EXT man/lpinfo.$CAT8EXT +f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpmove.$CAT8EXT man/lpmove.$CAT8EXT + +f 0444 root sys $MANDIR/fr/man1/backend.$MAN1EXT man/backend.man +f 0444 root sys $MANDIR/fr/man1/filter.$MAN1EXT man/filter.man +f 0444 root sys $MANDIR/fr/man1/lpoptions.$MAN1EXT man/lpoptions.man +f 0444 root sys $MANDIR/fr/man1/lppasswd.$MAN1EXT man/lppasswd.man +f 0444 root sys $MANDIR/fr/man1/lpq.$MAN1EXT man/lpq.man +f 0444 root sys $MANDIR/fr/man1/lprm.$MAN1EXT man/lprm.man +f 0444 root sys $MANDIR/fr/man1/lpr.$MAN1EXT man/lpr.man +f 0444 root sys $MANDIR/fr/man1/lpstat.$MAN1EXT man/lpstat.man +f 0444 root sys $MANDIR/fr/man1/lp.$MAN1EXT man/lp.man +l 0444 root sys $MANDIR/fr/man1/cancel.$MAN1EXT lp.$MAN1EXT + +f 0444 root sys $PMANDIR/fr/man3/cups-config.$MAN3EXT man/cups-config.man + +f 0444 root sys $MANDIR/fr/man5/classes.conf.$MAN5EXT man/classes.conf.man +f 0444 root sys $MANDIR/fr/man5/cupsd.conf.$MAN5EXT man/cupsd.conf.man +f 0444 root sys $MANDIR/fr/man5/mime.convs.$MAN5EXT man/mime.convs.man +f 0444 root sys $MANDIR/fr/man5/mime.types.$MAN5EXT man/mime.types.man +f 0444 root sys $MANDIR/fr/man5/printers.conf.$MAN5EXT man/printers.conf.man + +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/accept.$MAN8EXT man/accept.man +l 0444 root sys $AMANDIR/fr/man$MAN8DIR/reject.$MAN8EXT accept.$MAN8EXT +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cupsaddsmb.$MAN8EXT man/cupsaddsmb.man +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cups-lpd.$MAN8EXT man/cups-lpd.man +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cups-polld.$MAN8EXT man/cups-polld.man +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cupsd.$MAN8EXT man/cupsd.man +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/enable.$MAN8EXT man/enable.man +l 0444 root sys $AMANDIR/fr/man$MAN8DIR/disable.$MAN8EXT enable.$MAN8EXT +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpadmin.$MAN8EXT man/lpadmin.man +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpc.$MAN8EXT man/lpc.man +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpinfo.$MAN8EXT man/lpinfo.man +f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpmove.$MAN8EXT man/lpmove.man + +# Startup script +%system all +i 0555 root sys cups cups.sh + +# +# End of "$Id$". +# diff --git a/cups.plist b/cups.plist new file mode 100644 index 0000000000..a5b989b587 --- /dev/null +++ b/cups.plist @@ -0,0 +1,7 @@ +{ + Description = "Printing Services"; + Provides = ("Printing"); + Requires = ("Resolver"); + Uses = ("Network Time"); + OrderPreference = "Late"; +} diff --git a/cups.sh.in b/cups.sh.in new file mode 100755 index 0000000000..30272c6e90 --- /dev/null +++ b/cups.sh.in @@ -0,0 +1,211 @@ +#!/bin/sh +# +# "$Id$" +# +# Startup/shutdown script for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 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 +# + +#### OS-Dependent Information + +# +# Linux chkconfig stuff: +# +# chkconfig: 235 99 00 +# description: Startup/shutdown script for the Common UNIX \ +# Printing System (CUPS). +# + +# +# NetBSD 1.5+ rcorder script lines. The format of the following two +# lines is very strict -- please don't add additional spaces! +# +# PROVIDE: cups +# REQUIRE: DAEMON +# + + +#### OS-Dependent Configuration + +case "`uname`" in + IRIX*) + IS_ON=/sbin/chkconfig + + if $IS_ON verbose; then + ECHO=echo + else + ECHO=: + fi + ECHO_OK=: + ECHO_ERROR=: + ;; + + *BSD*) + IS_ON=: + ECHO=echo + ECHO_OK=: + ECHO_ERROR=: + ;; + + Darwin*) + . /etc/rc.common + + if test "${CUPS:=-YES-}" = "-NO-"; then + exit 0 + fi + + IS_ON=: + ECHO=ConsoleMessage + ECHO_OK=: + ECHO_ERROR=: + ;; + + Linux*) + IS_ON=/bin/true + if test -f /etc/init.d/functions; then + . /etc/init.d/functions + ECHO=echo + ECHO_OK="echo_success" + ECHO_ERROR="echo_failure" + else + ECHO=echo + ECHO_OK=: + ECHO_ERROR=: + fi + ;; + + *) + IS_ON=/bin/true + ECHO=echo + ECHO_OK=: + ECHO_ERROR=: + ;; +esac + +#### OS-Independent Stuff + +# +# Set the timezone, if possible... This allows the +# scheduler and all child processes to know the local +# timezone when reporting dates and times to the user. +# If no timezone information is found, then Greenwich +# Mean Time (GMT) will probably be used. +# + +for file in /etc/TIMEZONE /etc/rc.config /etc/sysconfig/clock; do + if test -f $file; then + . $file + fi +done + +if test "x$ZONE" != x; then + TZ="$ZONE" +fi + +if test "x$TIMEZONE" != x; then + TZ="$TIMEZONE" +fi + +if test "x$TZ" != x; then + export TZ +fi + +# +# See if the CUPS server (cupsd) is running... +# + +case "`uname`" in + HP-UX* | AIX* | SINIX*) + pid=`ps -e | awk '{if (match($4, ".*/cupsd$") || $4 == "cupsd") print $1}'` + ;; + IRIX* | 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 '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'` + ;; + Linux* | *BSD* | Darwin*) + pid=`ps ax | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'` + ;; + *) + pid="" + ;; +esac + +# +# Start or stop the CUPS server based upon the first argument to the script. +# + +case $1 in + start | restart | reload) + if $IS_ON cups; then + if test "$pid" != ""; then + kill -HUP $pid + else + prefix=@prefix@ + exec_prefix=@exec_prefix@ + @sbindir@/cupsd + if test $? != 0; then + $ECHO_FAIL + $ECHO "cups: unable to $1 scheduler." + exit 1 + fi + fi + $ECHO_OK + $ECHO "cups: ${1}ed scheduler." + fi + ;; + + stop) + if test "$pid" != ""; then + kill $pid + $ECHO_OK + $ECHO "cups: stopped scheduler." + fi + ;; + + status) + if test "$pid" != ""; then + echo "cups: scheduler is running." + else + echo "cups: scheduler is not running." + fi + ;; + + *) + echo "Usage: cups {reload|restart|start|status|stop}" + exit 1 + ;; +esac + +# +# Exit with no errors. +# + +exit 0 + + +# +# End of "$Id$". +# diff --git a/cups.spec b/cups.spec new file mode 100644 index 0000000000..9c1699f4a7 --- /dev/null +++ b/cups.spec @@ -0,0 +1,207 @@ +# +# "$Id: cups.spec 2890 2002-10-15 13:26:34Z mike $" +# +# RPM "spec" file for the Common UNIX Printing System (CUPS). +# +# Original version by Jason McMullan . +# +# Copyright 1999-2002 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 +# + +Summary: Common Unix Printing System +Name: cups +Version: 1.1.17 +Release: 1 +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: Anonymous +Vendor: Easy Software Products + +# 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 + +%package devel +Summary: Common Unix Printing System - development environment +Group: Development/Libraries +Provides: libcups1 + +%description +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software Products +to promote a standard printing solution for all UNIX vendors and users. +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. + +%prep +%setup + +%build +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 + +%install +# Make sure the RPM_BUILD_ROOT directory exists. +rm -rf $RPM_BUILD_ROOT + +make BUILDROOT=$RPM_BUILD_ROOT install + +%post +ldconfig + +if test -x /sbin/chkconfig; then + /sbin/chkconfig --add cups + /sbin/chkconfig cups on +fi + +# these lines automatically start cupsd after installation; commented out +# by request... +#if test -f /sbin/init.d/cups; then +# /sbin/init.d/cups start +#fi +#if test -f /etc/rc.d/init.d/cups; then +# /etc/rc.d/init.d/cups start +#fi +#if test -f /etc/init.d/cups; then +# /etc/init.d/cups start +#fi + +%preun +if test -f /sbin/init.d/cups; then + /sbin/init.d/cups stop +fi +if test -f /etc/rc.d/init.d/cups; then + /etc/rc.d/init.d/cups stop +fi +if test -f /etc/init.d/cups; then + /etc/init.d/cups stop +fi + +if test -x /sbin/chkconfig; then + /sbin/chkconfig --del cups +fi + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%dir /etc/cups +%config(noreplace) /etc/cups/*.conf +%dir /etc/cups/certs +%dir /etc/cups/interfaces +/etc/cups/mime.types +/etc/cups/mime.convs +%dir /etc/cups/ppd +%dir /etc/pam.d +/etc/pam.d/* + +# RC dirs are a pain under Linux... Uncomment the appropriate ones if you +# don't use Red Hat or Mandrake... + +/etc/rc.d/init.d/* +/etc/rc.d/rc0.d/* +/etc/rc.d/rc3.d/* +/etc/rc.d/rc5.d/* + +#/etc/init.d/* +#/etc/rc0.d/* +#/etc/rc3.d/* +#/etc/rc5.d/* + +#/sbin/rc.d/* +#/sbin/rc.d/rc0.d/* +#/sbin/rc.d/rc3.d/* +#/sbin/rc.d/rc5.d/* + +/usr/bin/cancel +/usr/bin/disable +/usr/bin/enable +/usr/bin/lp* +/usr/lib/*.so* +%dir /usr/lib/cups +/usr/lib/cups/* +/usr/sbin/* +%dir /usr/share/cups +/usr/share/cups/* +%dir /usr/share/doc/cups +/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/* + +%dir /usr/share/man/fr/cat1 +/usr/share/man/fr/cat1/* +%dir /usr/share/man/fr/cat5 +/usr/share/man/fr/cat5/* +%dir /usr/share/man/fr/cat8 +/usr/share/man/fr/cat8/* +%dir /usr/share/man/fr/man1 +/usr/share/man/fr/man1/* +%dir /usr/share/man/fr/man5 +/usr/share/man/fr/man5/* +%dir /usr/share/man/fr/man8 +/usr/share/man/fr/man8/* + +%attr(0700,lp,root) %dir /var/spool/cups +%attr(1700,lp,root) %dir /var/spool/cups/tmp + +%files devel +/usr/bin/cups-config +%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/man3/* + +%dir /usr/share/man/fr/cat3 +/usr/share/man/fr/cat3/* +%dir /usr/share/man/fr/man3 +/usr/share/man/fr/man3/* + +# +# End of "$Id: cups.spec 2890 2002-10-15 13:26:34Z mike $". +# diff --git a/cups.strings b/cups.strings new file mode 100644 index 0000000000..d08f919727 --- /dev/null +++ b/cups.strings @@ -0,0 +1,9 @@ + + + + + Starting printing services + Starting printing services + + + diff --git a/cups/.cvsignore b/cups/.cvsignore new file mode 100644 index 0000000000..2a1918bf91 --- /dev/null +++ b/cups/.cvsignore @@ -0,0 +1,11 @@ +libcups.a +libcups.la +libcups.sl +libcups.sl.2 +libcups.so +libcups.so.2 +libcups_s.a +libcups.2.dylib +libcups.dylib +testhttp +testppd diff --git a/cups/Dependencies b/cups/Dependencies new file mode 100644 index 0000000000..eb43c56e71 --- /dev/null +++ b/cups/Dependencies @@ -0,0 +1,26 @@ +# DO NOT DELETE + +dest.o: cups.h ipp.h http.h md5.h ppd.h language.h string.h ../config.h +emit.o: ppd.h string.h ../config.h +encode.o: cups.h ipp.h http.h md5.h ppd.h string.h ../config.h debug.h +http.o: string.h ../config.h http.h md5.h debug.h +http-addr.o: string.h ../config.h http.h md5.h +http-support.o: string.h ../config.h http.h md5.h ipp.h +ipp.o: string.h ../config.h language.h ipp.h http.h md5.h debug.h +ipp-support.o: string.h ../config.h language.h ipp.h http.h md5.h debug.h +language.o: string.h ../config.h language.h cups_C.h +mark.o: ppd.h string.h ../config.h debug.h +md5.o: md5.h string.h ../config.h +md5passwd.o: http.h md5.h string.h ../config.h +options.o: cups.h ipp.h http.h md5.h ppd.h string.h ../config.h debug.h +page.o: ppd.h string.h ../config.h +ppd.o: ppd.h string.h ../config.h language.h debug.h +snprintf.o: string.h ../config.h +string.o: string.h ../config.h +tempfile.o: cups.h ipp.h http.h md5.h ppd.h string.h ../config.h debug.h +usersys.o: cups.h ipp.h http.h md5.h ppd.h string.h ../config.h +util.o: cups.h ipp.h http.h md5.h ppd.h language.h string.h ../config.h +util.o: debug.h +testhttp.o: http.h md5.h +testlang.o: language.h +testppd.o: cups.h ipp.h http.h md5.h ppd.h string.h ../config.h diff --git a/cups/Makefile b/cups/Makefile new file mode 100644 index 0000000000..08cc2dddad --- /dev/null +++ b/cups/Makefile @@ -0,0 +1,216 @@ +# +# "$Id$" +# +# Support library Makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-2002 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 +# +# This file is subject to the Apple OS-Developed Software exception. +# + +include ../Makedefs + +# +# Object files... +# + +LIBOBJS = dest.o emit.o encode.o http.o http-addr.o http-support.o \ + ipp.o ipp-support.o language.o mark.o md5.o md5passwd.o \ + options.o page.o ppd.o snprintf.o string.o tempfile.o \ + usersys.o util.o +OBJS = $(LIBOBJS) testhttp.o testlang.o testppd.o ppd-debug.o + + +# +# Header files to install... +# + +HEADERS = cups.h http.h ipp.h language.h md5.h ppd.h + + +# +# Targets in this directory... +# + +TARGETS = $(LIBCUPS) libcups.a + + +# +# Make all targets... +# + +all: $(TARGETS) + + +# +# Remove object and target files... +# + +clean: + $(RM) $(OBJS) $(TARGETS) `basename $(LIBCUPS) .2` libcups.dylib + + +# +# Update dependencies (without system header dependencies...) +# + +depend: + makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1 + + +# +# Install object and target files... +# + +install: all installhdrs + $(INSTALL_DIR) $(LIBDIR) + $(INSTALL_LIB) $(LIBCUPS) $(LIBDIR) + if test $(LIBCUPS) = "libcups.so.2" -o $(LIBCUPS) = "libcups.sl.2"; then \ + $(RM) $(LIBDIR)/`basename $(LIBCUPS) .2`; \ + $(LN) $(LIBCUPS) $(LIBDIR)/`basename $(LIBCUPS) .2`; \ + fi + if test $(LIBCUPS) = "libcups.2.dylib"; then \ + $(STRIP) -x $(LIBDIR)/$(LIBCUPS); \ + $(RM) $(LIBDIR)/libcups.dylib; \ + $(LN) $(LIBCUPS) $(LIBDIR)/libcups.dylib; \ + fi + if test $(LIBCUPS) != "libcups.a"; then \ + $(INSTALL_LIB) libcups.a $(LIBDIR); \ + fi + $(RANLIB) $(LIBDIR)/libcups.a + +installhdrs: + $(INSTALL_DIR) $(INCLUDEDIR)/cups + for file in $(HEADERS); do \ + $(INSTALL_DATA) $$file $(INCLUDEDIR)/cups; \ + done + + +# +# libcups.so.2, libcups.sl.2 +# + +libcups.so.2 libcups.sl.2: $(LIBOBJS) ../Makedefs + echo Linking $@... + $(DSO) $(DSOFLAGS) -o $@ $(LIBOBJS) $(SSLLIBS) + $(RM) `basename $@ .2` + $(LN) $@ `basename $@ .2` + + +# +# libcups.2.dylib +# + +libcups.2.dylib: $(LIBOBJS) ../Makedefs + echo Linking $@... + $(DSO) $(DSOFLAGS) -o $@ \ + -install_name $(libdir)/$@ \ + -current_version 2.0.4 \ + -compatibility_version 2.0.0 \ + $(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 +# + +libcups.la: $(LIBOBJS) ../Makedefs + echo Linking $@... + $(DSO) $(DSOFLAGS) -o $@ $(LIBOBJS:.o=.lo) -rpath $(LIBDIR) \ + -version-info 2:4 $(SSLLIBS) + + +# +# libcups.a +# + +libcups.a: $(LIBOBJS) + echo Archiving $@... + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + + +# +# cups_C.h - the default POSIX locale that is compiled in. +# + +cups_C.h: ../locale/C/cups_C + echo Generating $@... + $(RM) cups_C.h + $(AWK) '{print "\"" $$0 "\","}' < ../locale/C/cups_C > cups_C.h + + +# +# testhttp (dependency on static CUPS library is intentional) +# + +testhttp: testhttp.o libcups.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ testhttp.o libcups.a $(NETLIBS) $(SSLLIBS) + + +# +# testlang (dependency on static CUPS library is intentional) +# + +testlang: testlang.o libcups.a + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ testlang.o libcups.a $(NETLIBS) $(SSLLIBS) + + +# +# testppd +# + +testppd: testppd.o ppd-debug.o language.o mark.o page.o string.o + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ testppd.o ppd-debug.o language.o mark.o page.o \ + string.o + +ppd-debug.o: ppd.c ppd.h string.h ../config.h language.h debug.h + echo Compiling $< with debugging... + $(CC) $(OPTIM) $(CFLAGS) -DDEBUG -c -o $@ $< + + +# +# Dependencies... +# + +include Dependencies + + +# +# End of "$Id$". +# diff --git a/cups/cups.dsp b/cups/cups.dsp new file mode 100644 index 0000000000..8867017d77 --- /dev/null +++ b/cups/cups.dsp @@ -0,0 +1,216 @@ +# Microsoft Developer Studio Project File - Name="cups" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=cups - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cups.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cups.mak" CFG="cups - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cups - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "cups - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cups - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../visualc" /I ".." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"cups.lib" + +!ELSEIF "$(CFG)" == "cups - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../visualc" /I ".." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"cupsd.lib" + +!ENDIF + +# Begin Target + +# Name "cups - Win32 Release" +# Name "cups - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\dest.c +# End Source File +# Begin Source File + +SOURCE=.\emit.c +# End Source File +# Begin Source File + +SOURCE=.\encode.c +# End Source File +# Begin Source File + +SOURCE=".\http-addr.c" +# End Source File +# Begin Source File + +SOURCE=".\http-support.c" +# End Source File +# Begin Source File + +SOURCE=.\http.c +# End Source File +# Begin Source File + +SOURCE=".\ipp-support.c" +# End Source File +# Begin Source File + +SOURCE=.\ipp.c +# End Source File +# Begin Source File + +SOURCE=.\language.c +# End Source File +# Begin Source File + +SOURCE=..\oemlicense\license.c +# End Source File +# Begin Source File + +SOURCE=.\mark.c +# End Source File +# Begin Source File + +SOURCE=.\md5.c +# End Source File +# Begin Source File + +SOURCE=.\md5passwd.c +# End Source File +# Begin Source File + +SOURCE=.\options.c +# End Source File +# Begin Source File + +SOURCE=.\page.c +# End Source File +# Begin Source File + +SOURCE=.\ppd.c +# End Source File +# Begin Source File + +SOURCE=.\snprintf.c +# End Source File +# Begin Source File + +SOURCE=.\string.c +# End Source File +# Begin Source File + +SOURCE=.\tempfile.c +# End Source File +# Begin Source File + +SOURCE=.\usersys.c +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\cups.h +# End Source File +# Begin Source File + +SOURCE=.\cups_C.h +# End Source File +# Begin Source File + +SOURCE=.\debug.h +# End Source File +# Begin Source File + +SOURCE=.\http.h +# End Source File +# Begin Source File + +SOURCE=.\ipp.h +# End Source File +# Begin Source File + +SOURCE=.\language.h +# End Source File +# Begin Source File + +SOURCE=..\oemlicense\license.h +# End Source File +# Begin Source File + +SOURCE=.\md5.h +# End Source File +# Begin Source File + +SOURCE=.\ppd.h +# End Source File +# Begin Source File + +SOURCE=.\string.h +# End Source File +# End Group +# End Target +# End Project diff --git a/cups/cups.h b/cups/cups.h new file mode 100644 index 0000000000..7874a593fe --- /dev/null +++ b/cups/cups.h @@ -0,0 +1,180 @@ +/* + * "$Id$" + * + * API definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_CUPS_H_ +# define _CUPS_CUPS_H_ + +/* + * Include necessary headers... + */ + +# include "ipp.h" +# include "ppd.h" + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Constants... + */ + +# define CUPS_VERSION 1.0117 +# define CUPS_VERSION_MAJOR 1 +# define CUPS_VERSION_MINOR 1 +# define CUPS_VERSION_PATCH 17 +# define CUPS_DATE_ANY -1 + + +/* + * Types and structures... + */ + +typedef unsigned cups_ptype_t; /**** Printer Type/Capability Bits ****/ +enum /* Not a typedef'd enum so we can OR */ +{ + CUPS_PRINTER_LOCAL = 0x0000, /* Local printer or class */ + CUPS_PRINTER_CLASS = 0x0001, /* Printer class */ + CUPS_PRINTER_REMOTE = 0x0002, /* Remote printer or class */ + CUPS_PRINTER_BW = 0x0004, /* Can do B&W printing */ + CUPS_PRINTER_COLOR = 0x0008, /* Can do color printing */ + CUPS_PRINTER_DUPLEX = 0x0010, /* Can do duplexing */ + CUPS_PRINTER_STAPLE = 0x0020, /* Can staple output */ + CUPS_PRINTER_COPIES = 0x0040, /* Can do copies */ + CUPS_PRINTER_COLLATE = 0x0080, /* Can collage copies */ + CUPS_PRINTER_PUNCH = 0x0100, /* Can punch output */ + CUPS_PRINTER_COVER = 0x0200, /* Can cover output */ + CUPS_PRINTER_BIND = 0x0400, /* Can bind output */ + CUPS_PRINTER_SORT = 0x0800, /* Can sort output */ + CUPS_PRINTER_SMALL = 0x1000, /* Can do Letter/Legal/A4 */ + CUPS_PRINTER_MEDIUM = 0x2000, /* Can do Tabloid/B/C/A3/A2 */ + CUPS_PRINTER_LARGE = 0x4000, /* Can do D/E/A1/A0 */ + CUPS_PRINTER_VARIABLE = 0x8000, /* Can do variable sizes */ + CUPS_PRINTER_IMPLICIT = 0x10000, /* Implicit class */ + CUPS_PRINTER_DEFAULT = 0x20000, /* Default printer on network */ + CUPS_PRINTER_OPTIONS = 0xfffc /* ~(CLASS | REMOTE | IMPLICIT) */ +}; + +typedef struct /**** Printer Options ****/ +{ + char *name; /* Name of option */ + char *value; /* Value of option */ +} cups_option_t; + +typedef struct /**** Destination ****/ +{ + char *name, /* Printer or class name */ + *instance; /* Local instance name or NULL */ + int is_default; /* Is this printer the default? */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ +} cups_dest_t; + +typedef struct /**** Job ****/ +{ + int id; /* The job ID */ + char *dest, /* Printer or class name */ + *title, /* Title/job name */ + *user, /* User the submitted the job */ + *format; /* Document format */ + ipp_jstate_t state; /* Job state */ + int size, /* Size in kilobytes */ + priority; /* Priority (1-100) */ + time_t completed_time, /* Time the job was completed */ + creation_time, /* Time the job was created */ + processing_time; /* Time the job was processed */ +} cups_job_t; + + +/* + * Functions... + */ + +extern int cupsCancelJob(const char *printer, int job); +#define cupsDoRequest(http,request,resource) cupsDoFileRequest((http),(request),(resource),NULL) +extern ipp_t *cupsDoFileRequest(http_t *http, ipp_t *request, + const char *resource, const char *filename); +extern http_encryption_t cupsEncryption(void); +extern void cupsFreeJobs(int num_jobs, cups_job_t *jobs); +extern int cupsGetClasses(char ***classes); +extern const char *cupsGetDefault(void); +extern int cupsGetJobs(cups_job_t **jobs, const char *dest, + int myjobs, int completed); +extern const char *cupsGetPPD(const char *printer); +extern int cupsGetPrinters(char ***printers); +extern ipp_status_t cupsLastError(void); +extern int cupsPrintFile(const char *printer, const char *filename, + const char *title, int num_options, + cups_option_t *options); +extern int cupsPrintFiles(const char *printer, int num_files, + const char **files, const char *title, + int num_options, cups_option_t *options); +extern char *cupsTempFile(char *filename, int len); +extern int cupsTempFd(char *filename, int len); + +extern int cupsAddDest(const char *name, const char *instance, + int num_dests, cups_dest_t **dests); +extern void cupsFreeDests(int num_dests, cups_dest_t *dests); +extern cups_dest_t *cupsGetDest(const char *name, const char *instance, + int num_dests, cups_dest_t *dests); +extern int cupsGetDests(cups_dest_t **dests); +extern void cupsSetDests(int num_dests, cups_dest_t *dests); + +extern int cupsAddOption(const char *name, const char *value, + int num_options, cups_option_t **options); +extern void cupsEncodeOptions(ipp_t *ipp, int num_options, + cups_option_t *options); +extern void cupsFreeOptions(int num_options, cups_option_t *options); +extern const char *cupsGetOption(const char *name, int num_options, + cups_option_t *options); +extern int cupsParseOptions(const char *arg, int num_options, + cups_option_t **options); +extern int cupsMarkOptions(ppd_file_t *ppd, int num_options, + cups_option_t *options); + +extern const char *cupsGetPassword(const char *prompt); +extern const char *cupsServer(void); +extern void cupsSetEncryption(http_encryption_t e); +extern void cupsSetPasswordCB(const char *(*cb)(const char *)); +extern void cupsSetServer(const char *server); +extern void cupsSetUser(const char *user); +extern const char *cupsUser(void); + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_CUPS_CUPS_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/cups_C.h b/cups/cups_C.h new file mode 100644 index 0000000000..32e1fa6b5d --- /dev/null +++ b/cups/cups_C.h @@ -0,0 +1,135 @@ +"iso-8859-1", +"OK", +"Cancel", +"Help", +"Quit", +"Close", +"Yes", +"No", +"On", +"Off", +"Save", +"Discard", +"Default", +"Options", +"More Info", +"Black", +"Color", +"Cyan", +"Magenta", +"Yellow", +"Copyright 1993-2002 by Easy Software Products, All Rights Reserved.", +"General", +"Printer", +"Image", +"HP-GL/2", +"Extra", +"Document", +"Other", +"Print Pages: ", +"Entire Document", +"Page Range:", +"Reverse Order: ", +"Page Format: ", +" 1-Up", +" 2-Up", +" 4-Up", +"Image Scaling: ", +"Use Natural Image Size", +"Zoom by Percent", +"Zoom by PPI", +"Mirror Image: ", +"Color Saturation: ", +"Color Hue: ", +"Fit to Page: ", +"Shading: ", +"Pen Width: ", +"Gamma Correction: ", +"Brightness: ", +"Add", +"Delete", +"Modify", +"Printer URI", +"Printer Name", +"Printer Location", +"Printer Info", +"Printer Make and Model", +"Device URI", +"Formatting Page", +"Printing Page", +"Initializing Printer", +"Printer State", +"Accepting Jobs", +"Not Accepting Jobs", +"Print Jobs", +"Class", +"Local", +"Remote", +"Duplexing", +"Stapling", +"Fast Copies", +"Collated Copies", +"Hole Punching", +"Covering", +"Binding", +"Sorting", +"Small (up to 9.5x14in)", +"Medium (9.5x14in to 13x19in)", +"Large (13x19in and larger)", +"Custom Size", +"Idle", +"Processing", +"Stopped", +"All", +"Odd", +"Even", +"Darker Lighter", +"Media Size", +"Media Type", +"Media Source", +"Orientation: ", +"Portrait", +"Landscape", +"Job State", +"Job Name", +"User Name", +"Priority", +"Copies", +"File Size", +"Pending", +"Output Mode", +"Resolution", +"Text", +"Pretty Print", +"Margins", +"Left", +"Right", +"Bottom", +"Top", +"Filename(s)", +"Print", +"Options Installed", +"Auto", +"400 Your browser sent a request that this server could not understand.", +"This server could not verify that you are authorized to access the resource.", +"You must pay to access this server.", +"You don't have permission to access the resource on this server.", +"The requested resource was not found on this server.", +"The requested method is not allowed with the resource.", +"An appropriate representation for the resource was not found on this server.", +"You don't have permission to use this server as a proxy host.", +"The request has taken too long to complete and has been aborted.", +"The requested resource has more than one value.", +"The requested resource is gone and has not been replaced.", +"The requested method requires a valid Content-Length.", +"The precondition on the request evaluated to false.", +"The request is too large for this server to process.", +"The request URI is too large for this server to process.", +"The request format is not understood by this server.", +"426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.", +"500 The server has detected an unrecoverable error and cannot process your request.", +"The requested method is not implemented by this server.", +"The proxy server received an invalid response from an upstream server.", +"The requested resource is currently unavailable on this server.", +"The proxy server has taken too long to respond to this server.", +"This server does not support the HTTP version required by your browser.", diff --git a/cups/debug.h b/cups/debug.h new file mode 100644 index 0000000000..4e160ff37f --- /dev/null +++ b/cups/debug.h @@ -0,0 +1,59 @@ +/* + * "$Id$" + * + * Debugging macros for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_DEBUG_H_ +# define _CUPS_DEBUG_H_ + +/* + * Include necessary headers... + */ + +# include + +/* + * The debug macros are used if you compile with DEBUG defined. + * + * Usage: + * + * DEBUG_puts("string") + * DEBUG_printf(("format string", arg, arg, ...)); + * + * Note the extra parenthesis around the DEBUG_printf macro... + */ + +# ifdef DEBUG +# define DEBUG_puts(x) puts(x) +# define DEBUG_printf(x) printf x +# else +# define DEBUG_puts(x) +# define DEBUG_printf(x) +# endif /* DEBUG */ + +#endif /* !_CUPS_DEBUG_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/dest.c b/cups/dest.c new file mode 100644 index 0000000000..30b95e7a6c --- /dev/null +++ b/cups/dest.c @@ -0,0 +1,798 @@ +/* + * "$Id$" + * + * User-defined destination (and option) support for the Common UNIX + * Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsAddDest() - Add a destination to the list of destinations. + * cupsFreeDests() - Free the memory used by the list of destinations. + * cupsGetDest() - Get the named destination from the list. + * cupsGetDests() - Get the list of destinations. + * cupsSetDests() - Set the list of destinations. + * cups_get_dests() - Get destinations from a file. + * cups_get_sdests() - Get destinations from a server. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "language.h" +#include "string.h" +#include +#include + + +/* + * Local functions... + */ + +static int cups_get_dests(const char *filename, int num_dests, + cups_dest_t **dests); +static int cups_get_sdests(ipp_op_t op, int num_dests, + cups_dest_t **dests); + + +/* + * 'cupsAddDest()' - Add a destination to the list of destinations. + */ + +int /* O - New number of destinations */ +cupsAddDest(const char *name, /* I - Name of destination */ + const char *instance, /* I - Instance of destination */ + int num_dests, /* I - Number of destinations */ + cups_dest_t **dests) /* IO - Destinations */ +{ + int i; /* Looping var */ + cups_dest_t *dest; /* Destination pointer */ + + + if (name == NULL || dests == NULL) + return (0); + + if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL) + return (num_dests); + + /* + * Add new destination... + */ + + if (num_dests == 0) + dest = malloc(sizeof(cups_dest_t)); + else + dest = realloc(*dests, sizeof(cups_dest_t) * (num_dests + 1)); + + if (dest == NULL) + return (num_dests); + + *dests = dest; + + for (i = num_dests; i > 0; i --, dest ++) + if (strcasecmp(name, dest->name) < 0) + break; + else if (strcasecmp(name, dest->name) == 0 && + instance != NULL && dest->instance != NULL && + strcasecmp(instance, dest->instance) < 0) + break; + + if (i > 0) + memmove(dest + 1, dest, i * sizeof(cups_dest_t)); + + dest->name = strdup(name); + dest->is_default = 0; + dest->num_options = 0; + dest->options = (cups_option_t *)0; + + if (instance == NULL) + dest->instance = NULL; + else + dest->instance = strdup(instance); + + return (num_dests + 1); +} + + +/* + * 'cupsFreeDests()' - Free the memory used by the list of destinations. + */ + +void +cupsFreeDests(int num_dests, /* I - Number of destinations */ + cups_dest_t *dests) /* I - Destinations */ +{ + int i; /* Looping var */ + cups_dest_t *dest; /* Current destination */ + + + if (num_dests == 0 || dests == NULL) + return; + + for (i = num_dests, dest = dests; i > 0; i --, dest ++) + { + free(dest->name); + + if (dest->instance) + free(dest->instance); + + cupsFreeOptions(dest->num_options, dest->options); + } + + free(dests); +} + + +/* + * 'cupsGetDest()' - Get the named destination from the list. + */ + +cups_dest_t * /* O - Destination pointer or NULL */ +cupsGetDest(const char *name, /* I - Name of destination */ + const char *instance, /* I - Instance of destination */ + int num_dests, /* I - Number of destinations */ + cups_dest_t *dests) /* I - Destinations */ +{ + int comp; /* Result of comparison */ + + + if (num_dests == 0 || dests == NULL) + return (NULL); + + if (name == NULL) + { + /* + * NULL name for default printer. + */ + + while (num_dests > 0) + { + if (dests->is_default) + return (dests); + + num_dests --; + dests ++; + } + } + else + { + /* + * Lookup name and optionally the instance... + */ + + while (num_dests > 0) + { + if ((comp = strcasecmp(name, dests->name)) < 0) + return (NULL); + else if (comp == 0) + { + if ((instance == NULL && dests->instance == NULL) || + (instance != NULL && dests->instance != NULL && + strcasecmp(instance, dests->instance) == 0)) + return (dests); + } + + num_dests --; + dests ++; + } + } + + return (NULL); +} + + +/* + * 'cupsGetDests()' - Get the list of destinations. + */ + +int /* O - Number of destinations */ +cupsGetDests(cups_dest_t **dests) /* O - Destinations */ +{ + int i; /* Looping var */ + int num_dests; /* Number of destinations */ + cups_dest_t *dest; /* Destination pointer */ + const char *home; /* HOME environment variable */ + char filename[1024]; /* Local ~/.lpoptions file */ + const char *defprinter; /* Default printer */ + char name[1024], /* Copy of printer name */ + *instance; /* Pointer to instance name */ + int num_reals; /* Number of real queues */ + cups_dest_t *reals; /* Real queues */ + + + /* + * Initialize destination array... + */ + + num_dests = 0; + *dests = (cups_dest_t *)0; + + /* + * Grab the printers and classes... + */ + + num_dests = cups_get_sdests(CUPS_GET_PRINTERS, num_dests, dests); + num_dests = cups_get_sdests(CUPS_GET_CLASSES, num_dests, dests); + + /* + * Make a copy of the "real" queues for a later sanity check... + */ + + if (num_dests > 0) + { + num_reals = num_dests; + reals = calloc(num_reals, sizeof(cups_dest_t)); + + if (reals) + memcpy(reals, *dests, num_reals * sizeof(cups_dest_t)); + else + num_reals = 0; + } + else + { + num_reals = 0; + reals = NULL; + } + + /* + * Grab the default destination... + */ + + if ((defprinter = cupsGetDefault()) != NULL) + { + /* + * Grab printer and instance name... + */ + + strlcpy(name, defprinter, sizeof(name)); + + if ((instance = strchr(name, '/')) != NULL) + *instance++ = '\0'; + + /* + * Lookup the printer and instance and make it the default... + */ + + 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... + */ + + if ((home = getenv("CUPS_SERVERROOT")) != NULL) + { + snprintf(filename, sizeof(filename), "%s/lpoptions", home); + num_dests = cups_get_dests(filename, num_dests, dests); + } + else + num_dests = cups_get_dests(CUPS_SERVERROOT "/lpoptions", num_dests, dests); + + if ((home = getenv("HOME")) != NULL) + { + snprintf(filename, sizeof(filename), "%s/.lpoptions", home); + num_dests = cups_get_dests(filename, num_dests, dests); + } + + /* + * Validate the current default destination - this prevents old + * Default lines in /etc/cups/lpoptions and ~/.lpoptions from + * pointing to a non-existent printer or class... + */ + + if (num_reals) + { + /* + * See if we have a default printer... + */ + + if ((dest = cupsGetDest(NULL, NULL, num_dests, *dests)) != NULL) + { + /* + * Have a default; see if it is real... + */ + + dest = cupsGetDest(dest->name, NULL, num_reals, reals); + } + + /* + * If dest is NULL, then no default (that exists) is set, so we + * need to set a default if one exists... + */ + + if (dest == NULL && defprinter != NULL) + { + for (i = 0; i < num_dests; i ++) + (*dests)[i].is_default = 0; + + if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL) + dest->is_default = 1; + } + + /* + * Free memory... + */ + + free(reals); + } + + /* + * Return the number of destinations... + */ + + return (num_dests); +} + + +/* + * 'cupsSetDests()' - Set the list of destinations. + */ + +void +cupsSetDests(int num_dests, /* I - Number of destinations */ + cups_dest_t *dests) /* I - Destinations */ +{ + int i, j; /* Looping vars */ + int wrote; /* Wrote definition? */ + cups_dest_t *dest; /* Current destination */ + cups_option_t *option; /* Current option */ + FILE *fp; /* File pointer */ + const char *home; /* HOME environment variable */ + char filename[1024]; /* lpoptions file */ + int num_temps; /* Number of temporary destinations */ + cups_dest_t *temps, /* Temporary destinations */ + *temp; /* Current temporary dest */ + const char *val; /* Value of temporary option */ + + + /* + * Get the server destinations... + */ + + num_temps = cups_get_sdests(CUPS_GET_PRINTERS, 0, &temps); + num_temps = cups_get_sdests(CUPS_GET_CLASSES, num_temps, &temps); + + /* + * Figure out which file to write to... + */ + + if ((home = getenv("CUPS_SERVERROOT")) != NULL) + snprintf(filename, sizeof(filename), "%s/lpoptions", home); + else + strcpy(filename, CUPS_SERVERROOT "/lpoptions"); + +#ifndef WIN32 + if (getuid()) + { + /* + * Merge in server defaults... + */ + + num_temps = cups_get_dests(filename, num_temps, &temps); + + /* + * Point to user defaults... + */ + + if ((home = getenv("HOME")) != NULL) + snprintf(filename, sizeof(filename), "%s/.lpoptions", home); + } +#endif /* !WIN32 */ + + /* + * Try to open the file... + */ + + if ((fp = fopen(filename, "w")) == NULL) + { + cupsFreeDests(num_temps, temps); + return; + } + + /* + * Write each printer; each line looks like: + * + * Dest name[/instance] options + * Default name[/instance] options + */ + + for (i = num_dests, dest = dests; i > 0; i --, dest ++) + if (dest->instance != NULL || dest->num_options != 0 || dest->is_default) + { + if (dest->is_default) + { + fprintf(fp, "Default %s", dest->name); + if (dest->instance) + fprintf(fp, "/%s", dest->instance); + + wrote = 1; + } + else + wrote = 0; + + if ((temp = cupsGetDest(dest->name, dest->instance, num_temps, temps)) == NULL) + temp = cupsGetDest(dest->name, NULL, num_temps, temps); + + for (j = dest->num_options, option = dest->options; j > 0; j --, option ++) + { + /* + * See if the server/global options match these; if so, don't + * write 'em. + */ + + if (temp && (val = cupsGetOption(option->name, temp->num_options, + temp->options)) != NULL) + { + if (strcasecmp(val, option->value) == 0) + continue; + } + + /* + * Options don't match, write to the file... + */ + + if (!wrote) + { + fprintf(fp, "Dest %s", dest->name); + if (dest->instance) + fprintf(fp, "/%s", dest->instance); + wrote = 1; + } + + if (option->value[0]) + { + if (strchr(option->value, ' ') != NULL) + fprintf(fp, " %s=\"%s\"", option->name, option->value); + else + fprintf(fp, " %s=%s", option->name, option->value); + } + else + fprintf(fp, " %s", option->name); + } + + if (wrote) + fputs("\n", fp); + } + + /* + * Free the temporary destinations... + */ + + cupsFreeDests(num_temps, temps); + + /* + * Close the file and return... + */ + + fclose(fp); +} + + +/* + * 'cups_get_dests()' - Get destinations from a file. + */ + +static int /* O - Number of destinations */ +cups_get_dests(const char *filename, /* I - File to read from */ + int num_dests, /* I - Number of destinations */ + cups_dest_t **dests) /* IO - Destinations */ +{ + int i; /* Looping var */ + cups_dest_t *dest; /* Current destination */ + FILE *fp; /* File pointer */ + char line[8192], /* Line from file */ + *lineptr, /* Pointer into line */ + *name, /* Name of destination/option */ + *instance; /* Instance of destination */ + const char *printer; /* PRINTER or LPDEST */ + + + /* + * Check environment variables... + */ + + if ((printer = getenv("LPDEST")) == NULL) + if ((printer = getenv("PRINTER")) != NULL) + if (strcmp(printer, "lp") == 0) + printer = NULL; + + /* + * Try to open the file... + */ + + if ((fp = fopen(filename, "r")) == NULL) + return (num_dests); + + /* + * Read each printer; each line looks like: + * + * Dest name[/instance] options + * Default name[/instance] options + */ + + while (fgets(line, sizeof(line), fp) != NULL) + { + /* + * See what type of line it is... + */ + + if (strncasecmp(line, "dest", 4) == 0 && isspace(line[4])) + lineptr = line + 4; + else if (strncasecmp(line, "default", 7) == 0 && isspace(line[7])) + lineptr = line + 7; + else + continue; + + /* + * Skip leading whitespace... + */ + + while (isspace(*lineptr)) + lineptr ++; + + if (!*lineptr) + continue; + + name = lineptr; + + /* + * Search for an instance... + */ + + while (!isspace(*lineptr) && *lineptr && *lineptr != '/') + lineptr ++; + + if (!*lineptr) + continue; + + if (*lineptr == '/') + { + /* + * Found an instance... + */ + + *lineptr++ = '\0'; + instance = lineptr; + + /* + * Search for an instance... + */ + + while (!isspace(*lineptr) && *lineptr) + lineptr ++; + } + else + instance = NULL; + + *lineptr++ = '\0'; + + /* + * See if the primary instance of the destination exists; if not, + * ignore this entry and move on... + */ + + if (cupsGetDest(name, NULL, num_dests, *dests) == NULL) + continue; + + /* + * Add the destination... + */ + + num_dests = cupsAddDest(name, instance, num_dests, dests); + + if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL) + { + /* + * Out of memory! + */ + + fclose(fp); + return (num_dests); + } + + /* + * Add options until we hit the end of the line... + */ + + dest->num_options = cupsParseOptions(lineptr, dest->num_options, + &(dest->options)); + + /* + * Set this as default if needed... + */ + + if (strncasecmp(line, "default", 7) == 0 && printer == NULL) + { + for (i = 0; i < num_dests; i ++) + (*dests)[i].is_default = 0; + + dest->is_default = 1; + } + } + + /* + * Close the file and return... + */ + + fclose(fp); + + return (num_dests); +} + + +/* + * '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$". + */ diff --git a/cups/emit.c b/cups/emit.c new file mode 100644 index 0000000000..6c6486e7f2 --- /dev/null +++ b/cups/emit.c @@ -0,0 +1,548 @@ +/* + * "$Id$" + * + * PPD code emission routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * ppdCollect() - Collect all marked options that reside in the + * specified section. + * ppdEmit() - Emit code for marked options to a file. + * ppdEmitFd() - Emit code for marked options to a file. + * ppdEmitJCL() - Emit code for JCL options to a file. + * ppd_handle_media() - Handle media selection... + * ppd_sort() - Sort options by ordering numbers... + */ + +/* + * Include necessary headers... + */ + +#include "ppd.h" +#include +#include "string.h" + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * Local functions... + */ + +static void ppd_handle_media(ppd_file_t *ppd); +static int ppd_sort(ppd_choice_t **c1, ppd_choice_t **c2); + + +/* + * Local globals... + */ + +static const char *ppd_custom_code = + "pop pop pop\n" + "<>setpagedevice\n"; + + +/* + * 'ppdCollect()' - Collect all marked options that reside in the specified + * section. + */ + +int /* O - Number of options marked */ +ppdCollect(ppd_file_t *ppd, /* I - PPD file data */ + ppd_section_t section, /* I - Section to collect */ + ppd_choice_t ***choices) /* O - Pointers to choices */ +{ + int i, j, k, m; /* Looping vars */ + ppd_group_t *g, /* Current group */ + *sg; /* Current sub-group */ + ppd_option_t *o; /* Current option */ + ppd_choice_t *c; /* Current choice */ + int count; /* Number of choices collected */ + ppd_choice_t **collect; /* Collected choices */ + + + if (ppd == NULL) + return (0); + + /* + * Allocate memory for up to 1000 selected choices... + */ + + count = 0; + collect = calloc(sizeof(ppd_choice_t *), 1000); + + /* + * Loop through all options and add choices as needed... + */ + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + { + for (j = g->num_options, o = g->options; j > 0; j --, o ++) + if (o->section == section) + for (k = o->num_choices, c = o->choices; k > 0; k --, c ++) + if (c->marked && count < 1000) + { + collect[count] = c; + count ++; + } + + for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++) + for (k = sg->num_options, o = sg->options; k > 0; k --, o ++) + if (o->section == section) + for (m = o->num_choices, c = o->choices; m > 0; m --, c ++) + if (c->marked && count < 1000) + { + collect[count] = c; + count ++; + } + } + + /* + * If we have more than 1 marked choice, sort them... + */ + + if (count > 1) + qsort(collect, count, sizeof(ppd_choice_t *), + (int (*)(const void *, const void *))ppd_sort); + + /* + * Return the array and number of choices; if 0, free the array since + * it isn't needed. + */ + + if (count > 0) + { + *choices = collect; + return (count); + } + else + { + *choices = NULL; + free(collect); + return (0); + } +} + + +/* + * 'ppdEmit()' - Emit code for marked options to a file. + */ + +int /* O - 0 on success, -1 on failure */ +ppdEmit(ppd_file_t *ppd, /* I - PPD file record */ + FILE *fp, /* I - File to write to */ + ppd_section_t section) /* I - Section to write */ +{ + int i, /* Looping var */ + count; /* Number of choices */ + ppd_choice_t **choices; /* Choices */ + ppd_size_t *size; /* Custom page size */ + + + /* + * Use PageSize or PageRegion as required... + */ + + ppd_handle_media(ppd); + + /* + * Collect the options we need to emit and emit them! + */ + + if ((count = ppdCollect(ppd, section, &choices)) == 0) + return (0); + + for (i = 0; i < count; i ++) + if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + { + /* + * Send wrapper commands to prevent printer errors for unsupported + * options... + */ + + if (fputs("[{\n", fp) < 0) + { + free(choices); + return (-1); + } + + /* + * Send DSC comments with option... + */ + + if (fprintf(fp, "%%%%BeginFeature: *%s %s\n", + ((ppd_option_t *)choices[i]->option)->keyword, + choices[i]->choice) < 0) + { + free(choices); + return (-1); + } + + if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 || + strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) && + strcasecmp(choices[i]->choice, "Custom") == 0) + { + /* + * Variable size; write out standard size options (this should + * eventually be changed to use the parameter positions defined + * in the PPD file...) + */ + + size = ppdPageSize(ppd, "Custom"); + fprintf(fp, "%.0f %.0f 0 0 0\n", size->width, size->length); + + if (choices[i]->code == NULL) + { + /* + * This can happen with certain buggy PPD files that don't include + * a CustomPageSize command sequence... We just use a generic + * Level 2 command sequence... + */ + + fputs(ppd_custom_code, fp); + } + } + + if (choices[i]->code != NULL && choices[i]->code[0] != '\0') + { + if (fputs(choices[i]->code, fp) < 0) + { + free(choices); + return (-1); + } + + if (choices[i]->code[strlen(choices[i]->code) - 1] != '\n') + putc('\n', fp); + } + + if (fputs("%%EndFeature\n", fp) < 0) + { + free(choices); + return (-1); + } + + if (fputs("} stopped cleartomark\n", fp) < 0) + { + free(choices); + return (-1); + } + } + else if (fputs(choices[i]->code, fp) < 0) + { + free(choices); + return (-1); + } + + free(choices); + return (0); +} + + +/* + * 'ppdEmitFd()' - Emit code for marked options to a file. + */ + +int /* O - 0 on success, -1 on failure */ +ppdEmitFd(ppd_file_t *ppd, /* I - PPD file record */ + int fd, /* I - File to write to */ + ppd_section_t section) /* I - Section to write */ +{ + int i, /* Looping var */ + count; /* Number of choices */ + ppd_choice_t **choices; /* Choices */ + ppd_size_t *size; /* Custom page size */ + char buf[1024]; /* Output buffer for feature */ + + + /* + * Use PageSize or PageRegion as required... + */ + + ppd_handle_media(ppd); + + /* + * Collect the options we need to emit and emit them! + */ + + if ((count = ppdCollect(ppd, section, &choices)) == 0) + return (0); + + for (i = 0; i < count; i ++) + if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + { + /* + * Send wrapper commands to prevent printer errors for unsupported + * options... + */ + + if (write(fd, "[{\n", 3) < 1) + { + free(choices); + return (-1); + } + + /* + * Send DSC comments with option... + */ + + snprintf(buf, sizeof(buf), "%%%%BeginFeature: *%s %s\n", + ((ppd_option_t *)choices[i]->option)->keyword, + choices[i]->choice); + + if (write(fd, buf, strlen(buf)) < 1) + { + free(choices); + return (-1); + } + + if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 || + strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) && + strcasecmp(choices[i]->choice, "Custom") == 0) + { + /* + * Variable size; write out standard size options (this should + * eventually be changed to use the parameter positions defined + * in the PPD file...) + */ + + size = ppdPageSize(ppd, "Custom"); + snprintf(buf, sizeof(buf), "%.0f %.0f 0 0 0\n", size->width, + size->length); + + if (write(fd, buf, strlen(buf)) < 1) + { + free(choices); + return (-1); + } + + if (choices[i]->code == NULL) + { + /* + * This can happen with certain buggy PPD files that don't include + * a CustomPageSize command sequence... We just use a generic + * Level 2 command sequence... + */ + + if (write(fd, ppd_custom_code, strlen(ppd_custom_code)) < 1) + { + free(choices); + return (-1); + } + } + } + + if (choices[i]->code != NULL && choices[i]->code[0] != '\0') + { + if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1) + { + free(choices); + return (-1); + } + } + + if (write(fd, "%%EndFeature\n", 13) < 1) + { + free(choices); + return (-1); + } + + if (write(fd, "} stopped cleartomark\n", 22) < 1) + { + free(choices); + return (-1); + } + } + else if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1) + { + free(choices); + return (-1); + } + + free(choices); + return (0); +} + + +/* + * 'ppdEmitJCL()' - Emit code for JCL options to a file. + */ + +int /* O - 0 on success, -1 on failure */ +ppdEmitJCL(ppd_file_t *ppd, /* I - PPD file record */ + FILE *fp, /* I - File to write to */ + int job_id, /* I - Job ID */ + const char *user, /* I - Username */ + const char *title) /* I - Title */ +{ + const char *ptr; /* Pointer into JCL string */ + + + /* + * Range check the input... + */ + + if (ppd == NULL || ppd->jcl_begin == NULL || ppd->jcl_ps == NULL) + return (0); + + /* + * See if the printer supports HP PJL... + */ + + if (strncmp(ppd->jcl_begin, "\033%-12345X@", 10) == 0) + { + /* + * This printer uses HP PJL commands for output; filter the output + * so that we only have a single "@PJL JOB" command in the header... + */ + + fputs("\033%-12345X", fp); + for (ptr = ppd->jcl_begin + 9; *ptr;) + if (strncmp(ptr, "@PJL JOB", 8) == 0) + { + /* + * Skip job command... + */ + + for (;*ptr; ptr ++) + if (*ptr == '\n') + break; + + if (*ptr) + ptr ++; + } + else + { + /* + * Copy line... + */ + + for (;*ptr; ptr ++) + { + putc(*ptr, fp); + if (*ptr == '\n') + break; + } + + if (*ptr) + ptr ++; + } + + /* + * Eliminate any path info from the job title... + */ + + if ((ptr = strrchr(title, '/')) != NULL) + title = ptr + 1; + + /* + * Send PJL JOB command before we enter PostScript mode... + */ + + fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%d %s %s\"\n", title, + job_id, user, title); + } + else + fputs(ppd->jcl_begin, stdout); + + ppdEmit(ppd, stdout, PPD_ORDER_JCL); + fputs(ppd->jcl_ps, stdout); + + return (0); +} + + +/* + * 'ppd_handle_media()' - Handle media selection... + */ + +static void +ppd_handle_media(ppd_file_t *ppd) +{ + ppd_choice_t *manual_feed, /* ManualFeed choice, if any */ + *input_slot; /* InputSlot choice, if any */ + ppd_size_t *size; /* Current media size */ + + + /* + * This function determines if the user has selected a media source + * via the InputSlot or ManualFeed options; if so, it marks the + * PageRegion option corresponding to the current media size. + * Otherwise it marks the PageSize option. + */ + + if ((size = ppdPageSize(ppd, NULL)) == NULL) + return; + + manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed"); + input_slot = ppdFindMarkedChoice(ppd, "InputSlot"); + + if (strcasecmp(size->name, "Custom") == 0 || + (manual_feed == NULL && input_slot == NULL) || + (manual_feed != NULL && strcasecmp(manual_feed->choice, "False") == 0) || + (input_slot != NULL && (input_slot->code == NULL || !input_slot->code[0]))) + { + /* + * Manual feed was not selected and/or the input slot selection does + * not contain any PostScript code. Use the PageSize option... + */ + + ppdMarkOption(ppd, "PageSize", size->name); + } + else + { + /* + * Manual feed was selected and/or the input slot selection contains + * PostScript code. Use the PageRegion option... + */ + + ppdMarkOption(ppd, "PageRegion", size->name); + } +} + + +/* + * 'ppd_sort()' - Sort options by ordering numbers... + */ + +static int /* O - -1 if c1 < c2, 0 if equal, 1 otherwise */ +ppd_sort(ppd_choice_t **c1, /* I - First choice */ + ppd_choice_t **c2) /* I - Second choice */ +{ + if (((ppd_option_t *)(*c1)->option)->order < ((ppd_option_t *)(*c2)->option)->order) + return (-1); + else if (((ppd_option_t *)(*c1)->option)->order > ((ppd_option_t *)(*c2)->option)->order) + return (1); + else + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/encode.c b/cups/encode.c new file mode 100644 index 0000000000..dd085e426c --- /dev/null +++ b/cups/encode.c @@ -0,0 +1,381 @@ +/* + * "$Id$" + * + * Option encoding routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsEncodeOptions() - Encode printer options into IPP attributes. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include +#include +#include "string.h" +#include "debug.h" + + +/* + * Local list of option names and the value tags they should use... + */ + +typedef struct +{ + const char *name; + ipp_tag_t value_tag; +} ipp_option_t; + +static ipp_option_t ipp_options[] = + { + { "blackplot", IPP_TAG_BOOLEAN }, + { "brightness", IPP_TAG_INTEGER }, + { "columns", IPP_TAG_INTEGER }, + { "copies", IPP_TAG_INTEGER }, + { "finishings", IPP_TAG_ENUM }, + { "fitplot", IPP_TAG_BOOLEAN }, + { "gamma", IPP_TAG_INTEGER }, + { "hue", IPP_TAG_INTEGER }, + { "job-priority", IPP_TAG_INTEGER }, + { "landscape", IPP_TAG_BOOLEAN }, + { "mirror", IPP_TAG_BOOLEAN }, + { "natural-scaling", IPP_TAG_INTEGER }, + { "number-up", IPP_TAG_INTEGER }, + { "orientation-requested", IPP_TAG_ENUM }, + { "page-bottom", IPP_TAG_INTEGER }, + { "page-left", IPP_TAG_INTEGER }, + { "page-ranges", IPP_TAG_RANGE }, + { "page-right", IPP_TAG_INTEGER }, + { "page-top", IPP_TAG_INTEGER }, + { "penwidth", IPP_TAG_INTEGER }, + { "ppi", IPP_TAG_INTEGER }, + { "prettyprint", IPP_TAG_BOOLEAN }, + { "printer-resolution", IPP_TAG_RESOLUTION }, + { "print-quality", IPP_TAG_ENUM }, + { "saturation", IPP_TAG_INTEGER }, + { "scaling", IPP_TAG_INTEGER }, + { "wrap", IPP_TAG_BOOLEAN } + }; + + +/* + * 'cupsEncodeOptions()' - Encode printer options into IPP attributes. + */ + +void +cupsEncodeOptions(ipp_t *ipp, /* I - Request to add to */ + int num_options, /* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i, j; /* Looping vars */ + int count; /* Number of values */ + char *s, /* Pointer into option value */ + *val, /* Pointer to option value */ + *copy, /* Copy of option value */ + *sep; /* Option separator */ + ipp_attribute_t *attr; /* IPP job-id attribute */ + + + DEBUG_printf(("cupsEncodeOptions(%p, %d, %p)\n", ipp, num_options, options)); + + if (ipp == NULL || num_options < 1 || options == NULL) + return; + + /* + * Handle the document format stuff first... + */ + + if ((val = (char *)cupsGetOption("document-format", num_options, options)) != NULL) + ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, val); + else if (cupsGetOption("raw", num_options, options)) + ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/vnd.cups-raw"); + else + ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/octet-stream"); + + /* + * Then add all other options... + */ + + for (i = 0; i < num_options; i ++) + { + /* + * Skip document format options - handled above... + */ + + if (strcasecmp(options[i].name, "raw") == 0 || + strcasecmp(options[i].name, "document-format") == 0 || + !options[i].name[0]) + continue; + + /* + * Count the number of values... + */ + + for (count = 1, sep = options[i].value; *sep; sep ++) + { + if (*sep == '\'') + { + /* + * Skip quoted option value... + */ + + sep ++; + + while (*sep && *sep != '\'') + sep ++; + + if (!*sep) + sep --; + } + else if (*sep == '\"') + { + /* + * Skip quoted option value... + */ + + sep ++; + + while (*sep && *sep != '\"') + sep ++; + + if (!*sep) + sep --; + } + else if (*sep == ',') + count ++; + else if (*sep == '\\' && sep[1]) + sep ++; + } + + DEBUG_printf(("cupsEncodeOptions: option = \'%s\', count = %d\n", + options[i].name, count)); + + /* + * Allocate memory for the attribute values... + */ + + if ((attr = _ipp_add_attr(ipp, count)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for attributes!"); + return; + } + + /* + * Now figure out what type of value we have... + */ + + attr->group_tag = IPP_TAG_JOB; + + if (strcasecmp(options[i].value, "true") == 0 || + strcasecmp(options[i].value, "false") == 0) + attr->value_tag = IPP_TAG_BOOLEAN; + else + attr->value_tag = IPP_TAG_NAME; + + for (j = 0; j < (int)(sizeof(ipp_options) / sizeof(ipp_options[0])); j ++) + if (strcasecmp(options[i].name, ipp_options[j].name) == 0) + { + attr->value_tag = ipp_options[j].value_tag; + break; + } + + /* + * Copy the name over... + */ + + if ((attr->name = strdup(options[i].name)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for name!"); + return; + } + + if (count > 1) + { + /* + * Make a copy of the value we can fiddle with... + */ + + if ((copy = strdup(options[i].value)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for value copy!"); + return; + } + + val = copy; + } + else + { + /* + * Since we have a single value, use the value directly... + */ + + val = options[i].value; + copy = NULL; + } + + /* + * Scan the value string for values... + */ + + for (j = 0; *val != '\0' || j == 0; val = sep, j ++) + { + /* + * Find the end of this value and mark it if needed... + */ + + if ((sep = strchr(val, ',')) != NULL) + *sep++ = '\0'; + else + sep = val + strlen(val); + + /* + * Copy the option value(s) over as needed by the type... + */ + + switch (attr->value_tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + /* + * Integer/enumeration value... + */ + + attr->values[j].integer = strtol(val, &s, 0); + + DEBUG_printf(("cupsEncodeOptions: Adding integer option value %d...\n", + attr->values[j].integer)); + break; + + case IPP_TAG_BOOLEAN : + if (strcasecmp(val, "true") == 0) + { + /* + * Boolean value - true... + */ + + attr->values[j].boolean = 1; + + DEBUG_puts("cupsEncodeOptions: Added boolean true value..."); + } + else + { + /* + * Boolean value - false... + */ + + attr->values[j].boolean = 0; + + DEBUG_puts("cupsEncodeOptions: Added boolean false value..."); + } + break; + + case IPP_TAG_RANGE : + /* + * Range... + */ + + if (*val == '-') + { + attr->values[j].range.lower = 1; + s = val; + } + else + attr->values[j].range.lower = strtol(val, &s, 0); + + if (*s == '-') + { + if (s[1]) + attr->values[j].range.upper = strtol(s + 1, NULL, 0); + else + attr->values[j].range.upper = 2147483647; + } + else + attr->values[j].range.upper = attr->values[j].range.lower; + + DEBUG_printf(("cupsEncodeOptions: Added range option value %d-%d...\n", + attr->values[j].range.lower, + attr->values[j].range.upper)); + break; + + case IPP_TAG_RESOLUTION : + /* + * Resolution... + */ + + attr->values[j].resolution.xres = strtol(val, &s, 0); + + if (*s == 'x') + attr->values[j].resolution.yres = strtol(s + 1, &s, 0); + else + attr->values[j].resolution.yres = attr->values[j].resolution.xres; + + if (strcasecmp(s, "dpc") == 0) + attr->values[j].resolution.units = IPP_RES_PER_CM; + else + attr->values[j].resolution.units = IPP_RES_PER_INCH; + + DEBUG_printf(("cupsEncodeOptions: Adding resolution option value %s...\n", + val)); + break; + + default : + if ((attr->values[j].string.text = strdup(val)) == NULL) + { + /* + * Ran out of memory! + */ + + DEBUG_puts("cupsEncodeOptions: Ran out of memory for string!"); + return; + } + + DEBUG_printf(("cupsEncodeOptions: Added string value \'%s\'...\n", + val)); + break; + } + } + } +} + + +/* + * End of "$Id$". + */ diff --git a/cups/http-addr.c b/cups/http-addr.c new file mode 100644 index 0000000000..7abb1a67dd --- /dev/null +++ b/cups/http-addr.c @@ -0,0 +1,118 @@ +/* + * "$Id$" + * + * HTTP host/address routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * httpGetHostByName() - Lookup a hostname or IP address, and return + * address records for the specified name. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include "string.h" + +#include "http.h" + + +/* + * '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 */ +{ + const char *nameptr; /* Pointer into name */ + 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 */ + +#if defined(__APPLE__) + /* OS X hack to avoid it's ocassional long delay in lookupd */ + static char sLoopback[] = "127.0.0.1"; + if (strcmp(name, "localhost") == 0) + name = sLoopback; +#endif /* __APPLE__ */ + + /* + * 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. + */ + + for (nameptr = name; isdigit(*nameptr) || *nameptr == '.'; nameptr ++); + + if (!*nameptr) + { + /* + * 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)); + } +} + + +/* + * End of "$Id$". + */ diff --git a/cups/http-support.c b/cups/http-support.c new file mode 100644 index 0000000000..36632ed799 --- /dev/null +++ b/cups/http-support.c @@ -0,0 +1,317 @@ +/* + * "$Id$" + * + * HTTP support routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * httpSeparate() - Separate a Universal Resource Identifier into its + * components. + * httpStatus() - Return a short string describing a HTTP status code. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include "string.h" + +#include "http.h" +#include "ipp.h" + + +/* + * 'httpSeparate()' - Separate a Universal Resource Identifier into its + * components. + */ + +void +httpSeparate(const char *uri, /* I - Universal Resource Identifier */ + char *method, /* O - Method [32] (http, https, etc.) */ + char *username, /* O - Username [32] */ + char *host, /* O - Hostname [32] */ + int *port, /* O - Port number to use */ + char *resource) /* O - Resource/filename [1024] */ +{ + char *ptr; /* Pointer into string... */ + const char *atsign, /* @ sign */ + *slash; /* Separator */ + char safeuri[HTTP_MAX_URI]; /* "Safe" local copy of URI */ + char quoted; /* Quoted character */ + + + /* + * Range check input... + */ + + if (uri == NULL || method == NULL || username == NULL || host == NULL || + port == NULL || resource == NULL) + return; + + /* + * Copy the URL to a local string to make sure we don't have a URL + * longer than HTTP_MAX_URI characters long... + */ + + strlcpy(safeuri, uri, sizeof(safeuri)); + + uri = safeuri; + + /* + * Grab the method portion of the URI... + */ + + if (strncmp(uri, "//", 2) == 0) + { + /* + * Workaround for HP IPP client bug... + */ + + strcpy(method, "ipp"); + } + else + { + /* + * Standard URI with method... + */ + + for (ptr = host; *uri != ':' && *uri != '\0'; uri ++) + if (ptr < (host + HTTP_MAX_URI - 1)) + *ptr++ = *uri; + + *ptr = '\0'; + if (*uri == ':') + uri ++; + + /* + * If the method contains a period or slash, then it's probably + * hostname/filename... + */ + + if (strchr(host, '.') != NULL || strchr(host, '/') != NULL || *uri == '\0') + { + if ((ptr = strchr(host, '/')) != NULL) + { + strlcpy(resource, ptr, HTTP_MAX_URI); + *ptr = '\0'; + } + else + resource[0] = '\0'; + + if (isdigit(*uri)) + { + /* + * OK, we have "hostname:port[/resource]"... + */ + + *port = strtol(uri, (char **)&uri, 10); + + if (*uri == '/') + strlcpy(resource, uri, HTTP_MAX_URI); + } + else + *port = 631; + + strcpy(method, "http"); + username[0] = '\0'; + return; + } + else + strlcpy(method, host, 32); + } + + /* + * If the method starts with less than 2 slashes then it is a local resource... + */ + + if (strncmp(uri, "//", 2) != 0) + { + strlcpy(resource, uri, HTTP_MAX_URI); + + username[0] = '\0'; + host[0] = '\0'; + *port = 0; + return; + } + + /* + * Grab the username, if any... + */ + + while (*uri == '/') + uri ++; + + if ((slash = strchr(uri, '/')) == NULL) + slash = uri + strlen(uri); + + if ((atsign = strchr(uri, '@')) != NULL && atsign < slash) + { + /* + * Got a username:password combo... + */ + + for (ptr = username; uri < atsign; uri ++) + if (ptr < (username + HTTP_MAX_URI - 1)) + { + if (*uri == '%' && isxdigit(uri[1]) && isxdigit(uri[2])) + { + /* + * Grab a hex-encoded username and password... + */ + + uri ++; + if (isalpha(*uri)) + quoted = (tolower(*uri) - 'a' + 10) << 4; + else + quoted = (*uri - '0') << 4; + + uri ++; + if (isalpha(*uri)) + quoted |= tolower(*uri) - 'a' + 10; + else + quoted |= *uri - '0'; + + *ptr++ = quoted; + } + else + *ptr++ = *uri; + } + + *ptr = '\0'; + + uri = atsign + 1; + } + else + username[0] = '\0'; + + /* + * Grab the hostname... + */ + + for (ptr = host; *uri != ':' && *uri != '/' && *uri != '\0'; uri ++) + if (ptr < (host + HTTP_MAX_URI - 1)) + *ptr++ = *uri; + + *ptr = '\0'; + + if (*uri != ':') + { + if (strcasecmp(method, "http") == 0) + *port = 80; + else if (strcasecmp(method, "https") == 0) + *port = 443; + else if (strcasecmp(method, "ipp") == 0) + *port = ippPort(); + else if (strcasecmp(method, "socket") == 0) /* Not registered yet... */ + *port = 9100; + else + *port = 0; + } + else + { + /* + * Parse port number... + */ + + *port = 0; + uri ++; + while (isdigit(*uri)) + { + *port = (*port * 10) + *uri - '0'; + uri ++; + } + } + + if (*uri == '\0') + { + /* + * Hostname but no port or path... + */ + + resource[0] = '/'; + resource[1] = '\0'; + return; + } + + /* + * The remaining portion is the resource string... + */ + + strlcpy(resource, uri, HTTP_MAX_URI); +} + + +/* + * 'httpStatus()' - Return a short string describing a HTTP status code. + */ + +const char * /* O - String or NULL */ +httpStatus(http_status_t status) /* I - HTTP status code */ +{ + switch (status) + { + case HTTP_CONTINUE : + return ("Continue"); + case HTTP_SWITCHING_PROTOCOLS : + return ("Switching Protocols"); + case HTTP_OK : + return ("OK"); + case HTTP_CREATED : + return ("Created"); + case HTTP_ACCEPTED : + return ("Accepted"); + case HTTP_NO_CONTENT : + return ("No Content"); + case HTTP_NOT_MODIFIED : + return ("Not Modified"); + case HTTP_BAD_REQUEST : + return ("Bad Request"); + case HTTP_UNAUTHORIZED : + return ("Unauthorized"); + case HTTP_FORBIDDEN : + return ("Forbidden"); + case HTTP_NOT_FOUND : + return ("Not Found"); + case HTTP_REQUEST_TOO_LARGE : + return ("Request Entity Too Large"); + case HTTP_URI_TOO_LONG : + return ("URI Too Long"); + case HTTP_UPGRADE_REQUIRED : + return ("Upgrade Required"); + case HTTP_NOT_IMPLEMENTED : + return ("Not Implemented"); + case HTTP_NOT_SUPPORTED : + return ("Not Supported"); + default : + return ("Unknown"); + } +} + + +/* + * End of "$Id$". + */ diff --git a/cups/http.c b/cups/http.c new file mode 100644 index 0000000000..26e984c3eb --- /dev/null +++ b/cups/http.c @@ -0,0 +1,2007 @@ +/* + * "$Id$" + * + * HTTP routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * httpInitialize() - Initialize the HTTP interface library and set the + * default HTTP proxy (if any). + * httpCheck() - Check to see if there is a pending response from + * the server. + * httpClose() - Close an HTTP connection... + * httpConnect() - Connect to a HTTP server. + * httpConnectEncrypt() - Connect to a HTTP server using encryption. + * httpEncryption() - Set the required encryption on the link. + * httpReconnect() - Reconnect to a HTTP server... + * httpGetSubField() - Get a sub-field value. + * httpSetField() - Set the value of an HTTP header. + * httpDelete() - Send a DELETE request to the server. + * httpGet() - Send a GET request to the server. + * httpHead() - Send a HEAD request to the server. + * httpOptions() - Send an OPTIONS request to the server. + * httpPost() - Send a POST request to the server. + * httpPut() - Send a PUT request to the server. + * httpTrace() - Send an TRACE request to the server. + * httpFlush() - Flush data from a HTTP connection. + * httpRead() - Read data from a HTTP connection. + * httpWrite() - Write data to a HTTP connection. + * httpGets() - Get a line of text from a HTTP connection. + * httpPrintf() - Print a formatted string to a HTTP connection. + * httpGetDateString() - Get a formatted date/time string from a time value. + * httpGetDateTime() - Get a time value from a formatted date/time string. + * httpUpdate() - Update the current HTTP state for incoming data. + * httpDecode64() - Base64-decode a string. + * httpEncode64() - Base64-encode a string. + * httpGetLength() - Get the amount of data remaining from the + * content-length or transfer-encoding fields. + * http_field() - Return the field index for a field name. + * http_send() - Send a request with all fields and the trailing + * blank line. + * http_upgrade() - Force upgrade to TLS encryption. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include "string.h" +#include +#include + +#include "http.h" +#include "debug.h" + +#ifndef WIN32 +# include +#endif /* !WIN32 */ + +#ifdef HAVE_LIBSSL +# include +# include +# include +#endif /* HAVE_LIBSSL */ + + +/* + * Some operating systems have done away with the Fxxxx constants for + * the fcntl() call; this works around that "feature"... + */ + +#ifndef FNONBLK +# define FNONBLK O_NONBLOCK +#endif /* !FNONBLK */ + + +/* + * Local functions... + */ + +static http_field_t http_field(const char *name); +static int http_send(http_t *http, http_state_t request, + const char *uri); +#ifdef HAVE_LIBSSL +static int http_upgrade(http_t *http); +#endif /* HAVE_LIBSSL */ + + +/* + * Local globals... + */ + +static const char *http_fields[] = + { + "Accept-Language", + "Accept-Ranges", + "Authorization", + "Connection", + "Content-Encoding", + "Content-Language", + "Content-Length", + "Content-Location", + "Content-MD5", + "Content-Range", + "Content-Type", + "Content-Version", + "Date", + "Host", + "If-Modified-Since", + "If-Unmodified-since", + "Keep-Alive", + "Last-Modified", + "Link", + "Location", + "Range", + "Referer", + "Retry-After", + "Transfer-Encoding", + "Upgrade", + "User-Agent", + "WWW-Authenticate" + }; +static const char *days[7] = + { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + }; +static const char *months[12] = + { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + + +/* + * 'httpInitialize()' - Initialize the HTTP interface library and set the + * default HTTP proxy (if any). + */ + +void +httpInitialize(void) +{ +#ifdef HAVE_LIBSSL +# ifndef WIN32 + struct timeval curtime; /* Current time in microseconds */ +# endif // !WIN32 + int i; /* Looping var */ + unsigned char data[1024]; /* Seed data */ +#endif /* HAVE_LIBSSL */ + +#ifdef WIN32 + WSADATA winsockdata; /* WinSock data */ + static int initialized = 0;/* Has WinSock been initialized? */ + + + if (!initialized) + WSAStartup(MAKEWORD(1,1), &winsockdata); +#elif defined(HAVE_SIGSET) + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + struct sigaction action; /* POSIX sigaction data */ + + + /* + * Ignore SIGPIPE signals... + */ + + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* WIN32 */ + +#ifdef HAVE_LIBSSL + SSL_load_error_strings(); + SSL_library_init(); + + /* + * Using the current time is a dubious random seed, but on some systems + * it is the best we can do (on others, this seed isn't even used...) + */ + +#ifdef WIN32 +#else + gettimeofday(&curtime, NULL); + srand(curtime.tv_sec + curtime.tv_usec); +#endif // WIN32 + + for (i = 0; i < sizeof(data); i ++) + data[i] = rand(); /* Yes, this is a poor source of random data... */ + + RAND_seed(&data, sizeof(data)); +#endif /* HAVE_LIBSSL */ +} + + +/* + * 'httpCheck()' - Check to see if there is a pending response from the server. + */ + +int /* O - 0 = no data, 1 = data available */ +httpCheck(http_t *http) /* I - HTTP connection */ +{ + fd_set input; /* Input set for select() */ + struct timeval timeout; /* Timeout */ + + + /* + * First see if there is data in the buffer... + */ + + if (http == NULL) + return (0); + + if (http->used) + return (1); + + /* + * Then try doing a select() to poll the socket... + */ + + FD_ZERO(&input); + FD_SET(http->fd, &input); + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + return (select(http->fd + 1, &input, NULL, NULL, &timeout) > 0); +} + + +/* + * 'httpClose()' - Close an HTTP connection... + */ + +void +httpClose(http_t *http) /* I - Connection to close */ +{ +#ifdef HAVE_LIBSSL + SSL_CTX *context; /* Context for encryption */ + SSL *conn; /* Connection for encryption */ +#endif /* HAVE_LIBSSL */ + + + if (!http) + return; + +#ifdef HAVE_LIBSSL + if (http->tls) + { + conn = (SSL *)(http->tls); + context = SSL_get_SSL_CTX(conn); + + SSL_shutdown(conn); + SSL_CTX_free(context); + SSL_free(conn); + + http->tls = NULL; + } +#endif /* HAVE_LIBSSL */ + +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif /* WIN32 */ + + free(http); +} + + +/* + * 'httpConnect()' - Connect to a HTTP server. + */ + +http_t * /* O - New HTTP connection */ +httpConnect(const char *host, /* I - Host to connect to */ + int port) /* I - Port number */ +{ + http_encryption_t encrypt;/* Type of encryption to use */ + + + /* + * Set the default encryption status... + */ + + if (port == 443) + encrypt = HTTP_ENCRYPT_ALWAYS; + else + encrypt = HTTP_ENCRYPT_IF_REQUESTED; + + return (httpConnectEncrypt(host, port, encrypt)); +} + + +/* + * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption. + */ + +http_t * /* O - New HTTP connection */ +httpConnectEncrypt(const char *host, /* I - Host to connect to */ + int port, /* I - Port number */ + http_encryption_t encrypt) + /* I - Type of encryption to use */ +{ + int i; /* Looping var */ + http_t *http; /* New HTTP connection */ + struct hostent *hostaddr; /* Host address data */ + + + if (host == NULL) + return (NULL); + + httpInitialize(); + + /* + * Lookup the host... + */ + + if ((hostaddr = httpGetHostByName(host)) == NULL) + { + /* + * This hack to make users that don't have a localhost entry in + * their hosts file or DNS happy... + */ + + if (strcasecmp(host, "localhost") != 0) + return (NULL); + else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL) + return (NULL); + } + + /* + * Verify that it is an IPv4 address (IPv6 support will come in CUPS 1.2...) + */ + + if (hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4) + return (NULL); + + /* + * Allocate memory for the structure... + */ + + http = calloc(sizeof(http_t), 1); + if (http == NULL) + return (NULL); + + http->version = HTTP_1_1; + http->blocking = 1; + http->activity = time(NULL); + http->fd = -1; + + /* + * Copy the hostname and port and then "reconnect"... + */ + + strlcpy(http->hostname, host, sizeof(http->hostname)); + 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... + */ + + 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... + */ + + strlcpy(http->hostname, host, sizeof(http->hostname)); + + for (i = 0; hostaddr->h_addr_list[i]; i ++) + { + /* + * Load the address... + */ + + memcpy((char *)&(http->hostaddr.sin_addr), hostaddr->h_addr_list[i], + hostaddr->h_length); + + /* + * Connect to the remote system... + */ + + if (!httpReconnect(http)) + return (http); + } + + /* + * Could not connect to any known address - bail out! + */ + + free(http); + return (NULL); +} + + +/* + * 'httpEncryption()' - Set the required encryption on the link. + */ + +int /* O - -1 on error, 0 on success */ +httpEncryption(http_t *http, /* I - HTTP data */ + http_encryption_t e) /* I - New encryption preference */ +{ +#ifdef HAVE_LIBSSL + if (!http) + return (0); + + http->encryption = e; + + if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) || + (http->encryption == HTTP_ENCRYPT_NEVER && http->tls)) + return (httpReconnect(http)); + else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls) + return (http_upgrade(http)); + else + return (0); +#else + if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED) + return (-1); + else + return (0); +#endif /* HAVE_LIBSSL */ +} + + +/* + * 'httpReconnect()' - Reconnect to a HTTP server... + */ + +int /* O - 0 on success, non-zero on failure */ +httpReconnect(http_t *http) /* I - HTTP data */ +{ + int val; /* Socket option value */ +#ifdef HAVE_LIBSSL + SSL_CTX *context; /* Context for encryption */ + SSL *conn; /* Connection for encryption */ + + + if (http->tls) + { + conn = (SSL *)(http->tls); + context = SSL_get_SSL_CTX(conn); + + SSL_shutdown(conn); + SSL_CTX_free(context); + SSL_free(conn); + + http->tls = NULL; + } +#endif /* HAVE_LIBSSL */ + + /* + * Close any previously open socket... + */ + + if (http->fd >= 0) +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif /* WIN32 */ + + /* + * Create the socket and set options to allow reuse. + */ + + if ((http->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { +#ifdef WIN32 + http->error = WSAGetLastError(); +#else + http->error = errno; +#endif /* WIN32 */ + http->status = HTTP_ERROR; + return (-1); + } + +#ifdef FD_CLOEXEC + fcntl(http->fd, F_SETFD, FD_CLOEXEC); /* Close this socket when starting * + * other processes... */ +#endif /* FD_CLOEXEC */ + + val = 1; + setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); + +#ifdef SO_REUSEPORT + val = 1; + setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); +#endif /* SO_REUSEPORT */ + + /* + * Using TCP_NODELAY improves responsiveness, especially on systems + * with a slow loopback interface... Since we write large buffers + * when sending print files and requests, there shouldn't be any + * performance penalty for this... + */ + + val = 1; + setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + + /* + * Connect to the server... + */ + + if (connect(http->fd, (struct sockaddr *)&(http->hostaddr), + sizeof(http->hostaddr)) < 0) + { +#ifdef WIN32 + http->error = WSAGetLastError(); +#else + http->error = errno; +#endif /* WIN32 */ + http->status = HTTP_ERROR; + +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif + + http->fd = -1; + + return (-1); + } + + http->error = 0; + http->status = HTTP_CONTINUE; + +#ifdef HAVE_LIBSSL + if (http->encryption == HTTP_ENCRYPT_ALWAYS) + { + /* + * Always do encryption via SSL. + */ + + context = SSL_CTX_new(SSLv23_method()); + conn = SSL_new(context); + + SSL_set_fd(conn, http->fd); + if (SSL_connect(conn) != 1) + { + SSL_CTX_free(context); + SSL_free(conn); + +#ifdef WIN32 + http->error = WSAGetLastError(); +#else + http->error = errno; +#endif /* WIN32 */ + http->status = HTTP_ERROR; + +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif + + return (-1); + } + + http->tls = conn; + } + else if (http->encryption == HTTP_ENCRYPT_REQUIRED) + return (http_upgrade(http)); +#endif /* HAVE_LIBSSL */ + + return (0); +} + + +/* + * 'httpGetSubField()' - Get a sub-field value. + */ + +char * /* O - Value or NULL */ +httpGetSubField(http_t *http, /* I - HTTP data */ + http_field_t field, /* I - Field index */ + const char *name, /* I - Name of sub-field */ + char *value) /* O - Value string */ +{ + const char *fptr; /* Pointer into field */ + char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */ + *ptr; /* Pointer into string buffer */ + + + if (http == NULL || + field < HTTP_FIELD_ACCEPT_LANGUAGE || + field > HTTP_FIELD_WWW_AUTHENTICATE || + name == NULL || value == NULL) + return (NULL); + + DEBUG_printf(("httpGetSubField(%p, %d, \"%s\", %p)\n", + http, field, name, value)); + + for (fptr = http->fields[field]; *fptr;) + { + /* + * Skip leading whitespace... + */ + + while (isspace(*fptr)) + fptr ++; + + if (*fptr == ',') + { + fptr ++; + continue; + } + + /* + * Get the sub-field name... + */ + + for (ptr = temp; + *fptr && *fptr != '=' && !isspace(*fptr) && ptr < (temp + sizeof(temp) - 1); + *ptr++ = *fptr++); + + *ptr = '\0'; + + DEBUG_printf(("name = \"%s\"\n", temp)); + + /* + * Skip trailing chars up to the '='... + */ + + while (isspace(*fptr)) + fptr ++; + + if (!*fptr) + break; + + if (*fptr != '=') + continue; + + /* + * Skip = and leading whitespace... + */ + + fptr ++; + + while (isspace(*fptr)) + fptr ++; + + if (*fptr == '\"') + { + /* + * Read quoted string... + */ + + for (ptr = value, fptr ++; + *fptr && *fptr != '\"' && ptr < (value + HTTP_MAX_VALUE - 1); + *ptr++ = *fptr++); + + *ptr = '\0'; + + while (*fptr && *fptr != '\"') + fptr ++; + + if (*fptr) + fptr ++; + } + else + { + /* + * Read unquoted string... + */ + + for (ptr = value; + *fptr && !isspace(*fptr) && *fptr != ',' && ptr < (value + HTTP_MAX_VALUE - 1); + *ptr++ = *fptr++); + + *ptr = '\0'; + + while (*fptr && !isspace(*fptr) && *fptr != ',') + fptr ++; + } + + DEBUG_printf(("value = \"%s\"\n", value)); + + /* + * See if this is the one... + */ + + if (strcmp(name, temp) == 0) + return (value); + } + + value[0] = '\0'; + + return (NULL); +} + + +/* + * 'httpSetField()' - Set the value of an HTTP header. + */ + +void +httpSetField(http_t *http, /* I - HTTP data */ + http_field_t field, /* I - Field index */ + const char *value) /* I - Value */ +{ + if (http == NULL || + field < HTTP_FIELD_ACCEPT_LANGUAGE || + field > HTTP_FIELD_WWW_AUTHENTICATE || + value == NULL) + return; + + strlcpy(http->fields[field], value, HTTP_MAX_VALUE); +} + + +/* + * 'httpDelete()' - Send a DELETE request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpDelete(http_t *http, /* I - HTTP data */ + const char *uri) /* I - URI to delete */ +{ + return (http_send(http, HTTP_DELETE, uri)); +} + + +/* + * 'httpGet()' - Send a GET request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpGet(http_t *http, /* I - HTTP data */ + const char *uri) /* I - URI to get */ +{ + return (http_send(http, HTTP_GET, uri)); +} + + +/* + * 'httpHead()' - Send a HEAD request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpHead(http_t *http, /* I - HTTP data */ + const char *uri) /* I - URI for head */ +{ + return (http_send(http, HTTP_HEAD, uri)); +} + + +/* + * 'httpOptions()' - Send an OPTIONS request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpOptions(http_t *http, /* I - HTTP data */ + const char *uri) /* I - URI for options */ +{ + return (http_send(http, HTTP_OPTIONS, uri)); +} + + +/* + * 'httpPost()' - Send a POST request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpPost(http_t *http, /* I - HTTP data */ + const char *uri) /* I - URI for post */ +{ + httpGetLength(http); + + return (http_send(http, HTTP_POST, uri)); +} + + +/* + * 'httpPut()' - Send a PUT request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpPut(http_t *http, /* I - HTTP data */ + const char *uri) /* I - URI to put */ +{ + httpGetLength(http); + + return (http_send(http, HTTP_PUT, uri)); +} + + +/* + * 'httpTrace()' - Send an TRACE request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpTrace(http_t *http, /* I - HTTP data */ + const char *uri) /* I - URI for trace */ +{ + return (http_send(http, HTTP_TRACE, uri)); +} + + +/* + * 'httpFlush()' - Flush data from a HTTP connection. + */ + +void +httpFlush(http_t *http) /* I - HTTP data */ +{ + char buffer[8192]; /* Junk buffer */ + + + while (httpRead(http, buffer, sizeof(buffer)) > 0); +} + + +/* + * 'httpRead()' - Read data from a HTTP connection. + */ + +int /* O - Number of bytes read */ +httpRead(http_t *http, /* I - HTTP data */ + char *buffer, /* I - Buffer for data */ + int length) /* I - Maximum number of bytes */ +{ + int bytes; /* Bytes read */ + char len[32]; /* Length string */ + + + DEBUG_printf(("httpRead(%p, %p, %d)\n", http, buffer, length)); + + if (http == NULL || buffer == NULL) + return (-1); + + http->activity = time(NULL); + + if (length <= 0) + return (0); + + if (http->data_encoding == HTTP_ENCODE_CHUNKED && + http->data_remaining <= 0) + { + DEBUG_puts("httpRead: Getting chunk length..."); + + if (httpGets(len, sizeof(len), http) == NULL) + { + DEBUG_puts("httpRead: Could not get length!"); + return (0); + } + + http->data_remaining = strtol(len, NULL, 16); + } + + DEBUG_printf(("httpRead: data_remaining = %d\n", http->data_remaining)); + + if (http->data_remaining == 0) + { + /* + * A zero-length chunk ends a transfer; unless we are reading POST + * data, go idle... + */ + + if (http->data_encoding == HTTP_ENCODE_CHUNKED) + httpGets(len, sizeof(len), http); + + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + + return (0); + } + 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) + { +#ifdef WIN32 + http->error = WSAGetLastError(); + return (-1); +#else + if (errno != EINTR) + { + http->error = errno; + return (-1); + } +#endif /* WIN32 */ + } + else + return (0); + } + + if (http->used > 0) + { + if (length > http->used) + length = http->used; + + bytes = length; + + DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes)); + + memcpy(buffer, http->buffer, length); + http->used -= length; + + if (http->used > 0) + memmove(http->buffer, http->buffer + length, http->used); + } +#ifdef HAVE_LIBSSL + else if (http->tls) + bytes = SSL_read((SSL *)(http->tls), buffer, length); +#endif /* HAVE_LIBSSL */ + else + { + DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length)); + bytes = recv(http->fd, buffer, length, 0); + DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes)); + } + + if (bytes > 0) + http->data_remaining -= bytes; + else if (bytes < 0) + { +#ifdef WIN32 + http->error = WSAGetLastError(); +#else + if (errno == EINTR) + bytes = 0; + else + http->error = errno; +#endif /* WIN32 */ + } + + 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; + } + } + +#ifdef DEBUG + { + int i, j, ch; + printf("httpRead: Read %d bytes:\n", bytes); + for (i = 0; i < bytes; i += 16) + { + printf(" "); + + for (j = 0; j < 16 && (i + j) < bytes; j ++) + printf(" %02X", buffer[i + j] & 255); + + while (j < 16) + { + printf(" "); + j ++; + } + + printf(" "); + for (j = 0; j < 16 && (i + j) < bytes; j ++) + { + ch = buffer[i + j] & 255; + + if (ch < ' ' || ch == 127) + ch = '.'; + + putchar(ch); + } + putchar('\n'); + } + } +#endif /* DEBUG */ + + return (bytes); +} + + +/* + * 'httpWrite()' - Write data to a HTTP connection. + */ + +int /* O - Number of bytes written */ +httpWrite(http_t *http, /* I - HTTP data */ + const char *buffer, /* I - Buffer for data */ + int length) /* I - Number of bytes to write */ +{ + int tbytes, /* Total bytes sent */ + bytes; /* Bytes sent */ + + + if (http == NULL || buffer == NULL) + return (-1); + + http->activity = time(NULL); + + if (http->data_encoding == HTTP_ENCODE_CHUNKED) + { + if (httpPrintf(http, "%x\r\n", length) < 0) + return (-1); + + if (length == 0) + { + /* + * A zero-length chunk ends a transfer; unless we are sending POST + * data, go idle... + */ + + DEBUG_puts("httpWrite: changing states..."); + + if (http->state == HTTP_POST_RECV) + http->state ++; + else if (http->state == HTTP_PUT_RECV) + http->state = HTTP_STATUS; + else + http->state = HTTP_WAITING; + + if (httpPrintf(http, "\r\n") < 0) + return (-1); + + return (0); + } + } + + tbytes = 0; + + while (length > 0) + { +#ifdef HAVE_LIBSSL + if (http->tls) + bytes = SSL_write((SSL *)(http->tls), buffer, length); + else +#endif /* HAVE_LIBSSL */ + bytes = send(http->fd, buffer, length, 0); + + if (bytes < 0) + { +#ifdef WIN32 + if (WSAGetLastError() != http->error) + { + http->error = WSAGetLastError(); + continue; + } +#else + if (errno == EINTR) + continue; + else if (errno != http->error) + { + http->error = errno; + continue; + } +#endif /* WIN32 */ + + DEBUG_puts("httpWrite: error writing data...\n"); + + return (-1); + } + + buffer += bytes; + tbytes += bytes; + length -= bytes; + if (http->data_encoding == HTTP_ENCODE_LENGTH) + http->data_remaining -= bytes; + } + + if (http->data_encoding == HTTP_ENCODE_CHUNKED) + if (httpPrintf(http, "\r\n") < 0) + return (-1); + + if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH) + { + /* + * Finished with the transfer; unless we are sending POST data, go idle... + */ + + DEBUG_puts("httpWrite: changing states..."); + + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + } + +#ifdef DEBUG + { + int i, j, ch; + printf("httpWrite: wrote %d bytes: \n", tbytes); + for (i = 0, buffer -= tbytes; i < tbytes; i += 16) + { + printf(" "); + + for (j = 0; j < 16 && (i + j) < tbytes; j ++) + printf(" %02X", buffer[i + j] & 255); + + while (j < 16) + { + printf(" "); + j ++; + } + + printf(" "); + for (j = 0; j < 16 && (i + j) < tbytes; j ++) + { + ch = buffer[i + j] & 255; + + if (ch < ' ' || ch == 127) + ch = '.'; + + putchar(ch); + } + putchar('\n'); + } + } +#endif /* DEBUG */ + return (tbytes); +} + + +/* + * 'httpGets()' - Get a line of text from a HTTP connection. + */ + +char * /* O - Line or NULL */ +httpGets(char *line, /* I - Line to read into */ + int length, /* I - Max length of buffer */ + http_t *http) /* I - HTTP data */ +{ + char *lineptr, /* Pointer into line */ + *bufptr, /* Pointer into input buffer */ + *bufend; /* Pointer to end of buffer */ + int bytes; /* Number of bytes read */ + + + DEBUG_printf(("httpGets(%p, %d, %p)\n", line, length, http)); + + if (http == NULL || line == NULL) + return (NULL); + + /* + * Pre-scan the buffer and see if there is a newline in there... + */ + +#ifdef WIN32 + WSASetLastError(0); +#else + errno = 0; +#endif /* WIN32 */ + + do + { + bufptr = http->buffer; + bufend = http->buffer + http->used; + + while (bufptr < bufend) + if (*bufptr == 0x0a) + break; + else + bufptr ++; + + if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER) + { + /* + * No newline; see if there is more data to be read... + */ + +#ifdef HAVE_LIBSSL + if (http->tls) + bytes = SSL_read((SSL *)(http->tls), bufend, + HTTP_MAX_BUFFER - http->used); + else +#endif /* HAVE_LIBSSL */ + bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0); + + if (bytes < 0) + { + /* + * Nope, can't get a line this time... + */ + +#ifdef WIN32 + if (WSAGetLastError() != http->error) + { + http->error = WSAGetLastError(); + continue; + } + + DEBUG_printf(("httpGets(): recv() error %d!\n", WSAGetLastError())); +#else + if (errno == EINTR) + continue; + else if (errno != http->error) + { + http->error = errno; + continue; + } + + DEBUG_printf(("httpGets(): recv() error %d!\n", errno)); +#endif /* WIN32 */ + + return (NULL); + } + else if (bytes == 0) + { + if (http->blocking) + http->error = EPIPE; + + return (NULL); + } + + /* + * Yup, update the amount used and the end pointer... + */ + + http->used += bytes; + bufend += bytes; + bufptr = bufend; + } + } + while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER); + + http->activity = time(NULL); + + /* + * Read a line from the buffer... + */ + + lineptr = line; + bufptr = http->buffer; + bytes = 0; + length --; + + while (bufptr < bufend && bytes < length) + { + bytes ++; + + if (*bufptr == 0x0a) + { + bufptr ++; + break; + } + else if (*bufptr == 0x0d) + bufptr ++; + else + *lineptr++ = *bufptr++; + } + + if (bytes > 0) + { + *lineptr = '\0'; + + http->used -= bytes; + if (http->used > 0) + memmove(http->buffer, bufptr, http->used); + + DEBUG_printf(("httpGets(): Returning \"%s\"\n", line)); + return (line); + } + + DEBUG_puts("httpGets(): No new line available!"); + + return (NULL); +} + + +/* + * 'httpPrintf()' - Print a formatted string to a HTTP connection. + */ + +int /* O - Number of bytes written */ +httpPrintf(http_t *http, /* I - HTTP data */ + const char *format, /* I - printf-style format string */ + ...) /* I - Additional args as needed */ +{ + int bytes, /* Number of bytes to write */ + nbytes, /* Number of bytes written */ + tbytes; /* Number of bytes all together */ + char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */ + *bufptr; /* Pointer into buffer */ + va_list ap; /* Variable argument pointer */ + + + va_start(ap, format); + bytes = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + DEBUG_printf(("httpPrintf: %s", buf)); + + for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes) + { +#ifdef HAVE_LIBSSL + if (http->tls) + nbytes = SSL_write((SSL *)(http->tls), bufptr, bytes - tbytes); + else +#endif /* HAVE_LIBSSL */ + nbytes = send(http->fd, bufptr, bytes - tbytes, 0); + + if (nbytes < 0) + { + nbytes = 0; + +#ifdef WIN32 + if (WSAGetLastError() != http->error) + { + http->error = WSAGetLastError(); + continue; + } +#else + if (errno == EINTR) + continue; + else if (errno != http->error) + { + http->error = errno; + continue; + } +#endif /* WIN32 */ + + return (-1); + } + } + + return (bytes); +} + + +/* + * 'httpGetDateString()' - Get a formatted date/time string from a time value. + */ + +const char * /* O - Date/time string */ +httpGetDateString(time_t t) /* I - UNIX time */ +{ + struct tm *tdate; + static char datetime[256]; + + + tdate = gmtime(&t); + snprintf(datetime, sizeof(datetime), "%s, %02d %s %d %02d:%02d:%02d GMT", + days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon], + tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec); + + return (datetime); +} + + +/* + * 'httpGetDateTime()' - Get a time value from a formatted date/time string. + */ + +time_t /* O - UNIX time */ +httpGetDateTime(const char *s) /* I - Date/time string */ +{ + int i; /* Looping var */ + struct tm tdate; /* Time/date structure */ + char mon[16]; /* Abbreviated month name */ + int day, year; /* Day of month and year */ + int hour, min, sec; /* Time */ + + + if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6) + return (0); + + for (i = 0; i < 12; i ++) + if (strcasecmp(mon, months[i]) == 0) + break; + + if (i >= 12) + return (0); + + tdate.tm_mon = i; + tdate.tm_mday = day; + tdate.tm_year = year - 1900; + tdate.tm_hour = hour; + tdate.tm_min = min; + tdate.tm_sec = sec; + tdate.tm_isdst = 0; + + return (mktime(&tdate)); +} + + +/* + * 'httpUpdate()' - Update the current HTTP state for incoming data. + */ + +http_status_t /* O - HTTP status */ +httpUpdate(http_t *http) /* I - HTTP data */ +{ + char line[1024], /* Line from connection... */ + *value; /* Pointer to value on line */ + http_field_t field; /* Field index */ + int major, minor; /* HTTP version numbers */ + http_status_t status; /* Authorization status */ +#ifdef HAVE_LIBSSL + SSL_CTX *context; /* Context for encryption */ + SSL *conn; /* Connection for encryption */ +#endif /* HAVE_LIBSSL */ + + + DEBUG_printf(("httpUpdate(%p)\n", http)); + + /* + * If we haven't issued any commands, then there is nothing to "update"... + */ + + if (http->state == HTTP_WAITING) + return (HTTP_CONTINUE); + + /* + * Grab all of the lines we can from the connection... + */ + + while (httpGets(line, sizeof(line), http) != NULL) + { + DEBUG_puts(line); + + if (line[0] == '\0') + { + /* + * Blank line means the start of the data section (if any). Return + * the result code, too... + * + * If we get status 100 (HTTP_CONTINUE), then we *don't* change states. + * Instead, we just return HTTP_CONTINUE to the caller and keep on + * tryin'... + */ + + if (http->status == HTTP_CONTINUE) + return (http->status); + +#ifdef HAVE_LIBSSL + if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls) + { + context = SSL_CTX_new(SSLv23_method()); + conn = SSL_new(context); + + SSL_set_fd(conn, http->fd); + if (SSL_connect(conn) != 1) + { + SSL_CTX_free(context); + SSL_free(conn); + +#ifdef WIN32 + http->error = WSAGetLastError(); +#else + http->error = errno; +#endif /* WIN32 */ + http->status = HTTP_ERROR; + +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif + + return (HTTP_ERROR); + } + + http->tls = conn; + + return (HTTP_CONTINUE); + } +#endif /* HAVE_LIBSSL */ + + httpGetLength(http); + + switch (http->state) + { + case HTTP_GET : + case HTTP_POST : + case HTTP_POST_RECV : + case HTTP_PUT : + http->state ++; + break; + + default : + http->state = HTTP_WAITING; + break; + } + + return (http->status); + } + else if (strncmp(line, "HTTP/", 5) == 0) + { + /* + * Got the beginning of a response... + */ + + if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, (int *)&status) != 3) + return (HTTP_ERROR); + + http->version = (http_version_t)(major * 100 + minor); + http->status = status; + } + else if ((value = strchr(line, ':')) != NULL) + { + /* + * Got a value... + */ + + *value++ = '\0'; + while (isspace(*value)) + value ++; + + /* + * Be tolerants of servers that send unknown attribute fields... + */ + + if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN) + { + DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line)); + continue; + } + + httpSetField(http, field, value); + } + else + { + http->status = HTTP_ERROR; + return (HTTP_ERROR); + } + } + + /* + * See if there was an error... + */ + + if (http->error) + { + http->status = HTTP_ERROR; + return (HTTP_ERROR); + } + + /* + * If we haven't already returned, then there is nothing new... + */ + + return (HTTP_CONTINUE); +} + + +/* + * 'httpDecode64()' - Base64-decode a string. + */ + +char * /* O - Decoded string */ +httpDecode64(char *out, /* I - String to write to */ + const char *in) /* I - String to read from */ +{ + int pos, /* Bit position */ + base64; /* Value of this character */ + char *outptr; /* Output pointer */ + + + for (outptr = out, pos = 0; *in != '\0'; in ++) + { + /* + * Decode this character into a number from 0 to 63... + */ + + if (*in >= 'A' && *in <= 'Z') + base64 = *in - 'A'; + else if (*in >= 'a' && *in <= 'z') + base64 = *in - 'a' + 26; + else if (*in >= '0' && *in <= '9') + base64 = *in - '0' + 52; + else if (*in == '+') + base64 = 62; + else if (*in == '/') + base64 = 63; + else if (*in == '=') + break; + else + continue; + + /* + * Store the result in the appropriate chars... + */ + + switch (pos) + { + case 0 : + *outptr = base64 << 2; + pos ++; + break; + case 1 : + *outptr++ |= (base64 >> 4) & 3; + *outptr = (base64 << 4) & 255; + pos ++; + break; + case 2 : + *outptr++ |= (base64 >> 2) & 15; + *outptr = (base64 << 6) & 255; + pos ++; + break; + case 3 : + *outptr++ |= base64; + pos = 0; + break; + } + } + + *outptr = '\0'; + + /* + * Return the decoded string... + */ + + return (out); +} + + +/* + * 'httpEncode64()' - Base64-encode a string. + */ + +char * /* O - Encoded string */ +httpEncode64(char *out, /* I - String to write to */ + const char *in) /* I - String to read from */ +{ + char *outptr; /* Output pointer */ + static char base64[] = /* Base64 characters... */ + { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/" + }; + + + for (outptr = out; *in != '\0'; in ++) + { + /* + * Encode the up to 3 characters as 4 Base64 numbers... + */ + + *outptr ++ = base64[in[0] >> 2]; + *outptr ++ = base64[((in[0] << 4) | (in[1] >> 4)) & 63]; + + in ++; + if (*in == '\0') + { + *outptr ++ = '='; + break; + } + + *outptr ++ = base64[((in[0] << 2) | (in[1] >> 6)) & 63]; + + in ++; + if (*in == '\0') + break; + + *outptr ++ = base64[in[0] & 63]; + } + + *outptr ++ = '='; + *outptr = '\0'; + + /* + * Return the encoded string... + */ + + return (out); +} + + +/* + * 'httpGetLength()' - Get the amount of data remaining from the + * content-length or transfer-encoding fields. + */ + +int /* O - Content length */ +httpGetLength(http_t *http) /* I - HTTP data */ +{ + DEBUG_printf(("httpGetLength(%p)\n", http)); + + if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0) + { + DEBUG_puts("httpGetLength: chunked request!"); + + http->data_encoding = HTTP_ENCODE_CHUNKED; + http->data_remaining = 0; + } + else + { + http->data_encoding = HTTP_ENCODE_LENGTH; + + /* + * The following is a hack for HTTP servers that don't send a + * content-length or transfer-encoding field... + * + * If there is no content-length then the connection must close + * after the transfer is complete... + */ + + if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0') + http->data_remaining = 2147483647; + else + http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]); + + DEBUG_printf(("httpGetLength: content_length = %d\n", http->data_remaining)); + } + + return (http->data_remaining); +} + + +/* + * 'http_field()' - Return the field index for a field name. + */ + +static http_field_t /* O - Field index */ +http_field(const char *name) /* I - String name */ +{ + int i; /* Looping var */ + + + for (i = 0; i < HTTP_FIELD_MAX; i ++) + if (strcasecmp(name, http_fields[i]) == 0) + return ((http_field_t)i); + + return (HTTP_FIELD_UNKNOWN); +} + + +/* + * 'http_send()' - Send a request with all fields and the trailing blank line. + */ + +static int /* O - 0 on success, non-zero on error */ +http_send(http_t *http, /* I - HTTP data */ + http_state_t request, /* I - Request code */ + const char *uri) /* I - URI */ +{ + int i; /* Looping var */ + char *ptr, /* Pointer in buffer */ + buf[1024]; /* Encoded URI buffer */ + static const char *codes[] = /* Request code strings */ + { + NULL, + "OPTIONS", + "GET", + NULL, + "HEAD", + "POST", + NULL, + NULL, + "PUT", + NULL, + "DELETE", + "TRACE", + "CLOSE" + }; + static const char *hex = "0123456789ABCDEF"; + /* Hex digits */ + + + if (http == NULL || uri == NULL) + return (-1); + + /* + * Encode the URI as needed... + */ + + for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++) + if (*uri <= ' ' || *uri >= 127) + { + if (ptr < (buf + sizeof(buf) - 1)) + *ptr ++ = '%'; + if (ptr < (buf + sizeof(buf) - 1)) + *ptr ++ = hex[(*uri >> 4) & 15]; + if (ptr < (buf + sizeof(buf) - 1)) + *ptr ++ = hex[*uri & 15]; + } + else + *ptr ++ = *uri; + + *ptr = '\0'; + + /* + * See if we had an error the last time around; if so, reconnect... + */ + + if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST) + httpReconnect(http); + + /* + * Send the request header... + */ + + http->state = request; + if (request == HTTP_POST || request == HTTP_PUT) + http->state ++; + + http->status = HTTP_CONTINUE; + +#ifdef HAVE_LIBSSL + if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls) + { + httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade"); + httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0"); + } +#endif /* HAVE_LIBSSL */ + + if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1) + { + http->status = HTTP_ERROR; + return (-1); + } + + for (i = 0; i < HTTP_FIELD_MAX; i ++) + if (http->fields[i][0] != '\0') + { + DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i])); + + if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1) + { + http->status = HTTP_ERROR; + return (-1); + } + } + + if (httpPrintf(http, "\r\n") < 1) + { + http->status = HTTP_ERROR; + return (-1); + } + + httpClearFields(http); + + return (0); +} + + +#ifdef HAVE_LIBSSL +/* + * 'http_upgrade()' - Force upgrade to TLS encryption. + */ + +static int /* O - Status of connection */ +http_upgrade(http_t *http) /* I - HTTP data */ +{ + int ret; /* Return value */ + http_t myhttp; /* Local copy of HTTP data */ + + + DEBUG_printf(("http_upgrade(%p)\n", http)); + + /* + * Copy the HTTP data to a local variable so we can do the OPTIONS + * request without interfering with the existing request data... + */ + + memcpy(&myhttp, http, sizeof(myhttp)); + + /* + * Send an OPTIONS request to the server, requiring SSL or TLS + * encryption on the link... + */ + + httpClearFields(&myhttp); + httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade"); + httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0"); + + if ((ret = httpOptions(&myhttp, "*")) == 0) + { + /* + * Wait for the secure connection... + */ + + while (httpUpdate(&myhttp) == HTTP_CONTINUE); + } + + httpFlush(&myhttp); + + /* + * Copy the HTTP data back over, if any... + */ + + http->fd = myhttp.fd; + http->error = myhttp.error; + http->activity = myhttp.activity; + http->status = myhttp.status; + http->version = myhttp.version; + http->keep_alive = myhttp.keep_alive; + http->used = myhttp.used; + + if (http->used) + memcpy(http->buffer, myhttp.buffer, http->used); + + http->auth_type = myhttp.auth_type; + http->nonce_count = myhttp.nonce_count; + + memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce)); + + http->tls = myhttp.tls; + http->encryption = myhttp.encryption; + + /* + * See if we actually went secure... + */ + + if (!http->tls) + { + /* + * Server does not support HTTP upgrade... + */ + + DEBUG_puts("Server does not support HTTP upgrade!"); + +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif + + http->fd = -1; + + return (-1); + } + else + return (ret); +} +#endif /* HAVE_LIBSSL */ + + +/* + * End of "$Id$". + */ diff --git a/cups/http.h b/cups/http.h new file mode 100644 index 0000000000..a276736683 --- /dev/null +++ b/cups/http.h @@ -0,0 +1,353 @@ +/* + * "$Id$" + * + * Hyper-Text Transport Protocol definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2002 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 + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_HTTP_H_ +# define _CUPS_HTTP_H_ + +/* + * Include necessary headers... + */ + +# include +# include +# ifdef WIN32 +# include +# else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# if !defined(__APPLE__) || !defined(TCP_NODELAY) +# include +# endif /* !__APPLE__ || !TCP_NODELAY */ +# endif /* WIN32 */ + +# include "md5.h" + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Limits... + */ + +# define HTTP_MAX_URI 1024 /* Max length of URI string */ +# define HTTP_MAX_HOST 256 /* Max length of hostname string */ +# define HTTP_MAX_BUFFER 2048 /* Max length of data buffer */ +# define HTTP_MAX_VALUE 256 /* Max header field value length */ + + +/* + * HTTP state values... + */ + +typedef enum /* States are server-oriented */ +{ + HTTP_WAITING, /* Waiting for command */ + HTTP_OPTIONS, /* OPTIONS command, waiting for blank line */ + HTTP_GET, /* GET command, waiting for blank line */ + HTTP_GET_SEND, /* GET command, sending data */ + HTTP_HEAD, /* HEAD command, waiting for blank line */ + HTTP_POST, /* POST command, waiting for blank line */ + HTTP_POST_RECV, /* POST command, receiving data */ + HTTP_POST_SEND, /* POST command, sending data */ + HTTP_PUT, /* PUT command, waiting for blank line */ + HTTP_PUT_RECV, /* PUT command, receiving data */ + HTTP_DELETE, /* DELETE command, waiting for blank line */ + HTTP_TRACE, /* TRACE command, waiting for blank line */ + HTTP_CLOSE, /* CLOSE command, waiting for blank line */ + HTTP_STATUS /* Command complete, sending status */ +} http_state_t; + + +/* + * HTTP version numbers... + */ + +typedef enum +{ + HTTP_0_9 = 9, /* HTTP/0.9 */ + HTTP_1_0 = 100, /* HTTP/1.0 */ + HTTP_1_1 = 101 /* HTTP/1.1 */ +} http_version_t; + + +/* + * HTTP keep-alive values... + */ + +typedef enum +{ + HTTP_KEEPALIVE_OFF = 0, + HTTP_KEEPALIVE_ON +} http_keepalive_t; + + +/* + * HTTP transfer encoding values... + */ + +typedef enum +{ + HTTP_ENCODE_LENGTH, /* Data is sent with Content-Length */ + HTTP_ENCODE_CHUNKED /* Data is chunked */ +} http_encoding_t; + + +/* + * HTTP encryption values... + */ + +typedef enum +{ + HTTP_ENCRYPT_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */ + HTTP_ENCRYPT_NEVER, /* Never encrypt */ + HTTP_ENCRYPT_REQUIRED, /* Encryption is required (TLS upgrade) */ + HTTP_ENCRYPT_ALWAYS /* Always encrypt (SSL) */ +} http_encryption_t; + + +/* + * HTTP authentication types... + */ + +typedef enum +{ + HTTP_AUTH_NONE, /* No authentication in use */ + HTTP_AUTH_BASIC, /* Basic authentication in use */ + HTTP_AUTH_MD5, /* Digest authentication in use */ + HTTP_AUTH_MD5_SESS, /* MD5-session authentication in use */ + HTTP_AUTH_MD5_INT, /* Digest authentication in use for body */ + HTTP_AUTH_MD5_SESS_INT /* MD5-session authentication in use for body */ +} http_auth_t; + + +/* + * HTTP status codes... + */ + +typedef enum +{ + HTTP_ERROR = -1, /* An error response from httpXxxx() */ + + HTTP_CONTINUE = 100, /* Everything OK, keep going... */ + HTTP_SWITCHING_PROTOCOLS, /* HTTP upgrade to TLS/SSL */ + + HTTP_OK = 200, /* OPTIONS/GET/HEAD/POST/TRACE command was successful */ + HTTP_CREATED, /* PUT command was successful */ + HTTP_ACCEPTED, /* DELETE command was successful */ + HTTP_NOT_AUTHORITATIVE, /* Information isn't authoritative */ + HTTP_NO_CONTENT, /* Successful command, no new data */ + HTTP_RESET_CONTENT, /* Content was reset/recreated */ + HTTP_PARTIAL_CONTENT, /* Only a partial file was recieved/sent */ + + HTTP_MULTIPLE_CHOICES = 300, /* Multiple files match request */ + HTTP_MOVED_PERMANENTLY, /* Document has moved permanently */ + HTTP_MOVED_TEMPORARILY, /* Document has moved temporarily */ + HTTP_SEE_OTHER, /* See this other link... */ + HTTP_NOT_MODIFIED, /* File not modified */ + HTTP_USE_PROXY, /* Must use a proxy to access this URI */ + + HTTP_BAD_REQUEST = 400, /* Bad request */ + HTTP_UNAUTHORIZED, /* Unauthorized to access host */ + HTTP_PAYMENT_REQUIRED, /* Payment required */ + HTTP_FORBIDDEN, /* Forbidden to access this URI */ + HTTP_NOT_FOUND, /* URI was not found */ + HTTP_METHOD_NOT_ALLOWED, /* Method is not allowed */ + HTTP_NOT_ACCEPTABLE, /* Not Acceptable */ + HTTP_PROXY_AUTHENTICATION, /* Proxy Authentication is Required */ + HTTP_REQUEST_TIMEOUT, /* Request timed out */ + HTTP_CONFLICT, /* Request is self-conflicting */ + HTTP_GONE, /* Server has gone away */ + HTTP_LENGTH_REQUIRED, /* A content length or encoding is required */ + HTTP_PRECONDITION, /* Precondition failed */ + HTTP_REQUEST_TOO_LARGE, /* Request entity too large */ + HTTP_URI_TOO_LONG, /* URI too long */ + HTTP_UNSUPPORTED_MEDIATYPE, /* The requested media type is unsupported */ + HTTP_UPGRADE_REQUIRED = 426, /* Upgrade to SSL/TLS required */ + + HTTP_SERVER_ERROR = 500, /* Internal server error */ + HTTP_NOT_IMPLEMENTED, /* Feature not implemented */ + HTTP_BAD_GATEWAY, /* Bad gateway */ + HTTP_SERVICE_UNAVAILABLE, /* Service is unavailable */ + HTTP_GATEWAY_TIMEOUT, /* Gateway connection timed out */ + HTTP_NOT_SUPPORTED /* HTTP version not supported */ +} http_status_t; + + +/* + * HTTP field names... + */ + +typedef enum +{ + HTTP_FIELD_UNKNOWN = -1, + HTTP_FIELD_ACCEPT_LANGUAGE, + HTTP_FIELD_ACCEPT_RANGES, + HTTP_FIELD_AUTHORIZATION, + HTTP_FIELD_CONNECTION, + HTTP_FIELD_CONTENT_ENCODING, + HTTP_FIELD_CONTENT_LANGUAGE, + HTTP_FIELD_CONTENT_LENGTH, + HTTP_FIELD_CONTENT_LOCATION, + HTTP_FIELD_CONTENT_MD5, + HTTP_FIELD_CONTENT_RANGE, + HTTP_FIELD_CONTENT_TYPE, + HTTP_FIELD_CONTENT_VERSION, + HTTP_FIELD_DATE, + HTTP_FIELD_HOST, + HTTP_FIELD_IF_MODIFIED_SINCE, + HTTP_FIELD_IF_UNMODIFIED_SINCE, + HTTP_FIELD_KEEP_ALIVE, + HTTP_FIELD_LAST_MODIFIED, + HTTP_FIELD_LINK, + HTTP_FIELD_LOCATION, + HTTP_FIELD_RANGE, + HTTP_FIELD_REFERER, + HTTP_FIELD_RETRY_AFTER, + HTTP_FIELD_TRANSFER_ENCODING, + HTTP_FIELD_UPGRADE, + HTTP_FIELD_USER_AGENT, + HTTP_FIELD_WWW_AUTHENTICATE, + HTTP_FIELD_MAX +} http_field_t; + + +/* + * HTTP connection structure... + */ + +typedef struct +{ + int fd; /* File descriptor for this socket */ + int blocking; /* To block or not to block */ + int error; /* Last error on read */ + time_t activity; /* Time since last read/write */ + http_state_t state; /* State of client */ + http_status_t status; /* Status of last request */ + http_version_t version; /* Protocol version */ + http_keepalive_t keep_alive; /* Keep-alive supported? */ + struct sockaddr_in hostaddr; /* Address of connected host */ + char hostname[HTTP_MAX_HOST], + /* Name of connected host */ + fields[HTTP_FIELD_MAX][HTTP_MAX_VALUE]; + /* Field values */ + char *data; /* Pointer to data buffer */ + http_encoding_t data_encoding; /* Chunked or not */ + int data_remaining; /* Number of bytes left */ + int used; /* Number of bytes used in buffer */ + char buffer[HTTP_MAX_BUFFER]; + /* Buffer for messages */ + int auth_type; /* Authentication in use */ + md5_state_t md5_state; /* MD5 state */ + char nonce[HTTP_MAX_VALUE]; + /* Nonce value */ + int nonce_count; /* Nonce count */ + void *tls; /* TLS state information */ + http_encryption_t encryption; /* Encryption requirements */ +} http_t; + + +/* + * Prototypes... + */ + +# define httpBlocking(http,b) (http)->blocking = (b) +extern int httpCheck(http_t *http); +# define httpClearFields(http) memset((http)->fields, 0, sizeof((http)->fields)),\ + httpSetField((http), HTTP_FIELD_HOST, (http)->hostname) +extern void httpClose(http_t *http); +extern http_t *httpConnect(const char *host, int port); +extern http_t *httpConnectEncrypt(const char *host, int port, + http_encryption_t encrypt); +extern int httpDelete(http_t *http, const char *uri); +extern int httpEncryption(http_t *http, http_encryption_t e); +# define httpError(http) ((http)->error) +extern void httpFlush(http_t *http); +extern int httpGet(http_t *http, const char *uri); +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); +extern void httpInitialize(void); +extern int httpOptions(http_t *http, const char *uri); +extern int httpPost(http_t *http, const char *uri); +extern int httpPrintf(http_t *http, const char *format, ...) +# ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 2, 3))) +# endif /* __GNUC__ */ +; +extern int httpPut(http_t *http, const char *uri); +extern int httpRead(http_t *http, char *buffer, int length); +extern int httpReconnect(http_t *http); +extern void httpSeparate(const char *uri, char *method, + char *username, char *host, int *port, + char *resource); +extern void httpSetField(http_t *http, http_field_t field, + const char *value); +extern const char *httpStatus(http_status_t status); +extern int httpTrace(http_t *http, const char *uri); +extern http_status_t httpUpdate(http_t *http); +extern int httpWrite(http_t *http, const char *buffer, int length); +extern char *httpEncode64(char *out, const char *in); +extern char *httpDecode64(char *out, const char *in); +extern int httpGetLength(http_t *http); +extern char *httpMD5(const char *, const char *, const char *, + char [33]); +extern char *httpMD5Final(const char *, const char *, const char *, + char [33]); +extern char *httpMD5String(const md5_byte_t *, char [33]); + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_HTTP_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/ipp-support.c b/cups/ipp-support.c new file mode 100644 index 0000000000..515a807eff --- /dev/null +++ b/cups/ipp-support.c @@ -0,0 +1,175 @@ +/* + * "$Id$" + * + * Internet Printing Protocol support functions for the Common UNIX + * Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * ippErrorString() - Return a textual message for the given error + * message. + * ippPort() - Return the default IPP port number. + * ippSetPort() - Set the default port number. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include "string.h" +#include "language.h" + +#include "ipp.h" +#include "debug.h" +#include + + +/* + * Local globals... + */ + +static int ipp_port = 0; + + +/* + * 'ippErrorString()' - Return a textual message for the given error message. + */ + +const char * /* O - Text string */ +ippErrorString(ipp_status_t error) /* I - Error status */ +{ + static char unknown[255]; /* Unknown error statuses */ + static const char *status_oks[] = /* "OK" status codes */ + { + "successful-ok", + "successful-ok-ignored-or-substituted-attributes", + "successful-ok-conflicting-attributes", + "successful-ok-ignored-subscriptions", + "successful-ok-ignored-notifications", + "successful-ok-too-many-events", + "successful-ok-but-cancel-subscription" + }, + *status_400s[] = /* Client errors */ + { + "client-error-bad-request", + "client-error-forbidden", + "client-error-not-authenticated", + "client-error-not-authorized", + "client-error-not-possible", + "client-error-timeout", + "client-error-not-found", + "client-error-gone", + "client-error-request-entity-too-large", + "client-error-request-value-too-long", + "client-error-document-format-not-supported", + "client-error-attributes-or-values-not-supported", + "client-error-uri-scheme-not-supported", + "client-error-charset-not-supported", + "client-error-conflicting-attributes", + "client-error-compression-not-supported", + "client-error-compression-error", + "client-error-document-format-error", + "client-error-document-access-error", + "client-error-attributes-not-settable", + "client-error-ignored-all-subscriptions", + "client-error-too-many-subscriptions", + "client-error-ignored-all-notifications", + "client-error-print-support-file-not-found" + }, + *status_500s[] = /* Server errors */ + { + "server-error-internal-error", + "server-error-operation-not-supported", + "server-error-service-unavailable", + "server-error-version-not-supported", + "server-error-device-error", + "server-error-temporary-error", + "server-error-not-accepting-jobs", + "server-error-busy", + "server-error-job-canceled", + "server-error-multiple-document-jobs-not-supported", + "server-error-printer-is-deactivated" + }; + + + /* + * See if the error code is a known value... + */ + + if (error >= IPP_OK && error <= IPP_OK_BUT_CANCEL_SUBSCRIPTION) + return (status_oks[error]); + else if (error == IPP_REDIRECTION_OTHER_SITE) + return ("redirection-other-site"); + else if (error >= IPP_BAD_REQUEST && error <= IPP_PRINT_SUPPORT_FILE_NOT_FOUND) + return (status_400s[error - IPP_BAD_REQUEST]); + else if (error >= IPP_INTERNAL_ERROR && error <= IPP_PRINTER_IS_DEACTIVATED) + return (status_500s[error - IPP_INTERNAL_ERROR]); + + /* + * No, build an "unknown-xxxx" error string... + */ + + sprintf(unknown, "unknown-%04x", error); + + return (unknown); +} + + +/* + * 'ippPort()' - Return the default IPP port number. + */ + +int /* O - Port number */ +ippPort(void) +{ + const char *server_port; /* SERVER_PORT environment variable */ + struct servent *port; /* Port number info */ + + + if (ipp_port) + return (ipp_port); + else if ((server_port = getenv("IPP_PORT")) != NULL) + return (ipp_port = atoi(server_port)); + else if ((port = getservbyname("ipp", NULL)) == NULL) + return (ipp_port = IPP_PORT); + else + return (ipp_port = ntohs(port->s_port)); +} + + +/* + * 'ippSetPort()' - Set the default port number. + */ + +void +ippSetPort(int p) /* I - Port number to use */ +{ + ipp_port = p; +} + + +/* + * End of "$Id$". + */ diff --git a/cups/ipp.c b/cups/ipp.c new file mode 100644 index 0000000000..cbd0f72076 --- /dev/null +++ b/cups/ipp.c @@ -0,0 +1,2067 @@ +/* + * "$Id$" + * + * Internet Printing Protocol object functions for the Common UNIX + * Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * ippAddBoolean() - Add a boolean attribute to an IPP request. + * ippAddBooleans() - Add an array of boolean values. + * ippAddDate() - Add a date attribute to an IPP request. + * ippAddInteger() - Add a integer attribute to an IPP request. + * ippAddIntegers() - Add an array of integer values. + * ippAddString() - Add a language-encoded string to an IPP request. + * ippAddStrings() - Add language-encoded strings to an IPP request. + * ippAddRange() - Add a range of values to an IPP request. + * ippAddRanges() - Add ranges of values to an IPP request. + * ippAddResolution() - Add a resolution value to an IPP request. + * ippAddResolutions() - Add resolution values to an IPP request. + * ippAddSeparator() - Add a group separator to an IPP request. + * ippDateToTime() - Convert from RFC 1903 Date/Time format to UNIX + * time in seconds. + * ippDelete() - Delete an IPP request. + * ippFindAttribute() - Find a named attribute in a request... + * ippFindNextAttribute() - Find the next named attribute in a request... + * ippLength() - Compute the length of an IPP request. + * ippNew() - Allocate a new IPP request. + * ippRead() - Read data for an IPP request. + * ippTimeToDate() - Convert from UNIX time to RFC 1903 format. + * ippWrite() - Write data for an IPP request. + * _ipp_add_attr() - Add a new attribute to the request. + * _ipp_free_attr() - Free an attribute. + * ipp_read() - Semi-blocking read on a HTTP connection... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include "string.h" +#include "language.h" + +#include "ipp.h" +#include "debug.h" +#include + + +/* + * Local functions... + */ + +static int ipp_read(http_t *http, unsigned char *buffer, int length); + + +/* + * 'ippAddBoolean()' - Add a boolean attribute to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddBoolean(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + const char *name, /* I - Name of attribute */ + char value) /* I - Value of attribute */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddBoolean(%p, %02x, \'%s\', %d)\n", ipp, group, name, value)); + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_BOOLEAN; + attr->values[0].boolean = value; + + return (attr); +} + + +/* + * 'ippAddBooleans()' - Add an array of boolean values. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddBooleans(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const char *values) /* I - Values */ +{ + 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, + group, name, num_values, values)); + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_BOOLEAN; + + if (values != NULL) + for (i = 0, value = attr->values; + i < num_values; + i ++, value ++) + value->boolean = values[i]; + + return (attr); +} + + +/* + * 'ippAddDate()' - Add a date attribute to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddDate(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + const char *name, /* I - Name of attribute */ + const ipp_uchar_t *value) /* I - Value */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddDate(%p, %02x, \'%s\', %p)\n", ipp, group, name, + value)); + + if (ipp == NULL || name == NULL || value == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_DATE; + memcpy(attr->values[0].date, value, 11); + + return (attr); +} + + +/* + * 'ippAddInteger()' - Add a integer attribute to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddInteger(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + const char *name, /* I - Name of attribute */ + int value) /* I - Value of attribute */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddInteger(%p, %d, \'%s\', %d)\n", ipp, group, name, + value)); + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + attr->values[0].integer = value; + + return (attr); +} + + +/* + * 'ippAddIntegers()' - Add an array of integer values. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddIntegers(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const int *values) /* I - Values */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + ipp_value_t *value; /* Current value */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + + if (values != NULL) + for (i = 0, value = attr->values; + i < num_values; + i ++, value ++) + value->integer = values[i]; + + return (attr); +} + + +/* + * 'ippAddString()' - Add a language-encoded string to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddString(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + const char *name, /* I - Name of attribute */ + const char *charset, /* I - Character set */ + const char *value) /* I - Value */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, 1)) == NULL) + return (NULL); + + /* + * Force value to be English for the POSIX locale... + */ + + if (type == IPP_TAG_LANGUAGE && strcasecmp(value, "C") == 0) + value = "en"; + + /* + * Initialize the attribute data... + */ + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + 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; + + /* + * Convert language values to lowercase and change _ to - as needed... + */ + + if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && + attr->values[0].string.text) + { + char *p; + + + for (p = attr->values[0].string.text; *p; p ++) + if (*p == '_') + *p = '-'; + else + *p = tolower(*p); + } + + return (attr); +} + + +/* + * 'ippAddStrings()' - Add language-encoded strings to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddStrings(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const char *charset, /* I - Character set */ + const char **values) /* I - Values */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + ipp_value_t *value; /* Current value */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, num_values)) == NULL) + return (NULL); + + /* + * Initialize the attribute data... + */ + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + + 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) + { + /* + * Force language to be English for the POSIX locale... + */ + + if (type == IPP_TAG_LANGUAGE && strcasecmp(values[i], "C") == 0) + value->string.text = ((int)type & IPP_TAG_COPY) ? "en" : + strdup("en"); + else + value->string.text = ((int)type & IPP_TAG_COPY) ? (char *)values[i] : + strdup(values[i]); + } + } + + return (attr); +} + + +/* + * 'ippAddRange()' - Add a range of values to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddRange(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + const char *name, /* I - Name of attribute */ + int lower, /* I - Lower value */ + int upper) /* I - Upper value */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RANGE; + attr->values[0].range.lower = lower; + attr->values[0].range.upper = upper; + + return (attr); +} + + +/* + * 'ippAddRanges()' - Add ranges of values to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddRanges(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const int *lower, /* I - Lower values */ + const int *upper) /* I - Upper values */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + ipp_value_t *value; /* Current value */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RANGE; + + if (lower != NULL && upper != NULL) + for (i = 0, value = attr->values; + i < num_values; + i ++, value ++) + { + value->range.lower = lower[i]; + value->range.upper = upper[i]; + } + + return (attr); +} + + +/* + * 'ippAddResolution()' - Add a resolution value to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddResolution(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + const char *name, /* I - Name of attribute */ + ipp_res_t units, /* I - Units for resolution */ + int xres, /* I - X resolution */ + int yres) /* I - Y resolution */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RESOLUTION; + attr->values[0].resolution.xres = xres; + attr->values[0].resolution.yres = yres; + attr->values[0].resolution.units = units; + + return (attr); +} + + +/* + * 'ippAddResolutions()' - Add resolution values to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddResolutions(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + const char *name, /* I - Name of attribute */ + int num_values,/* I - Number of values */ + ipp_res_t units, /* I - Units for resolution */ + const int *xres, /* I - X resolutions */ + const int *yres) /* I - Y resolutions */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + ipp_value_t *value; /* Current value */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RESOLUTION; + + if (xres != NULL && yres != NULL) + for (i = 0, value = attr->values; + i < num_values; + i ++, value ++) + { + value->resolution.xres = xres[i]; + value->resolution.yres = yres[i]; + value->resolution.units = units; + } + + return (attr); +} + + +/* + * 'ippAddSeparator()' - Add a group separator to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddSeparator(ipp_t *ipp) /* I - IPP request */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddSeparator(%p)\n", ipp)); + + if (ipp == NULL) + return (NULL); + + if ((attr = _ipp_add_attr(ipp, 0)) == NULL) + return (NULL); + + attr->group_tag = IPP_TAG_ZERO; + attr->value_tag = IPP_TAG_ZERO; + + return (attr); +} + + +/* + * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time + * in seconds. + */ + +time_t /* O - UNIX time value */ +ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */ +{ + struct tm unixdate; /* UNIX date/time info */ + time_t t; /* Computed time */ + + + memset(&unixdate, 0, sizeof(unixdate)); + + /* + * RFC-1903 date/time format is: + * + * Byte(s) Description + * ------- ----------- + * 0-1 Year (0 to 65535) + * 2 Month (1 to 12) + * 3 Day (1 to 31) + * 4 Hours (0 to 23) + * 5 Minutes (0 to 59) + * 6 Seconds (0 to 60, 60 = "leap second") + * 7 Deciseconds (0 to 9) + * 8 +/- UTC + * 9 UTC hours (0 to 11) + * 10 UTC minutes (0 to 59) + */ + + unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900; + unixdate.tm_mon = date[2] - 1; + unixdate.tm_mday = date[3]; + unixdate.tm_hour = date[4]; + unixdate.tm_min = date[5]; + unixdate.tm_sec = date[6]; + + t = mktime(&unixdate); + + if (date[8] == '-') + t += date[9] * 3600 + date[10] * 60; + else + t -= date[9] * 3600 + date[10] * 60; + + return (t); +} + + +/* + * 'ippDelete()' - Delete an IPP request. + */ + +void +ippDelete(ipp_t *ipp) /* I - IPP request */ +{ + ipp_attribute_t *attr, /* Current attribute */ + *next; /* Next attribute */ + + + DEBUG_printf(("ippDelete(): %p\n", ipp)); + + if (ipp == NULL) + return; + + for (attr = ipp->attrs; attr != NULL; attr = next) + { + next = attr->next; + _ipp_free_attr(attr); + } + + free(ipp); +} + + +/* + * 'ippFindAttribute()' - Find a named attribute in a request... + */ + +ipp_attribute_t * /* O - Matching attribute */ +ippFindAttribute(ipp_t *ipp, /* I - IPP request */ + const char *name, /* I - Name of attribute */ + ipp_tag_t type) /* I - Type of attribute */ +{ + DEBUG_printf(("ippFindAttribute(%p, \'%s\')\n", ipp, name)); + + if (ipp == NULL || name == NULL) + return (NULL); + + /* + * Reset the current pointer... + */ + + ipp->current = NULL; + + /* + * Search for the attribute... + */ + + return (ippFindNextAttribute(ipp, name, type)); +} + + +/* + * 'ippFindNextAttribute()' - Find the next named attribute in a request... + */ + +ipp_attribute_t * /* O - Matching attribute */ +ippFindNextAttribute(ipp_t *ipp, /* I - IPP request */ + const char *name, /* I - Name of attribute */ + ipp_tag_t type) /* I - Type of attribute */ +{ + ipp_attribute_t *attr; /* Current atttribute */ + ipp_tag_t value_tag; /* Value tag */ + + + DEBUG_printf(("ippFindNextAttribute(%p, \'%s\')\n", ipp, name)); + + if (ipp == NULL || name == NULL) + return (NULL); + + if (ipp->current) + attr = ipp->current->next; + else + attr = ipp->attrs; + + for (; attr != NULL; attr = attr->next) + { + DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr, + attr->name)); + + value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK); + + if (attr->name != NULL && strcasecmp(attr->name, name) == 0 && + (value_tag == type || type == IPP_TAG_ZERO || + (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) || + (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME))) + { + ipp->current = attr; + + return (attr); + } + } + + ipp->current = NULL; + + return (NULL); +} + + +/* + * 'ippLength()' - Compute the length of an IPP request. + */ + +size_t /* O - Size of IPP request */ +ippLength(ipp_t *ipp) /* I - IPP request */ +{ + int i; /* Looping var */ + 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) + return (0); + + /* + * Start with 8 bytes for the IPP request or status header... + */ + + bytes = 8; + + /* + * Then add the lengths of each attribute... + */ + + group = IPP_TAG_ZERO; + + for (attr = ipp->attrs; attr != NULL; attr = attr->next) + { + if (attr->group_tag != group) + { + group = attr->group_tag; + if (group == IPP_TAG_ZERO) + continue; + + bytes ++; /* Group tag */ + } + + DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n", + attr->name, attr->num_values, bytes)); + + bytes += strlen(attr->name); /* Name */ + bytes += attr->num_values; /* Value tag for each value */ + bytes += 2 * attr->num_values; /* Name lengths */ + bytes += 2 * attr->num_values; /* Value lengths */ + + switch (attr->value_tag & ~IPP_TAG_COPY) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + bytes += 4 * attr->num_values; + break; + + case IPP_TAG_BOOLEAN : + bytes += attr->num_values; + 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, value = attr->values; + i < attr->num_values; + i ++, value ++) + if (value->string.text != NULL) + bytes += strlen(value->string.text); + break; + + case IPP_TAG_DATE : + bytes += 11 * attr->num_values; + break; + + case IPP_TAG_RESOLUTION : + bytes += 9 * attr->num_values; + break; + + case IPP_TAG_RANGE : + bytes += 8 * attr->num_values; + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + bytes += 4 * attr->num_values;/* Charset + text length */ + + for (i = 0, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if (value->string.charset != NULL) + bytes += strlen(value->string.charset); + + if (value->string.text != NULL) + bytes += strlen(value->string.text); + } + break; + + default : + for (i = 0, value = attr->values; + i < attr->num_values; + i ++, value ++) + bytes += attr->values[0].unknown.length; + break; + } + } + + /* + * Finally, add 1 byte for the "end of attributes" tag and return... + */ + + DEBUG_printf(("bytes = %d\n", bytes + 1)); + + return (bytes + 1); +} + + +/* + * 'ippNew()' - Allocate a new IPP request. + */ + +ipp_t * /* O - New IPP request */ +ippNew(void) +{ + ipp_t *temp; /* New IPP request */ + + + if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL) + { + /* + * Default to IPP 1.1... + */ + + temp->request.any.version[0] = 1; + temp->request.any.version[1] = 1; + } + + DEBUG_printf(("ippNew(): %p\n", temp)); + + return (temp); +} + + +/* + * 'ippRead()' - Read data for an IPP request. + */ + +ipp_state_t /* O - Current state */ +ippRead(http_t *http, /* I - HTTP data */ + ipp_t *ipp) /* I - IPP data */ +{ + int n; /* Length of data */ + unsigned char buffer[32768], /* Data buffer */ + *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)); + + if (http == NULL || ipp == NULL) + return (IPP_ERROR); + + switch (ipp->state) + { + case IPP_IDLE : + ipp->state ++; /* Avoid common problem... */ + + case IPP_HEADER : + /* + * Get the request header... + */ + + if ((n = ipp_read(http, buffer, 8)) < 8) + { + DEBUG_printf(("ippRead: Unable to read header (%d bytes read)!\n", n)); + return (n == 0 ? IPP_IDLE : IPP_ERROR); + } + + /* + * Verify the major version number... + */ + + if (buffer[0] != 1) + { + DEBUG_printf(("ippRead: version number (%d.%d) is bad.\n", buffer[0], + buffer[1])); + 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; + + DEBUG_printf(("ippRead: version=%d.%d\n", buffer[0], buffer[1])); + DEBUG_printf(("ippRead: op_status=%04x\n", ipp->request.any.op_status)); + DEBUG_printf(("ippRead: request_id=%d\n", ipp->request.any.request_id)); + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking && http->used == 0) + break; + + case IPP_ATTRIBUTE : + while (ipp_read(http, buffer, 1) > 0) + { + /* + * Read this attribute... + */ + + tag = (ipp_tag_t)buffer[0]; + + if (tag == IPP_TAG_END) + { + /* + * No more attributes left... + */ + + DEBUG_puts("ippRead: 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(("ippRead: group tag = %x\n", tag)); + continue; + } + + DEBUG_printf(("ippRead: value tag = %x\n", tag)); + + /* + * Get the name... + */ + + if (ipp_read(http, buffer, 2) < 2) + { + DEBUG_puts("ippRead: unable to read name length!"); + return (IPP_ERROR); + } + + n = (buffer[0] << 8) | buffer[1]; + + if (n > (sizeof(buffer) - 1)) + { + DEBUG_printf(("ippRead: bad name length %d!\n", n)); + return (IPP_ERROR); + } + + DEBUG_printf(("ippRead: name length = %d\n", n)); + + if (n == 0) + { + /* + * More values for current attribute... + */ + + if (ipp->current == NULL) + return (IPP_ERROR); + + attr = ipp->current; + + /* + * Make sure we aren't adding a new value of a different + * type... + */ + + if (attr->value_tag == IPP_TAG_STRING || + (attr->value_tag >= IPP_TAG_TEXTLANG && + attr->value_tag <= IPP_TAG_MIMETYPE)) + { + /* + * String values can sometimes come across in different + * forms; accept sets of differing values... + */ + + if (tag != IPP_TAG_STRING && + (tag < IPP_TAG_TEXTLANG || tag > IPP_TAG_MIMETYPE)) + return (IPP_ERROR); + } + else if (attr->value_tag != tag) + return (IPP_ERROR); + + /* + * 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) + 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 (ipp_read(http, buffer, n) < n) + { + DEBUG_puts("ippRead: unable to read name!"); + return (IPP_ERROR); + } + + buffer[n] = '\0'; + DEBUG_printf(("ippRead: 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; + } + + value = attr->values + attr->num_values; + + if (ipp_read(http, buffer, 2) < 2) + { + DEBUG_puts("ippRead: unable to read value length!"); + return (IPP_ERROR); + } + + n = (buffer[0] << 8) | buffer[1]; + DEBUG_printf(("ippRead: value length = %d\n", n)); + + switch (tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + if (ipp_read(http, buffer, 4) < 4) + return (IPP_ERROR); + + n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + + value->integer = n; + break; + case IPP_TAG_BOOLEAN : + if (ipp_read(http, buffer, 1) < 1) + return (IPP_ERROR); + + value->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 : + value->string.text = calloc(n + 1, 1); + + if (ipp_read(http, (unsigned char *)value->string.text, n) < n) + return (IPP_ERROR); + + DEBUG_printf(("ippRead: value = \'%s\'\n", + value->string.text)); + break; + case IPP_TAG_DATE : + if (ipp_read(http, value->date, 11) < 11) + return (IPP_ERROR); + break; + case IPP_TAG_RESOLUTION : + if (ipp_read(http, buffer, 9) < 9) + return (IPP_ERROR); + + value->resolution.xres = + (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + value->resolution.yres = + (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | + buffer[7]; + value->resolution.units = + (ipp_res_t)buffer[8]; + break; + case IPP_TAG_RANGE : + if (ipp_read(http, buffer, 8) < 8) + return (IPP_ERROR); + + value->range.lower = + (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + value->range.upper = + (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | + buffer[7]; + break; + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + if (n > sizeof(buffer) || n < 4) + { + DEBUG_printf(("ippRead: bad value length %d!\n", n)); + return (IPP_ERROR); + } + + if (ipp_read(http, 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]; + + value->string.charset = calloc(n + 1, 1); + + memcpy(value->string.charset, + bufptr + 2, n); + + bufptr += 2 + n; + n = (bufptr[0] << 8) | bufptr[1]; + + value->string.text = calloc(n + 1, 1); + + memcpy(value->string.text, + bufptr + 2, n); + break; + + default : /* Other unsupported values */ + value->unknown.length = n; + if (n > 0) + { + value->unknown.data = malloc(n); + if (ipp_read(http, value->unknown.data, n) < n) + return (IPP_ERROR); + } + else + value->unknown.data = NULL; + break; + } + + attr->num_values ++; + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking && http->used == 0) + break; + } + break; + + case IPP_DATA : + break; + + default : + break; /* anti-compiler-warning-code */ + } + + return (ipp->state); +} + + +/* + * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format. + */ + +const ipp_uchar_t * /* O - RFC-1903 date/time data */ +ippTimeToDate(time_t t) /* I - UNIX time value */ +{ + struct tm *unixdate; /* UNIX unixdate/time info */ + static ipp_uchar_t date[11]; /* RFC-1903 date/time data */ + + + /* + * RFC-1903 date/time format is: + * + * Byte(s) Description + * ------- ----------- + * 0-1 Year (0 to 65535) + * 2 Month (1 to 12) + * 3 Day (1 to 31) + * 4 Hours (0 to 23) + * 5 Minutes (0 to 59) + * 6 Seconds (0 to 60, 60 = "leap second") + * 7 Deciseconds (0 to 9) + * 8 +/- UTC + * 9 UTC hours (0 to 11) + * 10 UTC minutes (0 to 59) + */ + + unixdate = gmtime(&t); + unixdate->tm_year += 1900; + + date[0] = unixdate->tm_year >> 8; + date[1] = unixdate->tm_year; + date[2] = unixdate->tm_mon + 1; + date[3] = unixdate->tm_mday; + date[4] = unixdate->tm_hour; + date[5] = unixdate->tm_min; + date[6] = unixdate->tm_sec; + date[7] = 0; + date[8] = '+'; + date[9] = 0; + date[10] = 0; + + return (date); +} + + +/* + * 'ippWrite()' - Write data for an IPP request. + */ + +ipp_state_t /* O - Current state */ +ippWrite(http_t *http, /* I - HTTP data */ + ipp_t *ipp) /* I - IPP data */ +{ + int i; /* Looping var */ + int n; /* Length of data */ + unsigned char buffer[32768], /* Data buffer */ + *bufptr; /* Pointer into buffer */ + ipp_attribute_t *attr; /* Current attribute */ + ipp_value_t *value; /* Current value */ + + + if (http == NULL || ipp == NULL) + return (IPP_ERROR); + + switch (ipp->state) + { + case IPP_IDLE : + ipp->state ++; /* Avoid common problem... */ + + case IPP_HEADER : + /* + * Send the request header: + * + * Version = 2 bytes + * Operation/Status Code = 2 bytes + * Request ID = 4 bytes + * Total = 8 bytes + */ + + 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 (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP header..."); + return (IPP_ERROR); + } + + /* + * Reset the state engine to point to the first attribute + * in the request/response, with no current group. + */ + + ipp->state = IPP_ATTRIBUTE; + ipp->current = ipp->attrs; + ipp->curtag = IPP_TAG_ZERO; + + DEBUG_printf(("ippWrite: version=%d.%d\n", buffer[0], buffer[1])); + DEBUG_printf(("ippWrite: op_status=%04x\n", ipp->request.any.op_status)); + DEBUG_printf(("ippWrite: request_id=%d\n", ipp->request.any.request_id)); + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking) + break; + + 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 tag byte... + */ + + ipp->curtag = attr->group_tag; + + if (attr->group_tag == IPP_TAG_ZERO) + continue; + + DEBUG_printf(("ippWrite: wrote group tag = %x\n", attr->group_tag)); + *bufptr++ = attr->group_tag; + } + + /* + * Get the length of the attribute name, and make sure it won't + * overflow the buffer... + */ + + if ((n = strlen(attr->name)) > (sizeof(buffer) - 4)) + return (IPP_ERROR); + + DEBUG_printf(("ippWrite: writing value tag = %x\n", attr->value_tag)); + DEBUG_printf(("ippWrite: writing name = %d, \'%s\'\n", n, attr->name)); + + /* + * Write the attribute tag and name. The current implementation + * does not support the extension value tags above 0x7f, so all + * value tags are 1 byte. + * + * The attribute name length does not include the trailing nul + * character in the source string. + */ + + *bufptr++ = attr->value_tag; + *bufptr++ = n >> 8; + *bufptr++ = n; + memcpy(bufptr, attr->name, n); + bufptr += n; + + /* + * Now write the attribute value(s)... + */ + + switch (attr->value_tag & ~IPP_TAG_COPY) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + for (i = 0, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if ((sizeof(buffer) - (bufptr - buffer)) < 9) + { + if (httpWrite(http, (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; + } + + /* + * Integers and enumerations are both 4-byte signed + * (twos-complement) values. + * + * Put the 2-byte length and 4-byte value into the buffer... + */ + + *bufptr++ = 0; + *bufptr++ = 4; + *bufptr++ = value->integer >> 24; + *bufptr++ = value->integer >> 16; + *bufptr++ = value->integer >> 8; + *bufptr++ = value->integer; + } + break; + + case IPP_TAG_BOOLEAN : + for (i = 0, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if ((sizeof(buffer) - (bufptr - buffer)) < 6) + { + if (httpWrite(http, (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; + } + + /* + * Boolean values are 1-byte; 0 = false, 1 = true. + * + * Put the 2-byte length and 1-byte value into the buffer... + */ + + *bufptr++ = 0; + *bufptr++ = 1; + *bufptr++ = value->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, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + DEBUG_printf(("ippWrite: writing value tag = %x\n", + attr->value_tag)); + DEBUG_printf(("ippWrite: writing name = 0, \'\'\n")); + + if ((sizeof(buffer) - (bufptr - buffer)) < 3) + { + if (httpWrite(http, (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; + } + + /* + * All simple strings consist of the 2-byte length and + * character data without the trailing nul normally found + * in C strings. Also, strings cannot be longer than 32767 + * bytes since the 2-byte length is a signed (twos-complement) + * value. + */ + + if (value->string.text != NULL) + n = strlen(value->string.text); + else + n = 0; + + if (n > (sizeof(buffer) - 2)) + return (IPP_ERROR); + + DEBUG_printf(("ippWrite: writing string = %d, \'%s\'\n", n, + value->string.text)); + + if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2)) + { + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + bufptr = buffer; + } + + /* + * Put the 2-byte length and string characters in the + * buffer. + */ + + *bufptr++ = n >> 8; + *bufptr++ = n; + + if (n > 0) + { + memcpy(bufptr, value->string.text, n); + bufptr += n; + } + } + break; + + case IPP_TAG_DATE : + for (i = 0, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if ((sizeof(buffer) - (bufptr - buffer)) < 16) + { + if (httpWrite(http, (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; + } + + /* + * Date values consist of a 2-byte length and an + * 11-byte date/time structure defined by RFC 1903. + * + * Put the 2-byte length and 11-byte date/time + * structure in the buffer. + */ + + *bufptr++ = 0; + *bufptr++ = 11; + memcpy(bufptr, value->date, 11); + bufptr += 11; + } + break; + + case IPP_TAG_RESOLUTION : + for (i = 0, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if ((sizeof(buffer) - (bufptr - buffer)) < 14) + { + if (httpWrite(http, (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; + } + + /* + * Resolution values consist of a 2-byte length, + * 4-byte horizontal resolution value, 4-byte vertical + * resolution value, and a 1-byte units value. + * + * Put the 2-byte length and resolution value data + * into the buffer. + */ + + *bufptr++ = 0; + *bufptr++ = 9; + *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, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if ((sizeof(buffer) - (bufptr - buffer)) < 13) + { + if (httpWrite(http, (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; + } + + /* + * Range values consist of a 2-byte length, + * 4-byte lower value, and 4-byte upper value. + * + * Put the 2-byte length and range value data + * into the buffer. + */ + + *bufptr++ = 0; + *bufptr++ = 8; + *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, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + if ((sizeof(buffer) - (bufptr - buffer)) < 3) + { + if (httpWrite(http, (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; + } + + /* + * textWithLanguage and nameWithLanguage values consist + * of a 2-byte length for both strings and their + * individual lengths, a 2-byte length for the + * character string, the character string without the + * trailing nul, a 2-byte length for the character + * set string, and the character set string without + * the trailing nul. + */ + + n = 4; + + if (value->string.charset != NULL) + n += strlen(value->string.charset); + + if (value->string.text != NULL) + n += strlen(value->string.text); + + if (n > (sizeof(buffer) - 2)) + return (IPP_ERROR); + + if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2)) + { + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + bufptr = buffer; + } + + /* Length of entire value */ + *bufptr++ = n >> 8; + *bufptr++ = n; + + /* Length of charset */ + if (value->string.charset != NULL) + n = strlen(value->string.charset); + else + n = 0; + + *bufptr++ = n >> 8; + *bufptr++ = n; + + /* Charset */ + if (n > 0) + { + memcpy(bufptr, value->string.charset, n); + bufptr += n; + } + + /* Length of text */ + if (value->string.text != NULL) + n = strlen(value->string.text); + else + n = 0; + + *bufptr++ = n >> 8; + *bufptr++ = n; + + /* Text */ + if (n > 0) + { + memcpy(bufptr, value->string.text, n); + bufptr += n; + } + } + break; + + default : + for (i = 0, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + if ((sizeof(buffer) - (bufptr - buffer)) < 3) + { + if (httpWrite(http, (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; + } + + /* + * An unknown value might just be a collection value, + * or some new value that a vendor has come up with. + * It consists of a 2-byte length and the bytes in + * the unknown value buffer. + */ + + n = value->unknown.length; + + if (n > (sizeof(buffer) - 2)) + return (IPP_ERROR); + + if ((sizeof(buffer) - (bufptr - buffer)) < (n + 2)) + { + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: 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, value->unknown.data, n); + bufptr += n; + } + } + break; + } + + /* + * Write the data out... + */ + + if (httpWrite(http, (char *)buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + DEBUG_printf(("ippWrite: wrote %d bytes\n", bufptr - buffer)); + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking) + break; + } + + if (ipp->current == NULL) + { + /* + * Done with all of the attributes; add the end-of-attributes tag... + */ + + buffer[0] = IPP_TAG_END; + if (httpWrite(http, (char *)buffer, 1) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP end-tag..."); + return (IPP_ERROR); + } + + ipp->state = IPP_DATA; + } + break; + + case IPP_DATA : + break; + + default : + break; /* anti-compiler-warning-code */ + } + + return (ipp->state); +} + + +/* + * '_ipp_add_attr()' - Add a new attribute to the request. + */ + +ipp_attribute_t * /* O - New attribute */ +_ipp_add_attr(ipp_t *ipp, /* I - IPP request */ + int num_values) /* I - Number of values */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("_ipp_add_attr(%p, %d)\n", ipp, num_values)); + + if (ipp == NULL || num_values < 0) + return (NULL); + + attr = calloc(sizeof(ipp_attribute_t) + + (num_values - 1) * sizeof(ipp_value_t), 1); + + attr->num_values = num_values; + + if (attr == NULL) + return (NULL); + + if (ipp->last == NULL) + ipp->attrs = attr; + else + ipp->last->next = attr; + + ipp->last = attr; + + DEBUG_printf(("_ipp_add_attr(): %p\n", attr)); + + return (attr); +} + + +/* + * '_ipp_free_attr()' - Free an attribute. + */ + +void +_ipp_free_attr(ipp_attribute_t *attr) /* I - Attribute to free */ +{ + int i; /* Looping var */ + ipp_value_t *value; /* Current value */ + + + DEBUG_printf(("_ipp_free_attr(): %p\n", attr)); + + switch (attr->value_tag) + { + 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, 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, value = attr->values; + i < attr->num_values; + i ++, value ++) + { + if (value->string.charset && i == 0) + free(value->string.charset); + free(value->string.text); + } + break; + + default : + break; /* anti-compiler-warning-code */ + } + + if (attr->name != NULL) + free(attr->name); + + free(attr); +} + + +/* + * 'ipp_read()' - Semi-blocking read on a HTTP connection... + */ + +static int /* O - Number of bytes read */ +ipp_read(http_t *http, /* I - Client connection */ + unsigned char *buffer, /* O - Buffer for data */ + int length) /* I - Total length */ +{ + int tbytes, /* Total bytes read */ + bytes; /* Bytes read this pass */ + char len[32]; /* Length string */ + + + /* + * Loop until all bytes are read... + */ + + for (tbytes = 0, bytes = 0; tbytes < length; tbytes += bytes, buffer += bytes) + { + 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) + memmove(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... + */ + + if (tbytes == 0 && bytes < 0) + return (-1); + else + return (tbytes); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/ipp.h b/cups/ipp.h new file mode 100644 index 0000000000..cbf1c2ee9f --- /dev/null +++ b/cups/ipp.h @@ -0,0 +1,434 @@ +/* + * "$Id$" + * + * Internet Printing Protocol definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_IPP_H_ +# define _CUPS_IPP_H_ + +/* + * Include necessary headers... + */ + +# include "http.h" + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * IPP version string... + */ + +# define IPP_VERSION "\001\001" + +/* + * IPP registered port number... This is the default value - applications + * should use the ippPort() function so that you can customize things in + * /etc/services if needed! + */ + +# define IPP_PORT 631 + +/* + * Common limits... + */ + +# define IPP_MAX_NAME 256 +# define IPP_MAX_VALUES 10 /* Now just an allocation increment */ + + +/* + * Types and structures... + */ + +typedef enum /**** Format tags for attribute formats... ****/ +{ + IPP_TAG_ZERO = 0x00, + IPP_TAG_OPERATION, + IPP_TAG_JOB, + IPP_TAG_END, + IPP_TAG_PRINTER, + IPP_TAG_UNSUPPORTED_GROUP, + IPP_TAG_SUBSCRIPTION, + IPP_TAG_EVENT_NOTIFICATION, + IPP_TAG_UNSUPPORTED_VALUE = 0x10, + IPP_TAG_DEFAULT, + IPP_TAG_UNKNOWN, + IPP_TAG_NOVALUE, + IPP_TAG_NOTSETTABLE = 0x15, + IPP_TAG_DELETEATTR, + IPP_TAG_ADMINDEFINE, + IPP_TAG_INTEGER = 0x21, + IPP_TAG_BOOLEAN, + IPP_TAG_ENUM, + IPP_TAG_STRING = 0x30, + IPP_TAG_DATE, + IPP_TAG_RESOLUTION, + IPP_TAG_RANGE, + IPP_TAG_BEGIN_COLLECTION, + IPP_TAG_TEXTLANG, + IPP_TAG_NAMELANG, + IPP_TAG_END_COLLECTION, + IPP_TAG_TEXT = 0x41, + IPP_TAG_NAME, + IPP_TAG_KEYWORD = 0x44, + IPP_TAG_URI, + IPP_TAG_URISCHEME, + IPP_TAG_CHARSET, + IPP_TAG_LANGUAGE, + IPP_TAG_MIMETYPE, + IPP_TAG_MEMBERNAME, + IPP_TAG_MASK = 0x7fffffff, /* Mask for copied attribute values */ + IPP_TAG_COPY = -0x7fffffff-1 /* Bitflag for copied attribute values */ +} ipp_tag_t; + +typedef enum /**** Resolution units... ****/ +{ + IPP_RES_PER_INCH = 3, + IPP_RES_PER_CM +} ipp_res_t; + +typedef enum /**** Finishings... ****/ +{ + IPP_FINISHINGS_NONE = 3, + IPP_FINISHINGS_STAPLE, + IPP_FINISHINGS_PUNCH, + IPP_FINISHINGS_COVER, + IPP_FINISHINGS_BIND, + IPP_FINISHINGS_SADDLE_STITCH, + IPP_FINISHINGS_EDGE_STITCH, + IPP_FINISHINGS_FOLD, + IPP_FINISHINGS_TRIM, + IPP_FINISHINGS_BALE, + IPP_FINISHINGS_BOOKLET_MAKER, + IPP_FINISHINGS_JOB_OFFSET, + IPP_FINISHINGS_STAPLE_TOP_LEFT = 20, + IPP_FINISHINGS_STAPLE_BOTTOM_LEFT, + IPP_FINISHINGS_STAPLE_TOP_RIGHT, + IPP_FINISHINGS_STAPLE_BOTTOM_RIGHT, + IPP_FINISHINGS_EDGE_STITCH_LEFT, + IPP_FINISHINGS_EDGE_STITCH_TOP, + IPP_FINISHINGS_EDGE_STITCH_RIGHT, + IPP_FINISHINGS_EDGE_STITCH_BOTTOM, + IPP_FINISHINGS_STAPLE_DUAL_LEFT, + IPP_FINISHINGS_STAPLE_DUAL_TOP, + IPP_FINISHINGS_STAPLE_DUAL_RIGHT, + IPP_FINISHINGS_STAPLE_DUAL_BOTTOM, + IPP_FINISHINGS_BIND_LEFT = 50, + IPP_FINISHINGS_BIND_TOP, + IPP_FINISHINGS_BIND_RIGHT, + IPP_FINISHINGS_BIND_BOTTOM +} ipp_finish_t; + +typedef enum /**** Orientation... ****/ +{ + IPP_PORTRAIT = 3, /* No rotation */ + IPP_LANDSCAPE, /* 90 degrees counter-clockwise */ + IPP_REVERSE_LANDSCAPE, /* 90 degrees clockwise */ + IPP_REVERSE_PORTRAIT /* 180 degrees */ +} ipp_orient_t; + +typedef enum /**** Qualities... ****/ +{ + IPP_QUALITY_DRAFT = 3, + IPP_QUALITY_NORMAL, + IPP_QUALITY_HIGH +} ipp_quality_t; + +typedef enum /**** Job States.... */ +{ + IPP_JOB_PENDING = 3, + IPP_JOB_HELD, + IPP_JOB_PROCESSING, + IPP_JOB_STOPPED, + IPP_JOB_CANCELLED, + IPP_JOB_ABORTED, + IPP_JOB_COMPLETED +} ipp_jstate_t; + +typedef enum /**** Printer States.... */ +{ + IPP_PRINTER_IDLE = 3, + IPP_PRINTER_PROCESSING, + IPP_PRINTER_STOPPED +} ipp_pstate_t; + +typedef enum /**** IPP states... ****/ +{ + IPP_ERROR = -1, /* An error occurred */ + IPP_IDLE, /* Nothing is happening/request completed */ + IPP_HEADER, /* The request header needs to be sent/received */ + IPP_ATTRIBUTE, /* One or more attributes need to be sent/received */ + IPP_DATA /* IPP request data needs to be sent/received */ +} ipp_state_t; + +typedef enum /**** IPP operations... ****/ +{ + IPP_PRINT_JOB = 0x0002, + IPP_PRINT_URI, + IPP_VALIDATE_JOB, + IPP_CREATE_JOB, + IPP_SEND_DOCUMENT, + IPP_SEND_URI, + IPP_CANCEL_JOB, + IPP_GET_JOB_ATTRIBUTES, + IPP_GET_JOBS, + IPP_GET_PRINTER_ATTRIBUTES, + IPP_HOLD_JOB, + IPP_RELEASE_JOB, + IPP_RESTART_JOB, + IPP_PAUSE_PRINTER = 0x0010, + IPP_RESUME_PRINTER, + IPP_PURGE_JOBS, + IPP_SET_PRINTER_ATTRIBUTES, + IPP_SET_JOB_ATTRIBUTES, + IPP_GET_PRINTER_SUPPORTED_VALUES, + IPP_CREATE_PRINTER_SUBSCRIPTION, + IPP_CREATE_JOB_SUBSCRIPTION, + IPP_GET_SUBSCRIPTION_ATTRIBUTES, + IPP_GET_SUBSCRIPTIONS, + IPP_RENEW_SUBSCRIPTION, + IPP_CANCEL_SUBSCRIPTION, + IPP_GET_NOTIFICATIONS, + IPP_SEND_NOTIFICATIONS, + IPP_GET_PRINT_SUPPORT_FILES = 0x0021, + IPP_ENABLE_PRINTER, + IPP_DISABLE_PRINTER, + IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB, + IPP_HOLD_NEW_JOBS, + IPP_RELEASE_HELD_NEW_JOBS, + IPP_DEACTIVATE_PRINTER, + IPP_ACTIVATE_PRINTER, + IPP_RESTART_PRINTER, + IPP_SHUTDOWN_PRINTER, + IPP_STARTUP_PRINTER, + IPP_REPROCESS_JOB, + IPP_CANCEL_CURRENT_JOB, + IPP_SUSPEND_CURRENT_JOB, + IPP_RESUME_JOB, + IPP_PROMOTE_JOB, + IPP_SCHEDULE_JOB_AFTER, + IPP_PRIVATE = 0x4000, + CUPS_GET_DEFAULT, + CUPS_GET_PRINTERS, + CUPS_ADD_PRINTER, + CUPS_DELETE_PRINTER, + CUPS_GET_CLASSES, + CUPS_ADD_CLASS, + CUPS_DELETE_CLASS, + CUPS_ACCEPT_JOBS, + CUPS_REJECT_JOBS, + CUPS_SET_DEFAULT, + CUPS_GET_DEVICES, + CUPS_GET_PPDS, + CUPS_MOVE_JOB, + CUPS_ADD_DEVICE, + CUPS_DELETE_DEVICE +} ipp_op_t; + +typedef enum /**** IPP status codes... ****/ +{ + IPP_OK = 0x0000, + IPP_OK_SUBST, + IPP_OK_CONFLICT, + IPP_OK_IGNORED_SUBSCRIPTIONS, + IPP_OK_IGNORED_NOTIFICATIONS, + IPP_OK_TOO_MANY_EVENTS, + IPP_OK_BUT_CANCEL_SUBSCRIPTION, + IPP_REDIRECTION_OTHER_SITE = 0x300, + IPP_BAD_REQUEST = 0x0400, + IPP_FORBIDDEN, + IPP_NOT_AUTHENTICATED, + IPP_NOT_AUTHORIZED, + IPP_NOT_POSSIBLE, + IPP_TIMEOUT, + IPP_NOT_FOUND, + IPP_GONE, + IPP_REQUEST_ENTITY, + IPP_REQUEST_VALUE, + IPP_DOCUMENT_FORMAT, + IPP_ATTRIBUTES, + IPP_URI_SCHEME, + IPP_CHARSET, + IPP_CONFLICT, + IPP_COMPRESSION_NOT_SUPPORTED, + IPP_COMPRESSION_ERROR, + IPP_DOCUMENT_FORMAT_ERROR, + IPP_DOCUMENT_ACCESS_ERROR, + IPP_ATTRIBUTES_NOT_SETTABLE, + IPP_IGNORED_ALL_SUBSCRIPTIONS, + IPP_TOO_MANY_SUBSCRIPTIONS, + IPP_IGNORED_ALL_NOTIFICATIONS, + IPP_PRINT_SUPPORT_FILE_NOT_FOUND, + + IPP_INTERNAL_ERROR = 0x0500, + IPP_OPERATION_NOT_SUPPORTED, + IPP_SERVICE_UNAVAILABLE, + IPP_VERSION_NOT_SUPPORTED, + IPP_DEVICE_ERROR, + IPP_TEMPORARY_ERROR, + IPP_NOT_ACCEPTING, + IPP_PRINTER_BUSY, + IPP_ERROR_JOB_CANCELLED, + IPP_MULTIPLE_JOBS_NOT_SUPPORTED, + IPP_PRINTER_IS_DEACTIVATED +} ipp_status_t; + +typedef unsigned char ipp_uchar_t;/**** Unsigned 8-bit integer/character ****/ + +typedef union /**** Request Header ****/ +{ + struct /* Any Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + int op_status; /* Operation ID or status code*/ + int request_id; /* Request ID */ + } any; + + struct /* Operation Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + ipp_op_t operation_id; /* Operation ID */ + int request_id; /* Request ID */ + } op; + + struct /* Status Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + ipp_status_t status_code; /* Status code */ + int request_id; /* Request ID */ + } status; +} ipp_request_t; + + +typedef union /**** Attribute Value ****/ +{ + int integer; /* Integer/enumerated value */ + + char boolean; /* Boolean value */ + + ipp_uchar_t date[11]; /* Date/time value */ + + struct + { + int xres, /* Horizontal resolution */ + yres; /* Vertical resolution */ + ipp_res_t units; /* Resolution units */ + } resolution; /* Resolution value */ + + struct + { + int lower, /* Lower value */ + upper; /* Upper value */ + } range; /* Range of integers value */ + + struct + { + char *charset; /* Character set */ + char *text; /* String */ + } string; /* String with language value */ + + struct + { + int length; /* Length of attribute */ + void *data; /* Data in attribute */ + } unknown; /* Unknown attribute type */ +} ipp_value_t; + +typedef struct ipp_attribute_s /**** Attribute ****/ +{ + 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 */ + int num_values; /* Number of values */ + ipp_value_t values[1]; /* Values */ +} ipp_attribute_t; + +typedef struct /**** Request State ****/ +{ + ipp_state_t state; /* State of request */ + ipp_request_t request; /* Request header */ + ipp_attribute_t *attrs, /* Attributes */ + *last, /* Last attribute in list */ + *current; /* Current attribute (for read/write) */ + ipp_tag_t curtag; /* Current attribute group tag */ +} ipp_t; + + +/* + * Prototypes... + */ + +extern ipp_attribute_t *ippAddBoolean(ipp_t *ipp, ipp_tag_t group, const char *name, char value); +extern ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const char *values); +extern ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group, const char *name, const ipp_uchar_t *value); +extern ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int value); +extern ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const int *values); +extern ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group, const char *name, int lower, int upper); +extern ipp_attribute_t *ippAddRanges(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const int *lower, const int *upper); +extern ipp_attribute_t *ippAddResolution(ipp_t *ipp, ipp_tag_t group, const char *name, ipp_res_t units, int xres, int yres); +extern ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, ipp_res_t units, const int *xres, const int *yres); +extern ipp_attribute_t *ippAddSeparator(ipp_t *ipp); +extern ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, const char *charset, const char *value); +extern ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const char *charset, const char **values); +extern time_t ippDateToTime(const ipp_uchar_t *date); +extern void ippDelete(ipp_t *ipp); +extern const char *ippErrorString(ipp_status_t error); +extern ipp_attribute_t *ippFindAttribute(ipp_t *ipp, const char *name, + ipp_tag_t type); +extern ipp_attribute_t *ippFindNextAttribute(ipp_t *ipp, const char *name, + ipp_tag_t type); +extern size_t ippLength(ipp_t *ipp); +extern ipp_t *ippNew(void); +extern ipp_state_t ippRead(http_t *http, ipp_t *ipp); +extern const ipp_uchar_t *ippTimeToDate(time_t t); +extern ipp_state_t ippWrite(http_t *http, ipp_t *ipp); +extern int ippPort(void); +extern void ippSetPort(int p); + +extern ipp_attribute_t *_ipp_add_attr(ipp_t *, int); +extern void _ipp_free_attr(ipp_attribute_t *); + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_IPP_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/language.c b/cups/language.c new file mode 100644 index 0000000000..fc54316568 --- /dev/null +++ b/cups/language.c @@ -0,0 +1,427 @@ +/* + * "$Id$" + * + * I18N/language support for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsLangEncoding() - Return the character encoding (us-ascii, etc.) + * for the given language. + * cupsLangFlush() - Flush all language data out of the cache. + * cupsLangFree() - Free language data. + * cupsLangGet() - Get a language. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include "string.h" +#include "language.h" + + +/* + * Local globals... + */ + +static cups_lang_t *lang_cache = NULL; /* Language string cache */ +static char *lang_blank = ""; /* Blank constant string */ +static char *lang_encodings[] = /* Encoding strings */ + { + "us-ascii", + "iso-8859-1", + "iso-8859-2", + "iso-8859-3", + "iso-8859-4", + "iso-8859-5", + "iso-8859-6", + "iso-8859-7", + "iso-8859-8", + "iso-8859-9", + "iso-8859-10", + "utf-8", + "iso-8859-13", + "iso-8859-14", + "iso-8859-15", + "windows-874", + "windows-1250", + "windows-1251", + "windows-1252", + "windows-1253", + "windows-1254", + "windows-1255", + "windows-1256", + "windows-1257", + "windows-1258", + "koi8-r", + "koi8-u" + }; +static char *lang_default[] = /* Default POSIX locale */ + { +#include "cups_C.h" + NULL + }; + + +/* + * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.) + * for the given language. + */ + +char * /* O - Character encoding */ +cupsLangEncoding(cups_lang_t *lang) /* I - Language data */ +{ + if (lang == NULL) + return (lang_encodings[0]); + else + return (lang_encodings[lang->encoding]); +} + + +/* + * 'cupsLangFlush()' - Flush all language data out of the cache. + */ + +void +cupsLangFlush(void) +{ + int i; /* Looping var */ + cups_lang_t *lang, /* Current language */ + *next; /* Next language */ + + + for (lang = lang_cache; lang != NULL; lang = next) + { + for (i = 0; i < CUPS_MSG_MAX; i ++) + if (lang->messages[i] != NULL && lang->messages[i] != lang_blank) + free(lang->messages[i]); + + next = lang->next; + free(lang); + } +} + + +/* + * 'cupsLangFree()' - Free language data. + * + * This does not actually free anything; use cupsLangFlush() for that. + */ + +void +cupsLangFree(cups_lang_t *lang) /* I - Language to free */ +{ + if (lang != NULL && lang->used > 0) + lang->used --; +} + + +/* + * 'cupsLangGet()' - Get a language. + */ + +cups_lang_t * /* O - Language data */ +cupsLangGet(const char *language) /* I - Language or locale */ +{ + int i, count; /* Looping vars */ + char langname[32], /* Requested language name */ + *langptr, /* Pointer into language name */ + real[32], /* Real language name */ + *realptr, /* Pointer into real language name */ + filename[1024], /* Filename for language locale file */ + *localedir; /* Directory for locale files */ + FILE *fp; /* Language locale file pointer */ + char line[1024]; /* Line from file */ + cups_msg_t msg; /* Message number */ + char *text; /* Message text */ + cups_lang_t *lang; /* Current language... */ + + + /* + * Convert the language string passed in to a locale string. "C" is the + * standard POSIX locale and is copied unchanged. Otherwise the + * language string is converted from ll-cc (language-country) to ll_cc + * to match the file naming convention used by all POSIX-compliant + * operating systems. + */ + + if (language == NULL || language[0] == '\0' || + strcmp(language, "POSIX") == 0) + strcpy(langname, "C"); + else + { + /* + * Copy the locale string over safely... + */ + + strlcpy(langname, language, sizeof(langname)); + } + + if (strlen(langname) < 2) + strcpy(real, "C"); + else + { + /* + * Convert the language name to a normalized form, e.g.: + * + * ll[_CC[.charset]] + */ + + real[0] = tolower(langname[0]); + real[1] = tolower(langname[1]); + realptr = real + 2; + langptr = langname + 2; + + if (*langptr == '_' || *langptr == '-') + { + /* + * Add country code... + */ + + *realptr++ = '_'; + langptr ++; + + *realptr++ = toupper(*langptr++); + *realptr++ = toupper(*langptr++); + } + + if (*langptr == '.') + { + /* + * Add charset... + */ + + *langptr++ = '\0'; + *realptr++ = '.'; + + while (*langptr) + { + if ((realptr - real) < (sizeof(real) - 1) && + *langptr != '-' && *langptr != '_') + *realptr++ = tolower(*langptr++); + else + langptr ++; + } + } + + *realptr = '\0'; + } + + /* + * See if we already have this language loaded... + */ + + for (lang = lang_cache; lang != NULL; lang = lang->next) + if (strcmp(lang->language, langname) == 0) + { + lang->used ++; + + return (lang); + } + + + /* + * Next try to open a locale file; we will try the charset-localized + * file first, then the country-localized file, and finally look for + * a generic language file. If all else fails we will use the POSIX + * locale. + */ + + if ((localedir = getenv("LOCALEDIR")) == NULL) + localedir = CUPS_LOCALEDIR; + + for (fp = NULL; fp == NULL;) + { + snprintf(filename, sizeof(filename), "%s/%s/cups_%s", localedir, + real, real); + + if ((fp = fopen(filename, "r")) == NULL) + { + if ((realptr = strchr(real, '.')) != NULL) + *realptr = '\0'; + else if ((realptr = strchr(real, '_')) != NULL) + *realptr = '\0'; + else + break; + } + } + + /* + * OK, we have an open messages file; the first line will contain the + * language encoding (us-ascii, iso-8859-1, etc.), and the rest will + * be messages consisting of: + * + * #### SP message text + * + * or: + * + * message text + * + * If the line starts with a number, then message processing picks up + * where the number indicates. Otherwise the last message number is + * incremented. + * + * All leading whitespace is deleted. + */ + + if (fp == NULL) + strlcpy(line, lang_default[0], sizeof(line)); + else if (fgets(line, sizeof(line), fp) == NULL) + { + /* + * Can't read encoding! + */ + + fclose(fp); + return (NULL); + } + + i = strlen(line) - 1; + if (line[i] == '\n') + line[i] = '\0'; /* Strip LF */ + + /* + * See if there is a free language available; if so, use that + * record... + */ + + for (lang = lang_cache; lang != NULL; lang = lang->next) + if (lang->used == 0) + break; + + if (lang == NULL) + { + /* + * Allocate memory for the language and add it to the cache. + */ + + if ((lang = calloc(sizeof(cups_lang_t), 1)) == NULL) + { + fclose(fp); + return (NULL); + } + + lang->next = lang_cache; + lang_cache = lang; + } + + /* + * Free all old strings as needed... + */ + + for (i = 0; i < CUPS_MSG_MAX; i ++) + { + if (lang->messages[i] != NULL && lang->messages[i] != lang_blank) + free(lang->messages[i]); + + lang->messages[i] = lang_blank; + } + + /* + * Then assign the language and encoding fields... + */ + + lang->used ++; + strlcpy(lang->language, langname, sizeof(lang->language)); + + for (i = 0; i < (sizeof(lang_encodings) / sizeof(lang_encodings[0])); i ++) + if (strcmp(lang_encodings[i], line) == 0) + { + lang->encoding = (cups_encoding_t)i; + break; + } + + /* + * Read the strings from the file... + */ + + msg = (cups_msg_t)-1; + count = 1; + + for (;;) + { + /* + * Read a line from memory or from a file... + */ + + if (fp == NULL) + { + if (lang_default[count] == NULL) + break; + + strlcpy(line, lang_default[count], sizeof(line)); + } + else if (fgets(line, sizeof(line), fp) == NULL) + break; + + count ++; + + /* + * Ignore blank lines... + */ + + i = strlen(line) - 1; + if (line[i] == '\n') + line[i] = '\0'; /* Strip LF */ + + if (line[0] == '\0') + continue; + + /* + * Grab the message number and text... + */ + + if (isdigit(line[0])) + msg = (cups_msg_t)atoi(line); + else + msg ++; + + if (msg < 0 || msg >= CUPS_MSG_MAX) + continue; + + text = line; + while (isdigit(*text)) + text ++; + while (isspace(*text)) + text ++; + + lang->messages[msg] = strdup(text); + } + + /* + * Close the file and return... + */ + + if (fp != NULL) + fclose(fp); + + return (lang); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/language.h b/cups/language.h new file mode 100644 index 0000000000..d636d58021 --- /dev/null +++ b/cups/language.h @@ -0,0 +1,228 @@ +/* + * "$Id$" + * + * Multi-language support for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_LANGUAGE_H_ +# define _CUPS_LANGUAGE_H_ + +/* + * Include necessary headers... + */ + +# include + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +/* + * Messages... + */ + +typedef enum /**** Message Indices ****/ +{ + CUPS_MSG_OK, + CUPS_MSG_CANCEL, + CUPS_MSG_HELP, + CUPS_MSG_QUIT, + CUPS_MSG_CLOSE, + CUPS_MSG_YES, + CUPS_MSG_NO, + CUPS_MSG_ON, + CUPS_MSG_OFF, + CUPS_MSG_SAVE, + CUPS_MSG_DISCARD, + CUPS_MSG_DEFAULT, + CUPS_MSG_OPTIONS, + CUPS_MSG_MORE_INFO, + CUPS_MSG_BLACK, + CUPS_MSG_COLOR, + CUPS_MSG_CYAN, + CUPS_MSG_MAGENTA, + CUPS_MSG_YELLOW, + CUPS_MSG_COPYRIGHT, + CUPS_MSG_GENERAL, + CUPS_MSG_PRINTER, + CUPS_MSG_IMAGE, + CUPS_MSG_HPGL2, + CUPS_MSG_EXTRA, + CUPS_MSG_DOCUMENT, + CUPS_MSG_OTHER, + CUPS_MSG_PRINT_PAGES, + CUPS_MSG_ENTIRE_DOCUMENT, + CUPS_MSG_PAGE_RANGE, + CUPS_MSG_REVERSE_ORDER, + CUPS_MSG_PAGE_FORMAT, + CUPS_MSG_1_UP, + CUPS_MSG_2_UP, + CUPS_MSG_4_UP, + CUPS_MSG_IMAGE_SCALING, + CUPS_MSG_USE_NATURAL_IMAGE_SIZE, + CUPS_MSG_ZOOM_BY_PERCENT, + CUPS_MSG_ZOOM_BY_PPI, + CUPS_MSG_MIRROR_IMAGE, + CUPS_MSG_COLOR_SATURATION, + CUPS_MSG_COLOR_HUE, + CUPS_MSG_FIT_TO_PAGE, + CUPS_MSG_SHADING, + CUPS_MSG_DEFAULT_PEN_WIDTH, + CUPS_MSG_GAMMA_CORRECTION, + CUPS_MSG_BRIGHTNESS, + CUPS_MSG_ADD, + CUPS_MSG_DELETE, + CUPS_MSG_MODIFY, + CUPS_MSG_PRINTER_URI, + CUPS_MSG_PRINTER_NAME, + CUPS_MSG_PRINTER_LOCATION, + CUPS_MSG_PRINTER_INFO, + CUPS_MSG_PRINTER_MAKE_AND_MODEL, + CUPS_MSG_DEVICE_URI, + CUPS_MSG_FORMATTING_PAGE, + CUPS_MSG_PRINTING_PAGE, + CUPS_MSG_INITIALIZING_PRINTER, + CUPS_MSG_PRINTER_STATE, + CUPS_MSG_ACCEPTING_JOBS, + CUPS_MSG_NOT_ACCEPTING_JOBS, + CUPS_MSG_PRINT_JOBS, + CUPS_MSG_CLASS, + CUPS_MSG_LOCAL, + CUPS_MSG_REMOTE, + CUPS_MSG_DUPLEXING, + CUPS_MSG_STAPLING, + CUPS_MSG_FAST_COPIES, + CUPS_MSG_COLLATED_COPIES, + CUPS_MSG_PUNCHING, + CUPS_MSG_COVERING, + CUPS_MSG_BINDING, + CUPS_MSG_SORTING, + CUPS_MSG_SMALL, + CUPS_MSG_MEDIUM, + CUPS_MSG_LARGE, + CUPS_MSG_VARIABLE, + CUPS_MSG_IDLE, + CUPS_MSG_PROCESSING, + CUPS_MSG_STOPPED, + CUPS_MSG_ALL, + CUPS_MSG_ODD, + CUPS_MSG_EVEN_PAGES, + CUPS_MSG_DARKER_LIGHTER, + CUPS_MSG_MEDIA_SIZE, + CUPS_MSG_MEDIA_TYPE, + CUPS_MSG_MEDIA_SOURCE, + CUPS_MSG_ORIENTATION, + CUPS_MSG_PORTRAIT, + CUPS_MSG_LANDSCAPE, + CUPS_MSG_JOB_STATE, + CUPS_MSG_JOB_NAME, + CUPS_MSG_USER_NAME, + CUPS_MSG_PRIORITY, + CUPS_MSG_COPIES, + CUPS_MSG_FILE_SIZE, + CUPS_MSG_PENDING, + CUPS_MSG_OUTPUT_MODE, + CUPS_MSG_RESOLUTION, + CUPS_MSG_TEXT, + CUPS_MSG_PRETTYPRINT, + CUPS_MSG_MARGINS, + CUPS_MSG_LEFT, + CUPS_MSG_RIGHT, + CUPS_MSG_BOTTOM, + CUPS_MSG_TOP, + CUPS_MSG_FILENAME, + CUPS_MSG_PRINT, + CUPS_MSG_OPTIONS_INSTALLED, + CUPS_MSG_AUTO, + CUPS_MSG_HTTP_BASE = 200, + CUPS_MSG_HTTP_END = 505, + CUPS_MSG_MAX +} cups_msg_t; + +typedef enum /**** Language Encodings ****/ +{ + CUPS_US_ASCII, + CUPS_ISO8859_1, + CUPS_ISO8859_2, + CUPS_ISO8859_3, + CUPS_ISO8859_4, + CUPS_ISO8859_5, + CUPS_ISO8859_6, + CUPS_ISO8859_7, + CUPS_ISO8859_8, + CUPS_ISO8859_9, + CUPS_ISO8859_10, + CUPS_UTF8, + CUPS_ISO8859_13, + CUPS_ISO8859_14, + CUPS_ISO8859_15, + CUPS_WINDOWS_874, + CUPS_WINDOWS_1250, + CUPS_WINDOWS_1251, + CUPS_WINDOWS_1252, + CUPS_WINDOWS_1253, + CUPS_WINDOWS_1254, + CUPS_WINDOWS_1255, + CUPS_WINDOWS_1256, + CUPS_WINDOWS_1257, + CUPS_WINDOWS_1258, + CUPS_KOI8_R, + CUPS_KOI8_U +} cups_encoding_t; + +typedef struct cups_lang_str /**** Language Cache Structure ****/ +{ + struct cups_lang_str *next; /* Next language in cache */ + int used; /* Number of times this entry has been used. */ + cups_encoding_t encoding; /* Text encoding */ + char language[16]; /* Language/locale name */ + char *messages[CUPS_MSG_MAX]; + /* Message array */ +} cups_lang_t; + + +/* + * Prototypes... + */ + +# if defined(WIN32) || defined(__EMX__) || defined(__APPLE__) +# define cupsLangDefault() cupsLangGet(setlocale(LC_ALL, "")) +# else +# define cupsLangDefault() cupsLangGet(setlocale(LC_MESSAGES, "")) +# endif /* WIN32 || __EMX__ || __APPLE__ */ + +extern char *cupsLangEncoding(cups_lang_t *lang); +extern void cupsLangFlush(void); +extern void cupsLangFree(cups_lang_t *lang); +extern cups_lang_t *cupsLangGet(const char *language); +# define cupsLangString(lang,msg) (lang)->messages[(msg)] + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_CUPS_LANGUAGE_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/mark.c b/cups/mark.c new file mode 100644 index 0000000000..04937c430d --- /dev/null +++ b/cups/mark.c @@ -0,0 +1,443 @@ +/* + * "$Id$" + * + * Option marking routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * ppdConflicts() - Check to see if there are any conflicts. + * ppdFindChoice() - Return a pointer to an option choice. + * ppdFindMarkedChoice() - Return the marked choice for the specified option. + * ppdFindOption() - Return a pointer to the specified option. + * ppdIsMarked() - Check to see if an option is marked... + * ppdMarkDefaults() - Mark all default options in the PPD file. + * ppdMarkOption() - Mark an option in a PPD file. + * ppd_defaults() - Set the defaults for this group and all sub-groups. + */ + +/* + * Include necessary headers... + */ + +#include "ppd.h" +#include "string.h" +#include "debug.h" + + +/* + * Local functions... + */ + +static void ppd_defaults(ppd_file_t *ppd, ppd_group_t *g); + + +/* + * 'ppdConflicts()' - Check to see if there are any conflicts. + */ + +int /* O - Number of conflicts found */ +ppdConflicts(ppd_file_t *ppd) /* I - PPD to check */ +{ + int i, j, k, /* Looping variables */ + conflicts; /* Number of conflicts */ + ppd_const_t *c; /* Current constraint */ + ppd_group_t *g, *sg; /* Groups */ + ppd_option_t *o1, *o2; /* Options */ + ppd_choice_t *c1, *c2; /* Choices */ + + + if (ppd == NULL) + return (0); + + /* + * Clear all conflicts... + */ + + conflicts = 0; + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + { + for (j = g->num_options, o1 = g->options; j > 0; j --, o1 ++) + o1->conflicted = 0; + + for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++) + for (k = sg->num_options, o1 = sg->options; k > 0; k --, o1 ++) + o1->conflicted = 0; + } + + /* + * Loop through all of the UI constraints and flag any options + * that conflict... + */ + + for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++) + { + /* + * Grab pointers to the first option... + */ + + o1 = ppdFindOption(ppd, c->option1); + + if (o1 == NULL) + continue; + else if (c->choice1[0] != '\0') + { + /* + * This constraint maps to a specific choice. + */ + + c1 = ppdFindChoice(o1, c->choice1); + } + else + { + /* + * This constraint applies to any choice for this option. + */ + + for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++) + if (c1->marked) + break; + + if (j == 0 || + strcasecmp(c1->choice, "None") == 0 || + strcasecmp(c1->choice, "Off") == 0 || + strcasecmp(c1->choice, "False") == 0) + c1 = NULL; + } + + /* + * Grab pointers to the second option... + */ + + o2 = ppdFindOption(ppd, c->option2); + + if (o2 == NULL) + continue; + else if (c->choice2[0] != '\0') + { + /* + * This constraint maps to a specific choice. + */ + + c2 = ppdFindChoice(o2, c->choice2); + } + else + { + /* + * This constraint applies to any choice for this option. + */ + + for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++) + if (c2->marked) + break; + + if (j == 0 || + strcasecmp(c2->choice, "None") == 0 || + strcasecmp(c2->choice, "Off") == 0 || + strcasecmp(c2->choice, "False") == 0) + c2 = NULL; + } + + /* + * If both options are marked then there is a conflict... + */ + + if (c1 != NULL && c1->marked && + c2 != NULL && c2->marked) + { + DEBUG_printf(("%s->%s conflicts with %s->%s (%s %s %s %s)\n", + o1->keyword, c1->choice, o2->keyword, c2->choice, + c->option1, c->choice1, c->option2, c->choice2)); + conflicts ++; + o1->conflicted = 1; + o2->conflicted = 1; + } + } + + /* + * Return the number of conflicts found... + */ + + return (conflicts); +} + + +/* + * 'ppdFindChoice()' - Return a pointer to an option choice. + */ + +ppd_choice_t * /* O - Choice pointer or NULL */ +ppdFindChoice(ppd_option_t *o, /* I - Pointer to option */ + const char *choice) /* I - Name of choice */ +{ + int i; /* Looping var */ + ppd_choice_t *c; /* Current choice */ + + + if (o == NULL || choice == NULL) + return (NULL); + + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (strcasecmp(c->choice, choice) == 0) + return (c); + + return (NULL); +} + + +/* + * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option. + */ + +ppd_choice_t * /* O - Pointer to choice or NULL */ +ppdFindMarkedChoice(ppd_file_t *ppd, /* I - PPD file */ + const char *option) /* I - Keyword/option name */ +{ + int i; /* Looping var */ + ppd_option_t *o; /* Pointer to option */ + ppd_choice_t *c; /* Pointer to choice */ + + + if ((o = ppdFindOption(ppd, option)) == NULL) + return (NULL); + + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (c->marked) + return (c); + + return (NULL); +} + + +/* + * 'ppdFindOption()' - Return a pointer to the specified option. + */ + +ppd_option_t * /* O - Pointer to option or NULL */ +ppdFindOption(ppd_file_t *ppd, /* I - PPD file data */ + const char *option) /* I - Option/Keyword name */ +{ + int i, j, k; /* Looping vars */ + ppd_option_t *o; /* Pointer to option */ + ppd_group_t *g, /* Pointer to group */ + *sg; /* Pointer to subgroup */ + + + if (ppd == NULL || option == NULL) + return (NULL); + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + { + for (j = g->num_options, o = g->options; j > 0; j --, o ++) + if (strcasecmp(o->keyword, option) == 0) + return (o); + + for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++) + for (k = sg->num_options, o = sg->options; k > 0; k --, o ++) + if (strcasecmp(o->keyword, option) == 0) + return (o); + } + + return (NULL); +} + + +/* + * 'ppdIsMarked()' - Check to see if an option is marked... + */ + +int /* O - Non-zero if option is marked */ +ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */ + const char *option, /* I - Option/Keyword name */ + const char *choice) /* I - Choice name */ +{ + ppd_option_t *o; /* Option pointer */ + ppd_choice_t *c; /* Choice pointer */ + + + if (ppd == NULL) + return (0); + + if ((o = ppdFindOption(ppd, option)) == NULL) + return (0); + + if ((c = ppdFindChoice(o, choice)) == NULL) + return (0); + + return (c->marked); +} + + +/* + * 'ppdMarkDefaults()' - Mark all default options in the PPD file. + */ + +void +ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */ +{ + int i; /* Looping variables */ + ppd_group_t *g; /* Current group */ + + + if (ppd == NULL) + return; + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + ppd_defaults(ppd, g); +} + + +/* + * 'ppdMarkOption()' - Mark an option in a PPD file. + * + * Notes: + * + * -1 is returned if the given option would conflict with any currently + * selected option. + */ + +int /* O - Number of conflicts */ +ppdMarkOption(ppd_file_t *ppd, /* I - PPD file record */ + const char *option, /* I - Keyword */ + const char *choice) /* I - Option name */ +{ + int i; /* Looping var */ + ppd_option_t *o; /* Option pointer */ + ppd_choice_t *c; /* Choice pointer */ + + + if (ppd == NULL) + return (0); + + if (strcasecmp(option, "PageSize") == 0 && strncasecmp(choice, "Custom.", 7) == 0) + { + /* + * Handle variable page sizes... + */ + + ppdPageSize(ppd, choice); + choice = "Custom"; + } + + if ((o = ppdFindOption(ppd, option)) == NULL) + return (0); + + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (strcasecmp(c->choice, choice) == 0) + break; + + if (i) + { + /* + * Option found; mark it and then handle unmarking any other options. + */ + + c->marked = 1; + + if (o->ui != PPD_UI_PICKMANY) + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (strcasecmp(c->choice, choice) != 0) + c->marked = 0; + + if (strcasecmp(option, "PageSize") == 0 || strcasecmp(option, "PageRegion") == 0) + { + /* + * Mark current page size... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + ppd->sizes[i].marked = strcasecmp(ppd->sizes[i].name, choice) == 0; + + /* + * Unmark the current PageSize or PageRegion setting, as appropriate... + */ + + if (strcasecmp(option, "PageSize") == 0) + { + if ((o = ppdFindOption(ppd, "PageRegion")) != NULL) + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + else + { + if ((o = ppdFindOption(ppd, "PageSize")) != NULL) + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + } + else if (strcasecmp(option, "InputSlot") == 0) + { + /* + * Unmark ManualFeed option... + */ + + if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL) + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + else if (strcasecmp(option, "ManualFeed") == 0) + { + /* + * Unmark InputSlot option... + */ + + if ((o = ppdFindOption(ppd, "InputSlot")) != NULL) + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + } + + return (ppdConflicts(ppd)); +} + + +/* + * 'ppd_defaults()' - Set the defaults for this group and all sub-groups. + */ + +static void +ppd_defaults(ppd_file_t *ppd, /* I - PPD file */ + ppd_group_t *g) /* I - Group to default */ +{ + int i; /* Looping var */ + ppd_option_t *o; /* Current option */ + ppd_group_t *sg; /* Current sub-group */ + + + if (g == NULL) + return; + + for (i = g->num_options, o = g->options; i > 0; i --, o ++) + if (strcasecmp(o->keyword, "PageRegion") != 0) + ppdMarkOption(ppd, o->keyword, o->defchoice); + + for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++) + ppd_defaults(ppd, sg); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/md5.c b/cups/md5.c new file mode 100644 index 0000000000..5db868858e --- /dev/null +++ b/cups/md5.c @@ -0,0 +1,392 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id$ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "md5.h" +#include "string.h" + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +main() +{ + static const char *const test[7] = { + "", /*d41d8cd98f00b204e9800998ecf8427e*/ + "a", /*0cc175b9c0f1b6a831c399e269772661*/ + "abc", /*900150983cd24fb0d6963f7d28e17f72*/ + "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ + "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /*d174ab98d277d9f5a5611c2c9f419d9f*/ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ + }; + int i; + + for (i = 0; i < 7; ++i) { + md5_state_t state; + md5_byte_t digest[16]; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); + md5_finish(&state, digest); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + printf("%02x", digest[di]); + printf("\n"); + } + return 0; +} +#endif /* TEST */ + + +/* + * For reference, here is the program that computed the T values. + */ +#if 0 +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); + printf("#define T%d 0x%08lx\n", i, v); + } + return 0; +} +#endif +/* + * End of T computation program. + */ +#define T1 0xd76aa478 +#define T2 0xe8c7b756 +#define T3 0x242070db +#define T4 0xc1bdceee +#define T5 0xf57c0faf +#define T6 0x4787c62a +#define T7 0xa8304613 +#define T8 0xfd469501 +#define T9 0x698098d8 +#define T10 0x8b44f7af +#define T11 0xffff5bb1 +#define T12 0x895cd7be +#define T13 0x6b901122 +#define T14 0xfd987193 +#define T15 0xa679438e +#define T16 0x49b40821 +#define T17 0xf61e2562 +#define T18 0xc040b340 +#define T19 0x265e5a51 +#define T20 0xe9b6c7aa +#define T21 0xd62f105d +#define T22 0x02441453 +#define T23 0xd8a1e681 +#define T24 0xe7d3fbc8 +#define T25 0x21e1cde6 +#define T26 0xc33707d6 +#define T27 0xf4d50d87 +#define T28 0x455a14ed +#define T29 0xa9e3e905 +#define T30 0xfcefa3f8 +#define T31 0x676f02d9 +#define T32 0x8d2a4c8a +#define T33 0xfffa3942 +#define T34 0x8771f681 +#define T35 0x6d9d6122 +#define T36 0xfde5380c +#define T37 0xa4beea44 +#define T38 0x4bdecfa9 +#define T39 0xf6bb4b60 +#define T40 0xbebfbc70 +#define T41 0x289b7ec6 +#define T42 0xeaa127fa +#define T43 0xd4ef3085 +#define T44 0x04881d05 +#define T45 0xd9d4d039 +#define T46 0xe6db99e5 +#define T47 0x1fa27cf8 +#define T48 0xc4ac5665 +#define T49 0xf4292244 +#define T50 0x432aff97 +#define T51 0xab9423a7 +#define T52 0xfc93a039 +#define T53 0x655b59c3 +#define T54 0x8f0ccc92 +#define T55 0xffeff47d +#define T56 0x85845dd1 +#define T57 0x6fa87e4f +#define T58 0xfe2ce6e0 +#define T59 0xa3014314 +#define T60 0x4e0811a1 +#define T61 0xf7537e82 +#define T62 0xbd3af235 +#define T63 0x2ad7d2bb +#define T64 0xeb86d391 + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + +#ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +#endif +#if ARCH_IS_BIG_ENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + md5_word_t X[16]; + const md5_byte_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else /* !ARCH_IS_BIG_ENDIAN */ + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + md5_word_t xbuf[16]; + const md5_word_t *X; + + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = 0xefcdab89; + pms->abcd[2] = 0x98badcfe; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/cups/md5.h b/cups/md5.h new file mode 100644 index 0000000000..a2d7b34156 --- /dev/null +++ b/cups/md5.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id$ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/cups/md5passwd.c b/cups/md5passwd.c new file mode 100644 index 0000000000..6cb6b3aa02 --- /dev/null +++ b/cups/md5passwd.c @@ -0,0 +1,150 @@ +/* + * "$Id$" + * + * MD5 password support for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * httpMD5() - Compute the MD5 sum of the username:group:password. + * httpMD5Nonce() - Combine the MD5 sum of the username, group, and password + * with the server-supplied nonce value. + * httpMD5String() - Convert an MD5 sum to a character string. + */ + +/* + * Include necessary headers... + */ + +#include "http.h" +#include "string.h" + + +/* + * 'httpMD5()' - Compute the MD5 sum of the username:group:password. + */ + +char * /* O - MD5 sum */ +httpMD5(const char *username, /* I - User name */ + const char *realm, /* I - Realm name */ + const char *passwd, /* I - Password string */ + char md5[33]) /* O - MD5 string */ +{ + md5_state_t state; /* MD5 state info */ + md5_byte_t sum[16]; /* Sum data */ + char line[256]; /* Line to sum */ + + + /* + * Compute the MD5 sum of the user name, group name, and password. + */ + + snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd); + md5_init(&state); + md5_append(&state, (md5_byte_t *)line, strlen(line)); + md5_finish(&state, sum); + + /* + * Return the sum... + */ + + return (httpMD5String(sum, md5)); +} + + +/* + * 'httpMD5Final()' - Combine the MD5 sum of the username, group, and password + * with the server-supplied nonce value, method, and + * request-uri. + */ + +char * /* O - New sum */ +httpMD5Final(const char *nonce, /* I - Server nonce value */ + const char *method, /* I - METHOD (GET, POST, etc.) */ + const char *resource, /* I - Resource path */ + char md5[33]) /* IO - MD5 sum */ +{ + md5_state_t state; /* MD5 state info */ + md5_byte_t sum[16]; /* Sum data */ + char line[1024]; /* Line of data */ + char a2[33]; /* Hash of method and resource */ + + + /* + * First compute the MD5 sum of the method and resource... + */ + + snprintf(line, sizeof(line), "%s:%s", method, resource); + md5_init(&state); + md5_append(&state, (md5_byte_t *)line, strlen(line)); + md5_finish(&state, sum); + httpMD5String(sum, a2); + + /* + * Then combine A1 (MD5 of username, realm, and password) with the nonce + * and A2 (method + resource) values to get the final MD5 sum for the + * request... + */ + + snprintf(line, sizeof(line), "%s:%s:%s", md5, nonce, a2); + + md5_init(&state); + md5_append(&state, (md5_byte_t *)line, strlen(line)); + md5_finish(&state, sum); + + return (httpMD5String(sum, md5)); +} + + +/* + * 'httpMD5String()' - Convert an MD5 sum to a character string. + */ + +char * /* O - MD5 sum in hex */ +httpMD5String(const md5_byte_t *sum, /* I - MD5 sum data */ + char md5[33]) /* O - MD5 sum in hex */ +{ + int i; /* Looping var */ + char *md5ptr; /* Pointer into MD5 string */ + static char *hex = "0123456789abcdef"; + /* Hex digits */ + + + /* + * Convert the MD5 sum to hexadecimal... + */ + + for (i = 16, md5ptr = md5; i > 0; i --, sum ++) + { + *md5ptr++ = hex[*sum >> 4]; + *md5ptr++ = hex[*sum & 15]; + } + + *md5ptr = '\0'; + + return (md5); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/options.c b/cups/options.c new file mode 100644 index 0000000000..37d3ab3c72 --- /dev/null +++ b/cups/options.c @@ -0,0 +1,432 @@ +/* + * "$Id$" + * + * Option routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsAddOption() - Add an option to an option array. + * cupsFreeOptions() - Free all memory used by options. + * cupsGetOption() - Get an option value. + * cupsParseOptions() - Parse options from a command-line argument. + * cupsMarkOptions() - Mark command-line options in a PPD file. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include +#include +#include "string.h" +#include "debug.h" + + +/* + * 'cupsAddOption()' - Add an option to an option array. + */ + +int /* O - Number of options */ +cupsAddOption(const char *name, /* I - Name of option */ + const char *value, /* I - Value of option */ + int num_options, /* I - Number of options */ + cups_option_t **options) /* IO - Pointer to options */ +{ + int i; /* Looping var */ + cups_option_t *temp; /* Pointer to new option */ + + + if (name == NULL || !name[0] || value == NULL || + options == NULL || num_options < 0) + return (num_options); + + /* + * Look for an existing option with the same name... + */ + + for (i = 0, temp = *options; i < num_options; i ++, temp ++) + if (strcasecmp(temp->name, name) == 0) + break; + + if (i >= num_options) + { + /* + * No matching option name... + */ + + if (num_options == 0) + temp = (cups_option_t *)malloc(sizeof(cups_option_t)); + else + temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) * + (num_options + 1)); + + if (temp == NULL) + return (0); + + *options = temp; + temp += num_options; + temp->name = strdup(name); + num_options ++; + } + else + { + /* + * Match found; free the old value... + */ + + free(temp->value); + } + + temp->value = strdup(value); + + return (num_options); +} + + +/* + * 'cupsFreeOptions()' - Free all memory used by options. + */ + +void +cupsFreeOptions(int num_options, /* I - Number of options */ + cups_option_t *options) /* I - Pointer to options */ +{ + int i; /* Looping var */ + + + if (num_options <= 0 || options == NULL) + return; + + for (i = 0; i < num_options; i ++) + { + free(options[i].name); + free(options[i].value); + } + + free(options); +} + + +/* + * 'cupsGetOption()' - Get an option value. + */ + +const char * /* O - Option value or NULL */ +cupsGetOption(const char *name, /* I - Name of option */ + int num_options,/* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i; /* Looping var */ + + + if (name == NULL || num_options <= 0 || options == NULL) + return (NULL); + + for (i = 0; i < num_options; i ++) + if (strcasecmp(options[i].name, name) == 0) + return (options[i].value); + + return (NULL); +} + + +/* + * 'cupsParseOptions()' - Parse options from a command-line argument. + */ + +int /* O - Number of options found */ +cupsParseOptions(const char *arg, /* I - Argument to parse */ + int num_options, /* I - Number of options */ + cups_option_t **options) /* O - Options found */ +{ + char *copyarg, /* Copy of input string */ + *ptr, /* Pointer into string */ + *name, /* Pointer to name */ + *value; /* Pointer to value */ + + + if (arg == NULL || options == NULL || num_options < 0) + return (0); + + /* + * Make a copy of the argument string and then divide it up... + */ + + copyarg = strdup(arg); + ptr = copyarg; + + /* + * Skip leading spaces... + */ + + while (isspace(*ptr)) + ptr ++; + + /* + * Loop through the string... + */ + + while (*ptr != '\0') + { + /* + * Get the name up to a SPACE, =, or end-of-string... + */ + + name = ptr; + while (!isspace(*ptr) && *ptr != '=' && *ptr != '\0') + ptr ++; + + /* + * Avoid an empty name... + */ + + if (ptr == name) + break; + + /* + * Skip trailing spaces... + */ + + while (isspace(*ptr)) + *ptr++ = '\0'; + + if (*ptr != '=') + { + /* + * Start of another option... + */ + + if (strncasecmp(name, "no", 2) == 0) + num_options = cupsAddOption(name + 2, "false", num_options, + options); + else + num_options = cupsAddOption(name, "true", num_options, options); + + continue; + } + + /* + * Remove = and parse the value... + */ + + *ptr++ = '\0'; + + if (*ptr == '\'') + { + /* + * Quoted string constant... + */ + + ptr ++; + value = ptr; + + while (*ptr != '\'' && *ptr != '\0') + ptr ++; + + if (*ptr != '\0') + *ptr++ = '\0'; + } + else if (*ptr == '\"') + { + /* + * Double-quoted string constant... + */ + + ptr ++; + value = ptr; + + while (*ptr != '\"' && *ptr != '\0') + ptr ++; + + if (*ptr != '\0') + *ptr++ = '\0'; + } + else + { + /* + * Normal space-delimited string... + */ + + value = ptr; + + while (!isspace(*ptr) && *ptr != '\0') + ptr ++; + } + + /* + * Skip trailing whitespace... + */ + + while (isspace(*ptr)) + *ptr++ = '\0'; + + /* + * Add the string value... + */ + + num_options = cupsAddOption(name, value, num_options, options); + } + + /* + * Free the copy of the argument we made and return the number of options + * found. + */ + + free(copyarg); + + return (num_options); +} + + +/* + * 'cupsMarkOptions()' - Mark command-line options in a PPD file. + */ + +int /* O - 1 if conflicting */ +cupsMarkOptions(ppd_file_t *ppd, /* I - PPD file */ + int num_options, /* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i; /* Looping var */ + int conflict; /* Option conflicts */ + char *val, /* Pointer into value */ + *ptr, /* Pointer into string */ + s[255]; /* Temporary string */ + + + /* + * Check arguments... + */ + + if (ppd == NULL || num_options <= 0 || options == NULL) + return (0); + + /* + * Mark options... + */ + + conflict = 0; + + for (i = num_options; i > 0; i --, options ++) + if (strcasecmp(options->name, "media") == 0) + { + /* + * Loop through the option string, separating it at commas and + * marking each individual option. + */ + + for (val = options->value; *val;) + { + /* + * Extract the sub-option from the string... + */ + + for (ptr = s; *val && *val != ',' && (ptr - s) < (sizeof(s) - 1);) + *ptr++ = *val++; + *ptr++ = '\0'; + + if (*val == ',') + val ++; + + /* + * Mark it... + */ + + if (ppdMarkOption(ppd, "PageSize", s)) + conflict = 1; + if (ppdMarkOption(ppd, "InputSlot", s)) + conflict = 1; + if (ppdMarkOption(ppd, "MediaType", s)) + conflict = 1; + if (ppdMarkOption(ppd, "EFMediaQualityMode", s)) /* EFI */ + conflict = 1; + if (strcasecmp(s, "manual") == 0) + if (ppdMarkOption(ppd, "ManualFeed", "True")) + conflict = 1; + } + } + else if (strcasecmp(options->name, "sides") == 0) + { + if (strcasecmp(options->value, "one-sided") == 0) + { + 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 */ + conflict = 1; + } + else if (strcasecmp(options->value, "two-sided-long-edge") == 0) + { + 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 */ + conflict = 1; + } + else if (strcasecmp(options->value, "two-sided-short-edge") == 0) + { + 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 */ + conflict = 1; + } + } + else if (strcasecmp(options->name, "resolution") == 0 || + strcasecmp(options->name, "printer-resolution") == 0) + { + if (ppdMarkOption(ppd, "Resolution", options->value)) + conflict = 1; + if (ppdMarkOption(ppd, "SetResolution", options->value)) + /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */ + conflict = 1; + if (ppdMarkOption(ppd, "JCLResolution", options->value)) /* HP */ + conflict = 1; + if (ppdMarkOption(ppd, "CNRes_PGP", options->value)) /* Canon */ + conflict = 1; + } + else if (strcasecmp(options->name, "output-bin") == 0) + { + if (ppdMarkOption(ppd, "OutputBin", options->value)) + conflict = 1; + } + else if (ppdMarkOption(ppd, options->name, options->value)) + conflict = 1; + + return (conflict); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/page.c b/cups/page.c new file mode 100644 index 0000000000..ca3f262338 --- /dev/null +++ b/cups/page.c @@ -0,0 +1,191 @@ +/* + * "$Id$" + * + * Page size functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * ppdPageSize() - Get the page size record for the given size. + * ppdPageWidth() - Get the page width for the given size. + * ppdPageLength() - Get the page length for the given size. + */ + +/* + * Include necessary headers... + */ + +#include "ppd.h" +#include "string.h" +#include + + +/* + * 'ppdPageSize()' - Get the page size record for the given size. + */ + +ppd_size_t * /* O - Size record for page or NULL */ +ppdPageSize(ppd_file_t *ppd, /* I - PPD file record */ + const char *name) /* I - Size name */ +{ + int i; /* Looping var */ + float w, l; /* Width and length of page */ + char units[255]; /* Page size units... */ + + + if (ppd == NULL) + return (NULL); + + if (name != NULL) + { + if (strncmp(name, "Custom.", 7) == 0 && ppd->variable_sizes) + { + /* + * Find the custom page size... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + if (strcmp("Custom", ppd->sizes[i].name) == 0) + break; + + if (i == ppd->num_sizes) + return (NULL); + + /* + * Variable size; size name can be one of the following: + * + * Custom.WIDTHxLENGTHin - Size in inches + * Custom.WIDTHxLENGTHcm - Size in centimeters + * Custom.WIDTHxLENGTHmm - Size in millimeters + * Custom.WIDTHxLENGTH[pt] - Size in points + */ + + units[0] = '\0'; + if (sscanf(name + 7, "%fx%f%254s", &w, &l, units) < 2) + return (NULL); + + if (strcasecmp(units, "in") == 0) + { + ppd->sizes[i].width = w * 72.0f; + ppd->sizes[i].length = l * 72.0f; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w * 72.0f - ppd->custom_margins[2]; + ppd->sizes[i].top = l * 72.0f - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "cm") == 0) + { + ppd->sizes[i].width = w / 2.54f * 72.0f; + ppd->sizes[i].length = l / 2.54f * 72.0f; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w / 2.54f * 72.0f - ppd->custom_margins[2]; + ppd->sizes[i].top = l / 2.54f * 72.0f - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "mm") == 0) + { + ppd->sizes[i].width = w / 25.4f * 72.0f; + ppd->sizes[i].length = l / 25.4f * 72.0f; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w / 25.4f * 72.0f - ppd->custom_margins[2]; + ppd->sizes[i].top = l / 25.4f * 72.0f - ppd->custom_margins[3]; + } + else + { + ppd->sizes[i].width = w; + ppd->sizes[i].length = l; + ppd->sizes[i].left = ppd->custom_margins[0]; + ppd->sizes[i].bottom = ppd->custom_margins[1]; + ppd->sizes[i].right = w - ppd->custom_margins[2]; + ppd->sizes[i].top = l - ppd->custom_margins[3]; + } + + return (ppd->sizes + i); + } + else + { + /* + * Lookup by name... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + if (strcmp(name, ppd->sizes[i].name) == 0) + return (ppd->sizes + i); + } + } + else + { + /* + * Find default... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + if (ppd->sizes[i].marked) + return (ppd->sizes + i); + } + + return (NULL); +} + + +/* + * 'ppdPageWidth()' - Get the page width for the given size. + */ + +float /* O - Width of page in points or 0.0 */ +ppdPageWidth(ppd_file_t *ppd, /* I - PPD file record */ + const char *name) /* I - Size name */ +{ + ppd_size_t *size; /* Page size */ + + + if ((size = ppdPageSize(ppd, name)) == NULL) + return (0.0); + else + return (size->width); +} + + +/* + * 'ppdPageLength()' - Get the page length for the given size. + */ + +float /* O - Length of page in points or 0.0 */ +ppdPageLength(ppd_file_t *ppd, /* I - PPD file */ + const char *name) /* I - Size name */ +{ + ppd_size_t *size; /* Page size */ + + + if ((size = ppdPageSize(ppd, name)) == NULL) + return (0.0); + else + return (size->length); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/ppd.c b/cups/ppd.c new file mode 100644 index 0000000000..69e8ddf478 --- /dev/null +++ b/cups/ppd.c @@ -0,0 +1,2291 @@ +/* + * "$Id$" + * + * PPD file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * ppdClose() - Free all memory used by the PPD file. + * ppd_free_group() - Free a single UI group. + * ppd_free_option() - Free a single option. + * ppdOpen() - Read a PPD file into memory. + * ppdOpenFd() - Read a PPD file into memory. + * ppdOpenFile() - Read a PPD file into memory. + * ppd_read() - Read a line from a PPD file, skipping comment lines + * as necessary. + * compare_strings() - Compare two strings. + * compare_groups() - Compare two groups. + * compare_options() - Compare two options. + */ + +/* + * Include necessary headers. + */ + +#include "ppd.h" +#include +#include +#include "string.h" +#include "language.h" +#include "debug.h" + + +/* + * Definitions... + */ + +#if defined(WIN32) || defined(__EMX__) +# define READ_BINARY "rb" /* Open a binary file for reading */ +# define WRITE_BINARY "wb" /* Open a binary file for writing */ +#else +# define READ_BINARY "r" /* Open a binary file for reading */ +# define WRITE_BINARY "w" /* Open a binary file for writing */ +#endif /* WIN32 || __EMX__ */ + +#define safe_free(p) if (p) free(p) /* Safe free macro */ + +#define PPD_KEYWORD 1 /* Line contained a keyword */ +#define PPD_OPTION 2 /* Line contained an option name */ +#define PPD_TEXT 4 /* Line contained human-readable text */ +#define PPD_STRING 8 /* Line contained a string or code */ + + +/* + * Local functions... + */ + +#ifndef __APPLE__ +static int compare_strings(char *s, char *t); +static int compare_groups(ppd_group_t *g0, ppd_group_t *g1); +static int compare_options(ppd_option_t *o0, ppd_option_t *o1); +#endif /* !__APPLE__ */ +static int ppd_read(FILE *fp, char *keyword, char *option, + char *text, char **string); +static void ppd_decode(char *string); +#ifdef __APPLE__ +# define ppd_fix(s) +#else +static void ppd_fix(char *string); +#endif /* __APPLE__ */ +static void ppd_free_group(ppd_group_t *group); +static void ppd_free_option(ppd_option_t *option); +static ppd_group_t *ppd_get_group(ppd_file_t *ppd, char *name); +static ppd_option_t *ppd_get_option(ppd_group_t *group, char *name); +static ppd_choice_t *ppd_add_choice(ppd_option_t *option, char *name); + + +/* + * 'ppdClose()' - Free all memory used by the PPD file. + */ + +void +ppdClose(ppd_file_t *ppd) /* I - PPD file record */ +{ + int i; /* Looping var */ + ppd_emul_t *emul; /* Current emulation */ + ppd_group_t *group; /* Current group */ + char **font; /* Current font */ + char **filter; /* Current filter */ + + + /* + * Range check the PPD file record... + */ + + if (ppd == NULL) + return; + + /* + * Free all strings at the top level... + */ + + safe_free(ppd->patches); + safe_free(ppd->jcl_begin); + safe_free(ppd->jcl_ps); + safe_free(ppd->jcl_end); + safe_free(ppd->lang_encoding); + safe_free(ppd->lang_version); + safe_free(ppd->modelname); + safe_free(ppd->ttrasterizer); + safe_free(ppd->manufacturer); + safe_free(ppd->product); + safe_free(ppd->nickname); + safe_free(ppd->shortnickname); + + /* + * Free any emulations... + */ + + if (ppd->num_emulations > 0) + { + for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++) + { + safe_free(emul->start); + safe_free(emul->stop); + } + + safe_free(ppd->emulations); + } + + /* + * Free any UI groups, subgroups, and options... + */ + + if (ppd->num_groups > 0) + { + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + ppd_free_group(group); + + safe_free(ppd->groups); + } + + /* + * Free any page sizes... + */ + + if (ppd->num_sizes > 0) + safe_free(ppd->sizes); + + /* + * Free any constraints... + */ + + if (ppd->num_consts > 0) + safe_free(ppd->consts); + + /* + * Free any filters... + */ + + if (ppd->num_filters > 0) + { + for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++) + safe_free(*filter); + + safe_free(ppd->filters); + } + + /* + * Free any fonts... + */ + + if (ppd->num_fonts > 0) + { + for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++) + safe_free(*font); + + safe_free(ppd->fonts); + } + + /* + * Free any profiles... + */ + + if (ppd->num_profiles > 0) + safe_free(ppd->profiles); + + /* + * Free the whole record... + */ + + safe_free(ppd); +} + + +/* + * 'ppd_free_group()' - Free a single UI group. + */ + +static void +ppd_free_group(ppd_group_t *group) /* I - Group to free */ +{ + int i; /* Looping var */ + ppd_option_t *option; /* Current option */ + ppd_group_t *subgroup; /* Current sub-group */ + + + if (group->num_options > 0) + { + for (i = group->num_options, option = group->options; + i > 0; + i --, option ++) + ppd_free_option(option); + + safe_free(group->options); + } + + if (group->num_subgroups > 0) + { + for (i = group->num_subgroups, subgroup = group->subgroups; + i > 0; + i --, subgroup ++) + ppd_free_group(subgroup); + + safe_free(group->subgroups); + } +} + + +/* + * 'ppd_free_option()' - Free a single option. + */ + +static void +ppd_free_option(ppd_option_t *option) /* I - Option to free */ +{ + int i; /* Looping var */ + ppd_choice_t *choice; /* Current choice */ + + + if (option->num_choices > 0) + { + for (i = option->num_choices, choice = option->choices; + i > 0; + i --, choice ++) + safe_free(choice->code); + + safe_free(option->choices); + } +} + + +/* + * 'ppd_get_group()' - Find or create the named group as needed. + */ + +static ppd_group_t * /* O - Named group */ +ppd_get_group(ppd_file_t *ppd, /* I - PPD file */ + char *name) /* I - Name of group */ +{ + int i; /* Looping var */ + 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 + group = realloc(ppd->groups, + (ppd->num_groups + 1) * sizeof(ppd_group_t)); + + if (group == NULL) + return (NULL); + + ppd->groups = group; + group += ppd->num_groups; + ppd->num_groups ++; + + memset(group, 0, sizeof(ppd_group_t)); + strlcpy(group->text, name, sizeof(group->text)); + } + + return (group); +} + + +/* + * 'ppd_get_option()' - Find or create the named option as needed. + */ + +static ppd_option_t * /* O - Named option */ +ppd_get_option(ppd_group_t *group, /* I - Group */ + char *name) /* I - Name of option */ +{ + int i; /* Looping var */ + ppd_option_t *option; /* Option */ + + + for (i = group->num_options, option = group->options; i > 0; i --, option ++) + if (strcmp(option->keyword, name) == 0) + break; + + if (i == 0) + { + if (group->num_options == 0) + option = malloc(sizeof(ppd_option_t)); + else + option = realloc(group->options, + (group->num_options + 1) * sizeof(ppd_option_t)); + + if (option == NULL) + return (NULL); + + group->options = option; + option += group->num_options; + group->num_options ++; + + memset(option, 0, sizeof(ppd_option_t)); + strlcpy(option->keyword, name, sizeof(option->keyword)); + } + + return (option); +} + + +/* + * 'ppd_add_choice()' - Add a choice to an option. + */ + +static ppd_choice_t * /* O - Named choice */ +ppd_add_choice(ppd_option_t *option, /* I - Option */ + char *name) /* I - Name of choice */ +{ + ppd_choice_t *choice; /* Choice */ + + + if (option->num_choices == 0) + choice = malloc(sizeof(ppd_choice_t)); + else + choice = realloc(option->choices, + sizeof(ppd_choice_t) * (option->num_choices + 1)); + + if (choice == NULL) + return (NULL); + + option->choices = choice; + choice += option->num_choices; + option->num_choices ++; + + memset(choice, 0, sizeof(ppd_choice_t)); + strlcpy(choice->choice, name, sizeof(choice->choice)); + + return (choice); +} + + +/* + * 'ppd_add_size()' - Add a page size. + */ + +static ppd_size_t * /* O - Named size */ +ppd_add_size(ppd_file_t *ppd, /* I - PPD file */ + char *name) /* I - Name of size */ +{ + ppd_size_t *size; /* Size */ + + + if (ppd->num_sizes == 0) + size = malloc(sizeof(ppd_size_t)); + else + size = realloc(ppd->sizes, sizeof(ppd_size_t) * (ppd->num_sizes + 1)); + + if (size == NULL) + return (NULL); + + ppd->sizes = size; + size += ppd->num_sizes; + ppd->num_sizes ++; + + memset(size, 0, sizeof(ppd_size_t)); + strlcpy(size->name, name, sizeof(size->name)); + + return (size); +} + + +/* + * 'ppdOpen()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpen(FILE *fp) /* I - File to read from */ +{ + char *oldlocale; /* Old locale settings */ + int i, j, k, m; /* Looping vars */ + int count; /* Temporary count */ + ppd_file_t *ppd; /* PPD file record */ + ppd_group_t *group, /* Current group */ + *subgroup; /* Current sub-group */ + ppd_option_t *option; /* Current option */ + ppd_choice_t *choice; /* Current choice */ + ppd_const_t *constraint; /* Current constraint */ + ppd_size_t *size; /* Current page size */ + int mask; /* Line data mask */ + char keyword[PPD_MAX_NAME], + /* Keyword from file */ + name[PPD_MAX_NAME], + /* Option from file */ + text[PPD_MAX_LINE], + /* Human-readable text from file */ + *string, /* Code/text from file */ + *sptr, /* Pointer into string */ + *nameptr, /* Pointer into name */ + *temp, /* Temporary string pointer */ + **tempfonts; /* Temporary fonts pointer */ + float order; /* Order dependency number */ + ppd_section_t section; /* Order dependency section */ + ppd_profile_t *profile; /* Pointer to color profile */ + char **filter; /* Pointer to filter */ + cups_lang_t *language; /* Default language */ + + + /* + * Range check input... + */ + + if (fp == NULL) + return (NULL); + + /* + * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'... + */ + + mask = ppd_read(fp, keyword, name, text, &string); + + if (mask == 0 || + strcmp(keyword, "PPD-Adobe") != 0 || + string == NULL || string[0] != '4') + { + /* + * Either this is not a PPD file, or it is not a 4.x PPD file. + */ + + safe_free(string); + + return (NULL); + } + + DEBUG_printf(("ppdOpen: keyword = %s, string = %p\n", keyword, string)); + + safe_free(string); + + /* + * Allocate memory for the PPD file record... + */ + + if ((ppd = calloc(sizeof(ppd_file_t), 1)) == NULL) + return (NULL); + + ppd->language_level = 1; + ppd->color_device = 0; + ppd->colorspace = PPD_CS_GRAY; + ppd->landscape = -90; + + /* + * Get the default language for the user... + */ + + language = cupsLangDefault(); + +#ifdef LC_NUMERIC + oldlocale = setlocale(LC_NUMERIC, "C"); +#else + oldlocale = setlocale(LC_ALL, "C"); +#endif /* LC_NUMERIC */ + + /* + * Read lines from the PPD file and add them to the file record... + */ + + group = NULL; + subgroup = NULL; + option = NULL; + choice = NULL; + + while ((mask = ppd_read(fp, keyword, name, text, &string)) != 0) + { +#ifdef DEBUG + printf("mask = %x, keyword = \"%s\"", mask, keyword); + + if (name[0] != '\0') + printf(", name = \"%s\"", name); + + if (text[0] != '\0') + printf(", text = \"%s\"", text); + + if (string != NULL) + { + if (strlen(string) > 40) + printf(", string = %p", string); + else + printf(", string = \"%s\"", string); + } + + 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); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + if (strcmp(keyword, "LanguageLevel") == 0) + ppd->language_level = atoi(string); + else if (strcmp(keyword, "LanguageEncoding") == 0) + { + ppd->lang_encoding = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "LanguageVersion") == 0) + { + ppd->lang_version = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "Manufacturer") == 0) + { + ppd->manufacturer = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "ModelName") == 0) + { + ppd->modelname = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "NickName") == 0) + { + ppd->nickname = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "Product") == 0) + { + ppd->product = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "ShortNickName") == 0) + { + ppd->shortnickname = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "TTRasterizer") == 0) + { + ppd->ttrasterizer = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "JCLBegin") == 0) + { + ppd_decode(string); /* Decode quoted string */ + ppd->jcl_begin = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "JCLEnd") == 0) + { + ppd_decode(string); /* Decode quoted string */ + ppd->jcl_end = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "JCLToPSInterpreter") == 0) + { + ppd_decode(string); /* Decode quoted string */ + ppd->jcl_ps = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "AccurateScreensSupport") == 0) + ppd->accurate_screens = strcmp(string, "True") == 0; + else if (strcmp(keyword, "ColorDevice") == 0) + ppd->color_device = strcmp(string, "True") == 0; + else if (strcmp(keyword, "ContoneOnly") == 0) + ppd->contone_only = strcmp(string, "True") == 0; + else if (strcmp(keyword, "DefaultColorSpace") == 0) + { + if (strcmp(string, "CMY") == 0) + ppd->colorspace = PPD_CS_CMY; + else if (strcmp(string, "CMYK") == 0) + ppd->colorspace = PPD_CS_CMYK; + else if (strcmp(string, "RGB") == 0) + ppd->colorspace = PPD_CS_RGB; + else if (strcmp(string, "RGBK") == 0) + ppd->colorspace = PPD_CS_RGBK; + else if (strcmp(string, "N") == 0) + ppd->colorspace = PPD_CS_N; + else + ppd->colorspace = PPD_CS_GRAY; + } + else if (strcmp(keyword, "cupsFlipDuplex") == 0) + ppd->flip_duplex = strcmp(string, "True") == 0; + else if (strcmp(keyword, "cupsManualCopies") == 0) + ppd->manual_copies = strcmp(string, "True") == 0; + else if (strcmp(keyword, "cupsModelNumber") == 0) + ppd->model_number = atoi(string); + else if (strcmp(keyword, "cupsColorProfile") == 0) + { + if (ppd->num_profiles == 0) + profile = malloc(sizeof(ppd_profile_t)); + else + profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * + (ppd->num_profiles + 1)); + + ppd->profiles = profile; + profile += ppd->num_profiles; + ppd->num_profiles ++; + + memset(profile, 0, sizeof(ppd_profile_t)); + strlcpy(profile->resolution, name, sizeof(profile->resolution)); + strlcpy(profile->media_type, text, sizeof(profile->media_type)); + sscanf(string, "%f%f%f%f%f%f%f%f%f%f%f", &(profile->density), + &(profile->gamma), + profile->matrix[0] + 0, profile->matrix[0] + 1, + profile->matrix[0] + 2, profile->matrix[1] + 0, + profile->matrix[1] + 1, profile->matrix[1] + 2, + profile->matrix[2] + 0, profile->matrix[2] + 1, + profile->matrix[2] + 2); + } + else if (strcmp(keyword, "cupsFilter") == 0) + { + if (ppd->num_filters == 0) + filter = malloc(sizeof(char *)); + else + filter = realloc(ppd->filters, sizeof(char *) * (ppd->num_filters + 1)); + + if (filter == NULL) + { + safe_free(filter); + + ppdClose(ppd); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + ppd->filters = filter; + filter += ppd->num_filters; + ppd->num_filters ++; + + /* + * Copy filter string and prevent it from being freed below... + */ + + *filter = string; + string = NULL; + } + else if (strcmp(keyword, "Throughput") == 0) + ppd->throughput = atoi(string); + else if (strcmp(keyword, "Font") == 0) + { + /* + * Add this font to the list of available fonts... + */ + + if (ppd->num_fonts == 0) + tempfonts = (char **)malloc(sizeof(char *)); + else + tempfonts = (char **)realloc(ppd->fonts, + sizeof(char *) * (ppd->num_fonts + 1)); + + if (tempfonts == NULL) + { + safe_free(string); + + ppdClose(ppd); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + ppd->fonts = tempfonts; + ppd->fonts[ppd->num_fonts] = strdup(name); + ppd->num_fonts ++; + } + else if (strcmp(keyword, "VariablePaperSize") == 0 && + strcmp(string, "True") == 0 && + !ppd->variable_sizes) + { + ppd->variable_sizes = 1; + + /* + * Add a "Custom" page size entry... + */ + + ppd_add_size(ppd, "Custom"); + + /* + * Add a "Custom" page size option... + */ + + if ((option = ppdFindOption(ppd, "PageSize")) == NULL) + { + ppd_group_t *temp; + + + if ((temp = ppd_get_group(ppd, + cupsLangString(language, + CUPS_MSG_GENERAL))) == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + if ((option = ppd_get_option(temp, "PageSize")) == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + } + + if ((choice = ppd_add_choice(option, "Custom")) == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + strlcpy(choice->text, cupsLangString(language, CUPS_MSG_VARIABLE), + sizeof(choice->text)); + option = NULL; + } + else if (strcmp(keyword, "MaxMediaWidth") == 0) + ppd->custom_max[0] = (float)atof(string); + else if (strcmp(keyword, "MaxMediaHeight") == 0) + ppd->custom_max[1] = (float)atof(string); + else if (strcmp(keyword, "ParamCustomPageSize") == 0) + { + if (strcmp(name, "Width") == 0) + sscanf(string, "%*s%*s%f%f", ppd->custom_min + 0, + ppd->custom_max + 0); + else if (strcmp(name, "Height") == 0) + sscanf(string, "%*s%*s%f%f", ppd->custom_min + 1, + ppd->custom_max + 1); + } + else if (strcmp(keyword, "HWMargins") == 0) + sscanf(string, "%f%f%f%f", ppd->custom_margins + 0, + ppd->custom_margins + 1, ppd->custom_margins + 2, + ppd->custom_margins + 3); + else if (strcmp(keyword, "CustomPageSize") == 0 && + strcmp(name, "True") == 0) + { + if (!ppd->variable_sizes) + { + ppd->variable_sizes = 1; + + /* + * Add a "Custom" page size entry... + */ + + ppd_add_size(ppd, "Custom"); + + /* + * Add a "Custom" page size option... + */ + + if ((option = ppdFindOption(ppd, "PageSize")) == NULL) + { + ppd_group_t *temp; + + + if ((temp = ppd_get_group(ppd, + cupsLangString(language, + CUPS_MSG_GENERAL))) == NULL) + { + DEBUG_puts("Unable to get general group!"); + + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + if ((option = ppd_get_option(temp, "PageSize")) == NULL) + { + DEBUG_puts("Unable to get PageSize option!"); + + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + } + + if ((choice = ppd_add_choice(option, "Custom")) == NULL) + { + DEBUG_puts("Unable to add Custom choice!"); + + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + strlcpy(choice->text, cupsLangString(language, CUPS_MSG_VARIABLE), + sizeof(choice->text)); + option = NULL; + } + + if ((option = ppdFindOption(ppd, "PageSize")) == NULL) + { + DEBUG_puts("Unable to find PageSize option!"); + + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + if ((choice = ppdFindChoice(option, "Custom")) == NULL) + { + DEBUG_puts("Unable to find Custom choice!"); + + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + choice->code = string; + string = NULL; + option = NULL; + } + else if (strcmp(keyword, "LandscapeOrientation") == 0) + { + if (strcmp(string, "Minus90") == 0) + ppd->landscape = -90; + else if (strcmp(string, "Plus90") == 0) + ppd->landscape = 90; + } + else if (strcmp(keyword, "Emulators") == 0) + { + for (count = 1, sptr = string; sptr != NULL;) + if ((sptr = strchr(sptr, ' ')) != NULL) + { + count ++; + while (*sptr == ' ') + sptr ++; + } + + ppd->num_emulations = count; + ppd->emulations = calloc(sizeof(ppd_emul_t), count); + + for (i = 0, sptr = string; i < count; i ++) + { + for (nameptr = ppd->emulations[i].name; + *sptr != '\0' && *sptr != ' '; + sptr ++) + if (nameptr < (ppd->emulations[i].name + sizeof(ppd->emulations[i].name) - 1)) + *nameptr++ = *sptr; + + *nameptr = '\0'; + + while (*sptr == ' ') + sptr ++; + } + } + else if (strncmp(keyword, "StartEmulator_", 14) == 0) + { + ppd_decode(string); + + for (i = 0; i < ppd->num_emulations; i ++) + if (strcmp(keyword + 14, ppd->emulations[i].name) == 0) + { + ppd->emulations[i].start = string; + string = NULL; + } + } + else if (strncmp(keyword, "StopEmulator_", 13) == 0) + { + ppd_decode(string); + + for (i = 0; i < ppd->num_emulations; i ++) + if (strcmp(keyword + 13, ppd->emulations[i].name) == 0) + { + ppd->emulations[i].stop = string; + string = NULL; + } + } + else if (strcmp(keyword, "JobPatchFile") == 0) + { + if (ppd->patches == NULL) + { + ppd->patches = string; + string = NULL; + } + else + { + temp = realloc(ppd->patches, strlen(ppd->patches) + + strlen(string) + 1); + if (temp == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + ppd->patches = temp; + + strcpy(ppd->patches + strlen(ppd->patches), string); + } + } + else if (strcmp(keyword, "OpenUI") == 0) + { + /* + * Add an option record to the current sub-group, group, or file... + */ + + if (name[0] == '*') + strcpy(name, name + 1); /* Eliminate leading asterisk */ + + 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); + else if (group == NULL) + { + if (strcmp(name, "Collate") != 0 && + strcmp(name, "Duplex") != 0 && + strcmp(name, "InputSlot") != 0 && + strcmp(name, "ManualFeed") != 0 && + strcmp(name, "MediaType") != 0 && + strcmp(name, "MediaColor") != 0 && + strcmp(name, "MediaWeight") != 0 && + strcmp(name, "OutputBin") != 0 && + strcmp(name, "OutputMode") != 0 && + strcmp(name, "OutputOrder") != 0 && + strcmp(name, "PageSize") != 0 && + strcmp(name, "PageRegion") != 0) + group = ppd_get_group(ppd, cupsLangString(language, CUPS_MSG_EXTRA)); + else + group = ppd_get_group(ppd, cupsLangString(language, CUPS_MSG_GENERAL)); + + if (group == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + DEBUG_printf(("Adding to group %s...\n", group->text)); + option = ppd_get_option(group, name); + group = NULL; + } + else + option = ppd_get_option(group, name); + + if (option == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + /* + * Now fill in the initial information for the option... + */ + + if (strcmp(string, "PickMany") == 0) + option->ui = PPD_UI_PICKMANY; + else if (strcmp(string, "Boolean") == 0) + option->ui = PPD_UI_BOOLEAN; + else + option->ui = PPD_UI_PICKONE; + + if (text[0]) + { + strlcpy(option->text, text, sizeof(option->text)); + ppd_fix(option->text); + } + else + { + if (strcmp(name, "PageSize") == 0) + strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SIZE), + sizeof(option->text)); + else if (strcmp(name, "MediaType") == 0) + strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_TYPE), + sizeof(option->text)); + else if (strcmp(name, "InputSlot") == 0) + strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SOURCE), + sizeof(option->text)); + else if (strcmp(name, "ColorModel") == 0) + strlcpy(option->text, cupsLangString(language, CUPS_MSG_OUTPUT_MODE), + sizeof(option->text)); + else if (strcmp(name, "Resolution") == 0) + strlcpy(option->text, cupsLangString(language, CUPS_MSG_RESOLUTION), + sizeof(option->text)); + else + strlcpy(option->text, name, sizeof(option->text)); + } + + option->section = PPD_ORDER_ANY; + } + else if (strcmp(keyword, "JCLOpenUI") == 0) + { + /* + * Find the JCL group, and add if needed... + */ + + group = ppd_get_group(ppd, "JCL"); + + if (group == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + /* + * Add an option record to the current JCLs... + */ + + if (name[0] == '*') + strcpy(name, name + 1); + + option = ppd_get_option(group, name); + + if (option == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + /* + * Now fill in the initial information for the option... + */ + + if (strcmp(string, "PickMany") == 0) + option->ui = PPD_UI_PICKMANY; + else if (strcmp(string, "Boolean") == 0) + option->ui = PPD_UI_BOOLEAN; + else + option->ui = PPD_UI_PICKONE; + + strlcpy(option->text, text, sizeof(option->text)); + + option->section = PPD_ORDER_JCL; + group = NULL; + } + else if (strcmp(keyword, "CloseUI") == 0 || + strcmp(keyword, "JCLCloseUI") == 0) + option = NULL; + else if (strcmp(keyword, "OpenGroup") == 0) + { + /* + * Open a new group... + */ + + if (group != NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + if (strncasecmp(string, "InstallableOptions", 18) == 0) + { + /* + * Handle the InstallableOptions group differently than other + * groups; this is necessary so that UIs can correctly + * isolate them from normal user options. + * + * In CUPS 1.2 we have separate text and keyword fields, + * so this "hack" won't be needed... + */ + + group = ppd_get_group(ppd, "InstallableOptions"); + } + else + { + /* + * For all other groups, just use the human readable text... + */ + + if (strchr(string, '/') != NULL) + strcpy(string, strchr(string, '/') + 1); + + ppd_decode(string); + ppd_fix(string); + + group = ppd_get_group(ppd, string); + } + } + else if (strcmp(keyword, "CloseGroup") == 0) + group = NULL; + else if (strcmp(keyword, "OrderDependency") == 0 || + strcmp(keyword, "NonUIOrderDependency") == 0) + { + if (sscanf(string, "%f%40s%40s", &order, name, keyword) != 3) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + if (keyword[0] == '*') + strcpy(keyword, keyword + 1); + + if (strcmp(name, "ExitServer") == 0) + section = PPD_ORDER_EXIT; + else if (strcmp(name, "Prolog") == 0) + section = PPD_ORDER_PROLOG; + else if (strcmp(name, "DocumentSetup") == 0) + section = PPD_ORDER_DOCUMENT; + else if (strcmp(name, "PageSetup") == 0) + section = PPD_ORDER_PAGE; + else if (strcmp(name, "JCLSetup") == 0) + section = PPD_ORDER_JCL; + else + section = PPD_ORDER_ANY; + + if (option == NULL) + { + ppd_group_t *temp; + + + /* + * Only valid for Non-UI options... + */ + + for (i = ppd->num_groups, temp = ppd->groups; i > 0; i --, temp ++) + if (temp->text[0] == '\0') + break; + + if (i > 0) + for (i = 0; i < temp->num_options; i ++) + if (strcmp(keyword, temp->options[i].keyword) == 0) + { + temp->options[i].section = section; + temp->options[i].order = order; + break; + } + } + else + { + option->section = section; + option->order = order; + } + } + else if (strncmp(keyword, "Default", 7) == 0) + { + if (string == NULL) + continue; + + if (strchr(string, '/') != NULL) + *strchr(string, '/') = '\0'; + + if (option == NULL) + { + ppd_group_t *temp; + + + /* + * Only valid for Non-UI options... + */ + + for (i = ppd->num_groups, temp = ppd->groups; i > 0; i --, temp ++) + if (temp->text[0] == '\0') + break; + + if (i > 0) + for (i = 0; i < temp->num_options; i ++) + if (strcmp(keyword, temp->options[i].keyword) == 0) + { + strlcpy(temp->options[i].defchoice, string, + sizeof(temp->options[i].defchoice)); + break; + } + } + else if (strcmp(keyword + 7, option->keyword) == 0) + strlcpy(option->defchoice, string, sizeof(option->defchoice)); + } + else if (strcmp(keyword, "UIConstraints") == 0 || + strcmp(keyword, "NonUIConstraints") == 0) + { + if (ppd->num_consts == 0) + constraint = calloc(sizeof(ppd_const_t), 1); + else + constraint = realloc(ppd->consts, + (ppd->num_consts + 1) * sizeof(ppd_const_t)); + + if (constraint == NULL) + { + ppdClose(ppd); + + safe_free(string); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + ppd->consts = constraint; + constraint += ppd->num_consts; + ppd->num_consts ++; + + switch (sscanf(string, "%40s%40s%40s%40s", constraint->option1, + constraint->choice1, constraint->option2, + constraint->choice2)) + { + case 0 : /* Error */ + case 1 : /* Error */ + ppdClose(ppd); + safe_free(string); + break; + + case 2 : /* Two options... */ + /* + * The following strcpy's are safe, as optionN and + * choiceN are all the same size (size defined by PPD spec...) + */ + + if (constraint->option1[0] == '*') + strcpy(constraint->option1, constraint->option1 + 1); + + if (constraint->choice1[0] == '*') + strcpy(constraint->option2, constraint->choice1 + 1); + else + strcpy(constraint->option2, constraint->choice1); + + constraint->choice1[0] = '\0'; + constraint->choice2[0] = '\0'; + break; + + case 3 : /* Two options, one choice... */ + /* + * The following strcpy's are safe, as optionN and + * choiceN are all the same size (size defined by PPD spec...) + */ + + if (constraint->option1[0] == '*') + strcpy(constraint->option1, constraint->option1 + 1); + + if (constraint->choice1[0] == '*') + { + strcpy(constraint->choice2, constraint->option2); + strcpy(constraint->option2, constraint->choice1 + 1); + constraint->choice1[0] = '\0'; + } + else + { + if (constraint->option2[0] == '*') + strcpy(constraint->option2, constraint->option2 + 1); + + constraint->choice2[0] = '\0'; + } + break; + + case 4 : /* Two options, two choices... */ + if (constraint->option1[0] == '*') + strcpy(constraint->option1, constraint->option1 + 1); + + if (constraint->option2[0] == '*') + strcpy(constraint->option2, constraint->option2 + 1); + break; + } + } + else if (strcmp(keyword, "PaperDimension") == 0) + { + 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); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (NULL); + } + + sscanf(string, "%f%f", &(size->width), &(size->length)); + } + else if (strcmp(keyword, "ImageableArea") == 0) + { + 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); + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + 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)) == + (PPD_KEYWORD | PPD_OPTION | PPD_STRING) && + strcmp(keyword, option->keyword) == 0) + { + DEBUG_printf(("group = %p, subgroup = %p\n", group, subgroup)); + + if (strcmp(keyword, "PageSize") == 0) + { + /* + * Add a page size... + */ + + if (ppdPageSize(ppd, name) == NULL) + ppd_add_size(ppd, name); + } + + /* + * Add the option choice... + */ + + choice = ppd_add_choice(option, name); + + if (mask & PPD_TEXT) + { + strlcpy(choice->text, text, sizeof(choice->text)); + ppd_fix(choice->text); + } + else if (strcmp(name, "True") == 0) + strcpy(choice->text, "Yes"); + else if (strcmp(name, "False") == 0) + strcpy(choice->text, "No"); + else + strlcpy(choice->text, name, sizeof(choice->text)); + + if (option->section == PPD_ORDER_JCL) + ppd_decode(string); /* Decode quoted string */ + + choice->code = string; + string = NULL; /* Don't free this string below */ + } + + safe_free(string); + } + +#ifdef DEBUG + if (!feof(fp)) + printf("Premature EOF at %lu...\n", (unsigned long)ftell(fp)); +#endif /* DEBUG */ + +#ifndef __APPLE__ + /* + * Make sure that all PPD files with an InputSlot option have an + * "auto" choice that maps to no specific tray or media type. + */ + + if ((option = ppdFindOption(ppd, "InputSlot")) != NULL) + { + for (i = 0; i < option->num_choices; i ++) + if (option->choices[i].code == NULL || !option->choices[i].code[0]) + break; + + if (i >= option->num_choices) + { + /* + * No "auto" input slot, add one... + */ + + choice = ppd_add_choice(option, "Auto"); + + strlcpy(choice->text, cupsLangString(language, CUPS_MSG_AUTO), + sizeof(choice->text)); + choice->code = NULL; + } + } +#endif /* !__APPLE__ */ + + /* + * Set the option back-pointer for each choice... + */ + +#ifndef __APPLE__ + qsort(ppd->groups, ppd->num_groups, sizeof(ppd_group_t), + (int (*)(const void *, const void *))compare_groups); +#endif /* !__APPLE__ */ + + for (i = ppd->num_groups, group = ppd->groups; + i > 0; + i --, group ++) + { +#ifndef __APPLE__ + qsort(group->options, group->num_options, sizeof(ppd_option_t), + (int (*)(const void *, const void *))compare_options); +#endif /* !__APPLE__ */ + + for (j = group->num_options, option = group->options; + j > 0; + j --, option ++) + { + for (k = 0; k < option->num_choices; k ++) + option->choices[k].option = (void *)option; + } + +#ifndef __APPLE__ + qsort(group->subgroups, group->num_subgroups, sizeof(ppd_group_t), + (int (*)(const void *, const void *))compare_groups); +#endif /* !__APPLE__ */ + + for (j = group->num_subgroups, subgroup = group->subgroups; + j > 0; + j --, subgroup ++) + { +#ifndef __APPLE__ + qsort(subgroup->options, subgroup->num_options, sizeof(ppd_option_t), + (int (*)(const void *, const void *))compare_options); +#endif /* !__APPLE__ */ + + for (k = group->num_options, option = group->options; + k > 0; + k --, option ++) + { + for (m = 0; m < option->num_choices; m ++) + option->choices[m].option = (void *)option; + } + } + } + + /* + * Reset language preferences... + */ + + cupsLangFree(language); + +#ifdef LC_NUMERIC + setlocale(LC_NUMERIC, oldlocale); +#else + setlocale(LC_ALL, oldlocale); +#endif /* LC_NUMERIC */ + + return (ppd); +} + + +/* + * 'ppdOpenFd()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpenFd(int fd) /* I - File to read from */ +{ + FILE *fp; /* File pointer */ + ppd_file_t *ppd; /* PPD file record */ + + + /* + * Range check input... + */ + + if (fd < 0) + return (NULL); + + /* + * Try to open the file and parse it... + */ + + if ((fp = fdopen(fd, "r")) != NULL) + { + setbuf(fp, NULL); + + ppd = ppdOpen(fp); + + safe_free(fp); + } + else + ppd = NULL; + + return (ppd); +} + + +/* + * 'ppdOpenFile()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpenFile(const char *filename) /* I - File to read from */ +{ + FILE *fp; /* File pointer */ + ppd_file_t *ppd; /* PPD file record */ + + + /* + * Range check input... + */ + + if (filename == NULL) + return (NULL); + + /* + * Try to open the file and parse it... + */ + + if ((fp = fopen(filename, "r")) != NULL) + { + ppd = ppdOpen(fp); + + fclose(fp); + } + else + ppd = NULL; + + return (ppd); +} + + +#ifndef __APPLE__ +/* + * 'compare_strings()' - Compare two strings. + */ + +static int /* O - Result of comparison */ +compare_strings(char *s, /* I - First string */ + char *t) /* I - Second string */ +{ + int diff, /* Difference between digits */ + digits; /* Number of digits */ + + + /* + * Loop through both strings, returning only when a difference is + * seen. Also, compare whole numbers rather than just characters, too! + */ + + while (*s && *t) + { + if (isdigit(*s) && isdigit(*t)) + { + /* + * Got a number; start by skipping leading 0's... + */ + + while (*s == '0') + s ++; + while (*t == '0') + t ++; + + /* + * Skip equal digits... + */ + + while (isdigit(*s) && *s == *t) + { + s ++; + t ++; + } + + /* + * Bounce out if *s and *t aren't both digits... + */ + + if (isdigit(*s) && !isdigit(*t)) + return (1); + else if (!isdigit(*s) && isdigit(*t)) + return (-1); + else if (!isdigit(*s) || !isdigit(*t)) + continue; + + if (*s < *t) + diff = -1; + else + diff = 1; + + /* + * Figure out how many more digits there are... + */ + + digits = 0; + + while (isdigit(*s)) + { + digits ++; + s ++; + } + + while (isdigit(*t)) + { + digits --; + t ++; + } + + /* + * Return if the number or value of the digits is different... + */ + + if (digits < 0) + return (-1); + else if (digits > 0) + return (1); + else + return (diff); + } + else if (tolower(*s) < tolower(*t)) + return (-1); + else if (tolower(*s) > tolower(*t)) + return (1); + else + { + s ++; + t ++; + } + } + + /* + * Return the results of the final comparison... + */ + + if (*s) + return (1); + else if (*t) + return (-1); + else + return (0); +} + + +/* + * 'compare_groups()' - Compare two groups. + */ + +static int /* O - Result of comparison */ +compare_groups(ppd_group_t *g0, /* I - First group */ + ppd_group_t *g1) /* I - Second group */ +{ + return (compare_strings(g0->text, g1->text)); +} + + +/* + * 'compare_options()' - Compare two options. + */ + +static int /* O - Result of comparison */ +compare_options(ppd_option_t *o0,/* I - First option */ + ppd_option_t *o1)/* I - Second option */ +{ + return (compare_strings(o0->text, o1->text)); +} +#endif /* !__APPLE__ */ + + +/* + * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as + * necessary. + */ + +static int /* O - Bitmask of fields read */ +ppd_read(FILE *fp, /* I - File to read from */ + char *keyword, /* O - Keyword from line */ + char *option, /* O - Option from line */ + char *text, /* O - Human-readable text from line */ + 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 */ + *optptr, /* Option pointer */ + *textptr, /* Text pointer */ + *strptr, /* Pointer into string */ + *lineptr, /* Current position in line buffer */ + line[65536]; /* Line buffer (64k) */ + + + /* + * Range check everything... + */ + + if (fp == NULL || keyword == NULL || option == NULL || text == NULL || + string == NULL) + return (0); + + /* + * Now loop until we have a valid line... + */ + + *string = NULL; + + do + { + /* + * Read the line... + */ + + lineptr = line; + endquote = 0; + colon = 0; + + while ((ch = getc(fp)) != EOF && + (lineptr - line) < (sizeof(line) - 1)) + { + if (ch == '\r' || ch == '\n') + { + /* + * Line feed or carriage return... + */ + + if (lineptr == line) /* Skip blank lines */ + continue; + + if (ch == '\r') + { + /* + * Check for a trailing line feed... + */ + + if ((ch = getc(fp)) == EOF) + break; + if (ch != 0x0a) + ungetc(ch, fp); + } + + ch = '\n'; + + if (!endquote) /* Continue for multi-line text */ + break; + + *lineptr++ = '\n'; + } + else + { + /* + * Any other character... + */ + + *lineptr++ = ch; + + if (ch == ':' && strncmp(line, "*%", 2) != 0) + colon = 1; + + if (ch == '\"' && colon) + { + endquote = !endquote; + + if (!endquote) + { + /* + * End of quoted string; ignore trailing characters... + */ + + while ((ch = getc(fp)) != EOF) + if (ch == '\n') + break; + else if (ch == '\r') + { + ch = getc(fp); + if (ch != '\n') + ungetc(ch, fp); + + ch = '\n'; + break; + } + + break; + } + } + } + } + + if (endquote) + { + /* + * Didn't finish this quoted string... + */ + + while ((ch = getc(fp)) != EOF) + if (ch == '\"') + break; + } + + if (ch != '\n') + { + /* + * Didn't finish this line... + */ + + while ((ch = getc(fp)) != EOF) + if (ch == '\r' || ch == '\n') + { + /* + * Line feed or carriage return... + */ + + if (ch == '\r') + { + /* + * Check for a trailing line feed... + */ + + if ((ch = getc(fp)) == EOF) + break; + if (ch != 0x0a) + ungetc(ch, fp); + } + + break; + } + } + + if (lineptr > line && lineptr[-1] == '\n') + lineptr --; + + *lineptr = '\0'; + +/* DEBUG_printf(("LINE = \"%s\"\n", line));*/ + + if (ch == EOF && lineptr == line) + return (0); + + /* + * Now parse it... + */ + + mask = 0; + lineptr = line + 1; + + keyword[0] = '\0'; + option[0] = '\0'; + text[0] = '\0'; + *string = NULL; + + if (line[0] != '*') /* All lines start with an asterisk */ + continue; + + 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; + + /* + * Get a keyword... + */ + + keyptr = keyword; + + while (*lineptr != '\0' && *lineptr != ':' && !isspace(*lineptr)) + if ((keyptr - keyword) < (PPD_MAX_NAME - 1)) + *keyptr++ = *lineptr++; + + *keyptr = '\0'; + + if (strcmp(keyword, "End") == 0) + continue; + + mask |= PPD_KEYWORD; + +/* DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/ + + if (isspace(*lineptr)) + { + /* + * Get an option name... + */ + + while (isspace(*lineptr)) + lineptr ++; + + optptr = option; + + while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':' && + *lineptr != '/') + if ((optptr - option) < (PPD_MAX_NAME - 1)) + *optptr++ = *lineptr++; + + *optptr = '\0'; + mask |= PPD_OPTION; + +/* DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/ + + if (*lineptr == '/') + { + /* + * Get human-readable text... + */ + + lineptr ++; + + textptr = text; + + while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':') + if ((textptr - text) < (PPD_MAX_LINE - 1)) + *textptr++ = *lineptr++; + + *textptr = '\0'; + ppd_decode(text); + + mask |= PPD_TEXT; + } + +/* DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/ + } + + if (*lineptr == ':') + { + /* + * Get string... + */ + + *string = malloc(strlen(lineptr) + 1); + + while (*lineptr == ':' || isspace(*lineptr)) + lineptr ++; + + strptr = *string; + + while (*lineptr != '\0') + { + if (*lineptr != '\"') + *strptr++ = *lineptr++; + else + lineptr ++; + } + + *strptr = '\0'; + +/* DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/ + + mask |= PPD_STRING; + } + } + while (mask == 0); + + return (mask); +} + + +/* + * 'ppd_decode()' - Decode a string value... + */ + +static void +ppd_decode(char *string) /* I - String to decode */ +{ + char *inptr, /* Input pointer */ + *outptr; /* Output pointer */ + + + inptr = string; + outptr = string; + + while (*inptr != '\0') + if (*inptr == '<' && isxdigit(inptr[1])) + { + /* + * Convert hex to 8-bit values... + */ + + inptr ++; + while (isxdigit(*inptr)) + { + if (isalpha(*inptr)) + *outptr = (tolower(*inptr) - 'a' + 10) << 4; + else + *outptr = (*inptr - '0') << 4; + + inptr ++; + + if (isalpha(*inptr)) + *outptr |= tolower(*inptr) - 'a' + 10; + else + *outptr |= *inptr - '0'; + + inptr ++; + outptr ++; + } + + while (*inptr != '>' && *inptr != '\0') + inptr ++; + while (*inptr == '>') + inptr ++; + } + else + *outptr++ = *inptr++; + + *outptr = '\0'; +} + + +#ifndef __APPLE__ +/* + * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be + * valid ISO-8859-1 characters... + */ + +static void +ppd_fix(char *string) /* IO - String to fix */ +{ + unsigned char *p; /* Pointer into string */ + static unsigned char lut[32] =/* Lookup table for characters */ + { + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 'l', + '`', + '\'', + '^', + '~', + 0x20, /* bar */ + 0x20, /* circumflex */ + 0x20, /* dot */ + 0x20, /* double dot */ + 0x20, + 0x20, /* circle */ + 0x20, /* ??? */ + 0x20, + '\"', /* should be right quotes */ + 0x20, /* ??? */ + 0x20 /* accent */ + }; + + + for (p = (unsigned char *)string; *p; p ++) + if (*p >= 0x80 && *p < 0xa0) + *p = lut[*p - 0x80]; +} +#endif /* !__APPLE__ */ + + +/* + * End of "$Id$". + */ diff --git a/cups/ppd.h b/cups/ppd.h new file mode 100644 index 0000000000..88d4aaca5c --- /dev/null +++ b/cups/ppd.h @@ -0,0 +1,270 @@ +/* + * "$Id$" + * + * PostScript Printer Description definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2002 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 + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_PPD_H_ +# define _CUPS_PPD_H_ + +/* + * Include necessary headers... + */ + +# include + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * PPD version... + */ + +# define PPD_VERSION 4.3 /* Kept in sync with Adobe version number */ + + +/* + * PPD size limits (defined in Adobe spec) + */ + +# define PPD_MAX_NAME 41 /* Maximum size of name + 1 for nul */ +# define PPD_MAX_TEXT 81 /* Maximum size of text + 1 for nul */ +# define PPD_MAX_LINE 256 /* Maximum size of line + 1 for nul */ + + +/* + * Types and structures... + */ + +typedef enum /**** UI types ****/ +{ + PPD_UI_BOOLEAN, /* True or False option */ + PPD_UI_PICKONE, /* Pick one from a list */ + PPD_UI_PICKMANY /* Pick zero or more from a list */ +} ppd_ui_t; + +typedef enum /**** Order dependency sections ****/ +{ + PPD_ORDER_ANY, /* Option code can be anywhere in the file */ + PPD_ORDER_DOCUMENT, /* ... must be in the DocumentSetup section */ + PPD_ORDER_EXIT, /* ... must be sent prior to the document */ + PPD_ORDER_JCL, /* ... must be sent as a JCL command */ + PPD_ORDER_PAGE, /* ... must be in the PageSetup section */ + PPD_ORDER_PROLOG /* ... must be in the Prolog section */ +} ppd_section_t; + +typedef enum /**** Colorspaces ****/ +{ + PPD_CS_CMYK = -4, /* CMYK colorspace */ + PPD_CS_CMY, /* CMY colorspace */ + PPD_CS_GRAY = 1, /* Grayscale colorspace */ + PPD_CS_RGB = 3, /* RGB colorspace */ + PPD_CS_RGBK, /* RGBK (K = gray) colorspace */ + PPD_CS_N /* DeviceN colorspace */ +} ppd_cs_t; + +typedef struct /**** Option choices ****/ +{ + char marked, /* 0 if not selected, 1 otherwise */ + choice[PPD_MAX_NAME], + /* Computer-readable option name */ + text[PPD_MAX_TEXT], + /* Human-readable option name */ + *code; /* Code to send for this option */ + void *option; /* Pointer to parent option structure */ +} ppd_choice_t; + +typedef struct /**** Options ****/ +{ + char conflicted, /* 0 if no conflicts exist, 1 otherwise */ + keyword[PPD_MAX_NAME], + /* Option keyword name ("PageSize", etc.) */ + defchoice[PPD_MAX_NAME], + /* Default option choice */ + text[PPD_MAX_TEXT]; + /* Human-readable text */ + ppd_ui_t ui; /* Type of UI option */ + ppd_section_t section; /* Section for command */ + float order; /* Order number */ + int num_choices; /* Number of option choices */ + ppd_choice_t *choices; /* Option choices */ +} ppd_option_t; + +typedef struct ppd_group_str /**** Groups ****/ +{ + char text[PPD_MAX_TEXT]; + /* Human-readable group name */ + int num_options; /* Number of options */ + ppd_option_t *options; /* Options */ + int num_subgroups; /* Number of sub-groups */ + struct ppd_group_str *subgroups; + /* Sub-groups (max depth = 1) */ +} ppd_group_t; + +typedef struct /**** Constraints ****/ +{ + char option1[PPD_MAX_NAME], + /* First keyword */ + choice1[PPD_MAX_NAME], + /* First option/choice (blank for all) */ + option2[PPD_MAX_NAME], + /* Second keyword */ + choice2[PPD_MAX_NAME]; + /* Second option/choice (blank for all) */ +} ppd_const_t; + +typedef struct /**** Page Sizes ****/ +{ + int marked; /* Page size selected? */ + char name[PPD_MAX_NAME]; + /* Media size option */ + float width, /* Width of media in points */ + length, /* Length of media in points */ + left, /* Left printable margin in points */ + bottom, /* Bottom printable margin in points */ + right, /* Right printable margin in points */ + top; /* Top printable margin in points */ +} ppd_size_t; + +typedef struct /**** Emulators ****/ +{ + char name[PPD_MAX_NAME], + /* Emulator name */ + *start, /* Code to switch to this emulation */ + *stop; /* Code to stop this emulation */ +} ppd_emul_t; + +typedef struct /**** sRGB Color Profiles ****/ +{ + char resolution[PPD_MAX_NAME], + /* Resolution or "-" */ + media_type[PPD_MAX_NAME]; + /* Media type of "-" */ + float density, /* Ink density to use */ + gamma, /* Gamma correction to use */ + matrix[3][3]; /* Transform matrix */ +} ppd_profile_t; + +typedef struct /**** Files ****/ +{ + int language_level, /* Language level of device */ + color_device, /* 1 = color device, 0 = grayscale */ + variable_sizes, /* 1 = supports variable sizes, 0 = doesn't */ + accurate_screens,/* 1 = supports accurate screens, 0 = not */ + contone_only, /* 1 = continuous tone only, 0 = not */ + landscape, /* -90 or 90 */ + model_number, /* Device-specific model number */ + manual_copies, /* 1 = Copies done manually, 0 = hardware */ + throughput; /* Pages per minute */ + ppd_cs_t colorspace; /* Default colorspace */ + char *patches; /* Patch commands to be sent to printer */ + int num_emulations; /* Number of emulations supported */ + ppd_emul_t *emulations; /* Emulations and the code to invoke them */ + char *jcl_begin, /* Start JCL commands */ + *jcl_ps, /* Enter PostScript interpreter */ + *jcl_end, /* End JCL commands */ + *lang_encoding, /* Language encoding */ + *lang_version, /* Language version (English, Spanish, etc.) */ + *modelname, /* Model name (general) */ + *ttrasterizer, /* Truetype rasterizer */ + *manufacturer, /* Manufacturer name */ + *product, /* Product name (from PS RIP/interpreter) */ + *nickname, /* Nickname (specific) */ + *shortnickname; /* Short version of nickname */ + int num_groups; /* Number of UI groups */ + ppd_group_t *groups; /* UI groups */ + int num_sizes; /* Number of page sizes */ + ppd_size_t *sizes; /* Page sizes */ + float custom_min[2], /* Minimum variable page size */ + custom_max[2], /* Maximum variable page size */ + custom_margins[4];/* Margins around page */ + int num_consts; /* Number of UI/Non-UI constraints */ + ppd_const_t *consts; /* UI/Non-UI constraints */ + int num_fonts; /* Number of pre-loaded fonts */ + char **fonts; /* Pre-loaded fonts */ + int num_profiles; /* Number of sRGB color profiles */ + ppd_profile_t *profiles; /* sRGB color profiles */ + int num_filters; /* Number of filters */ + char **filters; /* Filter strings... */ + int flip_duplex; /* 1 = Flip page for back sides */ +} ppd_file_t; + + +/* + * Prototypes... + */ + +extern void ppdClose(ppd_file_t *ppd); +extern int ppdCollect(ppd_file_t *ppd, ppd_section_t section, + ppd_choice_t ***choices); +extern int ppdConflicts(ppd_file_t *ppd); +extern int ppdEmit(ppd_file_t *ppd, FILE *fp, + ppd_section_t section); +extern int ppdEmitFd(ppd_file_t *ppd, int fd, + ppd_section_t section); +extern int ppdEmitJCL(ppd_file_t *ppd, FILE *fp, int job_id, + const char *user, const char *title); +extern int ppdIsMarked(ppd_file_t *ppd, const char *keyword, + const char *option); +extern void ppdMarkDefaults(ppd_file_t *ppd); +extern int ppdMarkOption(ppd_file_t *ppd, const char *keyword, + const char *option); +extern ppd_choice_t *ppdFindChoice(ppd_option_t *o, const char *option); +extern ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword); +extern ppd_option_t *ppdFindOption(ppd_file_t *ppd, const char *keyword); +extern ppd_file_t *ppdOpen(FILE *fp); +extern ppd_file_t *ppdOpenFd(int fd); +extern ppd_file_t *ppdOpenFile(const char *filename); +extern float ppdPageLength(ppd_file_t *ppd, const char *name); +extern ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name); +extern float ppdPageWidth(ppd_file_t *ppd, const char *name); + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_PPD_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/snprintf.c b/cups/snprintf.c new file mode 100644 index 0000000000..61853b2b0a --- /dev/null +++ b/cups/snprintf.c @@ -0,0 +1,306 @@ +/* + * "$Id$" + * + * snprintf functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cups_vsnprintf() - Format a string into a fixed size buffer. + * cups_snprintf() - Format a string into a fixed size buffer. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include "string.h" + + +#ifndef HAVE_VSNPRINTF +/* + * 'cups_vsnprintf()' - Format a string into a fixed size buffer. + */ + +int /* O - Number of bytes formatted */ +cups_vsnprintf(char *buffer, /* O - Output buffer */ + size_t bufsize, /* O - Size of output buffer */ + const char *format, /* I - printf-style format string */ + va_list ap) /* I - Pointer to additional arguments */ +{ + char *bufptr, /* Pointer to position in buffer */ + *bufend, /* Pointer to end of buffer */ + sign, /* Sign of format width */ + size, /* Size character (h, l, L) */ + type; /* Format type character */ + const char *bufformat; /* Start of format */ + int width, /* Width of field */ + prec; /* Number of characters of precision */ + char tformat[100], /* Temporary format string for sprintf() */ + temp[1024]; /* Buffer for formatted numbers */ + char *s; /* Pointer to string */ + int slen; /* Length of string */ + + + /* + * Loop through the format string, formatting as needed... + */ + + bufptr = buffer; + bufend = buffer + bufsize - 1; + + while (*format && bufptr < bufend) + { + if (*format == '%') + { + bufformat = format; + format ++; + + if (*format == '%') + { + *bufptr++ = *format++; + continue; + } + else if (strchr(" -+#\'", *format)) + sign = *format++; + else + sign = 0; + + width = 0; + while (isdigit(*format)) + width = width * 10 + *format++ - '0'; + + if (*format == '.') + { + format ++; + prec = 0; + + while (isdigit(*format)) + prec = prec * 10 + *format++ - '0'; + } + else + prec = -1; + + if (*format == 'l' && format[1] == 'l') + { + size = 'L'; + format += 2; + } + else if (*format == 'h' || *format == 'l' || *format == 'L') + size = *format++; + + if (!*format) + break; + + type = *format++; + + switch (type) + { + case 'E' : /* Floating point formats */ + case 'G' : + case 'e' : + case 'f' : + case 'g' : + if ((format - bufformat + 1) > sizeof(tformat) || + (width + 2) > sizeof(temp)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + sprintf(temp, tformat, va_arg(ap, double)); + + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, bufend - bufptr); + bufptr = bufend; + break; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + break; + + case 'B' : /* Integer formats */ + case 'X' : + case 'b' : + case 'd' : + case 'i' : + case 'o' : + case 'u' : + case 'x' : + if ((format - bufformat + 1) > sizeof(tformat) || + (width + 2) > sizeof(temp)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + sprintf(temp, tformat, va_arg(ap, int)); + + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, bufend - bufptr); + bufptr = bufend; + break; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + break; + + case 'p' : /* Pointer value */ + if ((format - bufformat + 1) > sizeof(tformat) || + (width + 2) > sizeof(temp)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + sprintf(temp, tformat, va_arg(ap, void *)); + + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, bufend - bufptr); + bufptr = bufend; + break; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + break; + + case 'c' : /* Character or character array */ + if (width <= 1) + *bufptr++ = va_arg(ap, int); + else + { + if ((bufptr + width) > bufend) + width = bufend - bufptr; + + memcpy(bufptr, va_arg(ap, char *), width); + bufptr += width; + } + break; + + case 's' : /* String */ + if ((s = va_arg(ap, char *)) == NULL) + s = "(null)"; + + slen = strlen(s); + if (slen > width && prec != width) + width = slen; + + if ((bufptr + width) > bufend) + width = bufend - bufptr; + + if (slen > width) + slen = width; + + if (sign == '-') + { + strncpy(bufptr, s, slen); + memset(bufptr + slen, ' ', width - slen); + } + else + { + memset(bufptr, ' ', width - slen); + strncpy(bufptr + width - slen, s, slen); + } + + bufptr += width; + break; + + case 'n' : /* Output number of chars so far */ + if ((format - bufformat + 1) > sizeof(tformat) || + (width + 2) > sizeof(temp)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + sprintf(temp, tformat, va_arg(ap, int)); + + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, bufend - bufptr); + bufptr = bufend; + break; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + break; + } + } + else + *bufptr++ = *format++; + } + + /* + * Nul-terminate the string and return the number of characters in it. + */ + + *bufptr = '\0'; + return (bufptr - buffer); +} +#endif /* !HAVE_VSNPRINT */ + + +#ifndef HAVE_SNPRINTF +/* + * 'cups_snprintf()' - Format a string into a fixed size buffer. + */ + +int /* O - Number of bytes formatted */ +cups_snprintf(char *buffer, /* O - Output buffer */ + size_t bufsize, /* O - Size of output buffer */ + const char *format, /* I - printf-style format string */ + ...) /* I - Additional arguments as needed */ +{ + int bytes; /* Number of bytes formatted */ + va_list ap; /* Pointer to additional arguments */ + + + va_start(ap, format); + bytes = vsnprintf(buffer, bufsize, format, ap); + va_end(ap); + + return (bytes); +} +#endif /* !HAVE_SNPRINTF */ + + +/* + * End of "$Id$". + */ + diff --git a/cups/string.c b/cups/string.c new file mode 100644 index 0000000000..4d97525fd3 --- /dev/null +++ b/cups/string.c @@ -0,0 +1,210 @@ +/* + * "$Id$" + * + * String functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cups_strdup() - Duplicate a string. + * cups_strcasecmp() - Do a case-insensitive comparison. + * cups_strncasecmp() - Do a case-insensitive comparison on up to N chars. + * cups_strlcat() - Safely concatenate two strings. + * cups_strlcpy() - Safely copy two strings. + */ + +/* + * Include necessary headers... + */ + +#include "string.h" + + +/* + * 'cups_strdup()' - Duplicate a string. + */ + +#ifndef HAVE_STRDUP +char * /* O - New string pointer */ +cups_strdup(const char *s) /* I - String to duplicate */ +{ + char *t; /* New string pointer */ + + + if (s == NULL) + return (NULL); + + if ((t = malloc(strlen(s) + 1)) == NULL) + return (NULL); + + return (strcpy(t, s)); +} +#endif /* !HAVE_STRDUP */ + + +/* + * 'cups_strcasecmp()' - Do a case-insensitive comparison. + */ + +#ifndef HAVE_STRCASECMP +int /* O - Result of comparison (-1, 0, or 1) */ +cups_strcasecmp(const char *s, /* I - First string */ + const char *t) /* I - Second string */ +{ + while (*s != '\0' && *t != '\0') + { + if (tolower(*s) < tolower(*t)) + return (-1); + else if (tolower(*s) > tolower(*t)) + return (1); + + s ++; + t ++; + } + + if (*s == '\0' && *t == '\0') + return (0); + else if (*s != '\0') + return (1); + else + return (-1); +} +#endif /* !HAVE_STRCASECMP */ + +/* + * 'cups_strncasecmp()' - Do a case-insensitive comparison on up to N chars. + */ + +#ifndef HAVE_STRNCASECMP +int /* O - Result of comparison (-1, 0, or 1) */ +cups_strncasecmp(const char *s, /* I - First string */ + const char *t, /* I - Second string */ + size_t n) /* I - Maximum number of characters to compare */ +{ + while (*s != '\0' && *t != '\0' && n > 0) + { + if (tolower(*s) < tolower(*t)) + return (-1); + else if (tolower(*s) > tolower(*t)) + return (1); + + s ++; + t ++; + n --; + } + + if (n == 0) + return (0); + else if (*s == '\0' && *t == '\0') + return (0); + else if (*s != '\0') + return (1); + else + return (-1); +} +#endif /* !HAVE_STRNCASECMP */ + + +#ifndef HAVE_STRLCAT +/* + * 'cups_strlcat()' - Safely concatenate two strings. + */ + +size_t /* O - Length of string */ +cups_strlcat(char *dst, /* O - Destination string */ + const char *src, /* I - Source string */ + size_t size) /* I - Size of destination string buffer */ +{ + size_t srclen; /* Length of source string */ + size_t dstlen; /* Length of destination string */ + + + /* + * Figure out how much room is left... + */ + + dstlen = strlen(dst); + size -= dstlen + 1; + + if (!size) + return (dstlen); /* No room, return immediately... */ + + /* + * Figure out how much room is needed... + */ + + srclen = strlen(src); + + /* + * Copy the appropriate amount... + */ + + if (srclen > size) + srclen = size; + + memcpy(dst + dstlen, src, srclen); + dst[dstlen + srclen] = '\0'; + + return (dstlen + srclen); +} +#endif /* !HAVE_STRLCAT */ + + +#ifndef HAVE_STRLCPY +/* + * 'cups_strlcpy()' - Safely copy two strings. + */ + +size_t /* O - Length of string */ +cups_strlcpy(char *dst, /* O - Destination string */ + const char *src, /* I - Source string */ + size_t size) /* I - Size of destination string buffer */ +{ + size_t srclen; /* Length of source string */ + + + /* + * Figure out how much room is needed... + */ + + size --; + + srclen = strlen(src); + + /* + * Copy the appropriate amount... + */ + + if (srclen > size) + srclen = size; + + memcpy(dst, src, srclen); + dst[srclen] = '\0'; + + return (srclen); +} +#endif /* !HAVE_STRLCPY */ + + +/* + * End of "$Id$". + */ diff --git a/cups/string.h b/cups/string.h new file mode 100644 index 0000000000..996b4a2738 --- /dev/null +++ b/cups/string.h @@ -0,0 +1,128 @@ +/* + * "$Id$" + * + * String definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + */ + +#ifndef _CUPS_STRING_H_ +# define _CUPS_STRING_H_ + +/* + * Include necessary headers... + */ + +# include + +# include +# include +# include + +# ifdef HAVE_STRING_H +# include +# endif /* HAVE_STRING_H */ + +# ifdef HAVE_STRINGS_H +# include +# endif /* HAVE_STRINGS_H */ + +# ifdef HAVE_BSTRING_H +# include +# endif /* HAVE_BSTRING_H */ + + +/* + * Stuff for WIN32 and OS/2... + */ + +# if defined(WIN32) || defined(__EMX__) +# define strcasecmp stricmp +# define strncasecmp strnicmp +# endif /* WIN32 || __EMX__ */ + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Prototypes... + */ + +# ifndef HAVE_STRDUP +extern char *cups_strdup(const char *); +# define strdup cups_strdup +# endif /* !HAVE_STRDUP */ + +# ifndef HAVE_STRCASECMP +extern int cups_strcasecmp(const char *, const char *); +# define strcasecmp cups_strcasecmp +# endif /* !HAVE_STRCASECMP */ + +# ifndef HAVE_STRNCASECMP +extern int cups_strncasecmp(const char *, const char *, size_t n); +# define strncasecmp cups_strncasecmp +# endif /* !HAVE_STRNCASECMP */ + +# ifndef HAVE_STRLCAT +extern size_t cups_strlcat(char *, const char *, size_t); +# define strlcat cups_strlcat +# endif /* !HAVE_STRLCAT */ + +# ifndef HAVE_STRLCPY +extern size_t cups_strlcpy(char *, const char *, size_t); +# define strlcpy cups_strlcpy +# endif /* !HAVE_STRLCPY */ + +# ifndef HAVE_SNPRINTF +extern int cups_snprintf(char *, size_t, const char *, ...) +# ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 3, 4))) +# endif /* __GNUC__ */ +; +# define snprintf cups_snprintf +# endif /* !HAVE_SNPRINTF */ + +# ifndef HAVE_VSNPRINTF +extern int cups_vsnprintf(char *, size_t, const char *, va_list); +# define vsnprintf cups_vsnprintf +# endif /* !HAVE_VSNPRINTF */ + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_CUPS_STRING_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/tempfile.c b/cups/tempfile.c new file mode 100644 index 0000000000..ae9b861da5 --- /dev/null +++ b/cups/tempfile.c @@ -0,0 +1,208 @@ +/* + * "$Id$" + * + * Temp file utilities for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsTempFd() - Create a temporary file. + * cupsTempFile() - Generate a temporary filename. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "string.h" +#include "debug.h" +#include +#include +#include +#include +#include +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * 'cupsTempFd()' - Create a temporary file. + */ + +int /* O - New file descriptor */ +cupsTempFd(char *filename, /* I - Pointer to buffer */ + int len) /* I - Size of buffer */ +{ + int fd; /* File descriptor for temp file */ + int tries; /* Number of tries */ +#ifdef WIN32 + char tmpdir[1024]; /* Windows temporary directory */ + DWORD curtime; /* Current time */ +#else + char *tmpdir; /* TMPDIR environment var */ + struct timeval curtime; /* Current time */ +#endif /* WIN32 */ + static char buf[1024] = ""; /* Buffer if you pass in NULL and 0 */ + + + /* + * See if a filename was specified... + */ + + if (filename == NULL) + { + filename = buf; + len = sizeof(buf); + } + + /* + * See if TMPDIR is defined... + */ + +#ifdef WIN32 + GetTempPath(sizeof(tmpdir), tmpdir); +#else + if ((tmpdir = getenv("TMPDIR")) == NULL) + { + /* + * Put root temp files in restricted temp directory... + */ + + if (getuid() == 0) + tmpdir = CUPS_REQUESTS "/tmp"; + else + tmpdir = "/var/tmp"; + } +#endif /* WIN32 */ + + /* + * Make the temporary name using the specified directory... + */ + + tries = 0; + + do + { +#ifdef WIN32 + /* + * Get the current time of day... + */ + + curtime = GetTickCount() + tries; + + /* + * Format a string using the hex time values... + */ + + snprintf(filename, len - 1, "%s/%05lx%08lx", tmpdir, + GetCurrentProcessId(), curtime); +#else + /* + * Get the current time of day... + */ + + gettimeofday(&curtime, NULL); + + /* + * Format a string using the hex time values... + */ + + snprintf(filename, len - 1, "%s/%08lx%05lx", tmpdir, + (unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec); +#endif /* WIN32 */ + + /* + * Open the file in "exclusive" mode, making sure that we don't + * stomp on an existing file or someone's symlink crack... + */ + +#ifdef O_NOFOLLOW + fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); +#else + fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); +#endif /* O_NOFOLLOW */ + + if (fd < 0 && errno != EEXIST) + break; + + tries ++; + } + while (fd < 0 && tries < 1000); + + /* + * Return the file descriptor... + */ + + return (fd); +} + + +/* + * 'cupsTempFile()' - Generate a temporary filename. + */ + +char * /* O - Filename */ +cupsTempFile(char *filename, /* I - Pointer to buffer */ + int len) /* I - Size of buffer */ +{ + int fd; /* File descriptor for temp file */ + static char buf[1024] = ""; /* Buffer if you pass in NULL and 0 */ + + + /* + * See if a filename was specified... + */ + + if (filename == NULL) + { + filename = buf; + len = sizeof(buf); + } + + /* + * Create the temporary file... + */ + + if ((fd = cupsTempFd(filename, len)) < 0) + return (NULL); + + /* + * Close the temp file - it'll be reopened later as needed... + */ + + close(fd); + + /* + * Return the temp filename... + */ + + return (filename); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/testhttp.c b/cups/testhttp.c new file mode 100644 index 0000000000..baffbcb28b --- /dev/null +++ b/cups/testhttp.c @@ -0,0 +1,126 @@ +/* + * "$Id$" + * + * HTTP test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Main entry. + */ + +/* + * Include necessary headers... + */ + +#include +#include "http.h" + + +/* + * 'main()' - Main entry. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + http_t *http; /* HTTP connection */ + http_status_t status; /* Status of GET command */ + char buffer[8192]; /* Input buffer */ + long bytes; /* Number of bytes read */ + FILE *out; /* Output file */ + char host[HTTP_MAX_URI], + method[HTTP_MAX_URI], + username[HTTP_MAX_URI], + resource[HTTP_MAX_URI]; + int port; + long length, total; + time_t start, current; + + + + http = NULL; + out = stdout; + + for (i = 1; i < argc; i ++) + { + if (strcmp(argv[i], "-o") == 0) + { + i ++; + out = fopen(argv[i], "wb"); + continue; + } + + httpSeparate(argv[i], method, username, host, &port, resource); + + http = httpConnect(host, port); + if (http == NULL) + { + perror(host); + continue; + } + printf("Requesting file \"%s\"...\n", resource); + httpClearFields(http); + httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); + httpGet(http, resource); + while ((status = httpUpdate(http)) == HTTP_CONTINUE); + + if (status == HTTP_OK) + puts("GET OK:"); + else + printf("GET failed with status %d...\n", status); + + + start = time(NULL); + length = atoi(httpGetField(http, HTTP_FIELD_CONTENT_LENGTH)); + total = 0; + + while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0) + { + total += bytes; + fwrite(buffer, bytes, 1, out); + if (out != stdout) + { + current = time(NULL); + if (current == start) current ++; + printf("\r%ld/%ld bytes (%ld bytes/sec) ", total, length, + total / (current - start)); + fflush(stdout); + } + } + } + + puts("Closing connection to server..."); + httpClose(http); + + if (out != stdout) + fclose(out); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/testlang.c b/cups/testlang.c new file mode 100644 index 0000000000..4ac708b58a --- /dev/null +++ b/cups/testlang.c @@ -0,0 +1,96 @@ +/* + * "$Id$" + * + * HTTP test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Load the specified language and show the strings for yes and no. + */ + +/* + * Include necessary headers... + */ + +#include +#include "language.h" + + +/* + * 'main()' - Load the specified language and show the strings for yes and no. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + cups_lang_t *language; /* Message catalog */ + static const char *charsets[] = /* Character sets */ + { + "us-ascii", + "iso-8859-1", + "iso-8859-2", + "iso-8859-3", + "iso-8859-4", + "iso-8859-5", + "iso-8859-6", + "iso-8859-7", + "iso-8859-8", + "iso-8859-9", + "iso-8859-10", + "utf-8", + "iso8859-13", + "iso8859-14", + "iso8859-15", + "windows-874", + "windows-1250", + "windows-1251", + "windows-1252", + "windows-1253", + "windows-1254", + "windows-1255", + "windows-1256", + "windows-1257", + "windows-1258", + "koi8-r", + "koi8-u" + }; + + + if (argc == 1) + language = cupsLangDefault(); + else + language = cupsLangGet(argv[1]); + + printf("Language = \"%s\"\n", language->language); + printf("Encoding = \"%s\"\n", charsets[language->encoding]); + printf("No = \"%s\"\n", cupsLangString(language, CUPS_MSG_NO)); + printf("Yes = \"%s\"\n", cupsLangString(language, CUPS_MSG_YES)); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/testmime.dsp b/cups/testmime.dsp new file mode 100644 index 0000000000..33fbd301af --- /dev/null +++ b/cups/testmime.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="testmime" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=testmime - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testmime.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testmime.mak" CFG="testmime - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testmime - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "testmime - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testmime - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"testmime.exe" + +!ELSEIF "$(CFG)" == "testmime - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "testmime___Win32_Debug" +# PROP BASE Intermediate_Dir "testmime___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /I "../visualc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"testmimed.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "testmime - Win32 Release" +# Name "testmime - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\testmime.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\mime.h +# End Source File +# End Group +# End Target +# End Project diff --git a/cups/testppd.c b/cups/testppd.c new file mode 100644 index 0000000000..249851029c --- /dev/null +++ b/cups/testppd.c @@ -0,0 +1,197 @@ +/* + * "$Id$" + * + * PPD test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 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 + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Main entry for test program. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "string.h" + + +/* + * 'main()' - Main entry for test program. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i, j, k, m; /* Looping vars */ + ppd_file_t *ppd; /* PPD file record */ + ppd_size_t *size; /* Size record */ + ppd_group_t *group; /* UI group */ + ppd_option_t *option; /* Standard UI option */ + ppd_choice_t *choice; /* Standard UI option choice */ + static char *uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" }; + static char *sections[] = { "ANY", "DOCUMENT", "EXIT", + "JCL", "PAGE", "PROLOG" }; + + + setbuf(stdout, NULL); + + /* + * Display PPD files for each file listed on the command-line... + */ + + if (argc == 1) + { + fputs("Usage: ppdtest filename1.ppd [... filenameN.ppd]\n", stderr); + return (1); + } + + for (i = 1; i < argc; i ++) + { + if ((ppd = ppdOpenFile(argv[i])) == NULL) + { + fprintf(stderr, "Unable to open \'%s\' as a PPD file!\n", argv[i]); + continue; + } + + printf("FILE: %s\n", argv[i]); + printf(" language_level = %d\n", ppd->language_level); + printf(" color_device = %s\n", ppd->color_device ? "TRUE" : "FALSE"); + printf(" variable_sizes = %s\n", ppd->variable_sizes ? "TRUE" : "FALSE"); + printf(" landscape = %d\n", ppd->landscape); + + switch (ppd->colorspace) + { + case PPD_CS_CMYK : + puts(" colorspace = PPD_CS_CMYK"); + break; + case PPD_CS_CMY : + puts(" colorspace = PPD_CS_CMY"); + break; + case PPD_CS_GRAY : + puts(" colorspace = PPD_CS_GRAY"); + break; + case PPD_CS_RGB : + puts(" colorspace = PPD_CS_RGB"); + break; + default : + puts(" colorspace = "); + break; + } + + printf(" num_emulations = %d\n", ppd->num_emulations); + for (j = 0; j < ppd->num_emulations; j ++) + printf(" emulations[%d] = %s\n", j, ppd->emulations[j].name); + + printf(" lang_encoding = %s\n", ppd->lang_encoding); + printf(" lang_version = %s\n", ppd->lang_version); + printf(" modelname = %s\n", ppd->modelname); + printf(" ttrasterizer = %s\n", + ppd->ttrasterizer == NULL ? "None" : ppd->ttrasterizer); + printf(" manufacturer = %s\n", ppd->manufacturer); + printf(" product = %s\n", ppd->product); + printf(" nickname = %s\n", ppd->nickname); + printf(" shortnickname = %s\n", ppd->shortnickname); + printf(" patches = %d bytes\n", + ppd->patches == NULL ? 0 : (int)strlen(ppd->patches)); + + printf(" num_groups = %d\n", ppd->num_groups); + for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++) + { + printf(" group[%d] = %s\n", j, group->text); + + for (k = 0, option = group->options; k < group->num_options; k ++, option ++) + { + printf(" options[%d] = %s (%s) %s %s %.0f (%d choices)\n", k, + option->keyword, option->text, uis[option->ui], + sections[option->section], option->order, + option->num_choices); + + if (strcmp(option->keyword, "PageSize") == 0 || + strcmp(option->keyword, "PageRegion") == 0) + { + for (m = option->num_choices, choice = option->choices; + m > 0; + m --, choice ++) + { + size = ppdPageSize(ppd, choice->choice); + + if (size == NULL) + printf(" %s (%s) = ERROR", choice->choice, choice->text); + else + printf(" %s (%s) = %.2fx%.2fin (%.1f,%.1f,%.1f,%.1f)", choice->choice, + choice->text, size->width / 72.0, size->length / 72.0, + size->left / 72.0, size->bottom / 72.0, + size->right / 72.0, size->top / 72.0); + + if (strcmp(option->defchoice, choice->choice) == 0) + puts(" *"); + else + putchar('\n'); + } + } + else + { + for (m = option->num_choices, choice = option->choices; + m > 0; + m --, choice ++) + { + printf(" %s (%s)", choice->choice, choice->text); + + if (strcmp(option->defchoice, choice->choice) == 0) + puts(" *"); + else + putchar('\n'); + } + } + } + } + + printf(" num_profiles = %d\n", ppd->num_profiles); + for (j = 0; j < ppd->num_profiles; j ++) + printf(" profiles[%d] = %s/%s %.3f %.3f [ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n", + j, ppd->profiles[j].resolution, ppd->profiles[j].media_type, + ppd->profiles[j].gamma, ppd->profiles[j].density, + ppd->profiles[j].matrix[0][0], ppd->profiles[j].matrix[0][1], + ppd->profiles[j].matrix[0][2], ppd->profiles[j].matrix[1][0], + ppd->profiles[j].matrix[1][1], ppd->profiles[j].matrix[1][2], + ppd->profiles[j].matrix[2][0], ppd->profiles[j].matrix[2][1], + ppd->profiles[j].matrix[2][2]); + + printf(" num_fonts = %d\n", ppd->num_fonts); + for (j = 0; j < ppd->num_fonts; j ++) + printf(" fonts[%d] = %s\n", j, ppd->fonts[j]); + + ppdClose(ppd); + } + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/testppd.dsp b/cups/testppd.dsp new file mode 100644 index 0000000000..27d4f035ce --- /dev/null +++ b/cups/testppd.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="testppd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=testppd - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testppd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testppd.mak" CFG="testppd - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testppd - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "testppd - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testppd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"testppd.exe" + +!ELSEIF "$(CFG)" == "testppd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "testppd___Win32_Debug" +# PROP BASE Intermediate_Dir "testppd___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /I "../visualc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"testppdd.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "testppd - Win32 Release" +# Name "testppd - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\testppd.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\ppd.h +# End Source File +# End Group +# End Target +# End Project diff --git a/cups/usersys.c b/cups/usersys.c new file mode 100644 index 0000000000..464e1867b1 --- /dev/null +++ b/cups/usersys.c @@ -0,0 +1,460 @@ +/* + * "$Id$" + * + * User, system, and password routines for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsEncryption() - Get the default encryption settings... + * cupsGetPassword() - Get a password from the user... + * cupsServer() - Return the hostname of the default server... + * cupsSetEncryption() - Set the encryption preference. + * cupsSetPasswordCB() - Set the password callback for CUPS. + * cupsSetServer() - Set the default server name... + * cupsSetUser() - Set the default user name... + * cupsUser() - Return the current users name. + * cups_get_password() - Get a password from the user... + * cups_get_line() - Get a line from a file... + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "string.h" +#include +#include + +#ifdef WIN32 +# include +#endif /* WIN32 */ + + +/* + * Local functions... + */ + +static const char *cups_get_password(const char *prompt); +static char *cups_get_line(char *buf, int buflen, FILE *fp); + + +/* + * Local globals... + */ + +static http_encryption_t cups_encryption = (http_encryption_t)-1; +static char cups_user[65] = "", + cups_server[256] = ""; +static const char *(*cups_pwdcb)(const char *) = cups_get_password; + + +/* + * 'cupsEncryption()' - Get the default encryption settings... + */ + +http_encryption_t +cupsEncryption(void) +{ + FILE *fp; /* client.conf file */ + char *encryption; /* CUPS_ENCRYPTION variable */ + const char *home; /* Home directory of user */ + static char line[1024]; /* Line from file */ + + + /* + * First see if we have already set the encryption stuff... + */ + + if (cups_encryption == (http_encryption_t)-1) + { + /* + * Then see if the CUPS_ENCRYPTION environment variable is set... + */ + + if ((encryption = getenv("CUPS_ENCRYPTION")) == NULL) + { + /* + * Next check to see if we have a $HOME/.cupsrc or client.conf file... + */ + + if ((home = getenv("HOME")) != NULL) + { + snprintf(line, sizeof(line), "%s/.cupsrc", home); + fp = fopen(line, "r"); + } + else + fp = NULL; + + if (fp == NULL) + { + if ((home = getenv("CUPS_SERVERROOT")) != NULL) + { + snprintf(line, sizeof(line), "%s/client.conf", home); + fp = fopen(line, "r"); + } + else + fp = fopen(CUPS_SERVERROOT "/client.conf", "r"); + } + + encryption = "IfRequested"; + + if (fp != NULL) + { + /* + * Read the config file and look for a ServerName line... + */ + + while (cups_get_line(line, sizeof(line), fp) != NULL) + if (strncmp(line, "Encryption ", 11) == 0 || + strncmp(line, "Encryption\t", 11) == 0) + { + /* + * Got it! Drop any trailing newline and find the name... + */ + + encryption = line + strlen(line) - 1; + if (*encryption == '\n') + *encryption = '\0'; + + for (encryption = line + 11; isspace(*encryption); encryption ++); + break; + } + + fclose(fp); + } + } + + /* + * Set the encryption preference... + */ + + if (strcasecmp(encryption, "never") == 0) + cups_encryption = HTTP_ENCRYPT_NEVER; + else if (strcasecmp(encryption, "always") == 0) + cups_encryption = HTTP_ENCRYPT_ALWAYS; + else if (strcasecmp(encryption, "required") == 0) + cups_encryption = HTTP_ENCRYPT_REQUIRED; + else + cups_encryption = HTTP_ENCRYPT_IF_REQUESTED; + } + + return (cups_encryption); +} + + +/* + * 'cupsGetPassword()' - Get a password from the user... + */ + +const char * /* O - Password */ +cupsGetPassword(const char *prompt) /* I - Prompt string */ +{ + return ((*cups_pwdcb)(prompt)); +} + + +/* + * 'cupsSetEncryption()' - Set the encryption preference. + */ + +void +cupsSetEncryption(http_encryption_t e) /* I - New encryption preference */ +{ + cups_encryption = e; +} + + +/* + * 'cupsServer()' - Return the hostname of the default server... + */ + +const char * /* O - Server name */ +cupsServer(void) +{ + FILE *fp; /* client.conf file */ + char *server; /* Pointer to server name */ + const char *home; /* Home directory of user */ + static char line[1024]; /* Line from file */ + + + /* + * First see if we have already set the server name... + */ + + if (!cups_server[0]) + { + /* + * Then see if the CUPS_SERVER environment variable is set... + */ + + if ((server = getenv("CUPS_SERVER")) == NULL) + { + /* + * Next check to see if we have a $HOME/.cupsrc or client.conf file... + */ + + if ((home = getenv("HOME")) != NULL) + { + snprintf(line, sizeof(line), "%s/.cupsrc", home); + fp = fopen(line, "r"); + } + else + fp = NULL; + + if (fp == NULL) + { + if ((home = getenv("CUPS_SERVERROOT")) != NULL) + { + snprintf(line, sizeof(line), "%s/client.conf", home); + fp = fopen(line, "r"); + } + else + fp = fopen(CUPS_SERVERROOT "/client.conf", "r"); + } + + server = "localhost"; + + if (fp != NULL) + { + /* + * Read the config file and look for a ServerName line... + */ + + while (cups_get_line(line, sizeof(line), fp) != NULL) + if (strncmp(line, "ServerName ", 11) == 0 || + strncmp(line, "ServerName\t", 11) == 0) + { + /* + * Got it! Drop any trailing newline and find the name... + */ + + server = line + strlen(line) - 1; + if (*server == '\n') + *server = '\0'; + + for (server = line + 11; isspace(*server); server ++); + break; + } + + fclose(fp); + } + } + + /* + * Copy the server name over... + */ + + strlcpy(cups_server, server, sizeof(cups_server)); + } + + return (cups_server); +} + + +/* + * 'cupsSetPasswordCB()' - Set the password callback for CUPS. + */ + +void +cupsSetPasswordCB(const char *(*cb)(const char *)) /* I - Callback function */ +{ + if (cb == (const char *(*)(const char *))0) + cups_pwdcb = cups_get_password; + else + cups_pwdcb = cb; +} + + +/* + * 'cupsSetServer()' - Set the default server name... + */ + +void +cupsSetServer(const char *server) /* I - Server name */ +{ + if (server) + strlcpy(cups_server, server, sizeof(cups_server)); + else + cups_server[0] = '\0'; +} + + +/* + * 'cupsSetUser()' - Set the default user name... + */ + +void +cupsSetUser(const char *user) /* I - User name */ +{ + if (user) + strlcpy(cups_user, user, sizeof(cups_user)); + else + cups_user[0] = '\0'; +} + + +#if defined(WIN32) +/* + * WIN32 username and password stuff... + */ + +/* + * 'cupsUser()' - Return the current user's name. + */ + +const char * /* O - User name */ +cupsUser(void) +{ + if (!cups_user[0]) + { + DWORD size; /* Size of string */ + + + size = sizeof(cups_user); + if (!GetUserName(cups_user, &size)) + { + /* + * Use the default username... + */ + + strcpy(cups_user, "unknown"); + } + } + + return (cups_user); +} + + +/* + * 'cups_get_password()' - Get a password from the user... + */ + +static const char * /* O - Password */ +cups_get_password(const char *prompt) /* I - Prompt string */ +{ + return (NULL); +} +#else +/* + * UNIX username and password stuff... + */ + +# include + +/* + * 'cupsUser()' - Return the current user's name. + */ + +const char * /* O - User name */ +cupsUser(void) +{ + struct passwd *pwd; /* User/password entry */ + + + if (!cups_user[0]) + { + /* + * Rewind the password file... + */ + + setpwent(); + + /* + * Lookup the password entry for the current user. + */ + + if ((pwd = getpwuid(getuid())) == NULL) + strcpy(cups_user, "unknown"); /* Unknown user! */ + else + { + /* + * Copy the username... + */ + + setpwent(); + + strlcpy(cups_user, pwd->pw_name, sizeof(cups_user)); + } + + /* + * Rewind the password file again... + */ + + setpwent(); + } + + return (cups_user); +} + + +/* + * 'cups_get_password()' - Get a password from the user... + */ + +static const char * /* O - Password */ +cups_get_password(const char *prompt) /* I - Prompt string */ +{ + return (getpass(prompt)); +} +#endif /* WIN32 */ + + +/* + * 'cups_get_line()' - Get a line from a file. + */ + +static char * /* O - Line from file */ +cups_get_line(char *buf, /* I - Line buffer */ + int buflen, /* I - Size of line buffer */ + FILE *fp) /* I - File to read from */ +{ + char *bufptr; /* Pointer to end of buffer */ + + + /* + * Get the line from a file... + */ + + if (fgets(buf, buflen, fp) == NULL) + return (NULL); + + /* + * Remove all trailing whitespace... + */ + + bufptr = buf + strlen(buf) - 1; + if (bufptr < buf) + return (NULL); + + while (isspace(*bufptr) && bufptr >= buf) + *bufptr-- = '\0'; + + return (buf); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/util.c b/cups/util.c new file mode 100644 index 0000000000..0b11c35063 --- /dev/null +++ b/cups/util.c @@ -0,0 +1,1771 @@ +/* + * "$Id$" + * + * Printing utilities for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-2002 by Easy Software Products. + * + * 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 + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * cupsCancelJob() - Cancel a print job. + * cupsDoFileRequest() - Do an IPP request... + * cupsFreeJobs() - Free memory used by job data. + * cupsGetClasses() - Get a list of printer classes. + * cupsGetDefault() - Get the default printer or class. + * cupsGetJobs() - Get the jobs from the server. + * cupsGetPPD() - Get the PPD file for a printer. + * cupsGetPrinters() - Get a list of printers. + * cupsLastError() - Return the last IPP error that occurred. + * cupsPrintFile() - Print a file to a printer or class. + * cupsPrintFiles() - Print one or more files to a printer or class. + * cups_connect() - Connect to the specified host... + * cups_local_auth() - Get the local authorization certificate if + * available/applicable... + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "ipp.h" +#include "language.h" +#include "string.h" +#include "debug.h" +#include +#include +#include +#include +#include +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * Local globals... + */ + +static http_t *cups_server = NULL; /* Current server connection */ +static ipp_status_t last_error = IPP_OK; /* Last IPP error */ +static char authstring[HTTP_MAX_VALUE] = ""; + /* Authorization string */ +static char pwdstring[33] = ""; /* Last password string */ + + +/* + * Local functions... + */ + +static char *cups_connect(const char *name, char *printer, char *hostname); +static int cups_local_auth(http_t *http); + + +/* + * 'cupsCancelJob()' - Cancel a print job. + */ + +int /* O - 1 on success, 0 on failure */ +cupsCancelJob(const char *name, /* I - Name of printer or class */ + int job) /* I - Job ID */ +{ + char printer[HTTP_MAX_URI], /* Printer name */ + hostname[HTTP_MAX_URI], /* Hostname */ + uri[HTTP_MAX_URI]; /* Printer URI */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + cups_lang_t *language; /* Language info */ + + + /* + * See if we can connect to the server... + */ + + if (!cups_connect(name, printer, hostname)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (0); + } + + /* + * Build an IPP_CANCEL_JOB request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * job-id + * [requesting-user-name] + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_CANCEL_JOB; + 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 != NULL ? language->language : "C"); + + snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", hostname, ippPort(), printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, cupsUser()); + + /* + * Do the request... + */ + + if ((response = cupsDoRequest(cups_server, request, "/jobs/")) == NULL) + { + last_error = IPP_BAD_REQUEST; + return (0); + } + else + { + last_error = response->request.status.status_code; + ippDelete(response); + + return (1); + } +} + + +/* + * 'cupsDoFileRequest()' - Do an IPP request... + */ + +ipp_t * /* O - Response data */ +cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */ + ipp_t *request, /* I - IPP request */ + const char *resource, /* I - HTTP resource for POST */ + const char *filename) /* I - File to send or NULL */ +{ + ipp_t *response; /* IPP response data */ + char length[255]; /* Content-Length field */ + http_status_t status; /* Status of HTTP request */ + FILE *file; /* File to send */ + struct stat fileinfo; /* File information */ + int bytes; /* Number of bytes read/written */ + 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 */ + plain[255], /* Plaintext username:password */ + encode[512]; /* Encoded username:password */ + char prompt[1024]; /* Prompt string */ + int digest_tries; /* Number of tries with Digest */ + + + if (http == NULL || request == NULL || resource == NULL) + { + if (request != NULL) + ippDelete(request); + + last_error = IPP_INTERNAL_ERROR; + return (NULL); + } + + DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n", + http, request, resource, filename ? filename : "(null)")); + + /* + * See if we have a file to send... + */ + + if (filename != NULL) + { + if (stat(filename, &fileinfo)) + { + /* + * Can't get file information! + */ + + ippDelete(request); + last_error = IPP_NOT_FOUND; + return (NULL); + } + +#ifdef WIN32 + if (fileinfo.st_mode & _S_IFDIR) +#else + if (S_ISDIR(fileinfo.st_mode)) +#endif /* WIN32 */ + { + /* + * Can't send a directory... + */ + + ippDelete(request); + last_error = IPP_NOT_POSSIBLE; + return (NULL); + } + + if ((file = fopen(filename, "rb")) == NULL) + { + /* + * Can't open file! + */ + + ippDelete(request); + last_error = IPP_NOT_FOUND; + return (NULL); + } + } + else + file = NULL; + + /* + * Loop until we can send the request without authorization problems. + */ + + response = NULL; + status = HTTP_ERROR; + digest_tries = 0; + + while (response == NULL) + { + DEBUG_puts("cupsDoFileRequest: setup..."); + + /* + * Setup the HTTP variables needed... + */ + + if (filename != NULL) + sprintf(length, "%lu", (unsigned long)(ippLength(request) + + (size_t)fileinfo.st_size)); + else + sprintf(length, "%lu", (unsigned long)ippLength(request)); + + httpClearFields(http); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length); + httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); + httpSetField(http, HTTP_FIELD_AUTHORIZATION, authstring); + + DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", authstring)); + + /* + * Try the request... + */ + + DEBUG_puts("cupsDoFileRequest: post..."); + + if (httpPost(http, resource)) + { + if (httpReconnect(http)) + { + status = HTTP_ERROR; + break; + } + else + continue; + } + + /* + * Send the IPP data and wait for the response... + */ + + DEBUG_puts("cupsDoFileRequest: ipp write..."); + + request->state = IPP_IDLE; + if (ippWrite(http, request) != IPP_ERROR) + if (filename != NULL) + { + DEBUG_puts("cupsDoFileRequest: file write..."); + + /* + * Send the file... + */ + + rewind(file); + + while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0) + if (httpWrite(http, buffer, bytes) < bytes) + break; + } + + /* + * Get the server's return status... + */ + + DEBUG_puts("cupsDoFileRequest: update..."); + + while ((status = httpUpdate(http)) == HTTP_CONTINUE); + + DEBUG_printf(("cupsDoFileRequest: status = %d\n", status)); + + if (status == HTTP_UNAUTHORIZED) + { + DEBUG_puts("cupsDoFileRequest: unauthorized..."); + + /* + * Flush any error message... + */ + + httpFlush(http); + httpReconnect(http); + + /* + * See if we can do local authentication... + */ + + if (cups_local_auth(http)) + continue; + + /* + * See if we should retry the current digest password... + */ + + if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0 || + digest_tries > 1 || !pwdstring[0]) + { + /* + * Nope - get a password from the user... + */ + + snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(), + http->hostname); + + if ((password = cupsGetPassword(prompt)) == NULL) + break; + if (!password[0]) + break; + + strlcpy(pwdstring, password, sizeof(pwdstring)); + + digest_tries = 0; + } + else + digest_tries ++; + + /* + * Got a password; encode it for the server... + */ + + if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0) + { + /* + * Basic authentication... + */ + + snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), pwdstring); + httpEncode64(encode, plain); + snprintf(authstring, sizeof(authstring), "Basic %s", encode); + } + else + { + /* + * Digest authentication... + */ + + httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm); + httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce); + + httpMD5(cupsUser(), realm, pwdstring, encode); + httpMD5Final(nonce, "POST", resource, encode); + snprintf(authstring, sizeof(authstring), + "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " + "response=\"%s\"", cupsUser(), realm, nonce, encode); + } + + continue; + } + else if (status == HTTP_ERROR) + { +#ifdef WIN32 + if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH) +#else + if (http->error != ENETDOWN && http->error != ENETUNREACH) +#endif /* WIN32 */ + continue; + else + break; + } +#ifdef HAVE_LIBSSL + else if (status == HTTP_UPGRADE_REQUIRED) + { + /* + * Flush any error message... + */ + + httpFlush(http); + + /* + * Upgrade with encryption... + */ + + httpEncryption(http, HTTP_ENCRYPT_REQUIRED); + + /* + * Try again, this time with encryption enabled... + */ + + continue; + } +#endif /* HAVE_LIBSSL */ + else if (status != HTTP_OK) + { + DEBUG_printf(("cupsDoFileRequest: error %d...\n", status)); + + /* + * Flush any error message... + */ + + httpFlush(http); + break; + } + else + { + /* + * Read the response... + */ + + DEBUG_puts("cupsDoFileRequest: response..."); + + response = ippNew(); + + if (ippRead(http, response) == IPP_ERROR) + { + /* + * Delete the response... + */ + + ippDelete(response); + response = NULL; + + last_error = IPP_SERVICE_UNAVAILABLE; + break; + } + } + } + + /* + * Close the file if needed... + */ + + if (filename != NULL) + fclose(file); + + /* + * Flush any remaining data... + */ + + httpFlush(http); + + /* + * Delete the original request and return the response... + */ + + ippDelete(request); + + if (response) + last_error = response->request.status.status_code; + else if (status == HTTP_NOT_FOUND) + last_error = IPP_NOT_FOUND; + else if (status == HTTP_UNAUTHORIZED) + last_error = IPP_NOT_AUTHORIZED; + else if (status != HTTP_OK) + last_error = IPP_SERVICE_UNAVAILABLE; + + return (response); +} + + +/* + * 'cupsFreeJobs()' - Free memory used by job data. + */ + +void +cupsFreeJobs(int num_jobs,/* I - Number of jobs */ + cups_job_t *jobs) /* I - Jobs */ +{ + int i; /* Looping var */ + + + if (num_jobs <= 0 || jobs == NULL) + return; + + for (i = 0; i < num_jobs; i ++) + { + free(jobs[i].dest); + free(jobs[i].user); + free(jobs[i].format); + free(jobs[i].title); + } + + free(jobs); +} + + +/* + * 'cupsGetClasses()' - Get a list of printer classes. + */ + +int /* O - Number of classes */ +cupsGetClasses(char ***classes) /* O - Classes */ +{ + int n; /* Number of classes */ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + char **temp; /* Temporary pointer */ + + + if (classes == NULL) + { + last_error = IPP_INTERNAL_ERROR; + return (0); + } + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (0); + } + + /* + * Build a CUPS_GET_CLASSES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * requested-attributes + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_CLASSES; + 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_KEYWORD, + "requested-attributes", NULL, "printer-name"); + + /* + * Do the request and get back a response... + */ + + n = 0; + *classes = NULL; + + if ((response = cupsDoRequest(cups_server, request, "/")) != NULL) + { + last_error = response->request.status.status_code; + + for (attr = response->attrs; attr != NULL; attr = attr->next) + if (attr->name != NULL && + strcasecmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + { + if (n == 0) + temp = malloc(sizeof(char *)); + else + temp = realloc(*classes, sizeof(char *) * (n + 1)); + + if (temp == NULL) + { + /* + * Ran out of memory! + */ + + while (n > 0) + { + n --; + free((*classes)[n]); + } + + free(*classes); + ippDelete(response); + return (0); + } + + *classes = temp; + temp[n] = strdup(attr->values[0].string.text); + n ++; + } + + ippDelete(response); + } + else + last_error = IPP_BAD_REQUEST; + + return (n); +} + + +/* + * 'cupsGetDefault()' - Get the default printer or class. + */ + +const char * /* O - Default printer or NULL */ +cupsGetDefault(void) +{ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + const char *var; /* Environment variable */ + static char def_printer[256];/* Default printer */ + + + /* + * First see if the LPDEST or PRINTER environment variables are + * set... However, if PRINTER is set to "lp", ignore it to work + * around a "feature" in most Linux distributions - the default + * user login scripts set PRINTER to "lp"... + */ + + if ((var = getenv("LPDEST")) != NULL) + return (var); + else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0) + return (var); + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (NULL); + } + + /* + * Build a CUPS_GET_DEFAULT request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_DEFAULT; + 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); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(cups_server, request, "/")) != NULL) + { + last_error = response->request.status.status_code; + + if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) + { + strlcpy(def_printer, attr->values[0].string.text, sizeof(def_printer)); + ippDelete(response); + return (def_printer); + } + + ippDelete(response); + } + else + last_error = IPP_BAD_REQUEST; + + return (NULL); +} + + +/* + * 'cupsGetJobs()' - Get the jobs from the server. + */ + +int /* O - Number of jobs */ +cupsGetJobs(cups_job_t **jobs, /* O - Job data */ + const char *mydest, /* I - Only show jobs for dest? */ + int myjobs, /* I - Only show my jobs? */ + int completed) /* I - Only show completed jobs? */ +{ + int n; /* Number of jobs */ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + cups_job_t *temp; /* Temporary pointer */ + int id, /* job-id */ + priority, /* job-priority */ + size; /* job-k-octets */ + ipp_jstate_t state; /* job-state */ + time_t completed_time, /* time-at-completed */ + creation_time, /* time-at-creation */ + processing_time; /* time-at-processing */ + const char *dest, /* job-printer-uri */ + *format, /* document-format */ + *title, /* job-name */ + *user; /* job-originating-user-name */ + char uri[HTTP_MAX_URI]; /* URI for jobs */ + static const char *attrs[] = /* Requested attributes */ + { + "job-id", + "job-priority", + "job-k-octets", + "job-state", + "time-at-completed", + "time-at-creation", + "time-at-processing", + "job-printer-uri", + "document-format", + "job-name", + "job-originating-user-name" + }; + + + if (jobs == NULL) + { + last_error = IPP_INTERNAL_ERROR; + return (0); + } + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (0); + } + + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * requesting-user-name + * which-jobs + * my-jobs + * requested-attributes + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_JOBS; + 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); + + if (mydest) + snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", mydest); + else + strcpy(uri, "ipp://localhost/jobs"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requesting-user-name", NULL, cupsUser()); + + if (myjobs) + ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); + + if (completed) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "which-jobs", NULL, "completed"); + + 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... + */ + + n = 0; + *jobs = NULL; + + if ((response = cupsDoRequest(cups_server, request, "/")) != NULL) + { + last_error = response->request.status.status_code; + + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + /* + * Skip leading attributes until we hit a job... + */ + + while (attr != NULL && attr->group_tag != IPP_TAG_JOB) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Pull the needed attributes from this job... + */ + + id = 0; + size = 0; + priority = 50; + state = IPP_JOB_PENDING; + user = "unknown"; + dest = NULL; + format = "application/octet-stream"; + title = "untitled"; + creation_time = 0; + completed_time = 0; + processing_time = 0; + + while (attr != NULL && attr->group_tag == IPP_TAG_JOB) + { + if (strcmp(attr->name, "job-id") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + id = attr->values[0].integer; + else if (strcmp(attr->name, "job-state") == 0 && + attr->value_tag == IPP_TAG_ENUM) + state = (ipp_jstate_t)attr->values[0].integer; + else if (strcmp(attr->name, "job-priority") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + priority = attr->values[0].integer; + else if (strcmp(attr->name, "job-k-octets") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + size = attr->values[0].integer; + else if (strcmp(attr->name, "time-at-completed") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + completed_time = attr->values[0].integer; + else if (strcmp(attr->name, "time-at-creation") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + creation_time = attr->values[0].integer; + else if (strcmp(attr->name, "time-at-processing") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + processing_time = attr->values[0].integer; + else if (strcmp(attr->name, "job-printer-uri") == 0 && + attr->value_tag == IPP_TAG_URI) + { + if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL) + dest ++; + } + else if (strcmp(attr->name, "job-originating-user-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + user = attr->values[0].string.text; + else if (strcmp(attr->name, "document-format") == 0 && + attr->value_tag == IPP_TAG_MIMETYPE) + format = attr->values[0].string.text; + else if (strcmp(attr->name, "job-name") == 0 && + (attr->value_tag == IPP_TAG_TEXT || + attr->value_tag == IPP_TAG_NAME)) + title = attr->values[0].string.text; + + attr = attr->next; + } + + /* + * See if we have everything needed... + */ + + if (dest == NULL || id == 0) + { + if (attr == NULL) + break; + else + continue; + } + + /* + * Allocate memory for the job... + */ + + if (n == 0) + temp = malloc(sizeof(cups_job_t)); + else + temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1)); + + if (temp == NULL) + { + /* + * Ran out of memory! + */ + + cupsFreeJobs(n, *jobs); + *jobs = NULL; + + ippDelete(response); + return (0); + } + + *jobs = temp; + temp += n; + n ++; + + /* + * Copy the data over... + */ + + temp->dest = strdup(dest); + temp->user = strdup(user); + temp->format = strdup(format); + temp->title = strdup(title); + temp->id = id; + temp->priority = priority; + temp->state = state; + temp->size = size; + temp->completed_time = completed_time; + temp->creation_time = creation_time; + temp->processing_time = processing_time; + + if (attr == NULL) + break; + } + + ippDelete(response); + } + else + last_error = IPP_BAD_REQUEST; + + return (n); +} + + +/* + * 'cupsGetPPD()' - Get the PPD file for a printer. + */ + +const char * /* O - Filename for PPD file */ +cupsGetPPD(const char *name) /* I - Printer name */ +{ + int i; /* Looping var */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Local language */ + int fd; /* PPD file */ + int bytes; /* Number of bytes read */ + char buffer[8192]; /* Buffer for file */ + char printer[HTTP_MAX_URI], /* Printer name */ + method[HTTP_MAX_URI], /* Method/scheme name */ + username[HTTP_MAX_URI], /* Username:password */ + hostname[HTTP_MAX_URI], /* Hostname */ + resource[HTTP_MAX_URI]; /* Resource name */ + int port; /* Port number */ + const char *password; /* Password string */ + char realm[HTTP_MAX_VALUE], /* realm="xyz" string */ + nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */ + plain[255], /* Plaintext username:password */ + encode[512]; /* Encoded username:password */ + http_status_t status; /* HTTP status from server */ + char prompt[1024]; /* Prompt string */ + int digest_tries; /* Number of tries with Digest */ + static char filename[HTTP_MAX_URI]; /* Local filename */ + static const char *requested_attrs[] =/* Requested attributes */ + { + "printer-uri-supported", + "printer-type", + "member-uris" + }; + + + if (name == NULL) + { + last_error = IPP_INTERNAL_ERROR; + return (NULL); + } + + /* + * See if we can connect to the server... + */ + + if (!cups_connect(name, printer, hostname)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (NULL); + } + + /* + * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * requested-attributes + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + 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); + + snprintf(buffer, sizeof(buffer), "ipp://localhost/printers/%s", printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, buffer); + + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requested-attributes", + sizeof(requested_attrs) / sizeof(requested_attrs[0]), + NULL, requested_attrs); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(cups_server, request, "/")) != NULL) + { + last_error = response->request.status.status_code; + printer[0] = '\0'; + hostname[0] = '\0'; + + if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) + { + /* + * Get the first actual server and printer name in the class... + */ + + for (i = 0; i < attr->num_values; i ++) + { + httpSeparate(attr->values[0].string.text, method, username, hostname, + &port, resource); + if (strncmp(resource, "/printers/", 10) == 0) + { + /* + * Found a printer! + */ + + strlcpy(printer, resource + 10, sizeof(printer)); + break; + } + } + } + else if ((attr = ippFindAttribute(response, "printer-uri-supported", + IPP_TAG_URI)) != NULL) + { + /* + * Get the actual server and printer names... + */ + + httpSeparate(attr->values[0].string.text, method, username, hostname, + &port, resource); + strlcpy(printer, strrchr(resource, '/') + 1, sizeof(printer)); + } + + ippDelete(response); + + /* + * Remap local hostname to localhost... + */ + + gethostname(buffer, sizeof(buffer)); + + if (strcasecmp(buffer, hostname) == 0) + strcpy(hostname, "localhost"); + } + + cupsLangFree(language); + + if (!printer[0]) + return (NULL); + + /* + * Reconnect to the correct server as needed... + */ + + if (strcasecmp(cups_server->hostname, hostname) != 0) + { + httpClose(cups_server); + + if ((cups_server = httpConnectEncrypt(hostname, ippPort(), + cupsEncryption())) == NULL) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (NULL); + } + } + + /* + * Get a temp file... + */ + + if ((fd = cupsTempFd(filename, sizeof(filename))) < 0) + { + /* + * Can't open file; close the server connection and return NULL... + */ + + httpFlush(cups_server); + httpClose(cups_server); + cups_server = NULL; + return (NULL); + } + + /* + * And send a request to the HTTP server... + */ + + snprintf(resource, sizeof(resource), "/printers/%s.ppd", printer); + + digest_tries = 0; + + do + { + httpClearFields(cups_server); + httpSetField(cups_server, HTTP_FIELD_HOST, hostname); + httpSetField(cups_server, HTTP_FIELD_AUTHORIZATION, authstring); + + if (httpGet(cups_server, resource)) + { + if (httpReconnect(cups_server)) + { + status = HTTP_ERROR; + break; + } + else + { + status = HTTP_UNAUTHORIZED; + continue; + } + } + + while ((status = httpUpdate(cups_server)) == HTTP_CONTINUE); + + if (status == HTTP_UNAUTHORIZED) + { + DEBUG_puts("cupsGetPPD: unauthorized..."); + + /* + * Flush any error message... + */ + + httpFlush(cups_server); + + /* + * See if we can do local authentication... + */ + + if (cups_local_auth(cups_server)) + continue; + + /* + * See if we should retry the current digest password... + */ + + if (strncmp(cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0 || + digest_tries > 1 || !pwdstring[0]) + { + /* + * Nope - get a password from the user... + */ + + snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(), + cups_server->hostname); + + if ((password = cupsGetPassword(prompt)) == NULL) + break; + if (!password[0]) + break; + + strlcpy(pwdstring, password, sizeof(pwdstring)); + + digest_tries = 0; + } + else + digest_tries ++; + + /* + * Got a password; encode it for the server... + */ + + if (strncmp(cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0) + { + /* + * Basic authentication... + */ + + snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), pwdstring); + httpEncode64(encode, plain); + snprintf(authstring, sizeof(authstring), "Basic %s", encode); + } + else + { + /* + * Digest authentication... + */ + + httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm); + httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce); + + httpMD5(cupsUser(), realm, pwdstring, encode); + httpMD5Final(nonce, "GET", resource, encode); + snprintf(authstring, sizeof(authstring), + "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " + "response=\"%s\"", cupsUser(), realm, nonce, encode); + } + + continue; + } +#ifdef HAVE_LIBSSL + else if (status == HTTP_UPGRADE_REQUIRED) + { + /* + * Flush any error message... + */ + + httpFlush(cups_server); + + /* + * Upgrade with encryption... + */ + + httpEncryption(cups_server, HTTP_ENCRYPT_REQUIRED); + + /* + * Try again, this time with encryption enabled... + */ + + continue; + } +#endif /* HAVE_LIBSSL */ + } + while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED); + + /* + * See if we actually got the file or an error... + */ + + if (status != HTTP_OK) + { + unlink(filename); + httpFlush(cups_server); + httpClose(cups_server); + cups_server = NULL; + return (NULL); + } + + /* + * OK, we need to copy the file... + */ + + while ((bytes = httpRead(cups_server, buffer, sizeof(buffer))) > 0) + write(fd, buffer, bytes); + + close(fd); + + return (filename); +} + + +/* + * 'cupsGetPrinters()' - Get a list of printers. + */ + +int /* O - Number of printers */ +cupsGetPrinters(char ***printers) /* O - Printers */ +{ + int n; /* Number of printers */ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + char **temp; /* Temporary pointer */ + + + if (printers == NULL) + { + last_error = IPP_INTERNAL_ERROR; + return (0); + } + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (0); + } + + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * requested-attributes + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + 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_KEYWORD, + "requested-attributes", NULL, "printer-name"); + + /* + * Do the request and get back a response... + */ + + n = 0; + *printers = NULL; + + if ((response = cupsDoRequest(cups_server, request, "/")) != NULL) + { + last_error = response->request.status.status_code; + + for (attr = response->attrs; attr != NULL; attr = attr->next) + if (attr->name != NULL && + strcasecmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + { + if (n == 0) + temp = malloc(sizeof(char *)); + else + temp = realloc(*printers, sizeof(char *) * (n + 1)); + + if (temp == NULL) + { + /* + * Ran out of memory! + */ + + while (n > 0) + { + n --; + free((*printers)[n]); + } + + free(*printers); + ippDelete(response); + return (0); + } + + *printers = temp; + temp[n] = strdup(attr->values[0].string.text); + n ++; + } + + ippDelete(response); + } + else + last_error = IPP_BAD_REQUEST; + + return (n); +} + + +/* + * 'cupsLastError()' - Return the last IPP error that occurred. + */ + +ipp_status_t /* O - IPP error code */ +cupsLastError(void) +{ + return (last_error); +} + + +/* + * 'cupsPrintFile()' - Print a file to a printer or class. + */ + +int /* O - Job ID */ +cupsPrintFile(const char *name, /* I - Printer or class name */ + const char *filename, /* I - File to print */ + const char *title, /* I - Title of job */ + int num_options,/* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + DEBUG_printf(("cupsPrintFile(\'%s\', \'%s\', %d, %p)\n", + name, filename, num_options, options)); + + return (cupsPrintFiles(name, 1, &filename, title, num_options, options)); +} + + +/* + * 'cupsPrintFiles()' - Print one or more files to a printer or class. + */ + +int /* O - Job ID */ +cupsPrintFiles(const char *name, /* I - Printer or class name */ + int num_files, /* I - Number of files */ + const char **files, /* I - File(s) to print */ + const char *title, /* I - Title of job */ + int num_options,/* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i; /* Looping var */ + const char *val; /* Pointer to option value */ + ipp_t *request; /* IPP request */ + ipp_t *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP job-id attribute */ + char hostname[HTTP_MAX_URI], /* Hostname */ + printer[HTTP_MAX_URI], /* Printer or class name */ + uri[HTTP_MAX_URI]; /* Printer URI */ + cups_lang_t *language; /* Language to use */ + int jobid; /* New job ID */ + + + DEBUG_printf(("cupsPrintFiles(\'%s\', %d, %p, %d, %p)\n", + name, num_files, files, num_options, options)); + + if (name == NULL || num_files < 1 || files == NULL) + return (0); + + /* + * Setup a connection and request data... + */ + + if (!cups_connect(name, printer, hostname)) + { + DEBUG_printf(("cupsPrintFile: Unable to open connection - %s.\n", + strerror(errno))); + last_error = IPP_SERVICE_UNAVAILABLE; + return (0); + } + + language = cupsLangDefault(); + + /* + * Build a standard CUPS URI for the printer and fill the standard IPP + * attributes... + */ + + if ((request = ippNew()) == NULL) + return (0); + + request->request.op.operation_id = num_files == 1 ? IPP_PRINT_JOB : + IPP_CREATE_JOB; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", hostname, ippPort(), printer); + + 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 != NULL ? language->language : "C"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, cupsUser()); + + if (title) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); + + /* + * Then add all options... + */ + + cupsEncodeOptions(request, num_options, options); + + /* + * Do the request... + */ + + snprintf(uri, sizeof(uri), "/printers/%s", printer); + + if (num_files == 1) + response = cupsDoFileRequest(cups_server, request, uri, *files); + else + response = cupsDoRequest(cups_server, request, uri); + + if (response == NULL) + jobid = 0; + else if (response->request.status.status_code > IPP_OK_CONFLICT) + { + DEBUG_printf(("IPP response code was 0x%x!\n", + response->request.status.status_code)); + jobid = 0; + } + else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) + { + DEBUG_puts("No job ID!"); + jobid = 0; + } + else + jobid = attr->values[0].integer; + + if (response != NULL) + ippDelete(response); + + /* + * Handle multiple file jobs if the create-job operation worked... + */ + + if (jobid > 0 && num_files > 1) + for (i = 0; i < num_files; i ++) + { + /* + * Build a standard CUPS URI for the job and fill the standard IPP + * attributes... + */ + + if ((request = ippNew()) == NULL) + return (0); + + request->request.op.operation_id = IPP_SEND_DOCUMENT; + request->request.op.request_id = 1; + + snprintf(uri, sizeof(uri), "ipp://%s:%d/jobs/%d", hostname, ippPort(), + jobid); + + 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 != NULL ? language->language : "C"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", + NULL, uri); + + /* + * Handle raw print files... + */ + + if (cupsGetOption("raw", num_options, options)) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/vnd.cups-raw"); + else if ((val = cupsGetOption("document-format", num_options, options)) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, val); + else + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/octet-stream"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, cupsUser()); + + /* + * Is this the last document? + */ + + if (i == (num_files - 1)) + ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1); + + /* + * Send the file... + */ + + snprintf(uri, sizeof(uri), "/printers/%s", printer); + + if ((response = cupsDoFileRequest(cups_server, request, uri, + files[i])) != NULL) + ippDelete(response); + } + + return (jobid); +} + + +/* + * 'cups_connect()' - Connect to the specified host... + */ + +static char * /* I - Printer name or NULL */ +cups_connect(const char *name, /* I - Destination (printer[@host]) */ + char *printer, /* O - Printer name [HTTP_MAX_URI] */ + char *hostname) /* O - Hostname [HTTP_MAX_URI] */ +{ + char hostbuf[HTTP_MAX_URI]; /* Name of host */ + + + DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname)); + + if (name == NULL) + { + last_error = IPP_BAD_REQUEST; + return (NULL); + } + + /* + * All jobs are now queued to cupsServer() to avoid hostname + * resolution problems and to ensure that the user sees all + * locally queued jobs locally. + */ + + strlcpy(hostbuf, cupsServer(), sizeof(hostbuf)); + + if (hostname != NULL) + strlcpy(hostname, hostbuf, HTTP_MAX_URI); + else + hostname = hostbuf; + + if (printer != NULL) + strlcpy(printer, name, HTTP_MAX_URI); + else + printer = (char *)name; + + if (cups_server != NULL) + { + if (strcasecmp(cups_server->hostname, hostname) == 0) + return (printer); + + httpClose(cups_server); + } + + DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort())); + + if ((cups_server = httpConnectEncrypt(hostname, ippPort(), + cupsEncryption())) == NULL) + { + last_error = IPP_SERVICE_UNAVAILABLE; + return (NULL); + } + else + return (printer); +} + + +/* + * 'cups_local_auth()' - Get the local authorization certificate if + * available/applicable... + */ + +static int /* O - 1 if available, 0 if not */ +cups_local_auth(http_t *http) /* I - Connection */ +{ +#if defined(WIN32) || defined(__EMX__) + /* + * Currently WIN32 and OS-2 do not support the CUPS server... + */ + + return (0); +#else + int pid; /* Current process ID */ + FILE *fp; /* Certificate file */ + char filename[1024], /* Certificate filename */ + certificate[33];/* Certificate string */ + const char *root; /* Server root directory */ + + + DEBUG_printf(("cups_local_auth(http=%p) hostaddr=%08x, hostname=\"%s\"\n", + http, ntohl(http->hostaddr.sin_addr.s_addr), http->hostname)); + + /* + * See if we are accessing localhost... + */ + + if (ntohl(http->hostaddr.sin_addr.s_addr) != 0x7f000001 && + strcasecmp(http->hostname, "localhost") != 0) + { + DEBUG_puts("cups_local_auth: Not a local connection!"); + return (0); + } + + /* + * Try opening a certificate file for this PID. If that fails, + * try the root certificate... + */ + + if ((root = getenv("CUPS_SERVERROOT")) == NULL) + root = CUPS_SERVERROOT; + + pid = getpid(); + snprintf(filename, sizeof(filename), "%s/certs/%d", root, pid); + if ((fp = fopen(filename, "r")) == NULL && pid > 0) + { + DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n", + filename, strerror(errno))); + + snprintf(filename, sizeof(filename), "%s/certs/0", root); + fp = fopen(filename, "r"); + } + + if (fp == NULL) + { + DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n", + filename, strerror(errno))); + return (0); + } + + /* + * Read the certificate from the file... + */ + + fgets(certificate, sizeof(certificate), fp); + fclose(fp); + + /* + * Set the authorization string and return... + */ + + snprintf(authstring, sizeof(authstring), "Local %s", certificate); + + DEBUG_printf(("cups_local_auth: Returning authstring = \"%s\"\n", + authstring)); + + return (1); +#endif /* WIN32 || __EMX__ */ +} + + +/* + * End of "$Id$". + */ diff --git a/data/HPGLprolog b/data/HPGLprolog new file mode 100644 index 0000000000..8304582438 --- /dev/null +++ b/data/HPGLprolog @@ -0,0 +1,37 @@ +%%BeginResource: procset hpgltops 1.1 0 +% +% "$Id: HPGLprolog 2010 2002-01-02 17:59:21Z mike $" +% +% HP-GL/2 filter procset for the Common UNIX Printing System (CUPS). +% +% This procset contains the basic drawing commands that are used to +% reduce output size. Note the 'MP' (make newpath) definition - this +% should be called 'NP' (newpath), but GhostScript uses the 'NP' name +% for 'noaccess put' in some of its font files... +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/MO { moveto } bind def +/LI { lineto } bind def +/FI { fill } bind def +/ST { stroke } bind def +/CP { closepath } bind def +/MP { newpath } bind def +/SP { setlinewidth setrgbcolor } bind def +%%EndResource diff --git a/data/Makefile b/data/Makefile new file mode 100644 index 0000000000..e4499e6846 --- /dev/null +++ b/data/Makefile @@ -0,0 +1,104 @@ +# +# "$Id$" +# +# Datafile makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-2002 by Easy Software Products. +# +# 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 +# + +include ../Makedefs + +# +# Data files... +# + +BANNERS = classified \ + confidential \ + secret \ + standard \ + topsecret \ + unclassified + +CHARSETS = windows-874 \ + windows-1250 \ + windows-1251 \ + windows-1252 \ + windows-1253 \ + windows-1254 \ + windows-1255 \ + windows-1256 \ + windows-1257 \ + windows-1258 \ + koi8-r \ + koi8-u \ + iso-8859-1 \ + iso-8859-2 \ + iso-8859-3 \ + iso-8859-4 \ + iso-8859-5 \ + iso-8859-6 \ + iso-8859-7 \ + iso-8859-8 \ + iso-8859-9 \ + iso-8859-10 \ + iso-8859-13 \ + iso-8859-14 \ + iso-8859-15 \ + koi8-r \ + koi8-u \ + utf-8 +DATAFILES = HPGLprolog psglyphs testprint.ps + + +# +# Make everything... +# + +all: + + +# +# Clean all config and object files... +# + +clean: + + +# +# Install files... +# + +install: + $(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 + + +# +# End of "$Id$". +# diff --git a/data/classified b/data/classified new file mode 100644 index 0000000000..df921456fc --- /dev/null +++ b/data/classified @@ -0,0 +1,277 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Classified) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Classified) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({?job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: classified 2122 2002-01-31 14:19:37Z mike $". +% +%%EOF diff --git a/data/confidential b/data/confidential new file mode 100644 index 0000000000..48744d6eff --- /dev/null +++ b/data/confidential @@ -0,0 +1,277 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Confidential) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Confidential) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({?job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: confidential 2122 2002-01-31 14:19:37Z mike $". +% +%%EOF diff --git a/data/iso-8859-1 b/data/iso-8859-1 new file mode 100644 index 0000000000..90fd312098 --- /dev/null +++ b/data/iso-8859-1 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-1 +# (Latin1/West European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00BA +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 00D0 +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 00DE +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 00F0 +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 00FE +FF 00FF diff --git a/data/iso-8859-10 b/data/iso-8859-10 new file mode 100644 index 0000000000..8aca211d9f --- /dev/null +++ b/data/iso-8859-10 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-10 +# (Latin6/Nordic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0104 +A2 0112 +A3 0122 +A4 012A +A5 0128 +A6 0136 +A7 00A7 +A8 013B +A9 0110 +AA 0160 +AB 0166 +AC 017D +AD 00AD +AE 016A +AF 014A +B0 00B0 +B1 0105 +B2 0113 +B3 0123 +B4 012B +B5 0129 +B6 0137 +B7 00B7 +B8 013C +B9 0111 +BA 0161 +BB 0167 +BC 017E +BD 2015 +BE 016B +BF 014B +C0 0100 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 012E +C8 010C +C9 00C9 +CA 0118 +CB 00CB +CC 0116 +CD 00CD +CE 00CE +CF 00CF +D0 0110 +D1 0145 +D2 014C +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 0168 +D8 00D8 +D9 0172 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 00DE +DF 00DF +E0 0101 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 012F +E8 010D +E9 00E9 +EA 0119 +EB 00EB +EC 0117 +ED 00ED +EE 00EE +EF 00EF +F0 00F0 +F1 0146 +F2 014D +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 0169 +F8 00F8 +F9 0173 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 00FD +FF 0138 diff --git a/data/iso-8859-13 b/data/iso-8859-13 new file mode 100644 index 0000000000..1736fc57d1 --- /dev/null +++ b/data/iso-8859-13 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-13 +# (Latin7/Baltic Rim) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 201D +A2 00A2 +A3 00A3 +A4 00A4 +A5 201E +A6 00A6 +A7 00A7 +A8 00D8 +A9 00A9 +AA 0156 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00C6 +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 201C +B5 00B5 +B6 00B6 +B7 00B7 +B8 00F8 +B9 00B9 +BA 0157 +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00E6 +C0 0104 +C1 012E +C2 0100 +C3 0106 +C4 00C4 +C5 00C5 +C6 0118 +C7 0112 +C8 010C +C9 00C9 +CA 0179 +CB 0116 +CC 0122 +CD 0136 +CE 012A +CF 013B +D0 0160 +D1 0143 +D2 0145 +D3 00D3 +D4 014C +D5 00D5 +D6 00D6 +D7 00D7 +D8 0172 +D9 0141 +DA 015A +DB 016A +DC 00DC +DD 017B +DE 017D +DF 00DF +E0 0105 +E1 012F +E2 0101 +E3 0107 +E4 00E4 +E5 00E5 +E6 0119 +E7 0113 +E8 010D +E9 00E9 +EA 017A +EB 0117 +EC 0123 +ED 0137 +EE 012B +EF 013C +F0 0161 +F1 0144 +F2 0146 +F3 00F3 +F4 014D +F5 00F5 +F6 00F6 +F7 00F7 +F8 0173 +F9 0142 +FA 015B +FB 016B +FC 00FC +FD 017C +FE 017E +FF 2019 diff --git a/data/iso-8859-14 b/data/iso-8859-14 new file mode 100644 index 0000000000..460f1c2e07 --- /dev/null +++ b/data/iso-8859-14 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-14 +# (Latin8/Celtic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 1E02 +A2 1E03 +A3 00A3 +A4 010A +A5 010B +A6 1E0A +A7 00A7 +A8 1E80 +A9 00A9 +AA 1E82 +AB 1E0B +AC 1EF2 +AD 00AD +AE 00AE +AF 0178 +B0 1E1E +B1 1E1F +B2 0120 +B3 0121 +B4 1E40 +B5 1E41 +B6 00B6 +B7 1E56 +B8 1E81 +B9 1E57 +BA 1E83 +BB 1E60 +BC 1EF3 +BD 1E84 +BE 1E85 +BF 1E61 +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 0174 +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 1E6A +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 0176 +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 0175 +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 1E6B +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 0177 +FF 00FF diff --git a/data/iso-8859-15 b/data/iso-8859-15 new file mode 100644 index 0000000000..b7ce82bde0 --- /dev/null +++ b/data/iso-8859-15 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-15 +# (Latin9/West Europe + Euro) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 20AC +A5 00A5 +A6 0160 +A7 00A7 +A8 0161 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 017D +B5 00B5 +B6 00B6 +B7 00B7 +B8 017E +B9 00B9 +BA 00BA +BB 00BB +BC 0152 +BD 0153 +BE 0178 +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 00D0 +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 00DE +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 00F0 +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 00FE +FF 00FF diff --git a/data/iso-8859-2 b/data/iso-8859-2 new file mode 100644 index 0000000000..b5f3c852c9 --- /dev/null +++ b/data/iso-8859-2 @@ -0,0 +1,253 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-2 +# (Latin2/East European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +84 201E +85 2026 +86 2020 +87 2021 +89 2030 +8A 0160 +8B 2039 +8C 015A +8D 0164 +8E 017D +8F 0179 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9A 0161 +9B 203A +8C 015B +8D 0165 +8E 017E +8F 017A +A0 00A0 +A1 0104 +A2 02D8 +A3 0141 +A4 00A4 +A5 013D +A6 015A +A7 00A7 +A8 00A8 +A9 0160 +AA 015E +AB 0164 +AC 0179 +AD 00AD +AE 017D +AF 017B +B0 00B0 +B1 0105 +B2 02DB +B3 0142 +B4 00B4 +B5 013E +B6 015B +B7 02C7 +B8 00B8 +B9 0161 +BA 015F +BB 0165 +BC 017A +BD 02DD +BE 017E +BF 017C +C0 0154 +C1 00C1 +C2 00C2 +C3 0102 +C4 00C4 +C5 0139 +C6 0106 +C7 00C7 +C8 010C +C9 00C9 +CA 0118 +CB 00CB +CC 011A +CD 00CD +CE 00CE +CF 010E +D0 0110 +D1 0143 +D2 0147 +D3 00D3 +D4 00D4 +D5 0150 +D6 00D6 +D7 00D7 +D8 0158 +D9 016E +DA 00DA +DB 0170 +DC 00DC +DD 00DD +DE 0162 +DF 00DF +E0 0155 +E1 00E1 +E2 00E2 +E3 0103 +E4 00E4 +E5 013A +E6 0107 +E7 00E7 +E8 010D +E9 00E9 +EA 0119 +EB 00EB +EC 011B +ED 00ED +EE 00EE +EF 010F +F0 0111 +F1 0144 +F2 0148 +F3 00F3 +F4 00F4 +F5 0151 +F6 00F6 +F7 00F7 +F8 0159 +F9 016F +FA 00FA +FB 0171 +FC 00FC +FD 00FD +FE 0163 +FF 02D9 diff --git a/data/iso-8859-3 b/data/iso-8859-3 new file mode 100644 index 0000000000..fe3675ae12 --- /dev/null +++ b/data/iso-8859-3 @@ -0,0 +1,244 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-3 +# (Latin3/South European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0126 +A2 02D8 +A3 00A3 +A4 00A4 +A6 0124 +A7 00A7 +A8 00A8 +A9 0130 +AA 015E +AB 011E +AC 0134 +AD 00AD +AF 017B +B0 00B0 +B1 0127 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 0125 +B7 00B7 +B8 00B8 +B9 0131 +BA 015F +BB 011F +BC 0135 +BD 00BD +BF 017C +C0 00C0 +C1 00C1 +C2 00C2 +C4 00C4 +C5 010A +C6 0108 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 0120 +D6 00D6 +D7 00D7 +D8 011C +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 016C +DE 015C +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E4 00E4 +E5 010B +E6 0109 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 0121 +F6 00F6 +F7 00F7 +F8 011D +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 016D +FE 015D +FF 02D9 diff --git a/data/iso-8859-4 b/data/iso-8859-4 new file mode 100644 index 0000000000..3295cb56a1 --- /dev/null +++ b/data/iso-8859-4 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-4 +# (Latin4/North European) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0104 +A2 0138 +A3 0156 +A4 00A4 +A5 0128 +A6 013B +A7 00A7 +A8 00A8 +A9 0160 +AA 0112 +AB 0122 +AC 0166 +AD 00AD +AE 017D +AF 00AF +B0 00B0 +B1 0105 +B2 02DB +B3 0157 +B4 00B4 +B5 0129 +B6 013C +B7 02C7 +B8 00B8 +B9 0161 +BA 0113 +BB 0123 +BC 0167 +BD 014A +BE 017E +BF 014B +C0 0100 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 012E +C8 010C +C9 00C9 +CA 0118 +CB 00CB +CC 0116 +CD 00CD +CE 00CE +CF 012A +D0 0110 +D1 0145 +D2 014C +D3 0136 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 0172 +DA 00DA +DB 00DB +DC 00DC +DD 0168 +DE 016A +DF 00DF +E0 0101 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 012F +E8 010D +E9 00E9 +EA 0119 +EB 00EB +EC 0117 +ED 00ED +EE 00EE +EF 012B +F0 0111 +F1 0146 +F2 014D +F3 0137 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 0173 +FA 00FA +FB 00FB +FC 00FC +FD 0169 +FE 016B +FF 02D9 diff --git a/data/iso-8859-5 b/data/iso-8859-5 new file mode 100644 index 0000000000..64bd0ea60c --- /dev/null +++ b/data/iso-8859-5 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-5 +# (Cyrillic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 0401 +A2 0402 +A3 0403 +A4 0404 +A5 0405 +A6 0406 +A7 0407 +A8 0408 +A9 0409 +AA 040A +AB 040B +AC 040C +AD 00AD +AE 040E +AF 040F +B0 0410 +B1 0411 +B2 0412 +B3 0413 +B4 0414 +B5 0415 +B6 0416 +B7 0417 +B8 0418 +B9 0419 +BA 041A +BB 041B +BC 041C +BD 041D +BE 041E +BF 041F +C0 0420 +C1 0421 +C2 0422 +C3 0423 +C4 0424 +C5 0425 +C6 0426 +C7 0427 +C8 0428 +C9 0429 +CA 042A +CB 042B +CC 042C +CD 042D +CE 042E +CF 042F +D0 0430 +D1 0431 +D2 0432 +D3 0433 +D4 0434 +D5 0435 +D6 0436 +D7 0437 +D8 0438 +D9 0439 +DA 043A +DB 043B +DC 043C +DD 043D +DE 043E +DF 043F +E0 0440 +E1 0441 +E2 0442 +E3 0443 +E4 0444 +E5 0445 +E6 0446 +E7 0447 +E8 0448 +E9 0449 +EA 044A +EB 044B +EC 044C +ED 044D +EE 044E +EF 044F +F0 2116 +F1 0451 +F2 0452 +F3 0453 +F4 0454 +F5 0455 +F6 0456 +F7 0457 +F8 0458 +F9 0459 +FA 045A +FB 045B +FC 045C +FD 00A7 +FE 045E +FF 045F diff --git a/data/iso-8859-6 b/data/iso-8859-6 new file mode 100644 index 0000000000..18bdeff4f3 --- /dev/null +++ b/data/iso-8859-6 @@ -0,0 +1,206 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-6 +# (Arabic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff rtol single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0660 +31 0661 +32 0662 +33 0663 +34 0664 +35 0665 +36 0666 +37 0667 +38 0668 +39 0669 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A4 00A4 +AC 060C +AD 00AD +BB 061B +BF 061F +C1 0621 +C2 0622 +C3 0623 +C4 0624 +C5 0625 +C6 0626 +C7 0627 +C8 0628 +C9 0629 +CA 062A +CB 062B +CC 062C +CD 062D +CE 062E +CF 062F +D0 0630 +D1 0631 +D2 0632 +D3 0633 +D4 0634 +D5 0635 +D6 0636 +D7 0637 +D8 0638 +D9 0639 +DA 063A +E0 0640 +E1 0641 +E2 0642 +E3 0643 +E4 0644 +E5 0645 +E6 0646 +E7 0647 +E8 0648 +E9 0649 +EA 064A +EB 064B +EC 064C +ED 064D +EE 064E +EF 064F +F0 0650 +F1 0651 +F2 0652 diff --git a/data/iso-8859-7 b/data/iso-8859-7 new file mode 100644 index 0000000000..812828e8ae --- /dev/null +++ b/data/iso-8859-7 @@ -0,0 +1,246 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-7 +# (Greek) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 9f ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +a0 ff ltor single Symbol + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 02BD +A2 02BC +A3 00A3 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AB 00AB +AC 00AC +AD 00AD +AF 2015 +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 0384 +B5 0385 +B6 0386 +B7 00B7 +B8 0388 +B9 0389 +BA 038A +BB 00BB +BC 038C +BD 00BD +BE 038E +BF 038F +C0 0390 +C1 0391 +C2 0392 +C3 0393 +C4 0394 +C5 0395 +C6 0396 +C7 0397 +C8 0398 +C9 0399 +CA 039A +CB 039B +CC 039C +CD 039D +CE 039E +CF 039F +D0 03A0 +D1 03A1 +D3 03A3 +D4 03A4 +D5 03A5 +D6 03A6 +D7 03A7 +D8 03A8 +D9 03A9 +DA 03AA +DB 03AB +DC 03AC +DD 03AD +DE 03AE +DF 03AF +E0 03B0 +E1 03B1 +E2 03B2 +E3 03B3 +E4 03B4 +E5 03B5 +E6 03B6 +E7 03B7 +E8 03B8 +E9 03B9 +EA 03BA +EB 03BB +EC 03BC +ED 03BD +EE 03BE +EF 03BF +F0 03C0 +F1 03C1 +F2 03C2 +F3 03C3 +F4 03C4 +F5 03C5 +F6 03C6 +F7 03C7 +F8 03C8 +F9 03C9 +FA 03CA +FB 03CB +FC 03CC +FD 03CD +FE 03CE diff --git a/data/iso-8859-8 b/data/iso-8859-8 new file mode 100644 index 0000000000..cfbd4483b5 --- /dev/null +++ b/data/iso-8859-8 @@ -0,0 +1,214 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-8 +# (Hebrew) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 7f ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +80 ff rtol single Courier + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00D7 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 203E +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00F7 +BB 00BB +BC 00BC +BD 00BD +BE 00BE +DF 2017 +E0 05D0 +E1 05D1 +E2 05D2 +E3 05D3 +E4 05D4 +E5 05D5 +E6 05D6 +E7 05D7 +E8 05D8 +E9 05D9 +EA 05DA +EB 05DB +EC 05DC +ED 05DD +EE 05DE +EF 05DF +F0 05E0 +F1 05E1 +F2 05E2 +F3 05E3 +F4 05E4 +F5 05E5 +F6 05E6 +F7 05E7 +F8 05E8 +F9 05E9 +FA 05EA diff --git a/data/iso-8859-9 b/data/iso-8859-9 new file mode 100644 index 0000000000..7406122dd9 --- /dev/null +++ b/data/iso-8859-9 @@ -0,0 +1,251 @@ +charset 8bit + +# +# This file defines the font and character mappings used for ISO-8859-9 +# (Latin5/Turkish) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00BA +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 011E +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 0130 +DE 015E +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 011F +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 0131 +FE 015F +FF 00FF diff --git a/data/koi8-r b/data/koi8-r new file mode 100644 index 0000000000..c1fed66ccc --- /dev/null +++ b/data/koi8-r @@ -0,0 +1,261 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Russian +# Code Page KOI8-R text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 2500 +81 2502 +82 250C +83 2510 +84 2514 +85 2518 +86 251C +87 2524 +88 252C +89 2534 +8A 253C +8B 2580 +8C 2584 +8D 2588 +8E 258C +8F 2590 +90 2591 +91 2592 +92 2593 +93 2320 +94 25A0 +95 2219 +96 221A +97 2248 +98 2264 +99 2265 +9A 00A0 +9B 2321 +9C 00B0 +9D 00B2 +9E 00B7 +9F 00F7 +A0 2550 +A1 2551 +A2 2552 +A3 0451 +A4 2553 +A5 2554 +A6 2555 +A7 2556 +A8 2557 +A9 2558 +AA 2559 +AB 255A +AC 255B +AD 255C +AE 255D +AF 255E +B0 255F +B1 2560 +B2 2561 +B3 0401 +B4 2562 +B5 2563 +B6 2564 +B7 2565 +B8 2566 +B9 2567 +BA 2568 +BB 2569 +BC 256A +BD 256B +BE 256C +BF 00A9 +C0 044E +C1 0430 +C2 0431 +C3 0446 +C4 0434 +C5 0435 +C6 0444 +C7 0433 +C8 0445 +C9 0438 +CA 0439 +CB 043A +CC 043B +CD 043C +CE 043D +CF 043E +D0 043F +D1 044F +D2 0440 +D3 0441 +D4 0442 +D5 0443 +D6 0436 +D7 0432 +D8 044C +D9 044B +DA 0437 +DB 0448 +DC 044D +DD 0449 +DE 0447 +DF 044A +E0 042E +E1 0410 +E2 0411 +E3 0426 +E4 0414 +E5 0415 +E6 0424 +E7 0413 +E8 0425 +E9 0418 +EA 0419 +EB 041A +EC 041B +ED 041C +EE 041D +EF 041E +F0 041F +F1 042F +F2 0420 +F3 0421 +F4 0422 +F5 0423 +F6 0416 +F7 0412 +F8 042C +F9 042B +FA 0417 +FB 0428 +FC 042D +FD 0429 +FE 0427 +FF 042A + + diff --git a/data/koi8-u b/data/koi8-u new file mode 100644 index 0000000000..35c48645d1 --- /dev/null +++ b/data/koi8-u @@ -0,0 +1,259 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Ukrainian +# Code Page KOI8-U text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 2500 +81 2502 +82 250C +83 2510 +84 2514 +85 2518 +86 251C +87 2524 +88 252C +89 2534 +8A 253C +8B 2580 +8C 2584 +8D 2588 +8E 258C +8F 2590 +90 2591 +91 2592 +92 2593 +93 2320 +94 25A0 +95 2219 +96 221A +97 2248 +98 2264 +99 2265 +9A 00A0 +9B 2321 +9C 00B0 +9D 00B2 +9E 00B7 +9F 00F7 +A0 2550 +A1 2551 +A2 2552 +A3 0451 +A4 0454 +A5 2554 +A6 0456 +A7 0457 +A8 2557 +A9 2558 +AA 2559 +AB 255A +AC 255B +AD 0491 +AE 255D +AF 255E +B0 255F +B1 2560 +B2 2561 +B3 0401 +B4 0404 +B5 2563 +B6 0406 +B7 0407 +B8 2566 +B9 2567 +BA 2568 +BB 2569 +BC 256A +BD 0490 +BE 256C +BF 00A9 +C0 044E +C1 0430 +C2 0431 +C3 0446 +C4 0434 +C5 0435 +C6 0444 +C7 0433 +C8 0445 +C9 0438 +CA 0439 +CB 043A +CC 043B +CD 043C +CE 043D +CF 043E +D0 043F +D1 044F +D2 0440 +D3 0441 +D4 0442 +D5 0443 +D6 0436 +D7 0432 +D8 044C +D9 044B +DA 0437 +DB 0448 +DC 044D +DD 0449 +DE 0447 +DF 044A +E0 042E +E1 0410 +E2 0411 +E3 0426 +E4 0414 +E5 0415 +E6 0424 +E7 0413 +E8 0425 +E9 0418 +EA 0419 +EB 041A +EC 041B +ED 041C +EE 041D +EF 041E +F0 041F +F1 042F +F2 0420 +F3 0421 +F4 0422 +F5 0423 +F6 0416 +F7 0412 +F8 042C +F9 042B +FA 0417 +FB 0428 +FC 042D +FD 0429 +FE 0427 +FF 042A diff --git a/data/psglyphs b/data/psglyphs new file mode 100644 index 0000000000..392e782c0d --- /dev/null +++ b/data/psglyphs @@ -0,0 +1,1051 @@ +0020 space +0021 exclam +0022 quotedbl +0023 numbersign +0024 dollar +0025 percent +0026 ampersand +0027 quotesingle +0028 parenleft +0029 parenright +002a asterisk +002b plus +002c comma +002d hyphen +002e period +002f slash +0030 zero +0031 one +0032 two +0033 three +0034 four +0035 five +0036 six +0037 seven +0038 eight +0039 nine +003a colon +003b semicolon +003c less +003d equal +003e greater +003f question +0040 at +0041 A +0042 B +0043 C +0044 D +0045 E +0046 F +0047 G +0048 H +0049 I +004a J +004b K +004c L +004d M +004e N +004f O +0050 P +0051 Q +0052 R +0053 S +0054 T +0055 U +0056 V +0057 W +0058 X +0059 Y +005a Z +005b bracketleft +005c backslash +005d bracketright +005e asciicircum +005f underscore +0060 grave +0061 a +0062 b +0063 c +0064 d +0065 e +0066 f +0067 g +0068 h +0069 i +006a j +006b k +006c l +006d m +006e n +006f o +0070 p +0071 q +0072 r +0073 s +0074 t +0075 u +0076 v +0077 w +0078 x +0079 y +007a z +007b braceleft +007c bar +007d braceright +007e asciitilde +00a0 space +00a1 exclamdown +00a2 cent +00a3 sterling +00a4 currency +00a5 yen +00a6 brokenbar +00a7 section +00a8 dieresis +00a9 copyright +00aa ordfeminine +00ab guillemotleft +00ac logicalnot +00ad minus +00ae registered +00af macron +00b0 degree +00b1 plusminus +00b2 twosuperior +00b3 threesuperior +00b4 acute +00b5 mu +00b6 paragraph +00b7 periodcentered +00b8 cedilla +00b9 onesuperior +00ba ordmasculine +00bb guillemotright +00bc onequarter +00bd onehalf +00be threequarters +00bf questiondown +00c0 Agrave +00c1 Aacute +00c2 Acircumflex +00c3 Atilde +00c4 Adieresis +00c5 Aring +00c6 AE +00c7 Ccedilla +00c8 Egrave +00c9 Eacute +00ca Ecircumflex +00cb Edieresis +00cc Igrave +00cd Iacute +00ce Icircumflex +00cf Idieresis +00d0 Eth +00d1 Ntilde +00d2 Ograve +00d3 Oacute +00d4 Ocircumflex +00d5 Otilde +00d6 Odieresis +00d7 multiply +00d8 Oslash +00d9 Ugrave +00da Uacute +00db Ucircumflex +00dc Udieresis +00dd Yacute +00de Thorn +00df germandbls +00e0 agrave +00e1 aacute +00e2 acircumflex +00e3 atilde +00e4 adieresis +00e5 aring +00e6 ae +00e7 ccedilla +00e8 egrave +00e9 eacute +00ea ecircumflex +00eb edieresis +00ec igrave +00ed iacute +00ee icircumflex +00ef idieresis +00f0 eth +00f1 ntilde +00f2 ograve +00f3 oacute +00f4 ocircumflex +00f5 otilde +00f6 odieresis +00f7 divide +00f8 oslash +00f9 ugrave +00fa uacute +00fb ucircumflex +00fc udieresis +00fd yacute +00fe thorn +00ff ydieresis +0100 Amacron +0101 amacron +0102 Abreve +0103 abreve +0104 Aogonek +0105 aogonek +0106 Cacute +0107 cacute +0108 Ccircumflex +0109 ccircumflex +010a Cdotaccent +010b cdotaccent +010c Ccaron +010d ccaron +010e Dcaron +010f dcaron +0110 Dcroat +0111 dcroat +0112 Emacron +0113 emacron +0114 Ebreve +0115 ebreve +0116 Edotaccent +0117 edotaccent +0118 Eogonek +0119 eogonek +011a Ecaron +011b ecaron +011c Gcircumflex +011d gcircumflex +011e Gbreve +011f gbreve +0120 Gdotaccent +0121 gdotaccent +0122 Gcommaaccent +0123 gcommaaccent +0124 Hcircumflex +0125 hcircumflex +0126 Hbar +0127 hbar +0128 Itilde +0129 itilde +012a Imacron +012b imacron +012c Ibreve +012d ibreve +012e Iogonek +012f iogonek +0130 Idotaccent +0131 dotlessi +0132 IJ +0133 ij +0134 Jcircumflex +0135 jcircumflex +0136 Kcommaaccent +0137 kcommaaccent +0138 kgreenlandic +0139 Lacute +013a lacute +013b Lcommaaccent +013c lcommaaccent +013d Lcaron +013e lcaron +013f Ldot +0140 ldot +0141 Lslash +0142 lslash +0143 Nacute +0144 nacute +0145 Ncommaaccent +0146 ncommaaccent +0147 Ncaron +0148 ncaron +0149 napostrophe +014a Eng +014b eng +014c Omacron +014d omacron +014e Obreve +014f obreve +0150 Ohungarumlaut +0151 ohungarumlaut +0152 OE +0153 oe +0154 Racute +0155 racute +0156 Rcommaaccent +0157 rcommaaccent +0158 Rcaron +0159 rcaron +015a Sacute +015b sacute +015c Scircumflex +015d scircumflex +015e Scedilla +015f scedilla +0160 Scaron +0161 scaron +0162 Tcommaaccent +0163 tcommaaccent +0164 Tcaron +0165 tcaron +0166 Tbar +0167 tbar +0168 Utilde +0169 utilde +016a Umacron +016b umacron +016c Ubreve +016d ubreve +016e Uring +016f uring +0170 Uhungarumlaut +0171 uhungarumlaut +0172 Uogonek +0173 uogonek +0174 Wcircumflex +0175 wcircumflex +0176 Ycircumflex +0177 ycircumflex +0178 Ydieresis +0179 Zacute +017a zacute +017b Zdotaccent +017c zdotaccent +017d Zcaron +017e zcaron +017f longs +0192 florin +01a0 Ohorn +01a1 ohorn +01af Uhorn +01b0 uhorn +01e6 Gcaron +01e7 gcaron +01fa Aringacute +01fb aringacute +01fc AEacute +01fd aeacute +01fe Oslashacute +01ff oslashacute +0218 Scommaaccent +0219 scommaaccent +021a Tcommaaccent +021b tcommaaccent +02bc afii57929 +02bd afii64937 +02c6 circumflex +02c7 caron +02c9 macron +02d8 breve +02d9 dotaccent +02da ring +02db ogonek +02dc tilde +02dd hungarumlaut +0300 gravecomb +0301 acutecomb +0303 tildecomb +0309 hookabovecomb +0323 dotbelowcomb +0384 tonos +0385 dieresistonos +0386 Alphatonos +0387 anoteleia +0388 Epsilontonos +0389 Etatonos +038a Iotatonos +038c Omicrontonos +038e Upsilontonos +038f Omegatonos +0390 iotadieresistonos +0391 Alpha +0392 Beta +0393 Gamma +0394 Delta +0395 Epsilon +0396 Zeta +0397 Eta +0398 Theta +0399 Iota +039a Kappa +039b Lambda +039c Mu +039d Nu +039e Xi +039f Omicron +03a0 Pi +03a1 Rho +03a3 Sigma +03a4 Tau +03a5 Upsilon +03a6 Phi +03a7 Chi +03a8 Psi +03a9 Omega +03aa Iotadieresis +03ab Upsilondieresis +03ac alphatonos +03ad epsilontonos +03ae etatonos +03af iotatonos +03b0 upsilondieresistonos +03b1 alpha +03b2 beta +03b3 gamma +03b4 delta +03b5 epsilon +03b6 zeta +03b7 eta +03b8 theta +03b9 iota +03ba kappa +03bb lambda +03bc mu +03bd nu +03be xi +03bf omicron +03c0 pi +03c1 rho +03c2 sigma1 +03c3 sigma +03c4 tau +03c5 upsilon +03c6 phi +03c7 chi +03c8 psi +03c9 omega +03ca iotadieresis +03cb upsilondieresis +03cc omicrontonos +03cd upsilontonos +03ce omegatonos +03d1 theta1 +03d2 Upsilon1 +03d5 phi1 +03d6 omega1 +0401 afii10023 +0402 afii10051 +0403 afii10052 +0404 afii10053 +0405 afii10054 +0406 afii10055 +0407 afii10056 +0408 afii10057 +0409 afii10058 +040a afii10059 +040b afii10060 +040c afii10061 +040e afii10062 +040f afii10145 +0410 afii10017 +0411 afii10018 +0412 afii10019 +0413 afii10020 +0414 afii10021 +0415 afii10022 +0416 afii10024 +0417 afii10025 +0418 afii10026 +0419 afii10027 +041a afii10028 +041b afii10029 +041c afii10030 +041d afii10031 +041e afii10032 +041f afii10033 +0420 afii10034 +0421 afii10035 +0422 afii10036 +0423 afii10037 +0424 afii10038 +0425 afii10039 +0426 afii10040 +0427 afii10041 +0428 afii10042 +0429 afii10043 +042a afii10044 +042b afii10045 +042c afii10046 +042d afii10047 +042e afii10048 +042f afii10049 +0430 afii10065 +0431 afii10066 +0432 afii10067 +0433 afii10068 +0434 afii10069 +0435 afii10070 +0436 afii10072 +0437 afii10073 +0438 afii10074 +0439 afii10075 +043a afii10076 +043b afii10077 +043c afii10078 +043d afii10079 +043e afii10080 +043f afii10081 +0440 afii10082 +0441 afii10083 +0442 afii10084 +0443 afii10085 +0444 afii10086 +0445 afii10087 +0446 afii10088 +0447 afii10089 +0448 afii10090 +0449 afii10091 +044a afii10092 +044b afii10093 +044c afii10094 +044d afii10095 +044e afii10096 +044f afii10097 +0451 afii10071 +0452 afii10099 +0453 afii10100 +0454 afii10101 +0455 afii10102 +0456 afii10103 +0457 afii10104 +0458 afii10105 +0459 afii10106 +045a afii10107 +045b afii10108 +045c afii10109 +045e afii10110 +045f afii10193 +0462 afii10146 +0463 afii10194 +0472 afii10147 +0473 afii10195 +0474 afii10148 +0475 afii10196 +0490 afii10050 +0491 afii10098 +04d9 afii10846 +05b0 afii57799 +05b1 afii57801 +05b2 afii57800 +05b3 afii57802 +05b4 afii57793 +05b5 afii57794 +05b6 afii57795 +05b7 afii57798 +05b8 afii57797 +05b9 afii57806 +05bb afii57796 +05bc afii57807 +05bd afii57839 +05be afii57645 +05bf afii57841 +05c0 afii57842 +05c1 afii57804 +05c2 afii57803 +05c3 afii57658 +05d0 afii57664 +05d1 afii57665 +05d2 afii57666 +05d3 afii57667 +05d4 afii57668 +05d5 afii57669 +05d6 afii57670 +05d7 afii57671 +05d8 afii57672 +05d9 afii57673 +05da afii57674 +05db afii57675 +05dc afii57676 +05dd afii57677 +05de afii57678 +05df afii57679 +05e0 afii57680 +05e1 afii57681 +05e2 afii57682 +05e3 afii57683 +05e4 afii57684 +05e5 afii57685 +05e6 afii57686 +05e7 afii57687 +05e8 afii57688 +05e9 afii57689 +05ea afii57690 +05f0 afii57716 +05f1 afii57717 +05f2 afii57718 +060c afii57388 +061b afii57403 +061f afii57407 +0621 afii57409 +0622 afii57410 +0623 afii57411 +0624 afii57412 +0625 afii57413 +0626 afii57414 +0627 afii57415 +0628 afii57416 +0629 afii57417 +062a afii57418 +062b afii57419 +062c afii57420 +062d afii57421 +062e afii57422 +062f afii57423 +0630 afii57424 +0631 afii57425 +0632 afii57426 +0633 afii57427 +0634 afii57428 +0635 afii57429 +0636 afii57430 +0637 afii57431 +0638 afii57432 +0639 afii57433 +063a afii57434 +0640 afii57440 +0641 afii57441 +0642 afii57442 +0643 afii57443 +0644 afii57444 +0645 afii57445 +0646 afii57446 +0647 afii57470 +0648 afii57448 +0649 afii57449 +064a afii57450 +064b afii57451 +064c afii57452 +064d afii57453 +064e afii57454 +064f afii57455 +0650 afii57456 +0651 afii57457 +0652 afii57458 +0660 afii57392 +0661 afii57393 +0662 afii57394 +0663 afii57395 +0664 afii57396 +0665 afii57397 +0666 afii57398 +0667 afii57399 +0668 afii57400 +0669 afii57401 +066a afii57381 +066d afii63167 +0679 afii57511 +067e afii57506 +0686 afii57507 +0688 afii57512 +0691 afii57513 +0698 afii57508 +06a4 afii57505 +06af afii57509 +06ba afii57514 +06d2 afii57519 +06d5 afii57534 +1e80 Wgrave +1e81 wgrave +1e82 Wacute +1e83 wacute +1e84 Wdieresis +1e85 wdieresis +1ef2 Ygrave +1ef3 ygrave +200c afii61664 +200d afii301 +200e afii299 +200f afii300 +2012 figuredash +2013 endash +2014 emdash +2015 afii00208 +2017 underscoredbl +2018 quoteleft +2019 quoteright +201a quotesinglbase +201b quotereversed +201c quotedblleft +201d quotedblright +201e quotedblbase +2020 dagger +2021 daggerdbl +2022 bullet +2024 onedotenleader +2025 twodotenleader +2026 ellipsis +202c afii61573 +202d afii61574 +202e afii61575 +2030 perthousand +2032 minute +2033 second +2039 guilsinglleft +203a guilsinglright +203c exclamdbl +2044 fraction +2070 zerosuperior +2074 foursuperior +2075 fivesuperior +2076 sixsuperior +2077 sevensuperior +2078 eightsuperior +2079 ninesuperior +207d parenleftsuperior +207e parenrightsuperior +207f nsuperior +2080 zeroinferior +2081 oneinferior +2082 twoinferior +2083 threeinferior +2084 fourinferior +2085 fiveinferior +2086 sixinferior +2087 seveninferior +2088 eightinferior +2089 nineinferior +208d parenleftinferior +208e parenrightinferior +20a1 colonmonetary +20a3 franc +20a4 lira +20a7 peseta +20aa afii57636 +20ab dong +20ac Euro +2105 afii61248 +2111 Ifraktur +2113 afii61289 +2116 afii61352 +2118 weierstrass +211c Rfraktur +211e prescription +2122 trademark +2126 Omega +212e estimated +2135 aleph +2153 onethird +2154 twothirds +215b oneeighth +215c threeeighths +215d fiveeighths +215e seveneighths +2190 arrowleft +2191 arrowup +2192 arrowright +2193 arrowdown +2194 arrowboth +2195 arrowupdn +21a8 arrowupdnbse +21b5 carriagereturn +21d0 arrowdblleft +21d1 arrowdblup +21d2 arrowdblright +21d3 arrowdbldown +21d4 arrowdblboth +2200 universal +2202 partialdiff +2203 existential +2205 emptyset +2206 Delta +2207 gradient +2208 element +2209 notelement +220b suchthat +220f product +2211 summation +2212 minus +2215 fraction +2217 asteriskmath +2219 periodcentered +221a radical +221d proportional +221e infinity +221f orthogonal +2220 angle +2227 logicaland +2228 logicalor +2229 intersection +222a union +222b integral +2234 therefore +223c similar +2245 congruent +2248 approxequal +2260 notequal +2261 equivalence +2264 lessequal +2265 greaterequal +2282 propersubset +2283 propersuperset +2284 notsubset +2286 reflexsubset +2287 reflexsuperset +2295 circleplus +2297 circlemultiply +22a5 perpendicular +22c5 dotmath +2302 house +2310 revlogicalnot +2320 integraltp +2321 integralbt +2329 angleleft +232a angleright +2500 SF100000 +2502 SF110000 +250c SF010000 +2510 SF030000 +2514 SF020000 +2518 SF040000 +251c SF080000 +2524 SF090000 +252c SF060000 +2534 SF070000 +253c SF050000 +2550 SF430000 +2551 SF240000 +2552 SF510000 +2553 SF520000 +2554 SF390000 +2555 SF220000 +2556 SF210000 +2557 SF250000 +2558 SF500000 +2559 SF490000 +255a SF380000 +255b SF280000 +255c SF270000 +255d SF260000 +255e SF360000 +255f SF370000 +2560 SF420000 +2561 SF190000 +2562 SF200000 +2563 SF230000 +2564 SF470000 +2565 SF480000 +2566 SF410000 +2567 SF450000 +2568 SF460000 +2569 SF400000 +256a SF540000 +256b SF530000 +256c SF440000 +2580 upblock +2584 dnblock +2588 block +258c lfblock +2590 rtblock +2591 ltshade +2592 shade +2593 dkshade +25a0 filledbox +25a1 H22073 +25aa H18543 +25ab H18551 +25ac filledrect +25b2 triagup +25ba triagrt +25bc triagdn +25c4 triaglf +25ca lozenge +25cb circle +25cf H18533 +25d8 invbullet +25d9 invcircle +25e6 openbullet +263a smileface +263b invsmileface +263c sun +2640 female +2642 male +2660 spade +2663 club +2665 heart +2666 diamond +266a musicalnote +266b musicalnotedbl +f6be dotlessj +f6bf LL +f6c0 ll +f6c1 Scedilla +f6c2 scedilla +f6c3 commaaccent +f6c4 afii10063 +f6c5 afii10064 +f6c6 afii10192 +f6c7 afii10831 +f6c8 afii10832 +f6c9 Acute +f6ca Caron +f6cb Dieresis +f6cc DieresisAcute +f6cd DieresisGrave +f6ce Grave +f6cf Hungarumlaut +f6d0 Macron +f6d1 cyrBreve +f6d2 cyrFlex +f6d3 dblGrave +f6d4 cyrbreve +f6d5 cyrflex +f6d6 dblgrave +f6d7 dieresisacute +f6d8 dieresisgrave +f6d9 copyrightserif +f6da registerserif +f6db trademarkserif +f6dc onefitted +f6dd rupiah +f6de threequartersemdash +f6df centinferior +f6e0 centsuperior +f6e1 commainferior +f6e2 commasuperior +f6e3 dollarinferior +f6e4 dollarsuperior +f6e5 hypheninferior +f6e6 hyphensuperior +f6e7 periodinferior +f6e8 periodsuperior +f6e9 asuperior +f6ea bsuperior +f6eb dsuperior +f6ec esuperior +f6ed isuperior +f6ee lsuperior +f6ef msuperior +f6f0 osuperior +f6f1 rsuperior +f6f2 ssuperior +f6f3 tsuperior +f6f4 Brevesmall +f6f5 Caronsmall +f6f6 Circumflexsmall +f6f7 Dotaccentsmall +f6f8 Hungarumlautsmall +f6f9 Lslashsmall +f6fa OEsmall +f6fb Ogoneksmall +f6fc Ringsmall +f6fd Scaronsmall +f6fe Tildesmall +f6ff Zcaronsmall +f721 exclamsmall +f724 dollaroldstyle +f726 ampersandsmall +f730 zerooldstyle +f731 oneoldstyle +f732 twooldstyle +f733 threeoldstyle +f734 fouroldstyle +f735 fiveoldstyle +f736 sixoldstyle +f737 sevenoldstyle +f738 eightoldstyle +f739 nineoldstyle +f73f questionsmall +f760 Gravesmall +f761 Asmall +f762 Bsmall +f763 Csmall +f764 Dsmall +f765 Esmall +f766 Fsmall +f767 Gsmall +f768 Hsmall +f769 Ismall +f76a Jsmall +f76b Ksmall +f76c Lsmall +f76d Msmall +f76e Nsmall +f76f Osmall +f770 Psmall +f771 Qsmall +f772 Rsmall +f773 Ssmall +f774 Tsmall +f775 Usmall +f776 Vsmall +f777 Wsmall +f778 Xsmall +f779 Ysmall +f77a Zsmall +f7a1 exclamdownsmall +f7a2 centoldstyle +f7a8 Dieresissmall +f7af Macronsmall +f7b4 Acutesmall +f7b8 Cedillasmall +f7bf questiondownsmall +f7e0 Agravesmall +f7e1 Aacutesmall +f7e2 Acircumflexsmall +f7e3 Atildesmall +f7e4 Adieresissmall +f7e5 Aringsmall +f7e6 AEsmall +f7e7 Ccedillasmall +f7e8 Egravesmall +f7e9 Eacutesmall +f7ea Ecircumflexsmall +f7eb Edieresissmall +f7ec Igravesmall +f7ed Iacutesmall +f7ee Icircumflexsmall +f7ef Idieresissmall +f7f0 Ethsmall +f7f1 Ntildesmall +f7f2 Ogravesmall +f7f3 Oacutesmall +f7f4 Ocircumflexsmall +f7f5 Otildesmall +f7f6 Odieresissmall +f7f8 Oslashsmall +f7f9 Ugravesmall +f7fa Uacutesmall +f7fb Ucircumflexsmall +f7fc Udieresissmall +f7fd Yacutesmall +f7fe Thornsmall +f7ff Ydieresissmall +f8e5 radicalex +f8e6 arrowvertex +f8e7 arrowhorizex +f8e8 registersans +f8e9 copyrightsans +f8ea trademarksans +f8eb parenlefttp +f8ec parenleftex +f8ed parenleftbt +f8ee bracketlefttp +f8ef bracketleftex +f8f0 bracketleftbt +f8f1 bracelefttp +f8f2 braceleftmid +f8f3 braceleftbt +f8f4 braceex +f8f5 integralex +f8f6 parenrighttp +f8f7 parenrightex +f8f8 parenrightbt +f8f9 bracketrighttp +f8fa bracketrightex +f8fb bracketrightbt +f8fc bracerighttp +f8fd bracerightmid +f8fe bracerightbt +fb00 ff +fb01 fi +fb02 fl +fb03 ffi +fb04 ffl +fb1f afii57705 +fb2a afii57694 +fb2b afii57695 +fb35 afii57723 +fb4b afii57700 diff --git a/data/secret b/data/secret new file mode 100644 index 0000000000..1f8751430e --- /dev/null +++ b/data/secret @@ -0,0 +1,277 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Secret) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Secret) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({?job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: secret 2122 2002-01-31 14:19:37Z mike $". +% +%%EOF diff --git a/data/standard b/data/standard new file mode 100644 index 0000000000..ca0edb0372 --- /dev/null +++ b/data/standard @@ -0,0 +1,261 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({?job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: standard 2122 2002-01-31 14:19:37Z mike $". +% +%%EOF diff --git a/data/testprint.ps b/data/testprint.ps new file mode 100644 index 0000000000..a70de15d45 --- /dev/null +++ b/data/testprint.ps @@ -0,0 +1,522 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset testprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 11, 1999 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset testprint 1.1 0 +% +% PostScript test page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/OCTANT { % Draw a color wheel OCTANT... + % (name) radius r g b OCTANT - + % Loop through 100 shades... + 0 0.010101 0.98 { + % Set the color... + 3 index 1 eq % R == 1? + 3 index 1 eq % G == 1? + 3 index 1 eq % B == 1? + and and { + 0 index 4 index mul % R * val + 1 index 4 index mul % G * val + 2 index 4 index mul % B * val + } { + 0 index 4 index mul % R * val + 1 index neg 1 add add % + (1 - val) + 1 index 4 index mul % G * val + 2 index neg 1 add add % + (1 - val) + 2 index 4 index mul % B * val + 3 index neg 1 add add % + (1 - val) + } ifelse + setrgbcolor + + % Draw a polygon... + dup 5 index mul dup 0 % x1, y1 + moveto + 0.707106781 mul dup lineto % x2, y2 + + 0.010101 add 4 index mul dup % x3 + 0.707106781 mul dup lineto % x3, y3 + 0 lineto % x4, y4 + closepath + fill + } for + + % Draw a line around the polygons... + pop pop pop dup + 0 setgray + 0 0 moveto + dup 0 lineto + 0.707106781 mul dup lineto + closepath + stroke + + % Draw the label... + 0 exch dup -9 div exch % text offset = 0, -radius/9 + dup 0.923879532 mul % x = radius * cos(22.5) + exch 0.382683432 mul % y = radius * cos(22.5) + moveto % position label + gsave + 22.5 rotate % rotate label + rmoveto % offset label + show % show label + grestore +} bind def +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + 4 setlinewidth % Draw wide lines + 0 setgray closepath stroke % Draw a clipping rectangle + 1 setlinewidth % Draw normal lines + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + 72 72 dtransform % Get device resolution per inch + /yResolution exch abs def % yResolution = abs(yres) + /xResolution exch abs def % xResolution = abs(xres) + + % Figure out the sizes of things... + /wheelSize % size of wheels + pageWidth pageHeight lt + { pageWidth 9 mul } + { pageHeight 7 mul } + ifelse def + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + /smallFont /Times-Roman findfont % smallFont = Times-Roman + pageHeight scalefont def % size = pageHeight (nominally 11) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the color wheel... + mediumFont setfont % Font + 0 setgray % Color + + gsave + % Position the wheel on the left side... + pageWidth 18 mul % x = pageWidth * 1/4 * 72 + pageHeight 54 mul % y = pageHeight * 3/4 * 72 + translate + + % Size the wheel... + wheelSize + + % Draw the colors... + dup (C) exch 0 1 1 OCTANT 45 rotate + dup (M) exch 1 0 1 OCTANT 45 rotate + dup (Y) exch 1 1 0 OCTANT 45 rotate + dup (K) exch 0 0 0 OCTANT 45 rotate + dup (R) exch 1 0 0 OCTANT 45 rotate + dup (G) exch 0 1 0 OCTANT 45 rotate + dup (B) exch 0 0 1 OCTANT 45 rotate + (W) exch 1 1 1 OCTANT 45 rotate + grestore + + % Label the color wheel... + pageWidth 18 mul % x = pageWidth * 1/4 * 72 + pageHeight 44 mul % y = pageHeight * 19/32 * 72 + moveto % Position the text + (Color Wheel) CENTER % Show the text centered + + % Draw radial lines... + gsave + 0 setlinewidth % 1 pixel lines + + % Position the lines on the left side... + pageWidth 54 mul % x = pageWidth * 3/4 * 72 + pageHeight 54 mul % y = pageHeight * 3/4 * 72 + translate + + % Size the wheel... + wheelSize + + % Loop at 1 degree increments + 0 1 359 { + pop % Discard angle - not used + 0 0 moveto % Start line at the center + dup 0 lineto % Draw to the radius + 1 rotate % Rotate 1 degree + } for + + pop % Discard radius - not needed anymore + stroke % Draw lines... + + grestore + + % Label the lines... + pageWidth 54 mul % x = pageWidth * 3/4 * 72 + pageHeight 44 mul % y = pageHeight * 19/32 * 72 + moveto % Position the text + (1 Degree Radial Lines) CENTER % Show the text centered + + % Imageable area... + pageHeight 15 mul % Height of imageable area + + pageWidth 4.5 mul % x = pageWidth * 1/16 * 72 + pageHeight 35.5 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 1/4 * 72 + 3 index % height + 0.5 setgray rectfill % Draw a shadow + + pageWidth 4 mul % x = pageWidth * 1/16 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 3/8 * 72 + 3 index % height + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + pop % Discard height + + % Label the imageable area... + pageWidth 4 mul % x = pageWidth * 1/16 * 72 + pageHeight 37 mul % y = pageHeight * 1/2 * 72 + moveto % Position the text + mediumFont setfont % Font + (Imageable Area) show % Show the text + + smallFont setfont % Font + pageWidth 14 mul % x = pageWidth * 3/16 * 72 + pageHeight 36 mul % y = pageWidth * 1/2 * 72 + pageHeight -2 mul add % y -= 2 * smallFont height + + % Page Size inches + 2 copy moveto % Move to x & y + (Page Size: ) RIGHT % Label + 100 pageWidth NUMBER % pageWidth + (x) show % "x" + 100 pageHeight NUMBER % pageHeight + (in) show % "in" + + % Page Size millimeters + pageHeight sub % Move down... + + 2 copy moveto % Move to x & y + 10 pageWidth 25.4 mul NUMBER % pageWidth + (x) show % "x" + 10 pageHeight 25.4 mul NUMBER % pageHeight + (mm) show % "mm" + + % Lower-left inches + pageHeight 2 mul sub % Move down... + + 2 copy moveto % Move to x & y + (Lower-Left: ) RIGHT % Label + 100 pageLeft NUMBER % pageLeft + (x) show % "x" + 100 pageBottom NUMBER % pageBottom + (in) show % "in" + + % Lower-left millimeters + pageHeight sub % Move down... + + 2 copy moveto % Move to x & y + 10 pageLeft 25.4 mul NUMBER % pageLeft + (x) show % "x" + 10 pageBottom 25.4 mul NUMBER % pageBottom + (mm) show % "mm" + + % Upper-right inches + pageHeight 2 mul sub % Move down... + + 2 copy moveto % Move to x & y + (Upper-Right: ) RIGHT % Label + 100 pageRight NUMBER % pageRight + (x) show % "x" + 100 pageTop NUMBER % pageTop + (in) show % "in" + + % Upper-right millimeters + pageHeight sub % Move down... + + 2 copy moveto % Move to x & y + 10 pageRight 25.4 mul NUMBER % pageRight + (x) show % "x" + 10 pageTop 25.4 mul NUMBER % pageTop + (mm) show % "mm" + + % Resolution dots-per-inch + pageHeight 2 mul sub % Move down... + + 2 copy moveto % Move to x & y + (Resolution: ) RIGHT % Label + 1 xResolution NUMBER % xResolution + (x) show % "x" + 1 yResolution NUMBER % yResolution + (dpi) show % "dpi" + + % Resolution dots-per-meter + pageHeight sub % Move down... + + moveto % Move to x & y + 1 xResolution 39.27 mul NUMBER % xResolution + (x) show % "x" + 1 yResolution 39.27 mul NUMBER % yResolution + (dpm) show % "dpm" + + % Interpreter Information... + pageHeight 15 mul % Height of interpreter information + + pageWidth 40.5 mul % x = pageWidth * 9/16 * 72 + pageHeight 35.5 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 1/4 * 72 + 3 index % height + 0.5 setgray rectfill % Draw a shadow + + pageWidth 40 mul % x = pageWidth * 9/16 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + 2 index sub % y -= height + pageWidth 28 mul % width = pageWidth * 3/8 * 72 + 3 index % height + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + pop % Discard height + + % Label the interpreter info... + pageWidth 40 mul % x = pageWidth * 9/16 * 72 + pageHeight 37 mul % y = pageHeight * 1/2 * 72 + moveto % Position the text + mediumFont setfont % Font + (Interpreter Information) show % Show the text + + smallFont setfont % Font + pageWidth 49 mul % x = pageWidth * 11/16 * 72 + pageHeight 36 mul % y = pageWidth * 1/2 * 72 + pageHeight 2 mul sub % y -= 2 * smallFont height + + % Language level + 2 copy moveto % Move to x & y + (PostScript: ) RIGHT % Label + (Level ) show % "Level " + 1 languagelevel NUMBER % Language level + + % Version + pageHeight 2 mul sub % Move down... + 2 copy moveto % Move to x & y + (Version: ) RIGHT % Label + version show % Version + ( \() show % " (" + 1 revision NUMBER % Revision + (\)) show % ")" + + % Product + pageHeight 2 mul sub % Move down... + 2 copy moveto % Move to x & y + (Product: ) RIGHT % Label + product show % Product name + + % Serial Number + pageHeight 2 mul sub % Move down... + 2 copy moveto % Move to x & y + (Serial #: ) RIGHT % Label + 1 serialnumber NUMBER % S/N + + % Draw the label at the top... + pageWidth 36 mul % Center of page + pageHeight 68 mul % Top of page (15/16ths) + 2 copy moveto % Position text + bigFont setfont % Font + (Printer Test Page) CENTER % Show text centered + + % Draw the copyright notice at the bottom... + pageWidth 36 mul % Center of page + pageHeight 10 mul % Bottom of page + 2 copy moveto % Position text + (Printed Using CUPS v1.1.x) CENTER % Show text centered + + pageHeight 2 mul sub % Move down... + 2 copy moveto % Position text + smallFont setfont % Font + (Copyright 1993-2002 Easy Software Products, All Rights Reserved.) CENTER + pageHeight sub % Move down... + 2 copy moveto % Position text + (CUPS, Easy Software Products and their logos are the trademark property of) CENTER + pageHeight sub % Move down... + 2 copy moveto % Position text + (Easy Software Products, 44141 Airport View Drive, Suite 204,) CENTER + pageHeight sub % Move down... + 2 copy moveto % Position text + (Hollywood, Maryland, 20636-3111, USA.) CENTER + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageHeight 4 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageHeight 4 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: testprint.ps 2362 2002-04-26 19:58:42Z swdev $". +% +%%EOF diff --git a/data/topsecret b/data/topsecret new file mode 100644 index 0000000000..c5c77c3401 --- /dev/null +++ b/data/topsecret @@ -0,0 +1,277 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Top Secret) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Top Secret) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({?job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: topsecret 2122 2002-01-31 14:19:37Z mike $". +% +%%EOF diff --git a/data/unclassified b/data/unclassified new file mode 100644 index 0000000000..d53190841b --- /dev/null +++ b/data/unclassified @@ -0,0 +1,277 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 +%%Pages: 1 +%%LanguageLevel: 1 +%%DocumentData: Clean7Bit +%%DocumentSuppliedResources: procset bannerprint/1.0 +%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman +%%Creator: Michael Sweet, Easy Software Products +%%CreationDate: May 10, 2000 +%%Title: Test Page +%%EndComments +%%BeginProlog +%%BeginResource procset bannerprint 1.1 0 +% +% PostScript banner page for the Common UNIX Printing System ("CUPS"). +% +% Copyright 1993-2002 Easy Software Products +% +% 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 +% +/CENTER { % Draw centered text + % (name) CENTER - + dup stringwidth pop % Get the width of the string + 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance + show % Show the string +} bind def +/RIGHT { % Draw right-justified text + % (name) RIGHT - + dup stringwidth pop % Get the width of the string + neg 0 rmoveto % Shift left the entire distance + show % Show the string +} bind def +/NUMBER { % Draw a number + % power n NUMBER - + 1 index 1 eq { % power == 1? + round cvi exch pop % Convert "n" to integer + } { + 1 index mul round exch div % Truncate extra decimal places + } ifelse + 100 string cvs show % Convert to a string and show it... +} bind def +/CUPSLOGO { % Draw the CUPS logo + % height CUPSLOGO + % Start with a big C... + /Helvetica findfont 1 index scalefont setfont + 0 setgray + 0 0 moveto + (C) show + + % Then "UNIX Printing System" much smaller... + /Helvetica-Bold findfont 1 index 9 div scalefont setfont + 0.25 mul + dup dup 2.0 mul moveto + (UNIX) show + dup dup 1.6 mul moveto + (Printing) show + dup 1.2 mul moveto + (System) show +} bind def +/ESPLOGO { % Draw the ESP logo + % height ESPLOGO + % Compute the size of the logo... + 0 0 + 2 index 1.5 mul 3 index + + % Do the "metallic" fill from 10% black to 40% black... + 1 -0.001 0 { + dup % loopval + -0.15 mul % loopval * -0.15 + 0.9 add % 0.9 - loopval * 0.15 + setgray % set gray shade + + 0 % x + 1 index neg % loopval + 1 add % 1 - loopval + 3 index % height + mul % height * (1 - loopval) + moveto % starting point + + dup % loopval + 3 index % width + mul % loopval * width + 2 index % height + lineto % Next point + + 0 % x + 2 index % height + lineto % Next point + + closepath + fill + + dup % loopval + 0.15 mul % loopval * 0.15 + 0.6 add % 0.6 + loopval * 0.15 + setgray + + dup % loopval + neg 1 add % 1 - loopval + 3 index % width + mul % (1 - loopval) * width + 0 % y + moveto % Starting point + + 2 index % width + exch % loopval + 2 index % height + mul % loopval * height + lineto % Next point + + 1 index % width + 0 % y + lineto % Next point + + closepath + fill + } for + + 0 setgray rectstroke + + /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont + dup 40 div + + dup 4 mul 1 index 25 mul moveto (E) show + dup 10 mul 1 index 15 mul moveto (S) show + dup 16 mul 1 index 5 mul moveto (P) show + + /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont + dup 14 mul 1 index 29 mul moveto (asy) show + dup 20 mul 1 index 19 mul moveto (oftware) show + dup 26 mul 1 index 9 mul moveto (roducts) show + + pop +} bind def +%%EndResource +%%EndProlog +%%Page: 1 1 +gsave + + % Determine the imageable area and device resolution... + initclip newpath clippath pathbbox % Get bounding rectangle + 72 div /pageTop exch def % Get top margin in inches + 72 div /pageRight exch def % Get right margin in inches + 72 div /pageBottom exch def % Get bottom margin in inches + 72 div /pageLeft exch def % Get left margin in inches + + /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft + /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom + + /boxWidth % width of text box + pageWidth pageHeight lt + { pageWidth 54 mul } + { pageHeight 42 mul } + ifelse def + + newpath % Clear bounding path + + % Create fonts... + /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold + pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) + + /mediumFont /Helvetica findfont % mediumFont = Helvetica + pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) + + % Offset page to account for lower-left margin... + pageLeft 72 mul + pageBottom 72 mul + translate + + % Draw the label at the top and bottom... + 0 setgray % Color + + pageWidth 36 mul % Center of page + pageHeight 72 mul % Top of page + pageWidth -7 mul add % - 2 lines + moveto % Position text + bigFont setfont % Font + (Unclassified) CENTER % Show text centered + + pageWidth 36 mul % Center of page + pageHeight 6 mul % Bottom of page + moveto % Position text + bigFont setfont % Font + (Unclassified) CENTER % Show text centered + + % Job information box... + pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + 0.5 setgray rectfill % Draw a shadow + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + boxWidth 0.5 mul sub % x-= 1/2 box width + pageHeight 30 mul % y = pageHeight * 1/4 * 72 + boxWidth % w = box width + pageHeight 14 mul % h = pageHeight * 1/2 * 72 + + 4 copy 1 setgray rectfill % Clear the box to white + 0 setgray rectstroke % Draw a black box around it... + + % Job information text... + mediumFont setfont % Medium sized font + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 5 mul add % y += 2 lines + 2 copy % Copy X & Y + moveto + (Job ID: ) RIGHT + moveto + ({printer-name}-{job-id}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight 2 mul add % y += 1 line + 2 copy % Copy X & Y + moveto + (Title: ) RIGHT + moveto + ({job-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -1 mul add % y -= 1 line + 2 copy % Copy X & Y + moveto + (Requesting User: ) RIGHT + moveto + ({job-originating-user-name}) show + + pageWidth 36 mul % x = pageWidth * 1/2 * 72 + pageHeight 36 mul % y = pageHeight * 1/2 * 72 + pageHeight -4 mul add % y -= 2 lines + 2 copy % Copy X & Y + moveto + (Billing Info: ) RIGHT + moveto + ({?job-billing}) show + + % Then the CUPS logo.... + gsave + pageWidth 4 mul + pageWidth 6 mul + translate + pageWidth 9 mul CUPSLOGO + grestore + + % And the ESP logo.... + gsave + pageWidth 59 mul + pageWidth 6 mul + translate + pageWidth 6 mul ESPLOGO + grestore +% Show the page... +grestore +showpage +% +% End of "$Id: unclassified 2122 2002-01-31 14:19:37Z mike $". +% +%%EOF diff --git a/data/utf-8 b/data/utf-8 new file mode 100644 index 0000000000..d2e9161798 --- /dev/null +++ b/data/utf-8 @@ -0,0 +1,39 @@ +charset utf8 + +# +# This file defines the font mappings used for Unicode/UTF-8 text printing. +# +# Each line consists of: +# +# first last direction width normal bold italic bold-italic +# +# First and last 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. +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +0000 00FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +0100 01FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +0200 02FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +0300 03FF ltor single Symbol +0400 04FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +0500 05FF rtol single Courier +1E00 1EFF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +2000 20FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +2100 21FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +2200 22FF ltor single Symbol +2300 23FF ltor single Symbol diff --git a/data/windows-1250 b/data/windows-1250 new file mode 100644 index 0000000000..5d45eff014 --- /dev/null +++ b/data/windows-1250 @@ -0,0 +1,254 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1250 (WinLatin2) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +82 201A +84 201E +85 2026 +86 2020 +87 2021 +89 2030 +8A 0160 +8B 2039 +8C 015A +8D 0164 +8E 017D +8F 0179 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9A 0161 +9B 203A +9C 015B +9D 0165 +9E 017E +9F 017A +A0 00A0 +A1 02C7 +A2 02D8 +A3 0141 +A4 00A4 +A5 0104 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 015E +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 017B +B0 00B0 +B1 00B1 +B2 02DB +B3 0142 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 0105 +BA 015F +BB 00BB +BC 013D +BD 02DD +BE 013E +BF 017C +C0 0154 +C1 00C1 +C2 00C2 +C3 0102 +C4 00C4 +C5 0139 +C6 0106 +C7 00C7 +C8 010C +C9 00C9 +CA 0118 +CB 00CB +CC 011A +CD 00CD +CE 00CE +CF 010E +D0 0110 +D1 0143 +D2 0147 +D3 00D3 +D4 00D4 +D5 0150 +D6 00D6 +D7 00D7 +D8 0158 +D9 016E +DA 00DA +DB 0170 +DC 00DC +DD 00DD +DE 0162 +DF 00DF +E0 0155 +E1 00E1 +E2 00E2 +E3 0103 +E4 00E4 +E5 013A +E6 0107 +E7 00E7 +E8 010D +E9 00E9 +EA 0119 +EB 00EB +EC 011B +ED 00ED +EE 00EE +EF 010F +F0 0111 +F1 0144 +F2 0148 +F3 00F3 +F4 00F4 +F5 0151 +F6 00F6 +F7 00F7 +F8 0159 +F9 016F +FA 00FA +FB 0171 +FC 00FC +FD 00FD +FE 0163 +FF 02D9 diff --git a/data/windows-1251 b/data/windows-1251 new file mode 100644 index 0000000000..200bbde457 --- /dev/null +++ b/data/windows-1251 @@ -0,0 +1,258 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1251 (WinCyrillic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 0402 +81 0403 +82 201A +83 0453 +84 201E +85 2026 +86 2020 +87 2021 +88 20AC +89 2030 +8A 0409 +8B 2039 +8C 040A +8D 040C +8E 040B +8F 040F +90 0452 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9A 0459 +9B 203A +9C 045A +9D 045C +9E 045B +9F 045F +A0 00A0 +A1 040E +A2 045E +A3 0408 +A4 00A4 +A5 0490 +A6 00A6 +A7 00A7 +A8 0401 +A9 00A9 +AA 0404 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 0407 +B0 00B0 +B1 00B1 +B2 0406 +B3 0456 +B4 0491 +B5 00B5 +B6 00B6 +B7 00B7 +B8 0451 +B9 2116 +BA 0454 +BB 00BB +BC 0458 +BD 0405 +BE 0455 +BF 0457 +C0 0410 +C1 0411 +C2 0412 +C3 0413 +C4 0414 +C5 0415 +C6 0416 +C7 0417 +C8 0418 +C9 0419 +CA 041A +CB 041B +CC 041C +CD 041D +CE 041E +CF 041F +D0 0420 +D1 0421 +D2 0422 +D3 0423 +D4 0424 +D5 0425 +D6 0426 +D7 0427 +D8 0428 +D9 0429 +DA 042A +DB 042B +DC 042C +DD 042D +DE 042E +DF 042F +E0 0430 +E1 0431 +E2 0432 +E3 0433 +E4 0434 +E5 0435 +E6 0436 +E7 0437 +E8 0438 +E9 0439 +EA 043A +EB 043B +EC 043C +ED 043D +EE 043E +EF 043F +F0 0440 +F1 0441 +F2 0442 +F3 0443 +F4 0444 +F5 0445 +F6 0446 +F7 0447 +F8 0448 +F9 0449 +FA 044A +FB 044B +FC 044C +FD 044D +FE 044E +FF 044F diff --git a/data/windows-1252 b/data/windows-1252 new file mode 100644 index 0000000000..d758d536e1 --- /dev/null +++ b/data/windows-1252 @@ -0,0 +1,254 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1252 (WinLatin1) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +8E 017D +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9E 017E +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00BA +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 00D0 +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 00DD +DE 00DE +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 00F0 +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 00FD +FE 00FE +FF 00FF diff --git a/data/windows-1253 b/data/windows-1253 new file mode 100644 index 0000000000..a9dfcb8ebb --- /dev/null +++ b/data/windows-1253 @@ -0,0 +1,243 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1253 (WinGreek) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 9f ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique +a0 ff ltor single Symbol + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +89 2030 +8B 2039 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9B 203A +A0 00A0 +A1 0385 +A2 0386 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 2015 +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 0384 +B5 00B5 +B6 00B6 +B7 00B7 +B8 0388 +B9 0389 +BA 038A +BB 00BB +BC 038C +BD 00BD +BE 038E +BF 038F +C0 0390 +C1 0391 +C2 0392 +C3 0393 +C4 0394 +C5 0395 +C6 0396 +C7 0397 +C8 0398 +C9 0399 +CA 039A +CB 039B +CC 039C +CD 039D +CE 039E +CF 039F +D0 03A0 +D1 03A1 +D3 03A3 +D4 03A4 +D5 03A5 +D6 03A6 +D7 03A7 +D8 03A8 +D9 03A9 +DA 03AA +DB 03AB +DC 03AC +DD 03AD +DE 03AE +DF 03AF +E0 03B0 +E1 03B1 +E2 03B2 +E3 03B3 +E4 03B4 +E5 03B5 +E6 03B6 +E7 03B7 +E8 03B8 +E9 03B9 +EA 03BA +EB 03BB +EC 03BC +ED 03BD +EE 03BE +EF 03BF +F0 03C0 +F1 03C1 +F2 03C2 +F3 03C3 +F4 03C4 +F5 03C5 +F6 03C6 +F7 03C7 +F8 03C8 +F9 03C9 +FA 03CA +FB 03CB +FC 03CC +FD 03CD +FE 03CE diff --git a/data/windows-1254 b/data/windows-1254 new file mode 100644 index 0000000000..434c65c470 --- /dev/null +++ b/data/windows-1254 @@ -0,0 +1,252 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1254 (WinTurkish) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0160 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9A 0161 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00BA +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 00C3 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 00CC +CD 00CD +CE 00CE +CF 00CF +D0 011E +D1 00D1 +D2 00D2 +D3 00D3 +D4 00D4 +D5 00D5 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 0130 +DE 015E +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 00E3 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 00EC +ED 00ED +EE 00EE +EF 00EF +F0 011F +F1 00F1 +F2 00F2 +F3 00F3 +F4 00F4 +F5 00F5 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 0131 +FE 015F +FF 00FF diff --git a/data/windows-1255 b/data/windows-1255 new file mode 100644 index 0000000000..66681ec1b3 --- /dev/null +++ b/data/windows-1255 @@ -0,0 +1,236 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1255 (WinHebrew) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff rtol single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8B 2039 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9B 203A +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 20AA +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00D7 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00F7 +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 05B0 +C1 05B1 +C2 05B2 +C3 05B3 +C4 05B4 +C5 05B5 +C6 05B6 +C7 05B7 +C8 05B8 +C9 05B9 +CB 05BB +CC 05BC +CD 05BD +CE 05BE +CF 05BF +D0 05C0 +D1 05C1 +D2 05C2 +D3 05C3 +D4 05F0 +D5 05F1 +D6 05F2 +D7 05F3 +D8 05F4 +E0 05D0 +E1 05D1 +E2 05D2 +E3 05D3 +E4 05D4 +E5 05D5 +E6 05D6 +E7 05D7 +E8 05D8 +E9 05D9 +EA 05DA +EB 05DB +EC 05DC +ED 05DD +EE 05DE +EF 05DF +F0 05E0 +F1 05E1 +F2 05E2 +F3 05E3 +F4 05E4 +F5 05E5 +F6 05E6 +F7 05E7 +F8 05E8 +F9 05E9 +FA 05EA +FD 200E +FE 200F diff --git a/data/windows-1256 b/data/windows-1256 new file mode 100644 index 0000000000..6f41b24c9b --- /dev/null +++ b/data/windows-1256 @@ -0,0 +1,259 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1256 (WinArabic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff rtol single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +81 067E +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8A 0679 +8B 2039 +8C 0152 +8D 0686 +8E 0698 +8F 0688 +90 06AF +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 06A9 +99 2122 +9A 0691 +9B 203A +9C 0153 +9D 200C +9E 200D +9F 06BA +A0 00A0 +A1 060C +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 06BE +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 061B +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 061F +C0 06C1 +C1 0621 +C2 0622 +C3 0623 +C4 0624 +C5 0625 +C6 0626 +C7 0627 +C8 0628 +C9 0629 +CA 062A +CB 062B +CC 062C +CD 062D +CE 062E +CF 062F +D0 0630 +D1 0631 +D2 0632 +D3 0633 +D4 0634 +D5 0635 +D6 0636 +D7 00D7 +D8 0637 +D9 0638 +DA 0639 +DB 063A +DC 0640 +DD 0641 +DE 0642 +DF 0643 +E0 00E0 +E1 0644 +E2 00E2 +E3 0645 +E4 0646 +E5 0647 +E6 0648 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 0649 +ED 064A +EE 00EE +EF 00EF +F0 064B +F1 064C +F2 064D +F3 064E +F4 00F4 +F5 064F +F6 0650 +F7 00F7 +F8 0651 +F9 00F9 +FA 0652 +FB 00FB +FC 00FC +FD 200E +FE 200F +FF 06D2 diff --git a/data/windows-1257 b/data/windows-1257 new file mode 100644 index 0000000000..b56b337294 --- /dev/null +++ b/data/windows-1257 @@ -0,0 +1,247 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1257 (WinBaltic) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +82 201A +84 201E +85 2026 +86 2020 +87 2021 +89 2030 +8B 2039 +8D 00A8 +8E 02C7 +8F 00B8 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +99 2122 +9B 203A +9D 00AF +9E 02DB +A0 00A0 +A2 00A2 +A3 00A3 +A4 00A4 +A6 00A6 +A7 00A7 +A8 00D8 +A9 00A9 +AA 0156 +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00C6 +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00F8 +B9 00B9 +BA 0157 +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00E6 +C0 0104 +C1 012E +C2 0100 +C3 0106 +C4 00C4 +C5 00C5 +C6 0118 +C7 0112 +C8 010C +C9 00C9 +CA 0179 +CB 0116 +CC 0122 +CD 0136 +CE 012A +CF 013B +D0 0160 +D1 0143 +D2 0145 +D3 00D3 +D4 014C +D5 00D5 +D6 00D6 +D7 00D7 +D8 0172 +D9 0141 +DA 015A +DB 016A +DC 00DC +DD 017B +DE 017D +DF 00DF +E0 0105 +E1 012F +E2 0101 +E3 0107 +E4 00E4 +E5 00E5 +E6 0119 +E7 0113 +E8 010D +E9 00E9 +EA 017A +EB 0117 +EC 0123 +ED 0137 +EE 012B +EF 013C +F0 0161 +F1 0144 +F2 0146 +F3 00F3 +F4 014D +F5 00F5 +F6 00F6 +F7 00F7 +F8 0173 +F9 0142 +FA 015B +FB 016B +FC 00FC +FD 017C +FE 017E +FF 02D9 diff --git a/data/windows-1258 b/data/windows-1258 new file mode 100644 index 0000000000..dcd4790ab5 --- /dev/null +++ b/data/windows-1258 @@ -0,0 +1,250 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 1258 (WinVietnamese) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +82 201A +83 0192 +84 201E +85 2026 +86 2020 +87 2021 +88 02C6 +89 2030 +8B 2039 +8C 0152 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +98 02DC +99 2122 +9B 203A +9C 0153 +9F 0178 +A0 00A0 +A1 00A1 +A2 00A2 +A3 00A3 +A4 00A4 +A5 00A5 +A6 00A6 +A7 00A7 +A8 00A8 +A9 00A9 +AA 00AA +AB 00AB +AC 00AC +AD 00AD +AE 00AE +AF 00AF +B0 00B0 +B1 00B1 +B2 00B2 +B3 00B3 +B4 00B4 +B5 00B5 +B6 00B6 +B7 00B7 +B8 00B8 +B9 00B9 +BA 00BA +BB 00BB +BC 00BC +BD 00BD +BE 00BE +BF 00BF +C0 00C0 +C1 00C1 +C2 00C2 +C3 0102 +C4 00C4 +C5 00C5 +C6 00C6 +C7 00C7 +C8 00C8 +C9 00C9 +CA 00CA +CB 00CB +CC 0300 +CD 00CD +CE 00CE +CF 00CF +D0 0110 +D1 00D1 +D2 0309 +D3 00D3 +D4 00D4 +D5 01A0 +D6 00D6 +D7 00D7 +D8 00D8 +D9 00D9 +DA 00DA +DB 00DB +DC 00DC +DD 01AF +DE 0303 +DF 00DF +E0 00E0 +E1 00E1 +E2 00E2 +E3 0103 +E4 00E4 +E5 00E5 +E6 00E6 +E7 00E7 +E8 00E8 +E9 00E9 +EA 00EA +EB 00EB +EC 0301 +ED 00ED +EE 00EE +EF 00EF +F0 0111 +F1 00F1 +F2 0323 +F3 00F3 +F4 00F4 +F5 01A1 +F6 00F6 +F7 00F7 +F8 00F8 +F9 00F9 +FA 00FA +FB 00FB +FC 00FC +FD 01B0 +FE 20AB +FF 00FF diff --git a/data/windows-874 b/data/windows-874 new file mode 100644 index 0000000000..a231ce7336 --- /dev/null +++ b/data/windows-874 @@ -0,0 +1,228 @@ +charset 8bit + +# +# This file defines the font and character mappings used for Windows +# Code Page 874 (Thai) text printing. +# +# The first line consists of: +# +# direction width normal bold italic bold-italic +# +# Direction is the string "ltor" or "rtol", indicating left-to-right or +# right-to-left text. +# +# Width is the string "single" or "double"; double means that the glyphs +# are twice as wide as ASCII characters in the Courier typeface. +# +# "Normal", "bold", "italic", and "bold-italic" 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. "Symbol") +# +# Each font that is listed will be used (and downloaded if needed) when +# printing. +# + +00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique + +# +# The following lines define the mapping from the 8-bit character set to +# the Unicode glyphs for each character: +# +# char glyph +# +# "Char" and "glyph" are hexadecimal values. +# + +20 0020 +21 0021 +22 0022 +23 0023 +24 0024 +25 0025 +26 0026 +27 0027 +28 0028 +29 0029 +2A 002A +2B 002B +2C 002C +2D 002D +2E 002E +2F 002F +30 0030 +31 0031 +32 0032 +33 0033 +34 0034 +35 0035 +36 0036 +37 0037 +38 0038 +39 0039 +3A 003A +3B 003B +3C 003C +3D 003D +3E 003E +3F 003F +40 0040 +41 0041 +42 0042 +43 0043 +44 0044 +45 0045 +46 0046 +47 0047 +48 0048 +49 0049 +4A 004A +4B 004B +4C 004C +4D 004D +4E 004E +4F 004F +50 0050 +51 0051 +52 0052 +53 0053 +54 0054 +55 0055 +56 0056 +57 0057 +58 0058 +59 0059 +5A 005A +5B 005B +5C 005C +5D 005D +5E 005E +5F 005F +60 0060 +61 0061 +62 0062 +63 0063 +64 0064 +65 0065 +66 0066 +67 0067 +68 0068 +69 0069 +6A 006A +6B 006B +6C 006C +6D 006D +6E 006E +6F 006F +70 0070 +71 0071 +72 0072 +73 0073 +74 0074 +75 0075 +76 0076 +77 0077 +78 0078 +79 0079 +7A 007A +7B 007B +7C 007C +7D 007D +7E 007E +7F 007F +80 20AC +85 2026 +91 2018 +92 2019 +93 201C +94 201D +95 2022 +96 2013 +97 2014 +A0 00A0 +A1 0E01 +A2 0E02 +A3 0E03 +A4 0E04 +A5 0E05 +A6 0E06 +A7 0E07 +A8 0E08 +A9 0E09 +AA 0E0A +AB 0E0B +AC 0E0C +AD 0E0D +AE 0E0E +AF 0E0F +B0 0E10 +B1 0E11 +B2 0E12 +B3 0E13 +B4 0E14 +B5 0E15 +B6 0E16 +B7 0E17 +B8 0E18 +B9 0E19 +BA 0E1A +BB 0E1B +BC 0E1C +BD 0E1D +BE 0E1E +BF 0E1F +C0 0E20 +C1 0E21 +C2 0E22 +C3 0E23 +C4 0E24 +C5 0E25 +C6 0E26 +C7 0E27 +C8 0E28 +C9 0E29 +CA 0E2A +CB 0E2B +CC 0E2C +CD 0E2D +CE 0E2E +CF 0E2F +D0 0E30 +D1 0E31 +D2 0E32 +D3 0E33 +D4 0E34 +D5 0E35 +D6 0E36 +D7 0E37 +D8 0E38 +D9 0E39 +DA 0E3A +DF 0E3F +E0 0E40 +E1 0E41 +E2 0E42 +E3 0E43 +E4 0E44 +E5 0E45 +E6 0E46 +E7 0E47 +E8 0E48 +E9 0E49 +EA 0E4A +EB 0E4B +EC 0E4C +ED 0E4D +EE 0E4E +EF 0E4F +F0 0E50 +F1 0E51 +F2 0E52 +F3 0E53 +F4 0E54 +F5 0E55 +F6 0E56 +F7 0E57 +F8 0E58 +F9 0E59 +FA 0E5A +FB 0E5B diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000..7bd3851f1c --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,242 @@ +# +# "$Id$" +# +# Documentation makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-2002 by Easy Software Products. +# +# 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-9600 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# HTMLDOC generation rules... +# + +.SUFFIXES: .html .pdf .ps .shtml +.shtml.html: + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --numbered -f $@ $< +.shtml.pdf: + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \ + --numbered --jpeg -f $@ $< +.shtml.ps: + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --numbered \ + --jpeg -f $@ $< + +HTMLDOC = htmldoc --strict + + +# +# Document files... +# + +DOCUMENTS = cmp.shtml idd.shtml ipp.shtml sam.shtml sdd.shtml \ + spm.shtml sps.shtml ssr.shtml stp.shtml sum.shtml \ + svd.shtml translation.shtml +DOCIMAGES = images/cups-block-diagram.gif images/cups-large.gif \ + images/cups-medium.gif images/cups-small.gif +WEBPAGES = cups.css cupsdoc.css index.html documentation.html +WEBIMAGES = images/accept-jobs.gif \ + images/add-class.gif \ + images/add-printer.gif \ + images/cancel-job.gif \ + images/cancel-jobs.gif \ + images/cancel.gif \ + images/classes.gif \ + images/config-printer.gif \ + images/continue.gif \ + images/delete-class.gif \ + images/delete-printer.gif \ + images/draft.gif \ + images/hold-job.gif \ + images/left.gif \ + images/logo.gif \ + images/manage-classes.gif \ + images/manage-jobs.gif \ + images/manage-printers.gif \ + images/modify-class.gif \ + images/modify-printer.gif \ + images/navbar.gif \ + images/print-test-page.gif \ + images/printer-idle.gif \ + images/printer-processing.gif \ + images/printer-stopped.gif \ + images/reject-jobs.gif \ + images/release-job.gif \ + images/restart-job.gif \ + images/right.gif \ + images/show-active.gif \ + images/show-completed.gif \ + images/start-class.gif \ + images/start-printer.gif \ + images/stop-class.gif \ + images/stop-printer.gif + + +# +# Make all documents... +# + +all: $(DOCUMENTS:.shtml=.pdf) $(DOCUMENTS:.shtml=.html) overview.pdf + cd fr; $(MAKE) $(MFLAGS) all + + +# +# Make PS files... +# + +ps: $(DOCUMENTS:.shtml=.ps) overview.ps + cd fr; $(MAKE) $(MFLAGS) ps + + +# +# Remove all generated files... +# + +clean: + $(RM) $(DOCUMENTS:.shtml=.pdf) + $(RM) $(DOCUMENTS:.shtml=.html) + $(RM) overview.pdf + cd fr; $(MAKE) $(MFLAGS) clean + + +# +# Install all documentation files... +# + +install: + $(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 + cd fr; $(MAKE) $(MFLAGS) install + + +# +# The overview, admin manual, programmers manual, and users manual get +# special attention... +# + +overview.pdf: overview.html + echo Formatting $@... + $(HTMLDOC) --duplex --compression=9 --jpeg --webpage -f overview.pdf overview.html +overview.ps: overview.html + echo Formatting $@... + $(HTMLDOC) --duplex --jpeg --webpage -f overview.ps overview.html + +sam.html: sam.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif -f $@ $< +sam.pdf: sam.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \ + --jpeg -f $@ $< +sam.ps: sam.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg -f $@ $< + +spm.html: spm.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif -f $@ $< +spm.pdf: spm.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \ + --jpeg -f $@ $< +spm.ps: spm.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg -f $@ $< + +sum.html: sum.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif -f $@ $< +sum.pdf: sum.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \ + --jpeg -f $@ $< +sum.ps: sum.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg -f $@ $< + +sam-7x8.pdf: sam.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \ + --pagelayout tworight --pagemode document \ + --jpeg --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sam.shtml +sam-7x8.ps: sam.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg \ + --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sam.shtml +spm-7x8.pdf: spm.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \ + --pagelayout tworight --pagemode document \ + --jpeg --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ spm.shtml +spm-7x8.ps: spm.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg \ + --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ spm.shtml +sum-7x8.pdf: sum.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \ + --pagelayout tworight --pagemode document \ + --jpeg --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sum.shtml +sum-7x8.ps: sum.shtml + echo Formatting $@... + $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg \ + --size 7x8.5in --left 0.5in --right 0.25in \ + --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sum.shtml + +$(DOCUMENTS:.shtml=.html): \ + glossary.shtml printing-overview.shtml \ + references.shtml system-overview.shtml \ + ../LICENSE.html + +$(DOCUMENTS:.shtml=.pdf): \ + glossary.shtml printing-overview.shtml \ + references.shtml system-overview.shtml \ + ../LICENSE.html + +$(DOCUMENTS:.shtml=.ps): \ + glossary.shtml printing-overview.shtml \ + references.shtml system-overview.shtml \ + ../LICENSE.html + + +# +# End of Makefile. +# diff --git a/doc/cmp.html b/doc/cmp.html new file mode 100644 index 0000000000..ac8c03efbd --- /dev/null +++ b/doc/cmp.html @@ -0,0 +1,682 @@ + + + +CUPS Configuration Management Plan + + + + + + + +


+

CUPS Configuration Management Plan


+CUPS-CMP-1.1
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 File Management + +4 Trouble Report Processing + +5 Software Releases + +A Glossary + +B Coding Requirements + +C Software Trouble Report Form
+

1 Scope

+

1.1 Identification

+ This configuration management plan document provides the guidelines for + development and maintenance of the Common UNIX Printing System ("CUPS") + Version 1.1 software. +

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+

1.3 Document Overview

+ This configuration management document is organized into the following + sections: +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - File Management
  • +
  • 4 - Trouble Report Processing
  • +
  • 5 - Software Releases
  • +
  • A - Glossary
  • +
  • B - Coding Requirements
  • +
+

2 References

+

2.1 CUPS Documentation

+

The following CUPS documentation is referenced by this document:

+
    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.1: CUPS Software Security Report
  • +
  • CUPS-STP-1.1: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.1: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

The following non-CUPS documents are referenced by this document:

+ +

3 File Management

+

3.1 Directory Structure

+ Each source file shall be placed a sub-directory corresponding to the + software sub-system it belongs to ("scheduler", "cups", etc.) To remain + compatible with older UNIX filesystems, directory names shall not + exceed 16 characters in length. +

3.2 Source Files

+ Source files shall be documented and formatted as described in Appendix + B, Coding Requirements. +

3.3 Configuration Management

+ Source files shall be placed under the control of the Concurrent + Versions System ("CVS") software. Source files shall be "checked in" + with each change so that modifications can be tracked. +

Documentation on the CVS software is included with the whitepaper, + "CVS II: Parallelizing Software Development".

+

4 Trouble Report Processing

+ A Software Trouble Report ("STR") 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: +
    +
  1. STR is closed with complete resolution
  2. +
  3. STR is closed without resolution
  4. +
  5. STR is active
  6. +
  7. STR is pending (new STR or additional information available)
  8. +
+ Trouble reports shall be processed using the following steps. +

4.1 Classification

+ When a trouble report is received it must be classified at one of the + following levels: +
    +
  1. Request for enhancement
  2. +
  3. Documentation error
  4. +
  5. Unable to print a file
  6. +
  7. Unable to print to a printer
  8. +
  9. Unable to print at all
  10. +
+ The scope of the problem should also be determined as: +
    +
  1. Specific to a machine
  2. +
  3. Specific to an operating system
  4. +
  5. Applies to all machines and operating systems
  6. +
+

4.2 Identification

+ 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. +

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).

+

4.3 Correction

+ 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. +

4.4 Notification

+ The user or vendor is notified when the fix is available or if the + problem was caused by user error. +

5 Software Releases

+

5.1 Version Numbering

+ CUPS uses a three-part version number separated by periods to represent + the major, minor, and patch release numbers: +
    +
    +major.minor.patch
    +1.1.0
    +
    +
+ Beta-test releases are indentified by appending the letter B followed + by the build number: +
    +
    +major.minor.patchbbuild
    +1.1.0b1
    +
    +
+ A CVS snapshot is generated for every beta and final release and uses + the version number preceded by the letter "v" and with the decimal + points replaced by underscores: +
    +
    +v1_0_0b1
    +v1_0_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: +
    +
    +1.1.0b1    First beta release
    +1.1.0b2    Second beta release
    +1.1.0      First production release
    +1.1.1b1    First beta of 1.1.1
    +1.1.1      Production release of 1.1.1
    +1.1.1b1    First beta of 1.1.1
    +1.1.1      Production release of 1.1.1
    +2.0.0b1    First beta of 2.0.0
    +2.0.0      Production release of 2.0.0
    +
    +
+

5.2 Generation

+ 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. +

5.3 Testing

+ 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. +

5.4 Release

+ When testing has been completed successfully a new distribution image + is created from the current CVS code "snapshot". No production release + shall contain software that has not passed the appropriate software + tests. +

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Page Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+

B Coding Requirements

+ 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. +

B.1 Source Files

+

B.1.1 Naming

+ 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 ".c" for ANSI C and + ".cxx" for C++ source files. All other "include" files shall have an + extension of ".h". +

B.1.2 Documentation

+ 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 "$Id$" tag: +
    +
    +/*
    + * "$Id$"
    + *
    + *   Description of file contents.
    + *
    + *   Copyright 1997-2002 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-9600
    + *       EMail: cups-info@cups.org
    + *         WWW: http://www.cups.org
    + *
    + * Contents:
    + *
    + *   function1() - Description 1.
    + *   function2() - Description 2.
    + *   function3() - Description 3.
    + */
    +
    +
+ The bottom of each source file shall contain a trailer giving the name + of the file using the CVS "$Id$" 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: +
    +
    +/*
    + * End of "$Id$".
    + */
    +
    +
+

B.2 Functions

+

B.2.1 Naming

+ Functions with a global scope shall be capitalized ("DoThis", "DoThat", + "DoSomethingElse", etc.) The only exception to this rule shall be the + CUPS interface library functions which may begin with a prefix word in + lowercase ("cupsDoThis", "cupsDoThat", etc.) +

Functions with a local scope shall be declared "static" and be + lowercase with underscores between words ("do_this", "do_that", + "do_something_else", etc.)

+

B.2.2 Documentation

+ 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: +
    +
    +/*
    + * 'do_this()' - Compute y = this(x).
    + *
    + * Notes: none.
    + */
    +
    +static float     /* O - Inverse power value, 0.0 <= y <= 1.1 */
    +do_this(float x) /* I - Power value (0.0 <= x <= 1.1) */
    +{
    +  ...
    +  return (y);
    +}
    +
    +
+

B.3 Methods

+

B.3.1 Naming

+ Methods shall be in lowercase with underscores between words + ("do_this", "do_that", "do_something_else", etc.) +

B.3.2 Documentation

+ 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: +
    +
    +/*
    + * 'class::do_this()' - Compute y = this(x).
    + *
    + * Notes: none.
    + */
    +
    +float                   /* O - Inverse power value, 0.0 <= y <= 1.0 */
    +class::do_this(float x) /* I - Power value (0.0 <= x <= 1.0) */
    +{
    +  ...
    +  return (y);
    +}
    +
    +
+

B.4 Variables

+

B.4.1 Naming

+ Variables with a global scope shall be capitalized ("ThisVariable", + "ThatVariable", "ThisStateVariable", etc.) The only exception to this + rule shall be the CUPS interface library global variables which must + begin with the prefix "cups" ("cupsThisVariable", "cupsThatVariable", + etc.) Global variables shall be replaced by function arguments whenever + possible. +

Variables with a local scope shall be lowercase with underscores + between words ("this_variable", "that_variable", etc.) Any local + variables shared by functions within a source file shall be declared + "static".

+

B.4.2 Documentation

+ Each variable shall be declared on a separate line and shall be + immediately followed by a comment block describing the variable: +
    +
    +int this_variable;   /* The current state of this */
    +int that_variable;   /* The current state of that */
    +
    +
+

B.5 Types

+

B.5.1 Naming

+ All type names shall be lowercase with underscores between words and + "_t" appended to the end of the name ("this_type_t", "that_type_t", + etc.) +

B.5.2 Documentation

+ Each type shall have a comment block immediately before the typedef: +
    +
    +/*
    + * This type is for CUPS foobar options.
    + */
    +typedef int cups_this_type_t;
    +
    +
+

B.6 Structures

+

B.6.1 Naming

+ All structure names shall be lowercase with underscores between words + and "_str" appended to the end of the name ("this_struct_str", + "that_struct_str", etc.) +

B.6.2 Documentation

+ 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: +
    +
    +/*
    + * This structure is for CUPS foobar options.
    + */
    +struct cups_this_struct_str
    +{
    +  int this_member;   /* Current state for this */
    +  int that_member;   /* Current state for that */
    +};
    +
    +
+

B.7 Classes

+

B.7.1 Naming

+ All class names shall be lowercase with underscores between words + ("this_class", "that_class", etc.) +

B.7.2 Documentation

+ 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: +
    +
    +/*
    + * This class is for CUPS foobar options.
    + */
    +class cups_this_class
    +{
    +  int this_member;   /* Current state for this */
    +  int that_member;   /* Current state for that */
    +};
    +
    +
+

B.8 Constants

+

B.8.1 Naming

+ All constant names shall be uppercase with underscored between words + ("THIS_CONSTANT", "THAT_CONSTANT", etc.) Constants defined for the CUPS + interface library must begin with an uppercase prefix + ("CUPS_THIS_CONSTANT", "CUPS_THAT_CONSTANT", etc.) +

Typed enumerations shall be used whenever possible to allow for type + checking by the compiler.

+

B.8.2 Documentation

+ Comment blocks shall immediately follow each constant: +
    +
    +enum
    +{
    +  CUPS_THIS_TRAY,   /* This tray */
    +  CUPS_THAT_TRAY    /* That tray */
    +};
    +
    +
+

B.9 Code

+

B.9.1 Documentation

+ All source code shall utilize block comments within functions to + describe the operations being performed by a group of statements: +
    +
    +/*
    + * Clear the state array before we begin...
    + */
    +
    +for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
    +  array[i] = STATE_IDLE;
    +
    +/*
    + * Wait for state changes...
    + */
    +
    +do
    +{
    +  for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
    +    if (array[i] != STATE_IDLE)
    +      break;
    +
    +  if (i == (sizeof(array) / sizeof(array[0])))
    +    sleep(1);
    +} while (i == (sizeof(array) / sizeof(array[0])));
    +
    +
+

B.9.2 Style

+

B.9.2.a 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: +
    +
    +{
    +  int i; /* Looping var */
    +
    + /*
    +  * Process foobar values from 0 to 999...
    +  */
    +
    +  for (i = 0; i < 1000; i ++)
    +  {
    +    do_this(i);
    +    do_that(i);
    +  }
    +}
    +
    +
+ Single-line statements following "do", "else", "for", "if", and "while" + shall be indented 2 spaces as well. Blocks of code in a "switch" block + shall be indented 4 spaces after each "case" and "default" case: +
    +
    +switch (array[i])
    +{
    +  case STATE_IDLE :
    +      do_this(i);
    +      do_that(i);
    +      break;
    +  default :
    +      do_nothing(i);
    +      break;
    +}
    +
    +
+

B.9.2.b Spacing

+ A space shall follow each reserved word ("if", "while", etc.) Spaces + shall not be inserted between a function name and the arguments in + parenthesis. +

B.9.2.c Return Values

+ Parenthesis shall surround values returned from a function using + "return": +
    +
    +return (STATE_IDLE);
    +
    +
+

B.9.2.d Loops

+ Whenever convenient loops should count downward to zero to improve + program performance: +
    +
    +for (i = sizeof(array) / sizeof(array[0]) - 1; i >= 0; i --)
    +  array[i] = STATE_IDLE;
    +
    +
+

C Software Trouble Report Form

+
+ + + + + +
Summary of Problem: +________________________________________
Problem Severity:__1=RFE +
__2=Documentation-Error +
__3=Unable-to-Print-a-File +
__4=Unable-to-Print-to-a-Printer +
__5=Unable-to-Print-at-All
Problem Scope:__1=Machine + __2=Operating-System __3=All
Detailed Description of Problem:________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________
+
+ + diff --git a/doc/cmp.pdf b/doc/cmp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e9745a1bf98b9ba6479b7ed910e3d732236bd5e4 GIT binary patch literal 55293 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

o-KWxR#-I37=x1NKZIBE; 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 + + + + + CUPS Configuration Management Plan + + + +

Scope

+ +

Identification

+ +This configuration management plan document provides the guidelines for +development and maintenance of the Common UNIX Printing System ("CUPS") +Version 1.1 software. + + + +

Document Overview

+ +This configuration management document is organized into the following +sections: + +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - File Management
  • +
  • 4 - Trouble Report Processing
  • +
  • 5 - Software Releases
  • +
  • A - Glossary
  • +
  • B - Coding Requirements
  • +
+ + + +

File Management

+ +

Directory Structure

+ +Each source file shall be placed a sub-directory corresponding to the software +sub-system it belongs to ("scheduler", "cups", etc.) To remain compatible +with older UNIX filesystems, directory names shall not exceed 16 characters +in length. + +

Source Files

+ +Source files shall be documented and formatted as described in Appendix +B, Coding Requirements. + +

Configuration Management

+ +Source files shall be placed under the control of the Concurrent Versions +System ("CVS") software. Source files shall be "checked in" with each change +so that modifications can be tracked. + +

Documentation on the CVS software is included with the whitepaper, "CVS +II: Parallelizing Software Development". + +

Trouble Report Processing

+ +A Software Trouble Report ("STR") 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: + +
    +
  1. STR is closed with complete resolution
  2. +
  3. STR is closed without resolution
  4. +
  5. STR is active
  6. +
  7. STR is pending (new STR or additional information available)
  8. +
+ +Trouble reports shall be processed using the following steps. + +

Classification

+ +When a trouble report is received it must be classified at one of the following +levels: + +
    +
  1. Request for enhancement
  2. +
  3. Documentation error
  4. +
  5. Unable to print a file
  6. +
  7. Unable to print to a printer
  8. +
  9. Unable to print at all
  10. +
+ +The scope of the problem should also be determined as: + +
    +
  1. Specific to a machine
  2. +
  3. Specific to an operating system
  4. +
  5. Applies to all machines and operating systems
  6. +
+ +

Identification

+ +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. + +

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). + +

Correction

+ +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. + +

Notification

+ +The user or vendor is notified when the fix is available or if the problem +was caused by user error. + +

Software Releases

+ +

Version Numbering

+ +CUPS uses a three-part version number separated by periods to represent +the major, minor, and patch release numbers: + +
    +
    +major.minor.patch
    +1.1.0
    +
    +
+ +Beta-test releases are indentified by appending the letter B followed by +the build number: + +
    +
    +major.minor.patchbbuild
    +1.1.0b1
    +
    +
+ +A CVS snapshot is generated for every beta and final release and uses +the version number preceded by the letter "v" and with the decimal +points replaced by underscores: + +
    +
    +v1_0_0b1
    +v1_0_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: + +
    +
    +1.1.0b1    First beta release
    +1.1.0b2    Second beta release
    +1.1.0      First production release
    +1.1.1b1    First beta of 1.1.1
    +1.1.1      Production release of 1.1.1
    +1.1.1b1    First beta of 1.1.1
    +1.1.1      Production release of 1.1.1
    +2.0.0b1    First beta of 2.0.0
    +2.0.0      Production release of 2.0.0
    +
    +
+ +

Generation

+ +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. + +

Testing

+ +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. + +

Release

+ +When testing has been completed successfully a new distribution image is +created from the current CVS code "snapshot". No production release shall +contain software that has not passed the appropriate software tests. + + + +

Coding Requirements

+ +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. + +

Source Files

+ +

Naming

+ +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 ".c" for ANSI C and +".cxx" for C++ source files. All other "include" files shall have an +extension of ".h". + +

Documentation

+ +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 "$Id$" tag: + +
    +
    +/*
    + * "$Id$"
    + *
    + *   Description of file contents.
    + *
    + *   Copyright 1997-2002 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-9600
    + *       EMail: cups-info@cups.org
    + *         WWW: http://www.cups.org
    + *
    + * Contents:
    + *
    + *   function1() - Description 1.
    + *   function2() - Description 2.
    + *   function3() - Description 3.
    + */
    +
    +
+ +The bottom of each source file shall contain a trailer giving the name +of the file using the CVS "$Id$" 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: + +
    +
    +/*
    + * End of "$Id$".
    + */
    +
    +
+ +

Functions

+ +

Naming

+ +Functions with a global scope shall be capitalized ("DoThis", "DoThat", +"DoSomethingElse", etc.) The only exception to this rule shall be the +CUPS interface library functions which may begin with a prefix word in +lowercase ("cupsDoThis", "cupsDoThat", etc.) + +

Functions with a local scope shall be declared "static" and be lowercase +with underscores between words ("do_this", "do_that", "do_something_else", +etc.) + +

Documentation

+ +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: + +
    +
    +/*
    + * 'do_this()' - Compute y = this(x).
    + *
    + * Notes: none.
    + */
    +
    +static float     /* O - Inverse power value, 0.0 <= y <= 1.1 */
    +do_this(float x) /* I - Power value (0.0 <= x <= 1.1) */
    +{
    +  ...
    +  return (y);
    +}
    +
    +
+ +

Methods

+ +

Naming

+ +Methods shall be in lowercase with underscores between words ("do_this", +"do_that", "do_something_else", etc.) + +

Documentation

+ +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: + +
    +
    +/*
    + * 'class::do_this()' - Compute y = this(x).
    + *
    + * Notes: none.
    + */
    +
    +float                   /* O - Inverse power value, 0.0 <= y <= 1.0 */
    +class::do_this(float x) /* I - Power value (0.0 <= x <= 1.0) */
    +{
    +  ...
    +  return (y);
    +}
    +
    +
+ +

Variables

+ +

Naming

+ +Variables with a global scope shall be capitalized ("ThisVariable", +"ThatVariable", "ThisStateVariable", etc.) The only exception to this +rule shall be the CUPS interface library global variables which must +begin with the prefix "cups" ("cupsThisVariable", "cupsThatVariable", +etc.) Global variables shall be replaced by function arguments whenever +possible. + +

Variables with a local scope shall be lowercase with underscores between +words ("this_variable", "that_variable", etc.) Any local variables shared +by functions within a source file shall be declared "static". + +

Documentation

+ +Each variable shall be declared on a separate line and shall be immediately +followed by a comment block describing the variable: + +
    +int this_variable;   /* The current state of this */
    +int that_variable;   /* The current state of that */
    +
+ +

Types

+ +

Naming

+ +All type names shall be lowercase with underscores between words and +"_t" appended to the end of the name ("this_type_t", "that_type_t", +etc.) + +

Documentation

+ +Each type shall have a comment block immediately before the typedef: + +
    +
    +/*
    + * This type is for CUPS foobar options.
    + */
    +typedef int cups_this_type_t;
    +
    +
+ +

Structures

+ +

Naming

+ +All structure names shall be lowercase with underscores between words and +"_str" appended to the end of the name ("this_struct_str", "that_struct_str", +etc.) + +

Documentation

+ +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: + +
    +
    +/*
    + * This structure is for CUPS foobar options.
    + */
    +struct cups_this_struct_str
    +{
    +  int this_member;   /* Current state for this */
    +  int that_member;   /* Current state for that */
    +};
    +
    +
+ +

Classes

+ +

Naming

+ +All class names shall be lowercase with underscores between words +("this_class", "that_class", etc.) + +

Documentation

+ +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: + +
    +
    +/*
    + * This class is for CUPS foobar options.
    + */
    +class cups_this_class
    +{
    +  int this_member;   /* Current state for this */
    +  int that_member;   /* Current state for that */
    +};
    +
    +
+ +

Constants

+ +

Naming

+ +All constant names shall be uppercase with underscored between words +("THIS_CONSTANT", "THAT_CONSTANT", etc.) Constants defined for the CUPS +interface library must begin with an uppercase prefix +("CUPS_THIS_CONSTANT", "CUPS_THAT_CONSTANT", etc.) + +

Typed enumerations shall be used whenever possible to allow for type +checking by the compiler. + +

Documentation

+ +Comment blocks shall immediately follow each constant: + +
    +
    +enum
    +{
    +  CUPS_THIS_TRAY,   /* This tray */
    +  CUPS_THAT_TRAY    /* That tray */
    +};
    +
    +
+ +

Code

+ +

Documentation

+ +All source code shall utilize block comments within functions to describe +the operations being performed by a group of statements: + +
    +
    +/*
    + * Clear the state array before we begin...
    + */
    +
    +for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
    +  array[i] = STATE_IDLE;
    +
    +/*
    + * Wait for state changes...
    + */
    +
    +do
    +{
    +  for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
    +    if (array[i] != STATE_IDLE)
    +      break;
    +
    +  if (i == (sizeof(array) / sizeof(array[0])))
    +    sleep(1);
    +} while (i == (sizeof(array) / sizeof(array[0])));
    +
    +
+ +

Style

+ +

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: + +
    +
    +{
    +  int i; /* Looping var */
    +
    + /*
    +  * Process foobar values from 0 to 999...
    +  */
    +
    +  for (i = 0; i < 1000; i ++)
    +  {
    +    do_this(i);
    +    do_that(i);
    +  }
    +}
    +
    +
+ +Single-line statements following "do", "else", "for", "if", and "while" +shall be indented 2 spaces as well. Blocks of code in a "switch" block +shall be indented 4 spaces after each "case" and "default" case: + +
    +
    +switch (array[i])
    +{
    +  case STATE_IDLE :
    +      do_this(i);
    +      do_that(i);
    +      break;
    +  default :
    +      do_nothing(i);
    +      break;
    +}
    +
    +
+ +

Spacing

+ +A space shall follow each reserved word ("if", "while", etc.) Spaces shall +not be inserted between a function name and the arguments in parenthesis. + +

Return Values

+ +Parenthesis shall surround values returned from a function using "return": + +
    +
    +return (STATE_IDLE);
    +
    +
+ +

Loops

+ +Whenever convenient loops should count downward to zero to improve program +performance: + +
    +
    +for (i = sizeof(array) / sizeof(array[0]) - 1; i >= 0; i --)
    +  array[i] = STATE_IDLE;
    +
    +
+ +

Software Trouble Report Form

+ +
+ + + + + + + + + + + + + + + + + + + +
Summary of Problem:________________________________________
Problem Severity:__1=RFE +
__2=Documentation-Error +
__3=Unable-to-Print-a-File +
__4=Unable-to-Print-to-a-Printer +
__5=Unable-to-Print-at-All
Problem Scope:__1=Machine __2=Operating-System __3=All
Detailed Description of Problem:________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________
+ + + diff --git a/doc/cups.css b/doc/cups.css new file mode 100644 index 0000000000..9285a5b5ee --- /dev/null +++ b/doc/cups.css @@ -0,0 +1,4 @@ +H1 { font-family: sans-serif } +H2 { font-family: sans-serif } +TH { text-align: left } + diff --git a/doc/cupsdoc.css b/doc/cupsdoc.css new file mode 100644 index 0000000000..333f20144d --- /dev/null +++ b/doc/cupsdoc.css @@ -0,0 +1,9 @@ +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 } +SUP { font-family: sans-serif; font-size: 6pt } +PRE { margin-left: 2em } +CODE { font-weight: bold } diff --git a/doc/documentation.html b/doc/documentation.html new file mode 100644 index 0000000000..bace114408 --- /dev/null +++ b/doc/documentation.html @@ -0,0 +1,85 @@ + + + Documentation - Common UNIX Printing System + + + Easy Software Products Home Page + Do Administration Tasks + Manage Printer Classes Status + On-Line Help + Manage Jobs + Manage Printers + Download the Current CUPS Software + + + + +
+Common UNIX Printing System +
+ +

Documentation

+ +The following documentation for CUPS is available on this server: + +
    + +
  • Whitepaper - An Overview of the Common UNIX Printing System ( + HTML | + PDF ) + +
  • Software Users Manual ( + HTML | + PDF ) + +
  • Software Administrators Manual ( + HTML | + PDF ) + +
  • Software Programmers Manual ( + HTML | + PDF ) + +
  • Configuration Management Plan ( + HTML | + PDF ) + +
  • CUPS Implementation of IPP ( + HTML | + PDF ) + +
  • Interface Design Description ( + HTML | + PDF ) + +
  • Software Design Description ( + HTML | + PDF ) + +
  • Software Performance Specification ( + HTML | + PDF ) + +
  • Software Version Description ( + HTML | + PDF ) + +
  • Software Security Report ( + HTML | + PDF ) + +
  • Software Translation Guide ( + HTML | + PDF ) + +
+ +
+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property of Easy Software +Products. CUPS is copyright 1997-2002 by Easy Software Products, +All Rights Reserved. + + + diff --git a/doc/figures.sc b/doc/figures.sc new file mode 100644 index 0000000000000000000000000000000000000000..f51e814a63256737793741a4c9ffcd0c294da8b8 GIT binary patch literal 75144 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 + + Documentation CUPS (Common UNIX Printing System) + + + Page d'accueil Easy Software Products + Accès aux tâches d'administration + Administrer l'état des classes d'imprimantes + Aide électronique en ligne + Administrer les travaux d'impression + Administrer les imprimantes + Télécharger la dernière version du logiciel CUPS + + + + +

+CUPS (Common UNIX Printing System) +
+ +

Documentation

+ +La documentation CUPS suivante est disponible sur ce serveur: + +
    + +
  • Aperçu du logiciel CUPS - Common UNIX Printing System (français) ( + HTML | + PDF ) + +
  • Manuel de l'utilisateur (français) ( + HTML | + PDF ) + +
  • Manuel de l'administrateur (français) ( + HTML | + PDF ) + +
  • Manuel du programmeur (anglais) ( + HTML | + PDF ) + +
  • Plan d'organisation de la configuration (anglais) ( + HTML | + PDF ) + +
  • Implémentation du protocole IPP (Internet Printing Protocol) dans CUPS (anglais) ( + HTML | + PDF ) + +
  • Description de conception de l'interface (anglais) ( + HTML | + PDF ) + +
  • Description de conception logicielle (anglais) ( + HTML | + PDF ) + +
  • Spécification des capacités du logiciel (anglais) ( + HTML | + PDF ) + +
  • Description de la version du logiciel (anglais) ( + HTML | + PDF ) + +
  • Rapport de sécurité du logiciel (anglais) ( + HTML | + PDF ) + +
+ +
+ +

Common UNIX Printing System, CUPS, et le logo CUPS sont des marques déposées +appartenant à Easy Software +Products. CUPS copyright 1997-2002 Easy Software Products, +Tous droits réservés. + + + diff --git a/doc/fr/glossary.shtml b/doc/fr/glossary.shtml new file mode 100644 index 0000000000..2cc0c1c893 --- /dev/null +++ b/doc/fr/glossary.shtml @@ -0,0 +1,73 @@ +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Page Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
diff --git a/doc/fr/images/accept-jobs.gif b/doc/fr/images/accept-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..99a4446e88b35f4227a46634ab13e68f5fb7b58c GIT binary patch literal 295 zc-jFc0oeXWNk%w1VRHZ!0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0CNBo z000B@2)ZFdCCW*wy*TU5CmBMpjLguTXsWK$Ad-N=&U8H+q-^heU*U>?Z%DMgOqoM5 zqC_>9oB=?XEIfx-P8OPJXq4H5cp|=*CE(`SI%ZnQV=%M*cF&*qy4~Wa?(=$TXmfUg zgfNUBB5Ex~2l@z6lhN+vDaHg51e`s42AEcanyIxZ)O-GNL;$? tMN(7l?eab^G4i$aJU|ON`v3c2Oj!r8UglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0Ac_X z000Bp2)ZFdCCW*wy*TSlh6qc@3|ncQC^~>5V5D#?qlWm-c&-<<670YribcvCD92M0 zw-ibSfS<9@OjTo7XG3#rE)QVIml`IIui$YcJt?ofZi{2O7T53UWFBp&-u-}jczqTR zbbx_F*aSE$j}L@aY{NEeQZSv6OR) literal 0 Hc-jL100001 diff --git a/doc/fr/images/add-printer.gif b/doc/fr/images/add-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..0369a0e55bfdd40328d43c8d8d300773fbff1c34 GIT binary patch literal 307 zc-jFo0nGkKNk%w1VR--)0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0C@lu z000C22)ZFdCCW*wy*TU5GZ{j#jLguTXsWK+Ad-N=&U9@{1}Wcs?_W7Z;72U>UZ%`} zvOG1Nv}g1*01TA{X-aGSaWf6gQu;iYCFSf{oz^zTk#;*9r`zLe`r7=?TO3$*f@ybe zf_8p`V{mGUj%S9Bh=*Sh4}pc0nv;VTk)LRrpiH8h76cF&e0h$e*La!?V%Fnb*O8SDwFRevo*0gx$7_!^gL9gnPRa zB1uqP8`6w?j@%tC(0h|zI!H$6ljT9Ua0A9j}HC(`8=pYruiyJg9fM7yGF&G#U0|Np800384LI3~%EC2ui0Av6Z z000Bs2)ZFdCCW*wy*TR~$q>OJG6QFxXvz)Y2pDQC&!#cLbgt{R670aBs#VGyfJanv zmt0Z?fS?4#s&{7q literal 0 Hc-jL100001 diff --git a/doc/fr/images/cancel-jobs.gif b/doc/fr/images/cancel-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..6a0825e64c9e1678ab3ebfe763e37b035294df9d GIT binary patch literal 281 zc-jFO0p|WkNk%w1VQc^t0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui0Bish z000B#2)ZFdCCW*wy*TTg$q>OJG6QFxXsSv>I0D8h&$MccajoyXbSr_La42(?G6!A~ zwIrSffFQEaq*Xar=cb`aR=rKIBpeAJ$lo({O;wl2V>f&K#W<$#@^Zh=v-^2+aBY5o ze}iO)7!P=JiI0edeiMe2k`#t!8Uzp+XP<+LqJW=nS)y%nUX-AYahpdLSDBZPbD@^5 zl8K{%86TdQwULCqx5T=WwrX`3Ai=q|j;qtWthb=nseh}@79p`(;^PreQRL|2E->ls fJwFRM?(-|~A_3v_`itu?Q4XEh0fMCo*G0Yee%mV_<007KaLI3~%EC2ui06zc} z000A_2)ZFdCCW*wy_O6SmS+PdjwCj8A7GShTN>Z$&NKxpL9Od(C>}csur>hXeuZH$ zxoeDoO6EZcrAmg>>6LkLAR}2Y7%MK5&C$x^%Wa>zR`|AkAwV$G{9JCHWAkryJ{D<6wuO0!Tu{0+s Ov<`Q-BN`kj2>?5!M^eE6 literal 0 Hc-jL100001 diff --git a/doc/fr/images/config-printer.gif b/doc/fr/images/config-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..7e09990fec55f70380c07fe7919e253e24d88fe5 GIT binary patch literal 334 zc-jF@0kQr^Nk%w1VT%A10KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0E++= z000C22)ZFdCCW*wy*TU5dnbbsEF?2{XsWJkTMT0f7;bIfxMq}e?*Bm5P7w$ik4Q@F zggH15s%H|~qSmaN0if8NU^m~SSQE}Px)*5#>Rh+2@3n-=cEbx_I$kbs_xF2xbAEwz zergvEXcc#Of{$)|fQNID6o!tIkDHl-ntYyR5f6)(m4K6=r;UxNjH<4&kf^J*sGoqZorCCzW!r4^?DT#1KR{LCcmg?-VlR5Mu^JLI@X59I_ms g$Hb2yD{v$c;9$s;V_?W2>0lSimpDL(kdXiYJGgwEKmY&$ literal 0 Hc-jL100001 diff --git a/doc/fr/images/continue.gif b/doc/fr/images/continue.gif new file mode 100644 index 0000000000000000000000000000000000000000..09a0dd48bc7977be013981b076f1a64a2dc15397 GIT binary patch literal 229 zc-jHw02=>CNk%w1VMzcK0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui07(E8 z000BB2)ZFdCCW*wz4($L!urgRjbv#Sg9ie}>AtT4ws37@vJ%{UFR3ETVR(2I3rF8& z0N4p9$x>8_X*@4PNpTp-9=FM`mfJ;Q9M_5%`7N8-?zMbMd88?FZQT9N?=u7tSc89k zg>7*}h!`7pPg9fM7yGF&G#U0|Np800384LI3~%EC2ui0CE5n z000B>2)ZFdCCW*wy*TU5B^g4njLguTXsWK#Ad-N=&UDQhq-^hePvMGyZ%C}YOqYZ5 z;A0jG&gTFiOirRt9=6!PY$H)8Qz;pTp=h-DN(QIdXK-82hG!g^xqIIhuc3crf_rIt zgn?yzif>;n5E^rFl8KCqe}xubnuMH{7X*(Rm!pTJn1xH1R~2DPWmu7^7$07%o|B8G zh!l;Ro|Kf06(F_2bbx%jy1A;r%Dc}PA$hK^n32e)&)AvVfMdtu-x(rEGrn2r8B r=<4tkFEKRl@$o<{)i%EeM literal 0 Hc-jL100001 diff --git a/doc/fr/images/delete-printer.gif b/doc/fr/images/delete-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..7a358d0dbcaa5bfa1dd38cd355d2bb28442ed2af GIT binary patch literal 330 zc-jF<0k!@|Nk%w1VTk|~0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui0Eqw; z000C22)ZFdCCW*wy*TU5`zC`BEF?2{XsWI(JB%e@v~+FXol(ws@Bb{FA^mv`&vwYwef&-rL{P8kjv zbb57riGpx>ifWE_hlr4Uj*O3fi(i>Ig*oRXBStg4->o)rWT9HykP zy03wQv#zqZ!M>xtlN2Cjce%{Pz^RC^yt~fRsj?X%%D{n}*Qml4tKF~G;o#8~B8I+= ztfGq4*YFkNc%$ZPkj=eg081^rhyhcNpoc74Y6vu_VIV^aFl1OM_>fCQ3_=$0xX2js cVnz}H0CpUCh0fMCo*G0Yee%mV_<007KaLI3~%EC2ui0ABzU z000Bp2)ZFdCCW*wy*O)3h6qc@3|ncQXgPo)V5D#?mxlPxc#hXfp#MM=i)1+%jhO>V ziDCYjPRan_yF{ZDEKaNAMjFkD^B5r)%;)pCoR*N4P$YY3MpUS^nNTsK$Z?Y61L_yfuQa#$;+AJ>K;yOGFH{<9iF*XRE$j}P@aP>MEeQZSf>L&n literal 0 Hc-jL100001 diff --git a/doc/fr/images/manage-classes.gif b/doc/fr/images/manage-classes.gif new file mode 100644 index 0000000000000000000000000000000000000000..30ead441eb1771da04693d343ce2878ef43d61da GIT binary patch literal 312 zc-jFt0muGFNk%w1VSWG<0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0Db@z z000C22)ZFdCCW*wy*TU5dm)1mEF?2{XsWI(HjE`;v~+FXl2Oih@BbK`A^L zfMG717bi}7oD2ZOCv~#Db!p#fL&Mx2$`N!y>MXM*=X6|ses}9|cwEn=;`ta3Pic8; zZEkCXhKg;Ba*BzI6mOA~jg^p>VFeF^k)N85prVD8m=$-ZkgKDg7z7Yab*7=GmVl>* ze_yF`dyo86!$n`uiSNSo{D3UVtG(puvDb7VtR8ut-7@0rEARNaIBehz?>=+^7Zt Kgoqdk0028p506Fw literal 0 Hc-jL100001 diff --git a/doc/fr/images/manage-jobs.gif b/doc/fr/images/manage-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..c968698d5f55187fae806652b11b29247c467319 GIT binary patch literal 316 zc-jFx0mJ@BNk%w1VSWG<0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0Db@z z000C22)ZFdCCW*wy*TU5dm)1mEF?2{XsWI(HjE`;v~+FXl2Oih@BbK`A^L zfMG717w1ZP)C>T`Cv~#Dbv@szrJ-SN59Ua^Aa$DC60};rM#HIgww^6l$K!o_dUzNP zPkxAfbaiuyj(duKd=+kPl5m2Sk6{rHhnbg~h>)X?pn_bbp{k^#ffoc2O?H^AnwqVX zrnI=JsI-50d8fJglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0F?j~ z000C22)ZFdCCW*wy*TU5yT`;J1WU;bU#hNb>rMk{0>*3Kc>Wn?t^dHFji(3*kI1A( zhRPf;Pbc&eT~)2OYia;6O0^QOO{~n3I}OcKdss)@g=%yy56|22d>sGQhx>DXe0gw% z6K!>Th;M^?84gl?l8SVCcaxZwfs#DlBRwY50QR#sGF{&nXRXXnWVV4 z6}hOrAP`W9uCKbYgSf)Af5f!Suy%^ecZ-Y}Ayc-_#jzC6%Bj-Dz23as;Mo=;*x`=M z<=e}??6BVMr|;V55+m#PhW5tfz+p5j8@YD*khzI9?a-M5B$||&*pH$IE?q2Y?6xQI rgA5uSH$Dt0fye?MBvYy^V6sF2i7R84i7~^a17I?9;s`NfMgjmk%NeIk literal 0 Hc-jL100001 diff --git a/doc/fr/images/modify-class.gif b/doc/fr/images/modify-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..2774a6532358bfc934bd8ffc949ce17f5e32908f GIT binary patch literal 282 zc-jFP0pglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0A~Oc z000B$2)ZFdCCW*wy*TSl$q>OJG6QFxXo?Qu2pDQCuObgu7_tpvQFP}M3~4o42M zuw)*ZGw84|001vfN_Hca(!9e4W-B2-q1h$!%q*MR+INKQo{*hjiDL|JtIKn9e{h3@ zUQL6DfrN{S7Y}@jg_DhymRc2ui-2~V76cGjfr*@sqmn0*-^w7r{&r?;x5#g?bQ6d=Qncy?>dZqjkmY-+C5u>~PUQ{&_lRaWKcglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0Db@z z000C22)ZFdCCW*wy*TU5dm)1mEF?2{XsWI(HjE`;v~+FXl2Oih@BbK`A^3Q;pOK2EpcDiUUYD}0 zsFZ}NuBgDPfx5hF6(EU=!L7Tm&cC_L!oSTMA<41QnAMHG+|k^y-OLsu*o}pFa?pXW zVC;VA)9LG}ycr`(Wk-hl76U{4@e}9)h75v0`XMYJWC4$b5cf4C5kOzWi#T4ypy&#~ O7RHYrK!}Ku00296VU%MR- z&vb3yc&_h!@BhG{a7gSS3WNb=$utB$&?tyRB?Ye6qIS#edcWYXcuX!25sBuqfswkW z)%XER&zkS}ynfH``~O1)4{AuqNAjx zrlgh=4ViG8C7p_&vY@B6wzs&sx;KLpZHKN_uywP=w7ba3%FE1r1r<`kAq@}J!*s^k z$IXvO1PI*W;^Sgz2EQ9r4J`#13I!?zSOhBt4%(jz`uaBs3nniF2&l1u-iv};2rLjI zZ-W4EClHcSuwZ}+fh-gX5dfu@Mk4+aZ++}BvPDRf245gBuqwl*2QB0&fT$wDm6RzE z7~98_pACu&;JLs^Lx9ksM_CXhXt2OQFba(VKrmpzQvfF^A;orks%2@Hk~^HjVCy1livbpbfdw!}5j_L~t~>-#fL7s8dj~Y=*^_}|8wD2lyQ-A3 z7q>I)ehFaNpHR(_s`|s}0&Wn~rcg`5oKUSE(D9@lpjV(1IJ~kF6iCp(!3o8(elu3! zxVQt~HL3#O7>{BA0z{2gML6B!38_v2XRy9psLg+SZE`LkmpK3eKouC|s9>Pn6Ac4! z&(5);4uv#N05&KQeFpU?6#f9z05p9Uz+UhTn1X=_>cAORlzpXNeFKc-pM4~`2EbPc zJO}_@84Q*k3j6(r$zU5cC{+Sim59Sg(q%wTbth!!9Ct=3L=SckIfnoO&ZTrAfY$ogPWR4z8m8bRPT$SMBMR}Q#Flmo%!C4LDYTOa9q=u(&Q!n^W8DM$?6psE zjvXiGaW*`tBZ*xSkYq&i`PUwFl0`&MR26cx7ebL$SQR`;B4O2ok*Vh&IP4AdQB-x=l#R0Xc2KF6+#LPD;};-fD`Fi z6hUOwsaSp8KZQOqs8|Yh%HLl%$rFIPq_uzm6`lC{+b2mK z@jyO8?ehRQ1i(4x$8^#V8Gly=22oVu>KE?`?Frf~f-PgUW3>RpOq4|s2zSCK=M_+ zbgA6k>M~yb5Ow&};wXf0P2?=hLO@dI=|lR2Ag3Pk47Ab;`p+)MzTD;mk4^h>IbZbD z&<;z~-$Ick6?sWV8(lQtD*zt0*0~3G(t{@dfH&S4fr^51j>EnKTpZ=MpjdDx+n`r% zQx=jw2X3!cNFi+;!YA>vu3mud-C%}VynK8BHQNA#WzuJuW+rIC-b11J5&Ny~5ePDuL09a+wjITmH$ zbTdE=X3XNp$pw-guu|q6VNe)s-~&Ds+=nTN;}}FbU@sd~-6a?L!4=R-XW)3<*ZyuN zyHUOpf8QWq7}?jLbNcLnC>Wk7F{u(|y^4fb=_qZEqPzkv z2hSS7g?==lNVF`sso1uyD^;--vZgh+6MC~-Gz-i%+t^A$BB->eOeb$2{+BhDk+d{m zjSS2ncNL1%ZlYDw8$H6;HS2KhLvF=~KE_8P$8cvs$5GdD{L0>H%)m1%h!+ck)g_8L z)uNQeUsc*e5mOp5B)JWiw&K^aOL?omLX~O`Dpj9u23Q|m8ejv240~$%@Mke3^ za;lJA&n%~}$dJ7Yt%jT>8G|0y!yr@<$PrjYlb#ZW&s+@?pf}|HL6!Ed8W%&1N7v0dhmj|govWS0v$wNdO?NG$(yMZYHPuBnQLvDK)wO#QTt%h2o&|9 zKhz>WqiNPMtdT$nwAN)}snRMDQlDwkYi7OqD5;KVp!LI3O$&t6ji$+@0mBxj2w(s# zeRCdj5I24H)Y{wD^$-sSYirZR&zl~049vlj;k?OXl&mD289L{B)0rIj&bPjyyYCy& zWwc#*1_c-cCkDh@-t)esy%&D(emnf(+)xd~S8%Jd*aXEv=*7SbesDP@JkAUcdBZ18 z@{*^;hpA6K}@XFhV2+x+G@&p7}IVE{Wy#$4t!54z5WPV}NfTo62$ vfWbZfa}Ngn>2o%^)Td5$WS}AGOIV}>Vh;7L*SqRq54+eOafBogA_4$AjX7Kf literal 0 Hc-jL100001 diff --git a/doc/fr/images/print-test-page.gif b/doc/fr/images/print-test-page.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd214cf7852c9b6cff21277fcea285b2358c2e71 GIT binary patch literal 316 zc-jFx0mJ@BNk%w1VR!%(0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0C)ft z000C22)ZFdCCW*wy*TU5F&RRzjLguTXsWK*Ad-N=&U9@@1}Wcs?^`)V;72U-UM9s!_G<|K~TO440dUbnY zYIKNpWP)#pi-c-*af+0VEf80gnwx~1ZIY9ep`V|lk62t21ei*mqLG${d8wsxuzh)> zwtS)%AAz00!m+)@ug8*+t)Oql6Cl8`mci4?ytk0ZrmoBsAPpK7@dg0028!DUvw= literal 0 Hc-jL100001 diff --git a/doc/fr/images/reject-jobs.gif b/doc/fr/images/reject-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..39ee3092f76a6f54427f188d71401825be6f0cdd GIT binary patch literal 281 zc-jFO0p|WkNk%w1VP^mo0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0A~Oc z000B#2)ZFdCCW*wy*TSl$q>OJG6QFxXo?Qu2pDQCuObgu7_tpvQFP}M3~4oGC? zfMKGX!xaE{fflSM>_!{iG@27=QX*Df&Ep8uI$o>IS27tcj>|6&@V##5JN;UJe|v;# zhKGX~4^2sYeTR>BkrauPkb#$T8UzqkcV}sWp>LxVm7sNOrIK(L9(stTkcDAKnVF82 ziChvNu#>xmezvTilEr;)#uOmGWw~^s%WubR%hqRcY#1R%GrV2l69Ydv;Ns#fFW>0x f6+R0%?(;J6A_3m?`Wh@Q_YR%*3G@KMMFIdjoi=*P literal 0 Hc-jL100001 diff --git a/doc/fr/images/release-job.gif b/doc/fr/images/release-job.gif new file mode 100644 index 0000000000000000000000000000000000000000..59e9c63476cbd1947312f1bad660ab6b251d7113 GIT binary patch literal 271 zc-jFE0r37uNk%w1VP60g0KxzO%*>g9%wR&yF&NAe1Iz*d%m7!+LI3~%EC2ui0ABzU z000Br2)ZFdCCW*wy*O)3h6qc@3|ncQXgPo)V5D#?mxlPxc#hXfp#MM=ixfNrkCp+z zcQI0&&Pr4^%|S5@Om(sacC8qPRvIxLrst@+e3q=;?RVNuXRFJY$N0&{7w&&oerKqZ1Q1PRi;Q)El#*SFTY`-pdt8ZjglcJupp$`wh-h<{NdljhvW2LJrL}+S V0n6+0N#ZR_4v_Nd9UmglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0C)ft z000C22)ZFdCCW*wy*TU5F&RRzjLguTXsWK*Ad-N=&U9@@1}Wcs?^`)V;72U-UMAzg z$V?3Y!^>eh?JOnNrX_2;aw!cA_bb(M$X$#>JjqhqOLsLAr^DTax_6%MW2<#}e0X$& zb{7w9SciUljE;bhg_C}bWR8_yi$g+-L^j KLkJiN00295=91L_ literal 0 Hc-jL100001 diff --git a/doc/fr/images/show-active.gif b/doc/fr/images/show-active.gif new file mode 100644 index 0000000000000000000000000000000000000000..36388e72ad9dec34e5584cca5193a2472dcb7081 GIT binary patch literal 302 zc-jFj0nz?PNk%w1VRrx&0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0CxZs z000B~2)ZFdCCW*wy*TU5FBw9xjLguTXsWK)Ad-N=&U9@T1}Wcs?^iiR;72UpUM9CA#`Fzb)&5A7t_d4xmC%uV686S5x06CPsiu&id=1%zx!hn4rX+0 zbW>l5cZ+9+jE9R{kdKaQjusDuk&Tv2k&>5*n|vCblcpXJgn5)>rfz3#dyQ;?u%E4@ z7$2pVp_HD#qqLotqQIxYm;xJO$$F!otd(`X&cMdG7a`4hcGTY1X|#24wT9Dt=6mPG zfe|7}VDt1XLiPCh1urrB{zgF-?D$8}M!*pPglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0FnR{ z000C22)ZFdCCW*wy*TU5yRXC`1WU;bU#hNb>lOoP0>*3Kc+MGSt^dGai>C+(kI3Xj zhEh78lLJQD832qIszh7icA-hGIGSoqDPB(+tXoIi9Y;nhKG5HVx^(}xZ~uLFcw=aO zTZVawiiwDHhIUktQE)I2XLy*3k!hQmk${4snSh$0dwhAHrI@O#a0HfFq@s&twVF zBO6}9(&2>Uo%QzKn&{x^{1zmdT$)6yP%}T_0__u*OW`4Tr)D+UR0o5VD{L~dprj>3 p1`UlM)i@!tz(>fFvXYQ25kMfymr7#HVCf(h%$qhsjF^!C06P*Mq$vOZ literal 0 Hc-jL100001 diff --git a/doc/fr/images/start-class.gif b/doc/fr/images/start-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca6cfc89042d45e3f539d7677592c7e487d1e085 GIT binary patch literal 282 zc-jFP0pglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0Bryi z000B$2)ZFdCCW*wy*TTw$q>OJG6QFxXsS*_I0D8h&-7}HajozCbSr_La5!_7RtKW8 zHUI=KhiJ5tT&Akl1_oQ;T9My^V@ttGCCMuH97%WI-Dw*>VbksL`dWT@kn3}SQ-gtU za))SbUU!0thK-CD1Q1YVg=&z1k&%mZj+$PfpA{Z|j#7w^im7*~g_^Lgih5|W79XaW zrz$oozA|?yci)zRJNg9%wR&yF&NAe1Iz*d%m7!+LI3~%EC2ui0E7S( z000C22)ZFdCCW*wy*TU5yCs7VEF?2{XsWKPH;g4}U&nR=oLFP)X?}E0BjWq9adp#eX=l^_Ncz%9w zdv|kna2OA56NP_Rl6G-&iIkXom6CXtnT4E@o1mD06$B7fZh)kwnU$=ikFTP%wUC>+ zu@@kYql>MUim+G1S+tPJ$cDzZ#f$>Jwz|r@uGhD=)vbc1!E00&WyH(7-QKd)pW5Z; z?&udIOIgp4huV|pdit~3f#m*#@fo#`(GWCF)F7MyL&icQ3Lgqtz~iBhhzKW=2rv@Q WqDLPuVr+Df>Z8dNAVkDS002A8Vw!&d literal 0 Hc-jL100001 diff --git a/doc/fr/images/stop-class.gif b/doc/fr/images/stop-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..828b98a51f18769ab8ff5405d9cc0b057885e7de GIT binary patch literal 260 zc-jF30sH<(Nk%w1VPF6h0KxzO%*>h0fMCo*G0Yee%mV_<007KaLI3~%EC2ui0AK(V z000Bg2)ZFdCCW*wy*TSkh6qc@3|ncQs5yWlV5D#?n}+z#c%Iivp#Q)Wiv&CbkC*|# zr!kg{&O&rHMMfG;X{@@nQXJVSRO>vLBj)lMt)-+T(KlR7=T07(_#9n^v)gTJ6MBJu zg@=R|1P~aBj)r}Ic3hNyhL?5`9eHVwd~#}_7L}iIbaQeR9*u66iI5eOv97IymKh(c zwt$|IhqZ{X!MqqCM6?6iuy2L{ literal 0 Hc-jL100001 diff --git a/doc/fr/images/stop-printer.gif b/doc/fr/images/stop-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..24c5b1e7be4663a84ed390d8bce542a0f8785aa4 GIT binary patch literal 307 zc-jFo0nGkKNk%w1VRrx&0KxzO%*>h0fMCo*G0Yee%mV_<007KaLI3~%EC2ui0CxZs z000C22)ZFdCCW*wy*TU5FBw9xjLguTXsWK)Ad-N=&U9@T1}Wcs?^iiR;72UpUMAkb z$fOMbL(P)2oEEGdtV+w`W*XA#%GB-r6 zbmGwIY?bT8LS;Q?_!ciQ`!@RiNeHrFhrlrhGY}jRpj^U-GhD!6=-?B?iy1zIfROYk literal 0 Hc-jL100001 diff --git a/doc/fr/index.html b/doc/fr/index.html new file mode 100644 index 0000000000..17d4ffdcf3 --- /dev/null +++ b/doc/fr/index.html @@ -0,0 +1,36 @@ + + + CUPS (Common UNIX Printing System) + + + Page d'accueil Easy Software Products + Tâches d'administration + Etat des classes d'imprimantes + Aide électronique en ligne + Etat des travaux d'impression + Etat des imprimantes + Télécharger la dernière version du logiciel CUPS + + + + +
+CUPS (Common UNIX Printing System) +
+ +

Tâches d'administration

+

Administrer les classes d'imprimantes

+

Aide électronique en ligne

+

Administrer les travaux d'impression

+

Administrer les imprimantes

+

Télécharger la dernière version du logiciel CUPS

+ +
+

Common UNIX Printing System, CUPS, et le logo CUPS sont des marques déposées +appartenant à Easy Software +Products. CUPS copyright 1997-2002 Easy Software Products, +Tous droits réservés. + + + + diff --git a/doc/fr/overview.html b/doc/fr/overview.html new file mode 100644 index 0000000000..ca80a45d22 --- /dev/null +++ b/doc/fr/overview.html @@ -0,0 +1,503 @@ + + + + + Un aperçu de CUPS (Common UNIX Printing System) + + + + + + + + +

Un aperçu de CUPS
+ (Common UNIX Printing System),
+ Version 1.1

+ +

July 10, 2000
+ Michael Sweet, Easy Software Products
+ Copyright 1998-2002, All Rights Reserved.

+

Traduction française - 27/06/2002 : Marian REYT-LLABRES (mrl21_pub at netcourrier.com).

+
+ +

Ce document décrit le logiciel CUPSTM (Common UNIX Printing +SystemTM), un système d'impression portable et extensible pour UNIX®. +CUPS est développé par +Easy Software Products, un éditeur logiciel +implanté à Hollywood, Maryland qui vend des logiciels commerciaux pour UNIX depuis 1993 +par le biais de plus de 40 distributeurs répartis dans plus de 80 pays de par le monde. + +

Des informations supplémentaires sur CUPS sont disponibles sur le Web à l'adresse "http://www.cups.org". + +

Avant-propos

+ +


Note du traducteur : Amies lectrices, amis lecteurs, j'ai fait le choix de ne pas traduire l'expression anglaise "default" par la +version française +habituellent utilisée "par défaut" que l'on doit, entre autres, à la documentation d'un célèbre système d'exploitation "ouvert à tous vents". +

+En effet, l'expression "par défaut" est normalement utilisée en mathématiques (arrondi "par défaut" ou "par excès", +personnellement je cherche encore mon "imprimante par excès" !) +mais elle est abusivement employée en informatique pour signifier "donnée/comportement qui s'applique si l'on n'en +précise pas explicitement la valeur/nature/teneur". +

+Or la langue française possède justement un mot pout exprimer ce concept +: "implicite" (Larousse 1998 : "Qui est contenu dans une proposition sans être exprimé en termes précis formels; qui est la +conséquence nécessaire."). Dans la mesure du possible, j'utiliserai +cet adjectif sauf dans les cas où son emploi n'est pas suffisamment explicite (sic !). Je lui +préfèrerai alors l'expression "... de base ..." ou l'adjectif "standard". +

+Ce choix est totalement personnel et le fait que j'ai fait l'effort (non négligeable) de traduire ces lignes pour vos yeux délicats suffit à le justifier! Si, par malheur, ma prose vous est insupportable, +je ne vous empêche aucunement de vous reporter à la version originale où vous retrouverez "default" entouré de tout le +reste... en anglais, bien sûr. Enfin, si vous avez une meilleure traduction, je suis preneur ! +

+Malgré les très nombreuses relectures et corrections, certaines fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les signaler afin de contribuer à +l'amélioration constante de la qualité du présent manuel. +

+Bonne lecture ! +

+ + +

+Historiquement, l'impression sous UNIX a toujours été réalisée en utilisant +un des deux systèmes d'impression - le Berkeley Line Printer Daemon ("LPD") [RFC1179] +et l'AT&T Line Printer. Ces systèmes d'impression ont été conçus dans les années 70 pour +imprimer du texte sur des imprimantes matricielles à aiguilles; les constructeurs ont +depuis ajouté divers systèmes de pilotage sur bien d'autres types d'imprimantes. + +

+Des remplaçants pour ces systèmes d'impression ont émergé [LPRng, +Palladin, PLP], cependant aucun d'eux n'a fondamentalement changé les capacités de ces systèmes historiques. + +

+Au cours des dernières années, plusieurs tentatives de développement +d'une interface d'impression standard ont été faites, celles-ci incluant le projet +de standard d'impression POSIX développé par l'IEEE (Institute of Electrical and Electronics +Engineers, Inc.) [IEEE-1387.4] ainsi que le protocole IPP (Internet Printing +Protocol) développé par l'IETF (Internet Engineering Task Force) par le biais du PWG +(Printer Working Group) [IETF-IPP]. Le standard d'impression POSIX définit un ensemble commun +d'outils en ligne de commande ainsi qu'une interface C pour l'administration des +imprimantes et des travaux d'impression, mais il a été abandonné par l'IEEE. + +

Le protocole IPP définit des extensions au protocole HTTP 1.1 (Hypertext Transport Protocol) +[RFC2616] afin de fournir le support pour un service d'impression à distance. +IPP/1.0 a été accepté par l'IETF comme une RFC (Request For Comments - Requête pour commentaires ) +expérimentale en octobre 1999. Depuis lors, le PWG (Printing Working Group) a développé un jeu +de spécifications mises à jour pour IPP/1.1 qui a été accepté par l'IETF et attendent leur publication +en tant que proposition de standard. Contrairement au système d'impression POSIX, IPP enthousiasme les +acteurs de l'industrie et est en passe de devenir la solution standard d'impression via réseau pour tous +les systèmes d'exploitation. + +

CUPS utilise le protocole IPP/1.1 pour fournir un système d'impression complet et moderne +pour UNIX qui peut être étendu pour prendre en charge d'autres imprimantes, périphériques et protocoles tout +en fournissant une compatibilité avec les applications UNIX existantes. CUPS est un logiciel libre distribué +conformément aux termes de la licence GPL (General Public License). + +

Historique

+ + +

La première version de production de CUPS (basée sur le protocole IPP/1.0) a été réalisée +en octobre 1999. Depuis ce jour, nous avons réalisé diverses mises à jour du produit original CUPS 1.0 qui +concernaient la sécurité, la portabilité et des corrections de bogues, mais aucune nouvelle fonctionnalité n'a été +ajoutée, ceci afin de garantir la stabilité du code de CUPS + +

CUPS 1.1 est basé sur IPP/1.1 et ajoute nombre des améliorations fonctionnelles qui ont été demandées +par les utilsateurs. Comme pour la version 1.0, CUPS 1.1 sera suivie de mises à jour qui résoudront tout +problème découvert sur le logiciel, mais elles n'ajouteront aucune nouvelle fonctionnalité. + +

Aperçu de l'architecture

+ +

Comme la plupart des systèmes d'impression, CUPS est conçu autour d'un processus d'ordonnancement central qui +répartit les travaux d'impression, exécute des tâches d'administration, fournit des informations sur l'état des imprimantes +aux programmes locaux et distants, et informe les utilisateurs si nécessaire. La Figure 1 montre la base de l'organisation de CUPS. + +

+

Figure 1 - Diagramme de l'architecture globale de CUPS

+ +

L'ordonnanceur (Scheduler)

+ +

L'ordonnanceur est une application serveur HTTP 1.1 qui traite les requêtes HTTP. En plus de +traiter les demandes reçues par le biais de requêtes IPP POST, l'ordonnanceur agit également comme un serveur +"web" totalement fonctionnel qui ouvre l'accès à la documentation, à la surveillance de l'état du système et + à son administration. + + +

L'ordonnanceur maintient également une liste des imprimantes disponibles sur le réseau local (LAN) et répartit +les travaux d'impression si nécessaire en employant les filtres ou les programmes appropriés. + +

Fichiers de configuration

+ +Les fichiers se répartissent de la manière suivante : + +
    + +
  • Le fichier de configuration du serveur HTTP. + +
  • Les fichiers de définition des imprimantes et des classes d'imprimantes. + +
  • Les fichiers décrivant les règles de conversion des types MIME. + +
  • Les fichiers PPD (PostScript Printer Description). + +
+ +

Le fichier de configuration du serveur HTTP est conçu dans la même optique que celle du fichier de configuration du serveur Apache et +définit toutes les règles de contrôle d'accès pour le serveur. + +

Les fichiers de définition des imprimantes et des classes d'imprimantes listent les classes d'imprimantes et les +files d'impression disponibles. Les classes d'imprimantes sont des collections d'imprimantes. Les travaux +d'impression envoyés à une classe sont transmis à la première imprimante disponible de la classe selon un méthode de type "round-robin". + +

Les fichiers de définition des types MIME listent les différents types MIME pris en charge (texte simple, postscript, etc...) +et des règles "magiques" pour détecter automatiquement le format d'un fichier. Ils sont utilisés par le serveur +HTTP pour renseigner le champ Content-Type des requêtes GET et HEAD, et par le +gestionnaire de requêtes IPP pour déterminer le type de fichier lorsqu'une requête Print-Job ou Send-File +est reçue avec un champ document-format contenant la valeur application/octet-stream. + +

Les fichiers de règles de conversion MIME listent les filtres disponibles. Les filtres sont utilisés +quand un travail d'impression est soumis, de sorte qu'une application puisse envoyer un format de fichier +adapté au système d'impression qui convertit alors le document dans un format imprimable. Chaque filtre a un +coût relatif associé, et l'algorithme de filtrage choisit le jeu de filtres qui permettra de convertir le +fichier avec un coût minimal. + +

Les fichiers PPD décrivent les capacités de toutes les imprimantes, pas seulement celles de type PostScript. +Il y a un fichier PPD pour chaque imprimante. Les fichier PPD pour les imprimantes non-PostScript définissent des +filtres additionnels au moyen des attributs cupsFilter afin de prendre en charge les pilotes d'imprimantes. + +

L'API CUPS

+ +

L'API CUPS contient des fonctions spécifiques à CUPS pour mettre en file d'attente les travaux +d'impression, récupérer de l'information sur les imprimantes, accéder aux ressources via les +protocoles HTTP et IPP, manipuler les fichiers PPD. Contrairement au reste de CUPS, l'API CUPS +est distribuée conformément aux termes de la licence LGPL ainsi elle peut être utilisée par des +applications non-GPL. + +

Commandes de type Berkeley et System V

+ +

CUPS fournit une interface en ligne de commande de type System V et Berkeley pour soumettre des travaux +d'impression et vérifier l'état des imprimantes. Les commandes lpstat et lpc status +affichent aussi les imprimantes réseau ("imprimante@serveur") lorsque l'exploration réseau des imprimantes ("printer browsing") est activée. + +

Les commandes d'administration de type System V sont fournies pour administrer les imprimantes et les classes +d'imprimantes. L'outil d'administration d'imrpimante Berkeley lpc est uniquement pris en charge en mode +"lecture seule" pour vérifier l'état actuel des files d'impression et de l'ordonnanceur. + +

Filtres

+ +

Un programme de filtrage lit les données depuis l'entrée standard ou depuis un fichier si un nom de fichier est indiqué. +Tous les filtres doivent prendre en charge un jeu commun d'options incluant le nom d'imprimante, ne n° +d'identification du travail d'impression (ID), le nom de l'utilisateur, le nombre de copies, +et des options pour le travail d'impression. Toute sortie est envoyée vers la sortie standard. + +

Des filtres sont fournis pour de nombreux formats de fichiers y compris les fichiers image et des filtres +PostScript "matriciels" (NdT : "raster" = au sens où le document imprimé est en fait une image générée par une trame de points, +par exemple une imprimante à jet d'encre est de type "matriciel" même si l'impression ne se fait pas au moyen +d'aiguilles venant frapper un ruban et déposer de l'encre sur le papier, souvenirs, souvenirs...) qui prennent +en charge les +imprimantes non-PostScript (NdT : par opposition, le langage PostScript est un langage de description de +page de type vectoriel). Plusieurs filtres sont exécutés +en parallèle pour produire le format de sortie désiré. + +

Le filtre PostScript "matriciel" est basé sur le coeur du logiciel GNU Ghostscript 5.50. Au lieu +d'utiliser l'application d'arrière-plan et les pilotes d'imprimantes Ghostscript, le filtre CUPS utilise un +pilote "matriciel" d'imprimante générique et une application d'arrière-plan compatible CUPS pour prendre en +compte toute imprimante de type "matriciel". Ceci permet d'employer le même filtre de pilote d'impression +pour imprimer des données de type "matriciel" provenant de n'importe quel filtre. (NdT : je suis preneur de toute information ou tout éclaircissement qui pourrait me permettre de produire une +meilleure traduction pour les trois paragraphes précédents.) + +

Rendu d'image dans CUPS

+ +

La librairie de rendu d'image de CUPS fournit des fonctions pour manipuler +des images de grande taille, faire des conversions de palettes et des manipulations +sur les couleurs, dimensionner les images en vue de l'impression et administrer les flux de données +pour les pages de type "matriciel". Elle est utilisée par les filtres de fichiers image de CUPS, +et tous les pilotes d'imprimantes de type "matriciel". + +

Programmes d'arrière-plan (Backends)

+ +

Un programme d'arrière-plan est programme qui envoie des données d'impression à un périphérique ou +à une connexion réseau. Des programmes d'arrière-plan pour port parallèle, port série, USB, LPD, IPP, +et les connexions AppSocket (JetDirect) sont fournis dans CUPS 1.1. + +

Les versions de SAMBA commençant à partir de la version 2.0.6. incluent un programme d'arrière-plan SMB +(smbspool(1)) qui peut être employé avec CUPS 1.0 ou 1.1 pour imprimer vers des +machines Windows. + +

Impression réseau

+ +

Traditionnellement, l'impression réseau a toujour été l'une des choses les plus difficiles à faire +fonctionner sous UNIX. Une des raisons est que chaque fabricant ou vendeur a ajouté ses propres extensions +au protocol LPD (le standard précédent pour l'impression réseau), rendant l'impression inter-plateformes difficile +voire impossible. + +

Une autre raison est que vous devez administrer chaque imprimante réseau sur chaque machine cliente. +Dans certains cas, vous pouvez clôner la configuration à partir d'un original pour tous les autres postes, mais +même cette méthode peut être une perte de temps et une source d'erreur. Quelque chose de mieux est nécessaire. + +

CUPS fournit l'exploration des imprimantes réseau ("printer browsing") qui autorise les clients à +voir et utiliser automatiquement les imprimantes de tout serveur sur le réseau local (LAN). Cela signifie que +vous devez seulement configurer le serveur et les clients verront automatiquement les imprimantes et les classes +d'imprimantes définies sur celui-ci. + +

En plus de cela, CUPS peut automatiquement fusionner plusieurs imprimantes réseau identiques en des +classes implicites (NdT : le terme "implicite" est ici la traduction littérale du même mot anglais "implicit" et non celle de l'expression "default". Cf. ma note en tête du présent manuel.). Cela permet aux clients de soumettre des travaux d'impression à une classe implicite et que +ceux-ci soient imprimés sur la première imprimante ou le premier serveur disponible. En plus de cela, des fonctions de +répartition de charge et de tolérance de panne sont activées en définissant simplement la même imprimante sur plusieurs serveurs! + +

Nouvelles fonctionnalités dans CUPS 1.1

+ +

CUPS 1.1 inclut de nombreuses nouvelles fonctionnalités et caractéristiques: + +

    + +
  1. Programmes d'arrière-plan (Backends) + +
  2. Support des pages de garde (Banner Page) + +
  3. Authentication "Digest" + +
  4. Services d'annuaires + +
  5. Changement de stucture des répertoires + +
  6. Documentation + +
  7. Pilotes + +
  8. Filtres + +
  9. Prise en charge IPP + +
  10. Persistance des travaux d'impression + +
  11. Prise en charge des clients LPD + +
  12. Imprimantes et options définies par l'utilisateur + +
  13. Interface d'administration "web" + +
+ +

1. Programmes d'arrière-plan (Backends)

+ +

CUPS 1.1 implémente une nouvelle interface pour les programmes d'arrière-plan afin de récupérer +la liste des périphériques disponibles pour les clients CUPS. Ceci permet aux interfaces d'administration +d'interroger l'ordonnanceur CUPS pour obtenir une liste des périphériques disponibles, configurer automatiquement +les imprimante si les informations d'identification du périphérique sont disponibles, et présenter une liste à +l'utilisateur plutôt que compter sur celui-ci pour savoir quels périphériques sont réellement disponibles sur son système. + + +

La nouvelle version inclut un programme d'arrière-plan pour les imprimantes USB sous +*BSD et GNU/Linux. La prise en charge USB sous Solaris 8 sera fournie dans une prochaine mise à +jour du produit. + +

2. Pages de garde (Banner Page)

+ +

CUPS 1.1 inclut la prise en charge des page de garde au début et à la fin d'un travail d'impression. Les +pages de garde peuvent être dans n'importe quel format de fichier et prennent en charge la substitution de +variable pour le titre des travaux d'impression, les noms d'utilisateurs, etc. Des pages de garde implicites +("par défaut") peuvent être associées à chaque imprimante et peuvent être outrepassées par l'utilisateur +au moyen des options sur la ligne de commande. + +

3. Authentification "Digest"

+ +

L'authentification "Digest" fournit une méthode plus sécurisée pour +accéder au système d'impression. Contrairement à l'authentification "Basic", l'authentification "Digest" +n'envoie pas de mots de passe en clair sur le réseau ainsi il est plus difficile d'avoir un accès non +autorisé à votre système. + +

CUPS 1.1 implémente l'authentification "Digest" en utilisant un fichier de mot de passe MD5 spécial +au lieu du fichier de mots de passe UNIX. Ce fichier est administré au moyen de la commande lppasswd. + +

4. Services d'annuaires

+ +

CUPS 1.1 ajoute une nouvelle fonctionnalité de service d'annuaire ("printer browsing" = exploration des +imprimantes) pour permettre d'employer plus facilement CUPS sur de grands réseaux locaux (LAN) ou des réseaux WAN. +Vous pouvez maintenant surveiller un serveur distant pour obtenir des informations d'impression et les relayer +sur le LAN, ainsi que limiter les informations d'impression qui sont traitées (par exemple, cacher des serveurs, +des domaines ou des réseaux que vous ne voulez pas voir). + +

5. Changement de structure de répertoires

+ +

CUPS 1.1 utilise désormais une structure de répertoire conforme à la version 2.0 des recommandations FHS ("Filesystem Hierarchy Standard") +Ceci devrait rendre son intégration dans des distributions *BSD ou GNU/Linux plus facile. + +

6. Documentation

+ +

La documentation de CUPS 1.1 a subi de nombreuses révisions incluant une réécriture complète du guide de +l'administrateur, un nouveau guide du programmeur et un manuel de référence de l'implémentation du protocole IPP. +(NdT : ...et maintenant, une traduction française d'une partie celle-ci... ;o) + +

7. Pilotes

+ +

CUPS 1.1 inclut des pilotes pour imprimantes matricielles à aiguilles et jet d'encre EPSON. +Comme pour les pilots HP PCL, les pilotes EPSON ne fournissent pas forcément la meilleure sortie possible pour +chaque imprimante mais devrait produire une qualité suffisante pour les impressions de la vie courante. + +

8. Filtres

+ +

CUPS 1.1 inclut de nouveaux filtres image, PostScript, PDF et texte. Les filtres image ont +été mis à jour pour prendre en charge les fichiers Windows BMP et Alias PIX. + +

Le filtre PostScript est maintenant basé sur GNU/Ghostscript 5.50. Le nouveau filtre fournit des performances +bien meilleures avec les imprimantes haute résolution et prend en charge la plupart des caractéristiques du +langage PostScript 3. + +

Le nouveau filtre PDF est basé sur l'excellent programme Xpdf de Derek Noonburg et prend en charge la mise +à l'échelle automatique de page. Le nouveau filtre est plus rapide, plus petit, un remplaçant plus avantageux +pour le filtre PDF GNU/Ghostscript qui était utilisé dans CUPS 1.0. + +

Le nouveau filtre texte prend à présent en charge le texte bidirectionnel et peut encapsuler les polices +de caractères si nécessaire. + +

9. Support IPP

+ +

La partie la moins visible de CUPS est probablement le support IPP. CUPS 1.1 implémente toutes les opérations +et attributs requis dans le protocole IPP/1.1 et la plupart de ceux qui sont facultatifs.Les opérations optionnelles +Create-Job et Send-File sont maintenant implémentées, permettant une meilleur compatibilité avec les systèmes +d'impression de type System V (un n° de travail d'impression par commande lp) et le support des pages +de garde. + +

10. Persistance des travaux d'impression

+ +

CUPS 1.1 supporte la persistance des travaux d'impression. Cela signifie que les travaux d'impression sont +préservés même après un redémarrage du système, une fonctionnalité qui était malheureusement absente de CUPS 1.0. + +

En plus de cela, CUPS 1.1 vous permet de conserver des informations sur un travail d'impression après que le +travail ait été imprimé. Le mode de base de persistance de travaux d'impression fournit un historique des travaux +(nombre de pages imprimées, heure de soumission du travail, etc...) mais ne conserve pas les fichiers réels du +travail d'impression. Cela peut être changé pour supprimer toute information sur les travaux d'impression après +qu'ils aient été imprimés ou pour conserver les fichiers réels des travaux d'impression de manière à pouvoir +les resoumettre ultérieurement. + +

11. Support de clients LPD

+ +

A la demande générale, CUPS 1.1 prend en charge les client basés sur LPD au moyen d'un nouveu mini démon qui +traite les requêtes LPD et les transmet au serveur principal. + +

12. Imprimantes et options définies par l'utilisateur

+ +

CUPS 1.1 inclut la prise en charge d'imprimantes et d'options définies par l'utilisateur via une nouvelle +commande lpoptions. Les imprimantes définies par l'utilisateur sont des instances spéciales +d'imprimantes disponibles (par exemple "imprimante/instance" ou "imprimante@serveur/instance") qui peuvent avoir +leur propre options de base telles la taille du papier, la résolution, et ainsi de suite. +La commande lpoptions peut également être utilisée pour définir une autre file d'impression implicite. + +

13. Interface d'administration "web"

+ +

CUPS 1.0 fournissait une interface très limitée pour la surveillance des classes d'imprimantes, des travaux +d'impression et des imprimantes au moyen des navigateurs web. CUPS 1.1 remplace cette interface par une interface +d'administration améliorée qui vous permet d'ajouter, modifier, supprimer, configurer et contrôler les classes +d'imprimantes, les travaux d'impression et les imprimantes. + +

Logiciels utilisant CUPS

+ +

Il s'est passé beaucoup de choses depuis que CUPS 1.0 est sorti, et beaucoup de produits logiciels prennent en +charge CUPS. Nous avons contribué au code de l'équipe SAMBA pour prendre en charge CUPS, et une partie de cela +est déjà disponible dans SAMBA 2.0.6 et 2.0.7. Avec un peu de chance, les pièces finales qui fournissent une +complète intégration dans SAMBA seront disponibles dans la prochaine version de SAMBA. + +

Deux interfaces graphiques utilisant CUPS ont également vu le jour. Le projet KUPS fournit une interface +pour CUPS basée sur KDE et peut être trouvée à l'adresse : + +

+ +

Le projet XPP ("X Printing Panel") fournit une interface graphique de panneau d'impression pour CUPS et +peut être trouvé à l'adresse: + +

+ +

De nombreux autres filtres, pilotes et tutoriels, etc ont été rendus disponibles dans le "bazaar" CUPS à +l'adresse: + +

+ +

Finalement, notre propre logiciel ESP Print Pro utilise CUPS pour fournir des pilotes pour des milliers +d'imprimantes et peut être trouvé à l'adresse: + +

+ +

Systèmes d'exploitation utilisant CUPS

+ +

Un de nos buts a toujours été d'amener autant de distributions UNIX et GNU/Linux que possible à utiliser CUPS. +Debian fournit actuellement CUPS dans sa distribution stable, et beaucoup d'autres distributions projettent +d'en faire autant dans leurs prochaines versions. + +

Résumé

+ +

Le système CUPS fournit une interface d'impression moderne pour les applications UNIX qui est à la fois +flexible et ergonomique. Le logiciel fournit des interfaces sur ligne de commande compatibles avec System V et Berkeley pour +assurer la compatibilité avec les applications existantes. CUPS 1.1 ajoute de nombreuses nouvelles fonctionnalités +qui en font encore plus un excellent choix pour imprimer sous UNIX. + +

Qui contacter ?

+ +

Pour de plus amples informations, contactez-nous à: + +

    +Attn: CUPS Information
    +Easy Software Products
    +44141 Airport View Drive Suite 204
    +Hollywood, Maryland 20636-3111 USA
    +
    ++1.301.373.9600
    +
    +cups-info@cups.org
    +
+ +

Références

+ +
+ +
IEEE-1387.4
+ +
System Administration - Part 4: Printing Interfaces (draft)
+ +
IETF-IPP
+ +
Internet Printing Protocol/1.1
+ +
LPRng
+ +
An enhanced, extended, and portable implementation of the + Berkeley LPR print spooler functionality
+ +
Palladin
+ +
A printing system developed at the Massachussetts Institute + of Technology
+ +
PLP
+ +
The Portable Line Printer spooler system
+ +
RFC1179
+ +
Line Printer Daemon Protocol
+ +
RFC2046
+ +
Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types
+ +
RFC2616
+ +
Hypertext Transfer Protocol -- HTTP/1.1
+ +
+ +

Trademarks

+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property of Easy Software Products. All other trademarks are +the property of their respective owners. + + + diff --git a/doc/fr/overview.pdf b/doc/fr/overview.pdf new file mode 100644 index 0000000000000000000000000000000000000000..78b269384a4d8f8648ad777cc6415918ae31d437 GIT binary patch literal 42834 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 - Printing System Overview + +

This chapter provides an overview of how the Common UNIX Printing System +works. + +

The Printing Problem

+ +

For years the printing problem has plagued UNIX. Unlike +Microsoft® Windows® 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. + +

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. + +

CUPS is designed to eliminate the printing problem. 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. + +

The Technology

+ +

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. + +

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. + +

IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP") +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. + +

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. + +

Jobs

+ +

Each file or set of files that is submitted for printing is called a +job. 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. + +

Classes

+ +

CUPS supports collections of printers known as classes. Jobs +sent to a class are forwarded to the first available printer in the +class. + +

Filters

+ +

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. + +

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 ("RIP") filters that convert +PostScript or image files into bitmaps that can be sent to a raster +printer. + +

Backends

+ +

Backends perform the most important task of all - they send the +filtered print data to the printer. + +

CUPS provides backends for printing over parallel, serial, and USB +ports, and over the network via the IPP, JetDirect (AppSocket), and +Line Printer Daemon ("LPD") protocols. Additional backends are +available in network service packages such as the SMB backend +included with the popular SAMBA software. + +

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. + +

Printer Drivers

+ +

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. + +

Networking

+ +

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 "name@server". + +

CUPS also provides implicit classes, 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! diff --git a/doc/fr/references.shtml b/doc/fr/references.shtml new file mode 100644 index 0000000000..4b4930e574 --- /dev/null +++ b/doc/fr/references.shtml @@ -0,0 +1,42 @@ +

References

+ +

CUPS Documentation

+ +

The following CUPS documentation is referenced by this document: + +

    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan +
  • CUPS-IDD-1.1: CUPS System Interface Design Description +
  • CUPS-IPP-1.1: CUPS Implementation of IPP +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual +
  • CUPS-SSR-1.1: CUPS Software Security Report +
  • CUPS-STP-1.1: CUPS Software Test Plan +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual +
  • CUPS-SVD-1.1: CUPS Software Version Description +
+ +

Other Documents

+ +

The following non-CUPS documents are referenced by this document: + +

diff --git a/doc/fr/sam.html b/doc/fr/sam.html new file mode 100644 index 0000000000..0950f2ed6a --- /dev/null +++ b/doc/fr/sam.html @@ -0,0 +1,5229 @@ + + + +CUPS - Manuel de l'administrateur CUPS + + + + + + + +

+

CUPS - Manuel de l'administrateur CUPS


+CUPS-SAM-1.1.14
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table des matières

+
+
Préface + +1 - Aperçu du système d'impression + +2 - Construire et installer CUPS + +3 - Administration les imprimantes + +4 - Classes d'imprimantes + +5 - Configuration côté client + +6 - Administration du système + d'impression + +7 - Imprimer depuis et vers d'autres + systèmes + +A - Licence d'utilisation du logiciel + +B - Réglages réseau courants + +C - Pilotes d'imprimantes + +D - Liste des fichiers +
+
E - Résoudre les problèmes courants + +
+

Préface

+

Ce manuel de l'administrateur fournit les informations + d'administration pour le système d'impression CUPSTM (Common + UNIX Printing SystemTM) version 1.1.14.

+

+
Note du traducteur : + Amies lectrices, amis lecteurs, j'ai fait le choix de ne pas + traduire l'expression anglaise "default" par la version + française habituellent utilisée "par défaut" que l'on doit, + entre autres, à la documentation d'un célèbre système d'exploitation + "ouvert à tous vents". +
+
En effet, l'expression "par défaut" est normalement utilisée en + mathématiques (arrondi "par défaut" ou "par excès", personnellement je + cherche encore mon "imprimante par excès" !) mais elle est abusivement + employée en informatique pour signifier "donnée/comportement qui + s'applique si l'on n'en précise pas explicitement la + valeur/nature/teneur". +
+
Or la langue française possède justement un mot pout exprimer ce + concept : "implicite" (Larousse 1998 : "Qui est contenu dans une + proposition sans être exprimé en termes précis formels; qui est la + conséquence nécessaire."). Dans la mesure du possible, j'utiliserai cet + adjectif sauf dans les cas où son emploi n'est pas suffisamment + explicite (sic !). Je lui préfèrerai alors l'expression "... de + base ..." ou l'adjectif "standard". +
+
Ce choix est totalement personnel et le fait que j'ai fait l'effort + (non négligeable) de traduire ces lignes pour vos yeux délicats suffit + à le justifier! Si, par malheur, ma prose vous est insupportable, je ne + vous empêche aucunement de vous reporter à la version originale où vous + retrouverez "default" entouré de tout le reste... en anglais, bien sûr. + Enfin, si vous avez une meilleure traduction, je suis preneur ! +
+
Malgré les très nombreuses relectures et corrections, certaines + fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma + vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les + signaler afin de contribuer à l'amélioration constante de la qualité du + présent manuel. +
+
Bonne lecture !
+
+

Aperçu du système

+

CUPS fournit une couche d'impression portable pour les systèmes + d'exploitation de type UNIX®. Il a été développé par + Easy Software Products pour promouvoir une solution d'impression + standard pour tous les vendeurs et utilisateurs d'UNIX. CUPS fournit + des interfaces en ligne de commande de type System V et Berkeley.

+

CUPS utilise le protocol IPP (Internet Printing Protocol) comme base + de l'administration des travaux et files d'impression. Les protocoles + LPD ("Line Printer Daemon"), SMB ("Server Message Block"), et AppSocket + (JetDirect) sont également pris en charge avec des fontionnalités + réduites. CUPS ajoute l'exploration réseau des imprimantes ("network + printer browsing") et des options d'impression basées sur PPD + ("PostScript Printer Definition") pour prendre en charge l'impression + "dans le monde réel" sous UNIX.

+

CUPS inclut également une version adaptée de GNU/Ghostscript + (actuellement basée sur la version 5.50) et un module de rendu (RIP - + Raster Image Processor) pour fichier image qui sont utilisés pour + prendre en charge les imprimantes non-PostScript. Des pilotes d'exemple + (incluant ces filtres) pour imprimantes HP et EPSON sont également + inclus.

+ + +

Aperçu du document

+

Ce manuel de l'administrateur est organisé de la manière suivante:

+ +

Conventions d'écriture

+

+ +

+

Abréviations

+ Les abréviations suivantes sont utilisées au cours de ce manuel: +
    +
    +
    ko
    +
    Kilo-octets, ou 1024 octets +
     
    +
    Mo
    +
    Méga-octets, ou 1048576 octets +
     
    +
    Go
    +
    Giga-octets, ou 1073741824 octets +
     
    +
    +
+

Autres références

+
    +
    +
    CUPS - Manuel du programmeur (en anglais)
    +
    Un guide du programmeur pour interagir avec CUPS ou y ajouter des + extensions. +
     
    +
    CUPS - Manuel de l'utilisateur
    +
    Un guide d'utilisation pour l'utilisateur final du logiciel CUPS. +
     
    +
    +
+

1 - Aperçu du système d'impression +

+

Ce chapitre fournit un aperçu de la manière dont CUPS fonctionne.

+

Le problème d'impression

+

Depuis des années le problème d'impression a empoisonné le + monde UNIX. Contrairement à Microsoft® Windows® ou Mac OS, UNIX n'a pas + d'interface standard ou de système en place pour prendre en charge les + imprimantes. Parmi les solutions actuellement disponibles, les systèmes + Berkeley et System V sont prédominants.

+

Ces systèmes d'impressions prennent en charge les imprimantes de + type matriciel texte ou les imprimantes PostScript (texte et + graphique), et avec quelques ajustements il peuvent prendre en charge + un grand nombre d'imprimantes et de formats de fichiers. Cependant, + puisque chaque version de système d'exploitation UNIX utilise un + système d'impression différent de celui de son voisin, il est + extrêmement difficile de développer des pilotes d'imprimantes pour une + vaste gamme d'imprimantes et de systèmes d'exploitation. Ceci, combiné + au faible nombre de clients pour chaque variante d'UNIX, a poussé les + fabricants d'imprimantes à abandonner la prise en charge globale de + tous les UNIX.

+

CUPS est conçu pour éliminer le problème d'impression. Un + système d'impression commun peut être utilisé par toutes les variantes + d'UNIX pour prendre en charge les capacités d'impression dont les + utilisateurs ont besoin. Les fabricants d'imprimantes peuvent utiliser + l'interface modulaire des filtres pour développer un unique pilote qui + prend en charge une large gamme de formats de fichiers et ce, sans + presque aucun effort. Etant donné que CUPS fournit une interface + compatible avec les commandes Berkeley et System V, les utilisateurs + (et les applications) peuvent tirer bénéfice de cette nouvelle + technologie sans avoir à faire de changements.

+

La technologie

+

CUPS est basé sur un standard émergeant d'Internet appelé IPP + (Internet Printing Protocol). IPP a été adopté par des douzaines de + fabricants d'imprimantes et de serveurs d'impression et est pris en + charge par Microsoft Windows 2000.

+

IPP définit un protocole standard pour imprimer ainsi qu'administrer + les travaux d'impression et les options des imprimantes telles que la + taille du support d'impression, la résolution, etc. Comme tout + protocole de la pile TCP/IP, IPP peut être utilisé localement ou à + travers Internet pour atteindre des imprimantes éloignées de centaines + ou de milliers de kilomètres. Contrairement à d'autres protocoles de la + pile TCP/IP, IPP prend en charge le contrôle d'accès, + l'authentification et l'encryptage, ce qui fait de lui une solution + d'impression bien plus efficace et sécurisée que ses ancêtres.

+

IPP est une surcouche ajoutée au-dessus du protocole HTTP (HyperText + Transport Protocol) qui est à la base des serveurs "web" sur + l'Internet. Ceci permet aux utilisateurs de lire la documentation, + vérifier les informations sur l'état des imprimantes ou du serveur, + administrer les imprimantes, les classes d'imprimantes et les travaux + d'impression en utilisant leur navigateur "web".

+

CUPS fournit un système d'impression complet basé sur IPP/1.1 + prenant en charge l'authentification "Basic", "Digest" et par + certificats locaux ainsi qu'un contrôle d'accès basé sur l'utilisateur, + le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une + future version de CUPS.

+

Travaux d'impression

+

Tout fichier ou groupe de fichiers soumis à l'impression est appelé + un travail d'impression. Les travaux d'impression sont + identifiés par un nombre unique en commençant à 1 et sont affectés à + une destination particulière, généralement une imprimante. Les travaux + d'impression peuvent également inclure des options associées telles que + la taille du support d'impression, le nombre de copies et la priorité + dans la file d'impression.

+

Classes d'imprimantes

+

CUPS prend en charge des collections d'imprimantes connues sous le + nom de classes. Les travaux d'impression transmis à une classe + d'imprimantes sont envoyés à la première imprimante disponible dans la + classe.

+

Filtres

+

Les filtres permettent à un utilisateur ou une application d'imprimer + de nombreux types de documents sans effort supplémentaire. Les travaux + d'impressions envoyés au serveur CUPS sont filtrés avant d'être envoyés + à l'imprimante. Certains filtres convertissent les fichiers de travaux + d'impression dans différents formats que l'imprimante peut comprendre. + D'autres ne font que des sélections de page et des tris.

+

CUPS fournit des filtres pour imprimer de nombreux types de fichiers + image, des fichier HP-GL/2, fichiers PDF et texte. CUPS fournit + également des filtres PostScript et RIP (Raster Image Processor) qui + convertissent les fichiers PostScript ou image en format "bitmap" qui + peut être envoyé à une imprimante de type "matriciel" (NdT : il s'agit + ici, des imprimantes dont l'impression est générée au moyen d'une + grille de points comme l'étaient les vénérables imprimantes à aiguilles + de notre enfance, mais pas seulement elles puisque les imprimantes à + jet d'encre actuelles sont également de type matriciel... par + opposition aux imprimantes laser dont la méthode de génération + d'impression est différente.)

+

Programmes d'arrière-plan (Backends)

+

Les programmes d'arrière-plan effectuent le travail le plus important + : ils envoient les données d'impression à l'imprimante.

+

CUPS fournit des programmes d'arrière-plan pour imprimer via des + ports de type parallèle, série, USB et à travers un réseau au moyen des + protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des + programmes d'arrière-plan additionnels sont disponibles sous forme de + paquetage de service réseau comme le programme d'arrière_plan SMB + inclus dans le célèbre logiciel SAMBA.

+

Les programmes d'arrière-plan sont également utilisés pour déterminer + les périphériques disponibles. Au démarrage, chaque programme + d'arrière-plan est interrogé afin de déterminer la liste des + périphériques qu'il prend en charge, ainsi que toute information + disponible. Cela permet au programme d'arrière-plan de gestion du port + parallère d'indiquer à CUPS qu'une imprimante EPSON Stylus Color 600 + est branchée sur le port parallèle 1, par exemple.

+

Pilotes d'imprimantes

+

Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs + filtres spécifiques à une imprimante. CUPS inclut des pilotes + d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet + Hewlett-Packard et les imprimantes EPSON jet d'encre couleur Stylus + Color, Stylus Photo et les modèles 9 et 24 aiguilles matricielles. Bien + que ces pilotes ne produisent pas des impressions de qualité optimale + pour les différents modèles d'imprimantes, ils fournissent une + impression de base et démontrent comment vous pouvez écrire vos propres + pilotes d'imprimantes et les incorporer dans CUPS.

+

Réseau

+

Les imprimantes et classes d'imprimantes sur le système local sont + automatiquement partagées avec les autres systèmes sur le réseau. Cela + vous permet de configurer un système hôte pour tous les autres. Les + utilisateurs pourront sélectionner une imprimante locale par son nom ou + une imprimante à distance en utilisant la syntaxe + "nom_imprimante@serveur".

+

CUPS fournit également des classes d'imprimantes implicites + (NdT : le terme "implicite" est ici la traduction litérale du même mot + anglais "implicit" et non celle de l'expression "default". cf. ma + remarque dans la préface du présent manuel. De toute façon, CUPS ne + prévoit pas de "default class" c'est-à-dire de "classe de base", donc + aucune ambiguïté possible ici.), qui sont des collections d'imprimantes + ou de classes d'imprimantes qui portent le même nom. Cela vous permet + de configurer de multiples serveurs pointant vers la même imprimante + réseau physique, par exemple, de sorte que vous ne dépendez pas d'un + seul serveur pour pouvoir imprimer. Etant donné que cette méthode vous + permet de travailler avec des classes d'imprimantes, vous pouvez + configurer de multiples serveurs et imprimantes sans jamais vous + soucier d'un simple point en panne tant que tous les autres serveurs ne + tombent pas en panne en même temps.

+

2 - Construire et + installer CUPS

+

Ce chapitre décrit comment construire et installer CUPS. Si vous + installez une distribution binaire (précompilée) du produit, veuillez + vous reporter à la section, Installer une + distribution binaire.

+

Installer à partir d'une distribution du code source +

+

Cette section décrit comment compiler et installer CUPS sur votre + système à partir du code source du produit.

+

Conditions nécessaires

+

Vous aurez besoin d'un compilateur C et C++ conforme à la norme ANSI + pour construire CUPS sur votre système. Comme son nom l'indique, CUPS + est conçu pour fonctionner sur le système d'exploitation UNIX, + cependant la plupart des librairies, des filtres et des programmes + d'arrière-plan devraient également se compiler et fonctionner sous + Microsoft Windows.

+

Pour les filtres de fichiers image et PostScript, vous aurez besoin + des librairies JPEG, PNG, TIFF et ZLIB. CUPS se construira sans elles + mais avec des fonctionnalités singulièrement réduites. Easy Software + Products maintient un miroir des versions actuelles de ces librairies à + l'adresse:

+ +

Si vous faîtes des changements dans les pages de manuel vous aurez + besoin de GNU groff ou d'un autre paquetage compatible nroff. GNU groff + est disponible à l'adresse:

+ +

La documentation est formatée en utilisant le programme HTMLDOC. Si + vous voulez faire des changements, vous pouvez obtenir le programme + HTMLDOC à l'adresse:

+

+ +

Enfin, vous aurez besoin d'un programme make qui + comprend les directives include - les développeurs + FreeBSD, NetBSD et OpenBSD devraient utiliser le programme gmake +.

+

Compiler CUPS

+

CUPS utilise GNU autoconf pour configurer les "makefiles" et le code + source pour votre système. Tapez simplement la commande suivante pour + configurer CUPS pour votre système:

+
    +
    +./configure ENTREE
    +
    +
+

L'installation standard installera CUPS dans les répertoires + /etc, /usr, et /var de votre système, ce + qui écrasera toute commande d'impression existant déjà dans votre + système. Utilisez l'option --prefix pour installer CUPS à + un autre emplacement:

+
    +
    +./configure --prefix=/autre/répertoire ENTREE
    +
    +
+

Si les librairies PNG, JPEG, TIFF, et ZLIB ne sont pas installées à + un emplacement habituel du système (généralement il s'agit de + /usr/include et /usr/lib) vous devrez définir les + variables d'environnement CFLAGS, CXXFLAGS, + et LDFLAGS avant d'exécuter la commande configure:

+
    +
    +setenv CFLAGS "-I/some/directory" ENTREE
    +setenv CXXFLAGS "-I/some/directory" ENTREE
    +setenv LDFLAGS "-L/some/directory" ENTREE
    +setenv DSOFLAGS "-L/some/directory" ENTREE
    +./configure ... ENTREE
    +
    +
+

ou:

+
    +
    +CFLAGS="-I/some/directory"; export CFLAGS ENTREE
    +CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTREE
    +LDFLAGS="-L/some/directory"; export LDFLAGS ENTREE
    +DSOFLAGS="-L/some/directory"; export DSOFLAGS ENTREE
    +./configure ... ENTREE
    +
    +
+

Pour activer le support de l'encryptage, vous devrez également + activer l'option "--enable-ssl":

+
    +
    +./configure --enable-ssl
    +
    +
+

La prise en charge SSL et TLS nécessite la librairie OpenSSL, + disponible à l'adresse:

+ +

Si les en-têtes et les librairies OpenSSL ne sont pas installées dans + les répertoires standards, utilisez les options +--with-openssl-includes et --with-openssl-libs:

+
    +
    +./configure --enable-ssl \
    +    --with-openssl-includes=/foo/bar/include \
    +    --with-openssl-libs=/foo/bar/lib
    +
    +
+

Une fois que vous avez configuré toutes ces choses, tapez simplement:

+
    +
    +make ENTER
    +
    +
+

pour compiler le logiciel.

+ + +

Installer le logiciel

+

Utilisez la cible "install" pour installer le logiciel:

+
    +
    +make install ENTREE
    +
    +
+
+ + +
AVERTISSEMENT: +

Installer CUPS écrasera votre système d'impression précédent. Si vous + rencontrez des difficultés avec le logiciel CUPS et devez revenir à + votre ancien système d'impression, vous devrez réinstaller celui-ci à + partir de CD originaux de votre système d'exploitation.

+
+
+

Exécuter le logiciel

+

Une fois que vous avez installé le logiciel vous pouvez démarrer le + serveur CUPS en tapant:

+
    +
    +/usr/sbin/cupsd ENTREE
    +
    +
+ + +

Installer une distribution binaire du logiciel

+

CUPS est fourni dans une variété de formats binaires. Easy Software + Products fournit des binaires sous forme d'archives au format TAR avec + des scripts d'installation et de désinstallation (distributiond dites + "portables"), sous forme de format RPM et DPKG pour les distributions + RedHat et Debian. Les distributions portables sont disponibles pour + toutes les plateformes tandis que les distributions RPM et DPKG ne le + sont que pour GNU/Linux

+
+ + +
AVERTISSEMENT: +

Installer CUPS écrasera votre système d'impression précédent. Si vous + rencontrez des difficultés avec le logiciel CUPS et devez revenir à + votre ancien système d'impression, vous devrez réinstaller celui-ci à + partir de CD originaux de votre système d'exploitation.

+
+
+

Installer une distribution portable

+

Pour installer le logiciel CUPS à partir d'une distribution portable + vous devrez ouvrir une session en tant qu'utilisateur root; utiliser la + commande su est suffisant. Une fois que vous êtes + utilisateur root, lancer le script d'installation avec la commande:

+
    +
    +./cups.install ENTREE
    +
    +
+

Après vous avoir posé quelques questions de type oui/non, le logiciel + CUPS va s'installer et l'ordonnanceur sera démarré automatiquement.

+ + +

Installer une distribution de type RPM

+

Pour installer le logiciel CUPS à partir d'une distribution RPM vous + devez ouvrir une session en tant qu'utilisateur root; utiliser la + commande su est suffisant. Une fois connecté en tant + qu'utilisateur root, lancez simplement RPM au moyen de la commande:

+
    +
    +rpm -e lpr
    +rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTREE
    +
    +
+

Après un petit délai, le logiciel CUPS sera installé et + l'ordonnanceur sera démarré automatiquement.

+

Installer une distribution de type DEBIAN

+

Pour installer le logiciel CUPS à partir d'une distribution DEBIAN + vous devez ouvrir une session en tant qu'utilisateur root; utiliser la + commande su est suffisant. Une fois connecté en tant + qu'utilisateur root, lancez simplement dpkg au moyen de la commande:

+
    +
    +dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTREE
    +
    +
+

Après un court délai, le logiciel CUPS sera installé et + l'ordonnanceur sera automatiquement démarré.

+

3 - Administration les + imprimantes

+

Ce chapitre décrit comment ajouter votre première imprimante et + comment administrer vos imprimantes.

+

Les bases

+

Chaque file d'impression a un nom associé; le nom de l'imprimante + doit commencer avec une lettre et peut comporter jusqu'à 127 lettres, + des chiffres ou un caractère de soulignement "_" ("underscore"). La + casse des caractères n'est pas significative, par exemple les chaînes + de caractères "IMPRIMANTE", "Imprimante" et "imprimante" sont + considérées comme le même nom.

+

Les files d'impression ont également un périphérique associé. Ce + périphérique peut être un port parallèle, une interface réseau, etc. + Les périphériques dans CUPS utilisent des URI (Uniform Resource + Identifiers) qui sont une forme plus générale des URL (Uniform Resource + Locator) qui sont utilisés par votre noavigateur "web". Par exemple, le + premier port parallèle dans GNU/Linux est habituellement désigné par + l'URI de périphérique parallel:/dev/lp1.

+ + +

Vous pouvez voir une liste complète des périphériques pris en charge + en lançant la commande lpinfo(8):

+
    +
    +lpinfo -v ENTREE
    +file file
    +network socket
    +network http
    +network ipp
    +network lpd
    +direct parallel:/dev/lp1
    +serial serial:/dev/ttyS1?baud=115200
    +serial serial:/dev/ttyS2?baud=115200
    +direct usb:/dev/usb/lp0
    +network smb
    +
    +
+

L'option -v indique que vous voulez la liste de tous les + périphériques disponibles. Le premier mot de chaque ligne est le type + de périphérique (direct, fichier, réseau, série) et est suivi par l'URI + du périphérique ou le nom de la méthode d'accès à ce périphérique. Les + périphériques de type fichier ont des URI de périphérique de la forme +file:/répertoire/nom_fichier tandis que les périphériques réseau + utilisent la forme plus familière methode://serveur ou +méthode://serveur/chemin.

+

Enfin, les files d'impression ont généralement un fichier PPD + (PostScript Printer Definition) associé. Les fichiers PPD décrivent les + capacités de chaque imprimante, les tailles de support prises en + charge, etc., et sont utilisés pour les imprimantes PostScript et + non-PostScript. CUPS inclut des fichiers PPD pour les imprimantes HP + LaserJet et Deskjet, EPSON Stylus, et EPSON 9 et 24 aiguilles.

+

Ajouter votre première imprimante

+

CUPS fournit deux méthodes pour ajouter des imprimantes : un + programme en ligne de commande nommé lpadmin(8) et une + inteface "web". La commande lpadmin vous permet + d'effectuer la plupart des tâches d'administration d'imprimantes à + partir de la ligne de commande, elle est située dans le répertoire + /usr/sbin. L'interface "web" est disponible à l'adresse:

+ +

et vous quide pas à pas au travers des étapes de configuration + d'imprimante. Si vous n'aimez pas les interfaces en ligne de commande, + essayez plutôt l'interface web.

+

Ajouter votre première imprimante depuis la ligne de + commande

+

Exécutez la commande lpadmin avec l'option -p + pour ajouter une imprimante à CUPS:

+
    +
    +/usr/sbin/lpadmin -p imprimante -E -v périphérique -m ppd ENTREE
    +
    +
+

Pour une imprimante HP DeskJet connectée au port parallèle, la + commande serait:

+
    +
    +/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTREE
    +
    +
+

De la même manière, une imprimante HP LaserJet utilisant une + interface réseau de type JetDirect à l'adresse IP 11.22.33.44 serait + ajoutée avec la commande:

+
    +
    +/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTREE
    +
    +
+

Comme vous pouvez le voir, deskjet.ppd et +laserjet.ppd sont les fichiers PPD pour les pilotes HP DeskJet et + HP LaserJet inclus dans CUPS. Vous trouverez une liste complète des + fichiers PPD ainsi que celle des imprimantes avec lesquelles ils + fonctionnent dans l'Annexe C, "Pilotes + d'imprimantes".

+

Pour une imprimante matricielle à aiguilles connectée au port série, + la commande serait:

+

+
    +
    +/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTREE
    +
    +
+

Ici, vous indiquez le port série (par exemple S0, S1, d0, s1), le + taux de transfert en bauds (par exemple 9600, 19200, 38400, 115200, + etc.), le nombre de bits de partié, et le contrôle de flux. Si vous + n'avez pas besoin de contrôle de flux, supprimez la partie + "+flow=soft".

+

Ajouter votre première imprimante depuis + l'interface "web"

+

Le serveur CUPS fournit une interface ergonomique sous forme d'un + assistant ("wizard") pour ajouter les imprimantes. Plutôt que devoir + déterminer quel URI de périphérique et quel fichier PPD utiliser, vous + cliquez simplement sur l'option adéquate de la liste et vous remplissez + quelques champs de formulaires avec des informations simples. Entrez + l'adresse suivante dans votre navigateur "web" pour commencer:

+ +

Cliquez sur le bouton Ajouter imprimante pour en ajouter + une.

+

Administrer les imprimantes depuis la ligne de + commande

+

La commande lpadmin vous permet d'effectuer la plupart + des tâches d'administration d'imprimantes depuis la ligne de commande. + Vous trouverez lpadmin dans le répertoire /usr/bin +.

+

Ajouter et modifier des imprimantes

+

Exécutez la commande lpadmin avec l'option -p + pour ajouter ou modifier une imprimante.

+
    +
    +/usr/sbin/lpadmin -p imprimante options ENTREE
    +
    +
+

Les arguments options peuvent être n'importe lesquels parmi:

+
    +
    +
    -c classe
    +
    Ajoute l'imprimante nommée à la classe d'imprimantes classe +. Si la classe d'imprimantes n'existe pas alors elle est créée.
    +
    -i interface
    +
    Copie le script pour l'interface vers l'imprimante. Les + scripts d'interface sont utilisés par les pilotes d'imprimantes System + V. Etant donné que tous les filtres sont désactivés lorsque les scripts + d'interface sont employés, les scripts ne devraient normalement jamais + être utilisés à moins qu'il n'y ait aucun autre pilote pour + l'imprimante.
    +
    -m modèle
    +
    Indique une pilote d'imprimante standard qui est généralement un + fichier PPD. Une liste de tous les modèles disponibles peut être + affichée au moyen de l'option -m. Une liste de tous les + pilotes d'imprimantes inclus dans CUPS peut être consultée dans l' +Annexe C, "Pilotes d'imprimantes".
    +
    -r classe
    +
    Retire l'imprimante spécifiée de la classe d'imprimantes classe +. Si la classe qui en résulte est vide, elle est supprimée.
    +
    -v uri-périphérique
    +
    Indique le périphérique à employer pour dialoguer avec l'imprimante. + Si un travail d'impression est actuellement en cours d'édition sur + l'imprimante spécifiée, il est relancé et envoyé au nouveau + périphérique.
    +
    -D info
    +
    Fournit une description textuelle de l'imprimante, par exemple + "Imprimante personnelle de Marcel".
    +
    -E
    +
    Active l'imprimante et accepte les travaux d'impression. Cette + option équivaut à exécuter les commandes enable(1) et +accept(8).
    +
    -L emplacement
    +
    Fournit une description textuelle de l'emplacement de l'imprimante, + par exemple "Salle informatique n°5".
    +
    -P fichier-ppd
    +
    Indique un fichier PPD local pour le pilote d'imprimante.
    +
    +
+

Supprimer des imprimantes

+

Exécutez la commande lpadmin avec l'option -x + pour supprimer une imprimante:

+
    +
    +/usr/sbin/lpadmin -x printer ENTREE
    +
    +
+

Choisir l'imprimante implicite

+

Exécutez la commande lpadmin avec l'option -d + pour définir l'imprimante standard:

+
    +
    +/usr/sbin/lpadmin -d printer ENTREE
    +
    +
+

L'imprimante standard peut-être outrepassée par l'utilisateur au + moyen de la commande lpoptions(1).

+

Démarrer et arrêter des imprimantes

+

Les commandes enable et disable démarrent + et arrêtent les files d'impression, avec les syntaxes respectives + suivantes :

+
    +
    +/usr/bin/enable imrimante ENTREE
    +/usr/bin/disable imprimante ENTREE
    +
    +
+

Note du traducteur : utilisateurs du shell BASH attention ! + enable est une commande interne de celui-ci. Si vous tapez + simplement enable vous obtiendrez un message d'erreur car + c'est la version interne de BASH qui sera utilisée en standard. Pour + effectivement utiliser la commande enable de CUPS vous +devez faire précéder son nom du chemin d'accès complet : +/usr/bin/enable.

+

Les imprimantes qui sont désactivées peuvent toujours accepter les + travaux d'impression mais n'en imprimeront effectivement aucun tant + qu'elle ne seront pas réactivées. Cela est utile si une imprimante + fonctionne mal et que vous avez besoin de corriger le problème + (bourrage). Tout travail d'impression mis en file d'attente est imprimé + dès que la l'imprimante est réactivée.

+

Accepter et rejeter les travaux d'impression

+

Les commandes accept et reject permettent + respectivement d'indiquer à une imprimante qu'elle doit accepter ou + rejeter les nouveaux travaux d'impression:

+
    +
    +/usr/sbin/accept imprimante ENTREE
    +/usr/sbin/reject imprimante ENTREE
    +
    +
+

Comme indiqué ci-dessus, une imprimante peut être configurée pour ne + plus accepter de nouveaux travaux d'impression. Une imprimante peut + aussi rejeter les nouveaux travaux d'impression bien qu'elle soit en + train de terminer le traitement de ceux qui ont été mis en file + d'attente avant que celle-ci soit désactivée. Ceci est utile si vous + avez besoin d'effectuer des opérations de maintenance sur l'imprimante + et que vous ne voulez pas qu'elle soit disponible pour les utilisateurs + pendante une longue période.

+

Administrer les imprimantes depuis l'interface "web" +

+

L'interface "web" est disponible à l'adresse:

+ +

Depuis celle-ci vous pouvez effectuer toutes les tâches + d'administrations sur les imprimantes au moyen de quelques clics de + souris.

+

4 - Classes d'imprimantes +

+

Ce chapitre décrit ce que sont les classes d'imprimantes et comment + les administrer.

+

Les bases

+

CUPS fournit des collections d'imprimantes appelées classes + d'imprimantes. Les travaux soumis à une classe sont transmis à la + première imprimante disponible de la classe. Les classes peuvent elles + auusi être membres d'autres classes, ainsi il est possible que vous + définissiez de grandes classes réparties afin de fournir un système + d'impression à haute disponibilité.

+

CUPS prend également en charge les classe implicites. Les + classes implicites fonctionnent comme les classes d'imprimantes, mais + elles sont créées automatiquement à partir des classes et imprimantes + disponibles sur le réseau. Cela vous permet de configurer de multiples + serveurs d'impression avec des configurations d'imprimantes identiques + de sorte que les systèmes clients envoient des travaux d'impression au + premier serveur disponible. Si un ou plusieurs serveurs deviennent + indisponibles, les travaux d'impressions sont automatiquement redirigés + vers les serveurs encore en fonctionnement, fournissant ainsi un + système d'impression résistant aux pannes.

+

Administrer les classes d'imprimantes depuis la ligne + de commande

+

Exécutez la commande lpadmin avec les options -p + et -c pour ajouter une classe d'imprimantes:

+
    +
    +/usr/sbin/lpadmin -p imprimante -c classe ENTREE
    +
    +
+

La classe est créée automatiquement si elle n'existe pas. Pour + retirer une imprimante d'une classe, utilisez l'option -r:

+
    +
    +/usr/sbin/lpadmin -p imprimante -r classe ENTREE
    +
    +
+

Pour enlever toute la classe, utilisez l'option -x:

+
    +
    +/usr/sbin/lpadmin -x classe ENTREE
    +
    +
+

Administrer les classes d'imprimante depuis + l'interface "web"

+

L'interface "web" est disponible à l'adresse:

+ +

Les pages Ajouter classe et Modifier classe + fournissent une liste des imprimantes disponibles. Cliquez sur la ou + les imprimantes de votre choix pour les ajouter à la classe.

+

Classes implicites

+

Comme indiqué auparavant, les classes implicites sont automatiquement + créées à partir des imprimantes et des classes disponibles sur le + réseau. Pour désactiver cette fonctionnalité, réglez la valeur de la + directive ImplicitClasses + sur Off dans le fichier cupsd.conf. Vous + trouverez plus d'information sur la manière de faire cela dans le + Chapitre 6, "Administration du système d'impression".

+

5 - Configuration côté client +

+

Ce chapitre expose diverses manières de configurer les clients CUPS + pour pouvoir imprimer.

+

Les bases

+

Un client est toute machine qui envoie des travaux d'impression à une + autre machine pour édition finale. Les clients peuvent également être + des serveurs s'il communiquent directement avec des imprimantes qui + leur appartiennent.

+

CUPS prend en charge plusieurs méthodes pour configurer les machines + clientes:

+ +

Configuration manuelle des files + d'impression

+

La méthode la plus fastidieuse pour configurer les machines clientes + est de configurer chaque file d'impression à distance à la main au + moyen de la commande lpadmin:

+
    +
    +lpadmin -p imprimante -E -v ipp://serveur/printers/imprimante ENTREE
    +
    +
+

Le nom imprimante est le nom de l'imprimante sur la machine + serveur. Le nom serveur est le nom d'hôte ou l'adresse IP + de la machine serveur. Répètez la commande lpadmin pour + chaque imprimante distante que vous désirez utilser.

+

Choix d'un serveur unique pour l'impression +

+

CUPS peut être configuré pour fonctionnner sans file d'attente locale + et envoyer tous les travaux d'impression à un serveur unique. + Cependant, si ce serveur vient à tomber en panne, toute possibilité + d'imprimer sera supprimée. Utilisez cette configuration uniquement + lorsque c'est absolument nécessaire.

+

Le serveur implicite est normalement "localhost". Pour outrepasser ce + réglage de base, créez un fichier nommé /etc/cups/client.conf + et ajoutez une ligne:

+
    +
    +ServerName serveur
    +
    +
+

au fichier. Le nom serveur peut être le nom d'hôte ou + l'adresse IP du serveur implicite.

+

Le serveur implicite peut également être adapté en fonction de + l'utilisateur. Pour créer un réglage spécifique à l'utilisateur, créez + un fichier nommé ~/.cupsrc et ajoutez une ligne:

+
    +
    +ServerName serveur
    +
    +
+

+

au fichier. Le nom serveur peut être le nom d'hôte ou + l'adresse IP du serveur implicite.

+

Configuration automatique des files + d'impression

+

CUPS prend en charge la configuration automatique des clients pour + les imprimantes sur le même sous-réseau. Pour configurer des + imprimantes présentes sur le même sous-réseau, ne faîtes rien. + Chaque client devrait voir automatiquement les imprimantes disponibles + dans un délai de 30 secondes. Les listes des classes et des imprimantes + sont automatiquement mises à jour chaque fois que des imprimantes et + des serveurs sont ajoutés ou retirés.

+

Si vous désirez également voir les imprimantes sur d'autres + sous-réseau, utilisez la directive +BrowsePoll comme indiqué ci-après.

+

Choix de plusieurs serveurs pour l'impression +

+

Si vous disposez de plusieurs serveurs CUPS sur plusieurs + sous-réseaux, vous devriez configurer CUPS pour surveiller ces + serveurs. La surveillance fournit l'avantage d'automatiser + singulièrement la configuration sur les clients, et plusieurs clients + sur le même sous-réseau peuvent partager les mêmes informations de + configuration.

+

La surveillance est activée en indiquant une ou plusieurs directives BrowsePoll dans le fichier + /etc/cups/cupsd.conf. Pour savoir comment faire ces changements, + veuillez vous reporter au Chapitre 6, + "Administration du système d'impression".

+

6 - Administration du + système d'impression

+

Ce chapitre montre comment configurer le serveur CUPS.

+

Les bases

+

Plusieurs fichiers texte sont utilisés pour configurer CUPS. Tous les + fichiers de configuration du serveur sont placés dans le répertoire + /etc/cups:

+
    +
    + + +
    classes.conf
    +
    Ce fichier contient les informations sur chaque classe d'imprimante. + Normalement vous manipulez ce fichier en utilisant la commande +lpadmin ou l'interface "web". +
      + +
    +
    client.conf
    +
    Ce fichier fournit le nom du serveur implicite pour les machines + clientes. Veuillez vous reporter au Chapitre 5, + "Configuration côté client" pour de plus amples informations. +
      + +
    +
    cupsd.conf
    +
    Ce fichier contrôle la manière de fonctionner sur serveur CUPS ( +/usr/sbin/cupsd) et est normalement édité à la main. +
      + +
    +
    mime.convs
    +
    Ce fichier contient une liste des filtres de base pour la conversion + de fichier et leurs coûts respectifs. Normalement, vous n'éditerez pas + ce fichier. +
      + +
    +
    mime.types
    +
    Ce fichier contient la liste des formats de fichiers standards et + comment les reconnaître. Normalement, vous n'éditerez pas ce fichier. +
      + +
    +
    printers.conf
    +
    Ce fichier contient des informations sur chaque imprimante. + Normalement, vous manipulez ce fichier en utilisant la commande +lpadmin ou l'interface "web". +
     
    +
    +
+

Redémarrer le serveur CUPS

+

Une fois que vous avez fait des changements au fichier de + configuration, vous devez redémarrer le serveur CUPS en lui envoyant un + signal HUP ou en utilisant le script d'initialisation + adéquat. Les distributions de CUPS installent le script dans le + répertoire init.d sous le nom cups. L'emplacement + varie selon le système d'exploitation:

+
    +
    +/etc/rc.d/init.d/cups restart ENTREE
    +/etc/init.d/cups restart ENTREE
    +/sbin/init.d/cups restart ENTREE
    +
    +
+

Changer la configuration du serveur

+

Le fichier /etc/cups/cupsd.conf contient des directives + de configuration qui contrôlent le fonctionnement du serveur. Chaque + directive suivie de sa valeur est disposée seule sur une ligne. Les + commentaires sont ouverts par le signe dièse ("#") au début de la + ligne. Etant donné que le fichier de configuration du serveur est un + fichier texte, vous pouvez le modifier au moyen de votre éditeur de + texte préféré. + +

+

Directives de configuration du serveur

+

Le fichier cupsd.conf contient de nombreuses directives + qui déterminent le comportement du serveur:

+ + + +

AccessLog

+
+

Exemples

+
    +
    +AccessLog /var/log/cups/access_log
    +AccessLog /var/log/cups/access_log-%s
    +AccessLog syslog
    +
    +
+

Description

+

La directive AccessLog donne le nom du fichier de suivi + d'accès ("access log"). Si le chemin d'accès au fichier n'est pas + absolu, il est considéré comme relatif au répertoire +ServerRoot. Le fichier "access log" est stocké dans le + format "log" habituel et peut aisément être utilisé par tout outil + d'analyse d'accès "web" pour générer un rapport sur l'activité du + serveur CUPS.

+

Le nom du serveur peut être inclus dans le nom du fichier en + utilisant %s dans le nom.

+

Le nom spécial "syslog" peut être utilisé pour envoyer les + informations d'accès au fichier de suivi système au lieu d'un simple + fichier texte.

+

Le fichier de suivi d'accès implicite est + /var/log/cups/access_log. + +

+

Allow

+
+

Exemples

+
    +
    +Allow from All
    +Allow from None
    +Allow from *.domain.com
    +Allow from .domain.com
    +Allow from host.domain.com
    +Allow from nnn.*
    +Allow from nnn.nnn.*
    +Allow from nnn.nnn.nnn.*
    +Allow from nnn.nnn.nnn.nnn
    +Allow from nnn.nnn.nnn.nnn/mm
    +Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
    +
+

Description

+

La directive Allow indique un nom d'hôte, une adresse IP + ou un réseau qui est autorisé à accéder au serveur. Les directives +Allow se cumulent, ainsi plusieurs directives Allow + peuvent être utilisées pour autoriser l'accès à de multiples hôtes + et/ou réseaux. La notation /mm indique une notation de + sous-réseau CIDR: +

+ + + + + + +
mmnetmask + mmnetmask
00.0.0.0 + 8255.0.0.0
1128.0.0.0 + 16255.255.0.0
2192.0.0.0 + 24255.255.255.0
...... + 32255.255.255.255
+
+

+

La directive Allow doit apparaître à l'intérieur d'une + directive Location. + +

+

AuthClass

+
+

Exemples

+
    +
    +AuthClass Anonymous
    +AuthClass User
    +AuthClass System
    +AuthClass Group
    +
    +
+

Description

+

La directive AuthClass définit le niveau + d'authentification requis:

+
    +
  • Anonymous - Pas d'authentification nécessaire. C'est la + valeur implicite
  • +
  • User - Un nom d'utilisateur et un mot de passe valides + sont requis.
  • +
  • System - Un nom d'utilisateur et un mot de passe + valides sont requis, et cet utilisateur doit être membre du groupe + "sys"; cela peut être changé au moyen de la directive +SystemGroup.
  • +
  • Group - Un nom d'utilisateur et un mot de passe valides + sont requis, et cet utilisateur doit être membre du groupe indiqué dans + la directive AuthGroupName.
  • +
+

La directive AuthClass doit apparaître à l'intérieur + d'une directive Location. + +

+

AuthGroupName

+
+

Exemples

+
    +
    +AuthGroupName mygroup
    +AuthGroupName lp
    +
    +
+

Description

+

La directive AuthGroupName définit le groupe à utiliser + pour l'authentification de type Group.

+

La directive AuthGroupName doit apparaître à l'intérieur + d'une directive Location. + +

+

AuthType

+
+

Exemples

+
    +
    +AuthType None
    +AuthType Basic
    +AuthType Digest
    +AuthType BasicDigest
    +
    +
+

Description

+

La directive AuthType définit le type d'authentification + qui doit être effectuée:

+
    +
  • None - Pas d'authentification. C'est la valeur + implicite
  • +
  • Basic - Une authentification "Basic" doit être + effectuée en utilisant le fichier de mots de passe et de groupe d'UNIX.
  • +
  • Digest - Une authentification "Digest" doit être + effectuée en utilisant le fichier /etc/cups/passwd.md5.
  • +
  • BasicDigest - Une authentification "Basic" doit être + effectuée en utilisant le fichier /etc/cups/passwd.md5.
  • +
+

Lorsque vous utilisez Basic, Digest, ou +BasicDigest, les clients se connectant en utilisant l'adresse +localhost peuvent également le faire en utilisant les + certificats.

+

La directive AuthType doit apparaître à l'intérieur + d'une directive Location. + +

+

AutoPurgeJobs

+
+

Exemples

+
    +
    +AutoPurgeJobs Yes
    +AutoPurgeJobs No
    +
    +
+

Description

+

La directive AutoPurgeJobs indique si oui ou non il faut + purger les travaux d'impression lorsqu'ils ne sont plus nécessaires au + vu des quotas. Cet option n'a aucun effet si les quotas ne sont pas + activés. La valeur implicite est No. + +

+

BrowseAddress

+
+

Exemples

+
    +
    +BrowseAddress 255.255.255.255:631
    +BrowseAddress 192.0.2.255:631
    +BrowseAddress host.domain.com:631
    +
    +
+

Description

+

La directive BrowseAddress indique une adresse à + laquelle il faut envoyer les informations d'exploration. Plusieurs + directives BrowseAddress peuvent être indiquées pour + envoyer les informations d'exploration à différents systèmes ou + réseaux.

+

La valeur implicite de l'adresse est 255.255.255.255:631 + ce qui diffusera les informations à tous les réseaux auxquels le + serveur est connecté. +

+ + +
NOTA: +

Si vous utilisez HP-UX 10.20 sur un sous-réseau dont le masque n'est + pas sur 24, 16 ou 8 bits, l'exploration des imprimantes (et en fait + toute réception d'information diffusée) ne fonctionnera pas. Ce + problème semble résolu dans HP-UX 11.0.

+
+
+ + +

+

BrowseAllow

+
+

Exemples

+
    +
    +BrowseAllow from all
    +BrowseAllow from none
    +BrowseAllow from 192.0.2
    +BrowseAllow from 192.0.2.0/24
    +BrowseAllow from 192.0.2.0/255.255.255.0
    +BrowseAllow from *.domain.com
    +
    +
+

Description

+

La directive BrowseAllow indique un système dont on + accepte de recevoir des paquets d'exploration. Le comportement + implicite est d'accepter des paquets d'exploration de n'importe quel + hôte.

+

Le contrôle sur la base du nom d'hôte et de domaine impose que vous + activiez la directive HostNameLookups +.

+

Le contrôle sur la base de l'adresse IP prend en charge les + correspondances exactes, les adresses partielles qui correspondent à + des réseaux dont le masque est 255.0.0.0, 255.255.0.0, et + 255.255.255.0, ou des adresses réseau utilisant le masque indiqué. + +

+

BrowseDeny

+
+

Exemples

+
    +
    +BrowseDeny from all
    +BrowseDeny from none
    +BrowseDeny from 192.0.2
    +BrowseDeny from 192.0.2.0/24
    +BrowseDeny from 192.0.2.0/255.255.255.0
    +BrowseDeny from *.domain.com
    +
    +
+

Description

+

La directive BrowseDeny indique un système dont on + refuse de recevoir des paquets d'exploration. Le comportement implicite + est de ne refuser aucun paquet d'exploration d'aucun hôte.

+

Le contrôle sur la base du nom d'hôte et de domaine impose que vous + activiez la directive HostNameLookups +.

+

Le contrôle sur la base de l'adresse IP prend en charge les + correspondances exactes, les adresses partielles qui correspondent à + des réseaux dont le masque est 255.0.0.0, 255.255.0.0, et + 255.255.255.0, ou des adresses réseau utilisant le masque indiqué. + +

+

BrowseOrder

+
+

Exemples

+
    +
    +BrowseOrder allow,deny
    +BrowseOrder deny,allow
    +
    +
+

Description

+

La directive BrowseOrder indique l'ordre de traitement + accord/refus. L'ordre implicite est deny,allow:

+
    +
  • allow,deny - Les paquets d'exploration sont acceptés à + moins qu'ils ne soient explicitement refusés.
  • +
  • deny,allow - Les paquets d'exploration sont rejetés à + moins qu'ils ne soient explicitement acceptés.
  • +
+ + +

BrowseInterval

+
+

Exemples

+
    +
    +BrowseInterval 0
    +BrowseInterval 30
    +
    +
+

Description

+

La directive BrowseInterval indique le délai maximum + entre deux mises à jour de l'exploration. Le fait d'indiquer une valeur + de 0 interdit de diffuser des mises à jour mais autorise néanmoins un + serveur à recevoir des mises à jour en provenance d'autres hôtes.

+

La valeur BrowseInterval devrait toujours être + inférieure à la valeur BrowseTimeout +. Sinon des imprimantes et des classes pourraient disparaître des + système clients entre les mises à jour. + +

+

BrowsePoll

+
+

Exemples

+
    +
    +BrowsePoll 192.0.2.2:631
    +BrowsePoll host.domain.com:631
    +
    +
+

Description

+

La directive BrowsePoll collecte la liste des + imprimantes disponibles sur un serveur une fois toutes les + BrowseInterval secondes. Plusieurs directives +BrowsePoll peuvent être indiquées pour surveiller plusieurs + serveurs.

+

Si BrowseInterval est mis à 0 alors le serveur est + surveillé une fois toutes les 30 secondes. + +

+

BrowsePort

+
+

Exemples

+
    +
    +BrowsePort 631
    +BrowsePort 9999
    +
    +
+

Description

+

La directive BrowsePort indique un numéro de port UDP à + employer pour les échanges de paquets d'exploration. La valeur + implicite est 631. +

+ + +
NOTE: +

Vous devez choisir une valeur identique pour la directive +BrowsePort sur tous les systèmes que vous voulez voir.

+
+
+ + +

+

BrowseProtocols

+
+

Exemples

+
    +
    +BrowseProtocols CUPS
    +BrowseProtocols SLP
    +BrowseProtocols CUPS SLP
    +BrowseProtocols all
    +
    +
+

Description

+

La directive BrowseProtocols indique les protocoles à + employer pour collecter et distribuer les informations sur les + imprimantes partagées sur le réseau local. Le protocole implicite est +CUPS, c'est un protocole basé sur la diffusion réseau + ("broadcast"). +

+ + +
NOTE: +

Lorsque vous utilisez le protocole SLP, vous devez avoir + au moins un serveur "Directory Agent" (DA) sur votre réseau. A défaut, + l'ordonnanceur CUPS (cupsd) ne répondra pas aux requêtes + des clients pendant plusieurs secondes pendant qu'il sera en train + d'explorer le réseau.

+
+
+ + +

+

BrowseRelay

+
+

Exemples

+
    +
    +BrowseRelay 193.0.2.1 192.0.2.255
    +BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
    +BrowseRelay 193.0.2.0/24 192.0.2.255
    +BrowseRelay *.domain.com 192.0.2.255
    +BrowseRelay host.domain.com 192.0.2.255
    +
    +
+

Description

+

la directive indique des adresses source et destination pour relayer + les informations d'exploration en provenance d'un hôte ou d'un réseau + vers un autre. Plusieurs directives BrowseRelay peuvent + être indiquées si nécessaire.

+

BrowseRelay est généralement utilisé sur des systèmes + qui assurent la passerelle entre des réseaux multiples au moyen d'une + ou plusieurs interfaces réseau. Elle peut également être utilisée pour + relayer des informations sur les imprimantes provenant de serveurs + surveillés, au moyen de la ligne:

+
    +
    +BrowseRelay 127.0.0.1 255.255.255.255
    +
    +
+

Cela fournit un accès effectif aux imprimantes d'un WAN pour tous les + clients d'un LAN. + +

+

BrowseShortNames

+
+

Exemples

+
    +
    +BrowseShortNames Yes
    +BrowseShortNames No
    +
    +
+

Description

+

La directive BrowseShortNames indique s'il faut ou non + utiliser les noms courts pour les imprimantes à distance. Les noms + courts sont simplement composés du nom de l'imprimante, sans celui du + serveur ("imprimante"). Si le système détecte plus d'une imprimante à + distance portant le même nom, les imprimantes seront affichées avec les + noms longs ("imprimante@erveur1", "imprimante@erveur2")

+

La valeur implicite de cette option est Yes. + +

+

BrowseTimeout

+
+

Exemples

+
    +
    +BrowseTimeout 300
    +BrowseTimeout 60
    +
    +
+

Description

+

La directive BrowseTimeout fixe la durée de vie des + informations reçues sous forme de paquets d'exploration et concernant + les imprimantese et les classes. Une fois que les informations + concernant une imprimante ou une classe dépassent ce délai, elles sont + retirées de la liste des destinations disponibles.

+

La valeur BrowseTimeout devrait toujours être supérieure + à la valeur BrowseInterval. + Sinon des imprimantes et des classes pourraient disparaîtres des + systèmes clients entre les mises à jour. + +

+

Browsing

+
+

Exemples

+
    +
    +Browsing On
    +Browsing Off
    +
    +
+

Description

+

La directive Browsing contrôle l'activation ou non de + l'exploration réseau des imprimantes. La valeur implicite est On +. +

+ + +
NOTE: +

Si vous utilisez HP-UX 10.20 sur un sous-réseau dont le masque n'est + pas sur 24, 16 ou 8 bits, l'exploration des imprimantes (et en fait + toute réception d'information diffusée) ne fonctionnera pas. Ce + problème semble résolu dans HP-UX 11.0.

+
+
+ + +

+

Classification

+
+

Exemples

+
    +
    +Classification
    +Classification classified
    +Classification confidential
    +Classification secret
    +Classification topsecret
    +Classification unclassified
    +
    +
+

Description

+

La directive Classification fixe le niveau de + classification sur le serveur. Lorsque cette option est activée au + moins une des pages de garde est forcée à ce niveau et l'information de + classification est placée sur chaque page imprimée. La valeur implicite + est de n'avoir aucun niveau de classification. + +

+

ClassifyOverride

+
+

Exemples

+
    +
    +ClassifyOverride Yes
    +ClassifyOverride No
    +
    +
+

Description

+

La directive ClassifyOverride indique si les + utilisateurs peuvent outrepasser le niveau de classification du serveur + ou non. Lorsque la classification du serveur est activée, les + utilisateurs peuvent changer la classification en employant l'option +job-sheets et peuvent choisir de n'imprimer qu'une seule page de + garde de sécurité avant ou après le travail d'impression. Si l'option +job-sheets est positionnée à la valeur none alors le + niveau de classification implicite du serveur est utilisé.

+

La valeur implicite est de ne pas autoriser les utilisateurs à + outrepasser la classification. + +

+

DataDir

+
+

Exemples

+
    +
    +DataDir /usr/share/cups
    +
    +
+

Description

+

La directive DataDir fixe le répertoire à employer pour + les fichiers de données. + +

+

DefaultCharset

+
+

Exemples

+
    +
    +DefaultCharset utf-8
    +DefaultCharset iso-8859-1
    +DefaultCharset windows-1251
    +
    +
+

Description

+

La directive DefaultCharset définit le jeu de caractères + à utiliser pour les connexions avec les clients. Le jeu de caractère + implicite est le jeu utf-8 mais il est outrepassé par le + jeu de caractères associé à la langue indiquée par le client ou par la + directive DefaultLanguage. + +

+

DefaultLanguage

+
+

Exemples

+
    +
    +DefaultLanguage de
    +DefaultLanguage en
    +DefaultLanguage es
    +DefaultLanguage fr
    +DefaultLanguage it
    +
    +
+

Description

+

La directive DefaultLanguage définit le langage à + utiliser pour les connexions avec les clients. Régler la langue règle + également le jeu de caractères si un fichier de localisation existe + pour celle-ci. La valeur implicite est "en" c'est-à-dire "anglais". + +

+

Deny

+
+

Exemples

+
    +
    +Deny from All
    +Deny from None
    +Deny from *.domain.com
    +Deny from .domain.com
    +Deny from host.domain.com
    +Deny from nnn.*
    +Deny from nnn.nnn.*
    +Deny from nnn.nnn.nnn.*
    +Deny from nnn.nnn.nnn.nnn
    +Deny from nnn.nnn.nnn.nnn/mm
    +Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
    +
+

Description

+

La directive Deny indique un nom d'hôte, une adresse IP + ou un réseau qui n'est pas autorisé à accéder au serveur. Les + directives Deny se cumulent, ainsi plusieurs directives +Deny peuvent être utilisées pour interdire l'accès à de multiples + hôtes et/ou réseaux. La notation /mm indique une notation + de sous-réseau CIDR: +

+ + + + + + +
mmnetmask + mmnetmask
00.0.0.0 + 8255.0.0.0
1128.0.0.0 + 16255.255.0.0
2192.0.0.0 + 24255.255.255.0
...... + 32255.255.255.255
+
+

+

La directive Deny doit apparaître à l'intérieur d'une + directive Location. + +

+

DocumentRoot

+
+

Exemples

+
    +
    +DocumentRoot /usr/share/doc/cups
    +DocumentRoot /foo/bar/doc/cups
    +
    +
+

Description

+

La directive DocumentRoot indique l'emplacement du + contenu que le serveur HTTP de CUPS doit publier. Si un chemin absolu + n'est pas indiqué, celui-ci est considéré comme relatif au répertoire + ServerRoot. La valeur implicite est + /usr/share/doc/cups.

+

Les documents sont d'abord recherchés dans un sous-répertoire + correspondant à la langue demandée par le client (par exemple + /usr/share/doc/cups/fr/...) et ensuite directement dans le + répertoire DocumentRoot (par exemple + /usr/share/doc/cups/...), ainsi il est possible de localiser le + contenu "web" en fournissant des sous-répertoires pour chaque langue + nécessaire. + +

+

Encryption

+
+

Exemples

+
    +
    +Encryption Never
    +Encryption IfRequested
    +Encryption Required
    +Encryption Always
    +
    +
+

Description

+

La directive Encryption doit apparaître à l'intérieur + d'une section Location et définit + les réglages d'encryptage pour cet emplacement. Le réglage implicite + est IfRequested pour tous les emplacements. + +

+

ErrorLog

+
+

Exemples

+
    +
    +ErrorLog /var/log/cups/error_log
    +ErrorLog /var/log/cups/error_log-%s
    +ErrorLog syslog
    +
    +
+

Description

+

La directive ErrorLog définit le nom du fichier de suivi + d'erreurs ("error log"). Si le nom de fichier n'est pas un chemin + absolu, il est considéré comme un chemin relatif au répertoire + ServerRoot. Le fichier standard est + /var/log/cups/error_log.

+

Le nom du serveur peut être inclus dans le nom du fichier en + utilisant le nom %s.

+

Le nom spécial "syslog" peut être utilisé pour envoyer les + informations de suivi d'erreurs vers le fichier de suivi d'erreur + système au lieu d'un fichier texte simple. + +

+

FilterLimit

+
+

Exemples

+
    +
    +FilterLimit 0
    +FilterLimit 200
    +FilterLimit 1000
    +
    +
+

Description

+

La directive FilterLimit définit le coût maximal de tous + les filtres appliqués au travaux en cours de traitement. Elle peut être + utilisée pour limiter le nombre de programmes de filtres qui son + exécutés dans un serveur pour minimiser les problèmes de ressources + disque, mémoire ou CPU. Une limite de 0 désactive la limitation des + filtres.

+

Le coût moyen d'une impression vers une imprimante non-PostScript + nécessite une limitation de filtre aux alentours de 200. Une imprimante + PostScript nécessite une limite d'environ la moitié (100). Positionner + la limite en dessous de ces seuils va effectivement limiter + l'ordonnanceur à l'impression d'un travail à la fois.

+

La valeur implicite est 0. + +

+

FontPath

+
+

Exemples

+
    +
    +FontPath /foo/bar/fonts
    +FontPath /usr/share/cups/fonts:/foo/bar/fonts
    +
    +
+

Description

+

La directive FontPath définit le chemin de recherche des + polices de caractères à utiliser. La valeur implicite est +/usr/share/cups/fonts. + +

+

Group

+
+

Exemples

+
    +
    +Group sys
    +Group system
    +Group root
    +
    +
+

Description

+

La directive Group définit le groupe UNIX sous + l'identité duquel les programmes CGI et de filtrage fonctionnent. Le + groupe implicite est sys, system, ou +root selon le système d'exploitation. + +

+

HideImplicitMembers

+
+

Exemples

+
    +
    +HideImplicitMembers Yes
    +HideImplicitMembers No
    +
    +
+

Description

+

La directive HideImplicitMembers contrôle l'appartenance + ou non d'imprimantes individuelles aux classes implicites qui sont + montrées à l'utilisateur. La valeur standard est No.

+

ImplicitClasses doit être + activée pour que cette directive ait un quelconque effet.

+ + +

HostNameLookups

+
+

Exemples

+
    +
    +HostNameLookups On
    +HostNameLookups Off
    +HostNameLookups Double
    +
    +
+

Description

+

La directive HostNameLookups indique si CUPS doit ou non + rechercher le nom d'hôte des clients qui se connectent. La clause +Double force CUPS à vérifier que le nom d'hôte trouvé à partir de + l'adresse correspond bien à l'une des adresses retournées pour ce nom + d'hôte. Les recherches Double empêchent également que des + clients ayant des adresses non enregistrées ne se connectent au + serveur. La valeur implicite est Off pour éviter tout + problème potentiel de performance du serveur du fait des résolutions de + nom. Positionnez cette directive à la valeur On ou +Double uniquement si nécessaire. + +

+

ImplicitClasses

+
+

Exemples

+
    +
    +ImplicitClasses On
    +ImplicitClasses Off
    +
    +
+

Description

+

La directive ImplicitClasses contrôle si les classes + implicites sont créées sur la base des imprimantes et classes + disponibles sur le réseau. La valeur implicite est On mais + est automatiquement positionnée sur Off si + Browsing est à la valeur Off. + +

+

ImplicitAnyClasses

+
+

Exemples

+
    +
    +ImplicitAnyClasses On
    +ImplicitAnyClasses Off
    +
    +
+

Description

+

La directive ImplicitAnyClasses contrôle si oui ou non + les classes implicites pour les imprimantes locales et à distance sont + crées avec le nom AnyPrinter. La valeur implicite est +Off.

+

ImplicitClasses doit être + activée pour que cette directive ait un quelconque effet.

+ + +

Include

+
+

Exemples

+
    +
    +Include filename
    +Include /foo/bar/filename
    +
    +
+

Description

+

La directive Include inclut le fichier indiqué dans le + corps du fichier cupsd.conf. Si aucun chemin n'est + indiqué, le fichier est considéré comme étant relatif au répertoire + ServerRoot.

+ + +

KeepAlive

+
+

Exemples

+
    +
    +KeepAlive On
    +KeepAlive Off
    +
    +
+

Description

+

La directive KeepAlive contrôle la prise en charge ou + non des connexions HTTP persitantes. La valeur implicite est On +.

+

Les clients HTTP/1.1 prennent automatiquement en charge les + connexions persistantes, tandis que clients HTTP/1.0 doivent + spécifiquement les demander en utiliser l'attribut Keep-Alive + attribute dans le champ Connection: de chaque requête. + +

+

KeepAliveTimeout

+
+

Exemples

+
    +
    +KeepAliveTimeout 60
    +KeepAliveTimeout 30
    +
    +
+

Description

+

La directive KeepAliveTimeout contrôle combien de temps + une connexion HTTP persistante restera ouverte après la dernière + requête. La valeur implicite est de 60 secondes. + +

+

Limit

+
+

Exemples

+
    +
    +<Limit GET POST>
    +...
    +</Limit>
    +
    +<Limit ALL>
    +...
    +</Limit>
    +
    +
+

Description

+

La directive Limit groupe les directives de contrôle + d'accès pour certains types spécifiques de requêtes HTTP et doit + apparaître à l'intérieur d'une section +Location. L'accès peut être limité à des types individuels de + requêtes (DELETE, GET, HEAD , +OPTIONS, POST, PUT, et TRACE +) ou pour tous les types de requêtes (ALL). Les noms de + types de requêtes sont dépendants de la casse pour des raisons de + compatibilité avec Apache. + +

+

LimitExcept

+
+

Exemples

+
    +
    +<LimitExcept GET POST>
    +...
    +</LimitExcept>
    +
    +
+

Description

+

La directive LimitExcept groupe les directives de + contrôle d'accès pour certains types spécifiques de requêtes HTTP et + doit apparaître à l'intérieur d'une section +Location. Contrairement à la directive +Limit, LimitExcept restreint l'accès pour toutes + les requêtes à l'exception de celles listées dans la ligne +LimitExcept. + +

+

LimitRequestBody

+
+

Exemples

+
    +
    +LimitRequestBody 10485760
    +LimitRequestBody 10m
    +LimitRequestBody 0
    +
    +
+

Description

+

La directive LimitRequestBody contrôle la taille + maximale des fichiers d'impression, des requêtes IPP, et des données + des formulaires HTML dans les requêtes HTTP POST. La limite implicite + est de 0 ce qui désactive la vérification de la limite.

+

Reportez-vous également à la directive similaire + MaxRequestSize. + +

+

Listen

+
+

Exemples

+
    +
    +Listen 127.0.0.1:631
    +Listen 192.0.2.1:631
    +
    +
+

Description

+

La directive Listen indique une adresse réseau et un + port sur lequel écouter en attente de connexions. Plusieurs directives +Listen peuvent être indiquées pour écouter sur de multiples + adresses.

+

La directive Listen est similaire à la directive + Port mais vous permet de restreindre l'accès à des + interfaces ou des réseaux spécifiques. + +

+

Location

+
+

Exemples

+
    +
    +<Location />
    +...
    +</Location>
    +
    +<Location /admin>
    +...
    +</Location>
    +
    +<Location /printers/name>
    +...
    +</Location>
    +
    +
+

Description

+

La directive Location indique des options de contrôle + d'accès et d'authentification pour le chemin ou la ressource HTTP + indiquée. Des informations supplémentaires sont disponibles plus loin + dans le chapitre dans la section "Sécurité + du système d'impression". + +

+

LogLevel

+
+

Exemples

+
    +
    +LogLevel none
    +LogLevel emerg
    +LogLevel alert
    +LogLevel crit
    +LogLevel error
    +LogLevel warn
    +LogLevel notice
    +LogLevel info
    +LogLevel debug
    +LogLevel debug2
    +
    +
+

Description

+

La directive LogLevel indique la quantité d'informations + à consigner dans le fichier ErrorLog +. Les valeurs suivantes sont reconnues (chaque niveau inclut tout ce qui + l'est dans les niveaux inférieurs):

+
    +
  • none - Ne consigne rien.
  • +
  • emerg - Consigne les conditions d'urgence qui empêchent + le serveur de fonctionner.
  • +
  • alert - Consigne les alertes qui doivent être traitées + immédiatement.
  • +
  • crit - Consigne les erreurs critiques qui n'empêchent + pas le serveur de fonctionner.
  • +
  • error - Consigne les erreurs générales.
  • +
  • warn - Consigne les erreurs et les avertissements.
  • +
  • notice - Consigne les conditions d'erreurs temporaires.
  • +
  • info - Consigne toutes les requêtes de modifications et + de changement d'état (valeur implicite).
  • +
  • debug - Consigne des informations basiques de débogage.
  • +
  • debug2 - Consigne toutes les informations de débogage.
  • +
+ + +

MaxClients

+
+

Exemples

+
    +
    +MaxClients 100
    +MaxClients 1024
    +
    +
+

Description

+

La directive MaxClients contrôle le nombre maximum de + clients simultanés qui seront autorisés par le serveur. La valeur + implicite ("par défaut") est de 100 clients. +

+ + +
NOTE: +

Etant donné que chaque travail d'impression demande un descripteur de + fichier pour le tube de contrôle, le serveur CUPS limite de manière + interne la valeur MaxClients au tiers des descripteurs de + fichiers disponibles pour éviter les possibles problèmes lors de + l'impression de nombreux travaux d'impression.

+
+
+ + +

+

MaxJobs

+
+

Exemples

+
    +
    +MaxJobs 100
    +MaxJobs 9999
    +MaxJobs 0
    +
    +
+

Description

+

La directive MaxJobs contrôle le nombre maximum de + travaux d'impression qui sont conservés en mémoire. Dès que le nombre + de travaux atteint la limite, le plus ancien travail complété est + automatiquement purgé du système pour libérer de l'espace pour le + nouveau travail. Si tous les travaux connus sont toujours en attente de + traitement ou actifs, alors le nouveau travail sera rejeté.

+

Régler cette valeur sur 0 (valeur implicite) désactive cette + fonctionnalité. + +

+

MaxJobsPerPrinter

+
+

Exemples

+
    +
    +MaxJobsPerPrinter 100
    +MaxJobsPerPrinter 9999
    +MaxJobsPerPrinter 0
    +
    +
+

Description

+

La directive MaxJobsPerPrinter contrôle le nombre + maximum de travaux actifs qui sont autorisés pour chaque imprimante ou + classe d'imprimantes. Dès que le nombre est atteint pour une imprimante + ou une classe, les nouveaux travaux sont rejetés tant que l'un des + travaux actifs n'est pas complété, arrêté, annulé ou abandonné.

+

Régler le maximum sur la valeur 0 (valeur implicite) désactive cette + fonctionnalité. + +

+

MaxJobsPerUser

+
+

Exemples

+
    +
    +MaxJobsPerUser 100
    +MaxJobsPerUser 9999
    +MaxJobsPerUser 0
    +
    +
+

Description

+

La directive MaxJobsPerUser contrôle le nombre maximum + de travaux d'impression qui sont autorisés pour chaque utilisateur. Dès + qu'un utilsateur atteint le maximum autorisé, tout nouveau travail sera + rejeté avant qu'un des travaux actifs soit complété, arrêté, annulé ou + abandonné.

+

Régler le maximum sur 0 (valeur implicite) désactive cette + fonctionnalité. + +

+

MaxLogSize

+
+

Exemples

+
    +
    +MaxLogSize 1048576
    +MaxLogSize 1m
    +MaxLogSize 0
    +
    +
+

Description

+

La directive MaxLogSize contrôle la taille maximum de + chaque fichier de suivi ("log"). Dès qu'un fichier atteint ou dépasse + la limite il est fermé ou renommé en filename.O. Cela vous + permet de mettre en place automatiquement une rotation des fichiers de + suivi. La taille implicite est de 1048576 octets (1Mo).

+

Régler le maximum sur 0 désactive la rotation de fichier de suivi. + +

+

MaxRequestSize

+
+

Exemples

+
    +
    +MaxRequestSize 10485760
    +MaxRequestSize 10m
    +MaxRequestSize 0
    +
    +
+

Description

+

La directive MaxRequestSize contrôle la taille maximum + des fichiers d'impression, des requêtes IPP, et des données des + formulaires HTML contenus dans les requêtes HTTP POST. La valeur + implicite est 0, ce qui désactive cette vérification de limite.

+

Reportez-vous également à la directive similaire + LimitRequestBody. + +

+

Order

+
+

Exemples

+
    +
    +Order Allow,Deny
    +Order Deny,Allow
    +
    +
+

Description

+

La directive Order définit le type implicite de contrôle + d'accès. Les valeurs suivantes sont prises en charge:

+
    +
  • Allow,Deny - Autorise les requêtes depuis tous les + systèmes à l'exception de ceux listés dans une directive +Deny.
  • +
  • Deny,Allow - Autorise les requêtes uniquement depuis + les hôtes listés dans une directive Allow.
  • +
+

La directive Order doit apparaître à l'intérieur d'une + directive Location. + +

+

PageLog

+
+

Exemples

+
    +
    +PageLog /var/log/cups/page_log
    +PageLog /var/log/cups/page_log-%s
    +PageLog syslog
    +
    +
+

Description

+

La directive PageLog définit le nom du fichier "page + log". Si le nom du fichier n'est pas absolu, il est considéré comme + étant relatif au répertoire ServerRoot +. Le fichier standard "page log" est /var/log/cups/page_log +.

+

Le nom du serveur peut être inclus dans le nom de fichier en + utilisant le nom %s.

+

Le nom spécial "syslog" peut être utilisé pour envoyer les + informations de page vers le fichier de suivi système au lieu d'un + simple fichier texte. + +

+

Port

+
+

Exemples

+
    +
    +Port 631
    +Port 80
    +
    +
+

Description

+

La directive Port indique un port sur lequel écouter en + attente de connexions. Plusieurs lignes Port peuvent être + indiquées pour écouter sur plusieurs ports. La valeur implicite est + 631. + +

+

PreserveJobHistory

+
+

Exemples

+
    +
    +PreserveJobHistory On
    +PreserveJobHistory Off
    +
    +
+

Description

+

La directive PreserveJobHistory contrôle si l'historique + des travaux complétés, annulés ou abandonnés est conservé sur disque ou + non.

+

Une valeur On (valeur implicite) conserve les + informations concernant les travaux jusqu'à ce que l'administrateur les + purge avec la commande cancel.

+

Une valeur Off retire les informations concernant les + travaux dès que ceux-ci sont complétés, annulés ou abandonnés. + +

+

PreserveJobFiles

+
+

Exemples

+
    +
    +PreserveJobFiles On
    +PreserveJobFiles Off
    +
    +
+

Description

+

La directive PreserveJobFiles contrôle si les fichiers + des documents complétés, annulés ou abandonnés sont stockés sur disque.

+

La valeur On conserve les fichiers des travaux jusqu'à + ce que l'administrateur les purge au moyen de la commande cancel +. Les travaux peuvent être resoumis (réimprimés) jusqu'à ce qu'ils + soient purgés.

+

La valeur Off (valeur implicite) retire les fichiers des + travaux dès ceux-ci sont complétés, annulés ou abandonnés. + +

+

Printcap

+
+

Exemples

+
    +
    +Printcap
    +Printcap /etc/printcap
    +Printcap /etc/printers.conf
    +
    +
+

Description

+

La directive Printcap contrôle si le fichier printcap + est automatiquement généré et mis à jour ou non avec une liste des + imprimantes disponibles. Si la directive est utilisée sans valeur, + alors aucun fichier printcap ne sera généré. La valeur implicite est de + générer un fichier nommé /etc/printcap.

+

Quand un nom de fichier est indiqué (par exemple /etc/printcap +), le fichier printcap est écrit dès qu'une imprimante est ajoutée ou + supprimée. Le fichier printcap peut alors être utilisé par les + applications dont l'utilisation du fichier printcap comme référence des + imprimantes disponibles est codée en dur. + +

+

PrintcapFormat

+
+

Exemples

+
    +
    +PrintcapFormat BSD
    +PrintcapFormat Solaris
    +
    +
+

Description

+

La directive PrintcapFormat contrôle le format de sortie + du fichier printcap. Le comportement implicite est de générer un + fichier printcap de type BSD. + +

+

PrintcapGUI

+
+

Example

+
    +
    +PrintcapGUI /usr/bin/glpoptions
    +
    +
+

Description

+

La directive PrintcapGUI indique le programme à utiliser + pour afficher le panneau d'options à partir d'une application IRIX qui + utiliser l'API d'impression Impressario. Le programme implicite est le + programme graphique "glpoptions" d'ESP Print Pro.

+

Le programme doit accepter l'option -d pour indiquer + l'imprimante et l'option -o pour indiquer une ou plusieurs + options. Après avoir autorisé l'utilisateur à sélectionner/changer les + options, le programme doit écrire la liste des options d'impression + sans le -o sur la sortie standard. + +

+

RemoteRoot

+
+

Exemples

+
    +
    +RemoteRoot remroot
    +RemoteRoot root
    +
    +
+

Description

+

La directive RemoteRoot fixe le nom d'utilisateur à + utiliser pour les requêtes root non authentifiées depuis des hôtes + distants. Le nom d'utilisateur standard est remroot. Régler +RemoteRoot sur root désactive effectivement ce + mécanisme de sécurité. + +

+

RequestRoot

+
+

Exemples

+
    +
    +RequestRoot /var/spool/cups
    +RequestRoot /foo/bar/spool/cups
    +
    +
+

Description

+

La directive RequestRoot définit le répertoire pour les + requêtes entrantes IPP et les formulaires HTML. Si un chemin absolu + n'est pas fourni alors il est considéré comme relatif au répertoire + ServerRoot. Le répertoire implicite est + /var/spool/cups. + +

+

Require

+
+

Exemples

+
    +
    +Require group foo bar
    +Require user john mary
    +Require valid-user
    +
    +
+

Description

+

La directive Require indique que l'authentification est + nécessaire pour l'accès à la ressource considérée. Le mot clef +group indique que l'utilisateur authentifié doit être membre d'un + ou plusieurs des groupes qui suivent.

+

Le mot clef user indique que l'utilisateur authentifié + doit être l'un des utilisateurs dont les noms suivent.

+

Le mot clef valid-user indique que tout utilisateur + authentifié peut accéder à la ressource.

+

Le comportement implicite ("par défaut") est de ne faire aucune + authentification. Cette directive doit apparaître à l'intérieur d'une + directive Location. + +

+

RIPCache

+
+

Exemples

+
    +
    +RIPCache 8m
    +RIPCache 1g
    +RIPCache 2048k
    +
    +
+

Description

+

La directive RIPCache définit la quantité de mémoire + utilisée par les filtres RIP ("Raster Images Processor") tels que +imagetoraster et pstoraster. La taille peut être + suffixée par "k" pour kilo-octets, "m" pour méga-octets, ou "g" pour + giga-octets. La taille implicite est de "8m", ou 8 méga-octets. + +

+

RunAsUser

+
+

Exemples

+
    +
    +RunAsUser Yes
    +RunAsUser No
    +
    +
+

Description

+

La directive RunAsUser contrôle si l'ordonnanceur + fonctionne sous l'identité d'un compte utilisateur non privilégié + (habituellement lp). La valeur implicite est No + qui laisse l'utilisateur fonctionner en tant qu'utilisateur root +.

+

Note: Faire fonctionner CUPS en tant qu'utilisateur non + privilégié peut empêcher LPD et les imprimantes connectées localement + de fonctionner correctement en raison de problèmes de permissions. Le + programme d'arrière-plan lpd utilisera automatiquement le + mode non privilégié ce qui est 100% conforme à la RFC 1179. Les + programmes d'arrière-plan parallel, serial, + et usb auront besoin d'accès en écriture aux fichiers de + périphériques correspondants. + +

+

Satisfy

+
+

Exemples

+
    +
    +Satisfy all
    +Satisfy any
    +
    +
+

Description

+

La directive Satisfy indique si toutes les conditions + doivent être satisfaites pour ouvrir l'accès à la ressource. Si la + valeur est all alors toutes les conditions + d'authentification et de contrôle d'accès doivent être satisfaites pour + que l'accès soit autorisé.

+

Régler Satisfy à la valeur any autorise un + utilisateur à obtenir l'accès si l'authentification ou le contrôle + d'accès est satisfait. Par exemple, vous pourriez exiger + l'authentifiation pour l'accès à distance mais autoriser l'accès local + sans elle.

+

La valeur implicite est all. Cette directive doit + apparaître à l'intérieur d'une directive +Location. + +

+

ServerAdmin

+
+

Exemples

+
    +
    +ServerAdmin user@host
    +ServerAdmin root@foo.bar.com
    +
    +
+

Description

+

La directive ServerAdmin identifie l'adresse de courriel + de l'administrateur du système. La valeur implicite est +root@serveur, où server est le nom du serveur. + +

+

ServerBin

+
+

Exemples

+
    +
    +ServerBin /usr/lib/cups
    +ServerBin /foo/bar/lib/cups
    +
    +
+

Description

+

La directive ServerBin définit le répertoire contenant + les fichiers exécutables du serveur. Si un chemin absolu n'est pas + indiqué, il est considéré comme relatif au répertoire + ServerRoot . Le répertoire implicite est + /usr/lib/cups. + +

+

ServerCertificate

+
+

Exemples

+
    +
    +ServerCertificate /etc/cups/ssl/server.crt
    +
    +
+

Description

+

La directive ServerCertificate définit l'emplacement du + fichier de certificat SSL utilisé par le serveur lors de la négociation + des connexions encryptées. Le certificat ne doit pas être encrypté + (protégé par un mot de passe) car l'ordonnanceur fonctionne normalement + en arrière-plan et et ne sera pas en mesure de demander un mot de + passe. Le fichier standard de certificat est + /etc/cups/ssl/server.crt. + +

+

ServerKey

+
+

Exemples

+
    +
    +ServerKey /etc/cups/ssl/server.key
    +
    +
+

Description

+

La directive ServerKey indique l'emplacement du fichier + de clé privée SSL utilisé par le serveur pour négocier les connexions + encryptées. Le fichier standard de clé est + /etc/cups/ssl/server.crt . + +

+

ServerName

+
+

Exemples

+
    +
    +ServerName foo.domain.com
    +ServerName myserver.domain.com
    +
    +
+

Description

+

La directive ServerName indique le nom d'hôte qui doit + être envoyé aux clients. En standard, le nom du serveur est le nom + d'hôte. + +

+

ServerRoot

+
+

Exemples

+
    +
    +ServerRoot /etc/cups
    +ServerRoot /foo/bar/cups
    +
    +
+

Description

+

La directive ServerRoot indique un chemin absolu pour + les fichiers de configuration et d'état du serveur. Il est également + utilisé pour interpréter les chemins relatifs présents dans le fichier + cupsd.conf file. Le répertoire standard est /etc/cups. + +

+

SSLListen

+
+

Exemples

+
    +
    +SSLListen 127.0.0.1:443
    +SSLListen 192.0.2.1:443
    +
    +
+

Description

+

La directive SSLListen indique une adresse réseau et un + port sur lequel écouter les tentatives de connexion sécurisées. + Plusieurs directives SSLListen peuvent être fournies pour + indiquer plusieurs adresses sur lesquelles écouter.

+

La directive SSLListen est similaire à la directive + SSLPort mais vous permet de restreindre l'accès à + certaines interfaces ou réseaux. + +

+

SSLPort

+
+

Exemples

+
    +
    +SSLPort 443
    +
    +
+

Description

+

La directive SSLPort indique le port sur lequel écouter + les tentatives de connexions sécurisées. Plusieurs lignes SSLPort + peuvent être indiquées pour écouter les connexions sur plusieurs ports. + +

+

SystemGroup

+
+

Exemples

+
    +
    +SystemGroup sys
    +SystemGroup system
    +SystemGroup root
    +
    +
+

Description

+

La directive SystemGroup indique le groupe système + d'aministration pour l'authentification de type System. + Plus d'information peut être trouvée plus loin dans ce chapitre dans la + section "Sécurité du système d'impression" +. + +

+

TempDir

+
+

Exemples

+
    +
    +TempDir /var/tmp
    +TempDir /foo/bar/tmp
    +
    +
+

Description

+

La directive TempDir indique un chemin absolu pour le + répertoire à employer pour les fichiers temporaires. Le répertoire + standard est /var/tmp.

+

Les répertoires temporaires doivent être inscriptibles pour tous et + devraient avoir le "sticky" bit activé de sorte que les utilisateurs ne + puissent pas supprimer les fichiers temporaires de filtres. Les + commandes suivantes créerons un répertoire temporaire approprié appelé + /foo/bar/tmp:

+
    +
    +mkdir /foo/bar/tmp ENTREE
    +chmod a+rwxt /foo/bar/tmp ENTREE
    +
    +
+ + +

Timeout

+
+

Exemples

+
    +
    +Timeout 300
    +Timeout 90
    +
    +
+

Description

+

La directive Timeout définit le délai à attendre avant + qu'une requête HTTP ou IPP active ne soit hors délai. La valeur + implicite est de 300 secondes. + +

+

User

+
+

Exemples

+
    +
    +User lp
    +User guest
    +
    +
+

Description

+

La directive User indique l'utilisateur UNIX sous + l'identité duquel les programmes CGI et les filtres doivent + fonctionner. La valeur implicite est lp. + +

+

Sécurité du système d'impression

+

CUPS prend en charge le contrôle d'accès et l'authentification basée + sur l'adresse, un certificat ou un mot de passe (mode "Basic" et + "Digest"). Les authentifications par mot de passe et certificat + fournissent des moyens de limiter l'accès à certaines personnes ou + certains groupes.

+

Le contrôle d'accès basé sur l'adresse vous permet de limiter l'accès + à certains systèmes, réseaux ou domaines particuliers. Bien que cela ne + soit pas de l'authentification, cela vous permet de restreindre + efficacement le nombre potentiel d'utilisateurs de votre système.

+

CUPS maintient à jour une liste des emplacements dont + l'authentification et/ou le contrôle d'accès est/sont activé(e)(s). Ces + emplacements sont indiqués en utilisant la directive + Location:

+ +

Les emplacements suivent généralement la structure arborescente du + contenu du répertoire DocumentRoot +, cependant CUPS possède de nombreux emplacements virtuels pour + l'administration, les classes, les travaux d'impression et les + imprimantes: +

+ + + + + + + + + + +
EmplacementDescription
/adminLe chemin pour toutes les opérations + d'administration.
/classesLe chemin pour toutes les classes + d'imprimantes.
/classes/nom_classeLes ressources pour la classe nommée + nom_classe.
/jobsLe chemin pour tous les travaux d'impression.
/jobs/idLes ressources pour le travail d'impression n° +id.
/printersLe chemin pour toutes les imprimantes.
/printers/nom_imprimanteLe chemin pour l'imprimante + nommée nom_imprimante.
/printers/nom_imprimante.ppdLe chemin du fichier PPD + pour l'imprimante nom_imprimante.
+
+

+

Authentification basée sur les certificats +

+

CUPS prend en charge une authentification locale basée sur les + certificats qui peut être utilisée à la place des authentifications + "Basic" et "Digest" pour les clients se connectant à l'interface +localhost. L'authentification par certificats n'est ni prise en + charge, ni permise pour les clients se connectant par le biais de toute + autre interface.

+

Les certificats sont des nombres aléatoires codés sur 128 bits qui + font référence à un enregistrement interne d'authentification sur le + serveur. Un client se connectant via l'interface localhost + envoie une requête avec un en-tête d'autorisation:

+
    +
    +Authorization: Local 0123456789ABCDEF0123456789ABCDEF
    +
    +
+

Le serveur vérifie alors le certificat local correspondant et + authentifie le nom d'utilisateur qui y est associé.

+

Les certificats sont automatiquement générés par le serveur et + stockés dans le répertoire /etc/cups/certs en utilisant le + n° de processus du programme CGI ("process ID") exécuté par le serveur. + Les fichiers de certificats sont en lecture seule pour les utilisateurs User et groupes +Group définis dans le fichier cupsd.conf. Quand le + programme CGI se termine, le certificat est retiré et rendu + automatiquement invalide.

+

Le fichier spécial /etc/cups/certs/0 définit le + certificat de root qui peut être utilisé par tout client + fonctionnant sous l'identité du super-utilisateur et qui appartient au + group défini par la directive SystemGroup +. Le certificat de root est automatiquement régénéré toutes les 5 + minutes.

+

Utilisation de l'authentification "Basic"

+

L'authentification "Basic" utilise les utilisateurs et mots de passe + UNIX pour authentifier l'accès à des ressources telles que les + imprimantes ou les classes et pour limiter l'accès aux fonctions + d'administration. +

+ + +
NOTE: +

L'authentification "Basic" transmet le nom d'utilisateur et le mot de + passe en clair (encodage Base64) du client vers le serveur, donc elle + n'offre aucune protection contre l'espionnage. Cela signifie qu'une + utilisateur mal intentionné peut écouter les paquets réseau et + découvrir ces informations. Il peut en résulter une sérieuse + compromission de la sécurité de votre réseau. Utilisez + l'authentification avec la plus grande prudence.

+
+
+

+

L'implémentation de l'authentification "Basic" dans CUPS ne permet + pas l'accès en utilisant des comptes sans mot de passe. Si vous tentez + d'authentifier un tel compte, l'accès sera immédiatement bloqué.

+

Une fois le nom d'utilisateur et le mot de passe authentifiés par + CUPS, les contraintes supplémentaires d'appartenance à des groupes sont + vérifiées +

+ + +
NOTE: +

Pour CUPS, l'utilisateur root est considéré comme membre de tous les + groupes.

+
+
+ + +

+

Utilisez la directive AuthType pour activer + l'authentification "Basic":

+
    +
    +AuthType Basic
    +
    +
+ + +

Utilisation de l'authentification "Digest"

+

L'authentification "Digest" utilise des utilisateurs et mots de passe + définis dans le fichier /etc/cups/passwd.md5 pour + authentifier l'accès aux ressources telles que les imprimantes et les + classes et pour limiter l'accès aux fonctions d'administration. +

+ + +
NOTE: +

Contrairement à l'authentification "Basic", "Digest" transmet une + version codée du nom d'utilisateur et du mot de passe en utilisant le + codage MD5 (en résumé, une somme de contrôle compliquée) au lieu de + leur version en clair. De plus, l'authentification "Digest" n'utilise + pas les utilisateurs et mots de passe UNIX, ainsi si un attaquant + découvre le mot de passe original il est moins probable qu'il en + résulte un problème de sécurité, pour peu que vous utilisiez un mot de + passe "Digest" différent de celui stocké par UNIX.

+

L'implémentation actuelle de l'authenfication "Digest" dans CUPS + utilise le nom d'hôte du client ou son adresse IP comme valeur "nonce". + La valeur "nonce" est une chaîne de caractères additionnelle ajoutée au + nom d'utilisateur et au mot de passe pour rendre la découverte de ce + dernier plus difficile. Le serveur vérifie que la valeur "nonce" + correspond au nom d'hôte ou l'adresse IP du client et, si tel n'est pas + le cas, rejette la somme MD5 proposée par celui-ci. Les prochaines + versions de CUPS prendront en charge l'authentification "Digest" par + "session" qui ajoutera les données de la requête à la somme MD5, + fournissant ainsi une sécurité et une authentification encore + meilleures.

+

L'authentification "Digest" ne garantit pas qu'un attaquant ne peut + pas obtenir un accès non autorisé mais elle est plus sûre que + l'authentification "Basic" et devrait être utilisée à la place de + celle-ci chaque fois que c'est possible. La prise en charge de + l'authentification "Digest" dans les navigateurs "web" n'est pas encore + universellement disponible.

+
+
+ + +

+

La commande lppasswd(1) est utilisée pour ajouter, + changer et retirer des comptes du fichier passwd.md5. Pour + ajouter un utilisateur au groupe système standard, tapez:

+
    +
    +lppasswd -a utilisateur ENTREE
    +Password: (mot de passe) ENTREE  [le mot de passe n'est pas affiché]
    +Password again: (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +
    +
+ + +

Une fois ajouté, un utilisateur peut changer son mot de passe en + tapant:

+
    +
    +lppasswd ENTREE
    +Old Password: (mot de passe) ENTREE  [le mot de passe n'est pas affiché]
    +Password : (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +Password again: (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +
    +
+ + +

Pour retirer un utilisateur du fichier des mots de passe, tapez:

+
    +
    +lppasswd -x utilisateur ENTREE
    +
    +
+

Une fois qu'un utilisateur et un mot de passe valides ont été + authentifiés pas CUPS, celui-ci vérifie les contraintes supplémentaires + d'appartenance à des groupes. +

+ + +
NOTE: +

Pour CUPS, l'utilisateur root est membre de tous les groupes.

+
+
+

+

Utilisez la directive AuthType pour activer + l'authentification "Digest":

+
    +
    +AuthType Digest
    +
    +
+

Authentifications "System" et "Group"

+

La directive AuthClass contrôle + le niveau d'authentification à effectuer. Les authentifications +System et Group ajoutent à l'authentification + normale basée sur l'utilisateur une contrainte d'appartenance à un + groupe UNIX. Pour l'authentification System, chaque + utilisateur doit être membre du groupe sys, system +, ou root; le groupe réel dépend du système d'exploitation.

+

Pour l'authentification Group l'utilisateur doit être + membre du group indiqué par la directive +AuthGroupName:

+
    +
    +<Location /path>
    +AuthType Digest
    +AuthClass Group
    +AuthGroupName mygroup
    +</Location>
    +
    +
+

Le groupe indiqué doit être un groupe UNIX valide, habituellement + défini dans les fichiers /etc/group ou /etc/netgroup +. De plus, lors de l'utilisation de l'authentification "Digest", vous + devez créer les comptes utilisateur avec le groupe indiqué:

+
    +
    +lppasswd -g mon_groupe -a utilisateur ENTER
    +Password : (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +Password again: (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +
    +
+ + +

Suivi/facturation de travaux et + d'imprimantes

+

ESP Print Pro maintient à jour un suivi ("log") de tous les accès, + erreurs et pages qui sont imprimées. Les fichiers de suivi sont + normalement stockés dans le répertoire /var/log/cups. Vous + pouvez changer cela en éditant le fichier de configuration + /etc/cups/cupsd.conf.

+

Le fichier access_log

+

Le fichier access_log liste chaque ressource HTTP qui est + utilisée par le serveur "web" ou un client CUPS/IPP. Chaque ligne est + structurée dans le format habituel utilisé par de nombreux serveurs + "web" et outils d'analyse.:

+
    +
    +Hôte Groupe Utilisateur Date/heure \"Méthode Ressource Version\" Etat Octets
    +
    +127.0.0.1 - - [20/May/1999:19:20:29 +0000] "POST /admin/ HTTP/1.1" 401 0
    +127.0.0.1 - mike [20/May/1999:19:20:31 +0000] "POST /admin/ HTTP/1.1" 200 0
    +
    +
+

Le champ hôte ne devrait normalement être qu'une adresse IP à + moins que vous n'activiez la directive +HostNameLookups dans le fichier cupsd.conf.

+

Le champ groupe contient toujours "-" dans CUPS.

+

Le champ utilisateur est le nom de l'utilisateur authentifié + qui a émis la requête. Si aucun nom d'utilisateur et mot de passe n'est + fourni pour la requête, alors ce champ contient "-".

+

Le champ date/heure contient la date et l'heure de la requête + exprimées dans le fuseau horaire local, et est structuré de la manière + suivante:

+
    +
    +[JJ/MMM/AAAA:HH:MM:SS +ZZZZ]
    +
    +
+

ZZZZ est le décalage horaire entre le fuseau horaire local + et l'heure Greenwich Mean Time (a.k.a. GMT a.k.a. ZULU.) (NdT : en + réalité GMT est un abus de langage, il s'agit du temps UTC...)

+

Le champ méthode est la méthode HTTP utilisée ("GET", "PUT", + "POST", etc.)

+

Le champ ressource est le nom du fichier de la ressource + demandée.

+

Le champ version est la version du protocole HTTP employé par + le client. Pour les clients CUPS, c'est toujours "HTTP/1.1".

+

Le champ Etat contient l'état du résultat HTTP de la requête. + Habituellement, il s'agit de la valeur "200", mais d'autres codes + d'état HTTP sont possibles. Par exemple, 401 est le code d'état pour + "accès non autorisé" dans l'exemple ci-dessus.

+

Le champs octets contient le nombre d'octets contenus dans la + requête. Pour les requêtes POST, le champ octets contient le + nombre d'octets reçus du client.

+

Le fichier error_log

+

Le fichier error_log liste les messages provenant de + l'ordonnanceur (erreurs, avertissements, etc.):

+
    +
    +Niveau Date/Heure Message
    +
    +I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
    +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'.
    +
    +
+

Le champ Niveau contient le type du message:

+
    +
  • E - Une erreur est survenue.
  • +
  • W - Le serveur a été incapable d'effectuer une action.
  • +
  • I - Message d'information.
  • +
  • D - Message de débogage.
  • +
+

Le champ Date/heure contient la date et l'heure de début + d'impression de la page. Le format est identique à celui du champ + Date/heure dans le fichier access_log.

+

Le champ Message contient un message textuel dont la forme est + libre.

+

Le fichier page_log

+

Le fichier page_log liste chaque page qui est envoyée à + une imprimante. Chaque ligne contient les informations suivantes:

+
    +
    +Imprimante Utilisateur N°travail Date/heure N°Page Nombre_copies Facturation_travail
    +
    +DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123
    +
    +
+

Le champ imprimante contient le nom de l'imprimante qui a + imprimé la page. Si vous envoyez un travail d'impression à une classe, + le champ contient le nom de l'imprimante à laquelle ce travail a été + affecté..

+

Le champ utilisateur contient le nom de l'utilisateur + (l'attribut requesting-user-name de IPP) qui a envoyé le + fichier à l'impression.

+

Le champ N°Travail contient le n° du travail correspondant à + la page en cours d'impression. Les n° de travaux sont remis à 1 si le + serveur CUPS est redémarré, donc ne le considérez pas comme un + identifiant unique !

+

Le champ Date/heure contient la date et l'heure de démarrage + de l'impression dans un format identique au champ Date/heure du + fichier access_log.

+

Les champs N°Page et Nombre_copies contiennent le n° de + page imprimée et le nombre de copies de cette page. Pour les + imprimantes qui ne peuvent pas produire de copies multiples de manière + autonome, le champ Nombre_copies est toujours à 1.

+

Le champ facturation_travail contient une copie de l'attribut +job-billing fourni dans les requête IPP create-job + ou print-job. Si aucune valeur n'est fournie dans la + requête, ce champ contient "-". + +

+

Filtrage et détermination des types + de fichiers

+

CUPS fournit un mécanisme de filtrage et de détermination du type de + fichier basé sur MIME, afin de convertir les fichiers dans un format + utilisable par chaque imprimante. Au démarrage, le serveur CUPS lit les + fichiers de la base de données MIME contenus dans le répertoire + /etc/cups (ou un répertoire indiqué au moyen de la directive + ServerRoot) afin de construire en mémoire une base de + données de conversion et de types de fichiers. Ces fichiers de base de + données sont de simples fichiers texte ASCII et peuvent être modifiés + au moyen de votre éditeur de texte préféré.

+

Les fichiers mime.types et mime.convs + définissent les types de fichiers standards et les filtres qui sont + disponibles sur le système.

+

Le fichier mime.types

+

Le fichier mime.types définit les types de fichiers + connus. Chaque ligne débute par le type MIME et devrait être suivi par + une ou plusieurs règles de reconnaissance de fichier. Par exemple, le + type de fichier text/html est défini de la manière + suivante:

+
    +
    +text/html       html htm \
    +                printable(0,1024) + \
    +                (string(0,"<HTML>") string(0,"<!DOCTYPE"))
    +
    +
+

Les deux premièress règles indiquent que tout fichier portant + l'extension .html ou .htm est un fichier HTML. La + troisième règle précise que tout fichier dont les 1024 premiers + caractères sont des caractères imprimables et commencent par les + chaînes <HTML> ou <!DOCTYPE est également un + fichier HTML.

+

Les deux premières règle traitent simplement du nom du fichier. Cela + est utile lorsque le nom du fichier original est connu, cependant pour + les fichiers d'impression le serveur ne dispose pas de nom de fichier. + La troisième règle prend garde à cette éventualité et détermine + automatiquement le type du fichier en se basant plutôt sur son contenu.

+

Les test applicables sont les suivants:

+
    +
  • ( expr ) - Parenthèses pour grouper les expressions
  • +
  • + - ET logique
  • +
  • , ou espace vide - OU logique
  • +
  • ! - NON logique
  • +
  • match("pattern") - Recherche de motif sur le nom de + fichier
  • +
  • extension - Recherche de motif sur "*.extension"
  • +
  • ascii(offset,length) - Vrai si les octets sont des + caractères ASCII imprimables (CR, NL, TAB, BS, 32-126)
  • +
  • printable(offset,length) - Vrai si les octets sont des + caractères 8 bits imprimables (CR, NL, TAB, BS, 32-126, 160-254)
  • +
  • string(offset,"chaîne") - Vrai si les octets sont + identiques à la chaîne
  • +
  • contains(offset,range,"chaîne") - Vrai si la plage + d'octets contient la chaîne
  • +
  • char(offset,value) - Vrai si l'octet correspond
  • +
  • short(offset,value) - Vrai si l'entier sur 16 bits + correspond (ordre des octets : "network" ou "big-endian")
  • +
  • int(offset,value) - Vrai si l'entier sur 32 bits + correspond (ordre des octets : "network" ou "big-endian")
  • +
  • locale("string") - Vrai si la locale courante + correspond à la chaîne
  • +
+

Toutes les valeurs numériques peuvent être exprimées en décimal + (123), octal (0123), ou hexadécimal (0x123) selon le cas. + +

+

Les chaînes de caractères peuvent être délimitées par des quotes, + sans quotes, sous forme d'une chaîne de valeurs hexadécimales ou toute + combinaison de ces écritures:

+
    +
    +"chaîne"
    +'chaîne'
    +chaîne
    +<737472696e67>
    +<7374>ring
    +
    +
+

Comme le montre l'exemple text/html, les règles peuvent + être réparties sur plusieurs lignes en utilisant le caractère + "backslash" ("\"). Un exemple plus complexe est fourni par les règles + de détermination du type image/jpeg:

+
    +
    +image/jpeg      jpeg jpg jpe string(0,<FFD8FF>) &&\
    +                (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
    +                 char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
    +                 char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
    +                 char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
    +
    +
+

Cette règle indique que tout fichier avec l'extension .jpeg +, .jpg, ou .jpe est un fichier JPEG. De plus, tout + fichier commençant par la chaîne hexadécimale <FFD8FF> + (JPEG Start-Of-Image) suivie d'un caractère compris entre 0xe0 + et 0xef (JPEG APPn markers) bornes comprises, est + également un fichier JPEG.

+

Le fichier mime.convs

+

Le fichier mime.convs définit tous les programmes de + filtrage qui sont connus du système. Chaque ligne est de la forme:

+
    +
    +Source Destination Coût Programme
    +
    +text/plain application/postscript 50 texttops
    +application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
    +image/* application/vnd.cups-postscript 50 imagetops
    +image/* application/vnd.cups-raster 50 imagetoraster
    +
    +
+

Le champ Source est un type MIME. Il peut éventuellement + utiliser des méta caractères ("joker", "wildcard") pour le sur-type ou + le sous-type (par exemple "text/plain", "image/*", "*/postscript").

+

Le champ Destination est un type MIME défini dans le fichier + mime.types.

+

Le champ Coût définit un coût relatif pour l'opération de + filtrage, exprimé sous forme d'une valeur entre 1 et 100. Le coût est + utilisé pour choisir entre deux jeux de filtres lors de la conversion + d'un fichier. Par exemple, pour convertir image/jpeg en +application/vnd.cups-raster, vous pourriez utiliser les filtres +imagetops et pstoraster pour un coût total de 100, + ou le filtre imagetoraster pour un coût total de 50.

+

Le champ Programme définit le programme de filtrage à + exécuter; le programme doit accepter les arguments standards de + filtrage et les variables d'environnement décrits dans le "Manuel de + conception d'interface" ainsi que le "Manuel du programmeur":

+
    +
    +Programme Travail Utilisateur Titre Options [nom_fichier]
    +
    +
+

S'il est indiqué, l'argument nom_fichier définit un fichier à + lire lors du filtrage, sinon le filtre doit lire l'entrée standard. + Toutes les sorties du programme de filtrage doivent être envoyées à la + sortie standard. + +

+

Ajouter des filtres et des types de fichiers

+

Ajouter un nouveau filtre ou type de fichier est relativement simple. + Plutôt qu'ajouter le nouveau filtre ou type aux fichiers + mime.types et mime.convs qui sont écrasés lorsque vous + mettez CUPS à jour avec une nouvelle version, vous devez simplement + créer de nouveaux fichiers avec les extensions .types et + .convs dans le répertoire /etc/cups. Nous recommandons + d'utiliser le nom du format ou du produit, par exemple:

+
    +
    +myproduct.types
    +myproduct.convs
    +
    +
+

Si vous installez un filtre pour un fichier ou une imprimante + courants, ajoutez le nom du fabricant ou de l'éditeur:

+
    +
    +acme-msword.types
    +acme.msword.convs
    +
    +
+

Cela aidera à éviter les conflits de noms si vous installez plusieurs + types de fichiers ou plusieurs filtres.

+

Une fois choisis les noms pour ces fichiers, créez-les au moyen de + votre éditeur de texte préféré comme décrit précédemment dans ce + chapitre. Une fois ces fichiers créés, redémarrez le processus +cupsd comme indiqué précédemment dans + "Redémarrage du serveur CUPS" .

+

Pilotes d'imprimantes et fichiers PPD

+

Plusieurs pilotes d'imprimante CUPS utilisent un ou plusieurs filtres + spécifiques et un fichier PPD pour chaque modèle d'imprimante. Les + filtres pilotes d'imprimante sont enregistrés au moyen des attributs du + fichier cupsFilter:

+
    +
    +*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
    +
    +
+

Le filtre est indiqué en utilisant seulement le type du fichier + source; le type du fichier destination est considéré comme étant du + type imprimante/nom - convenable pour envoi à + l'imprimante.

+

Ecrire vos propres filtres ou pilotes d'imprimantes +

+

CUPS prend en charge un nombre illimité de filtres et de formats de + fichiers, et peut traiter avec toute imprimante. Si vous désirez écrire + un pilote ou un filtre pour votre imprimante préférée, consultez le + "Manuel du programmeur" et suivez pas à pas les instructions qu'il + contient.

+

7 - Imprimer depuis et vers + d'autres systèmes

+

Ce chapitre décrit comment imprimer depuis des système clients qui + utilisent les protocoles d'impression LPD, Mac OS ou Windows.

+

Les bases

+

CUPS est basé sur le protocole IPP, ainsi tout autre système prenant + en charge IPP peut automatiquement envoyer ou recevoir des travaux + d'impression vers ou depuis un système utilisant CUPS. Cependant, tous + les systèmes ne prennent pas encore en charge IPP. Ce chapitre vous + montrera comment connecter ces systèmes à votre serveur CUPS, que ce + soit pour qu'ils puissent accepter des travaux provenant de celui-ci ou + pour lui en envoyer.

+

Imprimer depuis des clients LPD

+

CUPS prend en charge un nombre limité des fonctionnalités des clients + basés sur LPD. Avec LPD vous pouvez imprimer des fichiers vers des + imprimantes déterminées, voir l'état des files d'impression, etc. + Cependant, la configuration automatique des clients et des imprimantes + n'est pas prise en charge par le protocole LPD, donc vous devez + configurer manuellement chaque client pour les imprimantes auxquelles + il a besoin d'accéder.

+

Le programme cups-lpd(8) fournit la prise en charge pour + les clients LPD. Pour activer la prise en charge LPD sur votre serveur, + éditez le contenu du fichier /etc/inetd.conf et ajoutez une + ligne:

+
    +
    +printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
    +
    +
+

Le chemin vers le programme cups-lpd peut varier en + fonction de l'installation de votre serveur.

+

Une fois cette ligne ajoutée, envoyez un signal HUP au + processus inetd(8) ou redémarrez le système (NdT : le + redémarrage du système n'est pas des plus élégants...):

+
    +
    +killall -HUP inetd ENTREE [sur IRIX et quelques distributions GNU/Linux]
    +kill -HUP pid ENTREE [Autres systèmes]
    +reboot ENTREE [Pour tous les systèmes si le signal HUP ne fonctionne pas (NdT : ...en DERNIER recours, uniquement...)]
    +
    +
+

Imprimer vers des serveurs LPD

+

CUPS fournit le programme d'arrière-plan lpd pour + imprimer vers des serveurs et imprimantes utilisant LPD. Utilisez un + URI de périphérique de la forme lpd://serveur/nom pour + imprimer ver une imprimante sur un serveur LPD, où serveur + est le nom d'hôte ou l'adresse IP du serveur et nom est le + nom de la file d'impression.

+

Microsoft Windows NT fournit un service LPD sous le nom "Serveur + d'impression TCP/IP". Pour activer l'impression sur un système Windows + NT, ouvrez le panneau de configuration puis "Services", sélectionnez le + service "Serveur d'impression TCP/IP" et cliquez sur le bouton + "Démarrer". Toute imprimante partagée devient alors accessible via le + protocole LPD.

+

Imprimer depuis des client Mac OS

+

NdT : je ne suis pas spécialiste Mac et je ne dispose pas de ce + type de matériel. Il se peut qu'il y ait quelques imprécisions ou + erreurs dans ce qui suit, faîtes-moi l'amitié de me les pardonner ET de + me les signaler. Merci par avance...

+

CUPS ne fournit pas de prise en charge directe de Mac OS. Cependant, + il existe plusieurs logiciels libres ou commerciaux qui le font.

+

Columbia Appletalk Package (CAP)

+

Etant donné que le serveur CAP LaserWriter (lwsrv(8)) ne + prend pas en charge les spécifications des fichiers PPD, nous ne + recommandons pas l'utilisation de CAP avec CUPS. Cependant, vous pouvez + exécuter le programme lpsrv pour une prise en charge + limitée de l'impression au moyen de la syntaxe suivante:

+
    +
    +lwsrv -n "Nom" -p Imprimante -a /usr/lib/adicts -f /usr/lib/LW+Fonts
    +
    +
+

Nom est le nom que vous voulez utiliser pour partager + l'imprimante et imprimante est le nom de la file + d'impression. + +

+

XINET KA/Spool

+

Afin d'utiliser votre système comme serveur d'impression pour des + clients Mac OS, configurez chaque imprimante en utilisant +papserver(8) dans le fichier /usr/adm/appletalk/services +, et en indiquant le fichier PPD correspondant dans le répertoire +/etc/cups/ppd. Pour une imprimante appelée Mon_Imprimante + la syntaxe serait de la forme suivante:

+
    +
    +/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/Mon_Imprimante.ppd \
    +"Printer Description" Mon_Imprimante
    +
    +
+
+ + +
NOTE: +

Entrez le texte ci-dessus sur une seule ligne sans le caractère "\".

+
+
+

NetATalk

+

Pour utiliser votre système comme serveur d'impression pour des + clients Mac OS, configurez chaque imprimante dans le fichier + papd.conf, en indiquant le fichier PPD correspondant dans le + répertoire /etc/cups/ppd pour chaque imprimante. Pour une + imprimante nommée Mon_Imprimante le texte serait de la + forme suivante:

+
    +
    +Printer Description:Mon_Imprimante@Mon_Serveur:\
    +        :pr=|/usr/bin/lp -d Mon_Imprimante:\
    +        :op=daemon:\
    +        :pd=/etc/cups/ppd/Mon_Imprimante.ppd:
    +
    +
+ + +

Imprimer vers des serveurs d'impression Mac OS

+

Actuellement, CUPS ne fournit pas de programme d'arrière-plan pour + communiquer avec un serveur Mac OS. Cependant, vous pouvez écrire et + installer un court script dans le répertoire /usr/lib/cups/backend + qui envoie un fichier d'impression en utilisant la commande appropriée. + Le court script suivant exécutera la commande papif + fournie avec CAP.

+

Après avoir copié le script dans /usr/lib/cups/backend/cap +, indiquez un URI de périphérique de la forme +cap://serveur/imprimante pour utiliser ce script avec une file + d'impression. + +

+
    +
    +"/usr/lib/cups/backend/cap"
    +#!/bin/sh
    +#
    +# Usage: cap job user title copies options [filename]
    +#
    +
    +# No arguments means show available devices...
    +
    +if test ${#argv} = 0; then
    +	echo "network cap \"Unknown\" \"Mac OS Printer via CAP\""
    +	exit 0
    +fi
    +
    +# Collect arguments...
    +
    +user=$2
    +copies=$4
    +
    +if test ${#argv} = 5; then
    +	# Get print file from stdin; copies have already been handled...
    +	file=/var/tmp/$$.prn
    +	copies=1
    +	cat > $file
    +else
    +	# Print file is on command-line...
    +	file=$6
    +fi
    +
    +# Create a dummy cap.printers file for this printer based
    +# upon a device URI of "cap://server/printer"...
    +
    +echo $PRINTER/$DEVICE_URI | \
    +	awk -F/ '{print $1 "=" $5 ":LaserWriter@" $4}' > /var/tmp/$$.cap
    +
    +CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
    +
    +# Send the file to the printer, once for each copy. This assumes that you
    +# have properly initialized the cap.printers file...
    +
    +while [ $copies -gt 0 ]; do
    +	papif -n $user < $file
    +
    +        copies=`expr $copies - 1`
    +done
    +
    +# Remove any temporary files...
    +if test ${#argv} = 5; then
    +	/bin/rm -f $file
    +fi
    +
    +/bin/rm -f /var/tmp/$$.cap
    +
    +exit 0
    +
    +
+ + +

Imprimer depuis des clients Windows

+

Bien que CUPS ne fournisse directement pas de prise en charge de + Windows, le logiciel libre SAMBA le fait. La version 2.0.6 de SAMBA est + la première qui prenne en charge CUPS. Vous pouvez télécharger SAMBA à + l'adresse :

+ +

Pour configurer SAMBA pour CUPS, éditez le contenu du fichier + smb.conf et remplacez les commandes d'impression existantes par + les lignes:

+
    +
    +printing = cups
    +printcap name = cups
    +
    +
+

C'est tout ce qu'il y a à faire! Les utilisateurs distants pourront + désormais explorer les imprimantes de votre système et leur envoyer des + travaux d'impression.

+

Exporter les pilotes d'imprimantes

+

Vous pouvez éventuellement exporter des pilotes d'imprimantes de + votre serveur CUPS en utilisant la commande cupsaddsmb et + le logiciel SAMBA 2.2.0 ou supérieur.

+

Avant de pouvoir exporter les pilotes d'imprimantes, vous devez + télécharger les pilotes d'imprimantes actuels Adobe PostScript à partir + du site "web" Adobe ( +http://www.adobe.com/). Utilisez le logiciel libre unzip + pour extraire les fichiers des archives ZIP auto-extractibles contenant + les pilotes; vous aurez besoin des fichiers suivants:

+
    +
    +ADFONTS.MFM
    +ADOBEPS4.DRV
    +ADOBEPS4.HLP
    +ADOBEPS5.DLL
    +ADOBEPSU.DLL
    +ADOBEPSU.HLP
    +DEFPRTR2.PPD
    +ICONLIB.DLL
    +PSMON.DLL
    +
    +
+

Copiez ces fichiers dans le répertoire /usr/share/cups/drivers + - vous pourriez avoir à renommer certains fichiers de sorte que tous + les noms soient complètement en majuscules.

+

Ensuite, ajouter un partage d'imprimante print$ pour les + pilotes d'imprimantes à votre fichier smb.conf:

+
    +
    +[print$]
    +    comment = Pilotes d'imprimantes
    +    path = /etc/samba/drivers
    +    browseable = yes
    +    guest ok = no
    +    read only = yes
    +    write list = root
    +
    +
+

Le répertoire de vos pilotes d'imprimantes peut être n'importe où + dans le système; assurez-vous simplement qu'il est accessible en + écriture aux utilisateurs indiqués par la directive write list +. Assurez-vous également que chaque utilisateur de la liste write + list possède un mot de passe SAMBA en utilisant la commande +smbpasswd(1) sinon vous ne pourrez pas vous authentifier.

+

Enfin, exécutez la commande cupsaddsmb pour exporter les + pilotes d'imprimantes pour une ou plusieurs files d'impression:

+
    +
    +cupsaddsmb -U root printer1 ... printerN ENTREE
    +
    +
+

Exécuter la commande cupsaddsmb avec l'option -a + exportera les imprimantes:

+
    +
    +cupsaddsmb -U root -a ENTREE
    +
    +
+

Imprimer vers des serveurs d'impression Windows

+

CUPS peut imprimer vers des serveurs Windows de deux façons. La + première utilise le protocole LPD sur le système CUPS et le service + "Serveur d'impression TCP/IP" sur le système Windows NT. Vous pouvez + trouver plus d'information au sujet de la première configuration dans + la section précédente LPD de ce chapitre.

+

La seconde méthode utilise le protocole SMB de Microsoft ("Server + Message Block"). La prise en charge de ce protocole est fournie par le + logiciel libre SAMBA. Vous pouvez télécharger SAMBA à l'adresse + suivante:

+ +

Pour configurer CUPS pour SAMBA, exécutez la commande suivante:

+
    +
    +ln -s `which smbspool` /usr/lib/cups/backend/smb ENTREE
    +
    +
+

Le programme smbspool(1) est fourni avec SAMBA depuis la + version 2.0.6. Une fois que vous avez créé le lien vous pouvez + configurer vos imprimantes en utilisant l'un des URI de périphérique + suivants:

+
    +
    +smb://groupe_de_travail_ou_domaine/serveur/nom_partage
    +smb://serveur/nom_partage
    +smb://utilisateur:mot_de_passe@groupe_de_travail_ou_domaine/serveur/nom_partage
    +smb://utilisateur:mot_de_passe@serveur/nom_partage
    +
    +
+

Le nom groupe_de_travai_ou_domaine doit être indiqué si + votre système utilise un autre nom que la valeur standard de votre + réseau. Les chaînes utilisateur:mot_de_passe sont + nécessaires si vous imprimez vers des serveurs Windows NT ou des + partages Windows 95/98 dont les mots de passe sont activés.

+

A - Licence d'utilisation du + logiciel

+

Common UNIX Printing System License + Agreement

+

(NdT : pour des raisons évidentes de droit, j'ai volontairement + gardé la licence d'utilisation du logiciel et la licence GPL en anglais + car une traduction de celles-ci pourrait donner lieu à des + interprétations erronées... et en plus je ne suis pas juriste !)

+

Copyright 1997-2002 by Easy Software Products +
44141 AIRPORT VIEW DR STE 204 +
HOLLYWOOD, MARYLAND 20636-3111 USA +
+
Voice: +1.301.373.9600 +
Email: cups-info@cups.org +
WWW: http://www.cups.org

+

Introduction

+

The Common UNIX Printing SystemTM, ("CUPSTM"), + is provided under the GNU General Public License ("GPL") and GNU + Library General Public License ("LGPL"), Version 2. A copy of these + licenses follow this introduction.

+

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_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.93a.

+

For those not familiar with the GNU GPL, the license basically allows + you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in source or binary form.
  • +
  • Sell verbatim copies of the software for a media fee, or sell + support for the software.
  • +
  • Distribute or sell printer drivers and filters that use CUPS so long + as source code is made available under the GPL.
  • +
+

What this license does not 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.

+

The GNU LGPL relaxes the "link-to" restriction, allowing you to + develop applications that use the CUPS API library under other licenses + and/or conditions as appropriate for your application.

+

Trademarks

+

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.

+

Binary Distribution Rights

+

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.

+

The Common UNIX Printing System provides a "pstoraster" 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:

Miles Jones +
Director of Marketing +
Artifex Software Inc. +
454 Las Gallinas Ave., Suite 108 +
San Rafael, CA 94903 USA +
Voice: +1.415.492.9861 +
Fax: +1.415.492.9862 +
EMail: info@arsoft.com
+

+

The "pdftops" filter is based on the Xpdf 0.93a software. For binary + distribution licensing of this software, please contact:

+ Derek B. Noonburg +
Email: derekn@foolabs.com +
WWW: + http://www.foolabs.com/xpdf/

+

Support

+

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:

+ + + +

GNU GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+
+
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow.

+

GNU GENERAL PUBLIC LICENSE +
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+
    +
  1. 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 "Program", below, + refers to any such program or work, and a "work based on the Program" + 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 "modification".) Each licensee is addressed as "you".
  2. +

    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.

    +
  3. 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.
  4. +

    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.

    +
  5. 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: +
      +
    1. You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change.
    2. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +
  6. +

    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.

    +

    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.

    +

    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.

    +
  7. 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: +
      +
    1. 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,
    2. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +
  8. +

    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.

    +

    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.

    +
  9. 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.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. 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.
  16. +

    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.

    +

    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.

    +

    This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

    +
  17. 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.
  18. +
  19. 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.
  20. +

    Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", 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.

    +
  21. 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.
  22. +
+

NO WARRANTY

+
    +
  1. 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 "AS IS" 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.
  2. +
  3. 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.
  4. +
+

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, while the latter only + works together with the library.

+

Note that it is possible for a library to be covered by the ordinary + General Public License rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+

0. 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 "this License"). Each + licensee is addressed as "you".

+

A "library" 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.

+

The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" 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 "modification".)

+

"Source code" 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.

+

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.

+

1. 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.

+

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.

+

2. 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:

+
    +
  1. The modified work must itself be a software library.
  2. +

    +
  3. You must cause the files modified to carry prominent notices stating + that you changed the files and the date of any change.
  4. +

    +
  5. You must cause the whole of the work to be licensed at no charge to + all third parties under the terms of this License.
  6. +

    +
  7. 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.
  8. +

    (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.)

    +
+

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.

+

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.

+

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.

+

3. 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.

+

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.

+

This option is useful when you wish to copy part of the code of the + Library into a program that is not a library.

+

4. 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.

+

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.

+

5. 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 "work that uses the + Library". Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License.

+

However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. Section + 6 states terms for distribution of such executables.

+

When a "work that uses the Library" 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.

+

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.)

+

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.

+

6. As an exception to the Sections above, you may + also compile or link a "work that uses the Library" 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.

+

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:

+
    +
  1. 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 "work that uses the Library", 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.)
  2. +

    +
  3. 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.
  4. +

    +
  5. 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.
  6. +

    +
  7. Verify that the user has already received a copy of these materials + or that you have already sent this user a copy.
  8. +
+

For an executable, the required form of the "work that uses the + Library" 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.

+

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.

+

7. 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:

+
    +
  1. 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.
  2. +

    +
  3. 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.
  4. +
+

8. 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.

+

9. 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.

+

10. 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.

+

11. 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.

+

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.

+

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.

+

This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

+

12. 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.

+

13. 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.

+

Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and "any + later version", 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.

+

14. 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.

+

NO WARRANTY

+

15. 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 "AS IS" 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.

+

16. 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.

+

END OF TERMS AND CONDITIONS

+

B - Réglages réseau courants +

+

Cette annexe englobe de nombreux serveurs d'impression et interfaces + réseau TCP/IP disponibles actuellement sur le marché.

+

Configurer une interface réseau

+

Lorsque vous installez votre imprimante réseau ou votre serveur + d'impression pour la première fois sur votre réseau local (LAN), vous + devez configurer son adresse IP ("Internet Protocol"). Sur la plupart + des imprimantes réseau pour groupe de travail, vous pouvez le faire + directement au moyen du panneau de contrôle. Cependant, dans la plupart + des cas, vous préfèrerez assigner l'adresse IP à distance depuis votre + station de travail. Cela rend l'administration un peu plus simple et + évite d'assigner accidentellement des adresses réseau eu doublons.

+

Pour configurer votre imprimante ou votre serveur d'impression pour + une assignation à distance de l'adresse réseau, vous aurez besoin de + son adresse MAC (ethernet Media Access Control), également appelée + adresse de noeud ("node address") dans certains cas. Vous aurez + également besoin de connaître l'adresse IP que vous voulez utiliser + pour ce matériel. L'adresse MAC peut souvent être trouvée sur la page + de test de l'imprimante ou sur son panneau arrière. + +

+

Configuration de l'adresse IP utilisant ARP

+

La méthode la plus simple pour installer l'adresse IP d'un matériel + réseau est d'utiliser la commande arp(8). La commande +arp envoie un paquet ARP ("Address Resolution Protocol") à + l'adresse MAC indiquée tout en lui indiquant son adresse IP:

+
    +
    +arp -s adresse-ip adresse-mac ENTREE
    +arp -s hote.domaine.com 08:00:69:00:12:34 ENTREE
    +arp -s 192.0.2.2 08:00:69:00:12:34 ENTREE
    +
    +
+

Configuration de l'adresse IP utilisant RARP

+

La manière la plus souple d'assigner une adresse IP sous UNIX est + d'utiliser le protocole RARP ("Reverse Address Resolution Protocol"). + RARP permet à un matériel réseau d'émettre une requête d'adresse IP en + utilisant sont adresse MAC, un ou plusieurs serveurs RARP sur le réseau + répondront à cette requête par un paquet ARP proposant une adresse IP + que le matériel réseau peut utiliser.

+

RARP devrait être utilisé lorsque vous administrez de nombreuses + imprimantes ou serveurs d'impression, ou quand un matériel réseau ne + peut se "souvenir" de son adresse IP après chaque redémarrage. Si vous + n'avez qu'une seule imprimante ou serveur d'impression, la commande +arp est la plus adaptée.

+

Certains systèmes d'exploitation UNIX utilisent un programme nommé +rarpd(8) pour administrer RARP. Les autres, tels que GNU/Linux, + prennent en charge ce protocole à l'intérieur du noyau. Pour les + systèmes qui utilisent le programme rarpd vous aurez + besoin de le démarrer avant que les requêtes RARP commencent:

+
    +
    +rarpd ENTREE
    +
    +
+

Sous IRIX vous pouvez activer cette fonctionnalité en standard en + utilisant la commande suivante:

+
    +
    +chkconfig rarpd on ENTREE
    +
    +
+

Le programme rarpd et la version noyau de la prise en + charge RARP lisent toutes les deux une liste des adresses MAC et IP à + partir d'un fichier /etc/ethers. Chaque ligne comporte + l'adresse Ethernet suivie de l'adresse IP ou du nom d'hôte:

+
    +
    +08:00:69:00:12:34 mon_imprimante.mon_domaine.com
    +08:00:69:00:12:34 192.0.2.2
    +
    +
+

Ajoutez une ligne à ce fichier et redémarrez l'imprimante ou le + serveur d'impression pour qu'elle/il récupère son adresse IP. + +

+

Configuration de l'adresse IP utilisant BOOTP

+

Le protocole BOOTP est utilisé quand vous avez besoin de fournir des + informations supplémentaires à l'interface réseau telles que + l'emplacement du fichier de configuration. En utilisant le programme + standard bootpd(8) fourni sous UNIX, vous avez simplement + besoin d'ajouter la ligne suivante au fichier /etc/bootptab + pour IRIX:

+
    +
    +mon_imprimante 08:00:69:00:12:34 192.0.2.2 mon_imprimante.boot
    +
    +
+ + +

Les versions plus récentes de bootpd utilisent un format + différent:

+
    +
    +mon_imprimante:ha=080069001234:ip=192.0.2.2:t144=mon_imprimante.boot
    +
    +
+

Le fichier mon_imprimante.boot est situé en standard dans + le répertoire /usr/local/boot Si vous n'avez pas besoin de + fournir un fichier de démarrage, vous pouvez laisser vide la fin de la + ligne. + + +

+ + +
NOTE: +

Certaines versions d'UNIX n'activent pas le service BOOTP en + standard. Le fichier /etc/inetd.conf contient généralement + une ligne pour le service BOOTP. ELle peut être décommentée si + nécessaire.

+
+
+

+

Vérifier la connexion de l'imprimante

+

Pour vérifier que l'adresse IP a bien été assignée et que + l'imprimante est correctement connectée au réseau local (LAN), tapez:

+
    +
    +ping adresse-ip ENTREE
    +
    +
+

Si la connexion fonctionne correctement vous devriez voir apparaître + quelque chose de la forme suivante :

+
    +
    +ping mon_imprimante ENTREE
    +PING mon_imprimante (192.0.2.2): 56 data bytes
    +64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
    +64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
    +
    +
+

Sinon, vérifiez que que l'imprimante ou le serveur d'impression est + bien connecté au réseau (NdT : vérifiez ces @#*¤%§ câbles !), qu'elle + est sous tension et que l'adresse IP est bonne. Vous pouvez également + voir la configuration réseau en imprimant une page de test à partir du + panneau de contrôle du matériel. + +

+

Réglages d'interfaces réseau et serveur d'impression + courants

+

Une fois que vous avez configuré l'adresse IP, vous pouvez accéder à + l'imprimante ou au serveur d'impression en utilisant les programmes + d'arrière-plan ipp, lpd, ou socket +. La liste qui suit donne les interfaces réseau et serveurs d'impression + courants ainsi que les réglages que vous devriez utiliser dans CUPS: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Modèle / FabricantURI de + périphérique
Apple LaserWriterlpd:// + address/PASSTHRU
Axis w/o IPP +
(voir instructions)
socket://address + :9100 +
socket://address:9101 +
socket://address:9102
Axis w/IPPipp://address + /LPT1 +
ipp://address/LPT2 +
ipp://address/COM1
Castelle LANpressTM + lpd://address/pr1 +
lpd://address/pr2 +
lpd://address/pr3
DPI NETPrintlpd://address + /pr1 +
lpd://address/pr2 +
lpd://address/pr3
EFI® Fiery® RIPlpd:// + address/print
EPSON® Multiprotocol Ethernet + Interface Boardsocket://address
Extended System ExtendNET + lpd://address/pr1 +
lpd://address/pr2 +
lpd://address/pr3
Hewlett Packard JetDirect w/o IPP + socket://address:9100 +
socket://address:9101 +
socket://address:9102
Hewlett Packard JetDirect w/IPP + ipp://address/ipp +
ipp://address/ipp/port1 +
ipp://address/ipp/port2 +
ipp://address/ipp/port3
Intel® NetportExpress XL, PRO/100 + lpd://address/LPT1_PASSTHRU +
lpd://address/LPT2_PASSTHRU +
lpd://address/COM1_PASSTHRU
LexmarkTM MarkNet + lpd://address/ps
Linksys EtherFast® +
(voir instructions)
socket:// +address :4010 +
socket://address:4020 +
socket://address:4030
Kodak®lpd://address/ps
QMS® CrownNetTM + lpd://address/ps
Tektronix® PhaserShareTM + socket://address:9100
XEROX® 4512 NIClpd:// + address/PORT1
XEROX® XNIClpd://address + /PASSTHRU
XEROX® (most others)socket:// + address:5503
+
+

+

Configuration de serveurs d'impression Axis

+

Les serveurs d'impression Axis peuvent être configurés en utilisant + ARP, RARP ou BOOTP. Cependant, sur certains modèles ne prenant pas en + charge IPP, une configuration supplémentaire est nécessaire pour + permettre au serveur de dialoguer avec CUPS. + +

+

Chaque serveur d'impression possède une fichier de configuration + nommé config qui contient la liste des paramètres réseau à + utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord + le télécharger à partir du serveur d'impression en utilisant le + programme ftp(1):

+
    +
    +ftp adresse-ip ENTREE
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTREE
    +331 User name ok, need password
    +Password: pass ENTREE (le mot de passe n'apparaît pas)
    +230 User logged in
    +ftp> get config ENTREE
    +local: config remote: config
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2),
    +(mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+ + +

Ensuite, éditez son contenu avec votre éditeur de texte préféré et + repérez les lignes commençant par:

+
    +
    +RTN_OPT.     : YES
    +RTEL_PR1.    : 0
    +RTEL_PR2.    : 0
    +RTEL_PR3.    : 0
    +RTEL_PR4.    : 0
    +RTEL_PR5.    : 0
    +RTEL_PR6.    : 0
    +RTEL_PR7.    : 0
    +RTEL_PR8.    : 0
    +
    +
+ + + Changez la ligne RTN_OPT en: +
    +
    +RTN_OPT.     : NO
    +
    +
+ + +

Cela désactive le protocole "Reverse TELNET" et active le protocole + standard TELNET sur le serveur d'impression. Ensuite, assignez un + numéro de port pour chaque port parallèle ou série sur le serveur, + comme suit:

+
    +
    +RTEL_PR1.    : 9100
    +RTEL_PR2.    : 9101
    +RTEL_PR3.    : 9102
    +RTEL_PR4.    : 9103
    +RTEL_PR5.    : 9104
    +RTEL_PR6.    : 9105
    +RTEL_PR7.    : 9106
    +RTEL_PR8.    : 9107
    +
    +
+ + +

Cela a principalement pour effet de forcer le serveur Axis à + ressembler à un serveur d'impression Hewlett Packard JetDirect EX. + Sauvegardez le fichier et installez le sur le serveur d'impression dans + le fichier config au moyen de la commande ftp:

+
    +
    +ftp adresse-ip ENTREE
    +Connected to adresse-ip.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTREE
    +331 User name ok, need password
    +Password: pass ENTREE (le mot de passe n'est pas affiché)
    +230 User logged in
    +ftp> put config CONFIG ENTREE
    +local: config remote: CONFIG
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2), (mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> get hardreset ENTREE
    +local: hardreset remote: hardreset
    +200 PORT command successful.
    +421 Axis NPS ### hard reset, closing connection.
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+

Votre serveur d'impression Axis est à présent opérationnel!

+

Configuration de serveurs d'impression Linksys

+

Les serveurs d'impression LinkSys peuvent être configurés au moyen de + ARP, RARP ou BOOTP. Comme certains serveurs d'impression Axis anciens, + une configuration supplémentaire TCP/IP est nécessaire pour les faire + fonctionner avec CUPS + +

+

Chaque serveur d'impression possède une fichier de configuration + nommé config qui contient la liste des paramètres réseau à + utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord + le télécharger à partir du serveur d'impression en utilisant le + programme ftp(1):

+
    +
    +ftp -n adresse-ip ENTREE
    +Connected to adress-ip.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> get CONFIG ENTREE
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +WARNING! 68 bare linefeeds received in ASCII mode
    +File may not have transferred correctly.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+ + +

Ensuite, éditez son contenu avec votre éditeur de texte préféré et + repérez les lignes commençant par:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P1
    +0140 L3_PROUT:P1
    +
    +
+

Changez le numéro de port pour chaque port parallèle et série sur le + serveur, comme suit:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P2
    +0140 L3_PROUT:P3
    +
    +
+ + +

Cela relie chaque imprimante virtuelle à un port physique. + Sauvegardez le fichier et installez le sur le serveur d'impression dans + le fichier config au moyen de la commande ftp:

+
    +
    +ftp -n adresse-ip ENTREE
    +Connected to adresse-ip.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> put CONFIG ENTREE
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+

Votre serveur d'impression SysLink est désomais opérationnel !

+

C - Pilotes d'imprimantes +

+

Cette annexe dresse la liste des pilotes d'imprimantes qui sont + fournis avec CUSP.

+

Pilotes d'imprimantes

+

CUPS inclut les pilotes d'imprimantes suivants:

+ +

EPSON 9-pin Dot Matrix

+

Le pilote EPSON 9-pin Dot Matrix (epson9.ppd) prend en + charge les imprimantes 9 aiguilles qui utilisent le jeu de commandes + ESC/P. Il fournit l'impression en noir et blanc dans les résolutions + 60x72, 120x72, et 240x72 PPP (DPI).

+

EPSON 24-pin Dot Matrix

+

Le pilote EPSON 24-pin Dot Matrix (epson9.ppd) prend en + charge les imprimantes 24 aiguilles qui utilisent le jeu de commandes + ESC/P. Il fournit l'impression en noir et blanc dans les résolutions + 120x180, 180x180, 360x180, et 360x360 PPP (DPI).

+

EPSON Stylus Color

+

Le pilote EPSON Stylus Color (stcolor.ppd) prend en charge + les imprimantes EPSON Stylus Color qui utilisent le jeu de commandes + ESC/P2. Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et + blanc dans les résolutions 180, 360, et 720 PPP (DPI).

+

EPSON Stylus Photo

+

Le pilote EPSON Stylus Photo (stphoto.ppd) prend en charge + les imprimantes EPSON Stylus Photo qui utilisent le jeu de commandes + ESC/P2. Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et + blanc dans les résolutions 180, 360, et 720 PPP (DPI).

+

HP DeskJet

+

Le pilote HP DeskJet (deskjet.ppd) prend en charge les + imprimantes HP DeskJet qui utilisent le jeu de commandes PCL. Il + fournit l'imrpession en couleur (CMYK) ainsi qu'en noir et blanc dans + les résolutions 150, 300, et 600 PPP (DPI).

+

Les imprimantes DeskJet qui utilisent le jeu de commandes HP-PPA + (720C, 722C, 820C, and 1100C) ne sont pas prises en charge du + fait de l'absence totale de documentation de la part de Hewlett + Packard.

+

Le "duplexer" fourni avec les imprimantes de la série d'imprimantes + HP DeskJet 900 n'est également pas pris en charge pour les mêmes + raisons.

+

HP LaserJet

+

Le pilote HP LaserJet (laserjet.ppd) prend en charge les + impriamntes HP LaserJet qui utilisent le jeu de commandes PCL. Il + fournit l'impression seulement en noir et blanc et prend en charge le + "duplexer" s'il est installé. Il prend en charge les résolutions 150, + 300, et 600 PPP (DPI).

+

Les imprimantes LaserJet qui n'utilisent pas le jeu de commandes PCL + (3100, 3150) ne sont pas prises en charge du fait d'une absence totale + de documentation de la part de Hewlett Packard.

+

D - Liste des fichiers

+

Cette annexe dresse la liste des fichiers et répertoire qui sont + installés par CUPS +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CheminDescription
/etc/cups/certs/Emplacement des fichiers + des certificats d'authentification pour les clients HTTP locaux.
/etc/cups/classes.confFichiers de + configuration des classes d'imprimantes pour l'ordonnanceur.
/etc/cups/cupsd.confFichier de + configuration de l'ordonnanceur.
/etc/cups/interfaces/Emplacement des + scripts d'interface System V pour les imprimantes.
/etc/cups/mime.convsListe des filtres de + fichiers standards inclus dans ESP Print Pro.
/etc/cups/mime.typesListe des types de + fichiers reconnus par ESP Print Pro.
/etc/cups/ppd/Emplacement des fichiers PPD + ("PostScript Printer Description") pour les imprimantes.
/etc/cups/printers.confFichier de + configuration des imprimantes pour l'ordonnanceur.
/usr/bin/cancelLa commande d'annulation de + travaux System V.
/usr/bin/disableLa commande de + désactivation d'imprimante System V.
/usr/bin/enableLa commande d'activation + d'imprimante System V.
/usr/bin/lpLa commande d'impression System + V.
/usr/bin/lpoptionsJeu d'options + d'impression et de valeurs implicites personnalisées par l'utiliseur.
/usr/bin/lppasswdAjoute, modifie et retire + des mots de passe pour des comptes "Digest".
/usr/bin/lpqLa commande d'état Berkeley.
/usr/bin/lprLa commande d'impression + Berkeley.
/usr/bin/lprmLa commande d'annulation de + travaux Berkeley.
/usr/bin/lpstatLa commande d'état System + V.
/usr/include/cups/Fichiers d'en-tête de + l'API CUPS.
/usr/lib32/libcups.a +
/usr/lib32/libcupsimage.a
Librairies statiques (IRIX 6.5)
/usr/lib/libcups.a +
/usr/lib/libcupsimage.a
Librairies statiques (tous les + autres systèmes)
/usr/lib/libcups.sl.2 +
/usr/lib/libcupsimage.sl.2
Librairies partagées (HP-UX)
/usr/lib32/libcups.so.2 +
/usr/lib32/libcupsimage.so.2
Librairies partagées (IRIX + 6.5)
/usr/lib/libcups.so.2 +
/usr/lib/libcupsimage.so.2
Librairies partagées (tous les + autres systèmes)
/usr/lib/cups/backend/Programme + d'arrière-plan pour connexion à diverses imprimantes.
/usr/lib/cups/cgi-bin/Programmes CGI pour + l'ordonnanceur.
/usr/lib/cups/daemon/Démons pour la + surveillance et pour la prise en charge LPD.
/usr/lib/cups/filter/Filtres pour divers + types de fichiers.
/usr/lib/locale/Emplacement des fichiers + de messages spécifiques à chaque langue. (System V)
/usr/lib/nls/msg/Emplacement des fichiers + de messages spécifiques à chaque langue. (Compaq Tru64 UNIX)
/usr/share/locale/Emplacement des fichiers + de messages spécifiques à chaque langue. (GNU/Linux, *BSD)
/usr/sbin/acceptLa commande d'acceptation + de travaux.
/usr/sbin/cupsdL'ordonnanceur CUPS.
/usr/sbin/lpadminL'outil d'administration + d'imprimante System V.
/usr/sbin/lpcL'outil d'administration + d'imprimante Berkeley.
/usr/sbin/lpinfoLes commandes + "get-devices" et "get-ppds".
/usr/sbin/lpmoveLa commande "move-jobs".
/usr/sbin/rejectLa commande "reject-jobs".
/usr/share/catman/a_man/ +
/usr/share/catman/u_man/
Pages de manuel (IRIX)
/usr/share/man/Pages de manuel (Compaq + Tru64 UNIX, HP-UX, Solaris)
/usr/man/Pages de manuel (tous les autres + systèmes)
/usr/share/cups/data/Emplacement des + fichiers de données des filtres.
/usr/share/cups/data/testprint.psFichier + de page de test PostScript.
/usr/share/cups/fonts/Emplacement des + polices de caractères PostScript pour le RIP PostScript.
/usr/share/cups/model/ Emplacement des + fichiers PPD ("PostScript Printer Description") et des scripts + d'interface pouvant être employés pour configurer une file + d'impression.
/usr/share/cups/pstoraster/ D'autres + fichiers d'initialisation du RIP PostScript.
/usr/share/cups/pstoraster/Fontmap Le + fichier de conversion de polices (convertit des noms de fichiers en + noms de polices)
/usr/share/cups/templates/Emplacement des + fichiers "templates" HTML pour l'interface "web".
/usr/share/doc/cups/Documentation et + données des pages "web" pour l'ordonnanceur.
/var/log/cups/Emplacement des fichiers de + suivi de l'ordonnanceur.
/var/spool/cups/Emplacement des fichiers + d'impression en attente de traitement.
+
+

+

E - Résoudre les problèmes courants

+

Cette annexe couvre certains des problèmes courants rencontrés par + les utilisateurs lors de la première installation / configuration / + utilisation de CUPS.

+

Le support commercial de CUPS est disponible auprès d'Easy Software + Products. Pour plus d'informations, veuillez nous contacter:

+ +

Mes applications ne voient pas les imprimantes + disponibles

+

Beaucoup d'applications lisent le contenu du fichier + /etc/printcap pour obtenir la liste des imprimantes disponibles.

+

La configuration standard de CUPS ne crée pas ce fichier + /etc/printcap automatiquement. Pour activer la création et la + mise à jour automatiques de ce fichier, utilisez la directive + Printcapdécrite au + Chapitre 6, "Administration du système d'impression".

+

CUPS ne reconnaît pas mon nom d'utilisateur et mon + mot de passe!

+

CUPS vous demandera un nom d'utilisateur UNIX et un mot de passe + lorsque vous effectuerez des tâches d'administration à distance ou au + moyen d'un navigateur "web". La configuration standard de CUPS + nécessite que vous utilisiez le nom d'utilisateur root et + son mot de passe correspondant pour authentifier la requête.

+

Pour des raisons de sécurité, CUPS ne vous autorise pas à + authentifier une requête d'administration au moyen d'un compte dépourvu + de mot de passe. Si vous n'avez pas de mot de passe pour le compte +root, vous ne pourrez pas faire d'administration à distance ou + via un navigateur "web" ! + +

+

Pour désactiver l'authentification par mot de passe vous devez éditer + le contenu du fichier /etc/cups/cupsd.conf et commenter les + lignes:

+
    +
    +AuthType Basic
    +AuthClass System
    +
    +
+ pour l'emplacement /admin. Redémarrez alors le serveur CUPS + comme indiqué dans le Chapitre 6, + "Administration du serveur d'impression". +
+ + +
NOTE: +

Désactiver les vérifications de mot de passe autorisera tout + utilisateur local à modifier les imprimantes et les classes, mais + l'administration distante depuis un autre poste ne sera toujours pas + autorisée.

+
+
+

Je ne peux pas effectuer de tâches + d'administration depuis un poste distant!

+

La configuration standard de CUPS limite l'administration au poste + local. Pour ouvrir l'accès, éditez le contenu du fichier + /etc/cups/cupsd.conf et commentez les lignes:

+
    +
    +Order deny,allow
    +Deny from all
    +Allow from 127.0.0.1
    +
    +
+ pour l'emplacement /admin. Redémarrez alors le serveur CUPS + comme indiqué dans le Chapitre 6, + "Administration du serveur d'impression". +
+ + +
NOTE: +

Autoriser l'accès à l'administration pour tous les hôtes présente un + risque potentiel de sécurité. Veuillez vous reporter au + Chapitre 6, "Administration du serveur d'impression" pour une + description de ces risques ainsi que des méthodes pour les minimiser.

+
+
+ + +

Je ne peux pas effectuer de tâches d'administration + depuis mon navigateur "web"!

+

Ce problème est généralement dû:

+
    +
  1. au fait de donner le mauvais mot de passe pour le compte root.
  2. +
  3. au fait d'accéder au serveur CUPS en utilisant le nom d'hôte ou + l'adresse IP sans activer l'accès à distance pour les fonctions + d'administration. Cela peut être corrigé en suivant les instructions + présentes dans la section "Je ne peux pas + effectuer de tâches d'administration depuis un poste distant!" + étudiée précédemment dans cette annexe.
  4. +
  5. au fait de ne pas avoir de mot de passe pour le compte root. Pour + des raisons de sécurité, CUPS n'authentifiera pas les comptes + utilisateur dépourvus de mot de passe.
  6. +
  7. au fait de s'authentifier au moyen d'un compte distinct de root mais + qui n'est pas membre du groupe system.
  8. +
  9. au fait de configurer CUPS pour utiliser l'authentification "Digest" + et tenter d'y accéder au moyen d'un navigateur "web" ne prenant pas en + charge ce type d'authentification.
  10. +
+

Messages "Connection Refused"

+

Dans des circonstances normales, des messages "connection refused" + pour une imprimante réseau peuvent être rencontrés de temps en temps. + La plupart des interfaces réseau autorisent une unique connexion à un + instant donné (un travail à la fois) et refuseront l'accès à tous les + autres systèmes tant que la première connexion sera active. CUPS + retente automatiquement de se connecter toutes les 30 secondes.

+

Si le problème persiste et que vous ne pouvez imprimer aucun travail + sur l'imprimantes, vérifiez qu'une autre machine ne maintient pas une + connexion avec l'imprimante, et que vous avez sélectionné le bon port + ou le bon nom d'imprimante.

+

De même, la plupart des serveurs d'impression externes refuseront les + connexions si une imprimante est hors tension ou hors ligne. Vérifiez + que l'imprimante affectée est sous tension et en ligne.

+

Message "Write Error"

+

Si vous obtenez des messages "write error" sur une file d'impression, + l'interface de l'imprimante (généralement une interface Hewlett Packard + JetDirect) a dépassé le délai d'attente maximum et résilié la connexion + réseau avec votre poste de travail.

+

L'erreur est causée par le délai d'amorçage qui existe entre + l'établissement initial de la connexion à l'imprimante et l'envoi + effectif des données de la première page imprimée. + +

+

Pour corriger le problème, chagez la valeur du délai d'attente de + l'interface et amenez sa valeur à un minimum de 180 secondes soit 3 + minutes. Pour changer le délai sur une interface Hewlett Packard + JetDirect, tapez:

+
    +
    +telnet adresse-ip ENTER
    +
    +Trying adresse-ip...
    +Connected to adresse-ip.
    +Escape character is `^]'.
    +
    +Please type [Return] two times, to initialize telnet configuration
    +For HELP type "?"
    +> idle-timeout: 180 ENTREE
    +> quit ENTREE
    +
    +
+ + diff --git a/doc/fr/sam.pdf b/doc/fr/sam.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b79e473973858abbd7222b6a2015a86fe83c500b GIT binary patch literal 262538 zc-ov@2V4`$8n<^nyQrwx?f{i!`$lXis9?hdL?xC00YVETM8&iB-Z{?R6-7C_;MuWa zFNnQ^3ijSk-|o%?vw3DV;`=>rcQQNQw6Dy6zWJuPuV?30m>W@{`TYmyE>*yslur8K z$Tn>hz6O1$DMV{8iBU=w zrKH#vN>ZtGQTXc;qP5PQ0(||PS~>O5#G16xPN7<-=sz@}F}hftF~PupY%(|rIb0MT zri2K+!P!mgHu7agYZY;Pbz`HoVF}<#tg1p|Owby1#wbNxw8^Ll(Z|GS6nxY9XTAuXK2%|h z))*rc!?gyzLLaMDBn;In5+V#*ts+csGAP1yL$nH`ZkWQT9ioj@XvH#Pb$rGUeY8H7 zPma-nr)aIwsL;lnG|`H1VPv!hzH(ZlFhUAVg2F@5QPD}^sqj*CR&-HxRd_3W6x|fv z6+IL^6}=R`irxxN;ivFd1St9_0u_A~{S^Hb!3Ir8lr}+ZQZWArstQxh%?r`#LUe`@ zQ;fnC8_M@eh~A*(YoOultx*IkLKLA2zAcJyMTA19h*U%=q7^ZUScP5@r-)Y=6h=jY z!lW3Y7^)biNK_0LOV>h*2JmJG4hn6^#)yR;UJ1> z+URIqoKa^~glfXW`F;Wa5r!DlJS7vDw#rpK}a>7Uo zlq@EQPoQ#UazE1f7w}WCiBC;X@H0~AJZ+5lAF&+@e)flIV>E^+h0%&2_*Bm~l~O7C zh3fdpD%9U{o`&j&#wx_wD9o^EVOocn48o*NR3!3KCD@>k(#8s%Xw-&?v!Jk;5Hlkw z^oGzdt-y)=gc68HYh(0ayrcEux)4ottUf^zkr)@j7iiFi>jYBTP(_R;M5u14He8sf z!psI!nxDKzlQ^#pU=kO;X+lg1T1AXWU=0mFJK`eX{1;jvmKmZA<>_k#CMf)huU-s4 z?xtu-{b1E&g~@IZ<~jcup@|LyBw?blaQ2HGMK8dA0pQaB@M(a>rvZiE^aDTo^Wv1BRa!#~KdXbIjS3B9Oz^YD;#&(1MS(;A5@D$J)ZLbRdroY)WtrF>?RZyl>#{N?Mbun6F zD^AZ(L|dh?zgilq3st{bn0JCES{GugI80fT%E^?8*UP#e3yP$3G;cR~YWb>b72UP5;e1hql2ST} z|Jt?V%~h=?royo6&u;bDwuG%-Y_P_0_R=R>#qXybH9ZG^?z(+RQtvz6yIiQY2K~7%b7x%Dw9gxzlFCgjdoq6S%W)6Nwm9ps*gYxidG^}a3ERhwE4y`U zT6*BsUH5#pzT83+UaIf5;GBb)~i%4HURJGj)nV#Af=o=#a1ky1LK^24FES4>uxYf^RSe0IwDY8@MSJ}$TN zwjiT@3W74B6b{FaampQwv*o`f8CCwbK6#` zaAs$1L)erg=PFN!-5xyV!0wvvIjy)PP3->s^hH@+3c7m4m!7{)-En8&v3p&voE{VN zx^G>w=SnWO){Fy&N=ch~F7ff%a(z=kGk!*GJo}*I(H4tq>95vKIo7>S;KBU)@eThd z`*3EPhS{I)+)qk7cQ-Sx=H=o3;VIh#H`bfs+<$)HwuUp5j_LJ!H(&LkakrTn@y~-_ zPRqfYRta3u|4_M0#R4W?YJVZ8MDD|$dn?br9`&zxy?<);p16I0$Bi~VyE{5e8kLc> zF&F)=4_;@BVUZJ;To0Nj|l9 zlx(zo--HoN1pQ|1kdDUEgZ8P`mOoP~dc?YQ4n@xUm zrgWetFxh#?{){y)RI|u^wTwP>ci#7@lN7f2eJe$U$UiR+*-)!@%ihOV_emY{VY}{g z|Fy1>b2}}YvbEmc{+mjuW9GcwxV81wmdDzRoE|yqvcGSWt|^|cruItwoHlpSzC}x_ z*H~V0TGPnAmmQXU&&;0Za#Fc-!R41J)SZA$75+@=Hgf-hCMjoH?7f{+zQ)_$De7|?{87}+BYP!^5xrHiGWJi{9>sEmls~V zw*PBr?=`3Q{2k(((k`iHubK`f*7Tk>c51Nle#?U2mbZOH9Xj;E-}A1`Ju$lG*E;IR+5?xiXi?YW+TDg(p7bW+qSjen<|*^oBvF!d%K_N>{9FKnc27VE8U$na|O}-X++jrhxOHe z_d8$Un9#;`_n((ncV0E_vvSvpDm#a`9A3YVYu_oRt>@yrJVMU4PPBR$mvPmxor3BA>aON!E}F}e{-K=#cz5ZwABG<_G7y2Ga?y#`@ioYvFzM4BIG$oi2GoN@w-VJ?2|^fX|ieh8rJn+fo+zRdpef>JRLl z);>C=DR;m1r)!&|+u!kT<9{*5xcT3twxg(|a!J9@`(E?M{Xf^6-X`+vN}q{Y-M^lF zb?ni$dKL0Z4Qe-aUU1JRzGD|&SeiL=lqv7c2mfjV^OhtYxLD94%dx?z4TJJSF2DW0 z`rBLmH}5`Ke+H<>b}w(tKjj#6Eb2m~=1<#a4e_nN@$?CgYpXx)ba1{jdUaN%@z3t$ zdppkU8FgL1*IeF=h}rn)N?7LJ zY`2RGbic1Y+rv2hxN1h5nP>3q-mB(CL-R>*JjzS5&bOUpX#{@C>L zoRnAnGT*E=usLU1mC1k8xA*%I|N4FSezSs4q@k{%O38l?Oq+N4?zRhG-wj^T!oB2` zr?a2*uXOoFxu$7r8q|CCboQtI30coq=rafU=hZn~cj*_sOU>M{;)8p2`?qo3-V0L$ z+_dd#Y$zXieQ7mijeAiSQl}=>OnxfXOK&T_xD8?OH-E?{CmUy;>EyyYeGlV z*}Q74-n;Uehx?wpTp^EEoc1nd>0eV$Hn>8To?7B!tD|#ns;aD6yzIlA-p4Ry$GGB8szfbwy|(tR?lBW4>`7|UtZeAcrp`l;yjXZ~ zLfDmlJt}1_{pRZDe(y?rQugO!9ZQ#7m|bh7f48cMRP~P9GRtzhHTECdVdJKkVdIN) z7re;&(On|X?r5Ql@H`nd-g}MftjI|NFK1sVH^TQ>7pBwffZErCj<#E|a$V=UO(5Gh9o{bGuln~xUcTzt{LhL>yR!t6S? zyz{%(+~6BAkV#tgy58m`D_#%ZGHyj)ckgliajy;9Jz@?3EC zjMA!?BPmlIPo3dzr=9al-U&#)I@F_W()?GSua2wtG41- z%%1RQ8KADSqvg|$-S^jA@Ozon>+gT=?OPUem|A_u-~|88gQojj8aLP3N!z(g?)MF= znysDbzAR!(K+QSy^sj3seJ1c`+U+NLt+=|eg7adpk=u^l^xe2{LfLmy8$Vm0_A>0| zhF%@}EuQwWufx;wioLZw{C74QI^HGa9pM#FZx?;}_7tysPuj1V_guR(XZOap{!Op3 z#^RgjyFWg;S^U>- z0RJh!K8e!{>l2$R7W>vdqlsIGeB019A@|9rcO#do?|+!y(0kmC@BQi~e~bzF-16K%@A{{|^ksImkGebj zPwx}WZ{^H2{@0@Vz{GZ5r{68^mV3#u@uID--NTk;+|D|(?`vR}W7+$f4fOe3uU5{B zBS9y7UWl8Dzv?%z={>`hiU&I7P3^X~+3jwhjqzz|T{|xLUOVq|aw*q-`%+}iG7zAAmz$*0X1k1fz|>u{~qqsaMQS+ftS2W+iW$D?NB zQ4_;;WjA?LsC&J5iwl+VYpyn$POi$WIW4vCUlmnH2bZq0@WIi+4VF!B`QFoQYnwjv z%G`Brde_JBLLF1xOO=>c-OEwEFgz`!y7#rj+{pP6KF{X1sNKR-g_Q_Q^7QX{JAKdJ zTQ*%RUQna5|K;K>YF6%kxp?X{@@4h+*^$ucc251U~;7C+Tt>+cVS z_g#IgX_&*NbIn(WIhd9pC64G5_h-tq`Iz&m*3yc9A1u9Pk0-0=uG8yTQjb%EYoVh z67OC24Dp>R4<8& z=wGJA-mYyw-pP*h{_|0@`b!+txzT>pmnSA&%GgtS%Zb4*OQ*MdyDx*J^O&^{>o!SWtYKTMiMU_Dw}ElhcO8wZ6+fknR{>Ef@YHXo|Ej;``q_Y^ zP3kQu?tV36T32$}<>fcCvX4>f6U9$$QU`=)PJFA`IWu)ibo!iL!^7|8uZlmp!!5UV z+V6Yr9rl{KaAN9==pifDZd&%RdbKKbV$U}EJ>z=0$rX3cT+qwVIH29qS{1ck*O~=Z z>mAzFf0m2ermS-_CN65YzP#I-tVc%UyJq!Eq-8A+d(_e4e%QDc70gh*#{S1ymF*@a6sjom+$# z!zR3$=~M4%r?Q`~w>WN$Ijzoq)YR2^`im+prgRt>)net|iF_4y?mm#+`*c;Tx1m9x z2id7b&Y=^g|292)7x=N2d+L@LQavtmQlGS&r%iiHBt0Pf*FW3kpP9{_IiHoZC?l=W z`=08CJGy$5+7_6$RlWGnm{vL2?6MU1<0r~hOBtvt*s8v9-*4Ft^}MdV`)p`_cG(!$ z`tEH4-+gj;tF9cC6j{02?xtz8q99}!fukGiJw|Y$5 z(eL8D;pL9(H1xc?C!q~vq&Bs6Uvj==Z@NlNxAc)S#&+BC{^_QDj`7&VI_op`EOvHC zj~&qL`L%!)w-P<*ZOaa4-&t_`Na-ad*O$?99p=w$HM3yd+uzfs5d&Lg)hOPBu0p0Q zzPLEO!r8CYQ^J3{S<<6sPLC&*)vaDsT79r9J!jR-87EAB!%GGpz43H++wU{8nmb%N zm1PRxQx3T=*`WNbQP*wpD+~jY2A<2tdSUfugp|2>yK}GHJ+AwfRXiPbx3>2Nb*+%$ z*D~CE{(0oOaG`sN2Y-*P?v|scTsQZq@{LUj2kd~P=0#a5QRhI zE>j=>?z<|b|M$m{*E(=X1sA3^4ou8`I4^ce7te#mH?=I0RN&NpQR6xe>Fvr+i(54A z)}(7$>M3m(&pgy@$hK8sCDYCx%)U9S^`6Fbxw^&1IXd$nw(&ja-pLJo&oDp-61n4r3>?_-4TjL571{81Hnq1`RR@`xtdh=hY8G*5nw<qt>2L^dq{AiacT38#QCaqo7*D(q=tKYSd_MyA3ZFrFYDo_bu3a*2r#u zjw$!?aoprr&2M0VtMAS8>+QO&al>ad%DglTI~?KHHZPx4Z@azYp_jwmj9D$OIb1uk zu95Lpbih5=hvmBsoG|snlP2*=e0tB*U!Ju+v!`z!N35Dv9IrQanJeu)+SIV;_Sub% z0n;>0aqfGuR+En%z4Kt-@9qC=mFy5-Yg(?UI7bz4@NUtwHUIAYNRC`~uYyZbswV4R zct+1FAJd;+7;*idjm7%pZ4WRc?R9n?o;I$I*U_`h)en`yX=i&^3CWGjxS)BcJ`*@U zvwq;wSydk7wSK)iGbJPIpWojwY4=l4-kUjnJ9VIh+pFBrZ&}%+R11$AHh0X+^>Vs< z)A04e-tQtD(i01hsQYZ}^4I zJlQWQV~Atg(q-M2dAEPAZhm9rlUJ2D5|8gs%G`OuVEX(fcigl6Z;O>78YW=(;+pqQ z<3>L}cxT6j8>udg>HN`>lM7bdi#+C9)_M05O$I&bW$uaxSt@nLq*RCYozJNQ$5Xjy zEARO`K7AXOvp!-?ucNn~7tj66NalE)OUh55l=I0~z1n@uP*wXc^LO75quI1)&2nrGyfZKg#ub62O@zi&MycuY+Rh{N|XZ zS$mBDp51)?=qr%C!Q|^cpYWRNmcq016>^ zvy<=Fqg~7BHV#d@SU<3T{q!}y0Z;DVZQW>A)cGmrk{V}R9RK#l;z9dk{(Sm&fTQ|R zW_;y(N%MkRs3$gZbNTK&i%GlDFk}Dp@dYE;G>_H29kT~#yl%L==M$6q;+K`=fW1@b zq;4?@j-5TTXSOJRD!XU=hMZ4x)QjB580yUKo3^<|VED90FFdr~54rkO<_1ok;W^k% zlYVq1-yM9?&XOl6(>UnOLKA;PHE0{aX2@TIkj9Z)SGt;FjCE z(O=zS{B`qQwNJmU&2X)fd@&_)iEDd0vCgANmD;Ci;}6^R9k1_p%I7!rxXiV*YokYl zzE>|1*kE3_{bwiV@uXM3$#O`qS0(v+MAhBR`9-a{)vF!U)O%tr_oD4KF_zT=|{sFrhQpl ztkQs*!h{@svCo9EX~VK^H2?nc!0|7SHmjpfj;-~2smB)m_RVg)KV$`rGLAHE9vk(> zE914vQ0tD`{6C&+m>ec>SlW@L1tGcP_XqlH__t-wfm80MF9voW>SC&sH@xn^L4Jei zX8SZf{Q^hVThV@l4_RmJjD5yD*Dg=$M=skxq79XH>Tc@|i&u_K|28X-%s;hv&vDK1 zL8oWBw#e}qxk8gZAQWqb894EU72bM~d-F$2m3t{aiykd`;f*Ljq8BUkUc zP5h{6viF+#tR$1^()8?J$fO>&LMmr|WJk@+z;J3OBBjcA3-n?kd=G1QY zuitER{P_HnkM2b_Y=6sdaEBfjuVgom&wai6#-8|o7k_*4{bt*d3zjzPvooPfmOA-} zY5#ZA=$ndt7`|vt6kNuHB!oyNTSM<6M5{hQ3rEzj4R? zd#;}{Evnft{K(9O_{PYu9xe5DQ z&RDoM*E#j5I{9Gs9mhAhyYHo!>9<4Iw%$p{-pPkerqgwHJI?Di{K8*8E5FQB`3VNWTyS5J=aGRC*9{?9Y@_&uf4QbYDnd)O?wTf6t40`Rigwd!ZA z%jeSDbypTN{IcF7-Ty;{D`$EN)twx==2e7qzJ1%%amv3zYl5UO!ndXXf0fjeKX0WZw-| z&up{o_@U#KTDu1%AI@&ur{sLK+lQ+E#9V4WyVK_Je7-b(V%^@={IZ`%*|eqa9N)*6 z(+zCdGka~E_lt>@j|cSFls!pZgCFDOvrau3IE3kKIzjbLJ{0h;F(&>Aoq2wA&D6gO z=B01Epf3?;3Y%Cr-gNUn=cE$PduivLdh%cW{DG%ukD7OipMTon?NbN2ZP@w+pq8e+V9FJabMv z`qt~#85_R`r43I~zpp&&l52*#_USw7H%3*fmVsw>4rreI@jz}?;7RSEF){m{19$aI zyI--){#kd9zdEzCSk5c{IsL^e)uwqB`5)huF6nvv1r@aM>cIDVj9(k>Svzg>sj@de zl<8cjD>W*8RmC;YT%h|X#UpNQ$M{;Q71`*OrQZLk52?udEFRhTzivPVoKSn3rnUxJyzOz{LJXmLw0l-Ic8eZrpCc*2RtnH$CCK+ZCCv>#+cB%{K&~$ zS{LA4R&Dz7^wnn-9=nW7pE-JX zgU;&g3covic5|-!zEhKOPc97Iyz-Co$1m2X^xv#9kG&6XeOYRI`_D5crOp^N?p}=- zV?y_K>$Ron@Kqgp)tIII!=as_*gRw3VdHjwTw8NaaPGuE9PYiX*41@S+?1|t>B-BS z9V_-!W;Jeb{#fD#$|1K>@hO#)Z$3;Zx3uJ{S#B98J+4KTy?;dQ`@}t~S@HW_6)A7m zG|;V}2lRZ>%_nEf#x>KQ?J7TSU2#*STiBFxLDwBJX1%J{B<4%$;h#(0@QR#dXjv*W zdHk8qGJGHsEj5)t~ShY?ykDRY{qT3Q}rLB$I#XhcEBYLdE)@D6_d#tL_ za`uHvNl9hm8lL_-J!#VCEh`^&-*PSRO!I&20G$oEZw#pnchVc$h`rI_+aLG5XPCLIF z_vY`hUxwyYtlnbQgW}K0rTT+?FEvQt*80Ynd&9ST#WhYEwXS%JzULf1j*eVbJY-V& zgUdI(snqvS#ey-<$~~&PWzv)GV-+6TOEoy*a^XSxtiD@1IcDzkFzlRL>2K$B5B6=( zN$kgsYqcFK-*T-poat0)Ph9O0sbg=SsX9Kg?fWOs&#Q-Zs^r{Y^Y}9zUPMmO?b~uJ z>S)EArRX)yzxDVS7V)t9$%}toRe9HWdv=mT*BagaXjI|se0t8%&Os|jg;!b<9^>%h zrmBBM_RD7{zwR|>Z7bbw+27x5ox1RD?zqWQ3+_z+ujz=mUb&H7OXm5xJ1fg>c|0wnmGb|sx>g~&wcTYODDdWE;abHN>g?9H=e`U7U>^Y(JUCmIBZ54(Fe9b-X zdGPq~?4}NtPdWZJCi%b8CzmeCJA!ws^>Nz8=Y!jabBCW~4t|-^BQ4+K*rN2AWxlof zp4ocXuB){!|CV)4J@QcT`lBwXHhx_<`t;Ou*;~@*z5UI!#i4flT4k@M|6TI0X6HQ4=-a>UUEK2V?oo68d9gaahW^Xp-1v8C>H+uHw`u$0!gIZ=fygXd%)|hL%_s6M&V=^Z` zY_jC~>E2cA5AT|`f6CN?hqF@$y1`DyLi3y|Zxol1>dGH20UcII`_1HsIE8$)o!v9ANHEOsz92=2iB-E~C=h zMPIlxN4vgV!?b~Wj}U#^Wwfb$?ahYSGgIpvSgL)w{-6CHAKqWz=T6GN|K1%@BzGE4 zH8K6^?dG;{(8j82$8C?6@BdPD-1NWeEPq~d@1rJ_a=IiQ*B)PgZuGbjBa~^UQuF!y^@x7wgqt|=y9N2%L?DrG>(rY`vY~OHm z^4b62GWg*oXWk{~u8WOQaN3ZBAO?3+I?*i2|HYJy8|g%=7&qkrMMu3MRBH$lyw3PH zPpvT_h-L|KL!ocK{``L#g5-bs;T**xh+s-qpu#BKSSL({yAeD^!i}{-g|eVRvq}jS zl{^)Saig7ZrBa~6Q>5*nLK2iE6L}p3PoZPDumn=qg0qMEF|W}IMGVd*088BL{muF zrcewk3=59)e+7!99aIR4mQbPOsnC=#EDXW7MWAS7SX2mh!D)Fal+bUulHh3x6qR;R zAqi<)7kd4HGHSc2L0yMnXlN^(jmk zcbrwaQ6fcKqi@NSj8Z~{kY{~TrQ-Vvjtfr_w}T4Fsw7n8S)XKSfhh?UKRN5g!s|#@r1oA67sB1@a)Jlr7(p>iliM>2$htIO1>>L zBaA*Tk^x2B4k{Qc(P5-go(d({Nw|uF6m5;Z#DY;t_=UvesgQ!5L|_E3j|qyfIr^4V zC`vNNNLkh=FwuY^#9_f1o5O-IEl7FRCzPTALkSXDporT+#Y!KO@>(Bf#lN&*SPB$v z4U0;mDWx4I&-yqcm|-N(E(A}Ju{kUf0Ygiel9XqCoEGdPf^QKfQnbO8n5BTB7%3Hb zt&fv}okZ}4rAnko+ChaRr0l}Vw}lYwB%BqrzCaPTg9<^h5-RenFIam*i$t@Zuw^GP zm_&@JBy)_CXMI5!^CFoN|KhgnBr7VIM2u1LtdFS#I|=7aaZ;p6+d+j;N^A=Xm#4xC zb`pUJs#2h6YxF7GyidvVK1K_65+Pdr0!7>oDpq2QBIU#wM&ja{QdqlS6lHT*5Ecw2 zZ}4NdU?%}FCQzj9pkgJ)D0zb)!vs5tR8m5R;VPTMVo3#~Buq)kvpyyou7t2`5h>aj z7F=S%VA3fjuk}@;nZ!#;OeCnZgNT)BK|#(B65$ID01O;J064Hj=fE181B+Y^tU@`k zPUOHsjsq(#4lIQ@uvX!~VuAzKJ_pQk4%o{auxL48a&o{XP`w;bjvUZl98fPDkpCPI&>WDU91w9FkU<;}5**-S4zL*q_<#d5l><|W17ppB z!Qcj%k6EH58A1QRdKh7VY-2qPj##|Xm@J?KpdMc1QwXR>O2mp`Xp|firx!$eRDv+G zjr2%~U{X~{6S71A(8CIv(l*e;;0TkCCS{3;I1ix|1hQ?MM@qy>9n+L75fSFW`DYaZ z=8+P?SzJPdmYZE>m`AX~ZNoeajxZ}}S-29QJYaU&MtP(}tY;T1OGE^D1RPO`0C^bP zQW{gVw7XQYL;%J^2xDR!Mrv%`P*-!wN02iSS5? z5Kz**@L(8&1b7&Nunq7qvK$Za9gMdmSp>c#B|=~ltCf-EcnI&%qQ7P!z_Td$NJ50dC1b+May&qfFj81_BhVuW5vv6eE6ec!JQ9egP~Z`X zFo{@MjtAHgCTbM~b|fJ}DJ24umF0K<9f5&IKu08EWyi{LyZ{&R1JAIKAZ-T`5|@Y- zR+i%dK84YOW<=mqBtopPvK$ZLDFPSqHk)>rgoyPNmgRVWPC*RJHaaCCf=kyzDp`&P z;1rl$2ylu-$S##E#{+B%!$ow$HZ~<8LMbJhQ6otMc`5tLUyTSIUc}Lz_>%e zQj`>8lTKk-jt8g|CfdRXREmMnbNR=$d3zHXsMvO>MX$KKf zihE*8S(b;;7bYOZ2LJng}S*8cj7sgNmz-AlzqNFYe zRy`)m^#J+;77GIUl29R}iVIW9vOOThh!&V_=!;UJI!u=BLGie-%w}!ccM=-^*Il$c zDj_mG!_Q*Irgw*Qh;j{FylC2XmP+4;()Qj0ds-_ z3ZDZinFC6b18R)}iiZQLfdj&u1LBnf0+0hDiUUG~gKW-0M&ux?aBwnnaJq4DMsRS{ z3ei4H$=c`Ig)=G{xDUy{@|!RK@WU|?T(S-L(Flc#Ve-2$0P+L26aw<2rMqKRWaPJD z0O*IY7$iyBL57gpg%~Ek4+CI7Tq)=Y1nftn-0mQiQ@(vgR z+y_ihj3;T+1f>atbj9SiVFAL3(Sq57Kp1HX)oJqkun=Qp7~W7oV2lznR!%DzChvm* zUCC$)=}N}XDE7qUcVZ#VhzU-S2%J$uhQh2Sw7e8BJCn&EjS@0AE7eQ5ycB>~BP-ZH z2&|DtsaRZI3P5)J@kUD6Cq>|m5;9hHFNVuY0W;z#uqOg>WKa?s zx5Et!V2->rBT$&5gbc}Ak+H)M3wW*x-GxFO84Mw8a625aMBEWf0R-;Ipd>WT*y+25 z(YOF_+D0B3#QF-uS-YLrNHq4yphPFGveSD_TwS5iM+q5gB~2*pbYBycG>yU^8L5Y) z)SaBL!y5}AkfN|bAdn17LKC>14r~J6#iB4s27z#61YxHKo3Q&!qfkgjDxsw_%?@Ww zh(n6n6M;iAC<$$cHzq_PMXU&cL`ukz(k)HQ4tGq5MT!pc2rQCCiB5a`F##G0#>O@p z$)b!~!Va%2;4P;VwmA@Zq=XEqwCXgKo$hj&=#hy)B#~!I>~P71n51Z`BQQw`8Omxx z+u@T5QAtL0WwVV+O308nEhU57=`n}#3XMYHk}OI>lZ2fva~Lgnm?Dr#2^lNg8zV_O zedaJ$aBDzdlM*skP%dVNVy3l4${99;c#aCy$b^)m+-xEx%8a&U>r!8IHQ7g-!!1#xhh z!ohU}2Mv7=TH+iul{sk3a?sf1pf$)rbB%-c6bB6+4q7A}G#NOk(>bVgIj9vmsJ1w$ zS2!s6IVhPqC^|VP+c+qEI4B)B$i5upFAg#Q2WKb;=MV>n`3JO#bY->hWQ4wEMT9mf z*&QS3$|!1n1hT0@Y zofTu0_PI6Ulz?W~h8d+)tQ<5kc{fmqGBQe}Un7g5?fsysia&f?+*%5KT?1dY@>dx^f-?6h#Y2zL#Q~rgqRp8&`(N*uv#G7;SmZj zKU~nuwlO~zNBDqaEMfogSOx+4u{eq=Sy|o(h@WsI1Lc3n5=bhtdjAI!MhaISPoAQnA+i@@}C3hZEcxPzP683K^+}wa-0J=qnrn!%3;oO6daJ4#!Y% za8*Sj53Wk7;8sAaO7`>zJh&>l@z@68SW0>fQ_A})*#lnygA@3XLSS$#(oIYyduSa% za5&8(Avjj*Tcxz3BFp;#fx`jZXA^;ACEgz-W;HIP99Kg3JxZ|pY$IbVa_1lE9tzq5 z-1nfCv1!B5h@(=NN|yJb`yMMue%rX1lnSnt^1e#e=7;WkDjey)C#8Z(4@+SxS-lV4 zLOE3;Dk~p}G;ow4pgG&Jp z8tWW1r#Wcwa?m8@pwY-dvyOv?7Y9uv4jL~UG%q-40B}%6b5MzLP|a~r5phsea8Q_Y zP~37*AaYP-aZspmknK6hm>gss4o+?kPCpLL5Dt!FA?AfEaXTZm@j8P+U|vY6fh!4n zL$%Qu^8BuJ_7Id+5H(rz2f|T|=*?#vjzYPl;7VB$2!SHf>~UwK%TRmKxKjS~K0t~H zQFkDaA_*B>8twpB+7Yiy1^gXIr2Ctc42D~^hP5-08c7JQ(ze~-Sm`FQbiWfL~>siC>Sngk$os1+VZi(G(*^irB9QM8PqY z{K8cwp3)H`yznEh`t=|ZI4-|*Q3-pKxVW(|P-K36g9pcDmo7LfI7SPL3Pz+z{W>g; z=-3NJduU}#DkqmNwb{1DAP7Z zA8mx-vb--uMPNj?4pyYd6u~;cxoR z<8Ut+H%GBChp{P)V*_QrIg*Vzl#Mx-4K6wUfg^oB2||qVB|68EEG|0ysq6~!XBB=A zxAgfeR2gBS#^C>2XbeT1DOeG$3pQvBI<3({f7lULQ&_18aRNnmE`t1ji-T7nV9VR0 zSPWUQ@K}?Z-ViRF#igqY}1eTZe%bmtE7+9#u|;$LWf$`MSj&z zW8#Vh?4m3G-}VyfLR-~^HTNTQS^#t``cGxMveEhwO>~6bn9!QH_7$4Y7+tJIg-NBn z2F1j!MKMMiVPoK}CL+>LYbfCL{S3!;bft42%R(l;UE2i^!+0+3eE>! zAPAyBz{TxCg#IrOGg;*Bmk+i^GFTzdE6A;%O&HQ@@*>^$NJ20pge@E=3KvfoD`~qR zs{d;?a(PAyD|2BB2ZG={LA)qL3gnfQsG^Kb(6Eh{Pu(vkuKD8>R3AYR($ zVP3?EVI1wgCPFL(D~5SiihHPnv?zk1Tj;=sL&qwdGRMKAq@!R*cu)fPpo2YQq9~Eo za65to0{0C<40tGzEJAEGoRS9__?5G`Oc8f;c#=hku7=Zg7%(bvWrvB|U_8kp#8<=V zAFKl{Mu@oL5OD<+`7xMCKPi%=;95;^`4DR-M8^O15IQ*0QHmf$e^`bPPsp%vX}}hR z42mI1N?1V&CuC?RN{K;|MF=p5%ezW}_)KOud8J(u=KhaLAwxn`9EYel4pDJX4~wxx zGNwvwF_>dCCAzwkMG4-B(}fC#mMRk3j>|QGF-MEnUNAQ4qoTawj6Jt&fN&Gy`DDQyb;jFwAAXyc>F$j<(e?9&i&f0O= z21AR^*GdufQQ4dV6sk4yQh=nzbA1>g-W+1nFh<3I!&y7lf~2ZY3Xrr-!x$9>4rk@1 zfUrWOq39Gy(!U-D4rk@100|&2kv#>H6qVGg1q!{JCLCP+p!2XS#z3tB)^SsHB)q5{$pN_i;&%t6362y+k>VvJDAO95yOioynA4x&Pg5lVR} z0L(!!HVAVN6=IA~%1Z%g4$`z3j)yKvh%o|_mjb{X1fmmR4x&Pg5tzIb0OlYhW7`}= zg%~3+c_{$RK~Z}m%t2I$F#?m90?-^3r2xVlL~TkCn7kAK<{$yiG1)c;Q6a_%OkN5A zbCAHmb#io3LW~iZycB@upg1-Na}X6`jKJij05At(Yiyf?s1RcWCNBkmIS6DL!W=|} z7$cBQK>{LaMhAr((r}bHi1OGVaHTvM(HtZMuSAqNhzc=AAl-r>8E|icI1v!$AS(73 zf%FT4WJGh2WM$AnR3tM3=@e5a7vzx zXbuYQsYr7W6=ICQX?ZfDIY^2wdkAw76=ICQ8F@0IIS5;0+Z;rN7$eZGK!6MhBC>(# zj8suVj1joJ6aeNRm}v-e5EWvKAmpV0Fb7GT6u0%+qJ$VD2ze<0%t6>`w#`9Qh%thY zmjb{Xgj2w_Ifx1|MiBB+0GNZI(-7t$D#RE;$V&lW4w4LmHV085#t1@Q3IKBuw#K$O zi1HpM2ze<0%t0Up5au8%#27)yO95aGLNd0^K~#t_f{>R2z#N2~X4@P@g%~3Uc_{$Q zLBKZ%a}X6`j3DKu05Asu-yqCERERNxl$Qd)90aXFn1iSgV+1KL1%NpS$=EgrQ6a_% zQeFxGa}XF%2y+k>VvHcsQb2Io7PeIQ!6$I>t_9m|1oV_7U^puRhO;6_^EIEOr4s~!^duC{=nHFH(Pv9^Ocz** zDgp|DbR{HIf|DpOKvkkzW1KJ{u6|J@o7vTafWCu-)OV0TM(`sT;Z!e!iwX%BfGUO{ z?Sgi!TZ?ow6dm3K+)lutK$~7wlC4X=OQ;Hkv;@%KW z*af2h9~HCn6hWEq;iaUFMH^J21_gE-$-o0w^sjFo6BH}!Dn^T2ZMgZmfFk%@5QTRg z6VUCCklyM`ps)263tEX4$=X0W27+KPq-Zs%#85gEStQOzU!zM2hY^Li5Q3F1 zUWmjLu{BI#Z$ciT&6ioz(%xm|L&u5USfU>^#n`v~_J6Hb$+MEcu&fv~m?@GM24QwC z3?g7?0YLUgTN&B&fUvDVNEWfJNUuOJ!Xy9|#1STK0}IFzW(xTQTEl>_MQf3`JtZEj zWXw*&m=J}rNctV=&&ON3;yFIB<;jW@nk^FFApQA-lL{;(BgD63kz`N+2UEy5a4kW= zwFIbuMeib!ca^ZtronBg3xi18hW1d9INBo* z6OMe+;+`cVP+@IjR4BxaEz~e@9Y(-)7$E8#q!@38!T{DJZlU6=UEU|wyBcgE z2eDGlVbPoeP86`BdyPt52Vh0oTSZ6j5|2C(l>8Zp?E-pj_hAN7n zQWef}hzbD0Kbnj56eB5d*&u>6z+%S{dv?fr6wYpybatb|QxPHx1z>!o2uj+9@zLE) z71EckveDjHw4fh>Ju949WKi}j5AQ& zmr-ONM1gay#0C}PL#?i55q@Ey>#Xe}*!Kv}$H z4IWTdQFdKvY=yOvWx5HjQIkvc94vJI$oo7bpl2w4jfpLt+>;F~J&XKnxPMVPz7QLIeB5DlMAE5-}4tP65k4t7q(+v$00T#%+X{j*>ffVO2_=)(Sj(-xPSCdwF~u2M>0-n59fT+A`XZe^S>ZG`JX$X< z*?xMo-opvdx2&+t9Q#>K&@+twar&N7**bkM)Wm9r5rs1h?)m{j7G1~K?mDs8GzOzS zEI}H@jznLM2aW-f;vrfwzBERueqLLvDfiQ0G_W%Km)fY<4qAcDw;d z2#AYt*jA_%`_tGtq*W*yk}RBda3>Uy`O$Zzj8wCzt72GOXqcr$LEkMW+TdWn5Ep_u z{(QgC!wFQuvd-kM$0Q`}2qi<~jJO9SdWsV4&+B3}_sGJz2X}}8A&dS)*`?6x5D$5Y z-tZKwEJ~Pa5_yH2NCjMY2dD@WmiYBB)g)P{dg1L&fbNgR+7Ti~P$Z-9e1w@QB_!YhlPN{7a;^R zNs)F2a>2kwCN=}PAfrH&6lG^17ZA(Fb|4pIxL~qy$CrfL+$7xQCgFu)B#diA!X05! zx+6?dOc8_#I!cWgKScoYX>rQYLbTSO>VC>fB~U6E{q)nypo7c^_Yd(?(j1tC7Ay8M zy-rza1mulfg0G26ynS4N`3P~RhP3ORYb)<0ymJhYp~S$12r{U!DkLo*zn=gn zAHg-3HkZ9_!662bH1tdk0MY*?*q-9rz z6wbhl7X^ySqQsOUX-2j&!c`w6Y>aSWMv;b89zPWwIzVFtibWbyBrZcL#k&OrX5d%h z;!$wIW>{Mk8Dw}HRy5}rVYP*kDoBwj3Y9`D5ANxcFtk1iL+g{YdEP=mg^^l;$Q^22 z++PzmS%kw0q9uiqHlt=EVt|u{JJh6fXPUIwnHGvM@>7VCiY<#xm@;9oKG ztMD6cei42lz>8Q2*i&=H2=Rq7zX;#Z<`>e1WEt}d#lNuT7n*;8wGh5n!72!!s~~-W zq6(51N>V}ULP20>#TggBrQoyhEe)TAZyES3e9OXT;ae4ard=q2e)7)@|BS(BmVX9x zg|<-u33VpLXA(Z+{4-^K7Js4P8^J#_=4bI2w(w2(N>%vA=LCSC_(r-=0QM8#DES-l415zQ<80xZkW*Fo#^)rIg>O6s0xNvudjYK1 zomrs_urB7G`4YhDnSU0(r{J^jHEn(tzhDaAgm2iwH{mN4eB-Hr)gu4Q&k5ixCOiuz zkY@V)3;}B+XO);vnxDlts_>1c1N=_KH=YhyWQcEk{lHR#e-rYl;4_~K*niHNkPxlW z7_ATIQ$Rg5p`n9@YJ>TAP!mmbw0tT#J_dEw4ATiOpt8ZbSdAgkg#wm=bFe`_ z)Trg_XwVAefSq7Y1vLdW1569m#tI)37D>9;1g&9+CYnzsEs{l{%coHmX>s~!Asa18 zG9>UxjAfERpP&!XM+@~~Ez%9zXpKNzWszo#;J+6-h0n}bHYq_Dqt%=Eq8W=O>0bOwkD;5gG$uq6-DJ08Eb7 z#D<$R;e3OjLI7hA6+)=i7!@gg1lka)4>85?bu;MoLLz8HXk1iyEAxzlIzk&8Vn~bw zT?kc$HqNMz#d+p}>Oy>1xlmAJ@cpVch%5!wMwlkvg@S4$Oc$*k#4~{~lKeA26~z`q zMI!vlk04Yf;P+@j>+)%!-eLOKgg8w?1fKxvEV7vk4K+&yKcc#rxM*F7E+Ix66Rb5D z`QJdbg}|@E)Qi^ZqfBu^I;g%mza}P}df^+WH^qj9X!t1zRi`;2OmB$M@HC+oH7AFgbbK25BTZ`< z#A_kFDKl^^KYsH=_`^-i3zB+{jO5V;ElsROLVz zgD}rDROcWqSWF=-QY=&m{|jmHOO#e9k+Mh;l{yWTI!FTj0@XTiP?*^as&qaDOhBmB zjS0NI)bnkFYTcL+7r`r0{vFmlk^ejfiZ-aw`Ghz@8_-aj7fKPR#zAMnaIY5YmmkY( z&mbCgOqH~7HT6VaqDfk~i+ZAO!XzzRK0VRbS&|lk6g|;*Qj!*~o1W;4B}t2bhMwr# zAxR5|Oi%QMg`|a3r6>BvEz%-5peOp)ERwYxE##F{B+J^&YK@w)Dw|oYu7)C2O38GQ zM8#&M%~D}DvyxU`Nh;iCR@`b&LPbcjqDD(a+RSQo5jUx_94+ZpPSyjfq9s{TL!e@8 zW)-&=Ewi#Vvx=t}Ewid@W)-if_>q-TN=8eC@B^Wgn9Z!DG=LSQ#BF93PtRCpm5i3; z@+vElK`AXqOL_y9)eulhN|IF?uvRI}O54mThMu;}YB^fcJ20#wu~SOcW>!KPC67|7 zBv}dDw_8(~(sovil4iwhX0?hwOJTSqE8<8!g%LKhQc{^kVUp33UO;X&S{P+BD@IBC z6_bpXYC5R|oGFlRjrKGxm!X=}nvg`rT_Oi@M+suk#RuzzpmI@J$mBJ-@ zODX9A+A6C=Z%MC@vg#~CVr3{Lddo@>5tz-a;vq@Pthmjr;zfg&StVA6RJ>VNfV7zv zw-RrJ#LAF}H*v{inU%Jgm9(1L1YUwNl3vskE8ZDw-liN=6GQ z-bmbLR?13fl9JKFB&LH(I$ES;w4{3SU7nl+6lQ1)HZB>1ZJLiL)+RSR@pG8Tq4CG}wloghNn%WX9gOM0dw3U2iNt^v@ZIZE+ z&8$|3C@2Y*!JzBP*vx8m42P0p87NONN`hq|Pu)-|sU$=#cm7A*Sw_XRd~H6#0v#+! z(BSUcxVyVcutpNxo!}w32X}XepuyeU-6cRskO0GdZ_mu1E3A8G&CJUO>V)h*>zvvp zyMDFn=|?Q%NiBKSM=ayXR6y28EaS=KMAkz&p8iw=z`u>P|77|o%3yoa z^ikh>N~)ffgX3>a{~$LHe8e)IJTC-fcfsa|nQ=%2X$1LNiBdb6r;NJq^ zKRv)BZ?QdT%Ko>ee^9;vK4KYGM?0a20mgLPwF=VAF+%lvuuHnSjLk& z%D_h~<4G-KAoJgor$5~l__s*$Po`{tJIDUXl>Kkv-=9o5{ua^v(ex3^c=C8XkcIJY zE9(!6&OnyO-g@!@nE%%F534xfBbM&1K*tmhm_w z`$GT?WO>}To~+lu?^}Oh#Xweuf4UtCe9SVQ5?=;BW*JWjC<7m}jHg79fvhZlYx)Nv zW8h;v3kcS$1%kDufM9)EAXpCx2-c$o_X7ZUXBGh7OMNK8c3_=Z@Ma_cyeIfj zg6+UMvfu?N0Ne!u;0_J|$1wo#{u}^I`vBmLEdY2c>Y)VNfpuTO+dcsB@)-bLaRb0( zHvl{=0l=UU0ETz~Fm?lgkrn_9p#WeO1OU?;0GPJ`z<>e(Uit#Si&X%49R>ieMgZVQ z9{>)x0pJJ~0FM3u;2;bDj)ef=kOTmpm;vBf7XTjm0pPI`03KWb;64rjcQpXGZ34he z1OT300N{Ni0C-af0N(KdfG1S|cmoCiUhx6ITPFbU4h8@`p#i|?9{?us4<*<=&) z2Y};y02n?4z+@Q!#>NjN*beLucCbI#!Tta<V{k(s`rmGgg{arkXL z&&I)|L$3(3vvROC1lc{@OWxMXPzhwOMK3QbO0NuZwx^e{c(}9R?}gCsg@g{h=)#gQlM zpmP91#6Y3IV(@w9tbclShAhPXQAL$t71r(j_E79ABW%F}dCY1PM-f751v(r3kcj+Z zd3nhk){7!GCTA>bJ-M(FUD_BwE`fMK9Qhm(5z^#9G{xN9W-rf`nbld=c#iMip5N+h zj4b8g&`|EeyIf8+Jv6P^E0ysq=VUH8~u|ACGF-d_*B@X!9D-egi{cqS+WZODu) zIlN^HShGb~18hP(6Yql-|MQ#v2Xy`?Z_4z4{-%Fw%B%$J|D;X-RxR`bmX=lz5AcUm ziNOEh;7>GbwufNqkJYrKDP^}HiqdkRmTntqhwS4rf_u~{o6|pMYreJpQn(!v*Jtu< zP3G>_QEntlK%;iOhGcqPg^17nvw)MF93RZDp9!X%m-N`=IH061`{|lD+LT_p_aSQ7 zMUcNzutAzBZG|p&xiq%cV~{31wyy|!Rwte30Nsr2tb&du1|%|6p!WmWuO=l>#j4Q4 z1d=B=vi-9q8lQFKk-^qWKI4GVCn!+wWgmrFki?}B5QT_6r%LR`b|&zqF!N_9kY`4b zc^48Il{lS!(yI)W^*zJ@Su~^4T-~1_D9HxCJvk*suAiYCSRGc8ovu2@H2+lvqL&eq z78|pNK>8i$Wig3N;TKbdL{cA4vvpx|`9#5S{8&V zDQ)Z-EQmBlxcNe2##4G?5V3Zpu4vxt3JIv)AIxJno!=Sl=s%~Dn$Ubht4IB@(l#un zm;`~vCwa^p2CA~vtRT2`?B}6XLJ*=VCCmnIb%-Hy98udlwJ?FjK!_4mauB8rvB^Xf zqM-0VTaSvqXypW;@ZEeOVLzW~zxo#%-Vm1nQ5Ecv&3azdZzC%*dzYsmnP%kt! z6nd7G>T+`rMVLgGNG(LQJvN^P0lLpR$Jg5oPI#mUIW(NHCW>V=X!jt4ngH<-ll%)J zyrx9hm>(wd!vkaE$Fro5L#3Q+aSdU+A09SjOmL7aHxM8> z{2eVan%Q?N!+*1$ySfrSE0!UiF;2faDv2k~a2_q0)SIhAyPTOBLs}c9JOUTPn|i?d zRedG=Zx;-(#a-q!{UmRuU@&R++z?X|f+{K%;RO?X@M8^;YbKea3@689^WxtS(oPY< z*wJ`X$oQ9QG2|(Sbtfq2=?xM^oTbrfGi-IEN$;~SUZh6iW+_yBEHc+Nf#c#-_4+&o zC;U=bJV&8NJdE6J=P&g3 zb;u^B2N$O~2uswd{kQ7r-zS2kEJ~0@k@OnT2r%g^}zU>V3OMUiKwqml0gX@ZrDX@(_*%2nw5 z^|?KS!UTXa3r5s71R71$zkj?sj%xQqsxSd|fnec0H!%kpD%CJkGPQX(6L-#3F-=gm z(pu>^SslPnfSq+INzWvO`+jD&#L;}b$am^x?^VxWz%tZ9-Xb_h@pD9llvlw+7H ztO9=LO^L_;aAUhTz+uppzZA9cB-jWrn*I43`Q2GT`6p5=EfEwr}U200~l!x->S32FfM7{ zal;6B58E;p#IrTTNUXdkPvgYbU(XQBOw~!f{RSaqX?KNKOXghb|5}4Be!#gOIvzug z?xtvJlqOJz`QqlZglWlf*2C-Sxv0+x9Ii`bfUY?1_2$&;W0aHYt`BwIDLH1GB=gbt zAeXpmlv>2FLwtn)SF@iQMGD$woX~`Htit7xgguEi@ zw}0NaMjfkV`8v={{p6JMP=s1en05T+jdt#Ac+!Pfgu`NS){M`ImVOn{&Tc{QQ9Yme zhM*a2hHlyiphRrj>s>0#qHx0zdycOjIhmUQjnn#Rf-s#x(yCKR$+ zgBZ#_DlvYas4*Uaeke$1H(tS!P;&v4q;18fR#b?Q$^`8ctSi6jc7*SAn&nyEf8Kjv z*_tuyss5{CxfpoTlaCprteUpySgnAA!)&dvZM)!gh~$;iWE9H1w)J`Mc`RG_L6K)& zR({5$w7<>%jGMt>0UEvpB$rkY#zvvA=uE0(q%c63G5A+mZPL#L&%}Tzje#HPsXrGi z3SZNgs_{V6?J`KcI{ndC<$1bOu6w-fi67`x;#Hr&ZJO3-nLAQHe<+m;*tW9-eK$kn zIY!mmU?rPc8dX}~lWn?l6r-FTC+m|?_2lgnbg5ggLL#2Bat=_aJS>+}Xv|H1WqGVt zq>mFFNfBq}`RjHn$%qz&=LG7o`Gg)oe@w3peRy3-43vLw@BHc=MULIwQQZyWGT?_1 zbnlfuPj->uW>P%yXWJ&uLpzucrKM;TYzrT{j3w+ooWrFZd>+zI!fq`^XIhM>gtS;i zHhzWPq|Xs|tuADj3}rf9F&=n09ZtEqPWjPeFjkhzekl?#aiPvLiRrbOIbNqZ5Is9a zbiLqzaJ-&MU5MB?9dM|m&P&^^kAC7mKKe;aO$zp1n25^W)!Q*A#G7n1;k5LV{1^y) zx9^^0duU#4wt3=FKEB^*qTGS(+Mx%${(9Ue1*CVO={D7y+smQRu}(j8e_a?i_6SvS zM|-vXimd7A-uJA|!bCz1w!ObQc@OyI({OvB)|zYdjbK526fUUzM+N%*-c{Ax)H~{c z_i#bqcpb=dG)hP|tb`;>vRkYPDw4Zd3l~lNQ!JZnNaK#qD*R9z^f;;9GsKbhZPpXy zd;BAl$?xMOJSVQ*17@@@3dCY^Ri;yo-$*Cw$n$815Am8y_A3KX(@C{wyL5H{rl#h6SZ zzM!al=31!Y6fWC+n$tKEJCkv-o^%16!`|=3uDcZ6f8T&OVa(Bjqckyk3Ljs*tw}pc ztIAx$iiC<3l?maRn7NhI!TKrMsII22q3AH&_K?b)lLE1dxsMOH5jJn(?*CePN#lHJ zS8Kw*a2z1H?!kM>hO``O44OP-IV3-H&Gk$I5~HyR1~2F!Tlzg`;-WF)1~YBY5r04=14C0{Rjnet`S?9*E;Sh{@EH8XVZgx04??kx_&{P3CX4D*hK(RLU-1=0bdXbTdhNEn zyzAfX4i<08)dOD0lV-!e_4*ut=u@~@q@s9&F~~+qC{*;T&NQ0z4d1#|OUpNd@=bM4 z4BnKtm=OTJrf*jmVx<>~EYtb<{U>G1EEq#&x7Q5CZQFV)EkC|>=xeQLnW7(@y?o&S z9fEthem+pOGJN;)?e$BEzlh42|5a4Z^4}YkGcvIKAuMP42VprQ2NUow!tw>jB^G3l z5w%MM=Z{52q0GZFl!O_ zk)Oypcdycq7F+B6J48_O>_}Rw!V*4w-#q(MM8+V!z-B;(#>!wk-<&!N^`0;ciSjBY8nRVt8`} zOG{isG@4p-KY{W}oN2geQqd-(NcrCNe(WZNPEkz!0b8u9R{=e?6}&IzFd^S##sJGn z0Nh=1G$`s-_12(E0$UJwm~Vys!##b+k`^9*3-}6~`&I0|V}5NC4MU9P2^_nRpQ~oD zyoRFkK_-qPwtgj?mydvD*ik_yAWgp zfoyF6>F1;Fthh?_5jt`=H#USZQL|(OHhi-iv?%^P3bI!Oc{BgQS2pZZw~dN1iUCWA_RsZxkjT1LPwBvL@G z#@daLHbIm0yrpH3PoZDLO+N;4ps_p z2lDDD6wA75f@1}O5;7i3_zZq**}jckfS~uJBf1d}AbY$8<2~-4JV6eD06Y$42ET1< zTo4K!Du867f}mETTzD@Yom3S~d_$|A|KJtCNMH!%OZEkU_54rT85LM)#klOAAW}5( zR}KUa-W%fs0&1@SBwEI-u70DEwg)@3UwrvjL)aS6A0F>@MG73WVr0rvCkZlpfqMfK zNs2rH^i_lK#w%D{VlFLhFSuguy`|zY?yc^@X*aCO0yw{|6|Omr(pgLmH+<^t#P7zM zk-<8plieNdTAyv?>0iI_@^CrZg#PRYidRcVeg~;VlT|s;ys-6kYbic{sD47ZRs8@3< z%USKsUg0R=A$J8I+AJl@9DDLjEF@b{4!6$Kh{M9Pcw6SkpyGJ*2*e=kad4atYsmbzW3CaGXK=;Mj8sprqT${byhp=LFz*H=BRzvM@VbpxuP z-jRF}oiB9x&hdmC8B)O4$>+y=$Pt@^_*q3_$Q-Tw2;!T zpDL^kl=lbh9_|owIM?)2`|aK%e%6Rb?&j&)vb@Db{ogD~-aJpytnkuQA-%{epz6ZC z(ATcEX$LGKw?hW=ophSqlwG_b5AbJRKU1nMQAtlPn~2)`7o zt(W0>-|foAir*V){ZU=(8)V7;3beNPO#{U1L?4wcve~L7#QDxE>m!32i6L%!EM@2h z3$9QcQIS|j+0zXY-RMF{#7frL*$PS4f zZXIR(Sn%&eX)<-}HyG;Z;?|v6K|D!j1;mC}>!;}DnWF!?VE^SPwyo?%BRaLpZM7HYq9_pld4)E3?a{;f+ zx$($`Yi+x5uH;2-OfmI|#>_$U?Wqt?7{Z%p6J`ke8Png26RFrcz7Xe19@oFxBXbaN z@=zH%`u;r^JNzPMHf~mG*)phk{k*U>wdf!wOhS>*T3Qnr|6N8f>SVU*m}|v>8^_U3 z?dQaSzW6Xk7i5d`@=5nX$M`CWThTgtkCjSl_y)tZ6Mv<&dCzOJxCJLQ`o!0c=Q}bp z(v;hCiv#Du8EJHddjZSYWNeVl2J*F3j%6QEJXf|!drlTwyj8AMoJ^B+m_6P)oxHoQ z&1VUpXC`URu%_~vT-yb9?sR-Ra8I|Wkk-3)sc^ix*o;!HBP~>NgC@auhpsl|J+LC4 zqfF-Me=&?#cCEuTfv0rF-9qRf8#*2 zxY63|9Gzmk(zue)`@><{Q^DWL@W4g8HJQtyb(h!~W~Uq_5Qw1b>FIJd(TCrcq0jyo z;Rx%$3P*td&EW_u@DJe#@SlVuZ0rnw3P+|iWvmu~$jvuuuq`A!>aSb-vW_~<60;qS zhG_XSiuZ)O-pxc-i!Q!hAq+$#)!NJW@E-Wwyw!u~!k9gIt;ds#Km__;BE$5nQH3Q^ zVWp2;H-5a;BDw!2jAyMsg~+9wlJ*;t$=7}(`EcehEhKr@$dKn%+(l(84q{_nr!Cqo z1gKfxox9fiO1BY@#_Wwl#fVEv!DWxjroIR&N~X)}4KXG0k0iZlE>wh$5g!_rg=i)c zPiD~#(C2zVs@dQc z$Nee~Eaidl4q(m46=Ns@5g_1Gq7Uva-Z29UNNMC=7$U!I$ zBjKQI+wZc%K_rZE4F_?91_`Q|15lp9A4H=};f;mbkbnDhoJXlZjCfFmdHs6|lMHG0 z04B$NlSpaxk4A{igx0vxVOf}c$R)4XEg|&T7YRr$AyU+?ir3H}iwc;1hsj_Ils}iD za0kLBk--;RZ*c3AW2%dD8uZJSyOj*op*s2yb};QUbh;{#NlWwTkqr;Pb@oQ1(h02U z>7K#G>)}B33~qlxR9gC3wjrI?cKM}~6!UF-J=7R?G&>C>CyDFNZd^GFGiLzJwg;okv#jE-s1&}@qnM86LB>1wtH;;#MIZ*2Jc1rVoUdO zI}P!!;HjFo*=;=s@kQ6?-LGeA>E~Tdc^MTPYVXZ1$gBPI$V;~rOkIU_CgR5{Ea8+m zlyNy=`+{NIZI^%xx%iyBmURx<18|Bk*RChLK9h#_=3^^Aecf!{zk$Ar3{TN%HJ#T& zo(wDv8*xE{E+Wj~$MMboAhx36=2mHTd{}69WXV^br!SJ>Gk7+4ciJz(AxN9G_)})V zITShO`yA_CmaQ_o+THcd{IcsUGB!saQetyq!=}`Yh1JcPy_3g@p)YsiJ6Q&%US%^r zb^JYLV=OcQ=6tC{rvsZp=Gc_|^v?wa>+~l_DNF1=6HIk`Jq2oqv7w24lPe>@&?Q7( zj$kU^!P;~z2N{w3%A3UvRiOWbG#Al6TT|6Mf^Y=!f?&)RGS9MCcC{>3%Lm^U{f&FJyntk?BW2 z)V;xZdz(L89r9u;pPtfbtNi?hZ&$$kW6N3+#QrjT0lz;GFl(FJLn5e$=-E^T9?y5kuO^J=qioOs&nYyuW z`fR8@+ErigiqEEjWeMlIy%+awAJ2WUWzX?uVKIuyBPK?zw%KFKer=hwb)LNaRZ0S= zz7Jh4jPdkRow4+zsmiviB(lnZ#;2Q3D2fn|<3pWK^jvq=jw_0tZP8`_efEhL(Fsji#xHHgS_13KWG z`U=+V4r~zCIEDu#xoa-Q)V)SheQZpDGJJ`Bpg!neU!#tXDBW3%^!ubcy^2-4$sH44 ztfm7!dqw(oqvHi%$yN87qouV~stsYxp5O(TmQE@qk!_Ag@W7Ao!h$&GZ9jr`7&>2P zFdoyS%BkkycASr5kXK8@eld{ag@aBdMdm4qzS%D2XepTK@H|s_u8J+|#cd>{wlZ~d zLO71b%vXzYE;BK`@H{VTvpm#QQ_COGQ8ju%wAv@eR+@|<T1u0E5hDs zI0D`WJ00vFO;bdlA?a>0re{kR9I_aTHxC=6@DuIaOFPuWsl-*XBktaNrXL(`bg9@V zyXV)rHF~ewT@iZ3cO5sj^Q;Z|DW^lzhbe=!2Xf68d&<;awBr9lFciAY`HRW_U+sXi zvH$l@{!G88MEu9(&;E~gQd$4ZBBr!7>=wIUdCruzC2hSB{OqM!VtOoaK4Ql#zrC379+|~ zuLPHNfU$fzTq9r%CQ~J33sZgT)AuRCH=G1o6h7}VIwK_jJp`~uoM#5*-K}t0F;e(!}s4%7-8g zGgp)ds|tO1W)S~?Mt}kdN@A$sEZ9P(ASoLq@h~Y|mAJL0nTO{flZA^bF|Te0q!Nkv zz(ZvsPzy&ce%!>=!S1H%xKuQEqQW^!Z_02-n+ZyvCA1q0jx}W9s)@oi$zzIJJDlvd z4Y52YemxM#lq!gvaA}8DOR$)+1)NVmr1V`f+QJm(`TlS-k2iWI%yIfO8R}3}QUOzB zFVtcB%43C2Bt&gPGzhVaD&Y-PcfaMtf-q$cL}_~31bqoHrPlI{DC0OYBtLOesB4Rb zBzjCKOdMz3d|9kw7SHID2rKBN>h1=C#A%xYi=aL^g5R&@Tw7hL4(dG=|M~U zr4VLQre~#~;aZSGm#}Og6|GI!g0@g8X&Vxm+4I}$acO=wTtss1T=$IlbS?T~IxEeL zFTWjDS~AuEdAOX30{Lc&ZFveb}UpjLXmEY*LT+t%s(HqJYgu9uNMT}`WG>m?` zD5dF9CZ{npWC6r$n&C#lWoJRWWp@=@!^}?LXNWS~pCK{9%I$d8qmI&>D>~oqNq`Jp z7*PmM&Y|1c`p_b}k6x)1(R9RUaCX~1JyBP|R&C@#g3Z&R>eap{CS2=9;RH zG371AFq3q2jtNcA>`C84Lyn>ft(8ju6jM(kNXS7)^w5Zi6!kf}o5K=nDnF-GB;QPy zjE*#D^+}t{QFRe0Cs=;R^u?rPH&bT9CXjD@KQO{rz${9!xTrt*;${-Yu=;Ww8Ut#( z6O%?-#8i6G+1~(JhVs(T-d)VXRC{roteS|^-w4e&pYgSCzsg7Ys$U$5IZ9d!T^pYk zr(XNfqn_Gl;;N&6R?=7-Z<9xr{MA778B;Su9)5fn7@Osjkf<~Tf!}c$sWW^eb;)$Uv5pLpufvUWniJ#{!4ZC$i248TNDJLwhkACj7wndlwLi4&r z;PFIU?kWY-IF`N1+q|aX9 zlzUV(`oA-%WTfjYilD2O-dNyKMph!~3Th$vK6dlG`%TJ9+ zn6s2;+>M?}+V^JqMVg@Y6wRT2v^pKu0i(}ljuM)mbwja9YxNm*$fgrjJ-ZOq9MhE~ zVvU(xurLBS*N%9gL{!JAj&HN(jAw;kw3Tn^sBTVtYTC)*Hu9cHn&RZ}%I>ugsF){j z{er7_@J`8epYz1Bh7x8y?Z}SlSy9;dn%RN?cfT)2Ls@*!jDqky1!pxwP0XdvNgzrg zQHbI5FXa&zzhc&(VSjNwU2ojuT|i2NF)Kw^%iQGYl6XHA>qDE|8g);>4lf?#ba=B@ zYiNuN6J>wL4pMk|9b2Ay154w?euk}Q6Z{@p~BO* zmXuvU)uc7^pmxQ5|0iYEX(~PSOOMKkpZL#J$sYoDTPx+^n#|1~_<2?D7p{gh-bFXw zTsS>U^@Z2LQ|_(Ke9~F_5lMo>w1Ec~O)D}x_{4@9TPe~e_;x$}9yiB(!5w{#CrTWL z=Jgm`m5SYJIi9W_w)Ux#;@>zH?vB3A&AHYjiutD#X`Ozf>`kQLF_OazC%--Z#+{^F zyB(R+Pf~rPX-6-yv7c`0{@!-){u(BFyR=`r(mSLz+?w8DJ+0%+;Nk#iF?myrKAltC zCwi7Oaxg_U0yR1ws{@pyGMjGka#MOicQENe8Fx`>IoZgqOk(%qV0tC=O>yh|8utF8 zZLk}roWp$j7Ol+jDZ@d06)(qf1(`!D&UQyFuEOfi`E*M@?8GvFjegBtY+$x*gR#*?GIgS5=UQR&G@3uYRpjx(l&JYhRKm}b{j@h3DTwiWd6lD61^WWkU*GPp z?k6A3s3V+d5{u#71V-15y(qk3I%&cWlMRza3ZKx|9y*V%8wr2gD$bgL z=h9J=6@6Q35BIGaCvAxds~5il1^RYaVYS`Ne)K2afr~wk zDe{~}+KW9jxdHkehKx-`O`Hw{+Xc@ra$=0J2_-+0%-%KfpU4KjKr*l@oyhO%y9b8QpIo`Sr;GP%a`3jpDo+sWJIh4nYMW)=_I^Qcp zj>Dg3uG}HQIZbQ@ynwNHg}dme6D z-Tx}sC+sI4-6aU&vyvTNPTpkE{?czop5cHRPIly1416^`RS*GMzD_Y#;drS$*7Dt}V{53oyqsQV zKgsW*^Zf`z|6+0VuM$n!8UC9WSB#Ipa|g)&PtsHwnVA0~|58mVd;y5ua-(MLA>mry zUf27+F6p%ZggG0XYoEyb_o(P`oBe0Ce61aUqFEj!rV1@dcTTnte zTJ>^_`YUxB*P#Pn{i?rW3}GnZajz|=aliA>J5ghPmq1~onGS27u=bJ};;U?bCP{YX zSNVi?QlUrzAX+cSTg>(@iU#`cXrN!A3dUsq{%GE`6Sn%IdIQDkv#(~EP6P>h{rN+b zH0WZz^7zr1+S|V;5Fx)-O79(f1&g=jLyYWB)uJB09`U8SSKidn14UD)5>7b71UA5j zUi?$Xo!NI(4Igi4xu{C0zzAVjFJm~E>A7~rxYam`5?`ZUMfhTRjDuVw8EfPVRxBeA z1Y3|cBnO00p@JLv@U^9D9^!ECl%0c7Y(YBH0gu7BK~M%79jtgt}_tV+dAKHx%U<94vqQt z!?Q!|t8<7eCKpB|D&lssjjF;*F^EH*DrkKYN;wr_LVNN2qMf-*fIsY$NSvNtiAHhK zravXhR;XSao1KK*CT#MiNLZVM?k23TOJp|YR*Hs?!g2yB=9WmDL5$PGO9lxSiy2WO zLVWT!`Q&{;rp&4D+jPqNQDzzxkyI=s+cp>#ffi`QahoWq42r%^pG#>a^k*;Kl^Oa{!DuiwZ#(g_H#0YigU)<<(}ffvWdL zLCd>q!q0?Xi(?|Q3#9QS8^;a2`+?kFE0g`oUxhQe@s69nMg&4L+j^hcbn~`DGtf{{ z^7f78vG(h!Q)g30Yl0g(5U7`9Ka)w1j$!PkrJ&KC$(f?QSSFS`-d}VhkHy`Z27x5+8Sz@b-099MH|1-<;oRlJiEp zEI5so(V(TdO3u`UcmJRtHncO9ol;K={LI1~A}gzS<1MDeRg*@3TkDbdqAsh(`6K?; zGyT;4;N+5;?X;I%W_u2YY|)>s_U)VeZlzCg56;sVVVdEOB7H8FbeeHS9F(Dt9rGs7 z8$$78;u__y@IDkO<3X4Hu$U0Y!!hvhiF;;6kLZ-no0?=q4hRLg9-k4Zr}W(QS;D1e ze5OBxCb^&HA!HAiq?(PqFNu=F^WSf|`pAkzKMx@{aUFi`=n>f*^J~BrKo|9KTR)FW z1z!p8+p_k&+0g|lE(n<<@0sedG{^F!(~eT}TN7f9yBQvLNm0`air8N?nM-I#*E1Os zq;MxZ<1+rPtnjzUN)g}q369iS3hgAzbQ|5tze@S}?FjSK>DB6=6dr5irw7b>Ph%;= zCM8ynkHSff07-v-J>!MfwNT?LyMxI7b*lO2ft~$d<<+zQU&yQfpTqbc2k-wFt^Y~3 zJR>9UpByR}cdC+SU{QvZP-0+V9Iaw__z1=irxQY()^El|3~RiOdQOAs&@xf8LI`+-}WCv93tU+ zStuFfl2bL=pfxAWAh`IEz7+T6G{HE<&mnajmz^Z(NLK8<7DWz9PH{Qk9@6sQE6DGB zE0Tm>LSHaOK2=CnTU|OWB2wh4Cb*FA}ZVNP0~%5J3_P82y)ev65JiTs@29BN&00~!$KUvh| zVmCkUSsFsyyS!_fPq!03d_AN3KKuH|)z8+wU?nn&syr>Um}{B+!sXXRXI@Hb)J7v^ zjwatpbRg8xFN=b4zi_1I(+$MzyVp<_?njNd*FJ9+5!|sbN0GrlFBmwT^zobqgj`g@ z$+C{qOPI#C663zb-w{+GN2!|RR=b#1(wf1M6-8Rtg*MHKCzFRSR7-WZK->$7uGX+U^$0qN z%<w?+h0Or@9{xNN;)rfNuS{$&KrO6P2(?6LN zMl6}|ImXYiqP%38cM;!hlULruZui)p7mw4q)vy&RjgJ*W=i47=R=AeaZThWb5%FPk zjOHonZV@JNoFVjmz<<g?sAdh!iW;j!WJ_!Ru6h4|@zzzuird2$+>+ne(#jbv(Cc z6js9A>LVLeYgXZ7;j}MU zt!n_)XDi$nE#f5~#6)%VOcdUd>brWvl2FHa(e;y5eDbl!p693(%pLXOgL*jd$4g9DP5YpnBZ{R zU$nyjKQLX%Kw}@!a5AL}u>Q0Jnd+qi5nZaeKx{b*FvIk%1 z9M%&Ojn^94)pY>es?;EZ_<&5|zzE za`l!F7j4&iHXd}}()bLHZY!JFVLpg_`jpUdL|4E=7iuuj>v^!^uf8G?WSHeoITEYT zG$F+F`YrK{q_duDZoJ%wcW(ENkpZbAQ7RB}%I2}{uU<;l>L9CE5NNwl5>mndb==;! zi&B0LZ6A!Vd4^5HAJ+DX^e%)Ld6Q&Se;u}X*7Zolj~KaAcy5rQtF4sWB6^Y_Kuoj% zMq2U3@H;zPZ&6uEc8IU~t6A(~ity%5i3vHFv*yq>$?DY8NNsHt(;p-b+cX@)h>@X7 z#`1|NYv*24N--GI+W?Z&t!sQ_v7j_op+b`t7;K;tTVBG65wQF5hQXP=F=nh@*d6`Q zx7MbC^zdQk53S@;27_&z9mXH7;m2XOIHse_7;3&iN2hyN0dU1u)uV#4F`-39<@`u7 z-AF#Ck=7gN`z--0R7=e&6-u8+FM3y9;yT)9auj+@fN+#+) z6+hP#NIo%+A`2#~7sqat9a`hu!${l03|~9pdT-Bvdw6}-F0sHc7DSsokYTj?YNFAmw3;-o zH@a_ft{?H}CK&;)H~UNV>7Z%@)r>bXhsG~MKEwHZ*6V%+i%3q~O;{7eHj)^DW@tJ6 zEvX#JuxEJge4%ULEy3`IrQ@|*Vja+7EkhYPZ{yHNHTPr_+NaazVhuv|<;j#NC!Sws z7+t*7axOK&QRy+E>nY~%+y$MQj-hyUZGSZEHq@E2-Dr$Aqk8(XMG)mU@BU>e`erAP@EWf&fCp=eOA|W<_-ne-kX_4gd(_g3_ zX9~?@+3cWMMP}+dQmC?Msb&B2mmD9)8E7?so^jS@(J8T1d|{oBx@KeqXR>jM=fkV( zXf_<~{ZP<8+Qd2`5 zgeW-5EXN$atI}_*qPExe9S(&+sN~gC9E5Dd=x)|?(q7o++!7&uU%%? zb5ECd2x=&$r*y4t7oS(xijMzlUrn*U1CoyCSCOen@^ec7XQzlE-+c9U zK+#@I-1Y8DwOSwKqAIv*ST`<@#YwQHEhvIGsEG(aT%64)e5D_dFiQQtAVS}E8L z4(Jq;#zaXq)nqB$NqGU{Cub)bb-_t$l*wweC^cFL#o|V>Ce(`-X9@ff$Q$^>?>KFp zz922yXJ&R1e*c*YTV&7~R3&V)<@`^rH)IF6-Jn!ZG7&{eMgPm?#F#`?SGV)Etp&Hy z(vlxbSb@+a{cEe3g+XYJ^QI)HC@V&L6um7l6(Vo37cg~@Ua!2hn2l=Q!H#xU(LdpT z-{H3>8d@+r@Jknh7U8xbzEt;Y+W*#MyeVBLO5lyIRMvp^kk4va)w>oBD z*H5fyFc0UY&Cg-uwimOwD|5M=MPJWA|+5q<+ADA#J ze7Kc?zk=ncfW6@4*A!FwYlJb?lNjS(h>_Xa4ixo#iduL<%C2GE;2Ba=&sUc-#WP&7 zvae$`gCZ$e-%ro*+NqL!2T2Fpj}LR}L1otdXV>z!ruP^lKV8Dy`UkDy-iyn{!?iF` z=HDTq-6PB{*AJbieV_1`hy+?CyJ~0f>7CfZ<6B~CSLS#~)l>J(w0TAQ+pN)c#9|cZ zmArs_W(C@)`LwLZy1`Y(Q;Qt}!|2`s3mHd}P$w$YaZzh@($WguV^N7KN6+kKp&Bvg zdN8U*>O1b`9MsaJ^Q+<#hZRzF{4Zwwf0c^D&i?;r#(!er_fK+9SQ!37bs;qRZFmd= zTGz@I+Ro5ir@>43@|F_Op917#y)8#lAkJ*+>i753-xu6oW<`#@L4bp6&TDn6&$~^8 zvv!3_gaCzl_Uk=r0WBYc5W*;h?p@ZCwav%lTmu4<&OTh9lLPG1%sdvBuqsc#mW zo+Sd!m#L8&rrX6lV#wsXv`~?K@oMBgWryxs*yFkR>*`056`pSSl*u_W^?u?kL%9#u zsgq?@*cK^lp2z~#B2iuLl)v)9K#x0NjkuLv)FC*I8W1SWP-(Q-_p-C1x3;?AsHRMk ztTyrV>i$YWs%jArx6-+4YJL6@X>TiLFZO<*S2nV#<>nh4e4|VCtQa>Z7dwXx73ZQ= zj5kXM1!YuG-kTLHcm*YKlN)?WZd1Tap8!{H);=R!cI!3bl^$^{g*MU!Eyc!!cQ3v4 z(O_}=r8x&ZlYHa-=}#%SlGkq3P>A!rF7R1z?8^$I_Fc{iqfpuA*xta_JM`9uJGhiR2=`sPrufktQhVuA}Ci$-bJ_p1956;8! zkElEg!=IZSYiJ{4I|G`~Pj`Q|{s>zuoOuQa9|SnzS@rQ3it;$Z^Jlj#g1xEc2bZ*% zEWwc&V-EC=qQzm@gA7RJnaU<1Q9uR+3R0raoO3I~YU0VoY4eCO!It_-%PwpoU&D^j zkTImr(aypn_(U@e3M+|Ja#GWFjI{jSTDHThvfQo+f4m^3TYp*JLxJ|^n&$XdM2&;# zzq|8u{3F`Nz{K(=FQlkSDG{?Fx13X72NW<>dFrozCQT|-J|fHhV1(4t%giH+6Pg{% z0(Ixn5@%i>2s)?e7jem*T3X4{x^rd8fxFAK=gqo`+CSdCJsN9Fqca0$EX3uW54>wh z-@1Zc0mgsDRJiDa|cej+bk<)5s56i z7xWyQB=+h;<4+QEqW+>j3U+d2wVR=S&fgGO%#$M01S86yA3K8&35^{K-^3m)|=H%CVI@_lS z>_=y7g7JYgpboh^v(1QTW&b~T2R z7mdPEl?RiPQ8mWMcG=w~^rIGiNbtuqs>(eFI=^_N&yW^9KB>g^F4CDN#S0v{BInqU zKHo&6xXW$u8u;ptsOd zzDZ^MpoAMMXG~*S+e@qxpeaezD$mhP)^>ndr$wMxG|iB5={jn#4Dk-(MX%$_*$-vi zg38W}gWdHtR86EYy>sWTSi`}GGWso!wTCl{<@QD_#vvW|Z|%{SnvVbxb6;7?n-1%% z5)N++$O?Fb^L*Nn$)I|}dg@8fxLyXo+fpgX@i)W0R6It2qXem}^9s8*+f3u81irpxTclk zdi^x92Tf(p$K|`qTcPKcuhI$y){yE+qvVx;(XA~|J35gvH$U_HjF&}(8iAorh6mA6 zW>x&-l+7|4@{KAn-9E($0>#MBzWvRFT_{e-lAOjxqKLSLjTj@uSN?7<1{z!HhU-JO zA$0XO{Fvm9RHOa}b?+D?`?jV1uCi_0wry*b%~iIoEZbaV+qPEOwpQ8pJ?HI+j(*SC z-M#mX#=RdiGBPqF|1p2hn9noDoI*H+OSWUmTc1&_D{oTvSv>iL9bo5CXe~;lq9=@#gNRn&j2>9Qz3hScrYG`cPEAMXPbqeP!bfK{c#TLgk)S z3F!O&y2fI(3S0LM?3Vp`(fZhNyU0mbeaI9goz5`dz#xhQeAKz0TEC`U1>^NcDs$1t z?kX%A?OMZXe%d_NkiK$fGBdSeKn6Qc8-uE`QU`91GwiO{Q1=KEgH`82(11vEY0$nl zz8^k7=0_=X_luCp_juneAQWTY-D?6dxWLzwnGN@qJ4*pqPBd;_=U zYBCu15IuU+`V~q#2%^f%6uYZbjI#LXL7rMp5ouWRrm>k>HG4WMsN9t>m^-O4)qFM{ z=R)ioMAC>0QXDgJ*G5$w5d!5W2nR@w>0W;rQEd`8G5qTnyCR!t42rOEl|b;z3*GB6J^%M^q?M(lpHVafikK>8Lbuekr(kLl0rFzIR}R!;R8eo8^M zFZKJ`8lZ1VeRk@+*n*G3bYl-H(XVkH*l92zb*bAWi4gqz=a{dc3dqw%VU8Kle3AJv zx)F9@rH8rZO8e|>-0uMYmU*L$TzU8>RuABTf~O4{ zrglsdme*YNTbNKwZeZADO%41tO5`|4c1F|AgByT3j z!#oZn>xb*)S8#JmgZWanRUmnkjS5U+f02o#VmW4N<9IPghO$)k2AzY&aJ{b5QW~T0 z-*>`iLgP55hRK<%-Vk#e>eRZkqk}%*x@(7*M)O@9e+m`c(*$H;oEyeg?+!lrcr*r< zF>`R8h*%P4m{@m_n{h;#i;`a(v?E@^U8Ol^XoSjMmnRULfSiO;M+x=A$Hh5SUJHen zjvfvMz;N7K?s+YjL1?ZZ%m|5xmWCkPu(atbaBQxRLE>rKa8;FHD${(YVfs>%HC6wa zK$@%M0Y?PpFvgv{oEgl@TM+|jw7WDN-0Tu1Wngf~HgI8)Jqe0r%ScSSw0G$z%%DU; z^~wBB)9lmPG*o030?kVD}(VoX+*I8~S|y_O>Oor6F>&NXT~_fq<&gA1`8TJ$BE3 z`jv>T3PB&BBA2V)voTNp2=F?WIsZwVizb`9ved-0B9s^ccG*(-11nel1Tp>Kv36Dq zkik)4a%b?hEo3fm@S&Mpre+OF@(fo}hz}R&&imD+Q>TyleKPh1d~|b}=$*E0#(m~r3R|<~R`*=DaKdFC(?v*}wHlv#j96}F;g}s)ySzMDJS1x9 zk59Zkbth^t2vzgv3wlJ~+qvKN&-I&Aq9Xo4asN`Zz{UQ*uDE|HLHPUSN&l$0$?Cc) z`|PMbN9r4+FpPzKrjyS}If05nKpd<$ zr=6y{d^ywRKm}B^CXNr1OkC_eoUZ3be`k<}h1I5+!Tx&!?Wr zC_CtTXSLi0V9Wd@K#*n)-X7zlS_ebRcFuab8b6HtRJ@V)N`m)kEj_aeRU2G4ZvJxc z05AwxR+yi#F+Vz!eLppRekXsh0j0oGh#J3iC0~}vLJGh@3x~IS5omS|_(&#hvB1Xl* zj!Gxv4)~VCACEQ@fJx<|2UxsQM9Z+iKg>aiR!W%#AA=uea4j2D>=e;O_c(b+NE+cX zI17)lG3Qfw)}%+cYnZy!uhj=Q2t!=E(FH0H9sL2mWErB#bRq8iH8y=fZ=!J0!J@}- z-#YW?d^GgFUec@gQ3iIqSf=Kwoa3xqjsVG24&Q2Sr1*D=b6(KtEVvH{B|j8ZZR*L- zQw42wbZBJZ$vWxX-sJ72l=bHF){e1iL-75ts-=`mR6#yd*F>iWr8kq>Cwyd0J@jH6 zn3u;H9g5KEK9q2qp?=u2WVP6d;CB0ocxj4)V#3DfZ7&Fj4{>SiUt)~!OnRtbr`xeb%xe9spYweT`J@{ecG}^@Ty0%chCnY=CtN;x`mg;G19g; zwuGCC6@a96pcAQ@u}~?i<6|2-%hEczh$62Kt^Q2n0kSsoQ9Cfq`0kM#e9(5L!;`af z55IW$Ue7EDSP@c_eD^ca6oZXD-7b`$6FIrLz&|uAV7PCmqhj3UUHRrp24}j`3H#K; z)8>n|$Hy@TNxJs5jm*RgR(%=Vv@K;=e;h&1y@c6VIX2msrr$J=+n`vya+9=e@jkq> zHsblKkvbVBt*G4KeHEE<582;d8%T&*{;2N4?LY*l#&}Qmju$b0b+v{c-eZa^8YW07 z>v!Q565EgL6kz%6%8InRu2AHGyyg`bMpjL%`u)xw00qua?B@Y)@4|9)w7&ZR@l;<0 z%v6Jgy0fzD+T+VHKyR-BXw|jw3Nmu|Xb*fHi@{FE9=kFJ?|_S(t;8R$#QflA{7k~M zQ#2#Kdun!{?BO@$4rbxd=ux18$^5Vci|Hyh#74F{Z~(QK@t%QfJ+2DbFPbRb6hJ4x zfiGEUl5ja+Vi^DlI;auH)Lq*$)QD;(5701BxhJLhY*AT|U0=C*gbgo=PyB`C=K7s6 z;3ZyXOCA_}z!!B&dPjkoThs+&rhk;ULggZkjGRdwRpt$GtY|$M7O&rOMYwjG$3L2@ zwxx!#F36H#-L%sR%;1r{#$J`kMYp7h5hR`sRvXrsldk0=6I!;LldpMc==GDTmX|kk zexOmyF-+=Qg|}HZ((;@Qabh7#WE29}1ci$xsjgp~69zC%Z@|u$45_G>aKUU6U@%`nyH60(xYtnJj3pF%t z4I+1rs7u#SRC{8<(80T3kJr?+{j+rp7a$Sl^Y_4HpFYGFkX|4n!XIeiUozdfIR8f+ zPR>82ckF-UaPlDpGGYcleMYSN=RKz&0MH6Dp@!S*SR1jE)ab6iikN=ewr}t~83H#- z6K;b)rLZN~#GnQHcM728fJ85Ozt6J zhkG-AN?a3=R10S;no7IW@z+S5>ATfbvY|K^b`rFAlG;6ceTUcGDE+j^`q@rOi;$4L ziebRU`2Gj~{9o~wIT-&7yk$nhf4KwT&z?8^f3-FI%VFUE`j9vn|BMaI#l-f{4=Gu7 z-F994?`;henRuf4?hW)FR-o&OGuW17En>T=Xl>uw3EL(vm2F=i_!^RErCt3&!6m0- z%zkIFu#DFPg$cilu|`v+E2_cu6Aq4!@5jCg@uq`PkvX8smgbXoLhS{q&UwzX>_#UV zEImD1yO+!po_Kk=idmrUZQjWT#+k7!R8z+M=6o2Aq>+zr&o@Wky?}G|*?=8(bBYjI zL%jylkxo2`VsE1e-aqFqMxt}J$+k$2C&i<}%%?5N8``)0u)PD5QjQ>&XXZA+BC~)k z&wTeJqI#pnK19qCAmdOnODd36Pp*9V_?Q5yLc4IW(x3V&Xck8YAU4@#&#~F4(jiV# z3V&B<&sSKEzG-q^EKT@IRJfwFD`VoeOU9YgYaaV?4;E$J=urBWR7jK@SUJJ@5tqUc z*R9TdjGCsxY6|9098Scim}TU%CXQJGd#GN+45U%)B&F6uo_G{Ntj{YZ(3LbbO47(N zWYSFeBrRQE1*CEr@L`5WJRtqEfIDa=@l=$7uRq=Go)N9hh%&`8R!nO=aD@Z%`s&N1 zNX&}xRZXkPl3@s_$sQRI1J>u}lW$rqZxV?FTiNR@HS{3?TksrVimNYDigOl@ad-v_ z*2<)!v{SkFt0{SaKB&jQu-(Z1!0pwp*o`cE z{S=rM2)Nv8{Zf*QOwk&)WKkiWXNMwLuD01UdEqt|P%XM@FjIsKHkYL|(Ch(z-G&{y z4~6terX552Q^{@=RLd?$GM0_Y?lD7YZjOz8SPX@(llmG8ztDg+D)n1sVIRMm(GiAg zQI)naIL=n-@&%uB{BJcNv5eYcM>8+w@8lZ}pxF9GpiStv=q18WT1IY~pEnb$Fp!kWJPb^~8cm+QqZ?S#`)`7lBXat z(0QG%$XvfhnWUCBhG)6}P_}JEWC;)BiRB(`-^SMd_?e?_tlkp9&cgsuSRI;}GHHc+ zrg;z{C~-yyZ_teJf&_BnZ`*|RC3r^|b+<+SCpK{~GW{hsG5;5`iHVT)KZO*7xFI1E z%YTe3&VRtwpUP|gJ_7TPxT;cLciiJd^f{twcMmA*=P-~=tKzjr{$&;^RS!~@v9>3+ z5@^1Z!kZvVuir!Wg3L&sZf%p`7`3^1%J1{qKdttS{}Y@MGrfn=;-xxPp?tihV#(m( zl@a@AyNDzq=F_Iq4ONK8C-X7FO$37g!sh&5qK8MfxyL*aC=l(E``Gb4D0+O;*#PnR z6r?Ee1o9Z$tgL;m^nli{;N!y`C&2*6U#yYo#5y9fM9D@ZQVELB#y2jm9$vfsS$%3I zV>(8!z*haFfG}!E0?2JeW9v_WZ=DU$*h4fqgD$xzV* zYOx+nmaT=*Iw*))N5+{vrsrIj*P%On0s>v>g$7S&k$86m?r^4VoeI&uI!}@Uwq2`X zueLYR#N&ww>OM}=u`p-;dh#!MNVtv#7nR#;^yG(k0E4ZEkm@sSpZQN3-D>H0S6-~wrFvTU3_ zv2Dtm!+~|-#6*Si%q5+ot7d+Y$`=BCCIh8y(00p_OHi?$F;=sN?|1&ZPLU85SL7{9IKUSTrhy4&g;FS6 z0EQ}X>?kA#NVr6IZ*B$17MtjTGw~s=C$wWG{Qd^OC;SYV9IjDBCPgk2sun9gp;=H0 z#oD4V#rcK8!gQAPOThYLO#`99Bgg3w>`c25y$V|b4`Q-ag*8bvf{g!`}cEaS}C*Xv)L6)UWT#F$~IqAr;YYz*Gvq$~XaSV-)LF zNX8cTOVZe!ZS=6DGdzPl7^Cc!ha*8g`HnRn>53YO?l%rFAR431$3N!;yPH3>{?hs+Z0O3XG~k7$X}9S zZEjZs442Je`l3E&nq$KQe^^Y6SG4zdQ)Ssh(Or(4;|t0G&+_G9H~64nOF41Gq7oaq zifgR`J(=5k6JV;=B-t^TYk<%~o(w&8o%L1!3dI_9*(PkeWi_3|QylQv)VBN(qx*a( z9>mYwQxQ<(c}Rb6G-#>IJsrf2>mDmBz$u0)KbyR0sO>9(L{diM!#i55vlIsN>@+yU zVn-L;LcB=%LT0mnRAI)ZCJ$2rLeMjD4}uvz%+s(LP!qh)BuU4IoW&w7lkcEk{is5L z`Kq?ebu%K)c0IYDC*TTEB7#dSCv#yk`&#k9V5tI1{RdoU`Ab}9{cq*^Ul>vRHyr;{ z=@TR4KX=n!sL464vmX^nGOd^M&y?sBq6X(vQCvIY$P%;LUEZ(#eqXEj@De! z3;HM}%p1dF#d3*U8*Z;}hNAuSBm#ZL=qC+S0@hrG(TJew2=xu-G(`y;Awlmo$F4;x zq{0b8uNAi!Y`rjs!5?XD0fTtHtc5T%w;>?KFAC#%D;n>FaTPMMIMB{Nli zZ#Y%P`+weev|YscL>IyAw~SVmpM$D&q#*WJUFuPREH4b8pfOO<1o0;67Evo}@@{yw%7bAt(8Oxc)InrMSVgawuO#$+P`U+7dIjca@n<$M+t##lR#dt;#><=P&vur(!v z9AV(oy?f!*=j?ibCFrKX-h{+2@W-r~GCj^)P2o}4v*j5F{KZr#b}#fBhEC@lxjMw& z&*X_D&FAFKJ~q9fzJJI%k+6TFZxeFe6$>V8B)rEt zEM)08&m+zDj;Bj;UtyIR zvSW2rWb3Y$vhWngLW)a~%vPF>^MJwdB!`CD*>C+AYbV`9b`k$r(U`TMKE*uB!7`uL zsqQg2qgER!g9q2$Y-uLhV$*1cS#$m$%kEd2`p!=GyWM^o(YRJ3i5KP7&I1n2X%%nk z9J*c?3l}Vaq4yL?{)w;W;~$WheAJBrfM0$Rq@oY zalUBR=wjO5MfL=*FX0_H_%OXH$=N?zoD`)s*VwLPYkZ9AX+P0KSBqn{muGP7s7u0> ztP6#+W9%$KRK0fBjhx(Xb~2;e7;vusb~ZCMCE*s=?Z-J#N|)(cN8m7NXBp14Vz{`y zH?y^Da8eI(_A-SuN)aa_-DiTCcjoYcupdtz!Z$b_Vw;vJD?Qa?BchxjEbO4a#Fq^` ziEJrwM{bY`OqCD@5YbJlbqRQV0THnIr2YZ?*!~jy*#C!%+W&xgf5!i3WBY@x_GXft z-8v&|$kiuWCm9I2gkvY`s{BO?Fkj&>?x&?lOBw*XrsF+Q<;Oz-Erafyk)Zzr^9neu zCaHe6ccsm+|K5-Rccj~<8HOr*8*KnnDf_c2yFgGmP=<=K?N#{|7Fd6=M}Y9Kyav1+?XsiQTRpG)ydy)MB~9bB@!)|YP^BzgoKbu# z)1#$6nK@9j^VZlKBH+?xt5TineHBPq6k^y4g_ifsdv;{Av2e!WY&Op9KK~oJd}07>l&K*+;h>{6f`<+`64~6sef-I9R#9J|7G&i+ikZ!a*bfw&&NFliNpPn;8T-g44sq^@+@?~Wt3yIyJ*votNE8ol{4i^tMV#%YUm%UYmF{Cc^Dd2% z2Mmy!2rUXJ=M}A&f&02Pedkznt^_1YMUEiHv6PfUb4-$3+Q^l?@@`v=J#;r|Q$wo~ z_`hh$SNE}5o%>~SR+MzQ1C6Ga821i_nWCfveHQhi6SXv4dtWsgL#gm zku>oYKt`)pJc66Pi`Gx)9^-P*^jggn1Mg;0rD?w=qe9A%1)dVj(oT9AgUzCN(Nbmx z*6#i;jl}jDz%6y;wmr;yUeid~S?tKZsu@OMrW)^{|60C#exTNq}-NkcGN&@*Meq{xG1Hgp?p zRaai=B?hC3b|1@=W$kI74(D6~&rDcg9c=kP^l|D>cV_cua)$6ZEJ*Su1)4b`iIq7@ zXo3?-oV3@BCM9Z{!$wg?(}4~qY(A8CEs~H+C=zx&LM^Ii4&gRlqQ8SvR%krN3p{>= zwc1W95mmK=HR>c&+mHbKi|p3Z1&D_sDEJ4hJ2Y2xhT>LV$oPq(3g!9CQBK}8T$|lF zlH&+9D~fpjX4_g=*G3q47vLD7Tl5ACP%>~2yZWnk(c)B~bOri)-+?Pb=Hd%jVPCED z*KolpE^I;H{OGix@Pp>hTbAuLz8u`gcbtM|%5sJR`S%_c zhXjQ^Z%;Xoq=Xoc6W`gl)i(&r`aaY@ShRo1Q)XiP?~phaLiYa(1BdnhK8%Ee>Cd%2 zv$Fp|2!3Vvx5EG9vM2C3l~j=SZySKYUPkN47MEY#46aY3y}gpo6Dj%M!yPj}AG{>S zQfSvTBa35b@nhYtw*FQu!2$o?*YC||`XF8Hee&*H_2d0y4;%hD-M_xlVTuJqZp>iY zP1TGEy3h2p|9Ke4m<^Vg!MuCc@`*>S;Mw5e=+NNaY9i2|ZW+?Zo5yf`0spMQ)bT|@ zPrdTjS=IAca~rK@6_`prb0C?ATB)k@{yrC4ZNHP^n9;tkU-^kH6%9G7411?H`h8)m zp4d&WRglDOyhAp$Yty?w=R0|fjH+bUlzM7Q1x-tRveZ6#uW>J3W{?E(U>mY6X61Co>0QSqC#I^dq(J@sDcC znh}GwfvGxFdBp|attHAKJ2i@LxeZ$KqY2qgpHpzs3{fXbN8b5@k}UK5$iq_asKrKm+Ngi&zt zr%lW$#%gZU?3eRk8}p@uX;XY@r+xd5Ji~Y0hk-q;3COHl%63_e_u>Mil^(PQCEij& zzj6Er*Ja98f9dv?RV!eq5qTRkPr8Su$w)<@a|~t>sEUYZg*1UgI~%7%X_F+)swdU- z>8rj55506TU|HDARAn664H(Xp1u;U*nq2WDTZ6Mrh=G^#%7&!M9ZM@BQ9&pMcj9QU zRvRdBCF!tgBzn(*BIOu%Rb5mMi%QGL7+d|I<8X-_LU*(Ry} zps9yipZz-ht!a$7AkoE`VhE{=_lKBs&o7@Td`{`7(Avu@v4@)=!LzB~kv&^=01u#W z>*LEIJiZX7{oA(YaIfkax3u!f+%RGFy&V1nHdT|%%zC7>5ci9hP+B5iS>C@DlT~c} z5_IwEA4T)KaPpluIgi&F$O;k6e)JwGZFv>|8nlZ}(Pd4)Q144i-9DAt=LJYIQ1d91 z?IqmP+usfDo*;o;?6FlX-6RzoionkJ&kRdeVP?@$GkwRpkoh!JoS31<<-S-%&If3o z`i?y8ItUl`wR;lsCMTq)m=LJwY|g~Aa&ln?*;W}i=Yl0V$KC|o#X4N&Kc^mF=!ZjL z)>G)@A8TD-TPe|)^R_VNgR~`{JcT(R!lK4ds@ZqGoN>VlP)c2gsT7+a{mRLpIJQNU znIOpp*OhY$(Ww<9F{+~zao6s3a(WkxVNP^TVdz;Vv~Nw{TvAPX#7kBn7AhioW?Y>w zsIf;Bv*6|Z%Pz{@moeS8w^TVROPRRjlix*0H2FS_9uTT~x_#?-rA!FZ2>~oEsrh!k zGu_R}Ycn?CrEk;Q-=8*c*mi3TXK}H)&c?g@S@q~w?Zr7ZME3Xl*0z%#+*)xgMhd-t z@CyxbnQn}uj>%Zc^uvr<+;^V|*w05Jd36-+QD?Aa=L=T1v2H`nT+)X2&Mu}W$Ywu# zNnU*+w{LH^3!BsSTWYxb5RZR&I~2s6sR`iiu4_+R-h!QZxmEEmgzC9g{AsBix4cAj zGVco*F%b^EJJdJo=AQ13Z&dL~NyRMLq{@UwZqt`PyRNkvz7c$ZGQt=#12`{Ue#Z8k z3-Et!!4!mZ08S2p1ymq^u-GYOlWsg@{P1qS?$W%o*w5-GwH{}mes*SBU$0Xr`H2w! zAxo4d*Hy~h7K%jOowXlJ$|b?~Xpn;!LnSJts9*RanuI@6%dsI2R?m}YHIw!fgzwd5 z6Xy$E2(i~Q@+M>IN3Fbdu(!rYP$sV&*ZHloNPH^KCv-xLFx>9sE0oxWv~!&O#}f*N zo)YP$RF(6$4QB?K;x=w4?W1%d8ti6bUsN3njjF9g7gImF;0ZWiKaKcYgaU)W>dM4E zFVJgL*Hwd7I?`KA^2=gcl=1aZGj({eQ1n}=!CI2vQ-9PUd89Zv&+Ns2xVd}&wr2^B zR6W#~v!iUkrWPTp1BI)iga>`Ghf+363Io#&e3LpLSqfFw=wM2ZgyTlDHy{g9!kTgZ z9*7{s?1%$gP^rI0vC3Fyk{F1%7;z#OUo zj|xdvFB+vA2j|Z5=&Rn))Uhk=^;4Tp@8#j$rZ0(+VOjI%O^bHAU(eFZl3);j?Yq;5 zN1OGXkx8B`)UOc@SUfVZ6v(JrGShLER)Sot-Weltu8kLwR+x~uofi1ZZCI(^+FPti zViZO+?U*@U5a9}*IZ)q~QMX#i8;P_Dl2_Wm!Xo5o!-UUoF&KM*d1o#@V3%9{f%R_wEl8x!e|`~=Cs76{sF-QvyqPZ(;qZd40c{|O@qgxd5Gq*N1 zt~nggF5;&MmN6UR20UT6dj4Y4OOmeqOrRDsT$Xw@1(&s|lxvKZYI~;FOP8j<+-`O4 zr5=>Lmp8{oJLr>63F$YnejsM4^AQqG7c@Lzvdm=$FysiV@p8eV#a?Ebv^sEZj{2JE zCy{{}Cxup^N>_9#kct6`nLuMg#u_yQjI^ z1RBK#!S{XCw$Ky#SMQD?cwJ=dN)1ir*|nRX!s!0z*%(l@pk^wY=`d)QP@ocT&I})c z(B(;L_z20!RycITE3?s<(8>7go+lhw;S35R8Neb|!H@Q_+jRdy%8#`S1A(JxoJkil zR}=9eDci-tv2l>4N5sd^^$q71ip$5`$@6c^O^J%A;OF~zk76zm}gLwwOXDz4V~-Y4Xr@b8M{RQsuvoa zHA{dTF{xMHR9f;@E&$4wO^p^?WE)g6AUuM8xw%S&nmGdN#WE}@qqtAJ9YPK^gw5Yu z(mIWa@%=V4pcvKu6n3eS=! zm7Gw24#*VH`_ zwHOCg*vpQKS*YXT#BkF|koj=mQLzE9#U3Cqf6ZQ$G^>7B%V2`gvPRx8N6f12^de-i zUQoTD?YFMP!}nh8sm7%Xej~leGi(LW-^yB_SD-K;98NYDx_%kO{bt~8==jw(m4=_J zg);V&X!AIST>Gi2G8&FUTX*cV>hL^M`3dd(x$8vd_IriLL5n%9= z%G$}^92v;zQc4*_kqnjM4MY|%aL8&@2b=KJ|J~KFj#NlBp>F@P?_dx2cN1Yy~!Re5FmSbDOJssi55v+S(R9|FFAy@jB;6tUVfVt`WX4R|^EX%6W z^@b!OH0uewT)<;+oik|wCEhSrKTf47y}S@AzzedtY_w1W#p@zb%`4b&6)$pW#vF_5 zS!+q*^Q{dE(IwVfl?&>d7B??=bA! zEV>EnDd!;xMO1vUqb-vy&TSp)n6f12DF>!OeU6Nb5jdT1Ql?5AV7^GK54FULu-_cI zsakJ?WXZogqp9~w#7-dU98R*Sd@FXJ&PaVO|Lr?NNP*drKN`+eVMTrnMTsH{oRP>Z z+V#mE0uSaE2dw4|wO?+8HS+prq);Ofc% z$!M_w*`pq`*7p_=j?)x(cA_pfyFNj9YwKVQmdJrN%j<^W-IEa}HqBYPO4>q0wOn<{ zBQkl)rtF2Q;n|U~&LIvV64DwQdl564Vzv}4rJ^PH6^51}JZU_l-u;c#f*L!>-#pf= z!aO_I39a5_Ck^8VB{rKoHh1~7>+TzP5yE|1txN&LqPGV)xMi@^uvapQsP)zZcea{w zC#2mgDvRx2xfT4y=jV^_wZq*!OIGIfhj4CWPEFHoAjb=dM4ETOSqS?4)1Sa*R6iF? z{2Kl1Tjrk1BhitG3w4RwyX~F8?A1cp9kyl@3r=xUZ*YK}P`CW^-<$rGy~s7Kcqa?ise!$r@yo z;NR{h0o^LNgQ!LUD2eN$ygm^jEZW?+DKvNi4EwZXYQWy6S}eNE=QCpB-0D%u_rs3} z)P0b=jiEXCd$!s%Dd6^8I)#vJOV)ozPocDYD@19J-oS}%U_zg$`>^1?`q+HK$m#L+ z{sVRSOL-m>`~Q~N`R{HA*_i%eJNRdEK90YA>JM6K<($?S5xeeaTpa_ZQ1@#L`sw5> z7%WQUe$inVGK4cXThoR&zdZOP1Y9qsn_oy7P0CBoAdU`?W%}m90i^69u3>eSeG7R zxVDg4F;{88yk$moS7xL%r8K=V`T?m)D=iqp?ZavWX$K#Z< zg~-!xwC-Soz^&G#+hFygb2cBNDXJcW8HG74Z_pcEX)EDLv{(wV#hT(AAH*RK0SS`f zle0Z(rfqA;$OU?K?=G;C=_xYpcy3^~1AlN6$VZ-vbm$0K)3`_w3$R+jru4+hOxZ2h z8lzZm$L%b)kqNVvuCORE>Z2ILgX*p^7DV`Q3Kg09Wd}}2T9G}3jgGPumIUn_Qw~y> zFgEat*pN=(JkqPHDb;jKCoycLB6YEoG8e6&|9oN$3?pi|6&F%IpyLXFNi6{2$kr$e zazwdR!fAqpk+7RP>GHfRy-UM@gHk?uv<0s&Rg{(4;wsa?YAwc?1BQErOK~^*gX()I z2;C}q%Ws#FXQF2$k`WH53vDgQFb;=RDcTBXni#FM;k3W+?ryp#HF*k$$D~xkz_&{c zlqJ~62a;a84!8i-6%AiI=h}(tQbYrq4Ps3@P>+A_VKC57;nD;Utgr7&GMwSN_1ukj zQ*IbsJ9`yoozMO-&NwmuzSKsUV`WpkPl^pC@sOka+eyOpNAq%vgUXAvooo79`_y{? z6tlzU`RjRP6*LY)6Q8PxM)|3Lx0#XQk8p;FROTm;+}-#EoJ9(pdZh>vk{C*;{mbiC zk7ox3kymomZ#r6S3ZTsik@kcGHkXVrHJvtB?--H|tiOg)(f|jPPO)ZpThm+mAtl)K ze?Wr2lvOhQPYf~q%eVaJLkygMG{hhTAIOL(_QW@|9S&0q2JBKM?naJ%29&`}PUgRY zzJFt5JTYN(dwcYOfwJQOT25YtwW?P)DJ2Y93L!cPqY2&U4YL@4k>y00hUy7WV8UNRPx_|$XG5?u}iIaunpC6gezw-AH zof~AB9aPxPCgdk~c5_~f4yqT?*h&Ji=1S4gEQay=Vkye-~;IPkXy=0!_L+~UpS+X%12jLoiTJ>nlluBj7AfO#wrinIpeL=^-rnU+2oyiibgc?B%I zK1G_l+$3?u6=pSLy?B99L2cuT2aF$*16&;Gg|J_H;;2K5wf^%P_B|a-nCi}q7e(2n%T(ZkhQJD>mw#R-@=sqM z8YU1TG}BS&88(APr#uRp70avqYKWy_DQ{C+iHuxa|5{wbU>j27Tt)Z@Yz<;#*?#@y z>qa)$dt$UD>bV=qo!41YGA>q`cH|fCHNr62@bUx0hJsSYXGpa5S^RiB7fltj)&zjJ z!t}hX52jpxpdV@rWC~vUtAHm&Ou7)AcD@C!x;F@!syea$e^6TWURL&lWIS@&xk|5=3cO^4NjY>z9-a06a#vEcZAj-(C zi3i*>Ny@YQ!SS!FwMFtm(q-VXQ^2h&BiCRDRX1Sg!o#8;yR@ZW5%{~=U0;&%f;EoT?Ap5AAfn98_p6d`yw75b4>0lC>@DIKO-^zKS@XqE4Kszf zgWnWFCE?*7->nLaRKhlAiC!J?>JO!3Y^?&k;w)$LLfTF;=#B3iYn;?fq3?`PS9{=s zN;hLat~Tj?J)Au4L4wbM_0M7nP8Q9Qt(Q0ofyKBN+!E6VC*u#*p~~l7_aQ47@o%XKB78?r{TlFaEJU5^@xC}kq@%Ldt1x=HS zj#R2s2TE98$z(Tki8m$zwv4GEKKsQ@20rrwU-FA{3emyYYduN;%ArJfGIrowb924Y zry_zRU^{_3b8xQxZx>{8D3HbETKFAK;V1nARp_3r^!IOtQNY$CPs`5 zzEYny`jc)rQ!{E?Erso;Vp~@^HST%4U|}PUJsYcR0}rS(mu0FGEh98lT6J8XClj4w zR8Yk}lE}u~Y;bHh)$~1*RoFLgoq_Z-bmd*s6m21tbf-vFO4aQ7`$bu3nb+~9i_F4V z6Z;WT3Uz@FuuGOJKKwr`R^Wpz1T$K^EQ2~|E9 z*xg7+@Jcm!6w&u+XJ4%|WeX$R)TojWIZjbuFmgPLQ)$ZdT=Bgm`%n`n5{0J~!sx2w;)HwDCA95o(#z7Z!^c=^sm zFfb_j?mqIh_%rJKefJjV#H;9S1=c!G@rB&@bDhvkUxOXU$QWnS^qx(q5t%R zYW9EFcQXGO`;wD`<)0zcq&8~1{> zuWpt?^sz}ING(u%R?mh`50=7@`rFM2xxFuD{?g6ra}(s)=<93bVhJR3vR-o#yPxALTRSbk|HAw zjN^j|dg4+PGtJ@EEs|F2q8vK;DbdbB{wC>)A{@o{1%Yd6Xt<0Fa~9+?&1I!mpzM~b zVP?DE#R^iQlk&qdG8ILr@~4%AY$l-LHJEvjQ&t>)rgF!Ft+BHu($1~1=a=clU^Q7Q zGY%+CA0O>oK9PZJ1NO1J8TyzV68h_Av?J{9_ekId z%s6I?4M|`2cI5?vcJ@NDG%sI&O0!ZPWBD8!JSU}$wdm-2)La|VNux@Qbt5zIwV?^$ zbg~egk2zh~Ef}hXPA^D>_i;37&ND6=en69C1Kk@JWY22flnWx6yPsmcQNO8~qbG#9 zre;W=*xC)VQ!-7(wzwq`T=li}8s)`VOpnjqd!i@xqkE<~@L#I$6*_krWh4?%)MnLy zm(V|@YRxRXS}q_)Ifl5s#Fo>x_t}(^@hc~PEynRhTX69&A>(Jy;I1#+Fu$kz7>L?s zG5LU}H_<3EPhwA1UWf)9Xn%G;%pN&;@a)JZbPpbw)qU~j1I&5U4mUJ@2{Q{B18aT_ zKd?_6E7n2h$kANRj1^mJ5Dm!%W%3w%#l@F#@UYgyeb(B9$Ohc3PW*60>Ik?1YF0;- zb81(wHqvSffx&E?@@uA9MFM0F;eecB3p53ux?yf5beO7H7m1C{@xl8F5uOCt9Fw_(bmy4>Gy9qW2ihkZ1{(6A!YOu5*~ z$fbjB9AfWiy8zJ4>VYE{#pP!n#BFbJEQFe_O0^srVT6z++}&(tV!iIu<|FzcRVjZ? zk7;5CyR&$AzPY3XcMul3CxSvHCs{8Is0bl6xTk{iM5wJBL@uggBPeuch)UJwQ|dub z<>*p$p60xt9%EIUyjr7uQbibDxuAe4J@v{Ij3hK~{i0rS(wo`GFD+b$Tk>F^G^96SG zA}Kj;jy4!(?@*all(ng4x--vKF32flg=J1^BRuXND(kRwAydS!#P8OQkeQ`+KEuQC z`y9if+!7gYeZ?K->WZK=rJATU8iyplXsaTK1y|h4O#h@Z0II5ph^Dcqi#qO?4r}y* zYy>rmI}uL8tA@{TbqEVpVbO3{fj#cN2W3HJj+&Gt1{UbO+LH2-|7l8PzO_L}47A=T zfmQh})@5O_7GbBh>xTWK{e30$;xnz*QTf4j5faMR(qiW?p4|sNMs@U^AIPh4=8)jI zFjXc`Vy3hp*^@;!lDzBX_P#<5d9dlw_L$DydyQo0Pb%n;Ws2#62<*8uD!?LkyTki0 z{||Ft6_JZ4(j!pc{q zocBf#yu!4nD%J>wx(waTzp_)4%)C@@yj+ax7l(~jS1m;^ydfKV$xw1u+Q&G&BM)j_ z0UfOxz9<@(-j39rp+j8)YGHh6*Jw@YIG5Nm%lKOjZf9;M_*;PYJP+3_8nr8jBIn}j zj6S#wDEAyV$*9}UW*u#d?Yc@hO{c%}GN`zE)~b~_YPMR3ocQsg)T66Ozm)O!B701i zd<10*Egyz_j}a*giAiSMdtZa&3`YvAuW9ml%)3kSulS&+4%!va2+l)OC*(>&ID{sp zxJrKP=W3N0pUn}_r*g{?QJ~zs03QpTnch?#QKDMQ;c zPj#1L&VDt$7$kC)#!lH4asS&Uw!ZxhQ8}nhEcCSU|Xst^GJY`dD@=k#@fS8k0GRH)O{Cwd!H1DmYYibRj#*XFaIHvsNi^rk3 zNb^}>DMVhNP05#JCAL;O<($~1_WF^kRkMLIRztX?+N@?6OM>XRLj*+GX}| zTl=^gtERVS80(d59I2gI9yx~WjSpz3$9}YKr86KyXL&Q@m^)SHDa<@@o9-lDqjdqv zJi5e_3TLQfYUmY28t@UwH}C=Wam5tEV-LFgcJ!`Wm4Hhao(dUDb8cSg!fsd<4KosU zbG!pR{jY=96i_+lTH)<8vw{XF@Fu7u~^1KC*6 zI!+j!=COR3%e?N6{Y;|G%)=B#dWER zu47~0wWJ1?>f*asl>~iD%sw~=22u9n2F($r$~1PSfkdiOI>^rkfU|Rn5xi?h9A=B9 z=G1v8?YBn)Ja6dph7g@kt7rS&Mz@iRTO7`ph&UZfP#cx_nr_*YrWT6Qt1xnT<@_^Re=}bx>8TfsepSRZPHS5A4Op3F*+6QYs0> zdSL4!i0xM?emMb@minwPs~Pyg>3NogI@QEeEZTA^%JTku1wT>pBdsF1@4Xfl5vzsaBT$(>e2J zvNs#3tVbi6VnOD)-W!SAF3gvuNgKs3@gt8s7|$Y6w}&a|V7Vev+OI#vI5TU<({>XE z&xFJ1ek@<@uEWB__rhenXDRNeuJWb!;Q-79seyT%aamcs5L2ph@&5ASQg>B@*H(L9 zxV>OvltrMr!WN2VTBdf|4FZgx>IjjTQ)6*+R*`TWGIYARF95BxOY}_1(#>2d0GAo; z%oA<|Xp$K=qA~j>PQCqhC%uB&Nt)UMt8`Ss1R6y+B8aQ>X%TWtPprCW za{jkr=PF&%7!C@ix&lf>3`(sBX>JgZ1-V@jxl>2uJkSNuXjx>91^H}PkXkWrhLMrg zI3)<+A*)!1ne4b|#?ldFGvH%)BNgZ|j~kpT+DAq${_b!_E0sF(tzt{w7ifvaTExZK z9n8M`i&0ZM@4J&TbBF$pRTz0Tqy2VexHJbNQV)e5Gz+=V0s5zS_Ua&DHiJHk$~V12 z2Tx^Uhq@2Ygm9&(Na0!jnL=AUVJm98(@h8-<&%$zQYNTu3n?;X73ZL=AVnQW9X&UE z!h%qIFDSe=#nD-njo|!Kq$z&Ikg95y922yrTpx|erTmBL26g~sa6Kk>faV^ZsMgh>w8?2^^tnA2e8sv=TWn4=l@fH)S#V}}?%&J9Yu@GlOdi5&~8P-PCM z2_*04CS}T0;8haCyjeukGyOOFC*uwrMbnc5g8hSzjcmrR#*dM)sOoP6u_;*K$Bo0^ zLk!8Xo9{ve-=s-mwlPHB<4i+@9T?GNz-0tt>baBNPTr+_PC+e5P!;1v7Y~ke+gVU+ zGxD<-rA}K+Q~Dq1ec+B}q!hY#U!Y~;V4p7m6cTvWn`693x*@EfG%##RJOcw~o`BWK zyK}Mq3u^MYPD&+9kp)W~h>cAwXM|lcwK{*ad5>q~VTECa*bi_K;MPB^yCs<2IA9ZE z`f`xOP=3PzVd7^1^LXE}=Tqbadmk{*RH?{Fg_N1&HRx1+OQA*oW*dV5AH6d@h+F+a z{73iN4is^4L_e_lcHNB(%fk*#$j*N+!<$uj4nEsMgpPl13^Mlg0 zZP!>)Lay$p!T^Ms^i+r?Qi?ZF9JpJVTUWwES}|!2#F!8?#ZghCm@u zQ>T;v+@UeXfgu-`TlL6}fh1DKcVsMg`*;zQfr9A_$j+2uQVc6ILOPQlqhP|w?hMk> zoZ?!&wb7kohMBTb+WUiU`nTd{`JM)ZWG2QY$c!zlw+4u7K~dGwooRIR1gC^_lT4X% zoUZZcjRT}cx#om)0x6^fZCQrFh9>)Li z7#V3^&}ecnopC6s;kJyC$mxf5SpPp>Ts}&+#K(HAp|$FSlpPk`l-5gr2xkhFm?i5b zg6dyFKfV%VRv9CvSb=dZRTv?+)`DxH6n|Qz)@D{fxYQJebAXK6S8_KmjEp)evJf9l zSs=X=z5-&c6mN}b$;z{)g0oW+2cO*=O*t!_cAQ04YZh#@Q5bUQGG~J zRCC$J7ku@oj72j`<&JJ0@1G zCLf+X|BS6}EX7eS+AujV|071!RP@hvXjAZit{85K`QxQ7Tq-#(l`&143xBS&$>zBz zBfMzo`SbUc^{0dC{LCeXA3t?~{ z7;B#{v!{SvNNx^?M1o;+fJ;V#s&~LxSOE!B#KJx^E!$Zf!>c-cxg#qSaP^I zs@|ZL;(mY~)gdK4owY><-gQ$ArD!MVcXYHjU%RkeXF9oxdrhvx!6oP26J0=WAh3(V>a97uj_ z_IGR``sHaWA+lnMo#~vG9X!N~eHJt}t2&i6%=kp=y8|ZyNm4_gg zE?wV3{(!#$nm@Hbzr0o$X*vDrt>f)>=axvd7?JaFOnbEaa~jj8-x%Oh)m9}{*&A<{ z-U*%Z{6kmJSfv%vt(v9u)?n?Hc79*IZIC3f>qAOEU&U7ax-1AMUoDniZ0XGS_!JgR z-`Kt@6lArx`aYz&BX6o}+j{4z+mwV_Qlxm0TSDTQ=IhR_E(_Z><*@Pu`hJE6i-BU} z#lXer`y?Kv`({{&qxZSHPWqWI%Ob{m!g5XM*OuO+kauJBYULsON;=O~Q*LENiq~y1 zJ5TK(@{IAplzJ@KlNWdq-O82Rv{5 zbw)yUV3Iqu_pl$Gfe}ROoZB9*@3-xj!UK2)iRQPj>7o?a+9QHc3+1WEixoBe6!H#EV0#fkvnW-pabJj2gnmEK=bXCnyK3o45m+n%9dO zjq0rAoB-lRFcG91mU|+p3S@^~HDYbarZG@-=>GB@Hj1Ry*blCDajK!~TF!cRzom=# z88H8w1mth2c1+Cw841Y$VZ7Df%S8Tx*I@c<%?7Oh+%(vwx@NP^ir~Ffi+^jtcI_a1 zn!{Txg9%~>%%;HNXfA zsgVs##F5>y)U@=NukG8!^rB1*v?|j@3n@UAQ@%+}J4IRY+?n|#?3%^*eX~}PGYp&M zu*Oc|52NC!IXUX9Vul9M8nqweh%_ly*V~qeY2-GUv2sBB)|Rk`uLqM4k0A4J(M%jM z{~nz+YCrn#(NZy$|4XzF%+=qBPWolOR|g~TM}!m~{2vkce?&-5sxwnf00EmiXdN&_ znj|*%>P3OEfwpmBe|mp371$Tpz?g&llF-`*40ETNPVQEprdRM9W`pK~0bnbro0CM5 zJIL2nnx}UR9ppnVH*7 z7xDVmCjqBo{PrC9b6pFQ3Hx&limi$T7Od~MrCbsub_~`aT*1ofT|w1r^A+vLc~mI4 zu|4a_BW2E;X3dmCMLBqj*V?CK9D05G&1zU$y?dZ_An=Mk+cLXejNfaU(Q=>$)tQAB zA^CP>|2`mJi<#SUFsG3Bt|ba=(1DzWxI)Y8jQx~S39$8j|8podASJgCLX_GzkC@}t zEBsXEg;{Pv$YC+xHd~G)T5V}DI?e)nLd}H6{Jmk^W1%DTL%uWrD1pUAim5C zO))Rt*;w_uf=5t}P$5ryMjY^%ZfNz!2A=&pdl8M3Ukz%oIxxWbY0XLMU?$|vZd>z% zh5i(9sY+RPNRD%AJ8>dxXp#|H7}48!=nyh1hTa=I}c7 z;IXMWf83beX%GQVB|IL%Fkp*NWEO;ww0j>E9k?6-DSFU3fOIJ$2x+k8(Ov{|RgWxb z|20TvZgD~E*qsw1H+HM6Yi2njyQUIFH=f{ZziqRi*!r6H<>8#@Q_&H5YTZVN5yQjB z%0BNYw)5C@?;D#bOF%A{Rzui8!U(04GfG++p@oVDi+Ps-+B_&*wAX^k9?FzyunI5d)v>N0!| zP%Afx;0f4Ni0e>Vl5HP-&hJ0-&&FI0)qYN$GAo&~|HRa0JPD|ppFiE~^J5V?BC9Ax zhq+MCr`)mgX7E#|gG$0@DE1I6bZd~a=63qUi)YBW^xQp z4`5+OixXF3g{SiJ{s+{8+#*E5*Vu z$nu3zbrR8rw#RIppXe&Ls+5T^lS?C^TTuD|-ltTxcW2{NaeHhk&YjZ~ocivN9qKL7 z>gl)i;6ea2p#e?xrC4~;zw&{4%*v{F1h+ohv_HCE!9zqvI(~EZ{4HsgiS@r>@yqfL zv%Z=BQey)9Z>aRa|7j2b`@s%Msh(s+)5Rhg2xK0|3Nz>E-K_)^gI#i~sY4k` zH3)p_!EOrH%d6!^8&YiodzcYejdA#XggWoaWg+uNcVL)*`bB%2xu#K;KMo_Om5Px` zC@(KVE@OcfwbN3~@jZD44R2fTHz6vc15jQe@t;2f$a%Ss;zlF}G-^OQ!@CKVPkTeJ zEWKT`9Ew*zHb)7FgXeq46I9=a)IBg0JMFdhc~gH3;i!nqtH%90(>izc)fvzlC&Y7O zTXTl^Wv$41j_^ZBJaI~0dHw)&Y5;7ImApUe6G1&4YGD}a1f|k!`7#K31lQ&yefl^c zzKBRl<8p`*(-jv`HYkEhJw{!QR|o5wA{acXMTwL|l~J@>5l}iOd$KvDT&WM8HMxb>lvwLE^s_Re20J$7tS7BSy7bl%VcYgC2*V(U z9hCqS;4E_#@WiMiqlz!J2D&KO$IU(qzOdHrz@;(;fx%0p{iKy$nA(OuG2^+-dcohq z14cSL2k%5^nY$9*hOcRjgH`Uecd3Q)hD@O>)nb1*Eit9*>UzCf$k?C8dzwGA+pvw# zb!yx*g*5}Zf_T zMNe+81+9wIco2L$y1tchzF8wMQ>bc{n@`+)%(MUF1eZWj0et-9zv4I*^|**&I}#_U zn{(B+6;Iublevnpe~^%`o#9aq+t}rq5>kbst&|U^$B=hsQSp6cV&=Hi*+C~iUi>x4 zZ_A{{DWiF|_Xl2_Z_0Al3QPP9F#2WpNU3cvZ4WsU6}`E5U2S*k8y)$z=|yKYoOdy| zXwLk`{RZ0n{si(HwD?=P8x#9~ai;ozVD8!fl5_PpmozjhYyWA}@Or9UX4Cakizio4 zxpNU$L=n!^K?FDR^V|_v8WSLNCOpx(J>#l`Uo++Uu94T4C>3A0bAD;}&?ZJcq$^-P z`DNS@R+x4h9p*3=0XqbwT3d#TwrGzXJ{}B&9jf_-;b$f&fYMvC#x7yrIAm?2zwVXU zXHH#U05t4|TSvys?Mgg43-q&+>WB+(Wb+)Y)@NNIVWvi8z}=spB`nNbb#ooe_DbMO z{lf}xJ#s^rh#jMksvh+Da3j&8LqvLAZ z1K4Mt*2>wWrKO0JO92TU+ncaLv8S>}mnyR)rulswYNHnZ{|$S+ZlCVD!a?q1x$CJYXn`4;-WLY<{IBP|D?;v%)SaWO$5G zo_8Kp;jmtp6JnQg&N%{pdND{IOo)=UA!d69u)}5$XA}we_%HnL&z>t~)4A60<|xqRH09tn%h-7+*bYXA%~)8>n*Z9QY_3rRq}A15R^gfpbYKYjlYVP36{G5-I!J zY!CB&raujxRJOR5B@53l%cef4{Ij7vK?VCn`wLm30#=mqPpyu76qgYe(%U4KSePD` zd*k1BxpQ{WxY>s~N}vflC9Ma#(dE%{n%Eo$QnL(4DS)*EYI8 zOE!4TRvV+XoeQ&HCHOX~c|ZBD+rvinxtzekdr$KsC@-N9<|T%Gm?TvOv;%esJ;lX+ z&=4);rUM@@NfbOa#BHS3cb%xBho3)1>Us1PFF1I}Mfq5p>J9S=a2wqQf%;%w+I{;r zDqBj7vUZ@H46h1nTHz;-VU3!+%}Q{xtP#?M%u7Isj{yu9BPcANpV0`5trCR|q%PKC zUGdC>dn5u0Cx*v))Yi3H8lkw5(X&)OS9M-JEu8>^=?h z0iA2P{svn9mQKk0FTP-e=^w4}%=CY0pd<4?1I&f;n!_ADg7=i_xhB+HS<9Z}yO{Zp zUnnKh*Nf=-wq?C3TH-c}-8snz?5Uff{^)5@Oes(2GpFaT&kiU8-+K@mAWA4u9?10o zi_`}c!b~wXM4ilof}s(dp5NYE0*BOl4ax|nLWMz1waqe&tz5vNgVY7?y<>FSvVOiC zZ%f1J!`y)`BuyTdoU=mf>73(OI9p#UE0>?4-(BHidK?pvLAJYg4z!m~KidKPh@34a zmH&mkL<&mXRN=3h42&%JO|IINzbN7P8|kkTFKQ3MC{S?ucNnXLx&>73l*feRibH`0 zfrT|nX-)!#ROg_Q>4JIz@z`*-B&jYXGHi+b`np{xeUdWKjmrT_U-%&ELF34233|4n z9NEM?5%T1wJmTwu-l17c^KVd{3IcOo{vnDnEOIgSD@qcMs+fU^{Ld7TTJlb1BIc1S zNV$1Bkpc)fn3Cl@FThbYx*TXZzz}kMgD=d{Gz~t5JNFQv3su@p0`%1(5kFOJ${tfh z3P^W(QKva|=(yS|l1@f;B$`8Fq@bYQPj12aTOZchx4DeZMRoSV75G+%&dc7iC=n|d z=vXi{I{AV{3aJ4}P|&q}3-QgB$fa*YMia&Z7TbypX3kyvc$X;3t9!?II;;k(L#oKN zL?=t_r^{tgN%HwOX}!E9Dky{RQ`80%Z8A0PKcV|Fz36aE#F`~>`g#^>t_w;YMR2-bZLr&^co+B`mV{^C`2qrttkJ!TVwVt z=@YxZMRz1}{~Tyx`Rnc8C#5)*Fqk?X#0Eb#A@4>Tmd!h#SvUI%e~!i4S}!}o%k8J9 zj2ShSryVw#)m)o14v}R%KIAoQ3 zG78%<4QCb-@tCCcG%U7uu-z6h~*~< z{$iXI{wo9#7sLm(#kMb?rt*95P`RnPDbD(x& zm^}E>E}4UK%`R>*5$E`~o2-(1G`nD24PlhPP>UFNYwPS?alh7hf|ecDjwD>0MsEKh zi@lxh%(K-%egSipek{+)DogI@C@uaAPj_!f#JAKvMCw6_euxg~$b;}zA8)$7(pg`+ zpF23b@`FZ5zLbVA{e;?(KSG2j?Kjr$_>iYBls=k>qm=PEGW|asQr->U@Wwe30T}sY zYgI5YAM!G505cqN!!H3bFYMW~xYq2gD3}r*i`=F+1V=eIQY?6x?WSk=kpQDQkWZze zC~=;(i(8HQKRK^sJy;|><+ST!(0b`5jSGZ184*TzGk9`D{J1JNC?c7ZXTG1E!$mWa zAf_n-i~7~Js>g#zk#go-fB&o<(%gx;LWXGBtC8AfJSewlG$xQy6pv~;)oooq2D3(& z;e=?L32{&orjikw<2i6D3`+xt`7j#SaL*BtR0=~gt(fgrmO)G<#BBlp+Hj0Z05b;; zeBTawz4>(5{UVA)!F{7jt4@zepDzk? z<|guXbMq<|N|BRErri>{GXPeZ@BeF5sXR!ahOlQTx7POf?abGhvudxpv_b@nQ>Fd6 zjfkji#9+NcjkK$0FFB`lU&Du++vjqpxHWTScml(B0CODJl0WynyxY(ocfNm^8HhMLtS-6%>Rn(%wh5XjGFh7==4^_?mA7-NV;Nr z5!W=U0ir9U4M(#g)aF!hK%Q*42N97TFF*yh+aIXY7Sk6ti8Th6d5CpnGP*W+dWj~8 zaUyq=)Nrk6aLy67zKta&X z`Z%=<@k^BY%F246geiNzFb^k74;!I93!fe4;Y0lIkPoUv*-hkPFe{k(-f}B5U$Vgt zZL^9QhK-_(8I;?RNa2ZypYjCS~q$jd_R<*viMLO6PVbN^6lxFis7t{`gmS;Fj z+u=$t#>@i&Zr3rwlZOmPAU%7vxn{hav3}{FQ>}CFxO5BXx3XoP;eY6L;wb0#!7|_1 zA5{B-Ti93`HXXK?%;7(~H>OQjt#w(F3Nf^!F}GkNLaINCu%#4&Pd{BiZxT<@z>)D{ zhrn5o#1nc59fNHEc?N6ut(&39?Xn4iWg*j+am7D*9paC=G- zkN6m^Je{s9wFhr@Ec6|TYM=q>%V%?JTvQGN@spErKMQq-<&|+Pql3$lCuORBr)T4N2yKd2gDTL2?Eb3>1CU))m^0%Rp3QGFv# zQo@2%RMXYueY}I6Lvj_B1_K8v`FNh&a=N}ALT0lTQ4OkV>d7Gw#RblGcMBVRJs(0V z4$e9rbi2$~GbbCd(sb6l%Sx(~uVRtgcNCSFrX2d}hX}~K)Wd{~2nQ)6E3JMQ$p%Rx z+kePDj(RSK@1(waUcE=t^8InJDPYMjA4b#4E{0yY;oxVADyf`*McxL_Sx+zCv%Wwq zD#vQll+Vkc^4p@CE1n+7$d_}E&Qe^}U$;006Qa6tnGtc|HZKou6fhq^paXA>wUgp{ zP);pKYHBX6Q8F>NAYhPLXKzpv!S<&dW#^Z|sv)DS)cCq&4l+JSxHKtGBD)x&XCd8} zUv{eCJU$A0VzSRXxk!}cpFvwFhj#iS@CtT{D|WppeWxv2wyglp}xk3;lb?E~xF zkH{O4lUXj@Yp%;if`gV>Y6bAG%;>|=d$wukU-lL3$Wn;{~iHR94pwx)h6Oxx%Wo**2mrNFaT!5 zs8D2{Z9}Z!iAmmDMcC9DZQSQj>7+fJKr4zv4py)jEAsKo3OSO;_gut`d-74YU;6Ww z>Ag%qRU~wztzaAarl=w!T_rywwGfR^`RmPdJ#Y#m60A0rUA@w7=i8S-NCD!2+NziT4IW`Ma4Q%wA9-1MRdgf zPC!R+1w#z|ioH{Uy`#O09miTH@_nBCiCIqhJ~g0RIlFI%Ik(%Oh#5IfS9`CaKRzrx zE@58#xcOTmryPzed8GupEEi;=rZRS3Rkb^a*`9~*siwpf?THhcAX^7sLg^ORXe?Fb(7N@XrP@T%FBfj?~Y#F!BMi0`3yx!UFXmelc}iaE#(J>??+D5rsi$ zKV00NuR5_^h&tt@?G-u9V!u~;>8DA#jNnw5>Xo5S{Tx6DhX_@B05VqnIJxfrz1eb4 zJ0#OS50KDrT;~HYQ#jE@qnNems)uBFQT1>2&?bkUYZtqjS8OQ7P1SMjR?(@m?&z~E zZ9bN(Jyq)!A}xYnCU1R#MDRL8Sbnv(x<+#gv#$qntep|}bbHKtmZc)(kb)uxoQXd=#C7R|#&$hwTa%Toao#zr%h*+pHFxXu(AUBQ+W^N~fE9pHCq zRfOWjMcKP}k`k)b<{)@h@vXze6W~&7E_DM`aO>f*f#(;zZ6L~idT6U3gB z8rouo!I$MGbJC_tf$>cVsqQsp!OgQ^f9#t=74-n)*c?vAdS){Yt|zn9RsSW?N+ky; zoE`&Rh8W9y8?nV^XsA1p$Fb5r2Qx9rYOAY6f7{yoW5IH(C5wlk?7ri^A|x*P@jfqk z42d610uS@8KSN#UQ?`ZI11nvQmkA2>P!mfLuK|05Exz(DNjR7v>}zT%U5KkmLbZ zPFku~3iuc19j(`M@f`W#)ebRe9GWB&p_*Mk2mjE$YH8i-&Is}p=34xmraBh*l;-Q! z<$dQDbHNTM1M_g4(C2_Gat(Z^ZL*G;fwcppgPdOx)@)cm|Tr2^h`ciYl zIXec#b9Kq-G*;I(agpr22W`fU1(3>*{#Pt z)q9N5kv0Ee4b>=J*^AO0k=B>(_Lw@}NMEcdGb0DzPUKT=ZflQkQ<<^TY_xX8INVE&k9v&eU=qr&7FMv2|_GHqsXWCzqe& zH>mix7-JUte|0Lx@>eKgHn!htP@^_$-(kAmsN5W(lp2V~*P6vWB-jRcP)3X?XBdFh z3xDkr`|2tfay9H0efR5S#h>C%h>eZB1g9W=7uV-bwynn?wg;M1N0TMUoqFcj%jH*V zMtA3pyi-KqV~%Y6985jXyLSdOhZ{!)PoI3r2MHmAq>gO7lTeqeEXC7g4v~0o>V$q~ z-Y&H2du|*TU1vsJwae}mut~Q}I;dy&+5!Irq4yL^bn`*F)y5Nz)Cg7V)5)WOVTp0V zp?43RVGin4kW1+6pFz`?rOwk4x4hbiDWg5vBvJ#Kgz7AesB$=t4hH)`vjkt|3WR;* z|A}A55p~KvCt|Y{y_NTMdbU#W5s=#su&xg^Q3E-8B33}i!)tv^>-5>)+E)gbC{aW zbZM3o(P{N6GhbN`;09I29Nvu*N^A}BTtCjjvr06IzuNcbBJ8MtDKKlvOUqQ)h3Zo# z?ZA=(PwZhuAg;D(Mg>6o#r}%m@`@B@uMB&NI*?x3!YAW?0y9DH9{$X8Nxc_|2i>GM za7oK?Az&Hn%m6oZ;-|6d5u)7e?UrTfROoM6d4YBxEwF_DtbI&oKU7{d?6zEZx%AC& z)HR}z8j3`CeSey=4BO7E;8987XHhx`sWfyi9~%SU4@)$&#hOTHi5~ueeKg99>$pW+ zx;Y2brUmB%`w2KSni2HR2*C2UNM{zt|2BEiKR8xc{@QiV^i2PZ462%c7HK|Dwd^C3 z4Fx7br`@g97a>3^)5V*bIuPkH%i>8y68x`Mo^JItYxDas-(WBpr(Ah`xX}}QbmYRW z1qnj(VAyfPf?-Lmd%k{;@DX&q3gTVe~MOsSrOY%MZZxyEk$@q?!nA-#$o5 zF6kc+L`0C1A!n`r}6>4-;p~PDTY7vUXBz7aM#zf4v19%nzhtssS@dMwNaj z|6CfZtsK0tB~j?J2uzKy>P>Bah}Kiy@It}jo&Ug5jRp2a;j8ZEV0XSIp+fYzJ5gp{ z(=aoQ$zxXOoTavB{OKwIY&jnE$=pu@3Lr26cn_mDHvwSe+nG^}n#EC8!};UFxDuNb zqnh1OvVE^ECA-Yyg;1~6E)+`Cde|QLER?+%tK0~_*$-1*WJ)kgi2lAIMZ>AiIux!N zvqFX9CPISw8eRTJy#~~RCD2pINxg{IgzI=TLr>Y%G#n78kWd&v*t&OrgZagV217?76Ra}xy9s4#PrAOw?euvida>a zvO6n&#j-qt;mM5QWIlps0=xmfnboT35~4RN2{O$ur(Xd=gLK$w!fOz2XqLAaxG})S zFsjGm96llwVSZTeNi0N8#^qe1FWET9yI2k$ii&qJf+WHk?s5@Nm*Q`37lV~E+tfv9cJa_-_* z#b-$J(U@n*dQTVJ#1YR6kz)e2dgb_O$Ai!MeR~wHhtOZ$%{xmpImKQbgFj&`$(fRE zBip)%9N3f>(oOoKd*?TZ?{IKkj^3uD`LZIk2}s+X7@#ONCnZdtO5uHdU!WwP11tIG zAD251&%of_He5T|n6QE(i=K22Rnt<#7G-u6 zlU#1p#41C_#}nIL9D>5}WzM5ggcvuIkICT;(Q_Yp!bR;YQ7duC}+R%xV!`x>CFGN~OdbYFYMWd6+biE7DJO_N*io8KY$p(Fj)Q z#LT5bDoZlSotP+i{2}{X!uI@B8EYzIY3oE+KQxvEPrzaaa;j!Qv+G3_GDd44EkDNM z*KY{-VT!0oD+pr%vl&p*er;jfGZ*yi&(`&B@Fe}Rc$<6z=E|UJb@Nc#v-@KQWZz?< z0svp4u#CS`cP#+^g5cqR=-GOt$ds-9UI1r7je1RJeWpAL9n*8{-pGI2f|jh|4}qX- zJENR3dtv%ILcS5sjogOLQbr zlh`?MgVqhz63kavCowsbSbSFU>IA6{h?&Kghm4tP@Ag|?^;&o12}q?_WW2y>#^ zDMDz76;K+)Rs*wIEff;>CdHm+Ifl1r*+U_&$&eO2|ELN+y&wF7rd8E)*bI;b-a`iA zUlZM4zKY6q;{)l1tr0Z~Lh^ReP~$6kA&HDD%HShnZ8@Mq7Q{uGx{jabUli-ZXKz5N zlk%m@Hd!Km+U(_p95Z=v-ys8bUQEi-gCG)DTP9XH&_Gfv2d-a zNOH{$>RIDzE>Pmb6!2Ny6(;n5g$Nn)c(qIU4XN#gRU2{*duW}&cUFqT$jCMazC5Mb zg1dDWKoV%J2)bHyXWPDIGS!qDIZ`bfZ1c0^-Y_VOoNliH&QNiR+mxZ4FhF1W{760E z`f>(%XC13S!VF>Q2^khUjW!tEI}vDXq_c;+hBY$YARP;`3-3PEg6F4UoJzi{3RKJ zmF2gJ=D*)}d%Xx}hV4ru-Fd-)9+iigan&Ho*1*1o2 zNOj0cSkiR5>wLhVQi`h6xmp2En;K!N_0WY{hzUZc3_3&)kNQ1pvLDfhC@Dt58FQUd zJd^RE!-c8ERuyU!F|lc>B!g6t<8wp$Qr^@?!6AU=2}cD%kHs|NM&Rc& zl+HwsH5Xb#By-qw5KN6UElY4vB4g>AS=AWwB_*k~czPIb|vG ziB{zvxm&_k3rDVL>DMD2y@u+C1nPf9;qv+*$VUhWBd7eB!L+w1CM8D*i-St>B%rav zxSk+o<#?Ertj#i;(~~Q)NO03mqR7EfiXQu>sXVgzORsQH6Y!f!JPJrxaTzdPWMMYU zo;n`8o(@wm-{i(UYlgf|7N)lmnB0Z#M#T4%>Z>nxlG@AH zOI-JTc0K!q>y>RbX7AGa0{a0A6FUX7L$kO*LVIMp#9l;1k!*p4s4|@D@vx&eLLJPD z4qs(@_CRl3OV+HtS1t=ijgGI9g}&rXH)L`zsm) z2Lt2p{9DqAYpgI`Z>rlV6MYrLmd%eWy4I!%%+~9IrVjZeW9v+!M)2P}ZI z7Zz+AhPFDolarln>$vjjWuJ0)HdNV59+w=g!iDpZ;&W^Gd%ZZ82@nAbVnhSB#&s-(U|`_$ykj-|tA zHkcut(U(RvOin2Y?^~xycXZH)~&L*vmTTcw%v$Qk0IPdF1Y2g z`uMteG1vQRZ@2vl>{HHBdjdA&5HJ#b6;I>ceT+-=UGq>~IE$BR=Vj|^b65h#gD4hn z<{DlsQNp#TH?~TS7L=mYf`pQ71nTH^P6CmT5yF9x#iIkjb?gJHL<9@T+YfmFV?fV{ zh#^8Ba0uffP`>GCGCl;~0dE0J+aINKw`4P?>~(u{i= z+A)jei5YX!`6+K*aX!lrgB{L|7#@sV5zeC!o~BEZ%SH!|rv5Nu56yc~{2VqQpu z10DJGfxn~6uJ>1O`VV!utl&PimRx#C+_c?Nwr?aAuf{nE)-q8LM&qdADn4f<7D>tRH( zrXpXK#qHWsU}v~Uw}g{<{TJ6+s72A-foGZdCHhGY z!{wsTW(*iwSiCbkjl-7j>Cpy5K2-L{d1^A%sRITCQPDX-jB2&w7H|JN)q$zU`MuR= zy|rqObwy5m{nCx{q?qOL7BvxT7+s+%&agOPtZD2? zJ-RLb528@sy@caumMQKTr43#Cf~;SizpSnkGHWE>8VJyhhiacprdeapJHOG{__Y#h zt6z7~%@^ufz$sUHjjANeQJ;c}I`;G$YByHZ?`E+S)pbE85vK^yMutn!-0I10CyPUQ zM5(Hf0LRCPv?+ttuhm1K#3w0k?RXx-9AZI>lm%BXjtKGrBxtd2H_&1_-5m zGnZGvrZPhJyhw=Wa|M6MYOzdX^^64|2=sP08c@&Z-0tw05=0ux3=MK2)wG$hd>#*; z_fv6zYbxJ49U~kG>nKNDkI~6|d`_=rEjd~h#x3iJWaD~UVv#hYwOSTsB~q=2imO)H zP+E%SKsVW(lf%v|L*5tR3Y9IMbaWlgsnyBWU?ptwn0UEJ{9uPljT#+Tu%?_c9%X)k zT0bWu54s~4g*m%mw^eSPXX!hZn>bCIXm=L%!7 z^3HKY21ll34%OQ!dsGgK+XqQ;;H#s*n!ikC=Up@n>_+O)!Sc9(J{BsL3p8fvk*0eq zl;$gr2g4T9Vp)}ztmFX4f!y`Z?{GcxJfD`<^Kk(a0wcIysiZ!KbO7A6Cyq5#^xZ=$ ztPDz+N4IODdGb{}9_^r!sdWJI7pbo@yna8P1s^?#tDoc%<_5zpqvAV`MZ`vg_)UbY z{N~!o{<5XA8RddrI)zBwt=kwYUv6JbStZbQa0mRWPO$&2t^hmp|K;V7|Gi-R6Hj9Q zOOxoVf3oPjQ$<^Logc|-x_X7<=MMzmT~d^?L_xnYbMfAe!^0X(k0ft)KJNUlu69!j zun-ghVf3FD8-Ki}w$>1NG4Wnoc0%4UO?gEDNC>>hf{ZwGjiTEqyHoUdtzA$$YJ|~` z-R1Y$$DDnT-*;l+I`SAcp6G)tB@cq8o)ETX)!=#`@z+Q|w;u=OJ%{xLb|Pjy*sy}n zxphA99ucO8b|8>8MfpEH*6(we8-u+H)5a$t#SSQdX)|g)3DG^)$3VQij&O@)m|x9o-4k~( zG%i&uQ3AKr2Q!czyt1{nO%c%<_1&oO zw88HZjTG0hEP@tBT>>N+y|p`62;nq)4t+i;yi@k6Wftx{pZ%OXaoC|9$NMbnkJ>+E zL?RDgp$aI0!&CmN0h=X)G`6m@Pq~v5byMmn_uj0# z$*7J2xKI={bh}!vjMtX7ejK=Ya*+W`n^vw%T<{4$4QP*;t*%9)d z*K_A9BaWxyR_kX6CO+_>FXU{}a-KNPM)6eAZz**K5m>!w0m=t@Co4jzE6=#TJZSxd zq;w1&piFu=k3J8dKr!QoKmJ5q{uZrfXZ<%9A%K6Hz+(R^jGB|>Pj9zK+itKUbzWCv z9T;Ga%;l3xt`VOQNw1-W&Q_{+9`;E%O$zE_P#GrZ=5Qn$RUVRB|Ac_WJ-D0PpV-HB zxMq(B@gglE5{5>9Bu4@!Gp9reuSeTQ^6f0f)d70g-F~djkTW4J94AD>UPK!O64tp_4r5HJ(4z>pj5g#SJ8y*mn}AiXtVTN+ov$_kHAc@FJd9U2VXVr%6ul;ui$;H;Tr`H*z@d zBJ0_VskA0+rd#p7(Zsa;xra8pBc1uouh3ViN0w1ebnE?BS9uiGbZTLlG?)SneCbL? z%ElsG#SNTIP3mc>&Brwj()$gDM?xP=?O=rc?Wecn!c8p;Fj+zlktFMRATsw6FKb=I zB*CHNtpiotUrJF$7Q)Zu)6WfGAF;54-smZL&~K{6JIG_e*h-YFoA4%`G`6OTrBGvS z$L_XrVFqNJb?M@RXx!!QmF-Qgul-M5__X#r+j99!QT?O{06Y2hpM5EHOCJ*W6pM&Q z0Xo0vzeRKV-0WB}pF7=OVjP;q6KNn5{5C`xrC7ox;&v*7!W?mB-d312;G9o{7@L_f zQy_a2SG-1)DhEdB1Gz%RVru2%-}dEdT29I(c;JKC!qQ6V$8OBx4>cL_%@r4_IJc6J_Q5W@iBY0-r~`YpYZ z%EFk|oy4`Ry73yjFr-WlO{|c^}Krw znD3gWS9E1bvmz#M2gsoT^wW46&IVnZek+eRB#_#Mg_)S0aFL44E&>pYYkl{SERNU= zjV+T8*g{J;ep}U^aF^k*X)iGWnrV9zldrv^vzbYmh7|`d#)`IcaC<_xnsp3)Z3S$+ zx62IzzQ?{B{~`ZV=b^paxhTV0{b<)JY4U(<7H#5-J9-qw=Y7r_sP(A?n-@t^m-~wF z$)*nH2I~M6`RY{dI_rw}S+A*F<`A(ob0#HFZFivVamIIc0$_6RIiEjKtiOed+1dZE zZm^OMwH@?2o#VE>bGiT}DDqvue|t62NaEPSY@dO0XQFVcAm5{DFp06hj& z`g;6K$1jnHWTlAYTKo2N3AwYZJ|Ou1gLd?!*~~;Asm=-+5?k^fe2M9^L5~}S z|MBJJ{8>FdL;!|uZLWq@{AbITN`3W|T&AeNr>_v_D%Q8QpMo`d>Y&+4|LZd+qbQ>UpXZxaRRfmzqCen?)tND@?zCH3eceZTV->4(B^T2{zGR<*c8n zmaK`QU>NF?&&Im9#7_ zYGlfrk(s0r(Ki;L2YRe?POR8}; zRFODSap0y}z-M$zeEZS299|mK53398`BcQes~7@w2mJfILBBWw(hXCsaV-C7N6Pu7 zt(8Fs0IUQR?%JcdkY(I7Sb)?+tL{w^iO-m(a~s7hkY^^2z>Y{TE#P6oYb$gc<(^hQ zy@$mVfQ;^zWH2&GJYsI7_eDO1fr$s$Wg0UC&+&A_nLxFAp)N9Q?>KiNQzH1L0cAfh z7y-mYxC!OWFGh*gWT`Bm8JmDRgRgml?<51616FF)%UFX%9YLkf_N)xrYK5bb6t4+Z zc>!M&eB=#@?y;hb_)7uZ)9dUivW}PIdtlQ(P%DU@a3Q5?wBFptj&rJ%Dgb?{50#`yvXN9+Cub<5L_UF;}5XCcpMWRlje;VW{946e(Uvc)jbucTjz=_ zf!_#V{cQT*js+SDx%~*Lb6(aJ>3+R*J*V5%_2e^l00gE3?O*$4X2uz1obrzn(cKdTYI;^=}uw;!d*EDvkm0J)7%YBN_%pJvoxdu!iv--7qe@rhussQXVW zMA`oqA7=;ryIXJUfWI_$`X@JlI+g#2Uls;rjk36k(c2n3FB*Jo)6^uUM!q5h>7gCd zM)x%w)nGVMiCMBoz{Kj-L0FkvPmDkE{eGhGWOnttG%JAdfP6 zbdO3Xdw#a(#-8o<#u!>1xSS4y3e!y?rW}HhJ94I0MMMj-TlPELPL+z-KIZF2R}+ zKs#HoHCW=i$r&FWE^+ERIB43xAOuLYL+VKpUuNSqA}^Lt4^5}+{jteFsS@qH1bw(q z=@_-4C-8ZK2GU!A%JxqnTbz43EYTc6>S?0IUA8tL3@;%WFKi|CfAwudaj01eMF-=8 zkW9C1)|S;H%XA-4xHh7`Q1!5dLSx?m;fLhjQo?~nxnki43(%R1Y9sLL5wc^&vVX(6 zvb3b=F*3YB6$Yl5h;4P{Vcmdl(tJha>PTAQAFL(3NIQVq+T#d%Z25>7Psr~pJ9jMY zZ&NE2hg)NBBepOnAFP$oB@_D+eeXItTHEPsaW9gK4wI2AK6cdL;Vp4ZnXP%lgrctc zpd{O?L1vc-d*L9IevF876AKb#+Cz6JiJ#Ee3TOGY4wk*3F(Xb>$8TF5vU);lk_i`% zx~Zx0?HdjIY;Slj1pi9#DUSPV z2g-r{ULj~lNdvQ+sqn^1b1bN_y9#XYt~wD|%vat|!(rPesZ&_}nvb4!6{sy}Dq6>u z@o)QK?nYt3`-+EZ-6=kT&6dw8ZZF+Wsj@`46M`o%^A;-%VGPIN|#{}zMhVEnfkkNlOg>YrAaaQr2A1GYcyoQ>P8OTcZu(S+JufHYO<#9dyk z6*Ke*c%g1)ae#)&90^uWL~51j>N-4>(sB#W=G#?74zS>TyNkV>9{^3^`v!*mMfQ8Z zSt~TT3ss;+V{WaaT5v^E2n*bcmnAml)8W~C&y!{t(ieY*Eu;rAQ`s}6x6}DR7hDG5 za=@VK1<*B9-I=5J?9bR5Oz`Ea>V+lR0u3;WTLaY&O<0Wr*o=jE{)X2b{^Ag;7NCD; zBQhn3PF2M|8@lLAuN-jO4MAwfaRZu$S5+Mk&1=}+2Z;E+8)tap^z>yTGo9c#=NlOt zsk5fqAsH?Fs6~#I2nvgX45VLza2~2%=L;yLja&nlPbD$}iHyarbg)l!&k_ocO$M5R0A5UL%@RpJope!EAd~V@&s2^UT~YcyO{24aIr$ZS*p)f=%fF9zI0s3+@yQ zwv;(;2hg&X*vc61b|faS1pbpcYR75bX48I-*AtT6yNWbSh+OI?c3~$(t`r=Obl9DZ zgoL7}nQ9fc$y2Pn1my3f#{Bp-IP+Ph_z^e*&hmhHOY#fh_3}G}uy}Ug(o6r8=nPN# zJw>HY#~xkfSL}0L)wh}jMd}K{N~-u)HmWC(}N1ZCtzy(D-q zaq$DcmSyK{O$`Rhlpwn4thUvR=VqI*T?9@Xs(g&J5@5&8GT-3eZ0f(Nq;iHUf9EUN zDz8aJZp)W$!r9hWymNIA?YS3r3{3>L4!*M;!i&8lWzvo5V9eQNWE@)n7~I+rz|v%d z<5%P*1}W%R7nhr+g?rCt0)r*Qr7hEqS<@FmyEvl?h!z4p(-ZZzVBI8zVtBK}83)Uf zao}kDtzXq~qp7bgkREk#tfg*KcY-=5X$2}`NV(4YEQMw7lj0)s+;qpzf_60V$+V$U zrp5xMW~XA3NeGs!KW)MOg7-$upP6(2+J4Hu^CAhy zVd0K0CZ7Do+aTX}^DDAu@5F^Zxhe}(eF*(uJnJS>0S2 zWqdhi!spxOXl(-5xduc5D_~Cixnm>C@%tFzU^m~}q&ziNrlI$*BU?kUsB@#NsPO`56Qn)51 zV;fTLrJD^yi#cVT=+|Qk2RBwX2T7j9Tf6|aKtLF!1dJyIUUS{k+zERzAXmN#z<{MR z2Xkdil503G!ke7S?FqB^c)_D7NykeGyk?aPQ1bwj=nEinpcCq=}zaz(N~uOJVkb=D3b|!L3mg)C zzDm_PM$QaMhx#=1-NuvuG077fNHsxEiy5548aRtbWR5(%Y?)l{YKVsrg4Xp%E4xd7 zX(8TjghyT>({~6Dl3U+}E-w?}0a}xc2CqpMfPB_Ix`($bNXZ@RamT<>iEDUMHb^Ek(mh z`~$R>L2d3&(vFVVlL=Ud{Big#wi;tyzrfJ=ee2m5P(rZkD@7E80l!S#;?nq0fl;!) z!XuHOue}`f+RyJ9x;cgSLwxV`8KNA$s=N(Ph)m~?UyiTP4xWfJLNTc2v^9J9Q^U8` zkr9n@c{f{i!9jGB?HYsjq6AlLjFm!Kc6uOFGMQ>>2=@AVlekX~J9M4#vLd56oU+U)i`#C9RDwv-8Oco)w z84(cOkk?ifAtU;O*?tBX+y?pK;Hmdun-HdE&v(UMO)`3KDPv=H{_hEdwj2Wj%?ZGTI_sS&|y^{yiW#T>eU6%F}KR)~;To?J*rxtJc7N{)?Y+eClITYwLMB_t?&+lFvy=!v{TTX#JPx3Aqmt3S(_lvEOA@#yWpWC zBuPF&V|7E3*IFG;n}vopxc1#V@*%3WV3md=*b%nfHD)Epl0c(ZTL7``uOb&1bAWo4b^Y9J7RMi+^(Ak!XQraK6vFq{^{#H8t3A%cPF0yawp;K& z;gGeSzK7hmY;gqF*}^^^h^s@6x3!_j^sn;dqirCwB1{nUJWnNnz^G-<7qh>9YZHBdH;O*j$JjFG8HE;5!D_!JhLc~qiMyH0VDc>p z<`!%;Py;46x4rDt6;g=YL&orralnG3A#g1V?<_00BAC9=E4<=?8y7&1On9v2Y-R^1 zMT9w?7ul(~KiobTmz~zJrV$OU)cWqS0^&ouoF|-xKBK$*2qfLqb(#{sXU#elP^L!%=>^)sfkcE-9Q{xTS z)1{4mh07ipm558WTw7$?K*@FUwwZ`-&}|vqx@XG)b}y01M?$?Z9)?8vtv$}ZFBqKj z`&M;9M2akl&2B}kX zW-zN>!RKhc=|ZO*+H|dhFAlS&QHC~#h00}BO8=i$fz9UY`%i0HU z4-^x5GVKqmFcbaJwEq#iGL6V#Ytb*3;aVgBhQ(PRx*dd9SuW!4^3@I2KJokxs~$>m z+-lpPVX3l=_ib1mZYo>?%RrnHzJhe_h5(zHiqlapvndQRBsk9iXPavk^CufA5{Y4p z`j%G!1;rC^+5CMw?t>6E8^;iC5E*;%ox`=`x;cEI4acR9l-H`2mo@Z{r;TE0o3Ia61)2l2GAn9R zFxNGHO?|Lqc!UK~_MU9?v))W)!1lr?7FX;PZ5!C)yNIxNft)h$7>86<=M?uyOvt7{ z#X}t-+=U#^0X0NuOb~|WmykJpKL@&Rw?_aKv6d$i*0@ox)9sTNy?Z6CF7@NG=2r-{v8;l6OFOh<0tBn>L|&>Qx7&VdW$A<^)q6WLaiPf^ys-og4aGeaww~;jon9&l zfw5hgUR=y8zvwd3-QX#cJ325by(og={S!@hGisqJs}#qOaTzLPTB?_}KC7=5uZu8} z2h|A}LG}s9^={NLX1gof=uDx@j1+PG(q?z8&<%5a^Vz2LjvyK4i$GR?@#G&mr?QBy z&y0Z#Qd~N5p3Y<88ieVK{@8VdvAavIfC$XtXT~(6dfIg9;}x=&tjUwbMT;Bf8`u<^ zSe8Fgi@ybLIRO7LPdJ?a)X3-fOJmNgfIllR)c;{c>GNET^)g5$Hy%$*Gj?v$-VUtL zBfZhw!H9BLvzvDV)%MlJk|;Y!?~!{$6z_PmKfxi?8Obbmo6y@)Xj>`rj~VAQ3No}s zvS`P5bp$$SIp=5B=W8<^`gm|!jC)c@@IjvSNzx5b(FoST)gF13WN~nJbyD#3!&UUF z#pxy!cb$&Suj)m!r)hK}@CuDUEfs(naWb09;~>5-^u}*)!}s>Z6dks6<&xj%WjbCj zW6Bh*=Yv#QacGFVljgQc06XA%RTI-H7Llp58DU(f#G+8I(p4N5Pp^VbNX977M5AX8 z*GBX#Op#}+2}nCcKzVD;wIAO%4xmqoaddxfO{sxY_qqa9}cLBI>W{@1PEhff3Us4a(}dc)CR zM;Z%#j)Jqe_1ZNuM$a?P^uB}9{GP$N_uE8R`kI=kT#?DZ2b0hiaWZxreVF%!0!(jT z*hQ-3!YpKq-z8c%J~vJ8&c4hxQ^YIz|kDyr-`oo^T! z6k_4hcJRV2_>5q_#~B1Ysz`1j2n_l85E$GD!VL3>VtKa2#Ygq#hZ*|=&{bnz%*aO^ zQF9Y|p&RUH^u!0eZ^DSM2_1nAOT6pUw}dh9vwJ(H*RBPV1Cw^}u?Tev-qM#uIA7eo zglw`zPNi>d@N@A+-E$r)1Vp;U-=Kf25OW#ws-7I@MibBv;n!z~gsevrYzb$x;j!u< z#TnBs2smQhG5K3w%?@TCqV)*CsE1r(doWOy^3H_K@G-{&ki>hZQ^qP!UEgk99O^qv zR-}AebF41%6#5}*lZ?(C<9X=Hj=wLnM@PH7rW=e9cK8QgQ$;Bi`iEb(mndC;@~g+B zB*bRZlRroswHQv36xg6??(favoUsiN(?NtiYPE?i0gDJEZ>^k|LZLAX_);HlP4( zyq`=J_(jvOMJJ=F>T#NxX{80$RIwtjYWgiv`IaoLGy*En*x9m9q&z}HTR z2V_b$H_eZ;)-{!ywT|2uO28J5-=3q4@>PiBh-?F$Q=l~ciH!X%3=LrXPg#7x`A?mE zz+Xbnod3-@(mwk?40R`p>@d{I<0~IUZLMAACELVMuk-vE8h#AZk}42U8P4l=+y3wk z8_SOX5sn?0^XhcJ2Rw{Z7NC8{rYmO6P?V3EBQ5%EkUl}BOMl}Yu1jOSjD2T5OL z0Qho$_h!{B4$UbpHJt&3pq>+kSV4CYpBKl|rz&dHqOVZQ^Xy8cfIX<*2%066k9S?xpC0EpQ5{`8 z$hY;C4bc6=_g z&d?AO+uhLVSDMH+Bsv&>^R5rbnI0O~H867(tTm{%+wgIBLt(Ydjr>y{B#mnQ~`Q?T?Dz zJPPcc)*3z<`IxbM>eEVCd%VOy!$1J#On?-xWI z?bKS!Ncudql+0#1pDhQ0UfG?^OP#NC44z=r)Nq%b)qLHrX7m+MUw!4%c=4UXW9jqX zv`&#bY$+h75TiZZ1Pq8C+9{%xF4k}eMdpYq>Q>43{LyFO#X#Y;KdgyRJ@&kvG)!zO zYDk1SPgNm6-w_6wWCpV_S;*;L@M&QBySA=We}-v<+acf>c~rFpynDIARXWh-A7J_7 z^clJW(U|+%ft1v{6_OMSb|WAPs^X?ZUu|-06W2c~JP*%qT7m{kjkoWI=k2C*5im-f zOh^bKf(XGH_{u_dVWyFnAAEPK%r3f2f?ebyHVjJ~bMG?$HKf4XY)nF^D!-Wyfi{t8 zJC*vIpo1{vOyWev1E7l_y9(dB+ZjCPh~bkuuVzl50=c|f4RrTrdbI^sx7|gOGJH%s zjFW1TSe>ko@1(jD_=$w0i=;N3n_H0tq0Jtd&I=elK;u>~EZ=ITYC4MGQJ+XzL8>{R z@p&}oeRX_*pGU#~`d8Tl{4G8W_|M_fod4v{3-~L1`X9~4KX0`$B6YmcJefd-8h5_8 z6^YO5DC9@S)_Nz3pOYO@-D1qH6lb*`S>FuYocD`kbq1qjF z5}V9@Xl)zP44^?ZX2?C7Jd`vV;{(ewvU?31)jBAu@YmKAH^K~y%xk2KhO(#e)5aY_ zvwHjQEI&c@L>*odJjy2dl1BVH(Oj4Xol7)9PP8E5Vkz$8U*(m(lKQO~a=s6XY2bACX8KG2p@U z$PK?hDlr(jvWx)(^WyQL zv1G>XDn!oVf#asu3NX@B@GcU)l+5sVU`0oVBIvfSGifW(SaA+Wt|k}a)UC3paA$-t ziZBoo=@%6HG;| z7)N;6o^TR+n*}8mZlCSWC<6sUePE7F1E|VqoQuxABDzeA(;aKG9(V)}gnK|{7+z=0 z0HUF4G&TkHm49i;wP7TGEW00ZrzZw$4R?z89i2duB<&cS6dTT)dF5eqDoVa-I9`j- zfX{MsTbyZ&G;S4yE+oKmLDyg}E(PxP$DyRPGAjvhlLhYDIReLS%Ysz24Li*!?u}RxRU<^C)XAA5OXW9vN1h_bCE&=zq>1)<$GNem2uNjRd9pwIglXuuFw5h=lCl=dDUDzif$oWQ2MfxC~ zH=!r*XGRV!nM=u{!rw)G%2`k?TxzJ7c1YWfriLc@iVwbJO>rM%DdxDcq*SOjD+HdH zOfFokMq83BI7W&VXF+I_}@CZp+$8CE}Tm^np&+s>S{t*ReOEI{{{Z{t^ zjgIPFcM!VdR{VZzSSo43l9Pev(S~9x7KzIjh)Ox+-T5yi5DcX;xzeDE51%gb2j6z{ z66CN?{fDyM9U#xLRz>06p2Zx*G*IKuH4vFQ@#Wg$UWW$>AG4KTb7;Ru-ZCVR5oR_W z0R0)>|Y#5TT-RMr0(!Wx*9qGYg!s|QHU2~0tqVm^Wu$Jz- zvtH}(!SVfy!w?8C6RGkj&v^r&#jh1uTZ3`8vCY{#iBnUna-a0mR{$wx5?k0^u4L<{ zqQhDZe=I5J-@JwD1=`Gd2$Aq?0)IJtLjA5$DDVGbrKqe&yK@-L54`sES?_`CvfIpq zsaI0ekq?-2$1zn~h(+c%8LqEqR{!4GE5yp+sDeSGkWD%hP8ucj^#l0t%Vkq89j`?fnY0tLiIH6Wk|PjM{6a^xG1fpSZ} zf3L!14*!W>`2);O*r5}8slTeQQWlM3cl8GvH1>!)p@gbhcp`xk+Bj=yF#d7I6>`)e z^m#!7Z@zixgJGg%I4Qis01Ck!E`s+O9iP``Y^Zs&C`CM4M4u#_d5W%0GY7|-OPNpi z+a{nT4eBo1GYLbbf*)He{x`6u+P#9p9cIo@k^f3i8h(#|4N&P|p0J ze90UR{dY`b$AWbk4$xXRLE2NAZ6hVKf;$-kH2mL>rL7hFr;>Bdc?6lnsx)IT1r^Fh zKEgEm%12_(P;%?3(G@I8)clfrc3Uknx2TdMYsOj&3VD>aXBxZ+JnHs=PXSqvC7H86 zc~<<*MfDn-hN5dvIquD4_;M+&Bhi}+07XkuvsyqI^Fp=-+#W4#ntTA%(x8Tjc`wjw z^%Zr*(5XZUb~Ld&oM%_&F-B*$=`UvM(-}ahVsW3;j7g}!)ya>oJK}LiM#M@6CdCw* zdE>TVfVR*w-*~On2HP9Q?eAkcbE$m(@GLA-8*m?%IYv|;PD(U?-RYW@}fv3?aU4!WYwQe9r>G{qq z=p%(`oZaaCF~!4m1uAO#I*H|$HuC*7?>GA_E!P<2)6S{4V@8qZg|cI13W$~L1zCw_ z9|3snYg|Qm^h8|IZU32G*)7?mF_8k5V1Z-1J?|w8k>8MR)@n=9XxB}mhIMcPK^bD{ zoT!84$+}*E7n>RhE+jOjAyV+ld}+kb_j?yf$=BpXFKL)B11gyh|HDw^Oe1%mcCC;t zahlPXeM;!LANefvzV>*nYjj-0HQA{(2sBh^@3wC{4AlSs%Hh-Pe(r0ZgN03TVQ2S6-d& z+_r9bKalox!RE1ss16nh;RMA>>|+I)Gxl5~zta2Lm`HC)Q#*}9=O0-2B-ydFCy68o zH4WpOf(gKLJ+TCnb4)wR7=k`iKOSx3TycjSow#**@>&muGK5kS(1{TCNppFu0g+8o zF;>b6BqE|j#24wy5>YCUDMG*W6X?i}C2bt&ENBuR_{1S)&d$9}<)9`VX`1jfl(x=W zlGvZ{0%->d_IF4RaCM-et&EjUb5&%7Mg_K`DC8#_l~b{=hQy&38aNrKlYY z7rX*!A)i2WDo+75%iYjH#IdX!5TCsV)Dru;eFD+=H~*kk7L;X_(A=_&5i6{i3Rl1~ zX%*rk4OxRWq_mxc!%|(=PqWsWEOojrpU{F;K;<1Op&?K+SX_h(c(D$<>gXi66 z8VydNb+MQmnJ9pc#-3e((2y8274}e6 zF=WGUw>4iKHku%xXpO_e@+D)LXi#u<`{(3k=Q@MGtD8UQ$^4*dwlf-RGsm)TtjGrR zVH%}eQ=i8y_X8d7Vt(iqTRHW6$BTz_d%tDttW~>%M?-be1a#*Cj`GJC?gM`c1AX`G zqLphj3Mpf>Ui?*PM~n7nFwwhSd@jZU4vk#_tYPDIG!NxyO%%RNzx#1YsMRPdbnz+N zufey`)GCbCo#UPF6^|?we-inB3paB9r{G3b#(x?MA5Ge_I2w`4p3O(d{m71llb`d)#`2Rco(Czx&+~fo&znnsR=v4 zt2?q^%oj+g!mI8AX4mol)aUf_G-e!uC#+chh-6+cWtyjBd)dyqaH0p_K*U6ZeCl9} zCB}4}RTVtw_ea5Y4~!{A2BBRq0p?D(WHM-*rC5=-!Ft;0M}LuG%xUHb*1Uv0-kB9d zB)0}e$f2~D!in(0JlVd$ivY7-VSdX|J!`U-<{3|5bu)q3*lfu;7HmL0`)lS%PC>8S zfgNVaX=tG>iycRFuUMbiM265Di#@6X5tgedbe8`g%Fw4r>Ul|Giy%HdAUzVKw~>}WKVBjk@`(t{s=9HVf7_KJ@L z^@`0fJ9|2cd63%((u3_^(dMxrWd>?tMUqB$3|vkUou;)ww<1Nh*9T7V+o3qHq%?td@2ioe4hu@$7zws05L8@EY1jtKI&(R4+|oaXF{><_FL*goT9s zZJ)_pum1BWBMJN24((5VQL#T_rI?8KdfdU`{$rejzp@x?iT^fr91;ROK#;XkOW0g1 zuAqZ*5iKAa=6p4}Y-L&LhaCt1AjFmG{i}`M#M@wQ`XKXZ!@de@f z?4UVo?Pu~!8WX%BYJw{_Y^prAJ}b)#hhqy&G%xH2uYKkIq%l@ZI02e{hei zF6KJHH1#4#g6q9j$}NDu$A@D~T=uMc`uU6-uh+sbWY$#XAFYgPnA;i!Il)TMHUeqn z8b$Ext*m>*_+4$4igR~}uu84&NzmH8pGejzbt9-3UVi5@Bwl2k;Q2mqjgY{uEY`(Y zr9J`G^+=T8!_de|w3#*}Yax*6ZXSz;xj;#PEde*F;shlTfQFmEG=DS>?5j;UpH=?J z$xdDk7}Z#Lo`X2L0A`U|-#%*Irv-n*Z5`LMLCp7BK5E57TgV&M;fxCSO?0IzsQgHC zpvMTf^cWgXi8CDHtVYNbs)teZ?U`%wLgt=;I1=n4Ph*hSovNPNtsiVPEYtDNoZ8Eq zR<+01yJOF|1Ear?f2rWzD@V}n+Thab!pZ!`VdxzZfOb3su4nZIz>*JL6RG;E7 zky(IB(YYsj?G(gIKy$u;4H&S)6X!~YijNh6x?jQp}1Pgfoe6mrBpf(cR`%kyv-Htx6ZM;hX57`h$JhKcg5_Y z=?n?LzRdQQa!wXO3Z}32JLDRhxbeTHXU@Nc#X0}au0j7xw^RPxjQw8;{eS$m zzqA?sA10pvVqf)-j4guXy{roNP7GONw&gUgnLzIE&nj(!eG;IXdN{V4d@$E8Ni@3r zJV8$;-;h~M2`6@>V=|S=$s)ungA#t5GQ(VCC6J#zARn33KTL2HL{~N}&UO60el`D9fRHnv& z)Oxt)spMYS1%Q7&jc{?Z)+3Q!X?OF!wBqjN<)&Fs`{1bBBMNp5k1N065bWp0I;aU z2=DyC!0sz;kX{r)35l0m1FD)_Vbfu(jVZ(HQWp&Av6B%6IZBYc)>kvm>*H4|6VcsI ze)AjZeHEjrkvV=-r<=}$o&HpV%bu=nNvGZwx9PsW$;u-Wx*Qtt)&dkP)G3R}loYQ~ z5Y*5VFdt3uO-g<_UZ=Y~?`=H7C&k96v&C27j%FV@Yrk3^44DZrcPAn~w>y#KS{5rF z-UfCVn|-!duAH0Q%sduIlBmLsU`hPt>+x(3^w1*tGbLY&O+4Q3Y-T)FQUkrpn(MH0W2tUViy zG;95zy*Ptu-z>$vB=AtBlAac7?2LT7J z+b)g1X0odFo8}`vejkgG-7YQj-k9@1o`xPhE};adE5<+b&pC@7Y7-Ej=&3F~tVI7% z>vU6ABcqqmuL~+l>8rIu=#{5;xG#i?uGJCHHg4F-k`dm zOgJeV$r14Mo1<|7v*-{~ZWdV-WBgps(nUe%zP}PmE7xdM*KQG74cq^HJD3q-qu^gDxnnQysWA0vEvW4vdR@c)o0lS zqg4FrYrZX%W4O-jM(vfn!rlSLY#$aNrl6$JV)+%~sVEZvJfxV_%I|QLN!+tfL)jCC>3ixvrbpK}fHB zsu)lasjeK!NRU5%^bzCOhh*PwV{~`XM~?IkNptqMEAhe*`WUDR>KJ%@G{fBGx=*;@ z{@}+HOUQ?g4qRi7jB!J@6y1Iklg%p8C6*^cpW(m#L3FPsD}UqooJ`E|4774ced+<4 z&L$~d%fO&} zW|PgEDdj}pZsu68=2_CwB;2C&b$OMadzoHc-d)^%{3Jtd(jp03Mdvf(i%g}P|Lja^ zW!)H4sFkXD&*XliOiZ#&3oh@pY(*Y=qED8sVbvE$p@kQ9R6E=5`UG>_YVp%o^gU7m zSf|!hP*xJfpmR7Guw|25{vxfiH&%V&_F=<&oAlrWGH?psr*z z-;ecHL7ipt_7YeOHjg%C5OA&w9LEGmAm*pJ!?T@6pxn{MNJ<7*Re7;HRY+H?cu0D0 z5WKZ>VWiHk- zO}tn0Ri#uz+DI9TuNg&g8}ZP2C{oDCM7-iDE_5kY{LqN(F>km5@md8@QDp zvonH++;S{i8muR*7RT9ze6jzSSozxWYqZ54yc2%JemIOO;-}M3$hZXyo(wk<;iPfX zV^B?PAQ?Z}%w?*<*#U&NT#>U-ZIbMbG+=dtriq+bHpSy8skrdt-wjIF-@RX)ds>u4 zm`S+Z0fQ}#@2kiN-)0+}G^K$FKvXPR|M-~H5uE-GIb5AY3gSDkY0f6+<_d6%Ch$UA zUH@rjB1SIDR@VF+L}Dj3&5m&VR&tfNRJd)8Gu9MBlvLI7LkonOHd@%X|A)DE4AO1Q zwsmLPwr$(CZQHhO+s>S6+qN;&cFwe&d8_Weckej0);(40#6IWNj}b9`z7Zq7)_VV* z{kf#? z4SD>LU~DK+pRcC~lN^iTn5>`y^|TjD3~b-Bd0tW~A61A}ueIHNNWrdZ@-~(*APr*T z7y}J%s~#37t++d3Hk2o6CiKZ)Os5Kctqfhi=m0jwlnA*)C1#G5y;!Nb)Gxl9OPVpE zjgLW3_ppo>Y!-{DV{RmqsdJH8wWvsxR-wGcdjYDV50UsJex-ow`eRS2SNIa%zQFc} zJb718bZ&4nZ=(F(5}!%;_&`l82KEKTH7r{()=Xen32HXk}79hG?QWk&MYzN>Tyz8C9Ea|{W zCH~@R#WEzLE9iq-4~geUAe(Y<$T>9)w82;2gzCyqzTupXH)JU^_O_fx7y2dtes2YN$P53>dEItN{CnXgvQz`-r>x5w3I& z{8l=5xdgh169$sHpYqMrtoW&Xfnj9Ozk(#urSc=$^tTDH_)YcZ5>dgk2={~LI$SW0 z44}kYN!zFQ3^9r()!3FeAMQtZCMKHN7&mroR`eaEHCLr?L&s?iS5H*4KJ>X9{Hy<+ z8rEJ`0xGIk&{GtKjE1J8{H|ZCV|RzS$VJUjGFGC#J*m(WH)cd9s#Hqv)tYt2PpyE8jKM8+TZJ|GQ|REFnV7x zsOH+PXdE{IvbQ+F*`~Wrx%J=4A%0o@-)Q$eKe9TmP zszSnKBuV=rps-Hr*@)v*^hqKK3hl636}1M5$IM;$;79{ZxPy-xipzM&7wJdjan5pA z<3dm$&@`hn8$MrDC*9uLPk$2>rwZO%-Isw)ptl z3k-+|j*mx|jOY_nYR!!7)^MMSf|Va(d!W z`eMR0QiLRlguxG?hQYdHHZd=N93cY>s!oYBa|}%5AgI13h%yRe`=Lh}sC2#_$ni!F zdx(3vU?dt7K_H=%)IbZ;_7j5V5xxRtiN+#z=#}-yRAk&_#ZxfzA^O4Zp-WU1s)(e@g(Y zcu*1E?L?iOUESAmk}Jr*e6eBZ2{oC~v4r^wJ0!@9&PWy}#s$`Fz>k;?SF$&Hz-HWO zFQJY9bj95B!$)W$P>!5LHhiP?z*TZT1lfs+WuM2QE$Z;2K?{T{X=a`kzSKUt+Z!?Ek;zl>C1y z+CQY>a{NoXgPEB*{)FA=IIXiI`^?t14MI6%M$3=`Z@YG`73a(~ggg|KG!~(QEUlu} zQ)gb(?l_TPg(G#G0RpL~UY&3}>+ax)An)VMOXTr6cp`%msJ7_k&3J@(b_>jvB!>=O ziU=+i?U;$>@P#46n7aZod@hEYLb=fwYiwp}HY?;{A)v9Mg)Csu5TmrOf_up|gj?mvkTH*|sP1YhQQpW&Xiv*|68NmJl4T_rs4&~H zAa+|%>2ZjxV@ehiAdKE8u@!KTW}GY>hq}}bBeq^u5f%|lVFlVGFazj#I_V2L1F9Je z#YCz}?vn$1>0GJ*yjLb>H1U!yIM7P;%R5WmFZ`;l}S3RO&3?{(30rrpS)1J)cA z`Y$8xvBCitw!6c~KE@lC@Uoca728#es4!V(Y*?{*`z08$ErM>)oI$&#bnon$G9uLS z2~JwH9P)6?B`5`9O0vP-CR$dN);o@IvUxv=D@PR1=$Mu$xn5vY_{5se&@WVOD!gXS zpYb~(n}>otrZj{rH1NY*8%?W(sL*T@*Q7l?#hNDCq{KGq@ft|O&=+770>dEc(`gM8 zyQps}4RlQuyy42amOk&vM_leaa`AagNsX&JceiWu)HwFPH3{a_U$&H6RM6;0U7+PfNQDH!u9uGY}0T@!I5 zJO(P2(W9^9I9maORAyt&4EdHOPj{|4A20*kNHKi>t)yjrFJ4%hM8Ui*yCIZ-s_ z<43@hN|=`}A@`&~*aRiazrU?QjlUa7tDLO-k<{1qXuwc}u=MImji}P5zE^BVj1ggF z<$cjWBF#;j5^oVnVmUmZNU+#kP`S2&@85@3NVJuDXeLDX#QM_HvNKCRnw>X|Ia(I2 z_5}vg(ElS`&$hqC?khUS)lc8PuWEf%5KxrX?ye+y^(EG+Z|{!wT>AubFi}==1z|^+ z&$^Q$)n^6Pe7_9J@C8IKKbFFl_o%-n-3Dt+>hk!>J$+CnjeIYE7v9)GY6=H z+zfa}4_9FPax4G-COYsqG}+cXXCI>&{jPC;g1%x5G-{RG#c=WXReJhMbQQUxm&-3k_DX^E(!wQ=O0q57Ca z{j{~ii?LA!!W(;$2HG_$G#zPl=2t1lR$i;`TC#TGBit&o7Qih@5>uig5UEH;BRZ=k-?txDo(vq=rjf+%WXs@UX9^SxUNBumk$wZbG_mN29%sYx8Vt-}q;O}7y|9)Xx|LI@8)UYf z^nRhX1UYmRZOo}h$<1QF7EB3K_RunM2Tk&leFWP#g~ zfYq?10=L!cXX`qhxkoTn+Q+^bQF6SsNre%ahu+W?9aiNf_UCm9(6bHBGk_Y{ySe77 zzX1rES`Qzm4-`(ON#$ycvakyeF;XRa1BIXKz?%#jP!ps{qFuxg(CUE)>?H4L^X%q{ z4X-*2b6$}p*^I+BhvXHDWfl)s_v;6!_TAQ>%e3}oli)_Chz^MZb@Sh&6qHzk_OR zSPpSv6bM4VMNT$*{zMG*e6c9tj0}{B8h(eLIot=(TT&iqqEyQQ2vVY3cHXpZGHOVO z6&QQ+L;|v{=J!_D!al*W-dnY7F(s`1#pTUQvddP%k9p11jJVl{BHOaad*S0z)eIo{ z2~wRbg0n@oeUh@YfL>p<>HAbBN5#U=z<>_H%XlkSgz+^v~| zXIrY*4QhTR(xtDtc#X7B16}9m$ag3DvV!?;C(;V9lAmut21=p_c?>cq^+qR#_}F42 z#6Q`b&Xx*m0|2aQn|1jU;yLFn*W<|3;d{`OApo+m)#9gD3sfuDPnS!szHI9!b&6*# z2Z-o5jVv%(DT)#@TN*nBlwk8n8u1D}C5{6y$WG(ot;|40r>Z7R_W2vFw#`TtT*6(6 z0CGbak$OmhrNi< z;9<*jS@AC|tplBhny%hxsoC)#-w_f>?09j2nsk)zP9_U_f!r!lg5q8Nr}-zw0+=?nxMtxYYr+AX=1>35?(R+=`DZW$s9T)+gJ9o@D1`99-;fF0*-xtQiAxj;K{;CoLgXnXqePTNXWVQtC<5QL+S-j`&C| z4a!uA!HX5h73sQm=`=<2d&f64YFTw;kEnweW^sKd_uHd;nyj>D)rAJl`oO6YZ3!iC zJN@aD)xB!hnPu;KE?aXHre@O>yc#;O=vk6ILU?-|959AFpvwr@C%#Rh(gS?D~1<29_+RZ&#L zY)My0Z?DAC=sw?|9H|vx+GC)Ws@4GCyACd2(F~W{O)NZN&*-*PDFKiC&isfV?GL%v zrK+d0?gcT0Az3}@2D7Q`0(7lU7|3yjNiWs{9p4yhLxEGRV{1jjT%rmnSw+>N zX)zx^)J~KDno%EJs2I{*M>1JZ{OvG{RfB!v)X}CUV8kFB2%*uXIk+%uMgWD-X8#U> z;(DTKXlqqXC1)&zDHL$j$(f8XsWReX8V)oIrwQkGZFSamj*uXslp?u3uV~3q@m4!B zpaPDK3rK9d!202VWwTNy2Xb;~;B?t~zcBo!oUIRj860_=lRX(?>3mev(ld?_iG;G^ zU-LsPbCMT8#s}ZMJ<%2qg?YVd!iq=%aKuHcZHx!730~WYIH1y5rylSLBWpM)zXRK4 zyHWRHkBCQyD8DZ@wPmceVsKTAG?O$`TVX2{#u%}7rTWNeJyd}qmW)>>$K<$oQ%ZZ) zdU*lfP+gzo+(!UCg`_(hW>5in1WCNV@_UCBOOUu&bFQX;wpXUM))zzn-81!*^G{j2$$T4~p(X83OrtOO=gUf=c;3NLjYfZ*394rP?li zv@MfvtF@ZqIem+4g=m4=pEc}_9m%3^tiR>i2oojC)=_^~S!ZUhJ{fcho@AD`5ag@$ zeqEZzZ`sU}E%|7ohVWM#mfArH-NR`ig`{;W>^ikfPc3(_#&n(*;G=P)fxLPLR=R9$ zN5xp%vvI%vw92>5j@cfy;)q+vjNK1h_uB!SFptr?XrIR-F^U$t;bVALxs z10qUVr?`A8JBUjc!CU;S#(@|25*LS|h)aSvah1WUarb-UQNX{MMuoS}6ik9QuX+TE z_^C1N0O=6qdp|`=KV%&d1lugUS1Lrrr*q2O5`$IlZ3W4HuFsmG&ITlJd>LS()|67p1F*~ZR=x!5GQl0$TOiZJ8o#bVltmq$I! z*FkCAY-`knL|Wrs{(c#2HE3sp6VXD++)GIZtt8dSWq?8B^0U~y(z%^I?+e8#E6kJI zlnf=w%<_FZf@?BVGe62z{w`cNLhu-hQHG{L9NVI>G{``sZhKL8a+uNE@xu&bWUOa+bzW?gLtCQhMuH8=^9vwQkZ-$#x zZMQj9?%H9$fm`w)f<*W3%wtc_)~W2_K5Q;{S=V(VW$dULdH}Raq=`@?+kKXzQaI?iWnhGEf3pireA0BSjI^dZ` zud%2#k8KGJ6U;(-Rt;%Pw&1z3(-uL*zA~7z!^~P(Aue39b3hC%BIyCY`-D4l@VtEP z>Y*4!ulz+2;#K{cULS)T_{ORfuu35c-Km2WVu1`w^8YzP;~11y>nSe z;}vDlEAe}7VPL9~K~;{)Smd|O1Fa;ruG*N~kFJ);U_Epxb--=oB*hQu;n^neae-&l zJ-9*%=$#K6E+ASxW;}|1c5D({c%=PPS&5vPW+A|g*%q~HRw|$VV7S)H@rVhA5&dXA zoCW1Pv`FprF)buYVG0X9VZDwc5^eDgIq;Qb&Qe|4Cf8MW;_3y0;c$Hn#n47t;VsLVG3!irRAx#&0 zFvFw~z!kNYvhFBSazYq3Lqr_bjLl=AM|Z^^&RLH=bJN|5RQe`$gkDciFCS(kEf{5~ zMFKXB%L<3P0!Bw7w3SnVn5bG9=wwC2R3TL{5+b2f1`TAhJ0HLWk)?XiV=Qg}{9M70 ztsmlkp)OF#3|7*=@rd)Nf(h+ZR9x*krOISoGisY)h!&McXK2}x+-B=8g8tbTy2G8e z>2P}LT^C2K&-ZlJUQ8E;NmeI6Vs~}DL-V(1WaZ|!3N}{&@ClLzDmH`+3U)vE=7+pAm*dV)_0;V#$sI^f*fk7$@Zj( zf;CJZiMqN>$OM@aLlHR$O2~ytN|H#}cV@T#hE+1Sm8yWKg-;rk1D;Pj1++mw3$#fF zyc%qjX|XtPs)I0Fm=Q3lTHZ1VmRn7>AvF;V0Z~QGl%U>{)i5V&^iB=4`Nl8&le}5! zPA4=+y1SV2v3StKQI8>pUQSWUCerh0tlHs?#aoVdqOO=sxs!aqOmNV5X`lGmyKYfJ zcNut(;H9~9R+*QD?&am?wi^r%qj{e*q?|yF+vEl^0DNBZvX| z3q>Qc^K5q*U#*amnNwdaZ#Bt*xsc@8xI0!1n8d~o7kg0F5zB7=;9T~!yr>r)Qm(Tw z$#Lg?wB8iIB!a$E+jZz9bt}&D7x8yUA<3#0rSL8Eqn^;^gn`0(c^8IgtPA&5^dVj8 zs;9DzJtIH5^FH!R4_L9SQ<+Pw3?S8PZjLonfe01x(J$QGvr?77E4Yw`UBPMq0| zvkwX-QdZShz?;aSnDF5*zerV;~Ei*32(G9v25Ta^U{j3QNMYz(%Uot20e@Z1(u9X=Q5pnir<@ufx=p__NxXlA3u!JL(_%UWaR|OL`_pIs%K3eDe?ZpNgco8W zl)CRCuzNTIt%9QvA1^V<74dO2OreiE-A%5&wDL@!uXe4b=BM`ww|ad{`zOxE@|T>A z_1}+0F*5u^8~86RAYx+rGZr=O`1jbNbE*#Kgd{`@%lg!Dij1j4Mv3Hl?}=hXdWf}j zLViprqxbVg7=J_&rSkG*9maA{PmfQ}+eLFwjISyE`obOU*aqf7yI8zDKMb4YGfdPd znaqITwQ0ic2s@I^*p6#*o$5sqwRMj)`q|^N2BOQJBIkP96Pz=-_xZ|%&eLp1*phT@ny}i$^ zD^_B_qPafITq0JVG#_me(AE6ev0IBdg&R;6V0ms{4}DmZvf+JXD|y+fz1dW%g?rL3 zyBHtxtJq!;r6IYSt0nCX$o8!jhiMz%oX!qA+K?S`_UU^`$ztLZX9kC!%?)NLJ-L+B zDaBNvPbjhrWXsSYkK^F+BUeJbkJrsyK+@+%XD3=5@Wu^6;jtijb*}W>75VR6FP4(V zMc6s1DJuP%roJ-jFl@QqpbSC%8!I+u*IJQSMLeB6*rQ;38sNvCNrndPJK;<}O6s!$ za*15gSHIC$Tr2o=@;1|eO5+}cf>UVFLfDcz(mGi~HP0X^9ZsUTjQ~*rgxsO}>f-s8 zSIQyBusIycfEL_arQqWe8;@+Ko%p~W3oVdZ2%G_1{7ST%F=HhKQ`yydx70|0wF579 zpBFOxtJ}FXCmL%yfIass7KbybStZ`lD&B_7p9+v>inVJEuo4_v2N02(Wc^n1I3S^XRm4{yF4SnLNXX!p3|+vA375 ze0t`eokof005kQ()g8+|zV3xY2-$dMZ66}LMiJl}G(?ih_kwqd5l*@dOF_5=%?$x3?rd)0yOLd-Av3xt|c z5amy7h3zld3j4oJ@XLRk<)1J1{gc$Y92J?k4OZl?ceSo8oW4|($>#3vW(i2@xkA`| z{IqU+iYr>6h~(D-=Fi6*F%2w<&hdg95nsYEru$=sw6##j4_4<@#dLeNs~S3BNKl-|SU zJG&V@|MsHkPzE)e(~4D_MjCrGJCt#n?DLT?vt!{kdg>l5teFHM zGg74eo{XNAm?n}RdW>eXuyQlF%-PbV{q}U20nX?a1P;Yv483eUCUfhU++4St-WCA_ zK*-|`#iuo^M@WFxGOUy0zxQC9pH+?Wz+$l0Wjq16Nf)xv=@M^N*5_H=PG#C7&^MZ?hRVr>dIw$d1yI z3Du_;p%7}&7c;c?-{RK}Uj+6kWrIED;^rYz*|Gx@_)&E28J%)PUd5B_M{4dn#Eb`n2f9dL$=8TW&vdJemF=A?NwQXU znMNelUDx8m9v2~{!~DKW)VptpufMIVptwdI?PNQkriqXIn<4yQ?YYS};|wH#saUm4;R#F4m_c8me9YE~$iT0JZWbyoH6H-Ts~ zXMc(l{anwoAGEr8)wFTTQNg!%FXKUv$PBcmr_%%Rnw#VFY^{0t%#_he6Wm+Zcm`Gc zo-@FEk3%g&12Ou}tKGS(n}mHQI>!9*9w>D^+X&bA{e!{Hn*UEE3;7lhzPvNm3OpLF$3 z@c7QGw?BRQ7I{qZxUX9)c36STT$Xo`e+%VdiYI3hn;9#QfYExs7ocTa8iLAxMIeL z7NLfkWPwAt5(PJ$PUHwRh|R|%;PQN54?k@3ig$pAVQnCa;kV?1t|hV##}E`c4qp|t3))Rhb1h?L@{^_Yp-Vi#pd zC{pSaOn>+KV>_w@F09ep{SQ|Cvqcyo0hFRigWZ!#z$8tjVCHe7(p%>*dfeK@4v1a8 zjfuHKgF7?{u^r0tTRbz$^JveCHsn;_EMC`Z72WQSZa3_c#i-hq(vYHoNP$M5@`dhr zS)f4P-fDU6&ZPQJuW5zG(gZn?Jyw85KzcE|S)iCKA{;S6+)6wSlS7A{gkQ^8LzL}bP;k*r;g$g-5- z6ID1sd+E3@llbw2!C(_L$0!UH-mpCUkx35eRTdl8bx%NdJ5!edg#zayky5{2_@xRtz#9=pN zwED0NlaD1GQP}}>R#+?HC>cU%Qe%0`xoLW|GH2L6=Zq^6$JY{JXs(#pKUecNx3Z7j z8n299F_Y4Q`SXH)q0)C_)g3#Z(`upXw^m>+Qi41H!U?NNB+&h;VC;{cgcLpR|53uz zjep)P&Wd=jyZm|{?VAaZlxKcbhlfjq&)wfwzx%K?A`634p%cV{T@+GW49zoTC02xGsW8h+&EGL_OIf5BM1jT6C$l zmC(WK%)xGlBUA3miC;Xa0=94=st4g-W!Tkf*)G{NDtL5%Q&1`LGyu0pV1p$r1(nnA{3^i2#o<0hNmv{#3 z^r4w1%#7-hcw}TXoraK2|58Vn`!0bwlhq&(|aFs_{MI{d~0KIkhOr{;kpD2y1!; zXoq?BmHtLXpXr6%7pj=$%99;Qg{tV_-jxY@BX<)wX6t!n8uXLE)+^1&lgS%t*^?dI#ftZ$d}t+8LXQi`MLMX>fm)ekL>$L2m;W| zA6<*#FL8DT#{c6Bp8t78%Om1!O!8GLvBD0&>B<4K3 z)*&EXJ#-=j(QEePRZllQEGlfcp`NiD9OL9RId3$JN>-_+V-QM!RTd!G;!y%8C;G%v z`%gBYxQX2MdzL@w#&B1SrYYD%qYZ_DgA(ED%^LRmNZM9kKxs$o#vQ8C8yp^8yHS3iT;;KF>b&vjOCWXY_pSJ6gh!_P7C~+z@8B8H;#iIpppk41 z`#e8!qZYyaDNSU5+Mr_YMIx`LP%z^iBHmC!HE3q=mwUr+hOrc=OTmhj>CbfG$92Jt zD@fu=y}rx18G_69*M&70%C)#i>lbFDx|RI2UEb#}O|5=TmL+)X9$z9ujG^&Neqwv* zu=RHX+6KE>o};2ZH9I^&v~Hz|FC)71YFP$kW9d2}T@+LqD`H|-nXD=&$$YoS^hXQ( zB5qFpeDHAUzCgP`$UC8Zw9-Jhts_J66QpL^BM_6Zsj~)a+GDvw-Oue|`~($&<*dtSm%GZfDxd>?kz3-MxMV?S zi`0=2V`Q&}iRja?fF2#jiZp+nJ2UvP-77x|fk^j0@0Y)#wX%7{gu;K{s{D3mN7c+l z5F{9o2G?{mv8JeV9DU93K=pM$*~;8;;hw9WtCUj@GPH)^*3Oz52cspER}-5F+Myc2LEA5d+U&w7$Bf>^LT03arsN1wS{3F|fCL5kdrA`!n@8Ld@$~M9?U|;C5C<_QOtSm@Ih+%&TZDH4%iah~ZXsH8mW&S$z{3@1W zC};3F)zpV!Bc#9+YubFgQL!TnQJuX^r>9_YYO>Hv2K!LseXnGR0Oj(Kuw_ga-{oO<)x z3X0!$i2ckGpX|-#8XaC^@)4MIYq-Ju}MJ4Ccr)l$iRE2{N0La#^GmXf#Dl3KYeyv@a!HGCgbQ!i3ci=U{ zGy1w7iC=67?ACdOW>!shfXcNV@=l-IkzgB_iwGV>4{d;b?OsKnSzXIFd3JP^Ok z234ufocbkA3z(rdkT)1i-;CUcIM;GP65w1@rJ~%{c2TJJ0)AB^39c;zyu{KlI(bRL0wp~Sj zA)-y@F)D80^$#m5dX~0?U-r}D@gO8PNhZoJTqua&imf}JVKWJssmcMxV+|#ZGV!$+ z29!7`!}_9TYJ>E9ph=>hk=d39DLH!=59mwC+<_Zr(VTo@)097I&teujzHS~~jJerO zz83ql4hH+l!0v*qI|B&ywE5q|`=5>~&V7M(cYyrhx<1jAi+n3VaGt|MIn_3bKc`t0 z4Vp2@!Bqf?d~J>Zj_}pi2Vz)Y2*jL`ID%@F8!NnP$ae}xhN&nLMw!e~Onw-ZQnH02 z8kw`a8kI+e)|FT|RXZ-7AqFF>-Y9#I{xXR1Wf|6)(iXVxuT`AmEfpUe1rlEZHF3&S z`dUZ)xI^^5iL$CSuxk01Mm&4OfcL2hAd@r{YEqg?o-Ec@++6+UY9c)L^!)ioCH*w04d(!9xwA7 zv6R#<=&!cNzbr#a_1btAeD2veOKral_7Z4aDbk&v>pV#6N6+OmEz&Mul7SnkUa8Jw z-voa86B+nR@QH!--z74hnel(z&io%o`{&Gw@lQr7RBhx4CE&kiYRfjX3$w=PfxtVm zKK%>bNXxQ!bsbN9%uO||?S6V)pvn7vs<^;~6Inko1DJMn>gIapR`^;H!yotoezH1y z#-qltN8V1q9UQlcmZA;MMJ1Jife>$9y-|co6y*@lBRIc_y=d^0aYVoULaNS{#;U$I z5`Uxb7Gvu!0{)r7hCRr<)k`i(16f0GP=W;73tim4yMXzkG$u_meR4*Wc`BF)j5O_v z$0OJHiL?nS7dv=%=?<7U*zKqZX~b?Uc)xT9c*#FLMxBqR-G_7rwCE&TO9=)R?=<#H zyEyP9J}Tpw9z#19`t*|riM0@Z&S4>9{m^|#zrPtlQjjZ>A>G==9}9{@NUsatEoTs& zhKEC7R?(KTG@R(ACObf}9mEeLY9lF|cK}sKqwC!HAoJZj&LmSQQxA}p0UL=~z1y@C z%f(_gsQD;O)v8@vG!%sim4e3)&Un%8nLieRO+2Lw&8c)HSISc=0QW~o3Ph9vAz|CR z;~Bn_J>3FWzYF~o<>0%1q=xYEHrFPYEkFQ;Q>v$wx`hg|wBfWBhN%~zM*s!l(1!;4 zb5v zUH{h(cn;=o5K;8RMnbeujVtB_8sUqmN|t>P3<2|GTJ*$hzO;72d7rWoUF*K&p)(PP26pn#hQPdoF4f9I&g|JZX{}6CMy9u z!Sy2c&h|;w$*XaqhTv6}It~$*BMs0Q zEg{BPj=;I5#!W&N75K)qQ_lAb2spxh+5i z&x`NGtLGf{oPBG`%_VuYO8WdPF#GIPXw9nd3*-MP|Al!I=ZSOl4KvcY?szFYegR}_ z=aAL%k-kH1Y;!Grpc2NUOp@!qW@&q6zFh9-5TvZN%wmQ?p3!^JRJXKLPfH0Zpl5}wFq85(9o8B$ClN8z$^MrJkA8#7+p7hQ0*@bJOX#ur_VDKW@iTC9<| zuuJS5@7oh*L}?Ca-q3?}8 z52Or^9^mB|&%uet$JPV_B*#aC3M_D=&<}3m2R7loPqWLw$u)T}T?hA;!jIDH6=e0B zgWqpr#p>s}FsY!069mh55-2@fK`B5;@3Y8!dm=;fgkx z-esWa`Pnq`9SH6zm!Hz$KQosSO8_4DIVglAp{RAb%{zr>XD1hQ>d^@_I}rf;>Ev8T zGn?;TL>YCuvEo_f<1L4MKZSGqmh2!Sc+0)x!H2$|YITUkgH_X-9FKIj zCr9Aa%v72$AvD<6_;_W(85GI2f$#Ur&1S~E{t3%vYWMt1!^_>sK{L2<|TZRrZ$llm6 z?#=+W53B-b=^WK+!18UGW`|h6fm%&6ZK^brqv;JoKtFrfLOWwXQ;SOnZz_Y?dEjP> zPi)ab zDT6<++0|m+i*E-)i(R*TOi*yPZ*)u47^|;?IYn_;3_NF^paEWSICPf!eaZw^aqCM6 zspA>BmW66^v$Lb zS#65vM9uDWmqnt-(5Y&UGd-dLjfD457w6ggz~TW8L<8ZwrgGL>7Cf_X);+}NF2jx$ z^>`$mQ%_T-O$K@D1dWplBZ0?iQ;vLvV?<;V`Hc@ULhMygf}dASMBo0}xuV9MzQ)n{~olViV;O+nKwPQTS8sT$zBpyRJmRiITc2CQTh@6NvLg>{9zO*RZMoVcek z7L!_inr3SafzK87D#D*mlAboxlauzxb$j{vbr8D){QJGt@H6%ITUzmg0TO!MOAEn2 zZ;863wbC;g9xuU+ejCWzkvILi`D$S4fgB|=jyjB<1Rs}Ui7N-~uPd?haTkDbT=I`r zn)2d%qKo<*JiX`-mI&)kGzDetQ4}|z*FmnglQ%AI?cKlJ^ z(~l-wIO!d>2TM&_t>GeUIK(HbgPkEG3TmXM)@BI5K4Wqk=Xsar)iQ4|%W7IA1vQsBkU zM6QLg6@HTQObY24Ok!Nm8boVoB`=c<3^5@fCCTOGK4yZ$NMOXlO|N-#cN2dLmmusX z5L~R``pz2zmyH%CZ!0nwz{Gjv4U8h;P4g$Q;Z{0O^HdU_oqKO}JOk}hBI?5tY{+4I z(}mO`n$$SR`$DD&`eK5Rd1GF$?2{XA47xpA*eLJl4oDmSEbYu}B4593*6X%B-uj(zSgZZ*hp2Pd)JK z8e1=YmcnA46v$!C0%#b=Za?=xuh2qj;HgX&$d9JXOZfT+@{V-EJN{cD{K#I%d8HoJ z5Y8{CND^KfBF~$tN%OFD@;~Ja1VZ}6}65Nv@O2NAqlcqEeci? z5$SQ>yY$FE29xL*>W#uVv|Su>46Tl#bK7D6-Fq+UB^_7R4AieJJ;E1Rp8Js0)zo zVnz@30-%;u=fo9c*w?+cSjAPgZQHhu zZ`rO|W!tuG+qP}nX7AJKbUJ;0H`zP6H|IZ?nVBSR^)|$eeq$Ts z`YMef>)^|=;XJTsE@qD|06Id637%{GPM)h|;*AJq#uoPSX2abzf9NePN*~=$98zPI<8HgB`IZsf!q1FHAkU5v&BNe z1K^aBC|l2{;(-dQi#m-(m6`I4N~01i=b>3)EHm!K_tUjdqRTDp@bG9%kSSe89a-I9 z6ZJq_SAOe+mh~iY+USx-+eNX-_I=trVEQMo@JwFVIkk@+(>~SGXm6NZV%<$MTpJ+S z8+L!O+fCbr)on}}hgp1Ei4+IW>c@LHG_#cSy-)Wl;Ndz!sNLGzpPc7|qLOeM%r~aF zlni!~tx3TA-gal+Q$4t}4Y=b_vCTLROyTmS#mXeHF4Tdnagdbm`zqV0izsFOrn4r5 zTB1!vbCHrVdhq$}McQy_dq4;dH4Z2Tr75~}a2tWp(Lfn~*SB-q@9`@LQ&cZX`(36o zx(GI|ObisXVkUIv(v>&qThPzKPePg`ov*#CWED6*NSHtqo$UANNBYtt=4eYDQ@DdA zo$n^uwTI#elc2{=)FV2XZj$t-VeKtg1~jOD=Ez2d3SkM|UpoG-z&P+2-r-MLSgH-J zw{GDfH1`C022HJiT%fYQ#~e~dU&J>^p0D?toh}Pv)1*LgtrKo)MQi@P?2NxhgtEJjtl39vmA{x4ESIcay#afV7*Dwvse$ zK8D9ucaH)+TbU9K-{iNYd@@#AT0YXC@S+NH;(FBQ(AS5mLYk&}b~mLth}1?S*X;w! z8<{9uFLwm)=!DhM(;)epsZdYF;?Yw_STW!oWhtX;v%lDyVE6r58L01bY4f2gy zRB1N{6;+a#={+{6TkGE+jNm_1;6}|su_s&dmP6IfSg8ugxuIr%1ugm5eG(q;ZN-VC3fwH8(#*Tm$Q(oq9OJmn6q z-Wx{pXu9^I5Gnpl&I~~|P%0jeTOBS(&7IIC9ov9jn-DVQBk=zT zDg2GWoES712RD*IlDE9lRjRs(F7|g_yOzIOWlHpXk-2>;PHM`3Qh~lFFDpdgJVIox z>+$liIN!oXv1xP0rYek}jfnr66+hE>E;JM!qUa3`juxI{D3KBej3WgbUDH1TV4cl> z9khm>RM3-JD|)eee+sSw6*F>tFGge35oPXD%Rn;R41ok7GT1#h^R|U+xeY*p1xZW^QI&UoBlJ3QE@HlVU0&xXZ!q!dF{6lKwLx3y=P=Po58rO~7+o^jFUQDeg z9K?Y|i>J4O?i3fF^EW7(6Q968sL+2DXE8GW&o-?wGynfR@V}FDF|qtZUA>OHjBNou zO6LRBaq}9;Flk~8wpJ03$~c;;LJWMW4rPFb)!_5a3&wnDdF zMYw9LZ~0onJ;EvreQ-IsLPNP?#4Bh;sj4z}YB^!)zuDP)OOuNjvo0Vs)9_t+Fogwf zg!3>~CyNFN0}9$WFbBp7A44P}>zDg7>%|WhZhgqfBmVV|E>fYU9Fvj-3bTC13$8+@ zTf|xEY-6~DC{TKA1Ci)Eoig=-0CU-CMIPjCr%HdlK8VHPT#R|UwO_KGC5kpMWGJxvlpCN_ z8!NLQ)qMM#6wp;gyro8%0>#5TE|or00;Pj>^0q#s#+(JvU>!SNfbsBbwXmM7KfRlZ zX#5MJmQ+yH*mSRpb_jQ57ZXTZDnG5&WTB5?s%BS$`{q|5$;oJWPco@YnX)cHDZRa@ z_z`HAcCUCEHIJp3UDtR=Tt0qj948u#R^#NIS-gnK=h{ajqv2)-0l_7+7o;0}t_35vm6biuN>B&jGo*E!9kRH>6Y;s6>GPqD?jw_j7RR3&hgdzl^o|=9W{#;pr|# z2ARVt!<@4kLVBL{_6krGJbf-S8lxEgvSXb$5#J$1|QU zbIkD|c;QR2-nqHhI#$e--LSLpTI4;vqQyob#%4usrXUCo=~vVaiz7|V355X*DnDZ7 zzUBV9L~o$k4O}i(`g@zwi#+l`)08q4It4h?6c@^a5Gv5@i}ETx zFI>6euZRoM9X^Bng1$fJaUwYkf^jCJo>aV!1tJVb@F|m(64MdxE@D?sp&Pr&g`{h_ zhCne3Zccj17%<3IzmdB!VK-PlWv#jdM|M}Eter8Au1JqjbqLr-PX2}7oazE29-Ia` z971m%fEfIG5L-mR$g|q#Q_K45;BWv zX9vjuhBuwB&)KZZme_z6>lX2YH^APUa9Y6Gg#^_(a|B>+?KWZKdO6_|Ha%V2KEueF z;}a?C<6NtJyS_H+fzNe^ZPT{gh{iyj;W`u7$C4<#hEqF$oJv!lF+@mz4h((lXUIl z{o4L2{_6Ah#qPu6ttWvZYlgM~W|LiO`}_5o|K^5wZsf)_2W?{Lr32#q^9$m;^T*Nt z1t6G%hA@E_fxzcJf%p0RwXpxNfACjV-@JxTPlQW<{cVW5NCVq5~LBTIE& z!CG9I=Bjc{T_L{C_`IsIk?omo-BzW$Xj8dKK8Z*msmwmdMf0#eS4E0F;!DSJ$waH+ z{K1b*s{kg{Azx)FSXrjX%$%f5zPj0BX)$(A*)woxaXvYE64R%5nyx-x)vVoCRr6@< zGBTOn-2<KBtZ2n@b^q2lcHs%D>j zZsEBE=qUMqR45!Nzi;D$}Pow^<%26Fu+;aXpvmsG~{VVRwH&K;x zk~$G{!Zq(j2txU|vl9OwOJ+E3<)ZQfmnD%z*^uE(lbD)QReXF-P-Vfz)rtJtd3)i& zf`w(~l0HV_$EOTCmS&=73q%agRx=b5WiYw-!qLq*k6Sj#MQ^z zq7Hf)0WNwpH>+96a#2=6JF=*D`7VdKRHUV&mhf@b<)#8b@~WT+2C~umfy#$Oh|M6; zmX_mlNpZ`@MP*J>7FSJ<@MDyp`xYt%t%@EvQnnu4N~5z`gE8Y+9jJ0v7n0-9&YF=t zV1#0u?w(0=cv@+<@MG3kiLK~Y>KEB7A>}YcIw@9RncvJ&B@pnbVufU3yghYi2OYTM zA8@l7!^hIXkYMrP93Z}qV?(2WeD?h-_AV)n(&9{d7H$ezKQdT=ZA zscA}O1XY(w37d&&i9M+K4Q}oyYQr!H!T?bOM;c|Q%iTF$brkij?t-4eP5UqhG^nbs zn!R)wRu69@q%wp*Sqr0)C=WVy4)y-B^kt4(Zh8t^I9mha$?(F$&?rfmxs3f{Sq(3~xL( z*j1Il>E1PQ5+((Xz{O&c!fc&F7V$Q=>S#X@y|SZ(T7f&TE1>hT1e6j9C;~#FBdRGA zSDuqe?t0^d-E%P^G*RJX>)-Wp2dk6d7sR63U-5r|7w0FQMgI*m%}`F_r4_Ll8c>Aq zM~Xo!?Mb}cQ>-%ij{9}z6ItG(o64{ z&rOnK?W;eRdcK!AZME?FGtX?KB5r;vHV~V?8?2n{{}+fHjtHm4oOJFBEef0lfE3;= zhF!!!tHK-ZSQehSpHpdfk!{x8$XO(isNBkp>*c7P!rx1P7VpSW41LCqg+*BLQKQOGXa zt03JvDfkEUJ@C;Oqo00$ap)u0_~4eHNj54AY+?Blqmqo|h3?in7-;`ljh3gUdkE2? z@W$yu>Z(vTB&`ks_3|mf7cZne5$f*F9?%PsmkOGHq=_9vI&z$0GyUG7z)j^`hZi=) z&q*Az7=0gmeUkEE#hanT2GD&3*fC@bL1aL%SWtT19ImKfaX#kqbH_Z2WXu7V-hKvI z*9oF_^p4eG{yw%lSX&*-?i$3d#$yn`f9BJI6=%=fxG^iPN8F#eD+;9fs3>7~HolCO>(r_6hCSIYhQx?dpom- zejJ^`i=EF(IUN@!$~MdU^$;u!isKoYime~bEMyx^JD+EUji{=8dSCL#K3CvUISV?3 zh3cp9)HD3{y?Dxz%Kh8X;IdBvJ*2ud(rAy!UxnpRn9u3s)4)&b1~P8@-PELpy)*HM z&fF38B!s`s3W!;=AZFO?7VV|koQCHlP>zW0Zei5QBWX)}(#-qd>h<;E+i&_TqZG4@ z!2i)UzgN1yJ}&S!LJqXLHT^x~WMzTP^XbQDy{)}_y!wQV`KVwerPHZ{`|W0oPr?R+ z=O6sUf0Q{g(f=Rt6aQ-$!Srw4>0@L0haOvXng3ct*!7`yNiz*Q6xvLy;Vo13?QMGXCVIJl%s;Z&h3YJV1&iwZ@#uVGEz<;j!pTo< zn$H4BBu^9IB-qp#KWJifBzg;#79Ys!wuO{I{P`hK(WrFg;$Y`vW5teoX%C*V2Jq;k z?J6p%-0V375kM$Dw>Zm6u#7^*@~l-RU(sy3_B3vyR#sCoD1=eaC}P`AMQE9E*sosz zyWbVlw!yUR*`gH7QKoH5U|{@7jkc&GHD=rdlHH>fuWJ@TH5*0?xm% zW%r%)cMR`OjA6Xdtg9wY8eT34)iSpn`TcT?z1qv56RVy9ArZxbQ0{x z;)W=lQx=(-R9rp@U-~ty=PMjyyM5SJhL!gsexR)rOeCkh7Bhsy+IbDeo z6tkH&eLQcPI%`vLPqUO|Npxe$(ckcjkmeEmxHMz1ve;j4A%{bx2QEHhFnfL{ z?E2=2NHS^kZ@14-Pm@|K!rxZp_w=UvVXj4g3&bv#jWgO+Xa3 zYE|mPQ#;2uIJ2_ffsUh8iUfx!9;8^tTJ%EZ5w0x8UK@8vZge2;?}I`S8Nx1}Ibft_ zuuLAT-Xdtu?5yN`JxCH9kdOg!eU-tPv%LSZnSrqgn(+l!5o7(hhQYnXlECmwv@etc{ z+2M8g#HA^v8U`_R7kV&7Ko1tM1&qI3*<}fs!bA?9MZv4bQL9}b4}wv8*u@fYsSm$H z?aC%UBh)%W+%YJlEWwFd70r%2Zq@M9rMY$NLhu@^8%RNz0F|MwDpME`a&?YC#WK>%B(wT0Dl(gywgz%@-(pM=OhB9(Q25Tw(JuK=sRZt=F@4Z?hj6pZXP{DLx1=GE5a)nka;l2 zNv-1Dokj1{$T^Q?^Y;>j#p)HzsU#Eo{x4;+si5B$L;D}iu%9uO+7PBj8 zS?6kCKK4>j1xUW(-sXa|4C2dHOPUPnu~Cwj?>c_y-qX8b(p?I$YSf8PJt+PMiKJ>3 zc46UQt{y8uD>-cgB)o`0G8BBZjDrJ95w<$sGmN{!4vgY3d~O)IwJP@#(^%^KMUMyh zdnobdz@22+^%1w(+mS>$rLX+ey@e}c7CKvjrZ!+RNGcQFUY^gYuT+JvMCo#QGftjD z>CNst`P}0WU>u{(0AB6}S?dT;by3~C(twr$A#~skQ4CYDjyfHFU6|G8NE>iI+@0k@|iBQL_ zIedI`=sAW?A9xkxjEUb%9~a*}8ugdX9$r8u#@U!R-QH~l7+(}lWOcn#<+`E3NF%-h zFZeuszbk2vzo*ugK7;kTG+(h?o5fGo{Es~!_a4;V?LOX~Z`g89CstZ=c)N){+rB(q zCu063Lf@Pp=#QtcEB{@?nf{~Xo{8~)=uCj=-^%4VSpU142dVwPYJNCxESgL*ayN2F zywO-yMpTBR!^YIcPfVOg0)>WOb-MFH!>@>P)SM7NgtQvdV!K28!;3Nh>nGUBSvH4` zLQ>9VAfX`y1{0n_`>tT(f(qIQ^AREdC}?ivu3W4?K3CjS^;>70I=)ctTEHCoy&-a? zY!Z4tSU7&Pi9B)oRhSmqyShF}VNG*6MAegiBaW7JJ~poZ{8H)lWXxAKBfJ@R2h}ASdgu_lBVeEu56@lFdT<~kw~Jbt(hHqgiB{WCT1hb={Ti>QrgkM`o~H_C}odNZ?QVkXsz!^Nh%$D zs)B{-E!lD$DKE^L%_(tXD=O7ydJ7G-_{w9>U$8KNR~BNbMF7Q6>GOF~u5N%h9r6*C ze%WMfeZ%&h#+xAOzAA}>Idl?-*|Vs&$r=L?`=Ih=DKZhftLIdtE>;}UE-2Ugqwo1d z4&fAXZgHxpigf~IX%%h4>Y4~Y{x6I!WQjU1ojiwJse>v*jidWVoE&mq&;3A?4y>q+ zIAvSyC~b*|-n-miPN5QjsTxBgr?zdoXq9(ufvmkHRrX9S4pG{}c510!iO`HW>y+kk zD~h&Y(dtNf37raeg5 zSN^Gq@QLe`l`={n(jq`;`89nyma&*<6i?tT2^6JI$+jvr7#|PSYJ4m&oo)wLqmVs#fwK2<=)Hjqy6jA~Xa2;-+t9 z06&&>e2Upy=~>?TYJ<9Iw_;r+ zJNqaiTPwi?zUz`hMf{)&KVG?gk{Hg1u6PA#X8UsNxaRCvVfpcd=z(=gw?PSDLnki0 z=e62}b`DR0a4t`aH8?>EpLpj}VsvtD)C3Zi=>g}xQB;2Fyg27`3Pg~gjVT#{ii>l| zz7`>%j6%bLTyUdyQGg^3XI7`|d~MUB;pkdijDp@949(4&1V-cWJrWz>~*evExhayEb`8V4fG}uu;fookGaB8XW5)8%0 zHo@*D(nEc!3vuTHvC;$>Hr0wG<`GU5saXztCdz30HO`P&3+dTK1q^G5dDG^;%Im@m z9ut;GKmNfa+v_ZrXXL~od+oCQVptJ7Z!McR zHpu4dD>R1B;zmrF_XERlUz>a_mEO$-i$Cv2dm;3W*pD|HaIql)^Y)wHN8PKLk{TCw zM>ySSK2wr&%NMHOTR3Mp?3~j-a7{IhM{OCB*UlHF1c&m+*(%s1YBf7!j^Q(exR2Gc zP1w10`(BwtstcMCgYQK!{`%V%ydPE24jSz(p8|dg`P+!|8BQ^;9hNG9_4^I{!ONEk z?eYwrX&X@6jO(JfC2Z^J%C2vc4oN}U4?WC19Qe-gOrA|;y{nP|tWLhJ_Pb~@B@djb zlLCp?tsG0QEw;oCxNA|m2;cq^Uz3Nk1JB2(VHgkG9k2uuJ2`|0{M<8;EuN_37=f6X zDG=Vdx^0`TvrcPx*Wzo}Td_aVg6Uunwg>cqR~t9X=~KHFP9NB_52sBrOs;*@mw!CH zph=klGc`tm?T})gf4TEk-q^9_aI>B|&MrSZKVMPi7areuQ|Zi@+xUdYulMIl_RMgj z1HeXJKVHA-zYq$*kUsfq4sOlgkyyShcChQW{&&(?E?<(*bdP) zUl7l>9wvBzujXhjWr_)I!NA$kWN`|g)?CZED=R#8RBYXNFMW9N=8xP}PC8Q7{AJyR z=tvUc`VXN~BgjtflFyEgMtoR8jKhn7Ts z&hOK~uelyz_@Mg}c4WVS-j(5_{=uL8M@$D3^Z%4T`FGe2R`!2bR|Zhlkvrgr^}MOM z-SArsF0?D+=EN$gvuVJ3E>I!SMYKaAy~V!e6JW!W2J3F&2}hY(c`4Gn^kPhM7NcwPNG4v=GP_@4%l!QnAxXyDVr)^f0Vj^E{Hw9$TpO)G)?#I@kZMMzm;OsX$ zUvew<;$COj#~}vu(AFJC$$luyn&PGYB(ZTpMI5V`Tg*#)5qnC^$f+ptKju}V3jAC_ z?6C%41TUMRY-X;k?c~R&!nrD=YYe2h(&51GnY_gWV)ITecn#!(kCzGYApUG*KWSlR zX9`FP`HrStPxhI2;K-Esuay!7ARPAT=>@z63>^BHX=dH>Q5>YkEtXB3Bx+>`vzMwu zFXAtSBF!ALcZXirfwlMZ&@}YZuO+NEg!@xxPT0)5s+1Wvd?+Ejl4COma}p7j@zhq! z*g@wb!C|1=8)q-RA87x2qZMdFuBGEQLxKtw?m!-%%eq&3_zmZhz=fCUD%x0afYklg z#rcb1XQO>u>o&Ox+HpgU8hu^b@FJ6RZsAk`pO5?RThJGT+sCWt@3*_7yP1uPtBrvV zDzm}pd0tl+4PEo|Bf*%NiirG5+Cv>OF{%{4VR>E2ChDBWt=P$|V8wK8xo=?hCuy{Q z_&@(62!`o@9D-r`w;&i+CWe22U}TgIL=n3lsNTV~0G-JMf8vql`Qr@Pj2YI}p*bRp z>UadQ?M*~oK5rh{#gGJJWuQy@m!*4FwrcnuS9C>*K8=|%7UrOiD!L-hwnr|Q#z~p8 z4#vjJMHl=<2jam1;71bnpscVzi@oTl=iT`E)KryRT#}0hh&U~$aS>wPE{n8oIyIDU_8?LhE1b*Dx|Q3Cg*-~77oD7#F=vBd z;%>Y+$uOfDsJSMiMH7H{cr#xnwXGX>IBHq^me*^fBinON$svRkn{)dEPp2yVtuwRy z=ECtXaXgAQGxw29Boi#Lm{DnKRM&@r_85<(0O-TCqr$`WwDFWuElVN?YwS|?pI+mt zw^%9Z$HO7wx+$7qh#QLxXw-0}X=>hLY%i`t`C84JL?X?aQ;j1_3{y_kl!zb!K?{D( zq_kQQ2gAh=L3L4ce2Ty`oNH*&FS->=m5a7RcJWBus4hsM{EjE)L5cEa@e@8l@FoUI zjRhXVDOybhSryza#tc`WcaxcmL#S&*o-3}MS^#__h2D6tOgh>+&D zc`}|@4d_p>gTp!rJFZz6v6?kfkP55qsPrqGY`v>XeJa$)YJjDKA4OxD9luuCi1F)D zzn~hxF#kqTfUh!Y$~1)UVezad>zIZ3jct3M{I6D_N0!1b@XpamFmucP`?G;vu=NY=3^=SR&uMuu^s+$ryn@GscT%Uw zn5+uVVl-Q|cphN-;WvK>_j^AX&3ccFPL01Uw-%`0lH+EPd|EBm3eY2ve)h5PE%Po` zBh*hRcu!jX2gV+> z?sWFzuEESQXu1aZ7=cL6L`?i2rHD|O>IZpgY4gHLY|O>-5Z^omoeRn5HazxSUX#WGfExp#PXx%^hnfgfhyJvOU$PU?a!!ri)>Ka^5X5;tFjY1CZH_rFAW!elw6 zME`>az(L$|-Tm0kN&%uY{IUQ`T@HNs$a79k;f7S=)LRfrFHcgwFzKmieHQ}tG!uyp zZgBSMNjyo?Utzsm1jov*T(_CO)9z$AHEPI$H3VM-h;IyNg6VFxE4zca%^hvHsFY+^ zR4-LX=Xy9w|4r}X4f9>W+RRO2L$Cpbyuert)EVi>A4ld$JL!BgK=8}MWfZj-dm1Ra zAY6R##>-q$Np#+e`cv~}OhLHbg^6XJFw`BI1w&lhVvk1Xf&!(=L%#Bv`uARq23fxS zZ8%LZ6-C=xxAQ{bSW_wauK^WeweO0O`X);={V7^frI-yVl0@lM{&+&eer#Ou_ixBF zaQQyT61_WQoK`vC`Gb1XPOAQ`@fh$$umoQk$rp z`V=qy*v7YOj>d?vJpk^FEs34Rk4jHrYWCZ4dM=bk5A~F*Qfow9Fqriz9Z{VElP+E8 zfj&A7?nrrTg)IRK?^pO-!(3zR1qoxV-cX*MKD~c8$N*G2hSf@KHPC_S$YJ!kA$L%$ z4y&6ynUT}4=RbdCc(Sn($jD0E==zez0(;uiufN(~5ZcrsI{!gf|07t3>3=7z!-oI= ztnK{Il=a`jb~yfF`9_qwj4c-1e;v`mI+cNphG&8{Z)97I$bu0^TT($n9|~SMG+DJ4 zN;*`P_H^5he$7joMI6?ylW;KEZg*n5*CaTmAM9{+b?yFWI6E|OyL`n|V zkUC%6&rii)cMlRJgO8)g$D0JkTb;vSX=Z7mugo>3j~QFz=x4>3 zfw}lTpt)!?=550XH)EB*+1SZ_Ml0bBi-@j30nM5eC`0TP7u^GZ#YiPO`f%)xe1i~R zSoXhkwLII{HK@?|GPjdlc2g@F9Hh%plfqY6Qn%4brU*xh!ebj%j4= zwj`q$qO5hKYS^hIl2sG@S;%9o2|VI#qU95Rtur6{%Batz@>y@0mNQXh$7OfSEG^;4 zkB03T*R5PD(Lie@kD#U8b~z5g7V2E-K&4 z0KDLdb?9N=qGjvK2#1_Q6qWa@N6Uf)X|$Pjm38aI@=9gK;(&;`m`JY0+6gZsc1jtj zrH}?NLqV$w&PSxo=<$qq&iWJ_bPeUueA%PLVjJVuvE|DRD#JQDzjywoyG9lK&|~;O zeCR!axn^2Q8$EVsynG`bP>wMaHTe3gf^gV!zX-O544q0ov|lBNG!b}ok@Gv{1_n*d z8yGy{IDqsrYI!D7?|{D{drj7?7k|TYp`>uD0wDsIVT=AE$uv_DLh48EXfa0c_nk@B z?*u~t`Px2!Y*3eS2Q)e_j+qf!cn*CB#DPZzS~GquBk5_Ms{~jZY2&GLTT*iL^xd^?X^7& z8*_nXH;*TD_UH!0#$^V?!9B>+z0k0W3#&d$plCO-2eN7!^Jq%Tj>Ply=QgHOq1bIe zrj!!Y$bLm-rN+|Rd(=raK&s$hN$FCnUP6?G!uB*Cf^C6702EAV?n;~@hhaZee z{OP5Cd$tgDoeg*4monnd7Q#z=laGc1bznSRVv%XLC@rKncj|pJ*EhPeGPrC413X}| z9}?cy4uKF-_cH8p0jHyzqr~UCUitRJ;>p#96vT+dQpi=l*?*s7u4RMFaXLjhLoacp z`b1mI7Xo?o%ixtW2F0RnI%wACieNK>3y4~a<0ggL4&^&A*Lhb$GR!fx^A_{ty)dMd zm-SvtWy0>Q=*vcw5If?C5m0RC4Z9Rb4vz9m;6Cq92ftj!vNVFQ*ju-&q&8pk3#-!O zlq{CY2|3$n(6e46#zb2q{egP^eFjv@k?O19J16^8FxO*Im%J(J6QC`SAKqIa_ZO54 zu%+-)SxI!S?CIOK%YDt z-E;6jK(O;v1AAqk(MC(k&)QoXxO?HcrE%BlS9*17Cv@QLc`gRk;J$%W@pIH(Xx9}T z;OeQO$FcF~7m-yfUiShEqzS9D9USMdJNQBl0P;oJ-R-<;` zczNAp^(d)cLVM}-Dv-}Q0(;w6&2d&Z2^?)2inLoRuZ_*kjsi!j zgjpB8_0Sj6qQ#7w^li^?8{Q5NM_F{Wxs(mMm>DP0oWQc8V3v8luufnY4J`k`&S|RG z&<2;2wWCkdZ4dXMnjP)VEFB#kL+sv)SJRB4sfDKnyvM!kz3a1gA|CIyx7OC7i;a$u z6RvHC7VfvNLp-5Zw&Z{CAO8{D!%Y8w)PMZ1T?g~Oh54|uu>M1fnvCrRJ7U*~+N8Bo z@7%fstL(axQlW^i)tvRFke{|$SbbZZa8lvr>CO#Sd_2hzP&+x|A`-{L@l*!F7pKN7 z_77SkcS!`58(pXLooq1iZN;I3=ij*dRS?*t^qiTKuqKUP?G11&S!L`E2-faz! zm#asT*8bD!x1O_$>{*FTDGE(dyN!f024I}CU^yzGF~Ni;lk%-7KG{juhKi#7ePG{R z109L1%0`;r^S*BBUodQ29t~f}(h#7lL z_YV=}ig&Ilg(bfWp)+xK{|I*Vn(y2wwrl1v9Y8>gk_t=u-SqWleH>cXiT4g34Lq9E zDFQLn)ZMIQb}9II+&bivY|bHNjW6a1L5Q z@4mw2b>Tu?JDUx4QTgCsFYDY3n(CpjrgmOPg3M^_?5a@Bev{nfv!l_}T+b#MlnH(S zGMTeG9#Kv-ME~uvutBo!GzSHBnW97iTLQre%xcD?uC5cQQxG0!s#h2{{iOqPtP8}B zBoSFlG~cB*p>bkVkfBVPCl`ZF(Zn)CS_*+zPzLIUr${^qufD%G~r=U zCdQw@3~^q8&O!{I9Y(=TdanXOyi@F#2%V-)T9JY1O1YY&-O!y}>=U%R{G5B1f-a5s z%YZgn7IrTvjO^9gsZcs$SgNH(n|#B4?cx`p)+PL+-L9q!jV!oYUpQ6*#Z~gOCyw@m z-7lH1J|doG$!*K=N%dr9D}}7|r3PEAlvcp>^ct*qQVmA-QUn?@tD=4bM&VBD2`GL~ zM>2c=YyOa|vMn`PNX*>QR5!8dNm@FEFQecnUq3TVvxnNZ+9)bPnW-F$TE?Jtq)Xs9 zU$BS8uVa`mNO#U0#p!_K=^B}7hzer0KZ7z8ih@78H=Y`Ht5VW7Xkw1dfCG!c+oYuK z9}t4&sR@{sqz;ZMYszwgC6daU1(T$p9ObbM*RAr&B3tn!<|=h|N4DX~@&>1UBXqNx z4qiKgT0Uvp69!J>CkUlP*fqiDukoqjs zR>K4_K^ElmJ8uLk9|2#W%H^EN9nyoF92r9|dBpadbVGA!nngBBS2{} z^uJpV!PbZ*g1HRB62+aPe}_vZK@17z%(S&9&O=;=l~k{7q}A*p>`O~4Oh(XxdUId` zxU!-thqcuP?CP;?TP#lc^DTGXcrwM#n1!I!KEKaC>m(rrlXMsv4)e!{U2F_@IcHRo zL-6XCQ;m+Yd{d%y)Q^~a__ePDbiW|G1`TwcCaFi6zNKb%#o)pfC@*{1bsh(HW1PT9 zigdG|rSuUQ(JEWoVU9j`K(`3!0^WdHa#;hd4nkgFt0odQdBK|Gr1} zLK*3;8hm)DH4`nipl|;jyBT44~u3-j09bJe@)_VLWM<+H)N=G(g~ z>8Ocu^}KR$Pou7>9vJDp560W7lKtj*LojpkG5GI7%lsb^ILwUyQ$qW15jbqj|1{p~ zI4-cGc-_>r4!{6N;UqNYFS}8jYqQSkso@$1r1em=WI>xzh}+gaKX}yYakR`SKtRff zc4{22+tj}78H=F4rO!O4eHzXWukH_@K48*i|25oayzR#)bI1%Qj0GmIodq$Q3oGKX0vI?W@h?})2DksH0lZ(5`D3H@PRZYrQ z5AtpoG1b=HDel!KY{`&0GqPh$L-&+X_o}iSGVZ>p-Unh?vnlU%;{WSPq$R}$WLI)+ zugxx|7-Aq6TeHc-9oWXZmMIch;)SkVZDI&ISk)4U;N+wWAK}p(7oZAuu1ZoOsE%RV ztv~GqI*xcg8H|J?$>|U-te#k{Ci7E43J3N9UGOAPsscAqOt_Kh`7g4GfsAt~!IaHd zSXvcAlan%+#v;kpdb=ao8byz!mVs9Uz(l|O&9g!^xj`X)prDGyk_t1YcB}|pd043L z=i(&=$Fg0VHoZnuFl$~7R6fkh2^UFuTC1tN3;VT;Pb6t?Wi=Mu`&0#(fs!v@^8jOO zj2b)555;$;vU^V;Awouy?k7RxN+iH=NnO83cYVBWZ#Yv($?31F0UpJ&{2Y_80TRkLU3{^zU68p8=$ei3`M#sR;)JsrY#I93*`g+lteIB0G;929caq?90r(|Ji-=+L#VnQf28tUw zC5FsFfm$`BPB0xcRztm^Q7vPk?!N1#>~(u@v2$u8#++_By=Q-CW5a*a{>cfcQ-3rY0NIMpE+&~mD= zScmNJ1yD=LqMidKx1^7_BjrF$NRQu@!Tf!UD+v2Tsn-_t+MqK;HkwD$6ztmyloa3IF&!;QIS^o+2U>TUC=Kj z8e&mG6F6ZG+p-VAD%@$gZ8LK;a{+mC)}2(tU11+> z-%@$&|9Da*~)m1u-9%8kg0bic|gCwKC8=VYVImtcSQ ze5W~kWom%TwMbhy3%lTw{C(c)ZYVlHgcjI&98{nXEp(TyKYQv1VH>fTyKETPyI{?^ z@#kNon;jc(Wr@~jglwrau5ndQ3@8GP#J(iul@$B>*=#7bN~Z(P6lIqv)5sU&BvxDb zisd)OsNBxlTqRTr!gj@5@Q8sLJy=sz%b>bm*cLaf-IsjFB&UCCE6>CIe#VuN+u`ph z;0i+*zKklJ*y>@hxTOO`nV(G=y3S7cr_iW?N#vbg^o!eVFe%k4HtX?f0^$xOPO1wN zEy)>Y`KGgo@xbUr)IW!2AxkMg=wU{ezs2L}HtLoPu^_6NtV6i7w@}{;(6w#og*8bW z_O7c}u3cSRdHH^ME^Upq&tq>*p03;&ny;TZU{Vf?y7XqRt$%X*!59L>Vri2<7EZ2R zVsuWXixckNfF&0g&7~DQ(V||ZOKgW5#<0?7&=0_J++L0raI)s~1Xt>XL*(BS4|h2` zgmRlmcz;{#Ne@S?B~Jfe#JyvbsLPTqy2`d~+qP}nSY_L`UA4-#%~iH-+txd$`*z>% zK6~`r`@VN>|IP7@%*gyk#LSF2GlQ0_=e8mef-h%sdN^{B1Q{;&1r4)>&6ZEk`%4n9 znorlayS+$GZ)K$YV7EM?bwjdva^c^v)nX;Q)mouJQ9GCm zhTq?sZe=R?W=*a_^EtXWj#i^mQ%!I2{ObC$n>=!S>MSl8ybIwuwn~{WWqQiWzE|!E zTO7oTs_^PR$Y`t5=d$i*valceEf>ESQxdEnth_BU&+R zgN#XcxrS|xQzMO}>)~>EQ5N%ZNTOow>D_J8DNatY9x&B$fduxFF+(z$KcLzUFi^tp zrkxgRn`TK2r-GBQg0&r0QMiR@zxv5pZwpd>pn5a1?o&zOL+hXA-OF+ob_J%bQMYLd zBISQl7o*9RsM#ih;Cury<;V_zZUtm@;%l-k7yu4VKzK!v>gx~U16%ihiY~WCu&;Nd z)LWd>7nVOGLc2JhL?8oZ>vo?OeDDwAjV=5J`w7lWp# z;krQuN~tZr990guyMnH(SsXMHNaP0NFn2b{FX6>dD7Es-gG@J!D#*ALi|)phl=7?) z{)_)YmW5I~!3;6TV5N6~>zG)|&0JEKA3bDQ^*A@-hp$LUc^FS}gmB1>rjApBPw%*` zTk>yysv50|`%*^nlMZ@GWTaROU`?u(@R6UjaC?CxRz}(UBFK&Mrt1vS#j0`PngU-# z$d4S()&4~&gBj?%MG`|EPt6H#Jtho6?FTSxwdFyU>zL?+suZK-r**q+6WX<)lgML= zTnJto@MZ^vJZ|JJCWUrETD$M$!T{rKyu}OFEH61ZF?|xbj;l+FxzQoS#mLxG;S%UB z%Fc+l%AuUemsVJ9R%W5|Si44|r_UuG!_(a&+zvH-8^5az{B~u$7HE-=FQ{w~D|K}V zAx{W%5X?B)Tk{~!Pg5NtaTneTCdag;=S?NQ-{9@@Sw+n3HXyB8yJdtJVp>V#7)yyx z`PYIh`GO)sXfKsan}a)n5pH~#**J_pBZ=Ex>&-<56?pAEaIq)THd+qYQNH_Se%iKS_-!Pia)a}4M4aVmWIn(hy@WM~v z``Z2JC9hH;PgS18&G1SL$WvY*>Vt|Lz^Ff(LoTV{_B*Q}c&>IgGL3XlU`dTPls&Gl zCdUpXoIS=Bd5N>&;5kxG)3oLyfc<%jr96#r2C~mNh}D6U=4D{Cs7l3)H^rPOH}de z=Pa+)vRr5|Uqx`;CPOhNWcy|Ljd`4AXx{rs854@LMVsN~;noD_11tiA2JJ+r7`A5Y z3oFktT|Qki4k+J)7kYTssEH4dRa*4&1RIl7ZHQ}TuB9J5@iy~xQlDOS5rZ6iYQq3I zjDF>31Evm@OTB7h@%?S*yLFne577){wG8UnKva#S(b*qIc&Ex5h2~!+T?B=czr*DP z7@H-=QUo1id=`xf;6Z4S2HvM2IqLXFxTl?$Ug29e}jK`!w;2D4w*C2VPu1Qu0H`=6$;yDNIa&fryvjHbWKi<17qu zshF8>P1%62F*}Zf?oih8a)YruhgoD%?7?TMoSfCz*Iqd)$Xg0Z&n-4InOrHWq>L?a zT`XG(TSJRa5|57o-19Z>w$IlX?-tLNcel6xukKFIR^QnDXV+LcSEtLjBhEGrY6UP% zAV;T8&l;ZLSGmX{WbRU76OdKDpRD|;*{GW(pSkyEv%m0vB0X_Vz#&S79)8~ zO%$vgn-AQ{NYOeFw_#gt+13+Sc4}(amOWs!(0e)0Q5r9mNbyI20r;C()hbZ`G1y2( z_u^_fze|w0a?W}3-o>kM8KsZS#T*g;CeB_h2GcTOF<^`@kEja}yMq$?5WuW!v0$n5 z%bP=^5|Te@3Zc;mR_^1YTf>qeuKaKM?CC}^QmUGFapC}&vD-(I8wH{78wK~|ye!3G zoK(dwnj9jZZTX`@;WsnQf`07bxsE+H*Wn*&)3DxDdGz{^Xda3{xu|Q=U$z(s(^m)H*to1~k%&q>j8Ju7 zLzD-d(C1ki9!dZ?{1Xkf8V4tg4u~+6ie@Zl;BMyd0 zaql&6RN}Pcu*O3Bj#|fIaF_Ze-viYQJzbYKxjtG>QZ%nNK$+cI766-?A{$XzFX*8mQniRSBI8CktYViZGG0+IRi(DAG9ITe>!>Beo{dl712BVn^8{g8h715H7f{{@gLV#o=Crxx*@8Eg;hAEv^V@YVcse4Mzx9=6zwWL| z#HZH^j~&iN!&?2~$qg|>{uFQoGpKjOp`fl8K>I;Rqac00dU;2+j{->Q8yt0QmpxxN z5t$OJUE88!7RFx~QY-b69iT@hBt|)kDxViRc6^-`sp2OZB_+(%utYGhx~kp2d`KD^ zsft#>GwGIn2f=dtg`fgU##YZ*R&u>UNP6TBKHEk|PQRvk3xhjtT!*(wbUdCN_fR*= z1S^2TEUaRfRMMFXRvi6&)4)1``*9%Zrgeaz_i=};c0SIWb^#Ha6*L)IuN2=<;!I+o z2KF*Ee8Xjs0BH~2yO~^+cU}813-MP(QQ@|p$Dv5n=2?M;3%Q68#n-8&DeP~xOdI@b z=AC?wliK=tR%E7?z7$BSXv>3}e)VJ}->_UVYU9dBlPR+2d=EpwyBS3cxxPH)Z{ucv zHLA;6zvL4#w>2rfr}z=EiI>hP!)J%ZcV;o}l3*ZDH3R`{vt(+DeAj_8C?47@Y6l!+ zh2t5Y+3cxW>J?QhWo<4OMJ86~88kR2B51B#!QdGvtZ4xC>gnCPHaiW++AQwrv}LfU z^npVbxYJNsi0XI=R3QBgk;r~bX?Nz%$|k3J524t#&`X!bsvS>M{Doaz;|mMT7OfNt z+9p0~_2Rx8ZBq4= zT?hD3co*mucD|XS6Ch9eLB!w_O+M*p6c^+LadIHp#UJ5ii`li#bu&I2O~#=z4T1+OK3I+8<4~&Y*bleaU1&trD?)6R6Z>@lZ79_An-R3IWCi_MQN;rE1AndO?qt4uDlBV)Q8ebRv zr8Kdihtfj?-7V!ZyrGxlbj)2np%tfxFfnp`vGzxlZNKJ^;YO{a z9`d7|?v9+i>{;{fq3V1ePrv+S-TbRq24r9HD5;`M>I; zc)5Iec-h~gw(icpugiJgT_>&^vv%dZ%cX`@0tM6%-xv7Cet{X-P$~bxUg9qa{Fwje z1%AwbM&QTxZ_h{m$6bZBvW)GzBy{Jy8hjTsh}EEr_Buy3@fa!PC1nRy2cQQ;2J(rJ z*3RSpw`*&Pk{Ydp9X@U7z;4{P94hnhb^xnXyVm@0O(M6fO$7=KDl#8I{gw?m?<{xb z^f5BuR%@%7Z&ELEez%3r0;5RK&Cw$I(p>L%uSuIS z#cZo$rRz?oSzeXgrd|@dxG2MFigNx91}>OgrNS`{hx40)LhPERSU#;&lw0<`jwsM^sk8Kz z@~rkiIHP!Zr)BUQv+1w_r^~@=Sol&5ji-_vMWc4uS0H-|0Bl9F$F7whyCtp{I{s*{ z2tPW(c@DJfX>HyJs^=4h+iA9LD&G(-M^3dv)(ZqhKxd_=X1ukV_d!zP1E+vg{J|j%yr?Civ{Y+~L#C%Q zUguUVEqs$HAQFuMntIO$M~Gjo?+cW{C-da29NM&TlILGQi4_9OIn8im3d zcs*k)N*7eH%dk&1<4#Y}kSG(Cib4=jkE8=PcO9~ZM-Fga95V9o_w$Jz1(O%jS;Q5Z znF17@Va?x$bXRt1^6KpL1TGS~tlUDk`f)%{OKQzSU?gZ%D~Lrv3fDyXIg_ncWzg5KVPXI~zo%$sz7ao>S zEnXTZy`$*5X3tlw%Oy(V$4V)~z@f9jiG#^1vjK6)TW7C`t{!`3+g&wHrzs5i93=Ym z0k{YsQ9%%wbUwR^)6hixTHrb>VK%jNjPY@ypQa3jM=@Qtz|%4S%W~toRn&g!_+Uua zc-lKdP>`2n6-=rdfr_zis$g~al?x&wu|nUNC)g<&Po$?w&F0o-Q5iQ-7 zpxa>IKdJ>WP5;2b{}Kno!u-#uLHB=D%=AAv|DWP#n3&oBK+3povn~$pJ*@_Pw}%{t zGJ4zYvNea_K|UkJ>g?}LUz;ZG#I0i?njSfObS~vksGe|X6{(#o?8w2*&0Y9QmN9-$ zjg;2xAzO{?I)x0)msXe+Wt^oueeyOB-Xfv6O#R4=O|)jwsCJI3Km;Hkd$d2m5r1nt zd`G1$Ye83gd%H`+XP}^%aC}c;e^iV6>>?0(@$4>k!WP;(HJ>&RNmj)fBA>MnvM4*% z1ftp3jR8_qd2ZgcA{RL&2YUp+*WF{XWuBG7K}kh%9|S>UEtfs9SvPx9&Gv0)3h@n# zz%+HV5a4wTB5)G$VTl|bye35sfZd~xldFpsy{i?>Y^*nGQ)6GoW^8^DtFAq(I2)c% zcU%7?*aH$74csRHtby)If z?`i(->#4bmT;?d725X;yLYgEw1egQi^n+5S#uVx;Tc(<}q{e0%HIZ0`H0-m;Pi2W%-$8IS+K1ZJ|?0AeU_;D9u>U|BxU5cBQ)2Fr{=1C5a(?^QKMt~6!4Ld zK&?3B3Jo7UJsSH84!BQwG%a=ZZ$C%j1t29ULkGV+B?NIDYxF5UTWx_B9M~RE>OfW? z>ugz5g=OewzpCU2c>?IYFtmAqeCDOuQ?0R5YRaPI0g`EAGV5|Ms6Kxrb6(XvMQ&aq zDmrasB9B0N2Jhn+Q+TXJeS2-Mg+hckFlZBeX5<8Ls0G_e z+QpFW^29?0L>EEl&Vkm#B51=@w#R_>Q?w{c)di}RqGbq_$_0+yK5vhDU7t5vgW)&b zL?gT5Q=XsGghW*mbAAO+bO}EH?9{h*l5Jb6SC+;=i0slvn?rr*WGbwN)R9L9#uiJn z{Tgq>3JXIyeBiU=`=DL!O&b}NsLV2)oghPUyGNQKDv=$Y#oTAOOP{p=D_MLA=UmX0zv~0&|uMFscj?)w$qR~g?Wiz!Evx<6gQl67A|PvBMtW{9K%6W z;2sc^86#Q?nv{7g<~CpNXN?4hGDdTg(8|WM;B|eA+fn;UiCP;y7_}m z&~NE03!q833(ccVgI*+&S($N!ot>DPQ}hJc%#eWJE8#o{EnRQdOJ+Y2J~=OY-ROt# zEPxq$H%DBy@(6rN^^IwWh(-bTrok2Xs@`*FacO&CVXK8e_YVj9QiNgMJN4fV33Mrb z%o^@6fnp&Az@trMo;NsUOpv9g$!wEqle6hvcZb!zkURJ06(Z=)(-x84&O>qM@k0u#ZvK{j4>{g1$s~1}~JYF5!CXv$HB}Y7o(+=%AWE zs=1z!bf6~NZB6l$S8cG}>U3xF!G7(%nGPlPqYtUXX0VMR8xGwPVtz(U3(i9mXw}yR zABD!#?1c@)7<`Q7WjA$#|}bL+fNKt+zdlL-JXD}HUQTu{?k(oDf-qQ!fOn8b)gi+UA6r!nce zL-QZ*?1kcl-wKGT!V{_3b&g$uX_L{ePgC5?#b)%36MW|9`LxZC5NQ*G8X*OH)_LXyTRC=p4%HGIQ-A%h5oEK)=Jz|YA&3L!+7{+NLZd+VZ4 zR$hqFSu`hUns1{Ck#&^Rb*OsP)oxOEUW8ZeD`G%*ibGem>palEsfzO?=}Z}`EMSD{ z93&K&O+%v_A>W_0Zr9C`7!#ju_UWs zC37vy@~~62lqF7&!kTGFn(3)g>=_4qC6YPh@G`_-X6ebkC+n@<5|$hKItHaGvtg&kK{|VPn(T4 zXOoROs!*2OY@2J(hh4zk>V$Nf#R1;V8w~qO0WcR{45^ht-DO;T<*MJ2((J5qPSdzq zWvp(j9n*b2V-0*O3u3<#di{2iF7xsbMO`@gTN*N*cfi`W!{Gt4+m>A^*wpf~6HzD@rX%iRv}3+VB# zF8a-tDuzYC`u5|o$Nlcdkc-!b?)o^%grPPX>iPp5?XvFNl?QgyaP7Pb#IzKgvFegu zw3{|VZL|6-Q*AwR1xC^~+%6n`|2H7Qhi}-8N*G&bE~T@x;XB#!9-3@*hEFAkti%;> z-sT9eu>%_#*%7WAR!8Hgk~(a?@tzmh_s4#RHM|JlE|I?#mS~^1zseUs(9Mc=SiU*f zSR752ytTu-gES7o-d`&k(TKr9kCDaOsp69T}DaN%cF0vX9&_8 zE;V-3OT>M5iezTgR|Pck0DaQWONoBe?GDHS;=2U5n7|OUV+fq8`Pt#wo?N^IxjzVw ze<^p#!v4>A_2b`T;{Qqg(SJ$9{D<00EPv|qG7AU&KSan$bsfhw_P^K0IjK68HX_FI zooQi((Q-i&^q)E+V8WqOMYN5&93z!^KYx~F>`SBS@Sl<;!~4zKew^d@m|epoO76w5 z=XU4Wb_NrYBDO)$U}f0he~1Lh7m&CPd8-py<~q>;2*bX>hTjwis)15)M<1$rg&Q=> z(amy_G?UBpb0&<7xsE`b2AC~~!aQ$2gp-*0q*NqtI>&eN>!fWW|F^T%jwXVh&q-*| zglE%mvSIzt+|?LS{@9W&80@eLD4{q_a9ykkX{hXKnNZ-y1_l^NjF-UjIT=>yvf!N% zdJr0?G5J*B3HWjWBG`(p%YPY*C5ZB0$I1<%hk>*YAc)hqLRW<9gE4^AJW0xk>^=&0Q>_{LMl) z68cjbr*=df#F^?rW^!Y8V9Cl#@LHJOP5skJ<1uMZj|s>WJpg~BTtPqUA7{W)Hb;u0 zYYj%CwGWUtUg(kND1cT#@IXFxKMK!W#i?nsFx2s^y0Hp}jZRr*5T8$>d zwy4EQIY0m2i{GxQ0rzejDADCAmi9GT*Oxi?Pil>g{>5!5bPeG%N{LZJcg7BTZI{#_ z*G~M|3U->dR+!Wqd}8?hCS|>zY$ody0+u(x3 z2p~{CnC1GD%&8jd9T1OStJ@OUCP^i5FIfQWqg6$ky>?6r@S*(v=<)gX>cwVNX=xWPl9BPfGT7|3B%hh8L4iza{=HE}>Vettu`yH446 zLUMvM%JQg&_D((K_dy7#>=A)}Tp$!YpNo=8@h9F`o#(cbz+nzj*jBS{{e50Tr@eBY&J6HA00tNygBD4*SniH)~RS*YtVGi6> zNGvDhY6@Mwo#%Z=n-@_!gxWJ{^%j0vT_j=R;D#~)C3VQ^$~<`7;U5~iOk5MLGK(D7 z(RGh_Op}r2*_UTN85L~!i=oNObP<&)6R$0}AdKg2eWn4+W86d$ zRloO;_o939=md<_cG3EMe!`l2F*5i=7FCRieL*>^r=Hwv1^M8nXiNP=F4d7mZc6xx zCfllp?QH{iSz((YJJV|%w^nFMMw9{SOFn`+`d3onX;&xH#I;bLt1<(oy8khjabH(9 z%!lNXKNnE(<(rp_bCnZ}b{aJj}C*17rh_&b_ei^FfynN{L+uiUGy-Nqz9#1n2^!)rt2nSQB&jk!5JuwdQ@x z_|WgjfQ4@g`|cC(vrn**f}uaS1jO=}XaQFGf5vHp5ufG1KK;OW5-JL zLey&J`|%tv=%_ax*o$(H^({Fsi!OVm|3g~!#W0nX!Wn-H1#4A4qT{1aR!w2gr=L>7H8&Uj=P zJ&+j3D~IOzmzpkmpQSvdHGjIN!ujH(^W8H@o|%nbo@Bkh>M5H+F&mq3n>(I!J6LZ+ zC93B7e)eb|GjzJ`H2g-|lqhc|`^582pR3`ANR@4}_HkzM5vdv?BY@_D*6adieMM)b zI0J(2_lPGbdKC8^uCo{XTM)W({wkz}{$XfN-%eq+gqJG|I7IYlq_(56dzUt}LHKqq zrW?~QGAOXE2+0xXGNBn68T^^Xb1s?><%N)AMWHgrg<;4bLJ<5P5^t1SnBv#&T?jYp zfK6<75dO}ZY$_`7X^0AU*a(mlfrW|4pXPFuj}uNLXNu?!VQgH_6n+|0P)!!XFkV!O zZtoWM$4>dWLBYZTJ;&Qvx5SNj^^z7cIk}_(?Njsb+Kmx#3Q{U5z_X^oe5!$mXDC2k zwhsAeS%?aDy>3`Rlup|ex{iwDGjuSlB7mP-uK?$FLHcn}5n>;()byN5{$4Wj^I{7^ zE9Ib4f>wh-9-}?woJ0ab9_w-I6AP+*Fx$bI0_~>wmy|T9ZJ6vy;FCG!eAf|nuR0ult zc7A;1<`phTrZee#ZwJf$rs5cq@WwK%!FRYo{DdnmHZz~ak@H*%`|OP~gQ&(T(C4a9 z1)2~KcdNAu*YWGzLqS0!<*|HsNR5L%9FgP$nJ`18e3}DgIJ)yfXYF@7^d*H2mUL&> zyj=o}k2uvmz954gelYBoj?+xhHf5(#%z!*EJ|P=|!I-dDJ#+xVV9P>Qw3ctGR_S62 z9b~@^u{we2T70Z62~7Dh6m`x#t+qT}0e);fS){9!SyoROgy3B)_13%mD+E)$kZ`+s zH?Xa6}I!%Cm!Z#W@u*^-}cmcM=^>PD7(i^(+pi0~r14P_*?ivlz1 zfIK?|xcE%bBW=+;iu?`mCSCV><*}nMFY=@~vEbX+9pDR9wY-~pz9eWQSQp70Jr5pdZkCVEUcY&ytw!@+mFs2!rzX!26V z2&$aqw%<_bTLxjU?5T0JxT~P6!`av4DvyL8injQh;sE{K=GK+#_SehrfgCW}FSnV?dE2zBF1-sJ zomToF5oxMV0A7(D&g%1iLaRyC{d2y+)n0&)tp43SI_77|`=uF2xv^wiH(VO$8Ij@Z zg2<&XGH7(;wz#|z^?oH<7~}F0|6v9;c>6FF+&gSU*o@}Y9QD`>{@4T+hgQrfl#*^xC7uevLdrWL5F&{=*^-BWa|yb_q!z8yXHDHJm?DgCvIxn`FkA)GPgzty>GniFooP zl}K;fxObLp3=^$8%(HD6Y&EVpcpSo;dkM!?#f<55s7?3nFKyL_U9b7<48&#JMQ)o7bP#zwTY6+KtEeX#Y=Q=I8Q;w>W1P}Me2<-jalAvVV;(0b*V(-pYb?CAU)@bTyIVHJ4v;G6 zS%bpogkO=?ZBMd81v^~`@B(!yQ8sNP`}MM>^pZwhrP-m<#yUQ z6UeS5kA-ezDS>r*uqBAJ=tV3fWK;%c*Zr%5JD0IOH)|i{up@6V#|@uHUqyw6>~o|9 zJuc?G`zdRKp{GMHSEc2ps&Ga~1%MF$a6^FLIY167IGtd&f&+x!8)KB+!hTgU;{d_)k%3wA#?cdbUf zT^DL72Fp~$BIk2uwYMggB>7HVMck*&mXiSjlduPgQw79Pz5;wq*uTx26llO%8kQ(u$+Kns8x0L z4D9q%c#9tyh3-CRP+`x&iAY+qS~ZNvTO!{6YZ38ARO4#oyKsUlX!Xpls=pzX+0~Q` zUEdZXCt%eWyVmNG_julTwrw`_I%=}pSDflJ6@D!N)KGov$=1NELq)%L`5)pe^mbPp*_v&OE2O{$yT%GEgLK9pixetn#r1CN8(LE+HRW@^ zo2hgw$H!|e7R~e5Q#ZiSQPa{N#P7dERkQxzqN@Kyu>LayH5((-AE{HWZP)1GKd1EU zmH3h*Wio=0&H1F);H%2N`~=$N#1k{IcWCOA)&(ZN-m(*Gj zW|u=1egqQy*0^?D=xBxLdnV9SGG@mWNb)=O$N^K>_ywtB7kFHYsr?4Q^9f7?@>>xd z8Kf3xs5Vh_*OosIUx5C_6yCu^ZTYFh1CTkFzGkaTF#=Pu8{q+MoLZ<3Gl+;3`aoLe zm&kT_I+$7ty1jG23{1Gz_I>zT;J0;m8jskr<2E3Vo!2zZ@~&Th->seat^n1C*pHGm zb94Vh8l=n!;xNJra;bFt&1=CKGnn53bij?A@J8(IjGfICVbHKR-(Iz5`sdLf3 zh_@b`CHkI_$LFZb#)4?q`hb0nP!Fei(BZ|tq*-#Mv)Xunv$j19890OCWD0tjDvDAM z0?g>0yF?`7^S2W3?@+C~C`^T%eFcLCUqUPf`*%a~FYGCor2lR!xp z>!q11t&Zx~;!SBhb%1ngg_SZzHWx((Xh9@`J#d5QT zoIJ%}!jS%TeZW!NBMw}}Fy{4+gQv#SRj81tBMJ49n);*?-a3|n7-@_pc_*ATP$W5c zc{~@L^z`XGn;V)&D%S13mv^Lia+VqfF54u#dLH!S65n#;qnkL~l5^b% zL8fmlpvK%Hj=DYzq#4;Dmv=znH#w~sULyR_rl!KYvfqPyjBz z$)n}9iI{(N9&UWZ$6m(G;+{_3=_NvP0;RJ3RZqMh@KZ?Sq8Zg7lKoxV>_CUbrO;7v z!E<#Xq|}C~iFwqdS(qJibJk9pQ~piGnN6l(D|L$w%6k6m54`#>@rA6c|2KqvtbdC4 zV`2XzVc$4x06o0O^Jhc{5ZVs1o(a`#GAZUc7`&!5N<_2%-uC)XT3f|C`@JDHa*R=3 zjHO3&vQ;RSu~4}(_<-F=t|ls z*Z5c1#jyA|;o6{OHWUIcSP7=pPa7rlj6Tt{Qxhd;*tr|Jl>{No?1QkHSdr2o4B z@JZE-lw4e&*P}AA`LvLxDm#-7IY}4-JV2QA^;w6&%FfVrPGX3ucYeORMf3V>D{p5v zR`7Q(96=3stXpfn_s7@X3&E`)2m?fJzzEUp4@q@SBz1uVc;9{*eUPLf;;cBOsEe$t zAWbP>*_EYwu!6&01-cc25_Anzcuo_tm9!A9x}_urFB@r3`V3g?$I|%K1SKnJqXcPn zs`Eke+W5;paxS~TiIgluqRhD0pi2`A#$ifT`e(ZmkdVw?$USg9BC~zNrR7bVi#~KV zySiJfHaV)}1E!quz(tfVr6~R3AO+}(d|PDgDKjWL0u+;~wt&6B(hODQbYZ8)_Q8`M z9lgRGLapcfnR)$IeN9Jk5~Fw=$TVsZLg@k&$h2ssOBYJP@3Ma7MIjaKKa1q!cy6#! zQ^%9khk?zFv3VXC!2~MQ4njN9DKaE37ZD!V|UI%~Ahc_mFvzHz-3vNcsdzc8DATJ!2Du^*mYVJ*`=)V*KXwD~lA zi4?naOy@HH_GP#7SR3>VAvH3(zHSQ4_U;Qc4f*u1&EXk;a8I=nHajOW*QABoLA=YX z>^l0alqMtgm)3U8rw%Q0z8z?V_tez)-G z=H>K?#7=8gQ+pRVcu&a$2|crJ+G7ynJG*Z4-P{mBjw6qmnu}w%!rNsh2OnSt4bFG!OWsNY zCgL;c{+PETDUBk?Q}pK_HbjZyNe)*m$OfEt#p^2bgnlVS4LsDD23d!~#!EZ_GiZn< zOK17=g9ohmf@o8R!8YRM&h%$1b8G?H#=sa>s(*O{L49i>M-fgRiCA+|D!!DGZnKR4me_j7_9rt)m(LTyBia|Bwug^bHR&VqM(OA}P;t znSjrRb&W58v-6$2lhq5M^!zK$2jnf<9*rZ#+jscEV59|BbfFf=2C5&FCHx3yO2h~J z_)~4B)$_cS<#^`Of%T+6j6_!u7d#?yvl{G{1AV@B3)d;)(3R{1e(%`1bdJIA!Q0N&3nuYa9TF45E)(Frv zEH@Hu??_k=Mpg-KxoH7RBMXIUxb8PEig0=5DO(Z%0GHM+h0mz zu`&Kr6$F1pqR;kcGFBYSe}K@*s#1;x?C{<1YEF|R>49}_`{%L=83VYTDA!pIvwoek z$l#&@3llxtqJ~xhSay^Ysa3IGxRyLGZMXirzu+u>7y!CAg)`Cx)9dR3`($}w(0^2c zWPt{W=$a3I01H3?QxDZ3Gg793feX>K29USY57eccz_=%4T2TsP|tPrSEY{gCx=75Rq}Q77!xHZK;(o!)c2nP z)okDgA>?5vzU$(d6vZz4yzqkME=l`o+ofztNFLwld zN0GlI@8EdUD$T^560*qFpBSgKSPTk48*+p=>4iHLroK`ZB=2AoCv$Sc5ZI0aKTv+} zUi+#_Um@FzY~;vh<_E^fz!zjI^2{~R>cypm9gOQ_!duXJ&A#b#kXC%(EwDg}+Y4f9 zAqF;-R|o_4)HR+yl&{o0Bzcg3;)Gt&%+dWVSc)OpXSWmAg3SOq|Cf>dw@9OUUov7( ztvr+wa1!0ahy&KiW|4p-h-5(1sLXMvO=q=$%p_z zda=VmNzPLpdO20!1=3j59I{oncbeJNR=he^0^fcgHS@BIZ%#$>8>8j3^?T(gOSdDn zj;?Cw`Kl2W+D>n%N-ql3n)%q?+G6=e-uV0hMK@xY}Bn9qm zeKI6ev!OmrYNkW)C00$fI2?4C+K1&k?fe4CsW<`JGFZ1SUVee1=Pw%Dmc^f&VI)kb zzGfm&(7Bu~n^PG`bS)g_8GArj$98Uhsqb>3YmL**O0pU!r>L0L2Xb`3=+=*ox-7BV zUT+A!$((fAi~?J#_ohxZUCUhDzxCZWNn+Me&T=8RS!*c{-3uBsdUkK^bbHPTgPA`( zDN~OP>S4! z$kOLGhd*cb?eC|LeEZ%|CI291{iVbW8}mQ2*3o|xp#I!5Pt5;VDzz(p-FBT7eQ^6; z4c=XX^LIUMiWOh8Ooz!xgq3{=FEBcKx_$cD-bq5!_a|?J!}v;Q{v3b^)WG7d>kAh$ zUHzLIGX1YFU~0*QZDzg6sXwhAxGOjuQykc74I5qK-*OvC`3dqf(N6w2;>6e z>B^eZH;94}C^%wcG@8zl@LDr7vl&V3xsrC&*WZTi0E6Ux{_uT%*{}!ve*W-*s{JFG z25hZ=hBFa-WO8mj{)S0A{9*dNvS1GQz5HQ$N_!^y_CgT~0YC%+ z03Eb(PyiqS(3K+YIsC414AJS0UHDkdeP2L3yciTXigIIPIJ@?LoNyd4GaN#;e-zc z2pxpph)8M-xas#_?aenaOz#zEkhH@Wrq^EvaUjU$j}xF8-H5Eil8-_}2SA(>872JR zrmTaH1_%j^(a4yoCCgIyUstELHp}wg3@ZWRfY-QT2zq(FoMAdtX+u1TcjPIb z0o>a5HSX^#7XK(h)c7x!$(wu5qRSTz{!0(YntIHF|30_8M0h+){uf=p`P{2ZQ=PQk zD+T0*p09A`mQU#{EuT_NJ-Ymt7P(WT`GrgN>qktap_ z)@Pm?wu*vN&$oE^+C`p7i|;7G6ly~{SyZd0Vwdjg1{DuZ>vKyFvPg?&?qq#YR$_OB9^lrYN<>+%xb`d=O9 zqm636)+0j{V&%AztW}s08Pmr^op5=b3jz`bRF$1Ikhv2dX+D(^Sk~_%OvtQ>P7xPl z`quB-zg)ffpWpJVu>1^SE7c){!qKiGwp znpwtAsBAMOEtsE})qQBs(Cik|(P9MGS+H{poVRaedLTA(zFb(^UQa|Bu2gi+cu9$_ zma8w_a`0MzcF1lN+#6v=Yy{A!n+(G2{I|#eD~S6vf-WN|D~BmjfvQDYvsTv%B<=5D0{p z(EE{Gk|UQ~xXXp!n^Hs}C?KeSNRi$|dJ&Ws0|-)$fYPf}QQ)1uB$wTJ_HyxkfB)Z~ z&&QI7yZt`T?9BHm^UP#upJ%Ur&lB6ad#6Vu9z8ny>&XhK)y}ONJg35rzY-swc(d23 zU1eH~&O7#HqPQ!i_1}NYc=_kG7Z(q%I8(4w#0GbjwcAg;DtYg_OQ&(OQD1K#we?QO z!sT1W6#4CT-?Be;Xm+D+*s`Mw9^jjYpWTi8-4&SL<;BEBGe&-Wv&qK?M-M++{L=GF zdry_V8iMC+88&<6idmjo{u~|=+Dl-&P1!fpV)Tl^&=Y+ z#3LK~)TrxN;XLxX%NIAk9C>E-%QN=Z^LE@iGoyElow2RYRNMNYD{SQbJ}=JRA6Qt9 zy!7bcxvEdx^M{=Ot;%#q)bdnu#EUT}UT^)Z<_FT!b%#e?%l9h$ua$ET*1l8x?wMwL zE1nwq?NfaH*t4>hy|rEawuk-vN86W<_0=A~UAb4k@Rh^1#;lCK-@VP)sxRNZR#c8R zaN+-|N-NR-PcA$+bz507sM{`@+es}d9K1iOP|;66%Cm9i>j4)g*R=Y#d>;ixI&K7V@me(3bSniYJ%_}Di?%he2PyWxxA3LQdc$CT-Q zH6{A{sXsNSvt#M(d{~MLd}~R`vSW%kgoAZ&&aV;|_C@RRClAh_bZ&BmqHRi!NdC0K z>e=6ada=a8y8H52m`|Z;1>UMyAaZ@Xd1>FTp4`0h+S^kCIu@*2;N9};H;oS|k=C;O z#4cBwE*alzdeZ!>Q|e~^l{o%TiS;c5CU!e{=f;^mj<6x^(pm;E4^tFR7?*#4`PFZ& zt1u#c-j$T!#+#WhsT7;{&7zZpp0$3o&Dc?WTEv96_cK>w|FUFWT;kBclz?aZO1ln} zS)RA}q>@F>&Tko6prSIM0l_8VyGz ze{rU?qr%4~)9orBjIKDT@bj0`Z40BKc1<3=`~Doa@Tl>*5r0nJa`CH?Mt?csueJQ~J!h=L3uXc(F?P$KzKN-nMsl$+ycq?2*2y zdDQ}a-XGDU`OpS^!+N+z-|hSN-AZzuf_K-Z{@S)y@7m+9{`1DYgr3WnAFd#`Y}oDa zs&KSuntjKts@qQuE9lw~bG+Bi)HH%qa7>zwEhmq{5_|)n2(q9Iu|x+Oi>a zU57G@YHyIfntJc9*lO&|W${V-hX=jeyWhTB6NcWkrsRp+)voD)apgxuA70xu<-xUo zDzCj?zf$#8L!Tw@u0Ep7yzuo?pA~D_;&Siq^&$rb?6fA2`sAlMlR_ROe>?>jERuS? z+BbDjoms2z4O@1#n`GZH_5KHW%jFAv|5wX_;O586zBzySn1qBvx2g`THg@95Z$oUs z5zjZ6hyU5N(WP~D(rdqdqldWYO9OWKSNjl>{NLCEl5%yj0h^8XfQ}d2Z>oIYe$&>D z)I86BXfUVW%f_}PC992lWBR=K57zJ6QzG(w#Hm*=ETvLvb@}#Sa@5G5 zGU0sQu(aXuTVmbC#h<=2Dr{Nu$vdgLAI+|3aOJM_uL{Pp`M>jPXaCjK55@Ye zA2~ObWEm-jTR)DgRQ>&VVb8)FRXqCh)LQ43)A8San!l~o|Mx3}-g;sWC00-mMP`Whtczb1K%?DeLwQ|ee$u1wI*B6FC9`g|GDzRaltvJ7E1~S%yB)g zpMSyEjpk5 z_osc+#|dSZI!l&cKJ-rIIX^FW9X0kw(WrcV>dZ}8`A^mNdYzekBK2vh6(4Wyk*0K8 z*}d^Sd;7T?J|ADNV6nAxudl!Jq`-~$r#}AiN>sPd#rv|4!k2Z3K8R%KigDX+Pttq?8|NEb`Lnw$x@>5KbG#Ft}OAoX2JZ` zZ+Ds3sPFz!Cpym`*)xQ8ST=3({z;P@AsdntyIyG0?)1!Vr2f>`oks6;ZW$Uh<@y^b z-_~z3Z*$=NhVw4h=+tLOdcc_~bF19#`f$nFVo`slRa&s=y=!g1=~w-;qhS$)cQ!dD z2BbVWlV7;Dd}qptKT^cY1HS9ge|XiaU$(a$T{^MLoF&!7d(*=ojGf(}NzBe!Er#}8 zT4L!@OV1~VURCWeZR(7PHIiR_P71ZXAeVf6{)?s$p9GDW?G}qQ$e-tjcGmAYIh(y% zJiTo17dt0+d)49AjeD)>5liD!w=a);*1p$!GtbYm21%BY($0u6i6@FA^l5p2Li^Iw z=DaTUWODG*E#F^GO6*@WB!2LNg}Y*Rm#Dg8W)s|{NKF0lkyUaByhx%s~$^HfM?t8 z_UPccz=-8`5BsPMjU!L|Q>yi~YjWuFMKm;W*{O+*0t)u}@uR#&$F*BDAidwXuiCb& zQ0G+K4^2ngFIzWjxo||K_g@yMvgFva8fRBOTq57O7WMY^4z~_2+B7Tfc9TLuKYbW@CE(zN zO`rUg8f0E>D{tM_Y2C^`RY;Z9-A^r@dv@xLl1~?GKlr81v8hJY_@&l$H&4j@pDn1m zCOr)oh)i-FJNa{;CW9AOyBfD|#LNrbN*oe44t=i>>A&=y*Bw_cb?56c??l6i?wuiV zl^2`dy&XHVdzb}nT>C+n5>v~+@mIc*ft$bSc*12Zk$<1=RF>$4ZOEhKK88d>&-8B zKCoC@pDTOx%ItUMu9!@xRj3}moG_CE7?|W~$zNKW7eea|ciFkCj#_qJlbqA&_Dp7iC z@!vb1uUp%U{>Zm^*~xmA8`oA{{bk7BwD5xQ($K~oY21nX+bS&#NH08kcJ-8IpLPqn zpSCvmYFeoULXYD2CQa-zU}K(JZB5b5JC2|I?DFS5o~$aY{8TAl_@&xSYX4lJah=IY zCDwi!^G@DIskb_Yk)t!^&Yw4&)$UruQ3rlb>GMnD;6=YSSbw(h+AWvKtoC4_pbQH+e(BQ14EEFK_d#!l_m9<=iVisC+;8sOfCaX8BLg?!RR~-P(BP%O7?( z4I3G5DgR`7vzuv8US4bRLCJ4|&V4*gIG%s_NvYt7<}Gfu?_x<`bZg?K<998ke;a>y z$hoR1>yIzG{^NxYex6|7AV1cio9M znoNGXZ13yGJG@FQ|K+4%Cr9pkU9@@JgU@#NY2*H_;^VL0UmZNTW#us)G`00{5Usud&s1PyX)8QZXeSn?#;ZP?Uw3Ius)rAZ%65oug-9Vp4r{1{$$gk{YCTijQ?jw|DvP5`26j_ z39k#(lncDN{oD9WORpVIe)z+c0l$nS{S7?FzuF#<@qhJ>v25=ka^4|V+Xd>^z}*np z-XZB@F;b}cRC~;fbDz0Wl46=fwzqA3zwDxO_sVaYe!9ZsW66i+^*i`-%c2d-dR1=oO{#t9 zj9vrptiAhTgX34Njh3=c9q!P`IdsOkzm~MPP$4q;(yV{3MnArGsc67g$BU6(YfGR1 zJ$&*!dhYbP1?@V#eW~e*z~Lu%EK0o<(&Pv^ec@cw<5jmTAGO38*Y0ZE^1%^v=QYEJ z_Wb$}nPyvX=r{YE0lmUfZpA)bb!O($hviT5drVWEHxfxUXwA9gYI6W5&x(si7;yuyJ-&nA7_bmeN==Fs^= zGn^T=YKbeq3u@yPSttcO2pHtc%oS5=aua|?Ho?ZCu+RrXNkfu-A z)92Ut5^v@?k~Fh?q0?hdUN4oJFk#-w_V1LlZLS*oRT=V8*gKxDNNSiEOG&_F&ixL;VsQK>8k6q<|eR=kI^;ND3 z%lB?-KjHPsyt}_`5O=!!PbSLC1EF|LFPXj-_5sxH2lC$lTHi&8H0BGJ4#k zKc_rhJGj`0d7qCBsdBe);-lAjKkfEM>YYl=(6H5%a&;Dc zU3kI%VXa43OS@L+BipE>31zllTly>MfBmYX;%|#e^$V91%SsijI5P22jn+TYBoxr^qTt1vN>Ct6=?S7yGx#Z z_R!Zo@-9eh zFzKVfwcV|=zAh6K{4D6f_V_~m6RWqX;y!cX^7gko3v|eV8U;|9lHWD!dgn=rB43O} zmFe<@vp?M%H0|CSGx81IU_J56fRQg=BsY68Vezdx4+d3Hc_?|atG zyG9HzTB$^>q|fvGvwBY%`Lmn-tz+N&^whfTyTuQC4ezk3*&m5tFTyp77qXsBzMa;; zd$S4`dfMC@$}TK=*?qdpALrcpV}sZHFs<2|T`@NzzA5s@lQC~4JdgS<+`8)F-MK;E zRY!d+JN}wh_&}SQCE9-W$r1emM5cd#`H73}1fw%=T{W(X6HJX|KnXU9;tucNIMq@um=yW0X4?%rZg2bGLY}tcmaeK7kk_@Owf%1B z#`XPo{Cy(rpApfwznawc$L6b}e?2zxQFPTB#bz`wHplk-o7y9Kgv2~5B2RU;o^NYD zabx~Z%!j^Q9Wwn)r4_v+f3H|HU{dPlXSb4_sTC^+Z7CUdaeS!<0cA>UeA+o;_IuSA zS1okCbCXFG1B=$$b*x?20ykRX6)V$rm-)3L%HKce-7WS}kGB6)L3sbKnxUbo?^k@V zaQwklr%CViYm&?b2i{Mso%YSe0=vrnwPauT#kfg(e($lZ+l|WggP*jYS8?r$(I4f1 zPs(4X@x^}mZ*5YhP9Iocc$wwBX6GweY;LiWaTCuBs^27_`P_pWf7n#D(}IZ4!}9FJ zox<16`Ym*JR#izDHltwt~RxDzr$Ok{fE1MQR1gQd3qc?zQmyn zYa$=sGk)x`iidk!D*xE~e#0-MkYWv{U-@~->(ecU^}anMboZY2sT*r{QXV|I`RjM< zrZ*~apv~fDt6uF6u9EOW;{`PyLVwg3frnjqo)9R|*DA?*s>O(Vf^+r8=^=AK-)Nb&8jXJU=!k)q1 zP$Mh8U^3KgK(f?T%-QP73f8F7*~#FAXiKCu3ttws__7DTv(uXFH9A8Xh3J)0%upFc z0~DBOWl&gho1)w%*Kk*oYIb}!D$$~fVz$)^SG!Pze*qNbh;+xZ<iGvyg3E<`89K zA`TPfjL9f4nMrMq1eYnQjyj@|PFs@OX>1-+=ZhCt(Bg8DxFY(ob&%)vCEF|>Y%iMR z>lJ1gmW9TZn-%N_&CS+_%ak!=)PJ$hL|TnesaevX@@5e~6Ib?5T$(*`6|<;OMldxn z`IuAe71-hvnW`=}C|TMmg3oEKWRHnr=EsBrRWoLOrW#>ZQ=-!`$evqdjF4t(OB|Tw z2h3thvPQ-xIP8uXn|E$0J{N4}=w*V*9GILlSXZYd+2S5%Y?7#3Mo0rGX(2hnQk0w_ zgX|WU%j(L6w8dLkVBs>v6xEmJ#gw%#P|w8~Kj(m{#tBYeC}vTEqMIfHha%*R!UCQc zrzJk#W1Pk5%q0B=iFQkZsc%3lOJtntfBM$->Y?L9DO-#{` z$WguR(u*l*F+~nj%o#IWr3#nT;x@#=NYUW%=3qZWfij6gF%u0@Wd16P40yzdg7Gu+ z?QWaXYO*GoZ0rY%-EMW7g1U8%@M@*_Tt-A=y?{9t0heWRNS2D&tD=s}w8R?fRfw^f z*_3E;CfS_q9k~-2qu7|{wn1){;8mJaBUw{MByFfUHY;9&$s7ocvJ@&y^nNVLmf^+{ zJYI|~dy7rGJhV_E)eR|nM@+Rk5>7`zfBH3;1Ad~znWTophM)*bn#s(OgMj|mplk^xv2@lH-noMp zS4X%sJ3`AE)=VWh@)N}Wvl79rTZIO8G}MC%nk4}2_eYLi<`J~yh_tg*RHLYZW5)O($|(uyQNX(R$z>X3arwZ}MoWsoKbrb_H18Y)NxLv) zZAd%V;aQ={4i*HkNX{Cc>6tY{;MGh=vs!WzbPj?e3IP&fh9&<(1vXa_-8PrWZZX+y zG3rFJGDi^4{w~T`JyDZEWm>G!Nd6CMRL91Ca;gcWsm4(2pc+}~2s$dq8d?=NPa!CN z-eXo8t01#>9&4wOcMf~lRyTojGj=*|_pI^F#O3G)p`3ApVjVUY3tQ}(&{BoB zGoO;Zh;-ms*7y{prCG$$EE01D4_2LRJPWKdMw|T)6QHDA4uU9YVqJu^dT`Mm!hYU( zWTZ7Q^OZZTgRM!K^D)VHG9?Mb7qfy<@I$7#Sp`1Vt8c%<5gMYo^*cz*yQ0=DVl^nw zA={G#U(tA$#ToBM$vUHtX$W)4*-DXI7`9ZFcVj(Q_8kN9meiL*y7!#D3tJ+Zg7_bxkg-Gui4^BW2qV zHw!#ilAGyGIB=h#dghpAYQlMIk^Gy1u(*>PYIR=K#Lrj|U%`W@qbe?Z6=|*phK+;W z?Xt0Pab*pVE0;r~{$8kTUHH+E{45vAI}vqz9lCW(Vfx^=5-TB}nS`hb0R*$i1t20M zU{T6(S@=vPM4mg8oF5%-jnV`dY;|N!Rc-MCX?dF>?bvI%5p&##%{gNS#aa?#R8$M| z6xtc8j&z0^h8kd56LX8&;w9#sCKh~YkTn&&5jaNLxuDA$f^AM~WRfk}v4vLIHHU-I9jg5-0H@}KTaE`!=2dC;@yLjM4vThtR*tc5gDfbvDD@PLl~;r zgUhrc3x21}WH@Fx(J`m^I-Z))ETg2!#l_0qW$8vU>Rd z`{VQxj_rJ+AZD*h<)b9M9UR~ z;|e0>1}P$zji5?^E<-r1XsC&3>4I={L2^YGU2XAJhdcX~`J^VIr3=E*1<4Iv*b-t4 zVf1rd%N3O43hIX|JWk3MZHx3cctbEzo2?NoUr>%OsE{kL;hmDLPNyw9Q^r1dkZMVT za->21kVdd2$-<%;Llh!uTrkzL1?AX+`eBP;YqZ5}Ph#Pn(`8LE1jC|cZEiv8!BtBV}YH5RVv_XkKv}_lmgHW3RvmvxxK{>9Vez+nyv#}@K;qZz0hbL;MInncE2-2=3Ej@6j)fCAOJ$M3H zLky8>=9{GD1c~DW$qy&AWwaBTS)J-&jUQxndYuOGN#v52AGlK%isXkM+B#ew=M?5} z#JLlV(WsyqLrF^z5=Rh{AA-oTEwd75h$d;@6)({0FFc91!Cko~Yj2g|S^Pp#c$2$b33lnJC|1({<7nfe9N z77M6PBA2zSAakrBOSwYnY;|^adbU*z@rb0E;Ift-WR4wVIk$M-Tt2`=qMq*NITo1XT_~8g$X+npg3&XTM z;|kX^t|)$pK|M;N3HBtP+^y{pSGZPcMe)N7+9H7tf)K4CT2|oN!WG32E3ij+io0ym zwPj@Ia1J*F)X|Wl zZJH+O+kdqt$=cFC*U6nJ$PvoJ4>~NLl&)>(W{(zlEWtmP&3nE>kE5;qW|`pyLOhTk zng|c=9At@%HAYgmr8P*p?K7@TJ5!Jok~<;LrF9vSFDB12!wZFZC_j`D!J-vc^l(EU zqS>{~vcd~QcpyJi5ux&g)3ZgH1ttr=t-?Am%7f9|fVJ`grCm~4mUy8g9!km$RFKt~ zlu?7T8bV^K8%nB!lzB)wH<0bE-nZuSpjehYUMPi!QgQ>O-I~&2QT?pfk%qvNhG5PO zmX~vcA}&LjeXze)jCM`iR&^_5B;VmzQxy!D-9raPr@~A^YBW)J-D< z<||;Ati65BF0p!qGHXjgZRJpvvYK4(%!V~D+qn$Y5zS`r=01BkPdc#8nA4zJlFe>& zS+aWb?R6}?N;O(pT((GWGo0>VAJwE(-Z9S_4W5)>Z#uf}Dnk+JG)sBNw_JZnE&4_z2ZwM-3%0r{E4qIVJ_Q8$T+uHo61Y-<#4iA?gg zn^?UKw@g99{!%3e>d-ka#II=BikvmwvyX(bk&0EDy)B+@lmYhaG*6E!h?*ITcs7L1 z#=eoP>fV7*AVJo~9!STHh^H3VW$YU^ktMM@R9|~#M&?mJZ=YnpeM$TFMSeHK$+Ymi zX_YXNtWFl~WlaQ^=ZuY~B`H(qtSKOyeFuVozF=Q5*9oT?lX&Jk8hTI-k*J8ZFP#s= zko+%^A{`0I*+{zBMMp_UKdpIsM2a8WtiueM&5)j>;Ody?IK;a6#;lD5kd7fmo*G26 zA9V~*vZ@MY>0s*IIoMDSjEGhb9XX0TIf{ZGJz7UP)#G!?4wrfmT=kdU(Q&v6>DbTHd0V4Aeea&qvMEe6J+zoe(K3Ok<4Td|N|EGN zgN!k@YMOYp3h4HuWNp?a>f%e0_eQXb*sB2Wp`xBem0S&!se>ib)G5MHQ-ZX~k*G^) zF_^&y6sl`$4|3Su@q=s@Q($7E-I`>v$C)}?BI8tU?;8*l*x7qHUay3OQHxJ|7F4P`21~$}75Q6WVS>HO0`BWD64rdwU zJ+rNzM$SARlOuKOlpvnQJ}r>=A9_o?>AET-(K-zHV*H&B&gKP7wC{!JnrfND2(v}1 z_q?cQG_+X>I4>>>zUzgeF7GFNc!dpU6l3Fb7E|3U(qF?9AJ0_l)-klF$y4FBCB&FA zQk4uVTvk(HjMHk>TnVJt8fO$Av-IRS3>&a5*55Rc_Pe@TMBV+yA1!N-o0c*wLXy-7%uI7cK{u z(fK*TFFYdT0z53VRd`@{FF#6%zLfw|lb~E)2F50sG)_LjU%d^QuLXv8_Tn3qX0q`4fRd2^5PrBX1w0qbWzQqs zyCQseN$7t_omQPXbv4!p={70gfJi=PONIvBJvWhM9InqeBb8ts=2Zq<;~?uA1gS29 zCAwgr09uj#sG?mtQQ1dmwabWQTUlqvbebkq9azq6Dv{tXbE1KaqJN|%$BW< z&a+F}ViM8i@sy_}YW~k?6J|?@V~J^&Lb~2CEa_$tKOj`db?QuY5h~T*6cWUkF{j(J zWSYYp(?vfNC}J;Y+7~$L?3$oVxQ{AGaJbzGf#)#3p^UF=ACE~K)5Ft&`W zPG4vkY26SsM#=dK)nHFz;!4UooUN}rO1^^=s@tcMc)pU%e#nA)$wCrzcfjh3f>~jd z%i(6;Fe9JLz9!NI=st&53qTi=L4YY~gSZY1z>=tTSZ8k6B&hXCPcbLa;(|AW*j$N@ z1lyqOPAa`RqM(gfBtCbOkRNr_Gt#OGPOIvhEo=yAh9YXNmf(ojB$ldM^jwyc!2U_{ z9DY~3!>b$WB`DezDe2!U&wP^TN6U6rRmViDdzeQzYjm_VGRf_!NSKoPiWo)4W?bIL z9e2;DSGd)S%sjJ^{S_Nlug3a*3|%vUq@zrUr%Va|Kh@YX_?Bc_Ovb2tZu!X8+V^In zq@!Djr(22mpPVjFfK($$jnpDDl1gi|+hvWaVTez3n~0K*c_p5CC7L^YQ;i-@8+%`# zGdIS#qRzoVOS#|d7i3AY*c~yRE7D!w%h5euo|fSbcT%GWTSAQ8>bXI^lRL?7OR&1U zQbuI$NgJ{XBn@;FTdY`qaw=SxtdCndjOyUZ(ES>Sf5Rk{l-! zD8NOYTUR)lsBW?IG6g=*b2kJhBNTp@swGoS=DAjbm#Gw?ml03jvQ8!-0entCNS1)i zbGt#8aq(BVMwZVFs=xNsEWP%w188Txa6V1Rj5t|_f5g-N?AciDB z3>nNnLG;|GrVEibeVEm{^ z!T3?nZwlpPk_2U*UvACGJV(#;GRfo2IGF%=O^^`aCPDI?h~Q+Ni~Tqmk-_*$6!4HB zNiwiQ^86kWPNqOEk1D-@?A_zbRxs$n2K?E`x@F_BTuJ_c-GJ5wonE?DMVvY;oGRFXL8OcH!F_6g; z)I|Yn5UGX$nE=)dGVrU6?ZF&pVFZ}Fi1}5Z3!-4IF$ge+5Hgq>q8Yw(QGoAKMDQJn zBJgjBCuAuM2E2S&j6uxJefJ1_=*24PQo zF(;$Irywi=|G~mK3hclNh#e8}ly5khAOSlF0zL&15%>zkTqv-E5Wwv$!~~p;hy=J8 z5gBkSo05P#5j6u&L=*w8LsSGD#zI@jO%%pvh#K$m-jUZ!|9T{)Qm*O7t=_Ern2sK`F$L;CfR$^=nS%x${CNV>AiYpr}Sz zK!!kECz|29WV2p^7(|8`Fb)&Vk_<6q8Dc14{j!t^#7&Iufu9it1lF|35*mQPk^>pY zh=Ghk88U;hXKn_LJwg%!G7<2f$cUE$8G+->2mwCNU`&xLL!Dvn%+gB`PcqkN@Hyyv zME1uFWEl87Q6wV#E(LiRTlv5bilU4mh63_3mJ&n#m=6UQ%!dLDECPSYvOEGY2!R+B zt{E&z5JNW5PXRp1WFVGe+CdB!vQj96Yn33tCG2$w@N?JGQ+hm!Q7OEr@*hW+*L#g z*r8zPyA=ZGkV4@cVyPdnLxFV=QBlAg!e;1y)si3vG6d!UHpBV>HWR=(*i1pb&mwA& z$77bRA|O*hT#OC!ZY;o>C1!ayu!H5@zzzX}b&gp`2<#A`f5UMWa~&axT!H!KT~OJum`piWbWA;NVjW4JD5 z0_U?#;e3{14uM&|4|S1c_&f#pLB=l74=Mu4O|gQYUr%}a^23*1z48(*ia)fI^6bbws+_z#fzz0NxH44I#SOv=9 zykZFxC-Q03Tw!O z!WuGRAuIf@2*;kKM*x??9FfT&Zz!-H%RD2*P~e_FQQ#g1lR-XE6v!_M?7?6%@Q$e2 z401Xq1AIW$ZXqZG<4nyko}}sy7m$fy{HR*pgfhUp)Ql0d153~jB0xLf{G(=ShIUX4 z?VvKWLlU7K(4SMYEI>PC0_}h~9g|^b2dsHe0oI^sMz<&@6F{uYWFRi40s=J;CIfzp z3b2=i3XuPp48$~4zyh=b#+XzfW@rb&&<>(NJE#clpc1r05}+Ltg?7khXorlU9kK%L zP()}4jO!>egIJWw04GueIh)BqO_0fef1?QQX)+mzrKsAJ0A(OfqzLXOGZ}$)zPC`Xk z^PmPbC@R95Ad`W(ovj2An^ASs3(6E|2i)6cG8x)I5VQm4Lh2RB3_=R|`3oJi206WCM9WYC{8RiGUT^ydWj^im3Yz?lsCa~32KD1-i-!d?T)93h4> z=+7xUmp~2rnkgd=Xa|P=oMPzDDS`f+4L-DkLVwQwKszMp&)F-7c1X~lQyKbmgMDI3 zVJ(Bnpg)&jeS^uMKbK(6uC}U4PzL?E1kVC68T988?A2Ab$`O=7e=cF@&kcIT*)T(Y zF2On+i(;Wam*5@-lR9h2^+~^Tqm)~CIA_%x65WhfHD#Ask*(O0GR~*r7S3b>tqD`4rP%5zsjrt{!J#Z zZ%Jlc48BWYJx4aEdB_y*?M&E1;l@9%c25gFz;3bc;-hz zaGz5V;W+~4Jpiw%?T#XlNf4L7`inx%V60dc0Oq*DLLcy53FfAXB!hLND53;qAm&mp zeWp+b&TFW5J}TgIqQJ+K>V0B752+VzN#J=Ho8jjuKhEmqCVYIL-sZutRl(zEfK1`n zo4Wf!fE}`#0y`8;fi8?+c$sQ21v0>~f?zPFf*=F^1QGNfFd666$ z%w(X}Cm<{$C?iltKp%yGs2Qvyb;|~Pm-&5u?jjlSJT9m`;NWu#2J47f#^*DFsP6Ux z8HFKgKBjb%ngJ69zosP;dN$N58!bkn+2e=0?vFhnFQV?6$HMv#AG7icB&r!0x|;Z zP`8g{AOrPwfkpDb_psca&vls#05Kes5e#r81%6HzfDdIcI^c1t5Wa>YNU$$bJxU8= z0SSTqHzor$WY6(h3SIw?h`7 z|BwYx^I$Rs=)$sO@Q!4-kIme)4B{r4fF2;#bqi1i@)?1}<7S|rB7?Q12;i;*^%e&( zek`Tqb8+<;E&|WPGN0Rfj^>I$h5(na=?8q7LJ@c$3dIoDAWl?dGvHm8lJGS=HO%41 zMLpKb`x)ekICvQXXXlW5z>M-TST9Cun~}oH2slT8)CL&vU3ktPsTxiryfrRI;+7C zkYT_>$m1M&83lVCNNtTW^D+te1(gvo7#9ibmoXXPYZOdIp?;DK?T|okEn*~wp-h0f z$f5x3l|k&oWMJ=3z2$@eon?u_?}EJ;mIZ+N0h56~cy&h;+N*#)W~34autT8)eh&1U zFd3*>s;LWDtH=!M#YkQJ1js}Meh$P^Oa}Hzm`vjHRVD-b8Z3=6gSo~=iswlt13kS+ zZLb5k0yuk(Jd+K`Kuv~4&t?p8kpS&LBGeCooQcT@9D4-fPW9+Nl!@Se1||dd8Za5i z=~VS(@GeDyz`GRTyi(8B1KUIe+J?<=4q?#SsNQ-6I0C7S`anhuWEA))^&CCW56keK zW6*EQUWb{F&5(MI9_Y-53Sba$$B}v>1g;MjqQmck{e5+62vBA)&J>(2U@`&DQwn-r zm`sH4mtqP(2ll&}jKXISi-G|QuIT)MvW;j+7IQx&(x&^?HK#wL;+asWi!ts+N z5z1u9Ly|%Ou52dYoy#C6W-@T*5vgq%PzLT@U^3`05py$Op30H}-lZ(VF;&cP{wZM3 zkjW6_KjwbHyHv0U^izXdAfpB{3HWZL$Z(x23Lo2g=#Kyys52n-Y`p|zpjRBJwJHV3 zK;J);fjpkcWHZDCXX213fIcYo+7twE1<V!fWCZGmVV=SwZxPC53f?aPJ(Wxb>LtkF>^hTy`Wlmg zo@gec68tVWm(OGdW5v=a@Lh`FyjL5wfD8kEX5otr#)TTJ1uDV$N5TD$NImlnWiU?` zB@vE+1kTPO^(;4(fjcFbOo3w{o8j7$LEoGjuEFQQd(fB+=JuiteWQBz8h%%SysMZY z? + + CUPS - Manuel de l'administrateur CUPS + + + + + + + +

Préface

+

Ce manuel de l'administrateur fournit les informations d'administration pour le +système d'impression CUPSTM (Common UNIX Printing SystemTM) version 1.1.14.

+ +


Note du traducteur : Amies lectrices, amis lecteurs, j'ai fait le choix de ne pas traduire l'expression anglaise "default" par la +version française +habituellent utilisée "par défaut" que l'on doit, entre autres, à la documentation d'un célèbre système d'exploitation "ouvert à tous vents". +

+En effet, l'expression "par défaut" est normalement utilisée en mathématiques (arrondi "par défaut" ou "par excès", +personnellement je cherche encore mon "imprimante par excès" !) +mais elle est abusivement employée en informatique pour signifier "donnée/comportement qui s'applique si l'on n'en +précise pas explicitement la valeur/nature/teneur". +

+Or la langue française possède justement un mot pout exprimer ce concept +: "implicite" (Larousse 1998 : "Qui est contenu dans une proposition sans être exprimé en termes précis formels; qui est la +conséquence nécessaire."). Dans la mesure du possible, j'utiliserai +cet adjectif sauf dans les cas où son emploi n'est pas suffisamment explicite (sic !). Je lui +préfèrerai alors l'expression "... de base ..." ou l'adjectif "standard". +

+Ce choix est totalement personnel et le fait que j'ai fait l'effort (non négligeable) de traduire ces lignes pour vos yeux délicats suffit à le justifier! Si, par malheur, ma prose vous est insupportable, +je ne vous empêche aucunement de vous reporter à la version originale où vous retrouverez "default" entouré de tout le +reste... en anglais, bien sûr. Enfin, si vous avez une meilleure traduction, je suis preneur ! +

+Malgré les très nombreuses relectures et corrections, certaines fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les signaler afin de contribuer à +l'amélioration constante de la qualité du présent manuel. +

+Bonne lecture ! +

+ + +

Aperçu du système

+ +

CUPS fournit une couche d'impression portable pour les systèmes d'exploitation de +type UNIX®. Il a été développé par Easy + Software Products pour promouvoir une solution d'impression standard pour +tous les vendeurs et utilisateurs d'UNIX. CUPS fournit des interfaces en ligne de +commande de type System V et Berkeley. +

+ +

CUPS utilise le protocol IPP (Internet Printing Protocol) comme base de l'administration +des travaux et files d'impression. Les protocoles LPD ("Line Printer Daemon"), SMB +("Server Message Block"), et AppSocket (JetDirect) sont également pris en charge avec +des fontionnalités réduites. CUPS ajoute l'exploration réseau des imprimantes ("network +printer browsing") et des options d'impression basées sur PPD ("PostScript Printer +Definition") pour prendre en charge l'impression "dans le monde réel" sous UNIX. +

+ +

CUPS inclut également une version adaptée de GNU/Ghostscript (actuellement basée +sur la version 5.50) et un module de rendu (RIP - Raster Image Processor) pour fichier image qui sont utilisés pour prendre +en charge les imprimantes non-PostScript. Des pilotes d'exemple (incluant ces filtres) +pour imprimantes HP et EPSON sont également inclus. +

+ + +

Aperçu du document

+

+Ce manuel de l'administrateur est organisé de la manière suivante: +

+ + +

Conventions d'écriture

+ +

+ +

+

Abréviations

+ Les abréviations suivantes sont utilisées au cours de ce manuel: +
    +
    +
    ko
    +
    Kilo-octets, ou 1024 octets +
     
    +
    Mo
    +
    Méga-octets, ou 1048576 octets +
     
    +
    Go
    +
    Giga-octets, ou 1073741824 octets +
     
    +
    +
+

Autres références

+
    +
    +
    CUPS - Manuel du programmeur (en anglais)
    +
    Un guide du programmeur pour interagir avec CUPS ou y ajouter des extensions. +
     
    +
    CUPS - Manuel de l'utilisateur
    +
    Un guide d'utilisation pour l'utilisateur final du logiciel CUPS. +
     
    +
    +
+

1 - Aperçu du système d'impression

+

Ce chapitre fournit un aperçu de la manière dont CUPS fonctionne.

+

Le problème d'impression

+

Depuis des années le problème d'impression a empoisonné le monde UNIX. +Contrairement à Microsoft® Windows® ou Mac OS, UNIX n'a pas d'interface standard ou +de système en place pour prendre en charge les imprimantes. Parmi les solutions actuellement +disponibles, les systèmes Berkeley et System V sont prédominants.

+ +

+ Ces systèmes d'impressions prennent en charge les imprimantes de type matriciel texte ou les + imprimantes PostScript (texte et graphique), et avec quelques ajustements il peuvent prendre en + charge un grand nombre d'imprimantes et de formats de fichiers. Cependant, puisque chaque + version de système d'exploitation UNIX utilise un système d'impression différent de celui + de son voisin, il est extrêmement difficile de développer des pilotes d'imprimantes pour une + vaste gamme d'imprimantes et de systèmes d'exploitation. Ceci, combiné au faible nombre de + clients pour chaque variante d'UNIX, a poussé les fabricants d'imprimantes à abandonner la prise en + charge globale de tous les UNIX. +

+ +

+ CUPS est conçu pour éliminer le problème d'impression. Un système d'impression + commun peut être utilisé par toutes les variantes d'UNIX pour prendre en charge les + capacités d'impression dont les utilisateurs ont besoin. Les fabricants d'imprimantes peuvent + utiliser l'interface modulaire des filtres pour développer un unique pilote qui prend en charge une + large gamme de formats de fichiers et ce, sans presque aucun effort. Etant donné que CUPS fournit + une interface compatible avec les commandes Berkeley et System V, les utilisateurs (et les applications) + peuvent tirer bénéfice de cette nouvelle technologie sans avoir à faire de changements. +

+ +

La technologie

+ +

+ CUPS est basé sur un standard émergeant d'Internet appelé IPP (Internet Printing Protocol). IPP a été adopté + par des douzaines de fabricants d'imprimantes et de serveurs d'impression et est pris en charge par + Microsoft Windows 2000. +

+ +

+ IPP définit un protocole standard pour imprimer ainsi qu'administrer les travaux d'impression et les options + des imprimantes telles que la taille du support d'impression, la résolution, etc. Comme tout protocole de la pile + TCP/IP, IPP peut être utilisé localement ou à travers Internet pour atteindre des imprimantes éloignées de centaines + ou de milliers de kilomètres. Contrairement à d'autres protocoles de la pile TCP/IP, IPP prend en charge le + contrôle d'accès, l'authentification et l'encryptage, ce qui fait de lui une solution d'impression bien plus efficace + et sécurisée que ses ancêtres. +

+ +

+ IPP est une surcouche ajoutée au-dessus du protocole HTTP (HyperText Transport Protocol) qui est à la base + des serveurs "web" sur l'Internet. Ceci permet aux utilisateurs de lire la documentation, vérifier les informations + sur l'état des imprimantes ou du serveur, administrer les imprimantes, les classes d'imprimantes et les travaux + d'impression en utilisant leur navigateur "web". +

+ +

+ CUPS fournit un système d'impression complet basé sur IPP/1.1 prenant en charge l'authentification + "Basic", "Digest" et par certificats locaux ainsi qu'un contrôle d'accès basé sur l'utilisateur, + le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une future version de CUPS. +

+ +

Travaux d'impression

+ +

+ Tout fichier ou groupe de fichiers soumis à l'impression est appelé un travail d'impression. Les travaux + d'impression sont identifiés par un nombre unique en commençant à 1 et sont affectés à une destination particulière, + généralement une imprimante. Les travaux d'impression peuvent également inclure des options associées telles que la + taille du support d'impression, le nombre de copies et la priorité dans la file d'impression. +

+ +

Classes d'imprimantes

+ +

+ CUPS prend en charge des collections d'imprimantes connues sous le nom de classes. Les travaux d'impression + transmis à une classe d'imprimantes sont envoyés à la première imprimante disponible dans la classe. +

+ +

Filtres

+ +

Les filtres permettent à un utilisateur ou une application d'imprimer de nombreux types de documents sans +effort supplémentaire. Les travaux d'impressions envoyés au serveur CUPS sont filtrés avant d'être envoyés à +l'imprimante. Certains filtres convertissent les fichiers de travaux d'impression dans différents formats que +l'imprimante peut comprendre. D'autres ne font que des sélections de page et des tris. +

+ +

CUPS fournit des filtres pour imprimer de nombreux types de fichiers image, des fichier HP-GL/2, +fichiers PDF et texte. CUPS fournit également des filtres PostScript et RIP (Raster Image Processor) qui +convertissent les fichiers PostScript ou image en format "bitmap" qui peut être envoyé à une +imprimante de type "matriciel" (NdT : il s'agit ici, des imprimantes dont l'impression est générée au moyen d'une +grille de points +comme l'étaient les vénérables imprimantes à aiguilles de notre enfance, mais pas seulement elles puisque les +imprimantes à jet +d'encre actuelles sont également de type matriciel... par opposition aux imprimantes laser dont la méthode de génération +d'impression est différente.) +

+ +

Programmes d'arrière-plan (Backends)

+ +

Les programmes d'arrière-plan effectuent le travail le plus important : ils envoient les données +d'impression à l'imprimante. +

+ +

CUPS fournit des programmes d'arrière-plan pour imprimer via des ports de type parallèle, série, USB et à travers un +réseau au moyen des protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des programmes d'arrière-plan +additionnels sont disponibles sous forme de paquetage de service réseau comme le programme d'arrière_plan SMB +inclus dans le célèbre logiciel SAMBA. +

+ +

Les programmes d'arrière-plan sont également utilisés pour déterminer les périphériques +disponibles. Au démarrage, chaque programme d'arrière-plan est interrogé afin de déterminer la liste des +périphériques qu'il prend en charge, ainsi que toute information disponible. Cela permet au programme d'arrière-plan +de gestion du port parallère d'indiquer à CUPS qu'une imprimante EPSON Stylus Color 600 est branchée sur le port +parallèle 1, par exemple. +

+ +

Pilotes d'imprimantes

+ +

Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs filtres spécifiques à une imprimante. CUPS inclut +des pilotes d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet Hewlett-Packard et les imprimantes EPSON jet +d'encre couleur Stylus Color, Stylus Photo et les modèles 9 et 24 aiguilles matricielles. Bien que ces pilotes ne produisent +pas des impressions de qualité optimale pour les différents modèles d'imprimantes, ils fournissent une impression de +base et démontrent comment vous pouvez écrire vos propres pilotes d'imprimantes et les incorporer dans CUPS. +

+ +

Réseau

+ +

Les imprimantes et classes d'imprimantes sur le système local sont automatiquement partagées avec les autres systèmes +sur le réseau. Cela vous permet de configurer un système hôte pour tous les autres. Les utilisateurs pourront sélectionner +une imprimante locale par son nom ou une imprimante à distance en utilisant la syntaxe "nom_imprimante@serveur". +

+ +

CUPS fournit également des classes d'imprimantes implicites (NdT : le terme "implicite" est ici la traduction +litérale du même mot anglais "implicit" et non celle de l'expression "default". cf. ma remarque dans la préface du présent manuel. +De toute façon, CUPS ne prévoit pas de "default class" c'est-à-dire de "classe de base", donc aucune ambiguïté possible +ici.), qui sont des collections d'imprimantes ou +de classes d'imprimantes qui portent le même nom. Cela vous permet de configurer de multiples serveurs pointant vers +la même imprimante réseau physique, par exemple, de sorte que vous ne dépendez pas d'un seul serveur pour pouvoir +imprimer. Etant donné que cette méthode vous permet de travailler avec des classes d'imprimantes, vous pouvez configurer +de multiples serveurs et imprimantes sans jamais vous soucier d'un simple point en panne tant que tous les autres serveurs +ne tombent pas en panne en même temps. +

+ +

2 - Construire et installer CUPS

+ +

Ce chapitre décrit comment construire et installer CUPS. Si vous installez une distribution binaire (précompilée) du produit, +veuillez vous reporter à la section, Installer une distribution binaire. +

+ +

Installer à partir d'une distribution du code source

+ + +

Cette section décrit comment compiler et installer CUPS sur votre système à partir du code source du produit.

+ +

Conditions nécessaires

+ +

Vous aurez besoin d'un compilateur C et C++ conforme à la norme ANSI pour construire CUPS sur votre système. +Comme son nom l'indique, CUPS est conçu pour fonctionner sur le système d'exploitation UNIX, cependant la plupart des +librairies, des filtres et des programmes d'arrière-plan devraient également se compiler et fonctionner sous Microsoft Windows. +

+ +

Pour les filtres de fichiers image et PostScript, vous aurez besoin des librairies JPEG, PNG, TIFF et ZLIB. CUPS +se construira sans elles mais avec des fonctionnalités singulièrement réduites. Easy Software Products maintient un +miroir des versions actuelles de ces librairies à l'adresse: +

+ + + +

Si vous faîtes des changements dans les pages de manuel vous aurez besoin de GNU groff ou d'un autre +paquetage compatible nroff. GNU groff est disponible à l'adresse: +

+ + + +

La documentation est formatée en utilisant le programme HTMLDOC. Si vous voulez faire des changements, vous pouvez +obtenir le programme HTMLDOC à l'adresse: +

+ +

+ +

Enfin, vous aurez besoin d'un programme make qui comprend les directives include - les +développeurs FreeBSD, NetBSD et OpenBSD devraient utiliser le programme gmake. +

+ +

Compiler CUPS

+ +

CUPS utilise GNU autoconf pour configurer les "makefiles" et le code source pour votre système. Tapez simplement la +commande suivante pour configurer CUPS pour votre système: +

+ +
    +
    +./configure ENTREE
    +
    +
+ +

L'installation standard installera CUPS dans les répertoires /etc, /usr, et /var +de votre système, ce qui écrasera toute commande d'impression existant déjà dans votre système. Utilisez l'option +--prefix pour installer CUPS à un autre emplacement: +

+ +
    +
    +./configure --prefix=/autre/répertoire ENTREE
    +
    +
+ +

Si les librairies PNG, JPEG, TIFF, et ZLIB ne sont pas installées à un emplacement habituel du système (généralement +il s'agit de /usr/include et /usr/lib) vous devrez définir les variables d'environnement CFLAGS, +CXXFLAGS, et LDFLAGS avant d'exécuter la commande configure: +

+ +
    +
    +setenv CFLAGS "-I/some/directory" ENTREE
    +setenv CXXFLAGS "-I/some/directory" ENTREE
    +setenv LDFLAGS "-L/some/directory" ENTREE
    +setenv DSOFLAGS "-L/some/directory" ENTREE
    +./configure ... ENTREE
    +
    +
+

ou:

+
    +
    +CFLAGS="-I/some/directory"; export CFLAGS ENTREE
    +CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTREE
    +LDFLAGS="-L/some/directory"; export LDFLAGS ENTREE
    +DSOFLAGS="-L/some/directory"; export DSOFLAGS ENTREE
    +./configure ... ENTREE
    +
    +
+ +

Pour activer le support de l'encryptage, vous devrez également activer l'option "--enable-ssl": +

+ +
    +
    +./configure --enable-ssl
    +
    +
+ +

La prise en charge SSL et TLS nécessite la librairie OpenSSL, disponible à l'adresse: +

+ + + +

Si les en-têtes et les librairies OpenSSL ne sont pas installées dans les répertoires standards, utilisez les +options --with-openssl-includes et --with-openssl-libs: +

+ +
    +
    +./configure --enable-ssl \
    +    --with-openssl-includes=/foo/bar/include \
    +    --with-openssl-libs=/foo/bar/lib
    +
    +
+ +

Une fois que vous avez configuré toutes ces choses, tapez simplement: +

+ +
    +
    +make ENTER
    +
    +
+ +

pour compiler le logiciel.

+ + +

+ +

Installer le logiciel

+ +

Utilisez la cible "install" pour installer le logiciel: +

+ +
    +
    +make install ENTREE
    +
    +
+
+ + +
AVERTISSEMENT: + +

Installer CUPS écrasera votre système d'impression précédent. Si vous rencontrez des difficultés avec le logiciel +CUPS et devez revenir à votre ancien système d'impression, vous devrez réinstaller celui-ci à partir de CD originaux +de votre système d'exploitation. +

+ +
+
+

Exécuter le logiciel

+ +

Une fois que vous avez installé le logiciel vous pouvez démarrer le serveur CUPS en tapant: +

+ +
    +
    +/usr/sbin/cupsd ENTREE
    +
    +
+ + +

Installer une distribution binaire du logiciel

+ +

CUPS est fourni dans une variété de formats binaires. Easy Software Products fournit des binaires sous forme +d'archives au format TAR avec des scripts d'installation et de désinstallation (distributiond dites "portables"), +sous forme de format RPM et DPKG pour les distributions RedHat et Debian. Les distributions portables sont disponibles +pour toutes les plateformes tandis que les distributions RPM et DPKG ne le sont que pour GNU/Linux +

+
+ + +
AVERTISSEMENT: + +

Installer CUPS écrasera votre système d'impression précédent. Si vous rencontrez des difficultés avec le logiciel +CUPS et devez revenir à votre ancien système d'impression, vous devrez réinstaller celui-ci à partir de CD originaux de +votre système d'exploitation. +

+ +
+
+

+ +

Installer une distribution portable

+ +

Pour installer le logiciel CUPS à partir d'une distribution portable vous devrez ouvrir une session en tant +qu'utilisateur root; utiliser la commande su est suffisant. Une fois que vous êtes utilisateur root, +lancer le script d'installation avec la commande: +

+ +
    +
    +./cups.install ENTREE
    +
    +
+ +

Après vous avoir posé quelques questions de type oui/non, le logiciel CUPS va s'installer et l'ordonnanceur sera +démarré automatiquement. +

+ + +

+

Installer une distribution de type RPM

+

Pour installer le logiciel CUPS à partir d'une distribution RPM vous devez ouvrir une session en tant qu'utilisateur +root; utiliser la commande su est suffisant. Une fois connecté en tant qu'utilisateur root, lancez simplement +RPM au moyen de la commande: +

+ +
    +
    +rpm -e lpr
    +rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTREE
    +
    +
+

Après un petit délai, le logiciel CUPS sera installé et l'ordonnanceur sera démarré automatiquement.

+ +

Installer une distribution de type DEBIAN

+

Pour installer le logiciel CUPS à partir d'une distribution DEBIAN vous devez ouvrir une session en tant qu'utilisateur +root; utiliser la commande su est suffisant. Une fois connecté en tant qu'utilisateur root, lancez simplement +dpkg au moyen de la commande: +

+ +
    +
    +dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTREE
    +
    +
+ +

Après un court délai, le logiciel CUPS sera installé et l'ordonnanceur sera automatiquement démarré.

+ +

3 - Administration les imprimantes

+ +

Ce chapitre décrit comment ajouter votre première imprimante et comment administrer vos imprimantes. +

+ +

Les bases

+ +

Chaque file d'impression a un nom associé; le nom de l'imprimante doit commencer avec une lettre et peut comporter +jusqu'à 127 lettres, des chiffres ou un caractère de soulignement "_" ("underscore"). La casse des caractères n'est pas +significative, par exemple les chaînes de caractères "IMPRIMANTE", "Imprimante" et +"imprimante" sont considérées comme +le même nom. +

+ +

Les files d'impression ont également un périphérique associé. Ce périphérique peut être un port parallèle, une +interface réseau, etc. Les périphériques dans CUPS utilisent des URI (Uniform Resource Identifiers) qui sont une +forme plus générale des URL (Uniform Resource Locator) qui sont utilisés par votre noavigateur "web". Par exemple, +le premier port parallèle dans GNU/Linux est habituellement désigné par l'URI de périphérique parallel:/dev/lp1. +

+ + +

+ +

Vous pouvez voir une liste complète des périphériques pris en charge en lançant la commande lpinfo(8): +

+ +
    +
    +lpinfo -v ENTREE
    +file file
    +network socket
    +network http
    +network ipp
    +network lpd
    +direct parallel:/dev/lp1
    +serial serial:/dev/ttyS1?baud=115200
    +serial serial:/dev/ttyS2?baud=115200
    +direct usb:/dev/usb/lp0
    +network smb
    +
    +
+ +

L'option -v indique que vous voulez la liste de tous les périphériques disponibles. Le premier +mot de chaque ligne est le type de périphérique (direct, fichier, réseau, série) et est suivi par l'URI du périphérique +ou le nom de la méthode d'accès à ce périphérique. Les périphériques de type fichier ont des URI de périphérique de la +forme file:/répertoire/nom_fichier tandis que les périphériques réseau utilisent la forme plus familière + methode://serveur ou méthode://serveur/chemin. +

+ +

Enfin, les files d'impression ont généralement un fichier PPD (PostScript Printer Definition) associé. Les fichiers +PPD décrivent les capacités de chaque imprimante, les tailles de support prises en charge, etc., et sont utilisés pour +les imprimantes PostScript et non-PostScript. CUPS inclut des fichiers PPD pour les imprimantes HP LaserJet et Deskjet, +EPSON Stylus, et EPSON 9 et 24 aiguilles. +

+ +

Ajouter votre première imprimante

+ +

CUPS fournit deux méthodes pour ajouter des imprimantes : un programme en ligne de commande nommé +lpadmin(8) et une inteface "web". La commande lpadmin vous permet d'effectuer la plupart des +tâches d'administration d'imprimantes à partir de la ligne de commande, elle est située dans le répertoire /usr/sbin. +L'interface "web" est disponible à l'adresse: +

+ + +

et vous quide pas à pas au travers des étapes de configuration d'imprimante. Si vous n'aimez pas les interfaces en +ligne de commande, essayez plutôt l'interface web. +

+ +

Ajouter votre première imprimante depuis la ligne de commande

+ +

Exécutez la commande lpadmin avec l'option -p pour ajouter une imprimante à CUPS:

+ +
    +
    +/usr/sbin/lpadmin -p imprimante -E -v périphérique -m ppd ENTREE
    +
    +
+ +

Pour une imprimante HP DeskJet connectée au port parallèle, la commande serait:

+ +
    +
    +/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTREE
    +
    +
+

De la même manière, une imprimante HP LaserJet utilisant une interface réseau de type JetDirect à l'adresse IP 11.22.33.44 +serait ajoutée avec la commande:

+ +
    +
    +/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTREE
    +
    +
+ +

Comme vous pouvez le voir, deskjet.ppd et laserjet.ppd sont les fichiers PPD pour les pilotes +HP DeskJet et HP LaserJet inclus dans CUPS. Vous trouverez une liste complète des fichiers PPD ainsi que celle des imprimantes +avec lesquelles ils fonctionnent dans l'Annexe C, "Pilotes d'imprimantes". +

+ +

Pour une imprimante matricielle à aiguilles connectée au port série, la commande serait:

+ +

    +
    +/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTREE
    +
    +
+ +

Ici, vous indiquez le port série (par exemple S0, S1, d0, s1), le taux de transfert en bauds (par exemple 9600, 19200, +38400, 115200, etc.), le nombre de bits de partié, et le contrôle de flux. Si vous n'avez pas besoin de contrôle de flux, +supprimez la partie "+flow=soft". +

+ +

Ajouter votre première imprimante depuis l'interface "web"

+ +

Le serveur CUPS fournit une interface ergonomique sous forme d'un assistant ("wizard") pour ajouter les imprimantes. +Plutôt que devoir déterminer quel URI de périphérique et quel fichier PPD utiliser, vous cliquez simplement sur l'option +adéquate de la liste et vous remplissez quelques champs de formulaires avec des informations simples. Entrez l'adresse suivante +dans votre navigateur "web" pour commencer: +

+ + + +

Cliquez sur le bouton Ajouter imprimante pour en ajouter une.

+ +

Administrer les imprimantes depuis la ligne de commande

+ +

La commande lpadmin vous permet d'effectuer la plupart des tâches d'administration d'imprimantes depuis la +ligne de commande. Vous trouverez lpadmin dans le répertoire /usr/bin. +

+ +

Ajouter et modifier des imprimantes

+ +

Exécutez la commande lpadmin avec l'option -p pour ajouter ou modifier une imprimante. +

+ +
    +
    +/usr/sbin/lpadmin -p imprimante options ENTREE
    +
    +
+ +

Les arguments options peuvent être n'importe lesquels parmi: + +

    +
    +
    -c classe
    +
    Ajoute l'imprimante nommée à la classe d'imprimantes classe. Si la classe d'imprimantes n'existe +pas alors elle est créée.
    +
    -i interface
    +
    Copie le script pour l'interface vers l'imprimante. Les scripts d'interface sont utilisés par les pilotes d'imprimantes +System V. Etant donné que tous les filtres sont désactivés lorsque les scripts d'interface sont employés, les scripts ne devraient +normalement jamais être utilisés à moins qu'il n'y ait aucun autre pilote pour l'imprimante.
    + +
    -m modèle
    +
    Indique une pilote d'imprimante standard qui est généralement un fichier PPD. Une liste de tous les modèles disponibles peut +être affichée au moyen de l'option -m. Une liste de tous les pilotes d'imprimantes inclus dans CUPS peut être +consultée dans l'Annexe + C, "Pilotes d'imprimantes".
    + +
    -r classe
    + +
    Retire l'imprimante spécifiée de la classe d'imprimantes classe. Si la classe qui en résulte est vide, elle est +supprimée.
    + +
    -v uri-périphérique
    +
    Indique le périphérique à employer pour dialoguer avec l'imprimante. Si un travail d'impression est actuellement en +cours d'édition sur l'imprimante spécifiée, il est relancé et envoyé au nouveau périphérique.
    + +
    -D info
    + +
    Fournit une description textuelle de l'imprimante, par exemple "Imprimante personnelle de Marcel".
    + +
    -E
    + +
    Active l'imprimante et accepte les travaux d'impression. Cette option équivaut à exécuter les commandes +enable(1) et accept(8).
    + +
    -L emplacement
    +
    Fournit une description textuelle de l'emplacement de l'imprimante, par exemple "Salle informatique n°5".
    + +
    -P fichier-ppd
    +
    Indique un fichier PPD local pour le pilote d'imprimante.
    +
    +
+ +

Supprimer des imprimantes

+ +

Exécutez la commande lpadmin avec l'option -x pour supprimer une imprimante:

+ +
    +
    +/usr/sbin/lpadmin -x printer ENTREE
    +
    +
+ +

Choisir l'imprimante implicite

+ +

Exécutez la commande lpadmin avec l'option -d pour définir l'imprimante standard: +

+ +
    +
    +/usr/sbin/lpadmin -d printer ENTREE
    +
    +
+ +

L'imprimante standard peut-être outrepassée par l'utilisateur au moyen de la commande lpoptions(1).

+ +

Démarrer et arrêter des imprimantes

+ +

Les commandes enable et disable démarrent et arrêtent les files d'impression, avec les syntaxes respectives suivantes :

+ +
    +
    +/usr/bin/enable imrimante ENTREE
    +/usr/bin/disable imprimante ENTREE
    +
    +
+ +

Note du traducteur : utilisateurs du shell BASH attention ! enable est une commande interne de celui-ci. +Si vous tapez simplement enable vous +obtiendrez un message d'erreur car c'est la version interne de BASH qui sera utilisée en standard. Pour effectivement utiliser la commande enable de CUPS +vous devez faire précéder son nom du chemin d'accès complet : /usr/bin/enable.

+ +

Les imprimantes qui sont désactivées peuvent toujours accepter les travaux d'impression mais n'en imprimeront effectivement +aucun tant qu'elle ne seront pas réactivées. Cela est utile si une imprimante fonctionne mal et que vous avez besoin de corriger +le problème (bourrage). Tout travail d'impression mis en file d'attente est imprimé dès que la l'imprimante est réactivée.

+ +

Accepter et rejeter les travaux d'impression

+ +

Les commandes accept et reject permettent respectivement d'indiquer à une imprimante +qu'elle doit accepter ou rejeter les nouveaux travaux d'impression:

+ +
    +
    +/usr/sbin/accept imprimante ENTREE
    +/usr/sbin/reject imprimante ENTREE
    +
    +
+ +

Comme indiqué ci-dessus, une imprimante peut être configurée pour ne plus accepter de nouveaux travaux d'impression. +Une imprimante peut aussi rejeter les nouveaux travaux d'impression bien qu'elle soit en train de terminer le traitement +de ceux qui ont été mis en file d'attente avant que celle-ci soit désactivée. Ceci est utile si vous avez besoin d'effectuer +des opérations de maintenance sur l'imprimante et que vous ne voulez pas qu'elle soit disponible pour les utilisateurs pendante +une longue période.

+ +

Administrer les imprimantes depuis l'interface "web"

+ +

L'interface "web" est disponible à l'adresse:

+ + + +

Depuis celle-ci vous pouvez effectuer toutes les tâches d'administrations sur les imprimantes au moyen de +quelques clics de souris.

+ + +

4 - Classes d'imprimantes

+ +

Ce chapitre décrit ce que sont les classes d'imprimantes et comment les administrer.

+ +

Les bases

+ +

CUPS fournit des collections d'imprimantes appelées classes d'imprimantes. Les travaux soumis à une classe sont +transmis à la première imprimante disponible de la classe. Les classes peuvent elles auusi être membres d'autres classes, ainsi +il est possible que vous définissiez de grandes classes réparties afin de fournir un système d'impression à haute disponibilité. +

+ +

CUPS prend également en charge les classe implicites. Les classes implicites fonctionnent comme les classes d'imprimantes, +mais elles sont créées automatiquement à partir des classes et imprimantes disponibles sur le réseau. Cela vous permet de +configurer de multiples serveurs d'impression avec des configurations d'imprimantes identiques de sorte que les systèmes +clients envoient des travaux d'impression au premier serveur disponible. Si un ou plusieurs serveurs deviennent indisponibles, +les travaux d'impressions sont automatiquement redirigés vers les serveurs encore en fonctionnement, fournissant ainsi un +système d'impression résistant aux pannes.

+ +

Administrer les classes d'imprimantes depuis la ligne de commande

+

Exécutez la commande lpadmin avec les options -p et +-c pour ajouter une classe d'imprimantes:

+
    +
    +/usr/sbin/lpadmin -p imprimante -c classe ENTREE
    +
    +
+

La classe est créée automatiquement si elle n'existe pas. +Pour retirer une imprimante d'une classe, utilisez l'option -r:

+
    +
    +/usr/sbin/lpadmin -p imprimante -r classe ENTREE
    +
    +
+

Pour enlever toute la classe, utilisez l'option -x:

+
    +
    +/usr/sbin/lpadmin -x classe ENTREE
    +
    +
+

Administrer les classes d'imprimante depuis l'interface "web"

+

L'interface "web" est disponible à l'adresse:

+ +

Les pages Ajouter classe et Modifier classe fournissent une liste des imprimantes disponibles. +Cliquez sur la ou les imprimantes de votre choix pour les ajouter à la classe.

+ +

Classes implicites

+ +

Comme indiqué auparavant, les classes implicites sont automatiquement créées à partir des imprimantes et des classes +disponibles sur le réseau. Pour désactiver cette fonctionnalité, +réglez la valeur de la directive ImplicitClasses sur Off dans +le fichier cupsd.conf. Vous trouverez plus d'information sur la manière de faire cela dans le + Chapitre 6, "Administration du système d'impression".

+ +

5 - Configuration côté client

+ +

Ce chapitre expose diverses manières de configurer les clients CUPS pour pouvoir imprimer.

+ +

Les bases

+ +

Un client est toute machine qui envoie des travaux d'impression à une autre machine pour édition finale. Les clients peuvent +également être des serveurs s'il communiquent directement avec des imprimantes qui leur appartiennent.

+ +

CUPS prend en charge plusieurs méthodes pour configurer les machines clientes:

+ + +

Configuration manuelle des files d'impression

+ +

La méthode la plus fastidieuse pour configurer les machines clientes est de configurer chaque file d'impression à distance +à la main au moyen de la commande lpadmin: + +

    +
    +lpadmin -p imprimante -E -v ipp://serveur/printers/imprimante ENTREE
    +
    +
+ +

Le nom imprimante est le nom de l'imprimante sur la machine serveur. Le nom serveur est le nom +d'hôte ou l'adresse IP de la machine serveur. Répètez la commande lpadmin pour chaque imprimante distante que +vous désirez utilser.

+ +

Choix d'un serveur unique pour l'impression

+ +

CUPS peut être configuré pour fonctionnner sans file d'attente locale et envoyer tous les travaux d'impression à un serveur +unique. Cependant, si ce serveur vient à tomber en panne, toute possibilité d'imprimer sera supprimée. Utilisez cette configuration +uniquement lorsque c'est absolument nécessaire.

+ +

Le serveur implicite est normalement "localhost". Pour outrepasser ce réglage de base, +créez un fichier nommé /etc/cups/client.conf et ajoutez une ligne:

+ + +
    +
    +ServerName serveur
    +
    +
+ +

au fichier. Le nom serveur peut être le nom d'hôte ou l'adresse IP du serveur implicite.

+ +

Le serveur implicite peut également être adapté en fonction de l'utilisateur. Pour créer un réglage +spécifique à l'utilisateur, créez un fichier nommé ~/.cupsrc et ajoutez une ligne: + +

    +
    +ServerName serveur
    +
    +
+

+

au fichier. Le nom serveur peut être le nom d'hôte ou l'adresse IP du serveur implicite.

+ +

Configuration automatique des files d'impression

+ +

CUPS prend en charge la configuration automatique des clients pour les imprimantes sur le même sous-réseau. Pour +configurer des imprimantes présentes sur le même sous-réseau, ne faîtes rien. Chaque client devrait voir +automatiquement les imprimantes disponibles dans un délai de 30 secondes. Les listes des classes et des imprimantes +sont automatiquement mises à jour chaque fois que des imprimantes et des serveurs sont ajoutés ou retirés.

+ +

Si vous désirez également voir les imprimantes sur d'autres sous-réseau, utilisez la directive +BrowsePoll comme indiqué ci-après. + +

Choix de plusieurs serveurs pour l'impression

+ +

Si vous disposez de plusieurs serveurs CUPS sur plusieurs sous-réseaux, vous devriez configurer CUPS pour +surveiller ces serveurs. La surveillance fournit l'avantage d'automatiser singulièrement la configuration sur les clients, et +plusieurs clients sur le même sous-réseau peuvent partager les mêmes informations de configuration.

+ +

La surveillance est activée en indiquant une ou plusieurs directives +BrowsePoll dans le fichier /etc/cups/cupsd.conf. Pour savoir comment +faire ces changements, veuillez vous reporter au + Chapitre 6, "Administration du système d'impression".

+ +

6 - Administration du système d'impression

+ +

Ce chapitre montre comment configurer le serveur CUPS.

+ +

Les bases

+ +

Plusieurs fichiers texte sont utilisés pour configurer CUPS. Tous les fichiers de configuration du serveur sont +placés dans le répertoire /etc/cups:

+ +
    +
    + + +
    classes.conf
    +
    Ce fichier contient les informations sur chaque classe d'imprimante. Normalement vous manipulez ce fichier en utilisant +la commande lpadmin ou l'interface "web". +
      + +
    +
    client.conf
    +
    +Ce fichier fournit le nom du serveur implicite pour les machines clientes. Veuillez vous reporter au +Chapitre 5, "Configuration côté client" pour de plus amples informations. +
      + +
    +
    cupsd.conf
    +
    +Ce fichier contrôle la manière de fonctionner sur serveur CUPS (/usr/sbin/cupsd) et est normalement édité à la main. +
      + +
    +
    mime.convs
    +
    Ce fichier contient une liste des filtres de base pour la conversion de fichier et leurs coûts respectifs. +Normalement, vous n'éditerez pas ce fichier. +
      + +
    +
    mime.types
    +
    Ce fichier contient la liste des formats de fichiers standards et comment les reconnaître. Normalement, vous n'éditerez pas ce fichier. +
      + +
    +
    printers.conf
    +
    +Ce fichier contient des informations sur chaque imprimante. Normalement, vous manipulez ce fichier en utilisant la commande +lpadmin ou l'interface "web". +
     
    +
    +
+

Redémarrer le serveur CUPS

+ +

Une fois que vous avez fait des changements au fichier de configuration, vous devez redémarrer le serveur CUPS en lui +envoyant un signal HUP ou en utilisant le script d'initialisation adéquat. Les distributions de CUPS installent +le script dans le répertoire init.d sous le nom cups. L'emplacement varie selon le système d'exploitation: +

+
    +
    +/etc/rc.d/init.d/cups restart ENTREE
    +/etc/init.d/cups restart ENTREE
    +/sbin/init.d/cups restart ENTREE
    +
    +
+

Changer la configuration du serveur

+ +

Le fichier /etc/cups/cupsd.conf contient des directives de configuration qui contrôlent le +fonctionnement du serveur. Chaque directive suivie de sa valeur est disposée seule sur une ligne. +Les commentaires sont ouverts par le signe dièse ("#") au début de la ligne. Etant donné que le fichier de +configuration du serveur est un fichier texte, vous pouvez le modifier au moyen de votre éditeur de texte préféré. + +

+ +

Directives de configuration du serveur

+ +

Le fichier cupsd.conf contient de nombreuses directives qui déterminent le comportement du serveur:

+ + + +

AccessLog

+
+

Exemples

+
    +
    +AccessLog /var/log/cups/access_log
    +AccessLog /var/log/cups/access_log-%s
    +AccessLog syslog
    +
    +
+

Description

+

La directive AccessLog donne le nom du fichier de suivi d'accès ("access log"). Si le chemin d'accès au fichier n'est pas +absolu, il est considéré comme relatif au répertoireServerRoot. +Le fichier "access log" est stocké dans le format "log" habituel et peut aisément être utilisé par tout outil +d'analyse d'accès "web" pour générer un rapport sur l'activité du serveur CUPS.

+

Le nom du serveur peut être inclus dans le nom du fichier en utilisant %s dans le nom.

+

Le nom spécial "syslog" peut être utilisé pour envoyer les informations d'accès au fichier de suivi système au lieu +d'un simple fichier texte.

+

Le fichier de suivi d'accès implicite est /var/log/cups/access_log. + +

+

Allow

+
+

Exemples

+
    +
    +Allow from All
    +Allow from None
    +Allow from *.domain.com
    +Allow from .domain.com
    +Allow from host.domain.com
    +Allow from nnn.*
    +Allow from nnn.nnn.*
    +Allow from nnn.nnn.nnn.*
    +Allow from nnn.nnn.nnn.nnn
    +Allow from nnn.nnn.nnn.nnn/mm
    +Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
    +
+

Description

+ +

La directive Allow indique un nom d'hôte, une adresse IP ou un réseau qui est autorisé à accéder au serveur. +Les directives Allow se cumulent, ainsi plusieurs directives Allow peuvent être utilisées pour +autoriser l'accès à de multiples hôtes et/ou réseaux. La notation /mm indique une notation de sous-réseau CIDR: +

+ + + + + + +
mmnetmask +mmnetmask
00.0.0.0 +8255.0.0.0
1128.0.0.0 +16255.255.0.0
2192.0.0.0 +24255.255.255.0
...... +32255.255.255.255
+
+

+

La directive Allow doit apparaître à l'intérieur d'une directive +Location. + +

+

AuthClass

+
+

Exemples

+
    +
    +AuthClass Anonymous
    +AuthClass User
    +AuthClass System
    +AuthClass Group
    +
    +
+

Description

+

La directive AuthClass définit le niveau d'authentification requis:

+
    +
  • Anonymous - Pas d'authentification nécessaire. C'est la valeur implicite
  • +
  • User - Un nom d'utilisateur et un mot de passe valides sont requis.
  • +
  • System - Un nom d'utilisateur et un mot de passe valides sont requis, et cet utilisateur doit être membre du +groupe "sys"; cela peut être changé au moyen de la directiveSystemGroup.
  • +
  • Group - Un nom d'utilisateur et un mot de passe valides sont requis, et cet utilisateur doit être membre du +groupe indiqué dans la directive AuthGroupName.
  • +
+

La directive AuthClass doit apparaître à l'intérieur d'une directive + Location. + +

+

AuthGroupName

+
+

Exemples

+
    +
    +AuthGroupName mygroup
    +AuthGroupName lp
    +
    +
+

Description

+

La directive AuthGroupName définit le groupe à utiliser pour l'authentification de type +Group.

+

La directive AuthGroupName doit apparaître à l'intérieur d'une directive + Location. + +

+

AuthType

+
+

Exemples

+
    +
    +AuthType None
    +AuthType Basic
    +AuthType Digest
    +AuthType BasicDigest
    +
    +
+

Description

+

La directive AuthType définit le type d'authentification qui doit être effectuée:

+
    +
  • None - Pas d'authentification. C'est la valeur implicite
  • +
  • Basic - Une authentification "Basic" doit être effectuée en utilisant le fichier de mots de passe et de groupe d'UNIX.
  • +
  • Digest - Une authentification "Digest" doit être effectuée en utilisant le fichier /etc/cups/passwd.md5.
  • +
  • BasicDigest - Une authentification "Basic" doit être effectuée en utilisant le fichier /etc/cups/passwd.md5.
  • +
+

+Lorsque vous utilisez Basic, Digest, ou +BasicDigest, les clients se connectant en utilisant l'adresse +localhost peuvent également le faire en utilisant les certificats. +

+

La directive AuthType doit apparaître à l'intérieur d'une directive + Location. + +

+

AutoPurgeJobs

+
+

Exemples

+
    +
    +AutoPurgeJobs Yes
    +AutoPurgeJobs No
    +
    +
+

Description

+

La directive AutoPurgeJobs indique si oui ou non il faut purger les travaux d'impression lorsqu'ils ne sont +plus nécessaires au vu des quotas. Cet option n'a aucun effet si les quotas ne sont pas activés. +La valeur implicite est No. + +

+

BrowseAddress

+
+

Exemples

+
    +
    +BrowseAddress 255.255.255.255:631
    +BrowseAddress 192.0.2.255:631
    +BrowseAddress host.domain.com:631
    +
    +
+

Description

+

La directive BrowseAddress indique une adresse à laquelle il faut envoyer les informations d'exploration. +Plusieurs directives BrowseAddress peuvent être indiquées pour envoyer les informations d'exploration à différents +systèmes ou réseaux.

+ +

La valeur implicite de l'adresse est 255.255.255.255:631 +ce qui diffusera les informations à tous les réseaux auxquels le serveur est connecté. +

+ + +
NOTA: +

Si vous utilisez HP-UX 10.20 sur un sous-réseau dont le masque n'est pas sur 24, 16 ou 8 bits, +l'exploration des imprimantes (et en fait toute réception d'information diffusée) ne fonctionnera pas. +Ce problème semble résolu dans HP-UX 11.0.

+
+
+ + +

+

BrowseAllow

+
+

Exemples

+
    +
    +BrowseAllow from all
    +BrowseAllow from none
    +BrowseAllow from 192.0.2
    +BrowseAllow from 192.0.2.0/24
    +BrowseAllow from 192.0.2.0/255.255.255.0
    +BrowseAllow from *.domain.com
    +
    +
+

Description

+

La directive BrowseAllow indique un système dont on accepte de recevoir des paquets d'exploration. +Le comportement +implicite est d'accepter des paquets d'exploration de n'importe quel hôte.

+

Le contrôle sur la base du nom d'hôte et de domaine impose que vous activiez la directive +HostNameLookups.

+

Le contrôle sur la base de l'adresse IP prend en charge les correspondances exactes, les adresses partielles qui +correspondent à des réseaux dont le masque est 255.0.0.0, 255.255.0.0, et + 255.255.255.0, ou des adresses réseau utilisant le masque indiqué. + +

+

BrowseDeny

+
+

Exemples

+
    +
    +BrowseDeny from all
    +BrowseDeny from none
    +BrowseDeny from 192.0.2
    +BrowseDeny from 192.0.2.0/24
    +BrowseDeny from 192.0.2.0/255.255.255.0
    +BrowseDeny from *.domain.com
    +
    +
+

Description

+

La directive BrowseDeny indique un système dont on refuse de recevoir des paquets d'exploration. Le comportement +implicite est de ne refuser aucun paquet d'exploration d'aucun hôte.

+

Le contrôle sur la base du nom d'hôte et de domaine impose que vous activiez la directive +HostNameLookups.

+

Le contrôle sur la base de l'adresse IP prend en charge les correspondances exactes, les adresses partielles qui +correspondent à des réseaux dont le masque est 255.0.0.0, 255.255.0.0, et + 255.255.255.0, ou des adresses réseau utilisant le masque indiqué. + + +

+

BrowseOrder

+
+

Exemples

+
    +
    +BrowseOrder allow,deny
    +BrowseOrder deny,allow
    +
    +
+

Description

+

La directive BrowseOrder +indique l'ordre de traitement accord/refus. L'ordre implicite est deny,allow: +

    +
  • allow,deny - Les paquets d'exploration sont acceptés à moins qu'ils ne soient explicitement refusés.
  • +
  • deny,allow - Les paquets d'exploration sont rejetés à moins qu'ils ne soient explicitement acceptés.
  • +
+ + +

BrowseInterval

+
+

Exemples

+
    +
    +BrowseInterval 0
    +BrowseInterval 30
    +
    +
+

Description

+

La directive BrowseInterval indique le délai maximum entre deux mises à jour de l'exploration. +Le fait d'indiquer une valeur de 0 interdit de diffuser des mises à jour mais autorise néanmoins un serveur à recevoir +des mises à jour en provenance d'autres hôtes.

+ +

La valeur BrowseInterval devrait toujours être inférieure à la valeur BrowseTimeout. +Sinon des imprimantes et des classes pourraient disparaître des système clients entre les mises à jour. + +

+

BrowsePoll

+
+

Exemples

+
    +
    +BrowsePoll 192.0.2.2:631
    +BrowsePoll host.domain.com:631
    +
    +
+

Description

+

La directive BrowsePoll +collecte la liste des imprimantes disponibles sur un serveur une fois toutes les +BrowseInterval secondes. +Plusieurs directives BrowsePoll peuvent être indiquées pour surveiller plusieurs serveurs.

+

Si BrowseInterval est mis à 0 alors le serveur est surveillé une fois toutes les 30 secondes. + +

+

BrowsePort

+
+

Exemples

+
    +
    +BrowsePort 631
    +BrowsePort 9999
    +
    +
+

Description

+

+La directive BrowsePort indique un numéro de port UDP à employer pour les échanges de paquets d'exploration. La +valeur implicite est 631. +

+ + +
NOTE: +

Vous devez choisir une valeur identique pour la directive BrowsePort sur tous les systèmes que vous voulez voir.

+
+
+ + +

+

BrowseProtocols

+
+

Exemples

+
    +
    +BrowseProtocols CUPS
    +BrowseProtocols SLP
    +BrowseProtocols CUPS SLP
    +BrowseProtocols all
    +
    +
+

Description

+

La directive BrowseProtocols indique les protocoles à employer pour collecter et distribuer les informations +sur les imprimantes partagées sur le réseau local. Le protocole implicite est CUPS, c'est un protocole +basé sur la diffusion réseau ("broadcast"). +

+ + +
NOTE: +

Lorsque vous utilisez le protocole SLP, vous devez avoir au moins un serveur "Directory Agent" (DA) sur votre +réseau. A défaut, l'ordonnanceur CUPS (cupsd) ne répondra pas aux requêtes des clients pendant plusieurs secondes +pendant qu'il sera en train d'explorer le réseau.

+
+
+ + +

+

BrowseRelay

+
+

Exemples

+
    +
    +BrowseRelay 193.0.2.1 192.0.2.255
    +BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
    +BrowseRelay 193.0.2.0/24 192.0.2.255
    +BrowseRelay *.domain.com 192.0.2.255
    +BrowseRelay host.domain.com 192.0.2.255
    +
    +
+

Description

+

+la directive indique des adresses source et destination pour relayer les informations d'exploration en provenance d'un +hôte ou d'un réseau vers un autre. Plusieurs directives BrowseRelay peuvent être indiquées si nécessaire.

+

BrowseRelay est généralement utilisé sur des systèmes qui assurent la passerelle entre des réseaux multiples au +moyen d'une ou plusieurs interfaces réseau. Elle peut également être utilisée pour relayer des informations sur les imprimantes +provenant de serveurs surveillés, au moyen de la ligne:

+
    +
    +BrowseRelay 127.0.0.1 255.255.255.255
    +
    +
+

Cela fournit un accès effectif aux imprimantes d'un WAN pour tous les clients d'un LAN. + +

+

BrowseShortNames

+
+

Exemples

+
    +
    +BrowseShortNames Yes
    +BrowseShortNames No
    +
    +
+

Description

+ +

La directive BrowseShortNames indique s'il faut ou non utiliser les noms courts pour les imprimantes à +distance. Les noms courts sont simplement composés du nom de l'imprimante, sans celui du serveur ("imprimante"). Si le +système détecte plus d'une imprimante à distance portant le même nom, les imprimantes seront affichées avec les noms longs +("imprimante@erveur1", "imprimante@erveur2")

+

La valeur implicite de cette option est Yes. + +

+

BrowseTimeout

+
+

Exemples

+
    +
    +BrowseTimeout 300
    +BrowseTimeout 60
    +
    +
+

Description

+

La directive BrowseTimeout fixe la durée de vie des informations reçues sous forme de paquets d'exploration et +concernant les imprimantese et les classes. Une fois que les informations concernant une imprimante ou une classe dépassent ce +délai, elles sont retirées de la liste des destinations disponibles.

+ +

La valeur BrowseTimeout devrait toujours être supérieure à la valeur BrowseInterval. +Sinon des imprimantes et des classes pourraient disparaîtres des systèmes clients entre les mises à jour. + +

+

Browsing

+
+

Exemples

+
    +
    +Browsing On
    +Browsing Off
    +
    +
+

Description

+

La directive Browsing contrôle l'activation ou non de l'exploration réseau des imprimantes. +La valeur implicite est On. +

+ + +
NOTE: +

Si vous utilisez HP-UX 10.20 sur un sous-réseau dont le masque n'est pas sur 24, 16 ou 8 bits, +l'exploration des imprimantes (et en fait toute réception d'information diffusée) ne fonctionnera pas. +Ce problème semble résolu dans HP-UX 11.0.

+
+
+ + +

+

Classification

+
+

Exemples

+
    +
    +Classification
    +Classification classified
    +Classification confidential
    +Classification secret
    +Classification topsecret
    +Classification unclassified
    +
    +
+

Description

+

La directive Classification fixe le niveau de classification sur le serveur. Lorsque cette option est activée +au moins une des pages de garde est forcée à ce niveau et l'information de classification est placée sur chaque page imprimée. +La valeur implicite est de n'avoir aucun niveau de classification. + +

+

ClassifyOverride

+
+

Exemples

+
    +
    +ClassifyOverride Yes
    +ClassifyOverride No
    +
    +
+

Description

+

La directive ClassifyOverride indique si les utilisateurs peuvent outrepasser le niveau de classification +du serveur ou non. Lorsque la classification du serveur est activée, les utilisateurs peuvent changer la classification en +employant l'option job-sheets et peuvent choisir de n'imprimer qu'une seule page de garde de sécurité avant ou +après le travail d'impression. Si l'option job-sheets est positionnée à la valeur none alors +le niveau de classification implicite du serveur est utilisé.

+

La valeur implicite est de ne pas autoriser les utilisateurs à outrepasser la classification. + +

+

DataDir

+
+

Exemples

+
    +
    +DataDir /usr/share/cups
    +
    +
+

Description

+

La directive DataDir fixe le répertoire à employer pour les fichiers de données. + +

+

DefaultCharset

+
+

Exemples

+
    +
    +DefaultCharset utf-8
    +DefaultCharset iso-8859-1
    +DefaultCharset windows-1251
    +
    +
+

Description

+

La directive DefaultCharset définit le jeu de caractères à utiliser pour les connexions avec les clients. +Le jeu de caractère implicite est le jeu utf-8 mais il est outrepassé par le jeu de caractères associé à la langue indiquée par le client ou par la directive +DefaultLanguage. + +

+

DefaultLanguage

+
+

Exemples

+
    +
    +DefaultLanguage de
    +DefaultLanguage en
    +DefaultLanguage es
    +DefaultLanguage fr
    +DefaultLanguage it
    +
    +
+

Description

+

La directive DefaultLanguage définit le langage à utiliser pour les connexions avec les clients. Régler la langue +règle également le jeu de caractères si un fichier de localisation existe pour celle-ci. La valeur implicite est "en" c'est-à-dire "anglais". + +

+

Deny

+
+

Exemples

+
    +
    +Deny from All
    +Deny from None
    +Deny from *.domain.com
    +Deny from .domain.com
    +Deny from host.domain.com
    +Deny from nnn.*
    +Deny from nnn.nnn.*
    +Deny from nnn.nnn.nnn.*
    +Deny from nnn.nnn.nnn.nnn
    +Deny from nnn.nnn.nnn.nnn/mm
    +Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +
    +
+

Description

+

La directive Deny indique un nom d'hôte, une adresse IP ou un réseau qui n'est pas autorisé à accéder +au serveur. +Les directives Deny se cumulent, ainsi plusieurs directives Deny peuvent être utilisées pour +interdire l'accès à de multiples hôtes et/ou réseaux. La notation /mm indique une notation de sous-réseau CIDR: + +

+ + + + + + +
mmnetmask +mmnetmask
00.0.0.0 +8255.0.0.0
1128.0.0.0 +16255.255.0.0
2192.0.0.0 +24255.255.255.0
...... +32255.255.255.255
+
+

+

La directive Deny doit apparaître à l'intérieur d'une directive + Location. + +

+

DocumentRoot

+
+

Exemples

+
    +
    +DocumentRoot /usr/share/doc/cups
    +DocumentRoot /foo/bar/doc/cups
    +
    +
+

Description

+

La directive DocumentRoot indique l'emplacement du contenu que le serveur HTTP de CUPS doit publier. +Si un chemin absolu n'est pas indiqué, celui-ci est considéré comme relatif au répertoire +ServerRoot. La valeur implicite est /usr/share/doc/cups.

+

Les documents sont d'abord recherchés dans un sous-répertoire correspondant à la langue demandée par le client (par exemple +/usr/share/doc/cups/fr/...) et ensuite directement dans le répertoire DocumentRoot (par exemple +/usr/share/doc/cups/...), ainsi il est possible de localiser le contenu "web" en fournissant des sous-répertoires pour chaque + langue nécessaire. + +

+

Encryption

+
+

Exemples

+
    +
    +Encryption Never
    +Encryption IfRequested
    +Encryption Required
    +Encryption Always
    +
    +
+

Description

+

La directive Encryption doit apparaître à l'intérieur d'une section +Location et définit les réglages d'encryptage pour cet emplacement. Le réglage implicite est + IfRequested pour tous les emplacements. + +

+

ErrorLog

+
+

Exemples

+
    +
    +ErrorLog /var/log/cups/error_log
    +ErrorLog /var/log/cups/error_log-%s
    +ErrorLog syslog
    +
    +
+

Description

+

La directive ErrorLog définit le nom du fichier de suivi d'erreurs ("error log"). Si le nom de fichier n'est pas un chemin +absolu, il est considéré comme un chemin relatif au répertoire ServerRoot. Le fichier standard est + /var/log/cups/error_log.

+

Le nom du serveur peut être inclus dans le nom du fichier en utilisant le nom %s.

+

Le nom spécial "syslog" peut être utilisé pour envoyer les informations de suivi d'erreurs vers le fichier de suivi d'erreur +système au lieu d'un fichier texte simple. + +

+

FilterLimit

+
+

Exemples

+
    +
    +FilterLimit 0
    +FilterLimit 200
    +FilterLimit 1000
    +
    +
+

Description

+

La directive FilterLimit définit le coût maximal de tous les filtres appliqués au travaux en cours de +traitement. Elle peut +être utilisée pour limiter le nombre de programmes de filtres qui son exécutés dans un serveur pour minimiser les problèmes de ressources disque, +mémoire ou CPU. Une limite de 0 désactive la limitation des filtres.

+ +

Le coût moyen d'une impression vers une imprimante non-PostScript nécessite une limitation de filtre aux alentours de 200. Une imprimante +PostScript nécessite une limite d'environ la moitié (100). Positionner la limite en dessous de ces seuils va effectivement limiter l'ordonnanceur +à l'impression d'un travail à la fois.

+

La valeur implicite est 0. + +

+

FontPath

+
+

Exemples

+
    +
    +FontPath /foo/bar/fonts
    +FontPath /usr/share/cups/fonts:/foo/bar/fonts
    +
    +
+

Description

+

La directive FontPath définit le chemin de recherche des polices de caractères à utiliser. La valeur +implicite est /usr/share/cups/fonts. + +

+

Group

+
+

Exemples

+
    +
    +Group sys
    +Group system
    +Group root
    +
    +
+

Description

+

La directive Group définit le groupe UNIX sous l'identité duquel les programmes CGI et de filtrage fonctionnent. +Le groupe implicite est sys, system, ou root selon le système d'exploitation. + +

+

HideImplicitMembers

+
+

Exemples

+
    +
    +HideImplicitMembers Yes
    +HideImplicitMembers No
    +
    +
+

Description

+

La directive HideImplicitMembers contrôle l'appartenance ou non d'imprimantes individuelles aux classes implicites qui sont +montrées à l'utilisateur. La valeur standard est No.

+

ImplicitClasses doit être activée pour que cette directive ait un quelconque effet.

+ + +

HostNameLookups

+
+

Exemples

+
    +
    +HostNameLookups On
    +HostNameLookups Off
    +HostNameLookups Double
    +
    +
+

Description

+

La directive HostNameLookups indique si CUPS doit ou non rechercher le nom d'hôte des clients qui se connectent. La clause +Double force CUPS à vérifier que le nom d'hôte trouvé à partir de l'adresse correspond bien à l'une des adresses retournées pour +ce nom d'hôte. Les recherches Double empêchent également que des clients ayant des adresses non enregistrées ne se connectent au +serveur. La valeur implicite est Off pour éviter tout problème potentiel de performance du serveur du fait des résolutions de nom. +Positionnez cette directive à la valeur On ou Double uniquement si nécessaire. + +

+

ImplicitClasses

+
+

Exemples

+
    +
    +ImplicitClasses On
    +ImplicitClasses Off
    +
    +
+

Description

+

La directive ImplicitClasses contrôle si les classes implicites sont créées sur la base des imprimantes et classes disponibles +sur le réseau. La valeur implicite est On mais est automatiquement positionnée sur Off si Browsing +est à la valeur Off. + +

+

ImplicitAnyClasses

+
+

Exemples

+
    +
    +ImplicitAnyClasses On
    +ImplicitAnyClasses Off
    +
    +
+

Description

+

La directive ImplicitAnyClasses contrôle si oui ou non les classes implicites pour les imprimantes locales et à distance sont crées +avec le nom AnyPrinter. La valeur implicite est Off.

+

ImplicitClasses doit être activée pour que cette directive ait un quelconque effet.

+ +

Include

+
+

Exemples

+
    +
    +Include filename
    +Include /foo/bar/filename
    +
    +
+

Description

+

La directive Include inclut le fichier indiqué dans le corps du fichier +cupsd.conf. Si aucun chemin n'est indiqué, le fichier est considéré comme étant relatif au répertoire +ServerRoot.

+ +

KeepAlive

+
+

Exemples

+
    +
    +KeepAlive On
    +KeepAlive Off
    +
    +
+

Description

+

La directive KeepAlive contrôle la prise en charge ou non des connexions HTTP persitantes. La valeur +implicite est On.

+

Les clients HTTP/1.1 prennent automatiquement en charge les connexions persistantes, tandis que clients + HTTP/1.0 doivent spécifiquement les demander en utiliser l'attribut Keep-Alive attribute dans le champ + Connection: de chaque requête. + +

+

KeepAliveTimeout

+
+

Exemples

+
    +
    +KeepAliveTimeout 60
    +KeepAliveTimeout 30
    +
    +
+

Description

+

La directive KeepAliveTimeout contrôle combien de temps une connexion HTTP persistante restera ouverte +après la dernière requête. +La valeur implicite est de 60 secondes. + +

+

Limit

+
+

Exemples

+
    +
    +<Limit GET POST>
    +...
    +</Limit>
    +
    +<Limit ALL>
    +...
    +</Limit>
    +
    +
+

Description

+

La directive Limit groupe les directives de contrôle d'accès pour certains types spécifiques de requêtes HTTP et doit apparaître +à l'intérieur d'une section Location. +L'accès peut être limité à des types individuels de requêtes (DELETE, GET, HEAD +, OPTIONS, POST, PUT, et +TRACE) ou pour tous les types de requêtes (ALL). Les noms de types de requêtes sont dépendants de la casse pour des raisons +de compatibilité avec Apache. + +

+

LimitExcept

+
+

Exemples

+
    +
    +<LimitExcept GET POST>
    +...
    +</LimitExcept>
    +
    +
+

Description

+

La directive LimitExcept groupe les directives de contrôle d'accès pour certains types spécifiques de requêtes HTTP et doit +apparaître à l'intérieur d'une section Location. +Contrairement à la directive Limit, LimitExcept restreint l'accès pour toutes les requêtes + à l'exception de celles listées dans la ligne LimitExcept. + +

+

LimitRequestBody

+
+

Exemples

+
    +
    +LimitRequestBody 10485760
    +LimitRequestBody 10m
    +LimitRequestBody 0
    +
    +
+

Description

+

La directive LimitRequestBody contrôle la taille maximale des fichiers d'impression, des requêtes IPP, et des données des formulaires +HTML dans les requêtes HTTP POST. La limite implicite est de 0 ce qui désactive la vérification de la limite.

+

Reportez-vous également à la directive similaire MaxRequestSize. + +

+

Listen

+
+

Exemples

+
    +
    +Listen 127.0.0.1:631
    +Listen 192.0.2.1:631
    +
    +
+

Description

+

La directive Listen indique une adresse réseau et un port sur lequel écouter en attente de connexions. Plusieurs directives +Listen peuvent être indiquées pour écouter sur de multiples adresses.

+

La directive Listen est similaire à la directive Port +mais vous permet de restreindre l'accès à des interfaces ou des réseaux spécifiques. + +

+

Location

+
+

Exemples

+
    +
    +<Location />
    +...
    +</Location>
    +
    +<Location /admin>
    +...
    +</Location>
    +
    +<Location /printers/name>
    +...
    +</Location>
    +
    +
+

Description

+

La directive Location indique des options de contrôle d'accès et d'authentification pour le chemin ou +la ressource HTTP indiquée. +Des informations supplémentaires sont disponibles plus loin dans le chapitre dans la section +"Sécurité du système d'impression". + +

+

LogLevel

+
+

Exemples

+
    +
    +LogLevel none
    +LogLevel emerg
    +LogLevel alert
    +LogLevel crit
    +LogLevel error
    +LogLevel warn
    +LogLevel notice
    +LogLevel info
    +LogLevel debug
    +LogLevel debug2
    +
    +
+

Description

+

La directive LogLevel indique la quantité d'informations à consigner dans le fichier ErrorLog. +Les valeurs suivantes sont reconnues (chaque niveau inclut tout ce qui l'est dans les niveaux inférieurs):

+
    +
  • none - Ne consigne rien.
  • +
  • emerg - Consigne les conditions d'urgence qui empêchent le serveur de fonctionner.
  • +
  • alert - Consigne les alertes qui doivent être traitées immédiatement.
  • +
  • crit - Consigne les erreurs critiques qui n'empêchent pas le serveur de fonctionner.
  • +
  • error - Consigne les erreurs générales.
  • +
  • warn - Consigne les erreurs et les avertissements.
  • +
  • notice - Consigne les conditions d'erreurs temporaires.
  • +
  • info - Consigne toutes les requêtes de modifications et de changement d'état (valeur implicite).
  • +
  • debug - Consigne des informations basiques de débogage.
  • +
  • debug2 - Consigne toutes les informations de débogage.
  • +
+ + +

MaxClients

+
+

Exemples

+
    +
    +MaxClients 100
    +MaxClients 1024
    +
    +
+

Description

+

La directive MaxClients contrôle le nombre maximum de clients simultanés qui seront autorisés par le serveur. La valeur implicite ("par défaut") +est de 100 clients. +

+ + +
NOTE: +

Etant donné que chaque travail d'impression demande un descripteur de fichier pour le tube de contrôle, le serveur CUPS limite de manière +interne la valeur MaxClients au tiers des descripteurs de fichiers disponibles pour éviter les possibles problèmes lors de +l'impression de nombreux travaux d'impression.

+
+
+ + +

+

MaxJobs

+
+

Exemples

+
    +
    +MaxJobs 100
    +MaxJobs 9999
    +MaxJobs 0
    +
    +
+

Description

+

La directive MaxJobs contrôle le nombre maximum de travaux d'impression qui sont conservés en mémoire. Dès que le nombre de +travaux atteint la limite, le plus ancien travail complété est automatiquement purgé du système pour libérer de l'espace pour le nouveau +travail. Si tous les travaux connus sont toujours en attente de traitement ou actifs, alors le nouveau travail sera rejeté.

+

Régler cette valeur sur 0 (valeur implicite) désactive cette fonctionnalité. + +

+

MaxJobsPerPrinter

+
+

Exemples

+
    +
    +MaxJobsPerPrinter 100
    +MaxJobsPerPrinter 9999
    +MaxJobsPerPrinter 0
    +
    +
+

Description

+

La directive MaxJobsPerPrinter contrôle le nombre maximum de travaux actifs qui sont autorisés pour chaque imprimante ou classe +d'imprimantes. Dès que le nombre est atteint pour une imprimante ou une classe, les nouveaux travaux sont rejetés tant que l'un des travaux +actifs n'est pas complété, arrêté, annulé ou abandonné.

+

Régler le maximum sur la valeur 0 (valeur implicite) désactive cette fonctionnalité. + +

+

MaxJobsPerUser

+
+

Exemples

+
    +
    +MaxJobsPerUser 100
    +MaxJobsPerUser 9999
    +MaxJobsPerUser 0
    +
    +
+

Description

+

La directive MaxJobsPerUser contrôle le nombre maximum de travaux d'impression qui sont autorisés pour chaque utilisateur. Dès +qu'un utilsateur atteint le maximum autorisé, tout nouveau travail sera rejeté avant qu'un des travaux actifs soit complété, arrêté, annulé ou +abandonné.

+

Régler le maximum sur 0 (valeur implicite) désactive cette fonctionnalité. + +

+

MaxLogSize

+
+

Exemples

+
    +
    +MaxLogSize 1048576
    +MaxLogSize 1m
    +MaxLogSize 0
    +
    +
+

Description

+

La directive MaxLogSize contrôle la taille maximum de chaque fichier de suivi ("log"). +Dès qu'un fichier atteint ou dépasse la limite il est fermé ou renommé en filename.O. +Cela vous permet de mettre en place automatiquement une rotation des fichiers de suivi. La taille implicite +est de 1048576 octets (1Mo).

+

Régler le maximum sur 0 désactive la rotation de fichier de suivi. + +

+

MaxRequestSize

+
+

Exemples

+
    +
    +MaxRequestSize 10485760
    +MaxRequestSize 10m
    +MaxRequestSize 0
    +
    +
+

Description

+

La directive MaxRequestSize contrôle la taille maximum des fichiers d'impression, des requêtes IPP, et des données des +formulaires HTML contenus dans les requêtes HTTP POST. La valeur implicite est 0, ce qui désactive cette vérification de limite.

+

Reportez-vous également à la directive similaire LimitRequestBody. + +

+

Order

+
+

Exemples

+
    +
    +Order Allow,Deny
    +Order Deny,Allow
    +
    +
+

Description

+

La directive Order définit le type implicite de contrôle d'accès. +Les valeurs suivantes sont prises en charge:

+
    +
  • Allow,Deny - Autorise les requêtes depuis tous les systèmes à l'exception de ceux listés dans une directive Deny.
  • +
  • Deny,Allow - Autorise les requêtes uniquement depuis les hôtes listés dans une directive Allow.
  • +
+

La directive Order doit apparaître à l'intérieur d'une directive + Location. + +

+

PageLog

+
+

Exemples

+
    +
    +PageLog /var/log/cups/page_log
    +PageLog /var/log/cups/page_log-%s
    +PageLog syslog
    +
    +
+

Description

+

La directive PageLog définit le nom du fichier "page log". +Si le nom du fichier n'est pas absolu, il est considéré comme étant relatif au répertoire ServerRoot. +Le fichier standard "page log" est /var/log/cups/page_log.

+

Le nom du serveur peut être inclus dans le nom de fichier en utilisant le nom %s.

+

Le nom spécial "syslog" peut être utilisé pour envoyer les informations de page vers le fichier de suivi système au lieu d'un +simple fichier texte. + +

+

Port

+
+

Exemples

+
    +
    +Port 631
    +Port 80
    +
    +
+

Description

+

La directive Port indique un port sur lequel écouter en attente de connexions. +Plusieurs lignes Port peuvent être indiquées pour écouter sur plusieurs ports. La valeur implicite est 631. + +

+

PreserveJobHistory

+
+

Exemples

+
    +
    +PreserveJobHistory On
    +PreserveJobHistory Off
    +
    +
+

Description

+

La directive PreserveJobHistory contrôle si l'historique des travaux complétés, annulés ou abandonnés est conservé sur disque ou non.

+

Une valeur On (valeur implicite) conserve les informations concernant les travaux jusqu'à ce que l'administrateur +les purge avec la commande cancel.

+

Une valeur Off retire les informations concernant les travaux dès que ceux-ci sont complétés, annulés ou abandonnés. + +

+

PreserveJobFiles

+
+

Exemples

+
    +
    +PreserveJobFiles On
    +PreserveJobFiles Off
    +
    +
+

Description

+

La directive PreserveJobFiles contrôle si les fichiers des documents complétés, annulés ou abandonnés sont stockés sur disque.

+

La valeur On conserve les fichiers des travaux jusqu'à ce que l'administrateur les purge au moyen de la commande cancel. +Les travaux peuvent être resoumis (réimprimés) jusqu'à ce qu'ils soient purgés.

+

La valeur Off (valeur implicite) retire les fichiers des travaux dès ceux-ci sont complétés, annulés ou abandonnés. + +

+

Printcap

+
+

Exemples

+
    +
    +Printcap
    +Printcap /etc/printcap
    +Printcap /etc/printers.conf
    +
    +
+

Description

+

La directive Printcap contrôle si le fichier printcap est automatiquement généré et mis à jour ou non avec une liste des imprimantes +disponibles. Si la directive est utilisée sans valeur, alors aucun fichier printcap ne sera généré. La valeur implicite est de +générer un fichier nommé /etc/printcap.

+

Quand un nom de fichier est indiqué (par exemple /etc/printcap), +le fichier printcap est écrit dès qu'une imprimante est ajoutée ou supprimée. +Le fichier printcap peut alors être utilisé par les applications dont l'utilisation du fichier printcap comme référence des imprimantes +disponibles est codée en dur. + +

+

PrintcapFormat

+
+

Exemples

+
    +
    +PrintcapFormat BSD
    +PrintcapFormat Solaris
    +
    +
+

Description

+

La directive PrintcapFormat contrôle le format de sortie du fichier printcap. +Le comportement implicite est de générer un fichier printcap de type BSD. + +

+

PrintcapGUI

+
+

Example

+
    +
    +PrintcapGUI /usr/bin/glpoptions
    +
    +
+

Description

+

La directive PrintcapGUI indique le programme à utiliser pour afficher le panneau d'options à partir d'une application +IRIX qui utiliser l'API d'impression Impressario. Le programme implicite est le programme graphique "glpoptions" d'ESP Print Pro.

+

Le programme doit accepter l'option -d pour indiquer l'imprimante et l'option -o pour indiquer une ou plusieurs +options. Après avoir autorisé l'utilisateur à sélectionner/changer les options, le programme doit écrire la liste des options d'impression +sans le -o sur la sortie standard. + +

+

RemoteRoot

+
+

Exemples

+
    +
    +RemoteRoot remroot
    +RemoteRoot root
    +
    +
+

Description

+

La directive RemoteRoot fixe le nom d'utilisateur à utiliser pour les requêtes root non authentifiées depuis des hôtes distants. +Le nom d'utilisateur standard est remroot. +Régler RemoteRoot sur root désactive effectivement ce mécanisme de sécurité. + +

+

RequestRoot

+
+

Exemples

+
    +
    +RequestRoot /var/spool/cups
    +RequestRoot /foo/bar/spool/cups
    +
    +
+

Description

+

La directive RequestRoot définit le répertoire pour les requêtes entrantes IPP et les formulaires HTML. +Si un chemin absolu n'est pas fourni alors il est considéré comme relatif au répertoire ServerRoot. Le répertoire implicite est /var/spool/cups. + +

+

Require

+
+

Exemples

+
    +
    +Require group foo bar
    +Require user john mary
    +Require valid-user
    +
    +
+

Description

+

La directive Require indique que l'authentification est nécessaire pour l'accès à la ressource considérée. +Le mot clef group indique que l'utilisateur authentifié doit être membre d'un ou plusieurs des groupes qui suivent.

+

Le mot clef user indique que l'utilisateur authentifié doit être l'un des utilisateurs dont les noms suivent.

+

Le mot clef valid-user indique que tout utilisateur authentifié peut accéder à la ressource.

+

Le comportement implicite ("par défaut") est de ne faire aucune authentification. +Cette directive doit apparaître à l'intérieur d'une directive Location. + +

+

RIPCache

+
+

Exemples

+
    +
    +RIPCache 8m
    +RIPCache 1g
    +RIPCache 2048k
    +
    +
+

Description

+

La directive RIPCache définit la quantité de mémoire utilisée par les filtres RIP ("Raster Images Processor") tels que +imagetoraster et pstoraster. +La taille peut être suffixée par "k" pour kilo-octets, "m" pour méga-octets, ou "g" pour + giga-octets. La taille implicite est de "8m", ou 8 méga-octets. + +

+

RunAsUser

+
+

Exemples

+
    +
    +RunAsUser Yes
    +RunAsUser No
    +
    +
+

Description

+

La directive RunAsUser contrôle si l'ordonnanceur fonctionne sous l'identité d'un compte utilisateur non privilégié +(habituellement lp). La valeur implicite est No qui laisse l'utilisateur fonctionner +en tant qu'utilisateur root.

+

Note: Faire fonctionner CUPS en tant qu'utilisateur non privilégié peut empêcher +LPD et les imprimantes connectées localement de fonctionner correctement en raison de problèmes de permissions. Le programme d'arrière-plan + lpd utilisera automatiquement le mode non privilégié ce qui est 100% conforme à la RFC 1179. Les programmes d'arrière-plan +parallel, serial, et usb auront besoin d'accès en écriture aux fichiers de périphériques correspondants. + +

+ +

Satisfy

+
+

Exemples

+
    +
    +Satisfy all
    +Satisfy any
    +
    +
+

Description

+

La directive Satisfy indique si toutes les conditions doivent être satisfaites pour ouvrir l'accès à la ressource. +Si la valeur est all alors toutes les conditions d'authentification et de contrôle d'accès doivent être satisfaites pour +que l'accès soit autorisé.

+

Régler Satisfy à la valeur any autorise un utilisateur à obtenir l'accès si l'authentification ou le contrôle d'accès +est satisfait. Par exemple, vous pourriez exiger l'authentifiation pour l'accès à distance mais autoriser l'accès local sans elle.

+

La valeur implicite est all. Cette directive doit apparaître à l'intérieur d'une directive Location. + +

+

ServerAdmin

+
+

Exemples

+
    +
    +ServerAdmin user@host
    +ServerAdmin root@foo.bar.com
    +
    +
+

Description

+

La directive ServerAdmin identifie l'adresse de courriel de l'administrateur du système. La valeur implicite est root@serveur, +où server est le nom du serveur. + +

+

ServerBin

+
+

Exemples

+
    +
    +ServerBin /usr/lib/cups
    +ServerBin /foo/bar/lib/cups
    +
    +
+

Description

+

La directive ServerBin définit le répertoire contenant les fichiers exécutables du serveur. +Si un chemin absolu n'est pas indiqué, il est considéré comme relatif au répertoire +ServerRoot +. Le répertoire implicite est /usr/lib/cups. + +

+

ServerCertificate

+
+

Exemples

+
    +
    +ServerCertificate /etc/cups/ssl/server.crt
    +
    +
+

Description

+

La directive ServerCertificate définit l'emplacement du fichier de certificat SSL utilisé par le serveur +lors de la négociation des connexions encryptées. Le certificat ne doit pas être encrypté (protégé par un mot de passe) car l'ordonnanceur fonctionne +normalement en arrière-plan et et ne sera pas en mesure de demander un mot de passe. Le fichier standard de certificat est + /etc/cups/ssl/server.crt. + +

+

ServerKey

+
+

Exemples

+
    +
    +ServerKey /etc/cups/ssl/server.key
    +
    +
+

Description

+

La directive ServerKey indique l'emplacement du fichier de clé privée SSL utilisé par le serveur pour négocier les connexions +encryptées. Le fichier standard de clé est /etc/cups/ssl/server.crt +. + +

+

ServerName

+
+

Exemples

+
    +
    +ServerName foo.domain.com
    +ServerName myserver.domain.com
    +
    +
+

Description

+

La directive ServerName indique le nom d'hôte qui doit être envoyé aux clients. En standard, le nom du serveur est le nom d'hôte. + +

+

ServerRoot

+
+

Exemples

+
    +
    +ServerRoot /etc/cups
    +ServerRoot /foo/bar/cups
    +
    +
+

Description

+

La directive ServerRoot indique un chemin absolu pour les fichiers de configuration et d'état du serveur. +Il est également utilisé pour interpréter les chemins relatifs présents dans le fichier cupsd.conf file. +Le répertoire standard est /etc/cups. + +

+

SSLListen

+
+

Exemples

+
    +
    +SSLListen 127.0.0.1:443
    +SSLListen 192.0.2.1:443
    +
    +
+

Description

+

La directive SSLListen indique une adresse réseau et un port sur lequel écouter les tentatives de connexion sécurisées. +Plusieurs directives SSLListen peuvent être fournies pour indiquer plusieurs adresses sur lesquelles écouter.

+

La directive SSLListen est similaire à la directive +SSLPort mais vous permet de restreindre l'accès à certaines interfaces ou réseaux. + +

+

SSLPort

+
+

Exemples

+
    +
    +SSLPort 443
    +
    +
+

Description

+

La directive SSLPort indique le port sur lequel écouter les tentatives de connexions sécurisées. +Plusieurs lignes SSLPort peuvent être indiquées pour écouter les connexions sur plusieurs ports. + +

+

SystemGroup

+
+

Exemples

+
    +
    +SystemGroup sys
    +SystemGroup system
    +SystemGroup root
    +
    +
+

Description

+

La directive SystemGroup indique le groupe système d'aministration pour l'authentification de type System. +Plus d'information peut être trouvée plus loin dans ce chapitre dans la section +"Sécurité du système d'impression". + +

+

TempDir

+
+

Exemples

+
    +
    +TempDir /var/tmp
    +TempDir /foo/bar/tmp
    +
    +
+

Description

+

La directive TempDir indique un chemin absolu pour le répertoire à employer pour les fichiers temporaires. +Le répertoire standard est /var/tmp.

+

Les répertoires temporaires doivent être inscriptibles pour tous et devraient avoir le "sticky" bit activé +de sorte que les utilisateurs ne puissent pas supprimer les fichiers temporaires de filtres. +Les commandes suivantes créerons un répertoire temporaire approprié appelé /foo/bar/tmp:

+
    +
    +mkdir /foo/bar/tmp ENTREE
    +chmod a+rwxt /foo/bar/tmp ENTREE
    +
    +
+ + +

Timeout

+
+

Exemples

+
    +
    +Timeout 300
    +Timeout 90
    +
    +
+

Description

+

La directive Timeout définit le délai à attendre avant qu'une requête HTTP ou IPP active ne soit hors délai. La valeur implicite est de 300 secondes. + +

+

User

+
+

Exemples

+
    +
    +User lp
    +User guest
    +
    +
+

Description

+

La directive User indique l'utilisateur UNIX sous l'identité duquel les programmes CGI et les filtres doivent fonctionner. +La valeur implicite est lp. + +

+

Sécurité du système d'impression

+ +

CUPS prend en charge le contrôle d'accès et l'authentification basée sur l'adresse, un certificat ou un mot de passe +(mode "Basic" et "Digest"). Les authentifications par mot de passe et certificat fournissent des moyens de limiter l'accès +à certaines personnes ou certains groupes.

+ +

Le contrôle d'accès basé sur l'adresse vous permet de limiter l'accès à certains systèmes, réseaux ou domaines particuliers. +Bien que cela ne soit pas de l'authentification, cela vous permet de restreindre efficacement le nombre potentiel d'utilisateurs +de votre système.

+ +

CUPS maintient à jour une liste des emplacements dont l'authentification et/ou le contrôle d'accès est/sont activé(e)(s). +Ces emplacements sont indiqués en utilisant la directive +Location:

+ +

Les emplacements suivent généralement la structure arborescente du contenu du répertoire +DocumentRoot, cependant CUPS possède de nombreux emplacements virtuels pour l'administration, les classes, les travaux +d'impression et les imprimantes: +

+ + + + + + + + + + + + +
EmplacementDescription
/adminLe chemin pour toutes les opérations d'administration.
/classesLe chemin pour toutes les classes d'imprimantes.
/classes/nom_classeLes ressources pour la classe nommée nom_classe.
/jobsLe chemin pour tous les travaux d'impression.
/jobs/idLes ressources pour le travail d'impression n°id.
/printersLe chemin pour toutes les imprimantes.
/printers/nom_imprimanteLe chemin pour l'imprimante nommée nom_imprimante.
/printers/nom_imprimante.ppdLe chemin du fichier PPD pour l'imprimante nom_imprimante.
+
+

+

Authentification basée sur les certificats

+ +

CUPS prend en charge une authentification locale basée sur les certificats qui peut être utilisée à la place des authentifications +"Basic" et "Digest" pour les clients se connectant à l'interface localhost. +L'authentification par certificats n'est ni prise en charge, ni permise pour les clients se connectant par le biais de toute +autre interface.

+ +

Les certificats sont des nombres aléatoires codés sur 128 bits qui font référence à un enregistrement interne +d'authentification sur le serveur. Un client se connectant via l'interface localhost envoie une requête avec un en-tête d'autorisation:

+
    +
    +Authorization: Local 0123456789ABCDEF0123456789ABCDEF
    +
    +
+ +

Le serveur vérifie alors le certificat local correspondant et authentifie le nom d'utilisateur qui y est associé.

+ +

Les certificats sont automatiquement générés par le serveur et stockés dans le répertoire /etc/cups/certs +en utilisant le n° de processus du programme CGI ("process ID") exécuté par le serveur. Les fichiers de certificats sont +en lecture seule pour les utilisateurs User et groupes +Group définis dans le fichier cupsd.conf. Quand le programme CGI se termine, le certificat est retiré +et rendu automatiquement invalide.

+ +

Le fichier spécial /etc/cups/certs/0 définit le certificat de root qui peut être utilisé par tout client +fonctionnant sous l'identité du super-utilisateur et qui appartient au group défini par la directive +SystemGroup. +Le certificat de root est automatiquement régénéré toutes les 5 minutes.

+ +

Utilisation de l'authentification "Basic"

+ +

L'authentification "Basic" utilise les utilisateurs et mots de passe UNIX pour authentifier l'accès à des ressources +telles que les imprimantes ou les classes et pour limiter l'accès aux fonctions d'administration.

+ + +
NOTE: +

L'authentification "Basic" transmet le nom d'utilisateur et le mot de passe en clair (encodage Base64) du client vers +le serveur, donc elle n'offre aucune protection contre l'espionnage. Cela signifie qu'une utilisateur mal intentionné peut +écouter les paquets réseau et découvrir ces informations. Il peut en résulter une sérieuse compromission de la sécurité de +votre réseau. Utilisez l'authentification avec la plus grande prudence. +

+
+

+

L'implémentation de l'authentification "Basic" dans CUPS ne permet pas l'accès en utilisant des comptes sans +mot de passe. Si vous tentez d'authentifier un tel compte, l'accès sera immédiatement bloqué.

+

Une fois le nom d'utilisateur et le mot de passe authentifiés par CUPS, les contraintes supplémentaires d'appartenance à des groupes sont vérifiées +

+ + +
NOTE: +

Pour CUPS, l'utilisateur root est considéré comme membre de tous les groupes.

+
+
+ + +

+

Utilisez la directive AuthType pour activer l'authentification "Basic":

+
    +
    +AuthType Basic
    +
    +
+ + +

Utilisation de l'authentification "Digest"

+ +

L'authentification "Digest" utilise des utilisateurs et mots de passe définis dans le fichier /etc/cups/passwd.md5 pour authentifier l'accès aux ressources telles que les imprimantes et les classes et pour +limiter l'accès aux fonctions d'administration. +

+ + +
NOTE: + +

Contrairement à l'authentification "Basic", "Digest" transmet une version codée du nom d'utilisateur et du mot de passe +en utilisant le codage MD5 (en résumé, une somme de contrôle compliquée) au lieu de leur version en clair. De plus, +l'authentification "Digest" n'utilise pas les utilisateurs et mots de passe UNIX, ainsi si un attaquant découvre le mot de +passe original il est moins probable qu'il en résulte un problème de sécurité, pour peu que vous utilisiez un mot de passe +"Digest" différent de celui stocké par UNIX.

+ +

L'implémentation actuelle de l'authenfication "Digest" dans CUPS utilise le nom d'hôte du client ou son adresse IP comme +valeur "nonce". La valeur "nonce" est une chaîne de caractères additionnelle ajoutée au nom d'utilisateur et au mot de passe +pour rendre la découverte de ce dernier plus difficile. Le serveur vérifie que la valeur "nonce" correspond au nom d'hôte +ou l'adresse IP du client et, si tel n'est pas le cas, rejette la somme MD5 proposée par celui-ci. Les prochaines versions +de CUPS prendront en charge l'authentification "Digest" par "session" qui ajoutera les données de la requête à la somme +MD5, fournissant ainsi une sécurité et une authentification encore meilleures.

+ +

L'authentification "Digest" ne garantit pas qu'un attaquant ne peut pas obtenir un accès non autorisé mais elle est plus +sûre que l'authentification "Basic" et devrait être utilisée à la place de celle-ci chaque fois que c'est possible. +La prise en charge de l'authentification "Digest" dans les navigateurs "web" n'est pas encore universellement disponible.

+
+
+ + +

+

La commande lppasswd(1) est utilisée pour ajouter, changer et retirer des comptes du fichier passwd.md5. +Pour ajouter un utilisateur au groupe système standard, tapez:

+
    +
    +lppasswd -a utilisateur ENTREE
    +Password: (mot de passe) ENTREE  [le mot de passe n'est pas affiché]
    +Password again: (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +
    +
+ + +

Une fois ajouté, un utilisateur peut changer son mot de passe en tapant:

+
    +
    +lppasswd ENTREE
    +Old Password: (mot de passe) ENTREE  [le mot de passe n'est pas affiché]
    +Password : (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +Password again: (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +
    +
+ + +

Pour retirer un utilisateur du fichier des mots de passe, tapez:

+
    +
    +lppasswd -x utilisateur ENTREE
    +
    +
+

Une fois qu'un utilisateur et un mot de passe valides ont été authentifiés pas CUPS, celui-ci vérifie les +contraintes supplémentaires d'appartenance à des groupes. +

+ + +
NOTE: +

Pour CUPS, l'utilisateur root est membre de tous les groupes.

+
+
+

+

Utilisez la directive AuthType pour activer l'authentification "Digest":

+
    +
    +AuthType Digest
    +
    +
+

Authentifications "System" et "Group"

+

La directive AuthClass contrôle le niveau d'authentification +à effectuer. Les authentifications System et Group +ajoutent à l'authentification normale basée sur l'utilisateur une contrainte d'appartenance à un groupe UNIX. +Pour l'authentification System, chaque utilisateur doit être membre du groupe sys, +system, ou root; le groupe réel dépend du système d'exploitation.

+ +

Pour l'authentification Group l'utilisateur doit être membre du group indiqué par la directive +AuthGroupName:

+
    +
    +<Location /path>
    +AuthType Digest
    +AuthClass Group
    +AuthGroupName mygroup
    +</Location>
    +
    +
+

Le groupe indiqué doit être un groupe UNIX valide, habituellement défini dans les fichiers /etc/group +ou /etc/netgroup. De plus, lors de l'utilisation de l'authentification "Digest", vous devez créer les comptes +utilisateur avec le groupe indiqué:

+
    +
    +lppasswd -g mon_groupe -a utilisateur ENTER
    +Password : (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +Password again: (mot de passe) ENTREE [le mot de passe n'est pas affiché]
    +
    +
+ + +

Suivi/facturation de travaux et d'imprimantes

+

ESP Print Pro maintient à jour un suivi ("log") de tous les accès, erreurs et pages qui sont imprimées. Les fichiers de +suivi sont normalement stockés dans le répertoire /var/log/cups. +Vous pouvez changer cela en éditant le fichier de configuration /etc/cups/cupsd.conf.

+ +

Le fichier access_log

+

Le fichier access_log liste chaque ressource HTTP qui est utilisée par le serveur "web" ou un client CUPS/IPP. +Chaque ligne est structurée dans le format habituel utilisé par de nombreux serveurs "web" et outils d'analyse.:

+
    +
    +Hôte Groupe Utilisateur Date/heure \"Méthode Ressource Version\" Etat Octets
    +
    +127.0.0.1 - - [20/May/1999:19:20:29 +0000] "POST /admin/ HTTP/1.1" 401 0
    +127.0.0.1 - mike [20/May/1999:19:20:31 +0000] "POST /admin/ HTTP/1.1" 200 0
    +
    +
+

Le champ hôte ne devrait normalement être qu'une adresse IP à moins que vous n'activiez la directive +HostNameLookups dans le fichier cupsd.conf.

+ +

Le champ groupe contient toujours "-" dans CUPS.

+ +

Le champ utilisateur est le nom de l'utilisateur authentifié qui a émis la requête. Si aucun nom d'utilisateur et +mot de passe n'est fourni pour la requête, alors ce champ contient "-".

+

Le champ date/heure contient la date et l'heure de la requête exprimées dans le fuseau horaire local, et est structuré + de la manière suivante:

+
    +
    +[JJ/MMM/AAAA:HH:MM:SS +ZZZZ]
    +
    +
+

ZZZZ est le décalage horaire entre le fuseau horaire local et l'heure Greenwich Mean Time (a.k.a. GMT a.k.a. ZULU.) (NdT : en réalité GMT est un abus de langage, il s'agit du temps UTC...)

+

Le champ méthode est la méthode HTTP utilisée ("GET", "PUT", + "POST", etc.)

+

Le champ ressource est le nom du fichier de la ressource demandée.

+

Le champ version est la version du protocole HTTP employé par le client. +Pour les clients CUPS, c'est toujours "HTTP/1.1".

+

Le champ Etat contient l'état du résultat HTTP de la requête. Habituellement, il s'agit de la valeur "200", mais +d'autres codes d'état HTTP sont possibles. +Par exemple, 401 est le code d'état pour "accès non autorisé" dans l'exemple ci-dessus.

+

Le champs octets contient le nombre d'octets contenus dans la requête. +Pour les requêtes POST, le champ octets contient le nombre d'octets reçus du client.

+ +

Le fichier error_log

+ +

Le fichier error_log liste les messages provenant de l'ordonnanceur (erreurs, avertissements, etc.):

+
    +
    +Niveau Date/Heure Message
    +
    +I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
    +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'.
    +
    +
+

Le champ Niveau contient le type du message:

+
    +
  • E - Une erreur est survenue.
  • +
  • W - Le serveur a été incapable d'effectuer une action.
  • +
  • I - Message d'information.
  • +
  • D - Message de débogage.
  • +
+

Le champ Date/heure contient la date et l'heure de début d'impression de la page. +Le format est identique à celui du champ Date/heure dans le fichier access_log.

+

Le champ Message contient un message textuel dont la forme est libre.

+ +

Le fichier page_log

+ +

Le fichier page_log liste chaque page qui est envoyée à une imprimante. +Chaque ligne contient les informations suivantes:

+
    +
    +Imprimante Utilisateur N°travail Date/heure N°Page Nombre_copies Facturation_travail
    +
    +DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123
    +
    +
+

Le champ imprimante contient le nom de l'imprimante qui a imprimé la page. +Si vous envoyez un travail d'impression à une classe, le champ contient le nom de l'imprimante +à laquelle ce travail a été affecté..

+

Le champ utilisateur contient le nom de l'utilisateur (l'attribut requesting-user-name de IPP) +qui a envoyé le fichier à l'impression.

+

Le champ N°Travail contient le n° du travail correspondant à la page en cours d'impression. Les n° de travaux sont +remis à 1 si le serveur CUPS est redémarré, donc ne le considérez pas comme un identifiant unique !

+

Le champ Date/heure contient la date et l'heure de démarrage de l'impression dans un format identique au champ +Date/heure du fichier access_log.

+

Les champs N°Page et Nombre_copies contiennent le n° de page imprimée et le nombre de copies de cette page. +Pour les imprimantes qui ne peuvent pas produire de copies multiples de manière autonome, le champ Nombre_copies est toujours +à 1.

+

Le champ facturation_travail contient une copie de l'attribut job-billing + fourni dans les requête IPP create-job ou +print-job. Si aucune valeur n'est fournie dans la requête, ce champ contient "-". + +

+

Filtrage et détermination des types de fichiers

+ +

CUPS fournit un mécanisme de filtrage et de détermination du type de fichier basé sur MIME, afin de convertir les fichiers +dans un format utilisable par chaque imprimante. Au démarrage, le serveur CUPS lit les fichiers de la base de données MIME +contenus dans le répertoire /etc/cups (ou un répertoire indiqué au moyen de la directive ServerRoot) +afin de construire en mémoire une base de données de conversion et de types de fichiers. +Ces fichiers de base de données sont de simples fichiers texte ASCII et peuvent être modifiés au moyen de votre éditeur de texte +préféré.

+

Les fichiers mime.types et mime.convs définissent les types de fichiers standards et les filtres qui +sont disponibles sur le système.

+ +

Le fichier mime.types

+ +

Le fichier mime.types définit les types de fichiers connus. +Chaque ligne débute par le type MIME et devrait être suivi par une ou plusieurs règles de reconnaissance de fichier. Par exemple, +le type de fichier text/html est défini de la manière suivante:

+
    +
    +text/html       html htm \
    +                printable(0,1024) + \
    +                (string(0,"<HTML>") string(0,"<!DOCTYPE"))
    +
    +
+

Les deux premièress règles indiquent que tout fichier portant l'extension .html +ou .htm est un fichier HTML. La troisième règle précise que tout fichier dont les 1024 premiers caractères sont des +caractères imprimables et commencent par les chaînes <HTML> ou <!DOCTYPE est également un fichier HTML.

+ +

Les deux premières règle traitent simplement du nom du fichier. Cela est utile lorsque le nom du fichier original est +connu, cependant pour les fichiers d'impression le serveur ne dispose pas de nom de fichier. La troisième règle prend garde +à cette éventualité et détermine automatiquement le type du fichier en se basant plutôt sur son contenu.

+

Les test applicables sont les suivants:

+
    +
  • ( expr ) - Parenthèses pour grouper les expressions
  • +
  • + - ET logique
  • +
  • , ou espace vide - OU logique
  • +
  • ! - NON logique
  • +
  • match("pattern") - Recherche de motif sur le nom de fichier
  • +
  • extension - Recherche de motif sur "*.extension"
  • +
  • ascii(offset,length) - Vrai si les octets sont des caractères ASCII imprimables (CR, NL, TAB, BS, 32-126)
  • +
  • printable(offset,length) - Vrai si les octets sont des caractères 8 bits imprimables (CR, NL, TAB, BS, 32-126, 160-254)
  • +
  • string(offset,"chaîne") - Vrai si les octets sont identiques à la chaîne
  • +
  • contains(offset,range,"chaîne") - Vrai si la plage d'octets contient la chaîne
  • +
  • char(offset,value) - Vrai si l'octet correspond
  • +
  • short(offset,value) - Vrai si l'entier sur 16 bits correspond (ordre des octets : "network" ou "big-endian")
  • +
  • int(offset,value) - Vrai si l'entier sur 32 bits correspond (ordre des octets : "network" ou "big-endian")
  • +
  • locale("string") - Vrai si la locale courante correspond à la chaîne
  • +
+

Toutes les valeurs numériques peuvent être exprimées en décimal (123), octal (0123), ou hexadécimal (0x123) selon le cas. + +

+

Les chaînes de caractères peuvent être délimitées par des quotes, sans quotes, sous forme d'une chaîne de valeurs hexadécimales ou toute combinaison de ces écritures:

+
    +
    +"chaîne"
    +'chaîne'
    +chaîne
    +<737472696e67>
    +<7374>ring
    +
    +
+

Comme le montre l'exemple text/html, les règles peuvent être réparties sur plusieurs lignes en utilisant le +caractère "backslash" ("\"). Un exemple plus complexe est fourni par les règles de détermination du type image/jpeg:

+
    +
    +image/jpeg      jpeg jpg jpe string(0,<FFD8FF>) &&\
    +                (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
    +                 char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
    +                 char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
    +                 char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
    +
    +
+

Cette règle indique que tout fichier avec l'extension .jpeg, +.jpg, ou .jpe est un fichier JPEG. De plus, tout fichier commençant par la chaîne hexadécimale <FFD8FF> + (JPEG Start-Of-Image) suivie d'un caractère compris entre 0xe0 et 0xef (JPEG APPn markers) bornes comprises, est également +un fichier JPEG.

+ +

Le fichier mime.convs

+ +

Le fichier mime.convs définit tous les programmes de filtrage qui sont connus du système. +Chaque ligne est de la forme:

+
    +
    +Source Destination Coût Programme
    +
    +text/plain application/postscript 50 texttops
    +application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
    +image/* application/vnd.cups-postscript 50 imagetops
    +image/* application/vnd.cups-raster 50 imagetoraster
    +
    +
+

Le champ Source est un type MIME. Il peut éventuellement utiliser des méta caractères ("joker", "wildcard") +pour le sur-type ou le sous-type (par exemple "text/plain", "image/*", + "*/postscript").

+

Le champ Destination est un type MIME défini dans le fichier mime.types.

+

Le champ Coût définit un coût relatif pour l'opération de filtrage, exprimé sous forme d'une valeur entre 1 et 100. +Le coût est utilisé pour choisir entre deux jeux de filtres lors de la conversion d'un fichier. Par exemple, pour convertir +image/jpeg en application/vnd.cups-raster, vous pourriez utiliser les filtres imagetops + et pstoraster pour un coût total de 100, ou le filtre +imagetoraster pour un coût total de 50.

+

Le champ Programme définit le programme de filtrage à exécuter; le programme doit accepter les arguments standards de +filtrage et les variables d'environnement décrits dans le "Manuel de conception d'interface" ainsi que le "Manuel du programmeur":

+
    +
    +Programme Travail Utilisateur Titre Options [nom_fichier]
    +
    +
+

S'il est indiqué, l'argument nom_fichier définit un fichier à lire lors du filtrage, sinon le filtre doit lire l'entrée +standard. Toutes les sorties du programme de filtrage doivent être envoyées à la sortie standard. + +

+

Ajouter des filtres et des types de fichiers

+ +

Ajouter un nouveau filtre ou type de fichier est relativement simple. +Plutôt qu'ajouter le nouveau filtre ou type aux fichiers mime.types et +mime.convs qui sont écrasés lorsque vous mettez CUPS à jour avec une nouvelle version, +vous devez simplement créer de nouveaux fichiers avec les extensions .types et .convs +dans le répertoire /etc/cups. Nous recommandons d'utiliser le nom du format ou du produit, par exemple:

+
    +
    +myproduct.types
    +myproduct.convs
    +
    +
+

Si vous installez un filtre pour un fichier ou une imprimante courants, ajoutez le nom du fabricant ou de l'éditeur:

+
    +
    +acme-msword.types
    +acme.msword.convs
    +
    +
+

Cela aidera à éviter les conflits de noms si vous installez plusieurs types de fichiers ou plusieurs filtres.

+

Une fois choisis les noms pour ces fichiers, créez-les au moyen de votre éditeur de texte préféré comme décrit précédemment +dans ce chapitre. Une fois ces fichiers créés, redémarrez le processus cupsd comme indiqué précédemment +dans "Redémarrage du serveur CUPS" +.

+

Pilotes d'imprimantes et fichiers PPD

+ +

Plusieurs pilotes d'imprimante CUPS utilisent un ou plusieurs filtres spécifiques et un fichier PPD pour chaque +modèle d'imprimante. Les filtres pilotes d'imprimante sont enregistrés au moyen des attributs du fichier +cupsFilter:

+
    +
    +*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
    +
    +
+

Le filtre est indiqué en utilisant seulement le type du fichier source; +le type du fichier destination est considéré comme étant du type imprimante/nom - + convenable pour envoi à l'imprimante.

+ +

Ecrire vos propres filtres ou pilotes d'imprimantes

+ +

CUPS prend en charge un nombre illimité de filtres et de formats de fichiers, et peut traiter avec toute imprimante. +Si vous désirez écrire un pilote ou un filtre pour votre imprimante préférée, consultez le "Manuel du programmeur" et suivez +pas à pas les instructions qu'il contient.

+ +

7 - Imprimer depuis et vers d'autres systèmes

+ +

Ce chapitre décrit comment imprimer depuis des système clients qui utilisent les protocoles d'impression +LPD, Mac OS ou Windows.

+ +

Les bases

+ +

CUPS est basé sur le protocole IPP, ainsi tout autre système prenant en charge IPP peut automatiquement envoyer ou recevoir +des travaux d'impression vers ou depuis un système utilisant CUPS. Cependant, tous les systèmes ne prennent pas encore en +charge IPP. Ce chapitre vous montrera comment connecter ces systèmes à votre serveur CUPS, que ce soit pour qu'ils +puissent accepter des travaux provenant de celui-ci ou pour lui en envoyer.

+ +

Imprimer depuis des clients LPD

+ +

CUPS prend en charge un nombre limité des fonctionnalités des clients basés sur LPD. Avec LPD vous pouvez imprimer des +fichiers vers des imprimantes déterminées, voir l'état des files d'impression, etc. Cependant, la configuration automatique +des clients et des imprimantes n'est pas prise en charge par le protocole LPD, donc vous devez configurer manuellement chaque +client pour les imprimantes auxquelles il a besoin d'accéder.

+ +

Le programme cups-lpd(8) fournit la prise en charge pour les clients LPD. +Pour activer la prise en charge LPD sur votre serveur, éditez le contenu du fichier +/etc/inetd.conf et ajoutez une ligne:

+
    +
    +printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
    +
    +
+

Le chemin vers le programme cups-lpd peut varier en fonction de l'installation de votre serveur.

+

Une fois cette ligne ajoutée, envoyez un signal HUP au processus inetd(8) ou redémarrez le +système (NdT : le redémarrage du système n'est pas des plus élégants...):

+
    +
    +killall -HUP inetd ENTREE [sur IRIX et quelques distributions GNU/Linux]
    +kill -HUP pid ENTREE [Autres systèmes]
    +reboot ENTREE [Pour tous les systèmes si le signal HUP ne fonctionne pas (NdT : ...en DERNIER recours, uniquement...)]
    +
    +
+

Imprimer vers des serveurs LPD

+ +

CUPS fournit le programme d'arrière-plan lpd pour imprimer vers des serveurs et imprimantes +utilisant LPD. Utilisez un URI de périphérique de la forme lpd://serveur/nom +pour imprimer ver une imprimante sur un serveur LPD, où serveur +est le nom d'hôte ou l'adresse IP du serveur et nom est le nom de la file d'impression.

+ +

Microsoft Windows NT fournit un service LPD sous le nom "Serveur d'impression TCP/IP". +Pour activer l'impression sur un système Windows NT, ouvrez le panneau de configuration puis "Services", sélectionnez +le service "Serveur d'impression TCP/IP" et cliquez sur le bouton "Démarrer". Toute imprimante partagée +devient alors accessible via le protocole LPD.

+ +

Imprimer depuis des client Mac OS

+ +

NdT : je ne suis pas spécialiste Mac et je ne dispose pas de ce type de matériel. Il se peut qu'il y ait quelques imprécisions ou erreurs dans ce qui suit, faîtes-moi +l'amitié de me les pardonner ET de me les signaler. Merci par avance...

+ +

CUPS ne fournit pas de prise en charge directe de Mac OS. Cependant, il existe plusieurs logiciels libres ou commerciaux +qui le font.

+ +

Columbia Appletalk Package (CAP)

+ +

Etant donné que le serveur CAP LaserWriter (lwsrv(8)) ne prend pas en charge les spécifications des fichiers +PPD, nous ne recommandons pas l'utilisation de CAP avec CUPS. Cependant, vous pouvez exécuter le programme lpsrv +pour une prise en charge limitée de l'impression au moyen de la syntaxe suivante:

+
    +
    +lwsrv -n "Nom" -p Imprimante -a /usr/lib/adicts -f /usr/lib/LW+Fonts
    +
    +
+

Nom est le nom que vous voulez utiliser pour partager l'imprimante et imprimante +est le nom de la file d'impression. + +

+

XINET KA/Spool

+ +

Afin d'utiliser votre système comme serveur d'impression pour des clients Mac OS, configurez chaque imprimante en utilisant +papserver(8) dans le fichier /usr/adm/appletalk/services, et en indiquant le fichier PPD correspondant +dans le répertoire/etc/cups/ppd. +Pour une imprimante appelée Mon_Imprimante la syntaxe serait de la forme suivante:

+
    +
    +/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/Mon_Imprimante.ppd \
    +"Printer Description" Mon_Imprimante
    +
    +
+
+ + +
NOTE: +

Entrez le texte ci-dessus sur une seule ligne sans le caractère "\".

+
+
+ +

NetATalk

+ +

Pour utiliser votre système comme serveur d'impression pour des clients Mac OS, configurez chaque imprimante dans le +fichier papd.conf, en indiquant le fichier PPD correspondant dans le répertoire /etc/cups/ppd pour +chaque imprimante. Pour une imprimante nommée Mon_Imprimante le texte serait de la forme suivante:

+
    +
    +Printer Description:Mon_Imprimante@Mon_Serveur:\
    +        :pr=|/usr/bin/lp -d Mon_Imprimante:\
    +        :op=daemon:\
    +        :pd=/etc/cups/ppd/Mon_Imprimante.ppd:
    +
    +
+ + +

Imprimer vers des serveurs d'impression Mac OS

+ +

Actuellement, CUPS ne fournit pas de programme d'arrière-plan pour communiquer avec un serveur Mac OS. Cependant, vous +pouvez écrire et installer un court script dans le répertoire /usr/lib/cups/backend qui envoie +un fichier d'impression en utilisant la commande appropriée. Le court script suivant exécutera la commande +papif fournie avec CAP.

+

Après avoir copié le script dans /usr/lib/cups/backend/cap, indiquez un URI de périphérique de la forme +cap://serveur/imprimante pour utiliser ce script avec une file d'impression. + +

+
    +
    +"/usr/lib/cups/backend/cap"
    +#!/bin/sh
    +#
    +# Usage: cap job user title copies options [filename]
    +#
    +
    +# No arguments means show available devices...
    +
    +if test ${#argv} = 0; then
    +	echo "network cap \"Unknown\" \"Mac OS Printer via CAP\""
    +	exit 0
    +fi
    +
    +# Collect arguments...
    +
    +user=$2
    +copies=$4
    +
    +if test ${#argv} = 5; then
    +	# Get print file from stdin; copies have already been handled...
    +	file=/var/tmp/$$.prn
    +	copies=1
    +	cat > $file
    +else
    +	# Print file is on command-line...
    +	file=$6
    +fi
    +
    +# Create a dummy cap.printers file for this printer based
    +# upon a device URI of "cap://server/printer"...
    +
    +echo $PRINTER/$DEVICE_URI | \
    +	awk -F/ '{print $1 "=" $5 ":LaserWriter@" $4}' > /var/tmp/$$.cap
    +
    +CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
    +
    +# Send the file to the printer, once for each copy. This assumes that you
    +# have properly initialized the cap.printers file...
    +
    +while [ $copies -gt 0 ]; do
    +	papif -n $user < $file
    +
    +        copies=`expr $copies - 1`
    +done
    +
    +# Remove any temporary files...
    +if test ${#argv} = 5; then
    +	/bin/rm -f $file
    +fi
    +
    +/bin/rm -f /var/tmp/$$.cap
    +
    +exit 0
    +
    +
+ + + +

Imprimer depuis des clients Windows

+ +

Bien que CUPS ne fournisse directement pas de prise en charge de Windows, le logiciel libre SAMBA le fait. La version +2.0.6 de SAMBA est la première qui prenne en charge CUPS. Vous pouvez télécharger SAMBA à l'adresse :

+ +

Pour configurer SAMBA pour CUPS, éditez le contenu du fichier smb.conf +et remplacez les commandes d'impression existantes par les lignes:

+
    +
    +printing = cups
    +printcap name = cups
    +
    +
+

C'est tout ce qu'il y a à faire! Les utilisateurs distants pourront désormais explorer les imprimantes de votre système et +leur envoyer des travaux d'impression.

+ +

Exporter les pilotes d'imprimantes

+ +

Vous pouvez éventuellement exporter des pilotes d'imprimantes de votre serveur CUPS en utilisant la commande +cupsaddsmb et le logiciel SAMBA 2.2.0 ou supérieur.

+ +

Avant de pouvoir exporter les pilotes d'imprimantes, vous devez télécharger les pilotes d'imprimantes actuels Adobe PostScript +à partir du site "web" Adobe +(http://www.adobe.com/). +Utilisez le logiciel libre unzip pour extraire les fichiers des archives ZIP auto-extractibles contenant +les pilotes; vous aurez besoin des fichiers suivants:

+
    +
    +ADFONTS.MFM
    +ADOBEPS4.DRV
    +ADOBEPS4.HLP
    +ADOBEPS5.DLL
    +ADOBEPSU.DLL
    +ADOBEPSU.HLP
    +DEFPRTR2.PPD
    +ICONLIB.DLL
    +PSMON.DLL
    +
    +
+

Copiez ces fichiers dans le répertoire /usr/share/cups/drivers - vous pourriez avoir à renommer certains fichiers +de sorte que tous les noms soient complètement en majuscules.

+

Ensuite, ajouter un partage d'imprimante print$ pour les pilotes d'imprimantes à votre fichier +smb.conf:

+
    +
    +[print$]
    +    comment = Pilotes d'imprimantes
    +    path = /etc/samba/drivers
    +    browseable = yes
    +    guest ok = no
    +    read only = yes
    +    write list = root
    +
    +
+ +

Le répertoire de vos pilotes d'imprimantes peut être n'importe où dans le système; assurez-vous simplement qu'il est +accessible en écriture aux utilisateurs indiqués par la directive write list. +Assurez-vous également que chaque utilisateur de la liste write list possède un mot de passe SAMBA en utilisant +la commande smbpasswd(1) sinon vous ne pourrez pas vous authentifier.

+

Enfin, exécutez la commande cupsaddsmb pour exporter les pilotes d'imprimantes pour une ou plusieurs +files d'impression:

+
    +
    +cupsaddsmb -U root printer1 ... printerN ENTREE
    +
    +
+

Exécuter la commande cupsaddsmb avec l'option -a exportera les imprimantes:

+
    +
    +cupsaddsmb -U root -a ENTREE
    +
    +
+

Imprimer vers des serveurs d'impression Windows

+ +

CUPS peut imprimer vers des serveurs Windows de deux façons. La première utilise le protocole LPD sur le système CUPS et +le service "Serveur d'impression TCP/IP" sur le système Windows NT. Vous pouvez trouver plus d'information au sujet de la première +configuration dans la section précédente LPD de ce chapitre.

+ +

La seconde méthode utilise le protocole SMB de Microsoft ("Server Message Block"). La prise en charge de ce protocole est +fournie par le logiciel libre SAMBA. Vous pouvez télécharger SAMBA à l'adresse suivante:

+ +

Pour configurer CUPS pour SAMBA, exécutez la commande suivante:

+
    +
    +ln -s `which smbspool` /usr/lib/cups/backend/smb ENTREE
    +
    +
+

Le programme smbspool(1) est fourni avec SAMBA depuis la version 2.0.6. Une fois que vous avez créé le lien +vous pouvez configurer vos imprimantes en utilisant l'un des URI de périphérique suivants:

+
    +
    +smb://groupe_de_travail_ou_domaine/serveur/nom_partage
    +smb://serveur/nom_partage
    +smb://utilisateur:mot_de_passe@groupe_de_travail_ou_domaine/serveur/nom_partage
    +smb://utilisateur:mot_de_passe@serveur/nom_partage
    +
    +
+

Le nom groupe_de_travai_ou_domaine doit être indiqué si votre système utilise un autre nom que la +valeur standard de votre réseau. Les chaînes utilisateur:mot_de_passe sont nécessaires si vous imprimez +vers des serveurs Windows NT ou des partages Windows 95/98 dont les mots de passe sont activés.

+ +

A - Licence d'utilisation du logiciel

+

Common UNIX Printing System License + Agreement

+

(NdT : pour des raisons évidentes de droit, j'ai volontairement gardé la licence d'utilisation du logiciel et la licence GPL en anglais car une traduction +de celles-ci pourrait donner lieu à des interprétations erronées... et en plus je ne suis pas juriste !)

+ +

Copyright 1997-2002 by Easy Software Products +
44141 AIRPORT VIEW DR STE 204 +
HOLLYWOOD, MARYLAND 20636-3111 USA +
+
Voice: +1.301.373.9600 +
Email: cups-info@cups.org +
WWW: http://www.cups.org

+

Introduction

+

The Common UNIX Printing SystemTM, ("CUPSTM"), + is provided under the GNU General Public License ("GPL") and GNU + Library General Public License ("LGPL"), Version 2. A copy of these + licenses follow this introduction.

+

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_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.93a.

+

For those not familiar with the GNU GPL, the license basically allows + you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in source or binary form.
  • +
  • Sell verbatim copies of the software for a media fee, or sell + support for the software.
  • +
  • Distribute or sell printer drivers and filters that use CUPS so long + as source code is made available under the GPL.
  • +
+

What this license does not 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.

+

The GNU LGPL relaxes the "link-to" restriction, allowing you to + develop applications that use the CUPS API library under other licenses + and/or conditions as appropriate for your application.

+

Trademarks

+

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.

+

Binary Distribution Rights

+

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.

+

The Common UNIX Printing System provides a "pstoraster" 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:

Miles Jones +
Director of Marketing +
Artifex Software Inc. +
454 Las Gallinas Ave., Suite 108 +
San Rafael, CA 94903 USA +
Voice: +1.415.492.9861 +
Fax: +1.415.492.9862 +
EMail: info@arsoft.com
+

+

The "pdftops" filter is based on the Xpdf 0.93a software. For binary + distribution licensing of this software, please contact:

+ Derek B. Noonburg +
Email: derekn@foolabs.com +
WWW: + http://www.foolabs.com/xpdf/

+

Support

+

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:

+ + + +

GNU GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+
+
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow.

+

GNU GENERAL PUBLIC LICENSE +
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+
    +
  1. 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 "Program", below, + refers to any such program or work, and a "work based on the Program" + 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 "modification".) Each licensee is addressed as "you".
  2. +

    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.

    +
  3. 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.
  4. +

    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.

    +
  5. 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: +
      +
    1. You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change.
    2. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +
  6. +

    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.

    +

    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.

    +

    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.

    +
  7. 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: +
      +
    1. 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,
    2. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +
  8. +

    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.

    +

    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.

    +
  9. 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.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. 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.
  16. +

    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.

    +

    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.

    +

    This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

    +
  17. 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.
  18. +
  19. 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.
  20. +

    Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", 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.

    +
  21. 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.
  22. +
+

NO WARRANTY

+
    +
  1. 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 "AS IS" 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.
  2. +
  3. 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.
  4. +
+

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, while the latter only + works together with the library.

+

Note that it is possible for a library to be covered by the ordinary + General Public License rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+

0. 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 "this License"). Each + licensee is addressed as "you".

+

A "library" 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.

+

The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" 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 "modification".)

+

"Source code" 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.

+

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.

+

1. 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.

+

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.

+

2. 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:

+
    +
  1. The modified work must itself be a software library.
  2. +

    +
  3. You must cause the files modified to carry prominent notices stating + that you changed the files and the date of any change.
  4. +

    +
  5. You must cause the whole of the work to be licensed at no charge to + all third parties under the terms of this License.
  6. +

    +
  7. 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.
  8. +

    (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.)

    +
+

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.

+

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.

+

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.

+

3. 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.

+

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.

+

This option is useful when you wish to copy part of the code of the + Library into a program that is not a library.

+

4. 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.

+

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.

+

5. 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 "work that uses the + Library". Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License.

+

However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. Section + 6 states terms for distribution of such executables.

+

When a "work that uses the Library" 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.

+

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.)

+

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.

+

6. As an exception to the Sections above, you may + also compile or link a "work that uses the Library" 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.

+

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:

+
    +
  1. 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 "work that uses the Library", 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.)
  2. +

    +
  3. 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.
  4. +

    +
  5. 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.
  6. +

    +
  7. Verify that the user has already received a copy of these materials + or that you have already sent this user a copy.
  8. +
+

For an executable, the required form of the "work that uses the + Library" 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.

+

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.

+

7. 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:

+
    +
  1. 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.
  2. +

    +
  3. 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.
  4. +
+

8. 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.

+

9. 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.

+

10. 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.

+

11. 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.

+

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.

+

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.

+

This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

+

12. 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.

+

13. 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.

+

Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and "any + later version", 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.

+

14. 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.

+

NO WARRANTY

+

15. 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 "AS IS" 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.

+

16. 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.

+

END OF TERMS AND CONDITIONS

+

B - Réglages réseau courants

+ +

Cette annexe englobe de nombreux serveurs d'impression et interfaces réseau TCP/IP disponibles actuellement sur le marché.

+ +

Configurer une interface réseau

+ +

Lorsque vous installez votre imprimante réseau ou votre serveur d'impression pour la première fois sur votre réseau +local (LAN), vous devez configurer son adresse IP ("Internet Protocol"). Sur la plupart des imprimantes réseau pour groupe +de travail, vous pouvez le faire directement au moyen du panneau de contrôle. Cependant, dans la plupart des cas, vous +préfèrerez assigner l'adresse IP à distance depuis votre station de travail. Cela rend l'administration un peu plus simple et +évite d'assigner accidentellement des adresses réseau eu doublons.

+ +

Pour configurer votre imprimante ou votre serveur d'impression pour une assignation à distance de l'adresse réseau, vous +aurez besoin de son adresse MAC (ethernet Media Access Control), également appelée adresse de noeud ("node address") dans +certains cas. Vous aurez également besoin de connaître l'adresse IP que vous voulez utiliser pour ce matériel. L'adresse MAC +peut souvent être trouvée sur la page de test de l'imprimante ou sur son panneau arrière. + +

+

Configuration de l'adresse IP utilisant ARP

+ +

La méthode la plus simple pour installer l'adresse IP d'un matériel réseau est d'utiliser la commande +arp(8). La commande arp envoie un paquet ARP ("Address Resolution Protocol") à l'adresse MAC indiquée +tout en lui indiquant son adresse IP:

+
    +
    +arp -s adresse-ip adresse-mac ENTREE
    +arp -s hote.domaine.com 08:00:69:00:12:34 ENTREE
    +arp -s 192.0.2.2 08:00:69:00:12:34 ENTREE
    +
    +
+

Configuration de l'adresse IP utilisant RARP

+ +

La manière la plus souple d'assigner une adresse IP sous UNIX est d'utiliser le protocole RARP +("Reverse Address Resolution Protocol"). RARP permet à un matériel réseau d'émettre une requête d'adresse IP en utilisant +sont adresse MAC, un ou plusieurs serveurs RARP sur le réseau répondront à cette requête par un paquet ARP proposant une +adresse IP que le matériel réseau peut utiliser.

+ +

RARP devrait être utilisé lorsque vous administrez de nombreuses imprimantes ou serveurs d'impression, ou quand un matériel +réseau ne peut se "souvenir" de son adresse IP après chaque redémarrage. Si vous n'avez qu'une seule imprimante ou serveur +d'impression, la commande arp est la plus adaptée.

+ +

Certains systèmes d'exploitation UNIX utilisent un programme nommé rarpd(8) pour administrer RARP. +Les autres, tels que GNU/Linux, prennent en charge ce protocole à l'intérieur du noyau. Pour les systèmes qui utilisent +le programme rarpd vous aurez besoin de le démarrer avant que les requêtes RARP commencent:

+
    +
    +rarpd ENTREE
    +
    +
+

Sous IRIX vous pouvez activer cette fonctionnalité en standard en utilisant la commande suivante:

+
    +
    +chkconfig rarpd on ENTREE
    +
    +
+

Le programme rarpd et la version noyau de la prise en charge RARP lisent toutes les deux une liste des adresses +MAC et IP à partir d'un fichier /etc/ethers. Chaque ligne comporte l'adresse Ethernet suivie de l'adresse IP ou +du nom d'hôte:

+
    +
    +08:00:69:00:12:34 mon_imprimante.mon_domaine.com
    +08:00:69:00:12:34 192.0.2.2
    +
    +
+

Ajoutez une ligne à ce fichier et redémarrez l'imprimante ou le serveur d'impression pour qu'elle/il récupère son adresse IP. + +

+

Configuration de l'adresse IP utilisant BOOTP

+ +

Le protocole BOOTP est utilisé quand vous avez besoin de fournir des informations supplémentaires à l'interface réseau +telles que l'emplacement du fichier de configuration. En utilisant le programme standard bootpd(8) +fourni sous UNIX, vous avez simplement besoin d'ajouter la ligne suivante au fichier /etc/bootptab pour IRIX:

+
    +
    +mon_imprimante 08:00:69:00:12:34 192.0.2.2 mon_imprimante.boot
    +
    +
+ + +

Les versions plus récentes de bootpd utilisent un format différent:

+
    +
    +mon_imprimante:ha=080069001234:ip=192.0.2.2:t144=mon_imprimante.boot
    +
    +
+

Le fichier mon_imprimante.boot est situé en standard dans le répertoire /usr/local/boot +Si vous n'avez pas besoin de fournir un fichier de démarrage, vous pouvez laisser vide la fin de la ligne. + + +

+ + +
NOTE: +

Certaines versions d'UNIX n'activent pas le service BOOTP en standard. Le fichier +/etc/inetd.conf contient généralement une ligne pour le service BOOTP. ELle peut être décommentée si nécessaire.

+
+
+

+

Vérifier la connexion de l'imprimante

+ +

Pour vérifier que l'adresse IP a bien été assignée et que l'imprimante est correctement connectée au réseau local (LAN), tapez:

+
    +
    +ping adresse-ip ENTREE
    +
    +
+

Si la connexion fonctionne correctement vous devriez voir apparaître quelque chose de la forme suivante :

+
    +
    +ping mon_imprimante ENTREE
    +PING mon_imprimante (192.0.2.2): 56 data bytes
    +64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
    +64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
    +
    +
+

Sinon, vérifiez que que l'imprimante ou le serveur d'impression est bien connecté au réseau (NdT : vérifiez ces @#*¤%§ câbles !), +qu'elle est sous tension et que l'adresse IP est bonne. Vous pouvez également voir la configuration réseau en imprimant une +page de test à partir du panneau de contrôle du matériel. + +

+

Réglages d'interfaces réseau et serveur d'impression courants

+ +

Une fois que vous avez configuré l'adresse IP, vous pouvez accéder à l'imprimante ou au serveur d'impression +en utilisant les programmes d'arrière-plan ipp, lpd, ou socket. +La liste qui suit donne les interfaces réseau et serveurs d'impression courants ainsi que les réglages que vous devriez +utiliser dans CUPS: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Modèle / FabricantURI de périphérique
Apple LaserWriterlpd:// +address/PASSTHRU
Axis w/o IPP +
(voir instructions)
socket://address +:9100 +
socket://address:9101 +
socket://address:9102
Axis w/IPPipp://address +/LPT1 +
ipp://address/LPT2 +
ipp://address/COM1
Castelle LANpressTM +lpd://address/pr1 +
lpd://address/pr2 +
lpd://address/pr3
DPI NETPrintlpd://address +/pr1 +
lpd://address/pr2 +
lpd://address/pr3
EFI® Fiery® RIPlpd:// +address/print
EPSON® Multiprotocol Ethernet + Interface Boardsocket://address
Extended System ExtendNET +lpd://address/pr1 +
lpd://address/pr2 +
lpd://address/pr3
Hewlett Packard JetDirect w/o IPP +socket://address:9100 +
socket://address:9101 +
socket://address:9102
Hewlett Packard JetDirect w/IPP +ipp://address/ipp +
ipp://address/ipp/port1 +
ipp://address/ipp/port2 +
ipp://address/ipp/port3
Intel® NetportExpress XL, PRO/100 +lpd://address/LPT1_PASSTHRU +
lpd://address/LPT2_PASSTHRU +
lpd://address/COM1_PASSTHRU
LexmarkTM MarkNet +lpd://address/ps
Linksys EtherFast® +
(voir instructions)
socket://address +:4010 +
socket://address:4020 +
socket://address:4030
Kodak®lpd://address/ps
QMS® CrownNetTM +lpd://address/ps
Tektronix® PhaserShareTM +socket://address:9100
XEROX® 4512 NIClpd:// +address/PORT1
XEROX® XNIClpd://address +/PASSTHRU
XEROX® (most others)socket:// +address:5503
+
+

+

Configuration de serveurs d'impression Axis

+ +

Les serveurs d'impression Axis peuvent être configurés en utilisant ARP, RARP ou BOOTP. Cependant, sur certains modèles +ne prenant pas en charge IPP, une configuration supplémentaire est nécessaire pour permettre au serveur de dialoguer avec CUPS. + +

+

Chaque serveur d'impression possède une fichier de configuration nommé config +qui contient la liste des paramètres réseau à utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord le +télécharger à partir du serveur d'impression en utilisant le programme ftp(1):

+
    +
    +ftp adresse-ip ENTREE
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTREE
    +331 User name ok, need password
    +Password: pass ENTREE (le mot de passe n'apparaît pas)
    +230 User logged in
    +ftp> get config ENTREE
    +local: config remote: config
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2),
    +(mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+ + +

Ensuite, éditez son contenu avec votre éditeur de texte préféré et repérez les lignes commençant par:

+
    +
    +RTN_OPT.     : YES
    +RTEL_PR1.    : 0
    +RTEL_PR2.    : 0
    +RTEL_PR3.    : 0
    +RTEL_PR4.    : 0
    +RTEL_PR5.    : 0
    +RTEL_PR6.    : 0
    +RTEL_PR7.    : 0
    +RTEL_PR8.    : 0
    +
    +
+ + +Changez la ligne RTN_OPT en: +
    +
    +RTN_OPT.     : NO
    +
    +
+ + +

Cela désactive le protocole "Reverse TELNET" et active le protocole standard TELNET sur le serveur d'impression. +Ensuite, assignez un numéro de port pour chaque port parallèle ou série sur le serveur, comme suit:

+
    +
    +RTEL_PR1.    : 9100
    +RTEL_PR2.    : 9101
    +RTEL_PR3.    : 9102
    +RTEL_PR4.    : 9103
    +RTEL_PR5.    : 9104
    +RTEL_PR6.    : 9105
    +RTEL_PR7.    : 9106
    +RTEL_PR8.    : 9107
    +
    +
+ + +

Cela a principalement pour effet de forcer le serveur Axis à ressembler à un serveur d'impression +Hewlett Packard JetDirect EX. Sauvegardez le fichier et installez le sur le serveur d'impression dans le fichier +config au moyen de la commande ftp:

+
    +
    +ftp adresse-ip ENTREE
    +Connected to adresse-ip.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTREE
    +331 User name ok, need password
    +Password: pass ENTREE (le mot de passe n'est pas affiché)
    +230 User logged in
    +ftp> put config CONFIG ENTREE
    +local: config remote: CONFIG
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2), (mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> get hardreset ENTREE
    +local: hardreset remote: hardreset
    +200 PORT command successful.
    +421 Axis NPS ### hard reset, closing connection.
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+

Votre serveur d'impression Axis est à présent opérationnel!

+ +

Configuration de serveurs d'impression Linksys

+ +

Les serveurs d'impression LinkSys peuvent être configurés au moyen de ARP, RARP ou BOOTP. Comme certains serveurs +d'impression Axis anciens, une configuration supplémentaire TCP/IP est nécessaire pour les faire fonctionner avec CUPS + +

+

Chaque serveur d'impression possède une fichier de configuration nommé config +qui contient la liste des paramètres réseau à utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord le +télécharger à partir du serveur d'impression en utilisant le programme ftp(1):

+
    +
    +ftp -n adresse-ip ENTREE
    +Connected to adress-ip.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> get CONFIG ENTREE
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +WARNING! 68 bare linefeeds received in ASCII mode
    +File may not have transferred correctly.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+ + +

Ensuite, éditez son contenu avec votre éditeur de texte préféré et repérez les lignes commençant par:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P1
    +0140 L3_PROUT:P1
    +
    +
+

Changez le numéro de port pour chaque port parallèle et série sur le serveur, comme suit:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P2
    +0140 L3_PROUT:P3
    +
    +
+ + +

Cela relie chaque imprimante virtuelle à un port physique. Sauvegardez le fichier et installez le sur le serveur d'impression dans le fichier +config au moyen de la commande ftp:

+
    +
    +ftp -n adresse-ip ENTREE
    +Connected to adresse-ip.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> put CONFIG ENTREE
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTREE
    +221 Goodbye.
    +
    +
+

Votre serveur d'impression SysLink est désomais opérationnel !

+ +

C - Pilotes d'imprimantes

+

Cette annexe dresse la liste des pilotes d'imprimantes qui sont fournis avec CUSP.

+

Pilotes d'imprimantes

+

CUPS inclut les pilotes d'imprimantes suivants:

+ +

EPSON 9-pin Dot Matrix

+

Le pilote EPSON 9-pin Dot Matrix (epson9.ppd) prend en charge les imprimantes 9 aiguilles qui utilisent le jeu de commandes ESC/P. +Il fournit l'impression en noir et blanc dans les résolutions 60x72, 120x72, et 240x72 PPP (DPI).

+ +

EPSON 24-pin Dot Matrix

+

Le pilote EPSON 24-pin Dot Matrix (epson9.ppd) prend en charge les imprimantes 24 aiguilles qui utilisent le jeu de commandes ESC/P. +Il fournit l'impression en noir et blanc dans les résolutions 120x180, 180x180, 360x180, et 360x360 PPP (DPI).

+ +

EPSON Stylus Color

+ +

Le pilote EPSON Stylus Color (stcolor.ppd) prend en charge les imprimantes EPSON + Stylus Color qui utilisent le jeu de commandes ESC/P2. +Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et blanc dans les résolutions 180, 360, et 720 PPP (DPI).

+ +

EPSON Stylus Photo

+ +

Le pilote EPSON Stylus Photo (stphoto.ppd) prend en charge les imprimantes EPSON + Stylus Photo qui utilisent le jeu de commandes ESC/P2. +Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et blanc dans les résolutions 180, 360, et 720 PPP (DPI).

+ +

HP DeskJet

+ +

Le pilote HP DeskJet (deskjet.ppd) prend en charge les imprimantes HP DeskJet +qui utilisent le jeu de commandes PCL. +Il fournit l'imrpession en couleur (CMYK) ainsi qu'en noir et blanc dans les résolutions 150, 300, et + 600 PPP (DPI).

+ +

Les imprimantes DeskJet qui utilisent le jeu de commandes HP-PPA (720C, + 722C, 820C, and 1100C) ne sont pas prises en charge du fait de l'absence totale de documentation de la part de +Hewlett Packard.

+ +

Le "duplexer" fourni avec les imprimantes de la série d'imprimantes HP DeskJet 900 n'est également pas pris en charge pour les mêmes raisons.

+ +

HP LaserJet

+ +

Le pilote HP LaserJet (laserjet.ppd) prend en charge les impriamntes HP LaserJet +qui utilisent le jeu de commandes PCL. +Il fournit l'impression seulement en noir et blanc et prend en charge le "duplexer" s'il est installé. +Il prend en charge les résolutions 150, 300, et 600 PPP (DPI).

+ +

Les imprimantes LaserJet qui n'utilisent pas le jeu de commandes PCL (3100, 3150) ne sont pas prises en charge +du fait d'une absence totale de documentation de la part de Hewlett Packard.

+ +

D - Liste des fichiers

+ +

Cette annexe dresse la liste des fichiers et répertoire qui sont installés par CUPS +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CheminDescription
/etc/cups/certs/Emplacement des fichiers des certificats d'authentification pour les clients HTTP locaux.
/etc/cups/classes.confFichiers de configuration des classes d'imprimantes pour l'ordonnanceur.
/etc/cups/cupsd.confFichier de configuration de l'ordonnanceur.
/etc/cups/interfaces/Emplacement des scripts d'interface System V pour les imprimantes.
/etc/cups/mime.convsListe des filtres de fichiers standards inclus dans ESP Print Pro.
/etc/cups/mime.typesListe des types de fichiers reconnus par ESP Print Pro.
/etc/cups/ppd/Emplacement des fichiers PPD ("PostScript Printer Description") pour les imprimantes.
/etc/cups/printers.confFichier de configuration des imprimantes pour l'ordonnanceur.
/usr/bin/cancelLa commande d'annulation de travaux System V.
/usr/bin/disableLa commande de désactivation d'imprimante System V.
/usr/bin/enableLa commande d'activation d'imprimante System V.
/usr/bin/lpLa commande d'impression System V.
/usr/bin/lpoptionsJeu d'options d'impression et de valeurs implicites personnalisées par l'utiliseur.
/usr/bin/lppasswdAjoute, modifie et retire des mots de passe pour des comptes "Digest".
/usr/bin/lpqLa commande d'état Berkeley.
/usr/bin/lprLa commande d'impression Berkeley.
/usr/bin/lprmLa commande d'annulation de travaux Berkeley.
/usr/bin/lpstatLa commande d'état System V.
/usr/include/cups/Fichiers d'en-tête de l'API CUPS.
/usr/lib32/libcups.a +
/usr/lib32/libcupsimage.a
Librairies statiques (IRIX 6.5)
/usr/lib/libcups.a
/usr/lib/libcupsimage.a
Librairies statiques (tous les autres systèmes)
/usr/lib/libcups.sl.2 +
/usr/lib/libcupsimage.sl.2
Librairies partagées (HP-UX)
/usr/lib32/libcups.so.2 +
/usr/lib32/libcupsimage.so.2
Librairies partagées (IRIX 6.5)
/usr/lib/libcups.so.2 +
/usr/lib/libcupsimage.so.2
Librairies partagées (tous les autres systèmes)
/usr/lib/cups/backend/Programme d'arrière-plan pour connexion à diverses imprimantes.
/usr/lib/cups/cgi-bin/Programmes CGI pour l'ordonnanceur.
/usr/lib/cups/daemon/Démons pour la surveillance et pour la prise en charge LPD.
/usr/lib/cups/filter/Filtres pour divers types de fichiers.
/usr/lib/locale/Emplacement des fichiers de messages spécifiques à chaque langue. (System V)
/usr/lib/nls/msg/Emplacement des fichiers de messages spécifiques à chaque langue. (Compaq Tru64 UNIX)
/usr/share/locale/Emplacement des fichiers de messages spécifiques à chaque langue. (GNU/Linux, *BSD)
/usr/sbin/acceptLa commande d'acceptation de travaux.
/usr/sbin/cupsdL'ordonnanceur CUPS.
/usr/sbin/lpadminL'outil d'administration d'imprimante System V.
/usr/sbin/lpcL'outil d'administration d'imprimante Berkeley.
/usr/sbin/lpinfoLes commandes "get-devices" et "get-ppds".
/usr/sbin/lpmoveLa commande "move-jobs".
/usr/sbin/rejectLa commande "reject-jobs".
/usr/share/catman/a_man/ +
/usr/share/catman/u_man/
Pages de manuel (IRIX)
/usr/share/man/Pages de manuel (Compaq Tru64 + UNIX, HP-UX, Solaris)
/usr/man/Pages de manuel (tous les autres systèmes)
/usr/share/cups/data/Emplacement des fichiers de données des filtres.
/usr/share/cups/data/testprint.psFichier de page de test PostScript.
/usr/share/cups/fonts/Emplacement des polices de caractères PostScript pour le RIP PostScript.
/usr/share/cups/model/ +Emplacement des fichiers PPD ("PostScript Printer Description") et des scripts d'interface pouvant être employés pour configurer une file d'impression.
/usr/share/cups/pstoraster/ +D'autres fichiers d'initialisation du RIP PostScript.
/usr/share/cups/pstoraster/Fontmap +Le fichier de conversion de polices (convertit des noms de fichiers en noms de polices)
/usr/share/cups/templates/Emplacement des fichiers "templates" HTML pour l'interface "web".
/usr/share/doc/cups/Documentation et données des pages "web" pour l'ordonnanceur.
/var/log/cups/Emplacement des fichiers de suivi de l'ordonnanceur.
/var/spool/cups/Emplacement des fichiers d'impression en attente de traitement.
+
+

+

E - Résoudre les problèmes courants

+ +

Cette annexe couvre certains des problèmes courants rencontrés par les utilisateurs lors de la première +installation / configuration / utilisation de CUPS.

+

Le support commercial de CUPS est disponible auprès d'Easy Software Products. +Pour plus d'informations, veuillez nous contacter:

+ + +

Mes applications ne voient pas les imprimantes disponibles

+ +

Beaucoup d'applications lisent le contenu du fichier /etc/printcap pour obtenir la liste des imprimantes disponibles.

+ +

La configuration standard de CUPS ne crée pas ce fichier /etc/printcap automatiquement. Pour activer la création +et la mise à jour automatiques de ce fichier, utilisez la directive Printcapdécrite au +Chapitre 6, "Administration du système d'impression".

+ +

CUPS ne reconnaît pas mon nom d'utilisateur et mon mot de passe!

+ +

CUPS vous demandera un nom d'utilisateur UNIX et un mot de passe lorsque vous effectuerez des tâches d'administration +à distance ou au moyen d'un navigateur "web". La configuration standard de CUPS nécessite que vous utilisiez le nom d'utilisateur +root et son mot de passe correspondant pour authentifier la requête.

+ +

Pour des raisons de sécurité, CUPS ne vous autorise pas à authentifier une requête d'administration au moyen d'un compte dépourvu de mot de passe. Si vous n'avez pas de mot de passe pour le compte root, vous ne pourrez pas faire d'administration +à distance ou via un navigateur "web" ! + +

+

Pour désactiver l'authentification par mot de passe vous devez éditer le contenu du fichier +/etc/cups/cupsd.conf et commenter les lignes:

+
    +
    +AuthType Basic
    +AuthClass System
    +
    +
+pour l'emplacement /admin. Redémarrez alors le serveur CUPS comme indiqué dans le +Chapitre 6, "Administration du serveur d'impression". +
+ + +
NOTE: +

Désactiver les vérifications de mot de passe autorisera tout utilisateur local à modifier les imprimantes et les classes, +mais l'administration distante depuis un autre poste ne sera toujours pas autorisée.

+
+
+

Je ne peux pas effectuer de tâches d'administration depuis un poste distant!

+ +

La configuration standard de CUPS limite l'administration au poste local. Pour ouvrir l'accès, éditez le contenu du +fichier /etc/cups/cupsd.conf et commentez les lignes:

+
    +
    +Order deny,allow
    +Deny from all
    +Allow from 127.0.0.1
    +
    +
+pour l'emplacement /admin. Redémarrez alors le serveur CUPS comme indiqué dans le +Chapitre 6, "Administration du serveur d'impression". +
+ + +
NOTE: +

Autoriser l'accès à l'administration pour tous les hôtes présente un risque potentiel de sécurité. Veuillez vous reporter +au Chapitre 6, "Administration du serveur d'impression" pour une description de +ces risques ainsi que des méthodes pour les minimiser.

+
+
+ + +

Je ne peux pas effectuer de tâches d'administration depuis mon navigateur "web"! +

+

Ce problème est généralement dû:

+
    +
  1. au fait de donner le mauvais mot de passe pour le compte root.
  2. +
  3. au fait d'accéder au serveur CUPS en utilisant le nom d'hôte ou l'adresse IP sans activer l'accès à distance pour les fonctions d'administration. +Cela peut être corrigé en suivant les instructions présentes dans la section + "Je ne peux pas effectuer de tâches d'administration depuis un poste distant!" étudiée précédemment dans cette +annexe.
  4. +
  5. au fait de ne pas avoir de mot de passe pour le compte root. Pour des raisons de sécurité, CUPS n'authentifiera pas les comptes utilisateur dépourvus de mot de passe.
  6. +
  7. au fait de s'authentifier au moyen d'un compte distinct de root mais qui n'est pas membre du groupe system.
  8. +
  9. au fait de configurer CUPS pour utiliser l'authentification "Digest" et tenter d'y accéder au moyen d'un navigateur +"web" ne prenant pas en charge ce type d'authentification.
  10. +
+

Messages "Connection Refused"

+ +

Dans des circonstances normales, des messages "connection refused" pour une imprimante réseau peuvent être +rencontrés de temps en temps. La plupart des interfaces réseau autorisent une unique connexion à un instant donné (un travail +à la fois) et refuseront l'accès à tous les autres systèmes tant que la première connexion sera active. CUPS retente automatiquement +de se connecter toutes les 30 secondes.

+ +

Si le problème persiste et que vous ne pouvez imprimer aucun travail sur l'imprimantes, vérifiez qu'une autre machine +ne maintient pas une connexion avec l'imprimante, et que vous avez sélectionné le bon port ou le bon nom d'imprimante.

+ +

De même, la plupart des serveurs d'impression externes refuseront les connexions si une imprimante est hors tension +ou hors ligne. Vérifiez que l'imprimante affectée est sous tension et en ligne.

+ +

Message "Write Error"

+ +

Si vous obtenez des messages "write error" sur une file d'impression, l'interface de l'imprimante (généralement +une interface Hewlett Packard JetDirect) a dépassé le délai d'attente maximum et résilié la connexion réseau avec votre poste +de travail.

+ +

L'erreur est causée par le délai d'amorçage qui existe entre l'établissement initial de la connexion à l'imprimante et +l'envoi effectif des données de la première page imprimée. +

+

+Pour corriger le problème, chagez la valeur du délai d'attente de l'interface et amenez sa valeur à un minimum de 180 secondes soit +3 minutes. Pour changer le délai sur une interface Hewlett Packard JetDirect, tapez:

+
    +
    +telnet adresse-ip ENTER
    +
    +Trying adresse-ip...
    +Connected to adresse-ip.
    +Escape character is `^]'.
    +
    +Please type [Return] two times, to initialize telnet configuration
    +For HELP type "?"
    +> idle-timeout: 180 ENTREE
    +> quit ENTREE
    +
    +
+ + + diff --git a/doc/fr/sum.html b/doc/fr/sum.html new file mode 100644 index 0000000000..e2994230b2 --- /dev/null +++ b/doc/fr/sum.html @@ -0,0 +1,1770 @@ + + + +CUPS - Manuel de l'utilisateur + + + + + + + +

+

CUPS - Manuel de l'utilisateur


+CUPS-SUM-1.1.14
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table des matières

+
+
Préface + +1 - Aperçu du système d'impression + +2 - Utilisation du système d'impression + +3 - Options standards d'imrimante + +4 - Sauvegarder les options et valeurs + implicites des réglages d'imprimante + +A - Licence d'utilisation du logiciel (NdT : en + anglais) + +
+

Préface

+

Ce manuel de l'utilisateur décrit comment utiliser le logiciel CUPS +TM ("Common Unix Printing SystemTM") Version 1.1.14.

+

+
Note du traducteur : + Amies lectrices, amis lecteurs, j'ai fait le choix de ne pas + traduire l'expression anglaise "default" par la version + française habituellent utilisée "par défaut" que l'on doit, + entre autres, à la documentation d'un célèbre système d'exploitation + "ouvert à tous vents". +
+
En effet, l'expression "par défaut" est normalement utilisée en + mathématiques (arrondi "par défaut" ou "par excès", personnellement je + cherche encore mon "imprimante par excès" !) mais elle est abusivement + employée en informatique pour signifier "donnée/comportement qui + s'applique si l'on n'en précise pas explicitement la + valeur/nature/teneur". +
+
Or la langue française possède justement un mot pout exprimer ce + concept : "implicite" (Larousse 1998 : "Qui est contenu dans une + proposition sans être exprimé en termes précis formels; qui est la + conséquence nécessaire."). Dans la mesure du possible, j'utiliserai cet + adjectif sauf dans les cas où son emploi n'est pas suffisamment + explicite (sic !). Je lui préfèrerai alors l'expression "... de + base ..." ou l'adjectif "standard". +
+
Ce choix est totalement personnel et le fait que j'ai fait l'effort + (non négligeable) de traduire ces lignes pour vos yeux délicats suffit + à le justifier! Si, par malheur, ma prose vous est insupportable, je ne + vous empêche aucunement de vous reporter à la version originale où vous + retrouverez "default" entouré de tout le reste... en anglais, bien sûr. + Enfin, si vous avez une meilleure traduction, je suis preneur ! +
+
Malgré les très nombreuses relectures et corrections, certaines + fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma + vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les + signaler afin de contribuer à l'amélioration constante de la qualité du + présent manuel. +
+
Bonne lecture !
+
+

Aperçu du système

+

CUPS fournit une couche d'impression portable pour les systèmes + d'exploitation de type UNIX®. Il a été développé par + Easy Software Products pour promouvoir une solution d'impression + standard pour tous les vendeurs et utilisateurs d'UNIX. CUPS fournit + des interfaces en ligne de commande de type System V et Berkeley.

+

CUPS utilise le protocol IPP (Internet Printing Protocol) comme base + de l'administration des travaux et files d'impression. Les protocoles + LPD ("Line Printer Daemon"), SMB ("Server Message Block"), et AppSocket + (JetDirect) sont également pris en charge avec des fontionnalités + réduites. CUPS ajoute l'exploration réseau des imprimantes ("network + printer browsing") et des options d'impression basées sur PPD + ("PostScript Printer Definition") pour prendre en charge l'impression + "dans le monde réel" sous UNIX.

+

CUPS inclut également une version adaptée de GNU/Ghostscript + (actuellement basée sur la version 5.50) et un module de rendu (RIP - + Raster Image Processor) pour fichier image qui sont utilisés pour + prendre en charge les imprimantes non-PostScript. Des pilotes d'exemple + (incluant ces filtres) pour imprimantes HP et EPSON sont également + inclus.

+ + +

Aperçu du document

+

Le présent manuel de l'utilisateur s'articule autour sections + suivantes:

+ +

Conventions d'écritures

+ Diverses conventions de polices de caractères et de syntaxe sont + utilisées dans ce guide. Des exemples et leur signification sont donnés + ci-dessous: +
+ + + + + + + + + + + + +
Exemple   Description
 
lpstat +
lpstat(1)
    Les noms des commandes; + La première référence faite à une commande ou une fonction dans un + chapitre est suivie par un numéro de section de page de manuel.
 
/var +
/usr/share/cups/data/testprint.ps
    + Noms de fichiers et de répertoires.
 
Request ID is Printer-123 +    Affichage écran.
 
lp -d imprimante nom_fichier ENTREE +    Frappe littérale de l'utilisateur; les touches + spéciales telles que ENTREE sont représentées en lettres + capitales.
 
12.3    Les nombres dans le texte + sont écrits avec un point symbolisant le séparateur décimal.
+
+ + +

Abréviations

+ Les abréviations suivantes sont utilisées au cours de ce manuel: +
    +
    +
    ko
    +
    Kilo-octets, ou 1024 octets +
     
    +
    Mo
    +
    Méga-octets, ou 1048576 octets +
     
    +
    Go
    +
    Giga-octets, ou 1073741824 octets +
     
    +
    +
+

Autres références

+
    +
    +
    CUPS - Manuel de l'administrateur
    +
    Un guide d'administration du logiciel CUPS. +
     
    +
    CUPS - Manuel du programmeur (NdT : en anglais)
    +
    Un guide du programmeur pour créer des programmes qui s'interfacent + avec et/ou étendent le logiciels CUPS. +
     
    +
    +
+

1 - Aperçu du système d'impression +

+

Ce chapitre fournit un aperçu du fonctionnement de CUPS.

+

Le problème d'impression

+

Depuis des années le problème d'impression a empoisonné le + monde UNIX. Contrairement à Microsoft® Windows® ou Mac OS, UNIX n'a pas + d'interface standard ou de système en place pour prendre en charge les + imprimantes. Parmi les solutions actuellement disponibles, les systèmes + Berkeley et System V sont prédominants.

+

Ces systèmes d'impressions prennent en charge les imprimantes de + type matriciel texte ou les imprimantes PostScript (texte et + graphique), et avec quelques ajustements il peuvent prendre en charge + un grand nombre d'imprimantes et de formats de fichiers. Cependant, + puisque chaque version de système d'exploitation UNIX utilise un + système d'impression différent de celui de son voisin, il est + extrêmement difficile de développer des pilotes d'imprimantes pour une + vaste gamme d'imprimantes et de systèmes d'exploitation. Ceci, combiné + au faible nombre de clients pour chaque variante d'UNIX, a poussé les + fabricants d'imprimantes à abandonner la prise en charge globale de + tous les UNIX.

+

CUPS est conçu pour éliminer le problème d'impression. Un + système d'impression commun peut être utilisé par toutes les variantes + d'UNIX pour prendre en charge les capacités d'impression dont les + utilisateurs ont besoin. Les fabricants d'imprimantes peuvent utiliser + l'interface modulaire des filtres pour développer un unique pilote qui + prend en charge une large gamme de formats de fichiers et ce, sans + presque aucun effort. Etant donné que CUPS fournit une interface + compatible avec les commandes Berkeley et System V, les utilisateurs + (et les applications) peuvent tirer bénéfice de cette nouvelle + technologie sans avoir à faire de changements.

+

La technologie

+

CUPS est basé sur un standard émergeant d'Internet appelé IPP + (Internet Printing Protocol). IPP a été adopté par des douzaines de + fabricants d'imprimantes et de serveurs d'impression et est pris en + charge par Microsoft Windows 2000.

+

IPP définit un protocole standard pour imprimer ainsi qu'administrer + les travaux d'impression et les options des imprimantes telles que la + taille du support d'impression, la résolution, etc. Comme tout + protocole de la pile TCP/IP, IPP peut être utilisé localement ou à + travers Internet pour atteindre des imprimantes éloignées de centaines + ou de milliers de kilomètres. Contrairement à d'autres protocoles de la + pile TCP/IP, IPP prend en charge le contrôle d'accès, + l'authentification et l'encryptage, ce qui fait de lui une solution + d'impression bien plus efficace et sécurisée que ses ancêtres.

+

IPP est une surcouche ajoutée au-dessus du protocole HTTP (HyperText + Transport Protocol) qui est à la base des serveurs "web" sur + l'Internet. Ceci permet aux utilisateurs de lire la documentation, + vérifier les informations sur l'état des imprimantes ou du serveur, + administrer les imprimantes, les classes d'imprimantes et les travaux + d'impression en utilisant leur navigateur "web".

+

CUPS fournit un système d'impression complet basé sur IPP/1.1 + prenant en charge l'authentification "Basic", "Digest" et par + certificats locaux ainsi qu'un contrôle d'accès basé sur l'utilisateur, + le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une + future version de CUPS.

+

Travaux d'impression

+

Tout fichier ou groupe de fichiers soumis à l'impression est appelé + un travail d'impression. Les travaux d'impression sont + identifiés par un nombre unique en commençant à 1 et sont affectés à + une destination particulière, généralement une imprimante. Les travaux + d'impression peuvent également inclure des options associées telles que + la taille du support d'impression, le nombre de copies et la priorité + dans la file d'impression.

+

Classes d'imprimantes

+

CUPS prend en charge des collections d'imprimantes connues sous le + nom de classes. Les travaux d'impression transmis à une classe + d'imprimantes sont envoyés à la première imprimante disponible dans la + classe.

+

Filtres

+

Les filtres permettent à un utilisateur ou une application d'imprimer + de nombreux types de documents sans effort supplémentaire. Les travaux + d'impressions envoyés au serveur CUPS sont filtrés avant d'être envoyés + à l'imprimante. Certains filtres convertissent les fichiers de travaux + d'impression dans différents formats que l'imprimante peut comprendre. + D'autres ne font que des sélections de page et des tris.

+

CUPS fournit des filtres pour imprimer de nombreux types de fichiers + image, des fichier HP-GL/2, fichiers PDF et texte. CUPS fournit + également des filtres PostScript et RIP (Raster Image Processor) qui + convertissent les fichiers PostScript ou image en format "bitmap" qui + peut être envoyé à une imprimante de type "matriciel" (NdT : il s'agit + ici, des imprimantes dont l'impression est générée au moyen d'une + grille de points comme l'étaient les vénérables imprimantes à aiguilles + de notre enfance, mais pas seulement elles puisque les imprimantes à + jet d'encre actuelles sont également de type matriciel... par + opposition aux imprimantes laser dont la méthode de génération + d'impression est différente.)

+

Programmes d'arrière-plan (Backends)

+

Les programmes d'arrière-plan effectuent le travail le plus important + : ils envoient les données d'impression à l'imprimante.

+

CUPS fournit des programmes d'arrière-plan pour imprimer via des + ports de type parallèle, série, USB et à travers un réseau au moyen des + protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des + programmes d'arrière-plan additionnels sont disponibles sous forme de + paquetage de service réseau comme le programme d'arrière_plan SMB + inclus dans le célèbre logiciel SAMBA.

+

Les programmes d'arrière-plan sont également utilisés pour déterminer + les périphériques disponibles. Au démarrage, chaque programme + d'arrière-plan est interrogé afin de déterminer la liste des + périphériques qu'il prend en charge, ainsi que toute information + disponible. Cela permet au programme d'arrière-plan de gestion du port + parallère d'indiquer à CUPS qu'une imprimante EPSON Stylus Color 600 + est branchée sur le port parallèle 1, par exemple.

+

Pilotes d'imprimantes

+

Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs + filtres spécifiques à une imprimante. CUPS inclut des pilotes + d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet + Hewlett-Packard et les imprimantes EPSON jet d'encre couleur Stylus + Color, Stylus Photo et les modèles 9 et 24 aiguilles matricielles. Bien + que ces pilotes ne produisent pas des impressions de qualité optimale + pour les différents modèles d'imprimantes, ils fournissent une + impression de base et démontrent comment vous pouvez écrire vos propres + pilotes d'imprimantes et les incorporer dans CUPS.

+

Réseau

+

Les imprimantes et classes d'imprimantes sur le système local sont + automatiquement partagées avec les autres systèmes sur le réseau. Cela + vous permet de configurer un système hôte pour tous les autres. Les + utilisateurs pourront sélectionner une imprimante locale par son nom ou + une imprimante à distance en utilisant la syntaxe + "nom_imprimante@serveur".

+

CUPS fournit également des classes d'imprimantes implicites + (NdT : le terme "implicite" est ici la traduction litérale du même mot + anglais "implicit" et non celle de l'expression "default". cf. ma + remarque dans la préface du présent manuel. De toute façon, CUPS ne + prévoit pas de "default class" c'est-à-dire de "classe de base", donc + aucune ambiguïté possible ici.), qui sont des collections d'imprimantes + ou de classes d'imprimantes qui portent le même nom. Cela vous permet + de configurer de multiples serveurs pointant vers la même imprimante + réseau physique, par exemple, de sorte que vous ne dépendez pas d'un + seul serveur pour pouvoir imprimer. Etant donné que cette méthode vous + permet de travailler avec des classes d'imprimantes, vous pouvez + configurer de multiples serveurs et imprimantes sans jamais vous + soucier d'un simple point en panne tant que tous les autres serveurs ne + tombent pas en panne en même temps.

+

2 - Utilisation du système + d'impression

+

Ce chapitre expose comment soumettre, lister et annuler les travaux + d'impression sur différentes imprimantes.

+

Soumission de travaux à l'impression

+

CUPS fournit les deux commandes d'impression System V (lp(1) +) et Berkeley ( lpr(1)). Tapez la commande suivante pour + imprimer un fichier sur l'imprimante implicite du système:

+
    +
    +lp nom_fichier ENTREE
    +
    +
+

ou:

+
    +
    +lpr nom_fichier ENTREE
    +
    +
+

CUPS sait directement interpréter différents types de fichier, y + compris les fichiers PostScript et image. Cela vous permet d'imprimer + depuis vos applications ou depuis la ligne de commande, selon votre + préférence!

+

Choix d'une imprimante

+

Beaucoup de systèmes disposeront de plusieurs imprimantes à offrir à + l'utilisateur. Ces imprimantes peuvent être reliées au système local + par un port parallèle, série ou USB, ou accessibles à travers le + réseau.

+

Utilisez la commande lpstat(1) pour voir une liste des + imprimantes disponibles:

+
    +
    +lpstat -p -d ENTREE
    +
    +
+

L'option -p indique que vous voulez voir la liste des + imprimantes et l'option -d provoque l'affichage de + l'imprimante ou classe d'imprimantes standard (implicite) du système.

+

Utilisez l'option -d avec la comamnde lp + pour imprimer vers une imprimante spécifique:

+
    +
    +lp -d imprimante nom_fichier ENTREE
    +
    +
+

ou l'option -P avec la commande lpr:

+
    +
    +lpr -P imprimante nom_fichier ENTREE
    +
    +
+

Réglage des options d'imprimante

+

Pour de nombreux types de fichiers, les options d'imprimante + implicites devraient satisfaire vos besoins. Cependant, il peut arriver + que vous ayez besoin de changer les options pour un fichier spécifique + que vous imprimez.

+

Les commandes lp et lpr vous permettent de + passer des options d'imprimante en utilisant l'option -o:

+
    +
    +lp -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
    +lpr -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
    +
    +
+

Les options d'imprimante disponibles varient en fonction de + l'imprimante. Les options standards sont décrites dans le + Chapitre 3, "Options standards d'imprimante".

+

Impression de plusieurs copies

+

Les deux commandes lp et lpr possèdent des + options pour l'impression de plus d'une copie d'un fichier:

+
    +
    +lp -n nombre_copies nom_fichier ENTREE
    +lpr -#nombre_copies nom_fichier ENTREE
    +
    +
+

Les copies ne sont généralement pas assemblées. Utilisez + l'option -o Collate=True pour obtenir des copies + assemblées:

+
    +
    +lp -n nombre_copies -o Collate=True nom_fichier ENTREE
    +lpr -#nombre_copies -o Collate=True nom_fichier ENTREE
    +
    +
+ + +

Vérification de l'état d'une imprimante depuis la + ligne de commande

+

La commande lpstat peut être utilisée pour vérifier les + travaux que vous avez soumis à l'impression:

+
    +
    +lpstat ENTREE
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +
    +
+

Les travaux sont listés dans l'ordre dans lequel ils seront imprimés. + Utilisez l'option -p pour voir les travaux actifs sur + l'imprimante:

+
    +
    +lpstat -p ENTREE
    +printer DeskJet now printing DeskJet-1.
    +
    +
+ + +

Utilisez les options -o et -p ensemble pout + voir les à la fois les travaux et les imprimantes:

+
    +
    +lpstat -o -p ENTREE
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +printer DeskJet now printing DeskJet-1.
    +
    +
+

Vérification de l'état d'un imprimante depuis + l'interface "web"

+

CUPS utilise le protocole IPP (Internet Printing Protocol), mais + c'est également un serveur "web" complètement fonctionnel. Pour + utiliser votre navigateur "web" pour surveiller les imprimantes sur + votre système, ouvrez l'adresse:

+ +

A partir de là, vous pouvez voir l'état des classes, travaux, et + imprimantes par un simple clic de bouton!

+

Suppression d'un travail d'impression

+

Les commandes cancel(1) et lprm(1) + suppriment un travail d'impression:

+
    +
    +cancel numéro_travail ENTREE
    +lprm numéro_travail ENTREE
    +
    +
+

Le numéro_travail est le nombre qui vous est fourni par + les commandes lp ou lpstat.

+

3 - Options standards + d'imrimante

+

Ce chapitre décrit les options standards d'imprimante qui sont + disponibles lors de l'impression au moyen des commandes lp + et lpr.

+

Options générales

+

Les options suivantes s'appliquent lors de l'impression de tous les + types de fichiers.

+

Réglage de l'orientation

+

L'option -o landscape tournera la sortie imprimée de 90° + pour imprimer en mode paysage:

+
    +
    +lp -o landscape nom_fichier ENTREE
    +lpr -o landscape nom_fichier ENTREE
    +
    +
+ + +

Choix du type, de la taille et de la source du + support d'impression

+

L'option -o media=xyz définit la taille, le type et la + source du support d'impression:

+
    +
    +lp -o media=Letter nom_fichier ENTREE
    +lp -o media=Letter,MultiPurpose nom_fichier ENTREE
    +lpr -o media=Letter,Transparency nom_fichier ENTREE
    +lpr -o media=Letter,MultiPurpose,Transparency nom_fichier ENTREE
    +
    +
+ + +

Les tailles, types et sources de support d'impression disponibles + dépendent de l'imprimante mais la plupart des matériels prennent en + charge les options suivantes (les plus courantes):

+
    +
  • Letter - US Letter (8.5x11 pouces, ou 216x279mm)
  • +
  • Legal - US Legal (8.5x14 pouces, ou 216x356mm)
  • +
  • A4 - ISO A4 (8.27x11.69 pouces, ou 210x297mm)
  • +
  • COM10 - US #10 Enveloppe (9.5x4.125 pouces, ou + 241x105mm)
  • +
  • DL - ISO DL Enveloppe (8.66x4.33 pouces, ou 220x110mm)
  • +
  • Transparency - Type de support transparent ou source de + support transparent
  • +
  • Upper - Bac d'alimentation supérieur
  • +
  • Lower - Bac d'alimentation inférieur
  • +
  • MultiPurpose - Bac papier multi-usage
  • +
  • LargeCapacity - Bac d'alimentation de grande capacité
  • +
+

Les options réellement prises en charge sont définies dans le fichier + PPD de l'imprimante au moyen des options PageSize, +InputSlot, et MediaType.

+

Impression en recto/verso

+

Les options -o sides=two-sided-short-edge et -o + sides=two-sided-long-edge activeront l'impression recto/verso si + l'imprimante la prend en charge. L'option -o + sides=two-sided-short-edge convient pour les pages orientées en + paysage, tandis que l'option -o sides=two-sided-long-edge + convient pour celles orientées en portrait:

+
    +
    +lp -o sides=two-sided-short-edge nom_fichier ENTREE
    +lp -o sides=two-sided-long-edge nom_fichier ENTREE
    +lpr -o sides=two-sided-long-edge nom_fichier ENTREE
    +
    +
+

La valeur implicite est d'imprimer en mode simple face + ("single-sided"):

+
    +
    +lp -o sides=one-sided nom_fichier ENTREE
    +lpr -o sides=one-sided nom_fichier ENTREE
    +
    +
+

Options de pages de garde

+

Les options suivantes s'appliquent à l'impression de tous les types + de fichiers.

+

Sélection des pages de garde

+

L'option -o jobsheets=start,end définit les pages de + garde pour un travail d'impression:

+
    +
    +lp -o job-sheets=none nom_fichier ENTREE
    +lp -o job-sheets=standard nom_fichier ENTREE
    +lpr -o job-sheets=classified,classified nom_fichier ENTREE
    +
    +
+

Si seulement un fichier de page de garde est indiqué il sera imprimé + avant le travail d'impression. Si un second fichier de page de garde + est indiqué, il sera imprimé après le travail d'impression..

+

Les pages de garde disponibles dépendent de la configuration du + système local; CUPS inclut les fichiers de pages de garde suivants:

+
    +
  • none - Ne pas produire de page de garde.
  • +
  • classified - Une page de garde avec une inscription + "classified" en haut et en bas de page.
  • +
  • confidential - Une page de garde avec une inscription + "confidential" en haut et en bas de page.
  • +
  • secret - Une page de garde avec une inscription + "secret" en haut et en bas de page.
  • +
  • standard - Une page de garde sans inscription en haut + et en bas de page.
  • +
  • topsecret - Une page de garde avec une inscription + "top-secret" en haut et en bas de page.
  • +
  • unclassified - Une page de garde avec une inscription + "unclassified" en haut et en bas de page.
  • +
+

Options de document

+

Les options suivantes s'appliquent à l'impression de tous les types + de fichiers.

+

Sélection d'une série de pages

+

L'option -o page-ranges=pages sélectionne une série de + pages à imprimer:

+
    +
    +lp -o page-ranges=1 nom_fichier ENTREE
    +lp -o page-ranges=1-4 nom_fichier ENTREE
    +lp -o page-ranges=1-4,7,9-12 nom_fichier ENTREE
    +lpr -o page-ranges=1-4,7,9-12 nom_fichier ENTREE
    +
    +
+

Comme indiqué ci-dessus, la valeur pages peut être une + page unique, un intervalle de numéros de pages ou une collections de + numéros de pages et d'intervalles séparés par des virgules. Les pages + seront imprimées dans l'ordre croissant de leurs numéros, sans tenir + compte de l'ordre dans lequel les valeurs ont été tapées dans l'option +page-ranges.

+

Le comportement implicite est d'imprimer toutes les pages.

+

Sélection des pages paires et impaires

+

Utilisez l'option -o page-set=set pour sélectionner les + pages paires ou impaires:

+
    +
    +lp -o page-set=odd nom_fichier ENTREE
    +lp -o page-set=even nom_fichier ENTREE
    +lpr -o page-set=even nom_fichier ENTREE
    +
    +
+

Le comportement implicite est d'imprimer toutes les pages.

+

Impression de plusieurs pages par face du support + ("N-Up Printing")

+

L'option -o number-up=value sélectionne l'impression de + plusieurs pages par face du support. Cela permet d'imprimer 1, 2 ou 4 + pages du document d'origine sur une seule page physique en sortie:

+
    +
    +lp -o number-up=1 nom_fichier ENTREE
    +lp -o number-up=2 nom_fichier ENTREE
    +lp -o number-up=4 nom_fichier ENTREE
    +lpr -o number-up=4 nom_fichier ENTREE
    +
    +
+

La valeur implicite est 1.

+

Réglage de la luminosité

+

Vous pouvez contrôler la luminosité globale de la sortie imprimée en + utilisant l'option -o brightness=percent:

+
    +
    +lp -o brightness=120 nom_fichier ENTREE
    +lpr -o brightness=120 nom_fichier ENTREE
    +
    +
+

Les valeurs supérieures à 100 éclaircissent l'impression, tandis que + les valeurs inférieures à 100 l'assombrissent.

+

Réglage de la correction Gamma

+

Vous pouvez contrôler la correction gamma goblale de la sortie + imprimée en utilsiant l'option -o gamma=value:

+
    +
    +lp -o gamma=1700 nom_fichier ENTREE
    +lpr -o gamma=1700 nom_fichier ENTREE
    +
    +
+

Les valeurs supérieures à 1000 éclaircissent l'impression, tandis que + les valeurs inférieures à 1000 l'assombrissent. La valeur implicite est + 1000.

+

Options de texte

+

Les options suivantes s'appliquent à l'impression de fichier texte.

+

Réglage du nombre de caractères par pouce

+

L'option -o cpi=value définit le nombre de caractères + par pouce (NdT : 1 pouce = 2,54 cm):

+
    +
    +lp -o cpi=10 nom_fichier ENTREE
    +lp -o cpi=12 nom_fichier ENTREE
    +lpr -o cpi=17 nom_fichier ENTREE
    +
    +
+

Le nombre implicite de caractères par pouce est 10.

+

Réglage du nombre de lignes par pouce

+

L'option -o lpi=value définit le nombre de lignes par + pouce:

+
    +
    +lp -o lpi=6 nom_fichier ENTREE
    +lpr -o lpi=8 nom_fichier ENTREE
    +
    +
+

Le nombre implicite de lignes par pouces est 6.

+

Réglage du nombre de colonnes

+

L'option -o columns=value définit le nombre de colonnes + de texte:

+
    +
    +lp -o columns=2 nom_fichier ENTREE
    +lpr -o columns=3 nom_fichier ENTREE
    +
    +
+

Le nombre de colonnes implicite est 1.

+

Réglage des marges de la page

+

Normalement, les marges de la page sont fixées par les limites + physiques de l'imprimante. Utilisez les options -o + page-left=value, -o page-right=value , -o + page-top=value, et -o page-bottom=value pour + ajuster les marges:

+
    +
    +lp -o page-left=valeur nom_fichier ENTREE
    +lp -o page-right=valeur nom_fichier ENTREE
    +lp -o page-top=valeur nom_fichier ENTREE
    +lp -o page-bottom=valeur nom_fichier ENTREE
    +lpr -o page-bottom=valeur nom_fichier ENTREE
    +
    +
+

L'argument valeur est la marge en points; 1 point = + 1/72ème de pouce = 0.35mm.

+

Impression améliorée

+

L'option -o prettyprint ajoute un en-tête en haut de + chaque page. Celui-ci comporte le numéro de page, le titre du travail + d'impression (habituellement le nom du fichier), et la date. Les mots + clefs C, C++ et les lignes de commentaires sont également représentées + en italique:

+
    +
    +lp -o prettyprint nom_fichier ENTREE
    +lpr -o prettyprint nom_fichier ENTREE
    +
    +
+

Options d'image

+

Les options suivantes s'appliquent lors de l'impression de fichiers + image.

+

Positionnement de l'image

+

L'option -o position=name indique la position de l'image + dans la page:

+
    +
  • center - Centre l'image dans la page (valeur implicite)
  • +
  • top - Imprime l'image calée en haut de la page et + centrée en largeur
  • +
  • left - Imprime l'image calée à gauche de la page et + centrée en hauteur
  • +
  • right - Imprime l'image calée à droite de la page et + centrée en hauteur
  • +
  • top-left - Imprime l'image calée dans le coin supérieur + gauche
  • +
  • top-right - Imprime l'image calée dans le coin + supérieur droit
  • +
  • bottom - Imprime l'image calée en bas de la page et + centrée en largeur
  • +
  • bottom-left - Imprime l'image calée dans le coin + inférieur gauche
  • +
  • bottom-right - Imprime l'image calée dans le coin + inférieur droit
  • +
+

Mise à l'échelle de l'image

+

Les options -o scaling=percent, -o ppi=value +, et -o natural-scaling=percent changent la taille de + l'image imprimée:

+
    +
    +lp -o scaling=percent nom_fichier ENTREE
    +lp -o ppi=value nom_fichier ENTREE
    +lpr -o natural-scaling=percent nom_fichier ENTREE
    +
    +
+

La valeur scaling=percent est un nombre compris entre 1 + et 800 indiquant la taille par rapport celle de la page (pas celle + de l'image). Un valeur de 100% va adapter l'image à la taille + maximale que permet la page (en fonction des contraintes imposées par + le rapport hauteur/largeur de l'image). Une valeur de 200% imprimera + l'image répartie sur 4 pages.

+

La valeur ppi=value est un nombre compris entre 1 et + 1200 indiquant la résolution de l'image en pixels par pouce. Une image + qui mesure 3000x2400 pixels s'imprimera sur le papier en 10x8 pouces à + une résolution de 300 pixels par pouce (ppp ou, en anglais, dpi). Si la + résolution indiquée donne une image plus grande que la page, plusieurs + pages sont imprimées pour satisfaire la requête.

+

La valeur natural-scaling=percent est un nombre compris + entre 1 et 800 indiquant la taille d'impression de l'image relativement + à sa taille d'origine. Une valeur de 100% imprimera l'image dans sa + taille normale, tandis qu'une valeur de 50% donnera une taille moitié + moins grande. Si la valeur indiquée donne une image plus grande que la + page, plusieurs pages sont imprimées pour satisfaire la requête.

+

Ajustement de la teinte ("Hue", "Tint") de l'image +

+

La valeur -o hue=value ajustera la teinte ("hue") de + l'image imprimée, comme le réglage de teinte de votre télévision:

+
    +
    +lp -o hue=value nom_fichier ENTREE
    +lpr -o hue=value nom_fichier ENTREE
    +
    +
+ + +

L'argument value est un nombre compris entre -360 et 360 + représentant une rotation de teinte. Le tableau suivant, résume les + changements que vous verrez avec différentes couleurs: +

+ + + + + + + + +
Originalhue=-45hue=45
RougePourpreJaune-orange
VertJaune-vertBleu-vert
JauneOrangeVert-Jaune
BleuBleu cielPourpre
MagentaIndigoRouge cramoisi
CyanBleu-vertBlue marine clair
+
+

+

La valeur implicite de ce paramètre est 0.

+

Ajustement de la saturation de couleur de l'image +

+

L'option -o saturation=percent ajuste la saturation des + couleurs de l'image, comme le bouton "couleur" de votre télévision:

+
    +
    +lp -o saturation=percent nom_fichier ENTREE
    +lpr -o saturation=percent nom_fichier ENTREE
    +
    +
+

L'argument percent indique la saturation de couleur de 0 + à 200. Une saturation de 0 produit une image en noir et blanc, tandis + qu'une valeur de 200 rend les couleurs extrêmement intenses.

+

La saturation implicite est de 100. + +

+

Options HP-GL/2

+

Les options suivantes s'appliquent aux fichiers HP-GL/2.

+

Impression en noir

+

L'option -o blackplot indique que tous les "stylos" + doivent écrire en noir:

+
    +
    +lp -o blackplot nom_fichier ENTREE
    +lpr -o blackplot nom_fichier ENTREE
    +
    +
+

La valeur implicite est d'utiliser les couleurs définies dans le + fichier ou les couleurs standards de "stylos" définies dans le manuel + de référence HP-GL/2.

+

Ajuster le tracé à la page

+

L'option -o fitplot indique que le tracé doit être mis à + l'échelle pour tenir sur la page:

+
    +
    +lp -o fitplot nom_fichier ENTREE
    +lpr -o fitplot nom_fichier ENTREE
    +
    +
+

Le comportement implicite est d'utiliser les distances absolues + définies dans le fichier. +

+ + +
NOTE: +

Cette fonctionnalité dépend d'une définition précise de la commande + de taille de tracé (PS) dans le fichier HP-GL/2. Si aucune + taille de tracé n'est donnée dans le fichier, alors le filtre HP-GL/2 + considère que le tracé a une taille ANSI E.

+
+
+

+

Réglage de la largeur implicite de tracé

+

L'option -o penwidth=valeur indique la valeur implicite + de largeur de tracé pour les fichiers HP-GL/2:

+
    +
    +lp -o penwidth=valeur nom_fichier ENTREE
    +lpr -o penwidth=valeur nom_fichier ENTREE
    +
    +
+

La valeur de largeur de tracé définit la largeur de + "stylo" en micromètres. La valeur implicite de 1000 produit des lignes + de 1 millimètre de large. Indiquer une largeur de "stylo" de 0 produit + un tracé d'un pixel de large. +

+ + +
NOTE: +

Cette option est ignorée si les largeurs de tracé sont définies dans + le fichier.

+
+
+

+

Sortie brute ou non filtrée

+

L'option -o raw vous permet d'envoyer directement des + fichiers à l'imprimante sans faire de filtrage. Cela est parfois + nécessaire lors que vous imprimez depuis des applications qui + fournissent leur propres "pilotes d'imprimantes" pour votre imprimante:

+
    +
    +lp -o raw nom_fichier ENTREE
    +lpr -o raw nom_fichier ENTREE
    +
    +
+

L'option -l peut également être utilisée avec la + commande lpr pour envoyer directement des fichiers à une + imprimante:

+
    +
    +lpr -l nom_fichier ENTREE
    +
    +
+

4 - Sauvegarder les options + et valeurs implicites des réglages d'imprimante

+

Ce chapitre décrit comment sauvegarder les options pour votre + imprimante et définir votre propre imprimante implicite.

+

Options d'imprimante

+

Chaque imprimante prend en charge un grand nombre d'options, que vous + avez découvertes dans le Chapitre 3, + "Options standards d'imprimante". Plutôt qu'indiquer ces options à + chaque fois que vous imprimez un fichier, CUPS vous permet de + sauvegarder comme "implicites" les options pour votre imprimante.

+

La commande lpoptions(1) sauvegarde les options de vos + imprimantes. Comme les commandes lp et lpr, + elle accepte les options d'imprimantes en utilisant l'argument -o +:

+
    +
    +lpoptions -o media=A4 -o sides=two-sided-long-edge ENTREE
    +lpoptions -o media=Legal -o scaling=100 ENTREE
    +
    +
+

Une fois sauvegardées, toute commande lp ou lpr + les utilisera lorsque vous imprimerez.

+

Réglage des options pour une imprimante spécifique

+

L'exemple précédent montre comment régler les options pour + l'imprimante implicite. L'option -p imprimante indique que + les options sont pour une autre imprimante:

+
    +
    +lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTREE
    +lpoptions -p deskjet -o media=Legal -o scaling=100 ENTREE
    +
    +
+

Visualisation des réglages implicites actuels

+

La commande lpoptions peut également être utilisée pour + afficher les options actuelles en n'indiquant aucune option sur la + ligne de commande:

+
    +
    +lpoptions ENTREE
    +media=A4 sides=two-sided-long-edge
    +lpoptions -p deskjet ENTREE
    +media=Legal scaling=100
    +
    +
+

Choix de l'imprimante implicite

+

L'administrateur définira généralement une imprimante implicite + valable pour tout le système et qui sera utilisée par tous. Utilisez + l'option -d imprimante pour définir votre propre + imprimante implicite:

+
    +
    +lpoptions -d deskjet ENTREE
    +
    +
+

L'imprimante peut être locale (deskjet) ou à distance ( +deskjet@serveur).

+

Instances d'imprimantes

+

En plus de définir des réglages pour chaque file d'impression, CUPS + prend en charge les instances d'imprimantes qui vous permettent + de définir différents jeux d'options pour chaque imprimante. Vous + indiquez chaque instante en utilisant le caractère "slash" (/ +):

+
    +
    +lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTREE
    +lpoptions -p laserjet/legal -o media=Legal ENTREE
    +
    +
+

Les commandes lp et lpr comprennent + également la notation:

+
    +
    +lp -d laserjet/duplex nom_fichier ENTREE
    +lpr -P laserjet/legal nom_fichier ENTREE
    +
    +
+

Retirer des instances d'imprimantes

+

Utilisez l'option -x imprimante/instance pour retirer + une instance d'imprimante dont vous n'avez plus besoin:

+
    +
    +lpoptions -x laserjet ENTREE
    +lpoptions -x laserjet/duplex ENTREE
    +lpoptions -x laserjet/legal ENTREE
    +
    +
+

L'option -x ne retire que les options implicites pour + cette instance d'imprimante. la file d'impression d'origine demeurera + jusqu'à suppression au moyen de la commande lpadmin(8) par + l'administrateur.

+

A - Licence d'utilisation du + logiciel (NdT : en anglais)

+

Common UNIX Printing System License + Agreement

+

Copyright 1997-2002 by Easy Software Products +
44141 AIRPORT VIEW DR STE 204 +
HOLLYWOOD, MARYLAND 20636-3111 USA +
+
Voice: +1.301.373.9600 +
Email: cups-info@cups.org +
WWW: http://www.cups.org

+

Introduction

+

The Common UNIX Printing SystemTM, ("CUPSTM"), + is provided under the GNU General Public License ("GPL") and GNU + Library General Public License ("LGPL"), Version 2. A copy of these + licenses follow this introduction.

+

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_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.93a.

+

For those not familiar with the GNU GPL, the license basically allows + you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in source or binary form.
  • +
  • Sell verbatim copies of the software for a media fee, or sell + support for the software.
  • +
  • Distribute or sell printer drivers and filters that use CUPS so long + as source code is made available under the GPL.
  • +
+

What this license does not 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.

+

The GNU LGPL relaxes the "link-to" restriction, allowing you to + develop applications that use the CUPS API library under other licenses + and/or conditions as appropriate for your application.

+

Trademarks

+

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.

+

Binary Distribution Rights

+

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.

+

The Common UNIX Printing System provides a "pstoraster" 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:

Miles Jones +
Director of Marketing +
Artifex Software Inc. +
454 Las Gallinas Ave., Suite 108 +
San Rafael, CA 94903 USA +
Voice: +1.415.492.9861 +
Fax: +1.415.492.9862 +
EMail: info@arsoft.com
+

+

The "pdftops" filter is based on the Xpdf 0.93a software. For binary + distribution licensing of this software, please contact:

+ Derek B. Noonburg +
Email: derekn@foolabs.com +
WWW: + http://www.foolabs.com/xpdf/

+

Support

+

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:

+ + + +

GNU GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+
+
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow.

+

GNU GENERAL PUBLIC LICENSE +
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+
    +
  1. 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 "Program", below, + refers to any such program or work, and a "work based on the Program" + 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 "modification".) Each licensee is addressed as "you".
  2. +

    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.

    +
  3. 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.
  4. +

    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.

    +
  5. 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: +
      +
    1. You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change.
    2. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +
  6. +

    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.

    +

    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.

    +

    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.

    +
  7. 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: +
      +
    1. 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,
    2. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +
  8. +

    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.

    +

    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.

    +
  9. 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.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. 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.
  16. +

    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.

    +

    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.

    +

    This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

    +
  17. 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.
  18. +
  19. 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.
  20. +

    Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", 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.

    +
  21. 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.
  22. +
+

NO WARRANTY

+
    +
  1. 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 "AS IS" 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.
  2. +
  3. 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.
  4. +
+

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, while the latter only + works together with the library.

+

Note that it is possible for a library to be covered by the ordinary + General Public License rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+

0. 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 "this License"). Each + licensee is addressed as "you".

+

A "library" 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.

+

The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" 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 "modification".)

+

"Source code" 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.

+

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.

+

1. 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.

+

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.

+

2. 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:

+
    +
  1. The modified work must itself be a software library.
  2. +

    +
  3. You must cause the files modified to carry prominent notices stating + that you changed the files and the date of any change.
  4. +

    +
  5. You must cause the whole of the work to be licensed at no charge to + all third parties under the terms of this License.
  6. +

    +
  7. 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.
  8. +

    (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.)

    +
+

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.

+

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.

+

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.

+

3. 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.

+

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.

+

This option is useful when you wish to copy part of the code of the + Library into a program that is not a library.

+

4. 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.

+

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.

+

5. 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 "work that uses the + Library". Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License.

+

However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. Section + 6 states terms for distribution of such executables.

+

When a "work that uses the Library" 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.

+

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.)

+

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.

+

6. As an exception to the Sections above, you may + also compile or link a "work that uses the Library" 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.

+

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:

+
    +
  1. 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 "work that uses the Library", 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.)
  2. +

    +
  3. 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.
  4. +

    +
  5. 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.
  6. +

    +
  7. Verify that the user has already received a copy of these materials + or that you have already sent this user a copy.
  8. +
+

For an executable, the required form of the "work that uses the + Library" 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.

+

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.

+

7. 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:

+
    +
  1. 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.
  2. +

    +
  3. 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.
  4. +
+

8. 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.

+

9. 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.

+

10. 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.

+

11. 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.

+

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.

+

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.

+

This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

+

12. 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.

+

13. 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.

+

Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and "any + later version", 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.

+

14. 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.

+

NO WARRANTY

+

15. 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 "AS IS" 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.

+

16. 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.

+

END OF TERMS AND CONDITIONS

+ + diff --git a/doc/fr/sum.pdf b/doc/fr/sum.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9a295064122e64164d87f0e14ddf0dec9a82ba3f GIT binary patch literal 100039 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 + + CUPS - Manuel de l'utilisateur + + + + + + +

Préface

+

Ce manuel de l'utilisateur décrit comment utiliser le logiciel CUPSTM ("Common Unix Printing SystemTM") Version 1.1.14.

+ +


Note du traducteur : Amies lectrices, amis lecteurs, j'ai fait le choix de ne pas traduire l'expression anglaise "default" par la +version française +habituellent utilisée "par défaut" que l'on doit, entre autres, à la documentation d'un célèbre système d'exploitation "ouvert à tous vents". +

+En effet, l'expression "par défaut" est normalement utilisée en mathématiques (arrondi "par défaut" ou "par excès", +personnellement je cherche encore mon "imprimante par excès" !) +mais elle est abusivement employée en informatique pour signifier "donnée/comportement qui s'applique si l'on n'en +précise pas explicitement la valeur/nature/teneur". +

+Or la langue française possède justement un mot pout exprimer ce concept +: "implicite" (Larousse 1998 : "Qui est contenu dans une proposition sans être exprimé en termes précis formels; qui est la +conséquence nécessaire."). Dans la mesure du possible, j'utiliserai +cet adjectif sauf dans les cas où son emploi n'est pas suffisamment explicite (sic !). Je lui +préfèrerai alors l'expression "... de base ..." ou l'adjectif "standard". +

+Ce choix est totalement personnel et le fait que j'ai fait l'effort (non négligeable) de traduire ces lignes pour vos yeux délicats suffit à le justifier! Si, par malheur, ma prose vous est insupportable, +je ne vous empêche aucunement de vous reporter à la version originale où vous retrouverez "default" entouré de tout le +reste... en anglais, bien sûr. Enfin, si vous avez une meilleure traduction, je suis preneur ! +

+Malgré les très nombreuses relectures et corrections, certaines fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les signaler afin de contribuer à +l'amélioration constante de la qualité du présent manuel. +

+Bonne lecture ! +

+ +

Aperçu du système

+ +

CUPS fournit une couche d'impression portable pour les systèmes d'exploitation de +type UNIX®. Il a été développé par Easy + Software Products pour promouvoir une solution d'impression standard pour +tous les vendeurs et utilisateurs d'UNIX. CUPS fournit des interfaces en ligne de +commande de type System V et Berkeley. +

+ +

CUPS utilise le protocol IPP (Internet Printing Protocol) comme base de l'administration +des travaux et files d'impression. Les protocoles LPD ("Line Printer Daemon"), SMB +("Server Message Block"), et AppSocket (JetDirect) sont également pris en charge avec +des fontionnalités réduites. CUPS ajoute l'exploration réseau des imprimantes ("network +printer browsing") et des options d'impression basées sur PPD ("PostScript Printer +Definition") pour prendre en charge l'impression "dans le monde réel" sous UNIX. +

+ +

CUPS inclut également une version adaptée de GNU/Ghostscript (actuellement basée +sur la version 5.50) et un module de rendu (RIP - Raster Image Processor) pour fichier image qui sont utilisés pour prendre +en charge les imprimantes non-PostScript. Des pilotes d'exemple (incluant ces filtres) +pour imprimantes HP et EPSON sont également inclus. +

+ + +

Aperçu du document

+

Le présent manuel de l'utilisateur s'articule autour sections suivantes:

+ +

Conventions d'écritures

+ +Diverses conventions de polices de caractères et de syntaxe sont utilisées dans ce guide. +Des exemples et leur signification sont donnés ci-dessous: +
+ + + + + + + + + + + + +
Exemple   Description
 
lpstat +
lpstat(1)
    +Les noms des commandes; La première référence faite à une commande ou une fonction dans un +chapitre est suivie par un numéro de section de page de manuel.
 
/var +
/usr/share/cups/data/testprint.ps
    +Noms de fichiers et de répertoires.
 
Request ID is Printer-123 +   Affichage écran.
 
lp -d imprimante nom_fichier ENTREE +   Frappe littérale de l'utilisateur; les touches spéciales telles que ENTREE +sont représentées en lettres capitales.
 
12.3    +Les nombres dans le texte sont écrits avec un point symbolisant le séparateur décimal.
+
+ +

+

Abréviations

+ Les abréviations suivantes sont utilisées au cours de ce manuel: +
    +
    +
    ko
    +
    Kilo-octets, ou 1024 octets +
     
    +
    Mo
    +
    Méga-octets, ou 1048576 octets +
     
    +
    Go
    +
    Giga-octets, ou 1073741824 octets +
     
    +
    +
+ +

Autres références

+
    +
    +
    CUPS - Manuel de l'administrateur
    +
    Un guide d'administration du logiciel CUPS. +
     
    +
    CUPS - Manuel du programmeur (NdT : en anglais)
    +
    Un guide du programmeur pour créer des programmes qui s'interfacent avec et/ou étendent le logiciels CUPS. +
     
    +
    +
+

1 - Aperçu du système d'impression

+

Ce chapitre fournit un aperçu du fonctionnement de CUPS.

+

Le problème d'impression

+

Depuis des années le problème d'impression a empoisonné le monde UNIX. +Contrairement à Microsoft® Windows® ou Mac OS, UNIX n'a pas d'interface standard ou +de système en place pour prendre en charge les imprimantes. Parmi les solutions actuellement +disponibles, les systèmes Berkeley et System V sont prédominants.

+ +

+ Ces systèmes d'impressions prennent en charge les imprimantes de type matriciel texte ou les + imprimantes PostScript (texte et graphique), et avec quelques ajustements il peuvent prendre en + charge un grand nombre d'imprimantes et de formats de fichiers. Cependant, puisque chaque + version de système d'exploitation UNIX utilise un système d'impression différent de celui + de son voisin, il est extrêmement difficile de développer des pilotes d'imprimantes pour une + vaste gamme d'imprimantes et de systèmes d'exploitation. Ceci, combiné au faible nombre de + clients pour chaque variante d'UNIX, a poussé les fabricants d'imprimantes à abandonner la prise en + charge globale de tous les UNIX. +

+ +

+ CUPS est conçu pour éliminer le problème d'impression. Un système d'impression + commun peut être utilisé par toutes les variantes d'UNIX pour prendre en charge les + capacités d'impression dont les utilisateurs ont besoin. Les fabricants d'imprimantes peuvent + utiliser l'interface modulaire des filtres pour développer un unique pilote qui prend en charge une + large gamme de formats de fichiers et ce, sans presque aucun effort. Etant donné que CUPS fournit + une interface compatible avec les commandes Berkeley et System V, les utilisateurs (et les applications) + peuvent tirer bénéfice de cette nouvelle technologie sans avoir à faire de changements. +

+ +

La technologie

+ +

+ CUPS est basé sur un standard émergeant d'Internet appelé IPP (Internet Printing Protocol). IPP a été adopté + par des douzaines de fabricants d'imprimantes et de serveurs d'impression et est pris en charge par + Microsoft Windows 2000. +

+ +

+ IPP définit un protocole standard pour imprimer ainsi qu'administrer les travaux d'impression et les options + des imprimantes telles que la taille du support d'impression, la résolution, etc. Comme tout protocole de la pile + TCP/IP, IPP peut être utilisé localement ou à travers Internet pour atteindre des imprimantes éloignées de centaines + ou de milliers de kilomètres. Contrairement à d'autres protocoles de la pile TCP/IP, IPP prend en charge le + contrôle d'accès, l'authentification et l'encryptage, ce qui fait de lui une solution d'impression bien plus efficace + et sécurisée que ses ancêtres. +

+ +

+ IPP est une surcouche ajoutée au-dessus du protocole HTTP (HyperText Transport Protocol) qui est à la base + des serveurs "web" sur l'Internet. Ceci permet aux utilisateurs de lire la documentation, vérifier les informations + sur l'état des imprimantes ou du serveur, administrer les imprimantes, les classes d'imprimantes et les travaux + d'impression en utilisant leur navigateur "web". +

+ +

+ CUPS fournit un système d'impression complet basé sur IPP/1.1 prenant en charge l'authentification + "Basic", "Digest" et par certificats locaux ainsi qu'un contrôle d'accès basé sur l'utilisateur, + le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une future version de CUPS. +

+ +

Travaux d'impression

+ +

+ Tout fichier ou groupe de fichiers soumis à l'impression est appelé un travail d'impression. Les travaux + d'impression sont identifiés par un nombre unique en commençant à 1 et sont affectés à une destination particulière, + généralement une imprimante. Les travaux d'impression peuvent également inclure des options associées telles que la + taille du support d'impression, le nombre de copies et la priorité dans la file d'impression. +

+ +

Classes d'imprimantes

+ +

+ CUPS prend en charge des collections d'imprimantes connues sous le nom de classes. Les travaux d'impression + transmis à une classe d'imprimantes sont envoyés à la première imprimante disponible dans la classe. +

+ +

Filtres

+ +

Les filtres permettent à un utilisateur ou une application d'imprimer de nombreux types de documents sans +effort supplémentaire. Les travaux d'impressions envoyés au serveur CUPS sont filtrés avant d'être envoyés à +l'imprimante. Certains filtres convertissent les fichiers de travaux d'impression dans différents formats que +l'imprimante peut comprendre. D'autres ne font que des sélections de page et des tris. +

+ +

CUPS fournit des filtres pour imprimer de nombreux types de fichiers image, des fichier HP-GL/2, +fichiers PDF et texte. CUPS fournit également des filtres PostScript et RIP (Raster Image Processor) qui +convertissent les fichiers PostScript ou image en format "bitmap" qui peut être envoyé à une +imprimante de type "matriciel" (NdT : il s'agit ici, des imprimantes dont l'impression est générée au moyen d'une +grille de points +comme l'étaient les vénérables imprimantes à aiguilles de notre enfance, mais pas seulement elles puisque les +imprimantes à jet +d'encre actuelles sont également de type matriciel... par opposition aux imprimantes laser dont la méthode de génération +d'impression est différente.) +

+ +

Programmes d'arrière-plan (Backends)

+ +

Les programmes d'arrière-plan effectuent le travail le plus important : ils envoient les données +d'impression à l'imprimante. +

+ +

CUPS fournit des programmes d'arrière-plan pour imprimer via des ports de type parallèle, série, USB et à travers un +réseau au moyen des protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des programmes d'arrière-plan +additionnels sont disponibles sous forme de paquetage de service réseau comme le programme d'arrière_plan SMB +inclus dans le célèbre logiciel SAMBA. +

+ +

Les programmes d'arrière-plan sont également utilisés pour déterminer les périphériques +disponibles. Au démarrage, chaque programme d'arrière-plan est interrogé afin de déterminer la liste des +périphériques qu'il prend en charge, ainsi que toute information disponible. Cela permet au programme d'arrière-plan +de gestion du port parallère d'indiquer à CUPS qu'une imprimante EPSON Stylus Color 600 est branchée sur le port +parallèle 1, par exemple. +

+ +

Pilotes d'imprimantes

+ +

Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs filtres spécifiques à une imprimante. CUPS inclut +des pilotes d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet Hewlett-Packard et les imprimantes EPSON jet +d'encre couleur Stylus Color, Stylus Photo et les modèles 9 et 24 aiguilles matricielles. Bien que ces pilotes ne produisent +pas des impressions de qualité optimale pour les différents modèles d'imprimantes, ils fournissent une impression de +base et démontrent comment vous pouvez écrire vos propres pilotes d'imprimantes et les incorporer dans CUPS. +

+ +

Réseau

+ +

Les imprimantes et classes d'imprimantes sur le système local sont automatiquement partagées avec les autres systèmes +sur le réseau. Cela vous permet de configurer un système hôte pour tous les autres. Les utilisateurs pourront sélectionner +une imprimante locale par son nom ou une imprimante à distance en utilisant la syntaxe "nom_imprimante@serveur". +

+ +

CUPS fournit également des classes d'imprimantes implicites (NdT : le terme "implicite" est ici la traduction +litérale du même mot anglais "implicit" et non celle de l'expression "default". cf. ma remarque dans la préface du présent manuel. +De toute façon, CUPS ne prévoit pas de "default class" c'est-à-dire de "classe de base", donc aucune ambiguïté possible +ici.), qui sont des collections d'imprimantes ou +de classes d'imprimantes qui portent le même nom. Cela vous permet de configurer de multiples serveurs pointant vers +la même imprimante réseau physique, par exemple, de sorte que vous ne dépendez pas d'un seul serveur pour pouvoir +imprimer. Etant donné que cette méthode vous permet de travailler avec des classes d'imprimantes, vous pouvez configurer +de multiples serveurs et imprimantes sans jamais vous soucier d'un simple point en panne tant que tous les autres serveurs +ne tombent pas en panne en même temps. +

+ +

2 - Utilisation du système d'impression +

+

Ce chapitre expose comment soumettre, lister et annuler les travaux d'impression sur différentes imprimantes.

+

Soumission de travaux à l'impression

+

CUPS fournit les deux commandes d'impression System V (lp(1)) et Berkeley ( +lpr(1)). Tapez la commande suivante pour imprimer un fichier sur l'imprimante implicite du système:

+
    +
    +lp nom_fichier ENTREE
    +
    +
+

ou:

+
    +
    +lpr nom_fichier ENTREE
    +
    +
+

CUPS sait directement interpréter différents types de fichier, y compris les fichiers PostScript et image. +Cela vous permet d'imprimer depuis vos applications ou depuis la ligne de commande, selon votre préférence!

+ +

Choix d'une imprimante

+ +

Beaucoup de systèmes disposeront de plusieurs imprimantes à offrir à l'utilisateur. Ces imprimantes peuvent être +reliées au système local par un port parallèle, série ou USB, ou accessibles à travers le réseau.

+ +

Utilisez la commande lpstat(1) pour voir une liste des imprimantes disponibles:

+
    +
    +lpstat -p -d ENTREE
    +
    +
+

L'option -p indique que vous voulez voir la liste des imprimantes et l'option -d +provoque l'affichage de l'imprimante ou classe d'imprimantes standard (implicite) du système.

+ +

Utilisez l'option -d avec la comamnde lp pour imprimer vers une imprimante spécifique:

+
    +
    +lp -d imprimante nom_fichier ENTREE
    +
    +
+

ou l'option -P avec la commande lpr:

+
    +
    +lpr -P imprimante nom_fichier ENTREE
    +
    +
+ +

Réglage des options d'imprimante

+ +

Pour de nombreux types de fichiers, les options d'imprimante implicites devraient satisfaire vos besoins. Cependant, +il peut arriver que vous ayez besoin de changer les options pour un fichier spécifique que vous imprimez.

+ + +

Les commandes lp et lpr vous permettent de passer des options d'imprimante en utilisant +l'option -o:

+
    +
    +lp -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
    +lpr -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
    +
    +
+ +

Les options d'imprimante disponibles varient en fonction de l'imprimante. Les options standards sont décrites dans le + Chapitre 3, "Options standards d'imprimante".

+ +

Impression de plusieurs copies

+ +

Les deux commandes lp et lpr possèdent des options pour l'impression de plus d'une copie d'un fichier:

+
    +
    +lp -n nombre_copies nom_fichier ENTREE
    +lpr -#nombre_copies nom_fichier ENTREE
    +
    +
+

Les copies ne sont généralement pas assemblées. Utilisez l'option -o Collate=True pour obtenir des copies assemblées:

+
    +
    +lp -n nombre_copies -o Collate=True nom_fichier ENTREE
    +lpr -#nombre_copies -o Collate=True nom_fichier ENTREE
    +
    +
+ + +

Vérification de l'état d'une imprimante depuis la ligne de commande

+ +

La commande lpstat peut être utilisée pour vérifier les travaux que vous avez soumis à l'impression:

+
    +
    +lpstat ENTREE
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +
    +
+

Les travaux sont listés dans l'ordre dans lequel ils seront imprimés. +Utilisez l'option -p pour voir les travaux actifs sur l'imprimante:

+
    +
    +lpstat -p ENTREE
    +printer DeskJet now printing DeskJet-1.
    +
    +
+ + +

Utilisez les options -o et -p ensemble pout voir les à la fois les travaux et les imprimantes:

+
    +
    +lpstat -o -p ENTREE
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +printer DeskJet now printing DeskJet-1.
    +
    +
+

Vérification de l'état d'un imprimante depuis l'interface "web"

+ +

CUPS utilise le protocole IPP (Internet Printing Protocol), mais c'est également un serveur "web" complètement fonctionnel. +Pour utiliser votre navigateur "web" pour surveiller les imprimantes sur votre système, ouvrez l'adresse:

+ +

A partir de là, vous pouvez voir l'état des classes, travaux, et imprimantes par un simple clic de bouton!

+ +

Suppression d'un travail d'impression

+ +

Les commandes cancel(1) et lprm(1) suppriment un travail d'impression:

+
    +
    +cancel numéro_travail ENTREE
    +lprm numéro_travail ENTREE
    +
    +
+

Le numéro_travail est le nombre qui vous est fourni par les commandes lp ou lpstat.

+ +

3 - Options standards d'imrimante

+ +

Ce chapitre décrit les options standards d'imprimante qui sont disponibles lors de l'impression au moyen des commandes +lp et lpr.

+ +

Options générales

+

Les options suivantes s'appliquent lors de l'impression de tous les types de fichiers.

+ +

Réglage de l'orientation

+ +

L'option -o landscape tournera la sortie imprimée de 90° pour imprimer en mode paysage:

+
    +
    +lp -o landscape nom_fichier ENTREE
    +lpr -o landscape nom_fichier ENTREE
    +
    +
+ + +

Choix du type, de la taille et de la source du support d'impression

+

L'option -o media=xyz définit la taille, le type et la source du support d'impression:

+
    +
    +lp -o media=Letter nom_fichier ENTREE
    +lp -o media=Letter,MultiPurpose nom_fichier ENTREE
    +lpr -o media=Letter,Transparency nom_fichier ENTREE
    +lpr -o media=Letter,MultiPurpose,Transparency nom_fichier ENTREE
    +
    +
+ + +

Les tailles, types et sources de support d'impression disponibles dépendent de l'imprimante mais la plupart des matériels prennent en charge les options suivantes (les plus courantes):

+
    +
  • Letter - US Letter (8.5x11 pouces, ou 216x279mm)
  • +
  • Legal - US Legal (8.5x14 pouces, ou 216x356mm)
  • +
  • A4 - ISO A4 (8.27x11.69 pouces, ou 210x297mm)
  • +
  • COM10 - US #10 Enveloppe (9.5x4.125 pouces, ou 241x105mm)
  • +
  • DL - ISO DL Enveloppe (8.66x4.33 pouces, ou 220x110mm)
  • +
  • Transparency - Type de support transparent ou source de support transparent
  • +
  • Upper - Bac d'alimentation supérieur
  • +
  • Lower - Bac d'alimentation inférieur
  • +
  • MultiPurpose - Bac papier multi-usage
  • +
  • LargeCapacity - Bac d'alimentation de grande capacité
  • +
+

Les options réellement prises en charge sont définies dans le fichier PPD de l'imprimante au moyen des options PageSize, InputSlot, et MediaType.

+ +

Impression en recto/verso

+ +

Les options -o sides=two-sided-short-edge et -o + sides=two-sided-long-edge activeront l'impression recto/verso si l'imprimante la prend en charge. L'option -o + sides=two-sided-short-edge convient pour les pages orientées en paysage, tandis que l'option +-o sides=two-sided-long-edge convient pour celles orientées en portrait:

+
    +
    +lp -o sides=two-sided-short-edge nom_fichier ENTREE
    +lp -o sides=two-sided-long-edge nom_fichier ENTREE
    +lpr -o sides=two-sided-long-edge nom_fichier ENTREE
    +
    +
+

La valeur implicite est d'imprimer en mode simple face ("single-sided"):

+
    +
    +lp -o sides=one-sided nom_fichier ENTREE
    +lpr -o sides=one-sided nom_fichier ENTREE
    +
    +
+

Options de pages de garde

+ +

Les options suivantes s'appliquent à l'impression de tous les types de fichiers.

+ +

Sélection des pages de garde

+ +

L'option -o jobsheets=start,end définit les pages de garde pour un travail d'impression:

+
    +
    +lp -o job-sheets=none nom_fichier ENTREE
    +lp -o job-sheets=standard nom_fichier ENTREE
    +lpr -o job-sheets=classified,classified nom_fichier ENTREE
    +
    +
+

Si seulement un fichier de page de garde est indiqué il sera imprimé avant le travail d'impression. +Si un second fichier de page de garde est indiqué, il sera imprimé après le travail d'impression..

+ +

Les pages de garde disponibles dépendent de la configuration du système local; + CUPS inclut les fichiers de pages de garde suivants:

+
    +
  • none - Ne pas produire de page de garde.
  • +
  • classified - Une page de garde avec une inscription "classified" en haut et en bas de page.
  • +
  • confidential - Une page de garde avec une inscription "confidential" en haut et en bas de page.
  • +
  • secret - Une page de garde avec une inscription "secret" en haut et en bas de page.
  • +
  • standard - Une page de garde sans inscription en haut et en bas de page.
  • +
  • topsecret - Une page de garde avec une inscription "top-secret" en haut et en bas de page.
  • +
  • unclassified - Une page de garde avec une inscription "unclassified" en haut et en bas de page.
  • +
+

Options de document

+ +

Les options suivantes s'appliquent à l'impression de tous les types de fichiers.

+ +

Sélection d'une série de pages

+ +

L'option -o page-ranges=pages sélectionne une série de pages à imprimer:

+
    +
    +lp -o page-ranges=1 nom_fichier ENTREE
    +lp -o page-ranges=1-4 nom_fichier ENTREE
    +lp -o page-ranges=1-4,7,9-12 nom_fichier ENTREE
    +lpr -o page-ranges=1-4,7,9-12 nom_fichier ENTREE
    +
    +
+

Comme indiqué ci-dessus, la valeur pages peut être une page unique, un intervalle de numéros de pages ou une collections de numéros de pages et d'intervalles séparés par des virgules. +Les pages seront imprimées dans l'ordre croissant de leurs numéros, sans tenir compte de l'ordre dans lequel les valeurs +ont été tapées dans l'option page-ranges.

+ +

Le comportement implicite est d'imprimer toutes les pages.

+ +

Sélection des pages paires et impaires

+ +

Utilisez l'option -o page-set=set pour sélectionner les pages paires ou impaires:

+
    +
    +lp -o page-set=odd nom_fichier ENTREE
    +lp -o page-set=even nom_fichier ENTREE
    +lpr -o page-set=even nom_fichier ENTREE
    +
    +
+

Le comportement implicite est d'imprimer toutes les pages.

+ +

Impression de plusieurs pages par face du support ("N-Up Printing")

+ +

L'option -o number-up=value sélectionne l'impression de plusieurs pages par face du support. Cela permet d'imprimer 1, 2 ou 4 pages du document d'origine sur une seule page physique en sortie:

+
    +
    +lp -o number-up=1 nom_fichier ENTREE
    +lp -o number-up=2 nom_fichier ENTREE
    +lp -o number-up=4 nom_fichier ENTREE
    +lpr -o number-up=4 nom_fichier ENTREE
    +
    +
+

La valeur implicite est 1.

+ +

Réglage de la luminosité

+ +

Vous pouvez contrôler la luminosité globale de la sortie imprimée en utilisant l'option +-o brightness=percent:

+
    +
    +lp -o brightness=120 nom_fichier ENTREE
    +lpr -o brightness=120 nom_fichier ENTREE
    +
    +
+

Les valeurs supérieures à 100 éclaircissent l'impression, tandis que les valeurs inférieures à 100 l'assombrissent.

+ +

Réglage de la correction Gamma

+ +

Vous pouvez contrôler la correction gamma goblale de la sortie imprimée en utilsiant l'option +-o gamma=value:

+
    +
    +lp -o gamma=1700 nom_fichier ENTREE
    +lpr -o gamma=1700 nom_fichier ENTREE
    +
    +
+

Les valeurs supérieures à 1000 éclaircissent l'impression, tandis que les valeurs inférieures à 1000 l'assombrissent. +La valeur implicite est 1000.

+ +

Options de texte

+ +

Les options suivantes s'appliquent à l'impression de fichier texte.

+ +

Réglage du nombre de caractères par pouce

+ +

L'option -o cpi=value définit le nombre de caractères par pouce (NdT : 1 pouce = 2,54 cm):

+
    +
    +lp -o cpi=10 nom_fichier ENTREE
    +lp -o cpi=12 nom_fichier ENTREE
    +lpr -o cpi=17 nom_fichier ENTREE
    +
    +
+

Le nombre implicite de caractères par pouce est 10.

+ +

Réglage du nombre de lignes par pouce

+ +

L'option -o lpi=value définit le nombre de lignes par pouce:

+
    +
    +lp -o lpi=6 nom_fichier ENTREE
    +lpr -o lpi=8 nom_fichier ENTREE
    +
    +
+

Le nombre implicite de lignes par pouces est 6.

+ +

Réglage du nombre de colonnes

+ +

L'option -o columns=value définit le nombre de colonnes de texte:

+
    +
    +lp -o columns=2 nom_fichier ENTREE
    +lpr -o columns=3 nom_fichier ENTREE
    +
    +
+

Le nombre de colonnes implicite est 1.

+ +

Réglage des marges de la page

+ +

Normalement, les marges de la page sont fixées par les limites physiques de l'imprimante. +Utilisez les options -o page-left=value, -o page-right=value +, -o page-top=value, et -o page-bottom=value + pour ajuster les marges:

+
    +
    +lp -o page-left=valeur nom_fichier ENTREE
    +lp -o page-right=valeur nom_fichier ENTREE
    +lp -o page-top=valeur nom_fichier ENTREE
    +lp -o page-bottom=valeur nom_fichier ENTREE
    +lpr -o page-bottom=valeur nom_fichier ENTREE
    +
    +
+

L'argument valeur est la marge en points; 1 point = 1/72ème de pouce = 0.35mm.

+ +

Impression améliorée

+ +

L'option -o prettyprint ajoute un en-tête en haut de chaque page. Celui-ci comporte le numéro de page, +le titre du travail d'impression (habituellement le nom du fichier), et la date. Les mots clefs C, C++ et les lignes de commentaires sont également représentées en italique:

+
    +
    +lp -o prettyprint nom_fichier ENTREE
    +lpr -o prettyprint nom_fichier ENTREE
    +
    +
+

Options d'image

+ +

Les options suivantes s'appliquent lors de l'impression de fichiers image.

+ +

Positionnement de l'image

+ +

L'option -o position=name indique la position de l'image dans la page:

+
    +
  • center - Centre l'image dans la page (valeur implicite)
  • +
  • top - Imprime l'image calée en haut de la page et centrée en largeur
  • +
  • left - Imprime l'image calée à gauche de la page et centrée en hauteur
  • +
  • right - Imprime l'image calée à droite de la page et centrée en hauteur
  • +
  • top-left - Imprime l'image calée dans le coin supérieur gauche
  • +
  • top-right - Imprime l'image calée dans le coin supérieur droit
  • +
  • bottom - Imprime l'image calée en bas de la page et centrée en largeur
  • +
  • bottom-left - Imprime l'image calée dans le coin inférieur gauche
  • +
  • bottom-right - Imprime l'image calée dans le coin inférieur droit
  • +
+

Mise à l'échelle de l'image

+

Les options -o scaling=percent, -o ppi=value, et +-o natural-scaling=percent changent la taille de l'image imprimée:

+
    +
    +lp -o scaling=percent nom_fichier ENTREE
    +lp -o ppi=value nom_fichier ENTREE
    +lpr -o natural-scaling=percent nom_fichier ENTREE
    +
    +
+

La valeur scaling=percent est un nombre compris entre 1 et 800 indiquant la taille par rapport celle de la page +(pas celle de l'image). Un valeur de 100% va adapter l'image à la taille maximale que permet la page (en fonction +des contraintes imposées par le rapport hauteur/largeur de l'image). Une valeur de 200% imprimera l'image répartie sur +4 pages.

+ +

La valeur ppi=value est un nombre compris entre 1 et 1200 indiquant la résolution + de l'image en pixels par pouce. Une image qui mesure 3000x2400 pixels s'imprimera sur le papier + en 10x8 pouces à une résolution de 300 pixels par pouce (ppp ou, en anglais, dpi). + Si la résolution indiquée donne une image plus grande que la page, plusieurs pages sont imprimées pour satisfaire la + requête.

+

La valeur natural-scaling=percent est un nombre compris entre 1 et 800 indiquant la taille d'impression +de l'image relativement à sa taille d'origine. Une valeur de 100% imprimera l'image dans sa taille normale, tandis +qu'une valeur de 50% donnera une taille moitié moins grande. Si la valeur indiquée donne une image plus grande que la page, +plusieurs pages sont imprimées pour satisfaire la + requête.

+ +

Ajustement de la teinte ("Hue", "Tint") de l'image

+

La valeur -o hue=value ajustera la teinte ("hue") de l'image imprimée, comme le réglage de teinte de +votre télévision:

+
    +
    +lp -o hue=value nom_fichier ENTREE
    +lpr -o hue=value nom_fichier ENTREE
    +
    +
+ + +

L'argument value est un nombre compris entre -360 et 360 représentant une rotation de teinte. +Le tableau suivant, résume les changements que vous verrez avec différentes couleurs: +

+ + + + + + + + +
Originalhue=-45hue=45
RougePourpreJaune-orange
VertJaune-vertBleu-vert
JauneOrangeVert-Jaune
BleuBleu cielPourpre
MagentaIndigoRouge cramoisi
CyanBleu-vertBlue marine clair
+
+

+

La valeur implicite de ce paramètre est 0.

+ +

Ajustement de la saturation de couleur de l'image

+

L'option -o saturation=percent ajuste la saturation des couleurs de l'image, comme le bouton "couleur" de +votre télévision:

+
    +
    +lp -o saturation=percent nom_fichier ENTREE
    +lpr -o saturation=percent nom_fichier ENTREE
    +
    +
+

L'argument percent indique la saturation de couleur de 0 à 200. Une saturation de 0 produit une +image en noir et blanc, tandis qu'une valeur de 200 rend les couleurs extrêmement intenses.

+

La saturation implicite est de 100. + +

+

Options HP-GL/2

+ +

Les options suivantes s'appliquent aux fichiers HP-GL/2.

+ +

Impression en noir

+

L'option -o blackplot indique que tous les "stylos" doivent écrire en noir:

+
    +
    +lp -o blackplot nom_fichier ENTREE
    +lpr -o blackplot nom_fichier ENTREE
    +
    +
+

La valeur implicite est d'utiliser les couleurs définies dans le fichier ou les couleurs standards de "stylos" +définies dans le manuel de référence HP-GL/2.

+ +

Ajuster le tracé à la page

+ +

L'option -o fitplot indique que le tracé doit être mis à l'échelle pour tenir sur la page:

+
    +
    +lp -o fitplot nom_fichier ENTREE
    +lpr -o fitplot nom_fichier ENTREE
    +
    +
+

Le comportement implicite est d'utiliser les distances absolues définies dans le fichier. +

+ + +
NOTE: +

Cette fonctionnalité dépend d'une définition précise de la commande de taille de tracé +(PS) dans le fichier HP-GL/2. Si aucune taille de tracé n'est donnée dans le fichier, alors le filtre +HP-GL/2 considère que le tracé a une taille ANSI E.

+
+
+

+

Réglage de la largeur implicite de tracé

+

L'option -o penwidth=valeur indique la valeur implicite de largeur de tracé pour les fichiers +HP-GL/2:

+
    +
    +lp -o penwidth=valeur nom_fichier ENTREE
    +lpr -o penwidth=valeur nom_fichier ENTREE
    +
    +
+

La valeur de largeur de tracé définit la largeur de "stylo" en micromètres. La valeur +implicite de 1000 produit des lignes de 1 millimètre de large. Indiquer une largeur de "stylo" de 0 produit un +tracé d'un pixel de large. +

+ + +
NOTE: +

Cette option est ignorée si les largeurs de tracé sont définies dans le fichier.

+
+
+

+

Sortie brute ou non filtrée

+

L'option -o raw vous permet d'envoyer directement des fichiers à l'imprimante sans faire de filtrage. +Cela est parfois nécessaire lors que vous imprimez depuis des applications qui fournissent leur propres "pilotes d'imprimantes" +pour votre imprimante:

+
    +
    +lp -o raw nom_fichier ENTREE
    +lpr -o raw nom_fichier ENTREE
    +
    +
+

L'option -l peut également être utilisée avec la commande lpr + pour envoyer directement des fichiers à une imprimante:

+
    +
    +lpr -l nom_fichier ENTREE
    +
    +
+

4 - Sauvegarder les options et valeurs implicites des réglages d'imprimante

+

Ce chapitre décrit comment sauvegarder les options pour votre imprimante et définir votre propre imprimante implicite.

+ +

Options d'imprimante

+ +

Chaque imprimante prend en charge un grand nombre d'options, que vous avez découvertes dans le + Chapitre 3, "Options standards d'imprimante". +Plutôt qu'indiquer ces options à chaque fois que vous imprimez un fichier, CUPS vous permet de sauvegarder comme +"implicites" les options pour votre imprimante.

+ +

La commande lpoptions(1) sauvegarde les options de vos imprimantes. +Comme les commandes lp et lpr, elle accepte les options d'imprimantes en utilisant l'argument +-o:

+
    +
    +lpoptions -o media=A4 -o sides=two-sided-long-edge ENTREE
    +lpoptions -o media=Legal -o scaling=100 ENTREE
    +
    +
+

Une fois sauvegardées, toute commande lp ou lpr les utilisera lorsque vous imprimerez.

+ +

Réglage des options pour une imprimante spécifique

+ +

L'exemple précédent montre comment régler les options pour l'imprimante implicite. L'option +-p imprimante indique que les options sont pour une autre imprimante:

+
    +
    +lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTREE
    +lpoptions -p deskjet -o media=Legal -o scaling=100 ENTREE
    +
    +
+

Visualisation des réglages implicites actuels

+

La commande lpoptions peut également être utilisée pour afficher les options actuelles en n'indiquant +aucune option sur la ligne de commande:

+
    +
    +lpoptions ENTREE
    +media=A4 sides=two-sided-long-edge
    +lpoptions -p deskjet ENTREE
    +media=Legal scaling=100
    +
    +
+

Choix de l'imprimante implicite

+ +

L'administrateur définira généralement une imprimante implicite valable pour tout le système et qui sera utilisée par tous. +Utilisez l'option -d imprimante pour définir votre propre imprimante implicite:

+
    +
    +lpoptions -d deskjet ENTREE
    +
    +
+

L'imprimante peut être locale (deskjet) ou à distance (deskjet@serveur).

+ +

Instances d'imprimantes

+ +

En plus de définir des réglages pour chaque file d'impression, CUPS prend en charge +les instances d'imprimantes qui vous permettent de définir différents jeux d'options pour chaque imprimante. +Vous indiquez chaque instante en utilisant le caractère "slash" (/):

+
    +
    +lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTREE
    +lpoptions -p laserjet/legal -o media=Legal ENTREE
    +
    +
+

Les commandes lp et lpr comprennent également la notation:

+
    +
    +lp -d laserjet/duplex nom_fichier ENTREE
    +lpr -P laserjet/legal nom_fichier ENTREE
    +
    +
+

Retirer des instances d'imprimantes

+ +

Utilisez l'option -x imprimante/instance pour retirer une instance d'imprimante dont vous n'avez plus +besoin:

+
    +
    +lpoptions -x laserjet ENTREE
    +lpoptions -x laserjet/duplex ENTREE
    +lpoptions -x laserjet/legal ENTREE
    +
    +
+

L'option -x ne retire que les options implicites pour cette instance d'imprimante. +la file d'impression d'origine demeurera jusqu'à suppression au moyen de la commande +lpadmin(8) par l'administrateur.

+ +

A - Licence d'utilisation du logiciel (NdT : en anglais)

+

Common UNIX Printing System License + Agreement

+

Copyright 1997-2002 by Easy Software Products +
44141 AIRPORT VIEW DR STE 204 +
HOLLYWOOD, MARYLAND 20636-3111 USA +
+
Voice: +1.301.373.9600 +
Email: cups-info@cups.org +
WWW: http://www.cups.org

+

Introduction

+

The Common UNIX Printing SystemTM, ("CUPSTM"), + is provided under the GNU General Public License ("GPL") and GNU + Library General Public License ("LGPL"), Version 2. A copy of these + licenses follow this introduction.

+

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_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.93a.

+

For those not familiar with the GNU GPL, the license basically allows + you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in source or binary form.
  • +
  • Sell verbatim copies of the software for a media fee, or sell + support for the software.
  • +
  • Distribute or sell printer drivers and filters that use CUPS so long + as source code is made available under the GPL.
  • +
+

What this license does not 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.

+

The GNU LGPL relaxes the "link-to" restriction, allowing you to + develop applications that use the CUPS API library under other licenses + and/or conditions as appropriate for your application.

+

Trademarks

+

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.

+

Binary Distribution Rights

+

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.

+

The Common UNIX Printing System provides a "pstoraster" 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:

Miles Jones +
Director of Marketing +
Artifex Software Inc. +
454 Las Gallinas Ave., Suite 108 +
San Rafael, CA 94903 USA +
Voice: +1.415.492.9861 +
Fax: +1.415.492.9862 +
EMail: info@arsoft.com
+

+

The "pdftops" filter is based on the Xpdf 0.93a software. For binary + distribution licensing of this software, please contact:

+ Derek B. Noonburg +
Email: derekn@foolabs.com +
WWW: + http://www.foolabs.com/xpdf/

+

Support

+

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:

+ + + +

GNU GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+
+
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow.

+

GNU GENERAL PUBLIC LICENSE +
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+
    +
  1. 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 "Program", below, + refers to any such program or work, and a "work based on the Program" + 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 "modification".) Each licensee is addressed as "you".
  2. +

    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.

    +
  3. 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.
  4. +

    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.

    +
  5. 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: +
      +
    1. You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change.
    2. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +
  6. +

    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.

    +

    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.

    +

    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.

    +
  7. 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: +
      +
    1. 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,
    2. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +
  8. +

    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.

    +

    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.

    +
  9. 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.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. 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.
  16. +

    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.

    +

    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.

    +

    This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

    +
  17. 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.
  18. +
  19. 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.
  20. +

    Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", 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.

    +
  21. 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.
  22. +
+

NO WARRANTY

+
    +
  1. 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 "AS IS" 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.
  2. +
  3. 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.
  4. +
+

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, while the latter only + works together with the library.

+

Note that it is possible for a library to be covered by the ordinary + General Public License rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+

0. 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 "this License"). Each + licensee is addressed as "you".

+

A "library" 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.

+

The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" 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 "modification".)

+

"Source code" 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.

+

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.

+

1. 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.

+

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.

+

2. 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:

+
    +
  1. The modified work must itself be a software library.
  2. +

    +
  3. You must cause the files modified to carry prominent notices stating + that you changed the files and the date of any change.
  4. +

    +
  5. You must cause the whole of the work to be licensed at no charge to + all third parties under the terms of this License.
  6. +

    +
  7. 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.
  8. +

    (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.)

    +
+

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.

+

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.

+

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.

+

3. 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.

+

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.

+

This option is useful when you wish to copy part of the code of the + Library into a program that is not a library.

+

4. 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.

+

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.

+

5. 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 "work that uses the + Library". Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License.

+

However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. Section + 6 states terms for distribution of such executables.

+

When a "work that uses the Library" 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.

+

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.)

+

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.

+

6. As an exception to the Sections above, you may + also compile or link a "work that uses the Library" 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.

+

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:

+
    +
  1. 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 "work that uses the Library", 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.)
  2. +

    +
  3. 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.
  4. +

    +
  5. 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.
  6. +

    +
  7. Verify that the user has already received a copy of these materials + or that you have already sent this user a copy.
  8. +
+

For an executable, the required form of the "work that uses the + Library" 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.

+

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.

+

7. 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:

+
    +
  1. 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.
  2. +

    +
  3. 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.
  4. +
+

8. 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.

+

9. 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.

+

10. 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.

+

11. 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.

+

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.

+

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.

+

This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

+

12. 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.

+

13. 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.

+

Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and "any + later version", 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.

+

14. 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.

+

NO WARRANTY

+

15. 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 "AS IS" 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.

+

16. 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.

+

END OF TERMS AND CONDITIONS

+ + diff --git a/doc/fr/system-overview.shtml b/doc/fr/system-overview.shtml new file mode 100644 index 0000000000..54b7df5e97 --- /dev/null +++ b/doc/fr/system-overview.shtml @@ -0,0 +1,19 @@ +

System Overview

+ +

CUPS provides a portable printing layer for UNIX®-based +operating systems. It has been developed by +Easy Software Products to promote a +standard printing solution for all UNIX vendors and users. CUPS +provides the System V and Berkeley command-line interfaces. + +

CUPS uses the Internet Printing Protocol ("IPP") as the basis for +managing print jobs and queues. The Line Printer Daemon ("LPD") Server +Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are +also supported with reduced functionality. CUPS adds network printer +browsing and PostScript Printer Description ("PPD") based +printing options to support real-world printing under UNIX. + +

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. diff --git a/doc/glossary.shtml b/doc/glossary.shtml new file mode 100644 index 0000000000..2cc0c1c893 --- /dev/null +++ b/doc/glossary.shtml @@ -0,0 +1,73 @@ +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Page Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
diff --git a/doc/idd.html b/doc/idd.html new file mode 100644 index 0000000000..d613d3d23d --- /dev/null +++ b/doc/idd.html @@ -0,0 +1,1088 @@ + + + +CUPS Interface Design Description + + + + + + + +

+

CUPS Interface Design Description


+CUPS-IDD-1.1
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Internal Interfaces + +4 External Interfaces + +5 Directories +
+
A Glossary + +
+

1 Scope

+

1.1 Identification

+

This interface design description document provides detailed file + formats, message formats, and program conventions for the Common UNIX + Printing System ("CUPS") Version 1.1.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+

1.3 Document Overview

+

This interface design description document is organized into the + following sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Internal Interfaces
  • +
  • 4 - External Interfaces
  • +
  • 5 - Directories
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+

The following CUPS documentation is referenced by this document:

+
    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.1: CUPS Software Security Report
  • +
  • CUPS-STP-1.1: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.1: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

The following non-CUPS documents are referenced by this document:

+ +

3 Internal Interfaces

+

3.1 Character Set Files

+

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 # character in the first column of a + line.

+

3.1.1 8-Bit Character Set Files

+

8-bit character set files start with a line reading:

+
    +
    +charset 8bit
    +
    +
+

Following this are lines that define the font information:

+
    +
    +first last direction width normal bold italic bold-italic
    +
    +
+

First and last 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.

+

Direction is the string "ltor", "rtol", or "rtola" + indicating left-to-right, right-to-left, or right-to-left Arabic text.

+

Width is the string "single" or "double"; double means + that the glyphs are twice as wide as ASCII characters in the Courier + typeface.

+

Normal, bold, italic, and bold-italic 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. "Symbol".) Each font that is listed will be used (and downloaded + if needed) when printing.

+

The remaining lines define a character to Unicode glyph mapping for + the character set. The character and glyph values are hexadecimal:

+
    +
    +xx yyyy
    +
    +
+

3.1.2 Unicode Character Set Files

+

Unicode character set files start with a line reading:

+
    +
    +charset encoding
    +
    +
+

Encoding is the encoding to use for the text; currently + only the string "utf8" is supported.

+

Following this are lines defining the font information:

+
    +
    +first last direction width normal bold italic bold-italic
    +
    +
+

First and last 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.

+

Direction is the string "ltor", "rtol", or "rtola" + indicating left-to-right, right-to-left, or right-to-left Arabic text.

+

Width is the string "single" or "double"; double means + that the glyphs are twice as wide as ASCII characters in the Courier + typeface.

+

Normal, bold, italic, and bold-italic 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. "Symbol".) Each font that is listed will be used (and downloaded + if needed) when printing.

+

3.2 Language Files

+

The language files define the default character set and a collection + of text messages in that language. They are named by prefixing the + string "cups_" to the front of the language specifier (e.g. "cups_en", + "cups_fr", etc.) Each file consists of two or more lines of ASCII text.

+

The first line identifies the character set to be used for the + messages. The currently recognized values are:

+
    +
  • iso-8859-1
  • +
  • iso-8859-2
  • +
  • iso-8859-3
  • +
  • iso-8859-4
  • +
  • iso-8859-5
  • +
  • iso-8859-6
  • +
  • iso-8859-7
  • +
  • iso-8859-8
  • +
  • iso-8859-9
  • +
  • iso-8859-10
  • +
  • iso-8859-13
  • +
  • iso-8859-14
  • +
  • iso-8859-15
  • +
  • us-ascii
  • +
  • utf-8
  • +
  • windows-874
  • +
  • windows-1250
  • +
  • windows-1251
  • +
  • windows-1252
  • +
  • windows-1253
  • +
  • windows-1254
  • +
  • windows-1255
  • +
  • windows-1256
  • +
  • windows-1257
  • +
  • windows-1258
  • +
  • koi8-r
  • +
  • koi8-u
  • +
+

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.

+

3.3 MIME Files

+

CUPS uses two MIME files in its standard configuration.

+

3.3.1 mime.types

+

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 ("#") + character. The backslash ("\") character can be used at the end of a + line to continue that line to the next.

+

Each non-blank line starts with a MIME type identifier ("super/type") + as registered with the IANA. All text following the MIME type is + treated as a series of type recognition rules:

+
    +
    +mime-type := super "/" type { SP rule }*
    +super := { "a-z" | "A-Z" }*
    +type := { "a-z" | "A-Z" | "-" | "." | "0-9" }*
    +rule := { extension | match | operator | "(" rule ")" }*
    +extension := { "a-z" | "A-Z" | "0-9" }*
    +match := "match(" regexp ")" |
    +         "ascii(" offset "," length ")" |
    +	 "printable(" offset "," length ")" |
    +	 "string(" offset "," string ")" |
    +	 "contains(" offset "," length "," string ")" |
    +	 "char(" offset "," value ")" |
    +	 "short(" offset "," value ")" |
    +	 "int(" offset "," value ")" |
    +	 "locale(" string ")"
    +operator := "+" |	[ logical AND ]
    +            "," | SP    [ logical OR ]
    +	    "!"         [ unary NOT ]
    +
    +
+

The int and short rules match look for + integers in network byte order (a.k.a. big-endian) with the + most-significant byte first.

+

3.3.2 mime.convs

+

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 + ("#") character.

+

Each non-blank line starts with two MIME type identifiers + ("super/type") 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:

+
    +
    +super/type SP super/type2 SP cost SP program
    +
    +
+

3.4 Option Files

+

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 (/etc/cups/lpoptions) are loaded first, + followed by the user option file ($HOME/.lpoptions). + 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:

+
    +
    +Dest name option=value option=value ... option=value
    +Dest name/instance option=value option=value ... option=value
    +Default name option=value option=value ... option=value
    +Default name/instance option=value option=value ... option=value
    +
    +
+

The line beginning with "Default" indicates the default destination + for print jobs; a default line in the user option file overrides the + default defined in the system option file.

+

Name is the name of a printer known to the local server.

+

Instance can be any string of letters, numbers, and the + underscore up to 127 characters in length.

+

The remainder of the line contains a list of space-separated options + and their values.

+

3.5 PostScript Printer Description Files

+

PostScript Printer Description ("PPD") files describe the + capabilities of each printer and are used by CUPS to support + printer-specific features and intelligent filtering.

+

3.5.1 PPD Specification

+

The PPD file format is described in + Adobe TechNote #5003: PostScript Printer Description File Format + Specification Version 4.3.

+

3.5.2 CUPS Extensions to PPD Files

+

CUPS adds several new attributes that are described below.

+

3.5.2.1 cupsFilter

+

This string attribute provides a conversion rule of the form:

+
    +
    +source/type cost program
    +
    +
+

The destination type is assumed to the printer's type. If a printer + supports the source type directly the special filter program "-" may be + specified.

+

3.5.2.2 cupsManualCopies

+

This boolean attribute notifies the RIP filters that the destination + printer does not support copy generation in hardware. The default value + is false.

+

3.5.2.3 cupsModelNumber

+

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.

+

3.5.2.4 cupsProfile

+

This string attribute specifies a color profile of the form:

+
    +
    +resolution/type density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22
    +
    +
+

The resolution and type values may be "-" to act as a + wildcard. Otherwise they must match one of the Resolution + or MediaType attributes defined in the PPD file.

+

The density and gamma values define gamma and density + adjustment function such that:

+
    +
    +f(x) = density * xgamma
    +
    +
+

The m00 through m22 values define a 3x3 transformation + matrix for the CMY color values. The density function is applied + after the CMY transformation.

+

3.5.2.5 cupsVersion

+

This required attribute describes which version of the CUPS IDD was + used for the PPD file extensions. Currently it must be the string "1.0" + or "1.1".

+

3.6 Scheduler Configuration Files

+

The scheduler reads three configuration files that define the + available printers, classes, and services:

+
+
classes.conf
+
This file defines all of the printer classes known to the system.
+
cupsd.conf
+
This file defines the files, directories, passwords, etc. used by + the scheduler.
+
printers.conf
+
This file defines all of the printers known to the system.
+
+

3.6.1 classes.conf

+

The classes.conf file consists of 1 or more lines of ASCII text. + Comment lines start with the pound ("#") character.

+

Each non-blank line starts with the name of a configuration directive + followed by its value. The following directives are understood: +

+ + + + + + + + + + + + + + +
DirectiveDescription
<Class name> +
</Class>
Surrounds a class definition.
<DefaultClass name> +
</Class>
Surrounds a class definition for the default + destination.
AcceptingSpecifies whether the class is accepting new + jobs. May be the names "Yes" or "No".
AllowUsersSpecifies a list of users that are allowed to + access the class.
BannerStartSpecifies the banner that is printed before + other files in a job.
BannerEndSpecifies the banner that is printed after + other files in a job.
DenyUsersSpecifies a list of users that are not allowed + to access the class.
InfoA textual description of the class.
LocationA textual location of the class.
PrinterSpecifies a printer that is a member of the + class.
StateSpecifies the initial state of the class; can be + "Idle" or "Stopped".
StateMessageSpecifies a textual message for the current + class state.
+
+

+

3.6.2 cupsd.conf

+

The cupsd.conf file consists of 1 or more lines of ASCII text. + Comment lines start with the pound ("#") character.

+

Each non-blank line starts with the name of a configuration directive + followed by its value. The following directives are understood: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDefaultDescription
AccessLogaccess_logSpecifies the location of + the access log file. The special name "syslog" can be used to send + access log information to the system log.
Allow-Allows connections from the specified + host, network, or domain.
AuthClass-Specifies what level of + authentication is required; may be "User", "System", or "Group".
AuthTypeNoneSpecifies the type of + authentication to perform; may be "None", "Basic", or "Digest".
BrowseAddress255.255.255.255Specifies a + broadcast address to send CUPS browsing packets to.
BrowseAllow-Specifies hosts or addresses from + which browsing information should be used.
BrowseDeny-Specifies hosts or addresses from + which browsing information should not be used.
BrowseInterval30Specifies the number of + seconds between browsing updates. A browse interval of 0 seconds + disables outgoing packets.
BrowseOrderAllow,DenySpecifies the order of + BrowseAllow and BrowseDeny directive processing; can be "Deny,Allow" to + implicitly deny hosts unless they are allowed by a BrowseAllow line, or + "Allow,Deny" to implicitly allow hosts unless they are denied by a + BrowseDeny line.
BrowsePoll-Specifies a server to poll for + available printers and classes.
BrowsePort631Specifies the UDP port number to + use for browse packets.
BrowseRelay-Specifies a source and destination + address for relaying browser information from one subnet to another.
BrowseShortNamesyesSpecifies whether or not to + provide short names (without the "@server" part) for remote printers.
BrowseTimeout300Specifies the number of + seconds to wait until remote destinations are removed from the local + destination list.
BrowsingOnSpecifies whether or not printer and + class browsing is enabled; can be "On" or "Off".
DataDir/usr/share/cupsSpecifies the directory + where CUPS data files are stored.
DefaultCharsetiso-8859-1Specifies the default + character set.
DefaultLanguagecurrent localeSpecifies the + default language.
Deny-Refuses connections from the specified + host, network, or domain.
DocumentRoot/usr/share/doc/cupsSpecifies the + document data root directory.
ErrorLogerror_logSpecifies the error log file + location. The special name "syslog" can be used to send error log + information to the system log.
Grouproot, sys, systemSpecifies the group name + or ID that is used when running external programs.
HostNameLookupsOffSpecifies whether or not to + perform reverse IP address lookups to get the actual hostname; may be + "On" or "Off". Hostname lookups can significantly degrade the + performance of the CUPS server if one or more DNS servers is not + functioning properly.
ImplicitClassesOnSpecifies 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 "On" or + "Off".
KeepAliveOnSpecifies whether or not to use the + HTTP Keep-Alive feature; may be "On" or "Off".
KeepAliveTimeout30Specifies the amount of time + to keep the HTTP connection alive before closing it.
<Location path> +
</Location>
-Specifies a location to restrict + access to.
LogLevelinfoControls the amount of information + that is logged in the error log file. Can be one of "debug", "info", + "warn", "error", or "none", in decreasing order or verbosity.
MaxClients100Specifies the maximum number of + simultaneous active clients. This value is internally limited to 1/3 of + the total number of available file descriptors.
MaxLogSize0Specifies 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.
MaxRequestSize0Specifies the maximum size of + HTTP requests in bytes. If set to 0 then there is no maximum.
OrderAllow,DenySpecifies the order of Allow + and Deny directive processing; can be "Deny,Allow" to implicitly deny + hosts unless they are allowed by an Allow line, or "Allow,Deny" to + implicitly allow hosts unless they are denied by a Deny line.
PageLogpage_logSpecifies the location of the + page log file. The special name "syslog" can be used to send page log + information to the system log.
Port631Specifies a port number to listen to + for HTTP connections.
Printcap/etc/printcapSpecifies 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.
RequestRoot/var/spool/cupsSpecifies the + location of request files.
RIPCache8mSpecifies the size of the memory + cache in bytes that is used by RIP filters.
ServerAdminroot@ServerNameSpecifies the person + to contact with problems.
ServerNamehostnameSpecifies the hostname that + is supplied to HTTP clients. This is also used to determine the default + CUPS server for the CUPS IPP client applications.
ServerRoot/etc/cupsSpecifies the root + directory for server configuration files.
SystemGrouproot, sys, systemSpecifies the + group name used for System class authentication.
TempDir/var/tmpSpecifies the temporary + directory to use.
Timeout300The timeout in seconds before client + connections are closed in the middle of a request.
UserlpSpecifies the user that is used when + running external programs.
+
+

+

3.6.3 printers.conf

+

The printers.conf file consists of 1 or more lines of ASCII text. + Comment lines start with the pound ("#") character.

+

Each non-blank line starts with the name of a configuration directive + followed by its value. The following directives are understood: +

+ + + + + + + + + + + + + + +
DirectiveDescription
AcceptingSpecifies whether the printer is accepting new + jobs. May be the names "Yes" or "No".
<DefaultPrinter name> +
</Printer>
Surrounds the printer definition for a default + destination.
AllowUsersSpecifies a list of users that are allowed to + access the printer.
BannerStartSpecifies the banner that is printed before + other files in a job.
BannerEndSpecifies the banner that is printed after + other files in a job.
DenyUsersSpecifies a list of users that are not allowed + to access the printer.
DeviceURISpecifies the device-uri attribute for the + printer.
InfoA textual description of the printer.
LocationA textual location of the printer.
<Printer name> +
</Printer>
Surrounds the printer definition.
StateSpecifies the initial state of the printer; can be + "Idle" or "Stopped".
StateMessageSpecifies a textual message for the current + printer state.
+
+

+

4 External Interfaces

+

4.1 AppSocket Protocol

+

The AppSocket protocol is an 8-bit clean TCP/IP socket connection. + The default IP service port is 9100. The URI method name is "socket".

+

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.

+

4.2 CUPS Browsing Protocol

+

The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By + default this service operates on IP service port 631.

+

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:

+
    +
    +type SP state SP uri SP "location" SP "info" SP "make-and-model" NL
    +
    +
+

State, uri, location, info, and make-and-model, + correspond to the IPP printer-state, +printer-uri-supported, printer-location, +printer-info, and printer-make-and-model attributes.

+

Type is a hexadecimal number string representing + capability/type bits: +

+ + + + + + + + + + + + + + + + + + +
BitDescription
00 = printer +
1 = class
10 = local +
1 = remote +
(always 1)
21 = can print B
31 = can print color
41 = can duplex
51 = can staple
61 = can do fast copies
71 = can do fast collating
81 = can punch holes
91 = can cover
101 = can bind
111 = can sort
121 = can print up to 9x14 inches
131 = can print up to 18x24 inches
141 = can print up to 36x48 inches
151 = can print variable sizes
+
+

+

4.3 CUPS Form File

+

CUPS Form files are XML files used by the CUPS formtops + filter to produce dynamic banner pages and support preprinted forms.

+

The MIME type for CUPS Form files is application/vnd.cups-form +.

+

4.3.1 CUPS Form DTD

+

The following DTD describes the available elements and attributes in + a CUPS Form file: +

+ + +
+
+<!ENTITY % Angle "CDATA" -- angle in degrees -->
+
+<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
+
+<!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % Lengths "CDATA" -- comma-separated Length values -->
+
+<!ENTITY % Text "CDATA">
+
+<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
+
+<!ENTITY % preformatted "PRE">
+
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --"
+  >
+
+<!ENTITY % attrs "%i18n;">
+
+<!ENTITY % fontstyle
+ "B | FONT | I | TT">
+
+<!ENTITY % graphics
+ "BOX | RECT | LINE | POLY | ARC | PIE | TEXT">
+
+<!ENTITY % insert
+ "IMG | VAR">
+
+<!-- %inline; covers inline or "text-level" elements -->
+<!ENTITY % inline "#PCDATA | %fontstyle; | %graphics; | %insert;">
+
+<!ELEMENT (%fontstyle;) - - (%inline;)*>
+<!ATTLIST (%fontstyle;)
+  %attrs;                              -- %i18n --
+  >
+
+<!ELEMENT BR - O EMPTY                 -- forced line break -->
+<!ATTLIST BR
+  %attrs;                              -- %i18n --
+  >
+
+<!ENTITY % block
+     "P | %heading; | %preformatted;">
+
+<!ENTITY % flow "%block; | %inline;">
+
+<!ELEMENT PAGE O O (%flow;)+           -- document body -->
+<!ATTLIST PAGE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  >
+
+<!ELEMENT P - O (%inline;)*            -- paragraph -->
+<!ATTLIST P
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->
+<!ATTLIST (%heading;)
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT PRE - - (%inline;)*          -- preformatted text -->
+<!ATTLIST PRE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT BOX - O EMPTY                -- unfilled box -->
+<!ATTLIST BOX
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT RECT - O EMPTY               -- filled box -->
+<!ATTLIST RECT
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT LINE - O EMPTY               -- polyline -->
+<!ATTLIST LINE
+  color       %Color;        #IMPLIED  -- override color --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT POLY - O EMPTY               -- polygon (filled) -->
+<!ATTLIST POLY
+  color       %Color;        #IMPLIED  -- override color --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT ARC - O EMPTY                -- unfilled arc -->
+<!ATTLIST ARC
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT PIE - O EMPTY                -- filled arc -->
+<!ATTLIST PIE
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT TEXT - - (%flow;)*           -- text box -->
+<!ATTLIST RECT
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  height      %Length;       #REQUIRED -- height of box --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+
+<!ELEMENT IMG - O EMPTY                -- Embedded image -->
+<!ATTLIST IMG
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  src         %URI;          #REQUIRED -- URI of image to embed --
+  height      %Length;       #IMPLIED  -- override height --
+  width       %Length;       #IMPLIED  -- override width --
+  >
+
+<!ELEMENT HEAD O O (DEFVAR)*           -- document head -->
+<!ATTLIST HEAD
+  %i18n;                               -- lang, dir --
+  >
+
+<!ELEMENT DEFVAR - O EMPTY             -- variable definition -->
+<!ATTLIST DEFVAR
+  name        CDATA          #REQUIRED -- name
+  value       CDATA          #REQUIRED -- value
+  >
+
+
+<!ENTITY % html.content "HEAD, PAGE">
+
+<!ELEMENT CUPSFORM - - (HEAD) (PAGE)+  -- document root element -->
+<!ATTLIST CUPSFORM
+  %i18n;                               -- lang, dir --
+  >
+
+
+
+

+

4.4 CUPS PostScript File

+

CUPS PostScript files are device-dependent Adobe PostScript program + files. The PostScript language is described in the + Adobe PostScript Language Reference Manual, Third Edition.

+

The MIME type for CUPS PostScript files is +application/vnd.cups-postscript.

+

4.5 CUPS Raster File

+

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.

+

A raster file begins with a four byte synchronization word: + 0x52615374 ("RaSt") for big-endian architectures and 0x74536152 + ("tSaR") 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.

+

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. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BytesDescriptionValues
0-63MediaClassNul-terminated ASCII string
64-127MediaColorNul-terminated ASCII string
128-191MediaTypeNul-terminated ASCII string
192-255OutputTypeNul-terminated ASCII string
256-259AdvanceDistance0 to 232 - 1 + points
260-263AdvanceMedia0 = Never advance roll +
1 = Advance roll after file +
2 = Advance roll after job +
3 = Advance roll after set +
4 = Advance roll after page
264-267Collate0 = do not collate copies +
1 = collate copies
268-271CutMedia0 = Never cut media +
1 = Cut roll after file +
2 = Cut roll after job +
3 = Cut roll after set +
4 = Cut roll after page
272-275Duplex0 = Print single-sided +
1 = Print double-sided
276-283HWResolutionHorizontal and vertical + resolution in dots-per-inch.
284-299ImagingBoundingBoxFour integers giving + the left, bottom, right, and top positions of the page bounding box in + points
300-303InsertSheet0 = Do not insert separator + sheets +
1 = Insert separator sheets
304-307Jog0 = Do no jog pages +
1 = Jog pages after file +
2 = Jog pages after job +
3 = Jog pages after set
308-311LeadingEdge0 = Top edge is first +
1 = Right edge is first +
2 = Bottom edge is first +
3 = Left edge is first
312-319MarginsLeft and bottom origin of image + in points
320-323ManualFeed0 = Do not manually feed + media +
1 = Manually feed media
324-327MediaPositionInput slot position from 0 + to N
328-331MediaWeightMedia weight in grams per + meter squared
332-335MirrorPrint0 = Do not mirror prints +
1 = Mirror prints
336-339NegativePrint0 = Do not invert prints +
1 = Invert prints
340-343NumCopies1 to 232 - 1
344-347Orientation0 = Do not rotate page +
1 = Rotate page counter-clockwise +
2 = Turn page upside down +
3 = Rotate page clockwise
348-351OutputFaceUp0 = Output face down +
1 = Output face up
352-359PageSizeWidth and length in points
360-363Separations0 = Print composite image +
1 = Print color separations
364-367TraySwitch0 = Do not change trays if + selected tray is empty +
1 = Change trays if selected tray is empty
368-371Tumble0 = Do not rotate even pages when + duplexing +
1 = Rotate even pages when duplexing
372-375cupsWidthWidth of page image in pixels
376-379cupsHeightHeight of page image in + pixels
380-383cupsMediaTypeDriver-specific 0 to 2 +32 - 1
384-387cupsBitsPerColor1, 2, 4, 8 bits
388-391cupsBitsPerPixel1 to 32 bits
392-395cupsBytesPerLine1 to 232 - 1 + bytes
396-399cupsColorOrder0 = chunky pixels (CMYK + CMYK CMYK) +
1 = banded pixels (CCC MMM YYY KKK) +
2 = planar pixels (CCC... MMM... YYY... KKK...)
400-403cupsColorSpace0 = white +
1 = RGB +
2 = RGBA +
3 = black +
4 = CMY +
5 = YMC +
6 = CMYK +
7 = YMCK +
8 = KCMY +
9 = KCMYcm
404-407cupsCompressionDriver-specific 0 to 2 +32 - 1
408-411cupsRowCountDriver-specific 0 to 2 +32 - 1
412-415cupsRowFeedDriver-specific 0 to 2 +32 - 1
416-419cupsRowStepDriver-specific 0 to 2 +32 - 1
+
+

+

The MIME type for CUPS Raster files is +application/vnd.cups-raster.

+

4.6 CUPS Raw Files

+

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 application/vnd.cups-raw.

+

4.7 Internet Printing Protocol

+

The Internet Printing Protocol and the CUPS extensions to it are + described in the CUPS Implementation of IPP document.

+

4.8 Line Printer Daemon Protocol

+

The Line Printer Daemon (LPD) protocol is described by + RFC 1179: Line Printer Daemon Protocol.

+

The URI method name for LPD is "lpd".

+

4.9 Server Message Block Protocol

+

The Server Message Block (SMB) and related Common Internet File + System (CIFS) protocols are described at + http://anu.samba.org/cifs.

+

The URI method name for SMB is "smb". Support for this protocol is + provided via the SAMBA smbspool(1) program provided with + SAMBA 2.0.6 and higher.

+

5 Directories

+
+
/etc/cups
+
The scheduler configuration and MIME files reside here.
+
/etc/cups/certs
+
The authentication certificates reside here.
+
/etc/cups/interfaces
+
System V interface scripts reside here.
+
/etc/cups/ppd
+
This directory contains PPD files for each printer.
+
/usr/bin
+
The cancel, lp, lpq, +lpr, lprm, and lpstat commands reside + here.
+
/usr/lib, /usr/lib32
+
The shared libraries (DSOs) reside here.
+
/usr/lib/cups/backend
+
The backend filters reside here.
+
/usr/lib/cups/cgi-bin
+
The CGI programs reside here.
+
/usr/lib/cups/daemon
+
The polling and LPD daemons reside here.
+
/usr/lib/cups/filter
+
The file filters reside here.
+
/usr/sbin
+
The accept, cupsd, lpadmin, +lpc, and reject commands reside here.
+
/usr/share/cups
+
This is the root directory of the CUPS static data.
+
/usr/share/cups/charsets
+
The character set files reside here.
+
/usr/share/cups/data
+
The filter data files reside here.
+
/usr/share/cups/fonts
+
The pstoraster font files reside here.
+
/usr/share/cups/model
+
The sample PPD files reside here.
+
/usr/share/cups/pstoraster
+
The pstoraster data files reside here.
+
/usr/share/doc/cups
+
The scheduler documentation files reside here.
+
/var/log/cups
+
The access_log, error_log, and +page_log files reside here.
+
/var/spool/cups
+
This directory contains print job files.
+
+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Page Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/idd.pdf b/doc/idd.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a18253bf716d1b0ad8564cb41cfc71e314ee3899 GIT binary patch literal 67423 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 + + + + + CUPS Interface Design Description + + + +

Scope

+ +

Identification

+ +

This interface design description document provides detailed file +formats, message formats, and program conventions for the Common UNIX +Printing System ("CUPS") Version 1.1. + + + +

Document Overview

+ +

This interface design description document is organized into the following +sections: + +

    +
  • 1 - Scope +
  • 2 - References +
  • 3 - Internal Interfaces +
  • 4 - External Interfaces +
  • 5 - Directories +
  • A - Glossary +
+ + + +

Internal Interfaces

+ +

Character Set Files

+ +

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 # character in the first column +of a line. + +

8-Bit Character Set Files

+ +

8-bit character set files start with a line reading: + +

    +charset 8bit
    +
+ +

Following this are lines that define the font information: + +

    +first last direction width normal bold italic bold-italic
    +
+ +

First and last 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. + +

Direction is the string "ltor", "rtol", or "rtola" indicating +left-to-right, right-to-left, or right-to-left Arabic text. + +

Width is the string "single" or "double"; double means that the +glyphs are twice as wide as ASCII characters in the Courier typeface. + +

Normal, bold, italic, and bold-italic 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. "Symbol".) +Each font that is listed will be used (and downloaded if needed) when +printing. + +

The remaining lines define a character to Unicode glyph mapping for the +character set. The character and glyph values are hexadecimal: + +

    +xx yyyy
    +
+ +

Unicode Character Set Files

+ +

Unicode character set files start with a line reading: + +

    +charset encoding
    +
+ +

Encoding is the encoding to use for the text; currently only +the string "utf8" is supported. + +

Following this are lines defining the font information: + +

    +first last direction width normal bold italic bold-italic
    +
+ +

First and last 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. + +

Direction is the string "ltor", "rtol", or "rtola" indicating +left-to-right, right-to-left, or right-to-left Arabic text. + +

Width is the string "single" or "double"; double means that the +glyphs are twice as wide as ASCII characters in the Courier typeface. + +

Normal, bold, italic, and bold-italic 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. "Symbol".) +Each font that is listed will be used (and downloaded if needed) when +printing. + +

Language Files

+ +

The language files define the default character set and a collection of +text messages in that language. They are named by prefixing the string "cups_" +to the front of the language specifier (e.g. "cups_en", "cups_fr", etc.) Each +file consists of two or more lines of ASCII text. + +

The first line identifies the character set to be used for the messages. +The currently recognized values are: + +

    +
  • iso-8859-1 +
  • iso-8859-2 +
  • iso-8859-3 +
  • iso-8859-4 +
  • iso-8859-5 +
  • iso-8859-6 +
  • iso-8859-7 +
  • iso-8859-8 +
  • iso-8859-9 +
  • iso-8859-10 +
  • iso-8859-13 +
  • iso-8859-14 +
  • iso-8859-15 +
  • us-ascii +
  • utf-8 +
  • windows-874 +
  • windows-1250 +
  • windows-1251 +
  • windows-1252 +
  • windows-1253 +
  • windows-1254 +
  • windows-1255 +
  • windows-1256 +
  • windows-1257 +
  • windows-1258 +
  • koi8-r +
  • koi8-u +
+ +

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. + +

MIME Files

+ +

CUPS uses two MIME files in its standard configuration. + +

mime.types

+ +

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 +("#") character. The backslash ("\") character can be used at the end +of a line to continue that line to the next. + +

Each non-blank line starts with a MIME type identifier ("super/type") +as registered with the IANA. All text following the MIME type is treated as +a series of type recognition rules: + +

    +mime-type := super "/" type { SP rule }*
    +super := { "a-z" | "A-Z" }*
    +type := { "a-z" | "A-Z" | "-" | "." | "0-9" }*
    +rule := { extension | match | operator | "(" rule ")" }*
    +extension := { "a-z" | "A-Z" | "0-9" }*
    +match := "match(" regexp ")" |
    +         "ascii(" offset "," length ")" |
    +	 "printable(" offset "," length ")" |
    +	 "string(" offset "," string ")" |
    +	 "contains(" offset "," length "," string ")" |
    +	 "char(" offset "," value ")" |
    +	 "short(" offset "," value ")" |
    +	 "int(" offset "," value ")" |
    +	 "locale(" string ")"
    +operator := "+" |	[ logical AND ]
    +            "," | SP    [ logical OR ]
    +	    "!"         [ unary NOT ]
    +
+ +

The int and short rules match look for integers +in network byte order (a.k.a. big-endian) with the most-significant byte first. + +

mime.convs

+ +

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 +("#") character. + +

Each non-blank line starts with two MIME type identifiers ("super/type") +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: + +

    +super/type SP super/type2 SP cost SP program
    +
+ +

Option Files

+ +

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 (/etc/cups/lpoptions) are loaded first, +followed by the user option file ($HOME/.lpoptions). +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: + +

    +Dest name option=value option=value ... option=value
    +Dest name/instance option=value option=value ... option=value
    +Default name option=value option=value ... option=value
    +Default name/instance option=value option=value ... option=value
    +
+ +

The line beginning with "Default" indicates the default destination for +print jobs; a default line in the user option file overrides the default +defined in the system option file. + +

Name is the name of a printer known to the local server. + +

Instance can be any string of letters, numbers, and the underscore +up to 127 characters in length. + +

The remainder of the line contains a list of space-separated options +and their values. + +

PostScript Printer Description Files

+ +

PostScript Printer Description ("PPD") files describe the capabilities +of each printer and are used by CUPS to support printer-specific features +and intelligent filtering. + +

PPD Specification

+ +

The PPD file format is described in + +Adobe TechNote #5003: PostScript Printer Description File Format +Specification Version 4.3. + +

CUPS Extensions to PPD Files

+ +

CUPS adds several new attributes that are described below. + +

cupsFilter

+ +

This string attribute provides a conversion rule of the form: + +

    +source/type cost program
    +
+ +

The destination type is assumed to the printer's type. If a printer +supports the source type directly the special filter program "-" may be +specified. + +

cupsManualCopies

+ +

This boolean attribute notifies the RIP filters that the destination printer +does not support copy generation in hardware. The default value is false. + +

cupsModelNumber

+ +

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. + +

cupsProfile

+ +

This string attribute specifies a color profile of the form: + +

    +resolution/type density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22
    +
+ +

The resolution and type values may be "-" to act as a +wildcard. Otherwise they must match one of the Resolution or +MediaType attributes defined in the PPD file. + +

The density and gamma values define gamma and density +adjustment function such that: + +

    +f(x) = density * xgamma
    +
+ +

The m00 through m22 values define a 3x3 transformation +matrix for the CMY color values. The density function is applied after +the CMY transformation. + +

cupsVersion

+ +

This required attribute describes which version of the CUPS IDD was used +for the PPD file extensions. Currently it must be the string "1.0" or "1.1". + +

Scheduler Configuration Files

+ +

The scheduler reads three configuration files that define the available +printers, classes, and services: + +

+ +
classes.conf +
This file defines all of the printer classes known to the + system. + +
cupsd.conf +
This file defines the files, directories, passwords, etc. + used by the scheduler. + +
printers.conf +
This file defines all of the printers known to the system. + +
+ +

classes.conf

+ +

The classes.conf file consists of 1 or more lines of ASCII text. +Comment lines start with the pound ("#") character. + +

Each non-blank line starts with the name of a configuration directive +followed by its value. The following directives are understood: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDescription
<Class name>
+ </Class>
Surrounds a class definition.
<DefaultClass name>
+ </Class>
Surrounds a class definition for the default destination.
AcceptingSpecifies whether the class is accepting new jobs. May be + the names "Yes" or "No".
AllowUsersSpecifies a list of users that are allowed to access the class.
BannerStartSpecifies the banner that is printed before other files in a + job.
BannerEndSpecifies the banner that is printed after other files in a + job.
DenyUsersSpecifies a list of users that are not allowed to access the + class.
InfoA textual description of the class.
LocationA textual location of the class.
PrinterSpecifies a printer that is a member of the class.
StateSpecifies the initial state of the class; can be "Idle" or + "Stopped".
StateMessageSpecifies a textual message for the current class state.
+ +

cupsd.conf

+ +

The cupsd.conf file consists of 1 or more lines of ASCII text. +Comment lines start with the pound ("#") character. + +

Each non-blank line starts with the name of a configuration directive +followed by its value. The following directives are understood: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDefaultDescription
AccessLogaccess_logSpecifies the location of the access log file. The special name + "syslog" can be used to send access log information to the system + log.
Allow-Allows connections from the specified host, network, or + domain.
AuthClass-Specifies what level of authentication is required; may be + "User", "System", or "Group".
AuthTypeNoneSpecifies the type of authentication to perform; may be + "None", "Basic", or "Digest".
BrowseAddress255.255.255.255Specifies a broadcast address to send CUPS browsing packets to.
BrowseAllow-Specifies hosts or addresses from which browsing information + should be used.
BrowseDeny-Specifies hosts or addresses from which browsing information + should not be used.
BrowseInterval30Specifies the number of seconds between browsing updates. A + browse interval of 0 seconds disables outgoing packets.
BrowseOrderAllow,DenySpecifies the order of BrowseAllow and BrowseDeny directive + processing; can be "Deny,Allow" to implicitly deny hosts unless + they are allowed by a BrowseAllow line, or "Allow,Deny" to + implicitly allow hosts unless they are denied by a BrowseDeny + line.
BrowsePoll-Specifies a server to poll for available printers and classes.
BrowsePort631Specifies the UDP port number to use for browse packets.
BrowseRelay-Specifies a source and destination address for relaying browser + information from one subnet to another.
BrowseShortNamesyesSpecifies whether or not to provide short names (without the + "@server" part) for remote printers.
BrowseTimeout300Specifies the number of seconds to wait until remote destinations + are removed from the local destination list.
BrowsingOnSpecifies whether or not printer and class browsing is enabled; can + be "On" or "Off".
DataDir/usr/share/cupsSpecifies the directory where CUPS data files are stored.
DefaultCharsetiso-8859-1Specifies the default character set.
DefaultLanguagecurrent localeSpecifies the default language.
Deny-Refuses connections from the specified host, network, or + domain.
DocumentRoot/usr/share/doc/cupsSpecifies the document data root directory.
ErrorLogerror_logSpecifies the error log file location. The special name + "syslog" can be used to send error log information to the system + log.
Grouproot, sys, systemSpecifies the group name or ID that is used when running + external programs.
HostNameLookupsOffSpecifies whether or not to perform reverse IP address lookups to + get the actual hostname; may be "On" or "Off". Hostname lookups can + significantly degrade the performance of the CUPS server if one or + more DNS servers is not functioning properly.
ImplicitClassesOnSpecifies 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 "On" or "Off".
KeepAliveOnSpecifies whether or not to use the HTTP Keep-Alive feature; may + be "On" or "Off".
KeepAliveTimeout30Specifies the amount of time to keep the HTTP connection alive + before closing it.
<Location path>
+ </Location>
-Specifies a location to restrict access to.
LogLevelinfoControls the amount of information that is logged in the + error log file. Can be one of "debug", "info", "warn", "error", + or "none", in decreasing order or verbosity.
MaxClients100Specifies the maximum number of simultaneous active clients. + This value is internally limited to 1/3 of the total number of + available file descriptors.
MaxLogSize0Specifies 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.
MaxRequestSize0Specifies the maximum size of HTTP requests in bytes. If set to 0 + then there is no maximum.
OrderAllow,DenySpecifies the order of Allow and Deny directive processing; can + be "Deny,Allow" to implicitly deny hosts unless they are allowed by + an Allow line, or "Allow,Deny" to implicitly allow hosts unless they + are denied by a Deny line.
PageLogpage_logSpecifies the location of the page log file. The special name + "syslog" can be used to send page log information to the system + log.
Port631Specifies a port number to listen to for HTTP connections.
Printcap/etc/printcapSpecifies 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.
RequestRoot/var/spool/cupsSpecifies the location of request files.
RIPCache8mSpecifies the size of the memory cache in bytes that is used by + RIP filters.
ServerAdminroot@ServerNameSpecifies the person to contact with problems.
ServerNamehostnameSpecifies the hostname that is supplied to HTTP clients. This + is also used to determine the default CUPS server for the CUPS IPP + client applications.
ServerRoot/etc/cupsSpecifies the root directory for server configuration files.
SystemGrouproot, sys, systemSpecifies the group name used for System class authentication.
TempDir/var/tmpSpecifies the temporary directory to use.
Timeout300The timeout in seconds before client connections are closed + in the middle of a request.
UserlpSpecifies the user that is used when running external programs.
+ +

printers.conf

+ +

The printers.conf file consists of 1 or more lines of ASCII text. +Comment lines start with the pound ("#") character. + +

Each non-blank line starts with the name of a configuration directive +followed by its value. The following directives are understood: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveDescription
AcceptingSpecifies whether the printer is accepting new jobs. May be + the names "Yes" or "No".
<DefaultPrinter name>
+ </Printer>
Surrounds the printer definition for a default destination.
AllowUsersSpecifies a list of users that are allowed to access the printer.
BannerStartSpecifies the banner that is printed before other files in a + job.
BannerEndSpecifies the banner that is printed after other files in a + job.
DenyUsersSpecifies a list of users that are not allowed to access the + printer.
DeviceURISpecifies the device-uri attribute for the printer.
InfoA textual description of the printer.
LocationA textual location of the printer.
<Printer name>
+ </Printer>
Surrounds the printer definition.
StateSpecifies the initial state of the printer; can be "Idle" or + "Stopped".
StateMessageSpecifies a textual message for the current printer state.
+ +

External Interfaces

+ +

AppSocket Protocol

+ +

The AppSocket protocol is an 8-bit clean TCP/IP socket connection. +The default IP service port is 9100. The URI method name is "socket". + +

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. + +

CUPS Browsing Protocol

+ +

The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By default +this service operates on IP service port 631. + +

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: + +

    +type SP state SP uri SP "location" SP "info" SP "make-and-model" NL
    +
+ +

State, uri, location, info, and make-and-model, +correspond to the IPP printer-state, +printer-uri-supported, printer-location, +printer-info, and printer-make-and-model +attributes. + +

Type is a hexadecimal number string representing +capability/type bits: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitDescription
00 = printer
+ 1 = class
10 = local
+ 1 = remote
+ (always 1)
21 = can print B&W
31 = can print color
41 = can duplex
51 = can staple
61 = can do fast copies
71 = can do fast collating
81 = can punch holes
91 = can cover
101 = can bind
111 = can sort
121 = can print up to 9x14 inches
131 = can print up to 18x24 inches
141 = can print up to 36x48 inches
151 = can print variable sizes
+ +

CUPS Form File

+ +

CUPS Form files are XML files used by the CUPS formtops +filter to produce dynamic banner pages and support preprinted forms. + +

The MIME type for CUPS Form files is +application/vnd.cups-form. + +

CUPS Form DTD

+ +

The following DTD describes the available elements and attributes in +a CUPS Form file: + +

+ + + +
+<!ENTITY % Angle "CDATA" -- angle in degrees -->
+
+<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
+
+<!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % Lengths "CDATA" -- comma-separated Length values -->
+
+<!ENTITY % Text "CDATA">
+
+<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
+
+<!ENTITY % preformatted "PRE">
+
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --"
+  >
+
+<!ENTITY % attrs "%i18n;">
+
+<!ENTITY % fontstyle
+ "B | FONT | I | TT">
+
+<!ENTITY % graphics
+ "BOX | RECT | LINE | POLY | ARC | PIE | TEXT">
+
+<!ENTITY % insert
+ "IMG | VAR">
+
+<!-- %inline; covers inline or "text-level" elements -->
+<!ENTITY % inline "#PCDATA | %fontstyle; | %graphics; | %insert;">
+
+<!ELEMENT (%fontstyle;) - - (%inline;)*>
+<!ATTLIST (%fontstyle;)
+  %attrs;                              -- %i18n --
+  >
+
+<!ELEMENT BR - O EMPTY                 -- forced line break -->
+<!ATTLIST BR
+  %attrs;                              -- %i18n --
+  >
+
+<!ENTITY % block
+     "P | %heading; | %preformatted;">
+
+<!ENTITY % flow "%block; | %inline;">
+
+<!ELEMENT PAGE O O (%flow;)+           -- document body -->
+<!ATTLIST PAGE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  >
+
+<!ELEMENT P - O (%inline;)*            -- paragraph -->
+<!ATTLIST P
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->
+<!ATTLIST (%heading;)
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT PRE - - (%inline;)*          -- preformatted text -->
+<!ATTLIST PRE
+  %attrs;                              -- %i18n --
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  >
+
+<!ELEMENT BOX - O EMPTY                -- unfilled box -->
+<!ATTLIST BOX
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT RECT - O EMPTY               -- filled box -->
+<!ATTLIST RECT
+  color       %Color;        #IMPLIED  -- override color --
+  height      %Length;       #REQUIRED -- height of box --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT LINE - O EMPTY               -- polyline -->
+<!ATTLIST LINE
+  color       %Color;        #IMPLIED  -- override color --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT POLY - O EMPTY               -- polygon (filled) -->
+<!ATTLIST POLY
+  color       %Color;        #IMPLIED  -- override color --
+  x           %Lengths;      #REQUIRED -- horizontal positions --
+  y           %Lengths;      #REQUIRED -- vertical positions --
+  >
+
+<!ELEMENT ARC - O EMPTY                -- unfilled arc -->
+<!ATTLIST ARC
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  thickness   %Length;       #IMPLIED  -- override line thickness --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT PIE - O EMPTY                -- filled arc -->
+<!ATTLIST PIE
+  color       %Color;        #IMPLIED  -- override color --
+  end         %Angle;        #IMPLIED  -- override end angle --
+  height      %Length;       #REQUIRED -- height of arc --
+  start       %Angle;        #IMPLIED  -- override start angle --
+  width       %Length;       #REQUIRED -- width of arc --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+<!ELEMENT TEXT - - (%flow;)*           -- text box -->
+<!ATTLIST RECT
+  align       (left|center|right) #IMPLIED -- horizontal alignment --
+  height      %Length;       #REQUIRED -- height of box --
+  valign      (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+  width       %Length;       #REQUIRED -- width of box --
+  x           %Length;       #REQUIRED -- horizontal position --
+  y           %Length;       #REQUIRED -- vertical position --
+  >
+
+
+<!ELEMENT IMG - O EMPTY                -- Embedded image -->
+<!ATTLIST IMG
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  src         %URI;          #REQUIRED -- URI of image to embed --
+  height      %Length;       #IMPLIED  -- override height --
+  width       %Length;       #IMPLIED  -- override width --
+  >
+
+<!ELEMENT HEAD O O (DEFVAR)*           -- document head -->
+<!ATTLIST HEAD
+  %i18n;                               -- lang, dir --
+  >
+
+<!ELEMENT DEFVAR - O EMPTY             -- variable definition -->
+<!ATTLIST DEFVAR
+  name        CDATA          #REQUIRED -- name
+  value       CDATA          #REQUIRED -- value
+  >
+
+
+<!ENTITY % html.content "HEAD, PAGE">
+
+<!ELEMENT CUPSFORM - - (HEAD) (PAGE)+  -- document root element -->
+<!ATTLIST CUPSFORM
+  %i18n;                               -- lang, dir --
+  >
+
+ +

CUPS PostScript File

+ +

CUPS PostScript files are device-dependent Adobe PostScript program files. +The PostScript language is described in the + +Adobe PostScript Language Reference Manual, Third Edition. + +

The MIME type for CUPS PostScript files is +application/vnd.cups-postscript. + +

CUPS Raster File

+ +

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. + +

A raster file begins with a four byte synchronization word: 0x52615374 +("RaSt") for big-endian architectures and 0x74536152 ("tSaR") 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. + +

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. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BytesDescriptionValues
0-63MediaClassNul-terminated ASCII string
64-127MediaColorNul-terminated ASCII string
128-191MediaTypeNul-terminated ASCII string
192-255OutputTypeNul-terminated ASCII string
256-259AdvanceDistance0 to 232 - 1 points
260-263AdvanceMedia0 = Never advance roll
+ 1 = Advance roll after file
+ 2 = Advance roll after job
+ 3 = Advance roll after set
+ 4 = Advance roll after page
264-267Collate0 = do not collate copies
+ 1 = collate copies
268-271CutMedia0 = Never cut media
+ 1 = Cut roll after file
+ 2 = Cut roll after job
+ 3 = Cut roll after set
+ 4 = Cut roll after page
272-275Duplex0 = Print single-sided
+ 1 = Print double-sided
276-283HWResolutionHorizontal and vertical resolution in dots-per-inch.
284-299ImagingBoundingBoxFour integers giving the left, bottom, right, and top positions + of the page bounding box in points
300-303InsertSheet0 = Do not insert separator sheets
+ 1 = Insert separator sheets
304-307Jog0 = Do no jog pages
+ 1 = Jog pages after file
+ 2 = Jog pages after job
+ 3 = Jog pages after set
308-311LeadingEdge0 = Top edge is first
+ 1 = Right edge is first
+ 2 = Bottom edge is first
+ 3 = Left edge is first
312-319MarginsLeft and bottom origin of image in points
320-323ManualFeed0 = Do not manually feed media
+ 1 = Manually feed media
324-327MediaPositionInput slot position from 0 to N
328-331MediaWeightMedia weight in grams per meter squared
332-335MirrorPrint0 = Do not mirror prints
+ 1 = Mirror prints
336-339NegativePrint0 = Do not invert prints
+ 1 = Invert prints
340-343NumCopies1 to 232 - 1
344-347Orientation0 = Do not rotate page
+ 1 = Rotate page counter-clockwise
+ 2 = Turn page upside down
+ 3 = Rotate page clockwise
348-351OutputFaceUp0 = Output face down
+ 1 = Output face up
352-359PageSizeWidth and length in points
360-363Separations0 = Print composite image
+ 1 = Print color separations
364-367TraySwitch0 = Do not change trays if selected tray is empty
+ 1 = Change trays if selected tray is empty
368-371Tumble0 = Do not rotate even pages when duplexing
+ 1 = Rotate even pages when duplexing
372-375cupsWidthWidth of page image in pixels
376-379cupsHeightHeight of page image in pixels
380-383cupsMediaTypeDriver-specific 0 to 232 - 1
384-387cupsBitsPerColor1, 2, 4, 8 bits
388-391cupsBitsPerPixel1 to 32 bits
392-395cupsBytesPerLine1 to 232 - 1 bytes
396-399cupsColorOrder0 = chunky pixels (CMYK CMYK CMYK)
+ 1 = banded pixels (CCC MMM YYY KKK)
+ 2 = planar pixels (CCC... MMM... YYY... KKK...)
400-403cupsColorSpace0 = white
+ 1 = RGB
+ 2 = RGBA
+ 3 = black
+ 4 = CMY
+ 5 = YMC
+ 6 = CMYK
+ 7 = YMCK
+ 8 = KCMY
+ 9 = KCMYcm
404-407cupsCompressionDriver-specific 0 to 232 - 1
408-411cupsRowCountDriver-specific 0 to 232 - 1
412-415cupsRowFeedDriver-specific 0 to 232 - 1
416-419cupsRowStepDriver-specific 0 to 232 - 1
+ +

The MIME type for CUPS Raster files is +application/vnd.cups-raster. + +

CUPS Raw Files

+ +

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 application/vnd.cups-raw. + +

Internet Printing Protocol

+ +

The Internet Printing Protocol and the CUPS extensions to it are +described in the CUPS Implementation of IPP document. + +

Line Printer Daemon Protocol

+ +

The Line Printer Daemon (LPD) protocol is described by +RFC 1179: Line Printer Daemon +Protocol. + +

The URI method name for LPD is "lpd". + +

Server Message Block Protocol

+ +

The Server Message Block (SMB) and related Common Internet File +System (CIFS) protocols are described at +http://anu.samba.org/cifs. + +

The URI method name for SMB is "smb". Support for this protocol is +provided via the SAMBA smbspool(1) program provided with +SAMBA 2.0.6 and higher. + +

Directories

+ +
+ +
/etc/cups +
The scheduler configuration and MIME files reside here. + +
/etc/cups/certs +
The authentication certificates reside here. + +
/etc/cups/interfaces +
System V interface scripts reside here. + +
/etc/cups/ppd +
This directory contains PPD files for each printer. + +
/usr/bin +
The cancel, lp, lpq, + lpr, lprm, and lpstat commands + reside here. + +
/usr/lib, /usr/lib32 +
The shared libraries (DSOs) reside here. + +
/usr/lib/cups/backend +
The backend filters reside here. + +
/usr/lib/cups/cgi-bin +
The CGI programs reside here. + +
/usr/lib/cups/daemon +
The polling and LPD daemons reside here. + +
/usr/lib/cups/filter +
The file filters reside here. + +
/usr/sbin +
The accept, cupsd, + lpadmin, lpc, and reject + commands reside here. + +
/usr/share/cups +
This is the root directory of the CUPS static data. + +
/usr/share/cups/charsets +
The character set files reside here. + +
/usr/share/cups/data +
The filter data files reside here. + +
/usr/share/cups/fonts +
The pstoraster font files reside here. + +
/usr/share/cups/model +
The sample PPD files reside here. + +
/usr/share/cups/pstoraster +
The pstoraster data files reside here. + +
/usr/share/doc/cups +
The scheduler documentation files reside here. + +
/var/log/cups +
The access_log, error_log, and + page_log files reside here. + +
/var/spool/cups +
This directory contains print job files. + +
+ + + + + diff --git a/doc/images/accept-jobs.gif b/doc/images/accept-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..9da7a0dce11b175dafc1f23c698367a584570a0a GIT binary patch literal 259 zc-jF20sQ_)Nk%v~VOana0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui09gPO z000Bf2)ZFdCCW*wy*O)0h6qc@3|ncQs5O8hV5D#?TZZ_~c#hUep#Q)OixH-;FljX}YJw1!H5r;IgHn-{ceE1IM+xKXBDiBI` zcVb9?iiL-PdK(0UYGZX*NR)z(YMGpLeI1O8h?b;&rJAUv6&|6FuBLpBR+Y4}f)yXF zjeDMCyk2Xwyk~X8!xbPzN1MwiPf*Rw(IqS{)2i1OJPSA3-Wl5=0m|Ry1uHG$4wB|a J9UmglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui089WB z000BO2)ZFdCCW*wy*L*#L|7m*Xk=-c!xsX^>ArAegl%l!*sKJ2?@Ovt=71qmjFp2D ziS!KsykVg^p-wGLqZQZC5UI**By8P^r(sEYY>qgjV>LUDPF}QfG5%b6z|Tx{e1b=I zgKZK75JgLYbdFVbYD<$glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui08#)H z000BY2)ZFdCCW*wy*OJkL|7m*Xk=-g)bNFXfxd7&8KEoRI7ur(?*En5D09FRDaXlS zxwIrJPt*X=BNn0(tX7G_o*J5Bw3#GBx!3ejyl!6IYK+4gDc9Hcb2guT*Z+Nea25}A zfp&*bOo)PejeuSg1Q14xj*o$tXqb3!On?|1Mo6HYnV_4dom&|lqiAiAtfY{Rs;Cwo zua{#H!Cg9(kD9$Hq+P^)gS@K+1M&9+zyoAKO7z`2>?5A CbZnvk literal 0 Hc-jL100001 diff --git a/doc/images/cancel-job.gif b/doc/images/cancel-job.gif new file mode 100644 index 0000000000000000000000000000000000000000..3cc1e23bc650c00b22adb435e40862516f3b9d66 GIT binary patch literal 248 zc-jH@00;j^Nk%v~VN(DU0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui08;=I z000BU2)ZFdCCW*wy*OVoL|7m*Xk=-g)$oOYfxd7|8KEoRcu6Zk?*Eq62y-YNfRrO~ zsTlxz%!m?Mm|CpKQX^V1N{+>e_ZyaGrsHZAOL1_;U#W5)SDWn@`n}ASJlz+o`iLgkro}5p{IMOgI%g~i4`6iMpj;6b!)U` yp15MVV3-jfLsY~vPEW?5W@?y9E literal 0 Hc-jL100001 diff --git a/doc/images/cancel-jobs.gif b/doc/images/cancel-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..2384b903c673223b776c21f76c2ea6a9ad5f9d14 GIT binary patch literal 255 zc-jH~0093-Nk%v~VOana0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui09gPO z000Bb2)ZFdCCW*wy*O)0h6qc@3|ncQs5O8hV5D#?TZZ_~c#hUep#Q)Oi-b8C55Wnt z$V?3YzGh^Zq*|;Ltf?Wb93@DjQVb>+w8}CyY&BaP-Sl+2tb^xx^!>ai+xZs{aaVYN zT5E-bfQEe=1P~W`XJ3ndW0aDNd3%!?9fO6ImYk%arj=P39vN+?h^VlKjd_2g6dxK# zZDL`Zlyt9IZoh0}LI6Zb%0N$0%g;J2F3{94JPS9~+8Ng&0m<9p1uHGy4v^x?9Umh0fMCo*G0Yee%mV_<007KaLI3~%EC2ui06G8^ z000A@2)ZFdCCW*wy^#zNmS+Pdj^s3SA7GShdl}#A&NQq9bUvdYcKiq3C}TH MbhQ>594QF^J97d~lmGw# literal 0 Hc-jL100001 diff --git a/doc/images/classes.gif b/doc/images/classes.gif new file mode 100644 index 0000000000000000000000000000000000000000..ace15df98035c8ff3e41036b0be59f2664f7d0d3 GIT binary patch literal 591 zc-jF^08~U*5-X9+fD*emQ%-t<0(_wQriGZ zZZazx6{;H!rfZ&NF^DjR%UP$gL12(v1z%TG%JvI>t<>1d$R6}E?QFaBuG=p#CYq`w ziZLKnI#?fMDjR}LReukMU5I;WPjg%#kve@k4n}f;gCRUfWn^cOf{Z>uD@%zdL!5^? zZErJON@0|Ace@NlyuZK^mQ+k1!FGr)XqH-AsBeLx4HT-7rY(4&t$Tq1JGN%5Vb2<> zecNi2Y_Y^HEYhh!)TfI?l!TXqlgPG)&Q*(hvyg$SQ4d$HfyWfAV+V3h%sVe{>bzsg*v?&fS|wvO z;ipJR`P$Vo+Q`t9b~&`r2nMgIIb~O{sU$>Hj3ZL$G-e2z&tV~XEGM?mG=|~0JOR9Q zx~ivQkCoAuorL9KVzjCZsL7LY2n_~8V(13pGyvmhOX_!0g^}SfQhCYc7E-lJ z<8mqB@6klgfj#Q`%u%b%(iC7vD_0O};S&#LvOb}>9YnB~>XIW%d3BaYhzM(>GRB~0 zFrl4c{!(`{Okt{tJ(sb!5}DI%@Dx;B@|5J*;qU$?8QeVQ>viyE2Cb&1&70FFgU_{d d<`(xg{4v$bVfLjbUglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0C4~m z000B^2)ZFdCCW*wy*TU5BN;-ljLguTXsWK!Ad-N=&UC#Rq-^heKjDgiZ%CxQOqhf6 zpjsA}N(=KcRSf{bB1XL0ms$%xn6?5ILsAra&K{R zg=>6igoRs;gNKWYhL0EzfOUzJlaZN%f|`6#nVX%Ak{1LJRI7)jq^+=nPMCqNuTZBJ zAD51=x2C|FW23#2oV1k!8Fs?K$B2}lVPl@I)fpjTvx?HOZlS)iQsdr=+{6|lNJXsd u?pIju#q#biG4$v7L_iBV`u{%ojR>#~purU`U<`Di>YzhZAnYwj002AUeve21 literal 0 Hc-jL100001 diff --git a/doc/images/continue.gif b/doc/images/continue.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff774adb348deca51456cc9934e33be9f9aea9a9 GIT binary patch literal 224 zc-jHr03ZKHNk%v~VMG8F0KxzO%*>g9reH#cF&J_Z17`vNW&l@_LI3~%EC2ui07L*3 z000B62)ZFdCCW*wy;zbV!urgRjbxb(9tap_>$V2SzI1KHN?`ANk&2ju@bDrQjJ?SK zpbJirC1{e;a9)NIqA-FrYLVdV7UQs1!bdN6oo1uamWP@0&brx0yc%C2K(2syf_r&| zg+pT&8*@)~hI@pOd>9-VP?C>>j$W7+9V3WOiEmnZVvmUy9zavABTG!KvKT2Vv$qmB a3p2Q`x*q|oy*nr>zz%=IB^w?4ZZ&};` literal 0 Hc-jL100001 diff --git a/doc/images/cups-block-diagram.gif b/doc/images/cups-block-diagram.gif new file mode 100644 index 0000000000000000000000000000000000000000..2fe505e44b91deeb805b568a4db3a0fb508b0805 GIT binary patch literal 11637 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 B-D3a% literal 0 Hc-jL100001 diff --git a/doc/images/cups-small.gif b/doc/images/cups-small.gif new file mode 100644 index 0000000000000000000000000000000000000000..6adb4a29ffbd6b806d8eed34fdad33f6138e8890 GIT binary patch literal 1266 zc-jH-1P%K~Nk%w1VQ2t*0P+9;%*@Q0nVDv0W-~K000030|NsC0|NsC0A^8LW000F5 zEC2ui0B8Vv073))Si0Q)Fv>}*y;P9RyZ>M)f&+k^&M>Z|5CEnF2ZGAp#DF#d?g_gf zMB^g>Geuovvm_`sy(66bkjl^nG{>zj(HFtg+CH;@**F8gro_jj zgj?4byer~)Nf456i8gNvL_|X0AKjZb>HiP(?JJY134<#O)`DciDjrm5wU?-9CnKXPnbDTvVa3|4f5K7S6B=AM! zSYIVh=MMvpL6%}^eK=5Ac<_z(R8;T0D3mP`7Qt9sGhSe$EOS+sTM)thaLtgUiD6_2 zhR`Sjh1$62wZ88{PYI*?4fc95P!hd?1I4wU9X6lPAS{=i&_ zo?VF1doqTGo^>DAmj)l0_Jo62Oos5|L@{Wf#B=Lafe9Y8?x1TS<83QJnBi<_-$QF~ zvqbn}J9Ra2PGl=fQ*CO_rXl%ZbOXykTl6(kKS27Gix4ug5I1RZMXO zBbFK{-Eb^oSCF{BD!VbP${lImYwjA1)NIC4D-y>1WqfmY9^86Ew$5hPT}r(E%AOU% zhC(C`+PyIFy&mz^)!zKG&baOq|v6_F*_C|4I;#4HBJ&n(8w@p2}RL(2}!DTz7 zIG=4kc*1vOOfO{;dR^(rrfcEDoT>YJgRMGB_C>cOroJw|OtX+}?8J8AwwtsUuK4Sw z5B0$9=>jZSq?PU7mVgl?>3n3RM_&Z&00rl%Ljuo*JnjL4`dgCQKS1hOMq(ehtE`8? zrH@~CI=#Aew*Nrz)z~kCpmbjemmzCuiKEn_sG606e}~$YGVqr`cF?JT*DDeP!%`*$ cc1nF?aZ~|iF+YF}&@50&%OUg^gaiNpJ5-EOApigX literal 0 Hc-jL100001 diff --git a/doc/images/delete-class.gif b/doc/images/delete-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..81b1465acdd35559182b55e5b98ade10bb0afcdf GIT binary patch literal 259 zc-jF20sQ_)Nk%v~VOana0KxzO%*>g9fM7yGF&G#U0|Np800384LI3~%EC2ui09gPO z000Bf2)ZFdCCW*wy*O)0h6qc@3|ncQs5O8hV5D#?TZZ_~c#hUep#Q)Oi)1+%jhX{S zX*x0sPu&3EyF{ZE>_ltbM!2)alJY!C%1CJ1ob7(o?=3ju7<-}TuYS)gw~Kptf_;G% z4|aKigMoyKT40ZbiWmeCZi!BfnS4%vo}F=La|IoUe1DOXo@9)ycPav=ey5JKs)d@E zv~wRzprW&CXm4}BXi9xoqaZ{<&dyU*&(lCGF4WjEJPSA3-W%H?0nOj#5-Tm@4wmNA J9Umg9fM7yGF&G#U0|Np800384LI3~%EC2ui0ABzU z000Bn2)ZFdCCW*wy*O)3h6qc@3|ncQXgPo)V5D#?mxlPxc#hXfp#MM=i)1+%jhX{S zxj7;$%%W@n@Li$>EOc4IYLl}DcM?5H%1?9lN%2OM@b~(iX2&m%@mbDimiv2cWORLg zfQ1Ybh&DCpHjZOgv*f^AVfjc))Z7#*W1@DF5KWcJPSAB<|yMK0o3R1 R7Ar044xH}h9Um|NkNW4ozWXWgvHHbZ8()Nlj1yEC2ui00031 z0RRI2jE||y?GK}zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4K zDwoWr^9hYgr_`$Tip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VM zSZH{Nn5ekO*y#8O87VnQS!sERnW?$S+3EQS8Y((UT55WVnyR|W+UoiW8!J0YTWfoZ z+W?T;1mMf7BmGNVZH=8Ry}e_7?TrH-E?z@kZZ3m9 ztq#Nf?EV5C&@Ioht6gt@kMirBfM357&*B9HIFQ7$eGCL9{NQjw#D^K^Jh?ofCY<;rVU zmR-@ecA?_j>oROZt$_CtMru}U+Q4`V&;09Guw%q}88@Cxd9hW=nA`R}xVE!r%bzhD z{zuj+=fd_LGi*M<<1Jrg z9bM+0O};_bTX;Ghh+ka76(^v7H$6z)gRxP#8gdSDHl2k`NoL(^&h52ah{Z{$TRY`F zMxZ+!%7$KaE&c}-ds)o~4S)SDrV@_%eRpDy^`W?pctL{L6p{29x#NiPsi@$JGS2uU zl|{Zc+f@xFCuEmS1{o!iNqXobGE0%ArIOSD*koTG{`97oR(|-Uh_z{WSDZtZ8K#<5 z(l#eWhso)upn5uoXP)y-^=4N%u9c{ZWI|f!gq7~dqG@1~HkhV%TG^;=7KSQng?x&Z zA*rQ087XU_sj4ZXr+T{Qtg)WNrl%27wWY2{_Udb!um=03i*LUA z?#pk#{{9Pazyc3UaKQ#2jBvsVFU)Ym4nGWW#1ch0fMCo*G0Yee%mV_<007KaLI3~%EC2ui07U>4 z000BA2)ZFdCCW*wy?Bx#!urgRjbu3v9tap_>$(QWzI1)XN?`ANl!}%EMR*}jj6n?Y zG63j`LuF+dg_0W5qvXKdZiQ5BglhzcC627OP#(M4=XV?awmg(%a-GOuTjz5Y1Q1qh zfO{Eza()#XYKxG8eu`{}OahOUnwpATRh)*D6&;yno||1^dS7j)79K!7vMx?47M_YOT literal 0 Hc-jL100001 diff --git a/doc/images/left.gif b/doc/images/left.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd7b0410439bdc234c3e56e5c41308dd2834437f GIT binary patch literal 110 zc-jGO0FnPkNk%v~VGsZq0KxzO%*>g@#F4YJfTpH%o}O!&nP#i2c(=ENEC2ui01yBe z0009!2)Yn5q)5q{nV7DV`x2c8aADSz-i2bpnt|>##8X7yIA+uH4b!a~KovXD6eQQD QxKT0!L{Y^7$s_;(JJ*UWq5uE@ literal 0 Hc-jL100001 diff --git a/doc/images/logo.gif b/doc/images/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..9999795caa725187141a472f5dd1109491286b8c GIT binary patch literal 1958 zc-jG`2U++>Nk%v~VMhQc0QCR>@bK{O@9&O|j*E+not>SVo14DAzPr1-mX?;3l$2gx zURqjOYHDg`W@dJFc5`!c2?+@W1qIX7)6me+&CSiq%F3*)tf{G~!^6YCz`*P4>+0(2 zqobpsprGaD<>ch#`T6aBzr-i0J6(DJdx+ARyr2;N0BY;^N|_rl!cq$W>KU^z`&HGBUBT zu>b%7EC2ui07n2Q07VA=z+G-gEOL%WWM|22b_md@lu)Qz3#+VFi|Be0iEudO3V}lC z$#2d6q1ZbBY~4HjZnj@Wv*~YUe;$H@AB7$tHaLhjjEyHZCnqSA5)%}b4GsXC0c~s| zeHtX5EHfwq0~{V45DWu93MB(L0|_<)IvFi8J|_YtEfNGRE)~WVIvC2z2F(W~3J)59 zeKXdBGan9gJug2HjSb=rEEtfI5|tB{6vrt&${88W2G1lV1V0=;{1z4$7l!PJL1@vU zMvQJKjC3O1oC_4%=|Hv&1HA*!o|P!U&xgN{L^yO1`Gg9W1Y|&{T*(rRO8`80Y?8UD zW&i*I0%*{wQ-l6bKGv?y7*r4k4n{{CK{|(mfrAh+L*Q6L0N@ZCb7cIG;3L8h7kzsC z(BR=3whxC6B~64-;W>2bA|9iNArsF48+_*VV~v1UHUd7V_#q;K3akQbL>OV?0xSs; z7QA_|4Z(;M6f*o!u_HnT4D&KzBte>E#|00DnmvT}gHfbwZA9`)VG;wv5n52#WcbS@o=xDt^i`z)^>>3gOZQUL`zB(qF2SmN~IPDtX_hYP>;;Q==@OqD8^!NLzUm_P#!6+l3P06(;Fn|=`-zzPX9&``n; z{txW%f(0tnV8I9rxF^y;s->ysQL(uN3Ab&$@Yx08`EUei_;gS}4kd7aKn^DGvw{FC z{4>A+IjkUq3-Jy>tw(H1G-jZku&xLYuY~-{1Xxr@MYnJ2{;ST zu~OVcVygtWB16}mp=t!IN5cjrFG*0WfQ1+d*eCVG7t5f6g%@UxVN3u52vtoV+5{q! zd|6YbiT1JvGC~zfl8H-DneYSt4V!%J z04^}d(7_KFRN&Jc3-qucAWHTPVNxruK8daC$oV==JVeX+4*|q*2Lvf>0D}S>)Bpnu z#vZ#Q$Sc0(Gs)}-olKrJ*#QHA1@2@w-hjZ+f(L<+p5|*#Lg}U?l&F$ijPWT9UQ>hflHDp-bRo|?44?o_i0wdp%F7HE*n(ZG zfdnvMK#eeP8yB=7H-O4RaehF72)IB5Fn|mUdLRP`JOBnFNLf5aI2vd;ASXNF$zJ}@ zhZ=lC6%KmA0uJ#58|>gP5U7C-p!0$gydVNP^4AM?aGMEW;0FmP&8PlCMFOMwpoBe1 z5ZS0Ghz-2sFDmeW3PjKW8%#h17Vx47Y+!&9VBiEJNQVPPP=FD%Km;wQ69+~h0us=} zSLZpJM^Mv~891&%R%8KdTqOfG&B`scq7pkOFn}G@X^9uX$kATr1Ay${0ehLCYKBq> zE3%;lY{`cw79fG|rCgU;zpkK@b1{JDeydnE(I) literal 0 Hc-jL100001 diff --git a/doc/images/manage-classes.gif b/doc/images/manage-classes.gif new file mode 100644 index 0000000000000000000000000000000000000000..69d5b0147068125faa07a4a84266a6d81aa269fc GIT binary patch literal 289 zc-jFW0p9*cNk%v~VQ>Hx0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0B`^l z000B-2)ZFdCCW*wy*TU53mHPNjLguTXsWKoAd-N=&UCFBq-^heFX4)SZ%CZIOqN5k zxH&kL5h$}V00=KmN_L8!K&9MC1GANspXNeYz0OL}6|mRb2G{L!ii509f75JHf`eaw zgL6xLgo}!Aj1~`kj(LWPh>n(&U0R2onVuE|5SvPsPo{KRn5UYFY-f0>uo)kGeTJ)m zxsR@#pNP7)kOIQHjlqnnfWFDdxQEXdA;rsRrPXdx*V=iq*xPkp;TR%FVZG-yRaWWM n?K>|q@2~SUKnptc`YZP%0p|MxW^e(+pMy~X1%3ztBLM(A>uiRu literal 0 Hc-jL100001 diff --git a/doc/images/manage-jobs.gif b/doc/images/manage-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..adaff856f0929ebe37519e68994a60a767490353 GIT binary patch literal 266 zc-jF90rmbzNk%v~VP60g0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0ABzU z000Bm2)ZFdCCW*wy*O)3h6qc@3|ncQXgPo)V5D#?mxlPxc#hXfp#MM=i)1+zgD~So zi5dWWOJ?LCMV6`)Y^i~vQoK`e!6+V=y-cb$D^a)2*>%Lx9lw?7@O00|s;R7(t)h(<9)X*+o~vM! zv9P(V6(6*^Zm6TfdTF4XQkr&WkRU`>SJF*A)WO##EH2qa$=ww^3pe29CgLFh(dO(F QD=p~`mhIggA1w(0J8!smBLDyZ literal 0 Hc-jL100001 diff --git a/doc/images/manage-printers.gif b/doc/images/manage-printers.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd897291dd439440a3c86a2b66cb8ebd6774878e GIT binary patch literal 296 zc-jFd0oVRVNk%v~VQv5v0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0B!&j z000B^2)ZFdCCW*wy*TT=$q>OJG6QFxXsS{}I0D8h&$Mieajow>bt{3Ma7c5NEC(b} zb7(e|m!xh02u7un=MsZ0bT{8wgZtHb%}MjQ`@}k-5oy{RKgYH2x;#8_aOrw=f_Q>} zdxc?acY|_+S&N1k4}Wfe6ODzBmY9}VPL+V0k^;fQk)g|kna{49%(KuEAjz6*yV-AtZfe=F(~z)id=eo?TN&r; uGE`OW#o_Wr3pw?#`8q%M`~N%oi3p$$pg|KYUJP__>Yzgj9zeWE0028T9*5-s literal 0 Hc-jL100001 diff --git a/doc/images/modify-class.gif b/doc/images/modify-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..58a0ead8297209371b80fcbfd0ca3cfc7513fee7 GIT binary patch literal 267 zc-jFA0rdVyNk%v~VOszc0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui09ybQ z000Bn2)ZFdCCW*wy*O)1h6qc@3|ncQC^mp1V5D#?V}|(7cn;S}p#Q)Pi)1+zOU6P{ zxy&4%%Vur>@Lir1>_#fZG?QIi!^@3oBUmug7_Eer66oa2%s9MobiTb;@8fP)dV_v` z77uuBhKq!Qd2@nUj*}Mz5Rq(+ntz;OZ)Rt7bQK+VaD{-6sCu55sjrk19;T{}g{!BL zntZEo1s}A0Yjc^LvBaTqX=q=*1t3I0Thb|1Rn!{J*cB`;+ehCeJPSAB<|gAI0nz8} R6e}(24wvrV9UmglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0AThCh_ApzO&_8KcK^A4i-{v97$Bme+At6qKs literal 0 Hc-jL100001 diff --git a/doc/images/navbar.gif b/doc/images/navbar.gif new file mode 100644 index 0000000000000000000000000000000000000000..c19f634c0d3278ff58e20c19eafe9136c8bbd5e4 GIT binary patch literal 2869 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 Tn1e`|gi81agHQ-67z6-28w6=Z literal 0 Hc-jL100001 diff --git a/doc/images/navbar.xcf.gz b/doc/images/navbar.xcf.gz new file mode 100644 index 0000000000000000000000000000000000000000..28438a6bb82303522c41ea5b3ce198a9de9a23bb GIT binary patch literal 4253 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 literal 0 Hc-jL100001 diff --git a/doc/images/print-test-page.gif b/doc/images/print-test-page.gif new file mode 100644 index 0000000000000000000000000000000000000000..807dca10e6c69e9e2eb439a00057365f748df68b GIT binary patch literal 288 zc-jFV0pI>dNk%v~VP^mo0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0A~Oc z000B+2)ZFdCCW*wy*TSl$q>OJG6QFxXo?Qu2pDQCuObgu7_tpvQFP}M3~4oKt? zbD$)jrlu1*8~}h9X++E6PP`j17p!YAzuQ7nx@IdY-sIOEM{nPEwM33_ocDQpYHVps zfQ5vDc8G^=g^CpqOjL@Af@F|dmXCXscAAfv1q2XThL??|oqU6bi&Jl)gRB)Ee@>~4 zr;xb3zLlYz7$3KbmYc7#iDIYA$9-74uFtJ-uydWga7vDvcorc>L*q1}kw4_=D6$+a mFY54N-x@v(IPv&2^&$b{`TrbPxZvlY6u^TKJb-YK0027`?SZ-g literal 0 Hc-jL100001 diff --git a/doc/images/printer-idle.gif b/doc/images/printer-idle.gif new file mode 100644 index 0000000000000000000000000000000000000000..68d990c628dedbf4326390527ef72f2e90aa9841 GIT binary patch literal 706 zc-jHN0zLglNk%w1VOjuC0P+9;0RI40RaM~N;Hs*s0001gk-vYDzkiXxA^8LW000F5 zEC2ui09pW0073))Si0Q)Fv>}*y^CnUxh7pGd<14vpEz!6>%QY4&ve>uB}(tM*u$=0 zh~*0aj!0x6HzDkv(CC0T1OcxjAXDO$YNXGu%!(~jZg(+7?vyLqy7<$y%2h8}_!c5O1#O@a zR!WRP_!jAB`?Z9$cdG_4C31H(A zdizN3T)OVI;oZx(uiw9b{pt&>?ju3M1^W$@co=a3AuVIfv^w~$y{pB-h-^IRve9Bg zZG=2w@aN}0nh$QUqw#^j(+Ej~1F`Ce!zK{J!PXLzHp!B$F;!J<`YG|1zggYpvXeMA z%FvQ4S$-^KZ{23iki0V_sP*gF|CtQpooYbnMxmBBKcy4M-C5$iA{&z@e5CS~(%)GY zwuySBIn~$SY5(E223JIZ}*wI++r^T@^^jv{DWCws3gD8=aCR3G_lbf6jnVq1aqNAh{ODr@msT`{UV~RXa zb|9cdbtSI`sH!zhz8kV)B833O#aR`3i#xZty1;+Jjb~JacFD}j%SVjU-XDP2+p*dK zeBV&f;AMi7hp^*EQtE!0h@tlH+VmOukfogbDLI z6u`|b))n)fk!G4+fU%3!vgav2879Rp@fd}_GxTc(nAWJ z9e*AbdbDXnrc(x{OOD=pkAS@z@ztpvHjzaIt{&cubs z;yQA&y$zTrab7GZzJxB>Y%X@P*KC&P^ZNDKs^mw4WnkgPw59do|` ztnAKQ#LZWp6HV1LR8dE*F%mz^4M-q^n;i&Mf~G9fl!MTf#EyhSwRaa<3^J7lTTdNh z%^4piRp5wfVPaQVUP*`CTtSe9RE%Jlg9c&fOqWb|IHpA-J2omv4vx(1HDrx+q^Kia zN-pVFlQ8DEjgV3<=3|v_eHCSoe{6XpUdmwk4OX+H0HlgZ#&RZ!b+tnql6tx62V<3$ zl0{-@Y51l+0YS26pFx3HS_PT$Ne-T&dFD=JS87$6WqL+-)>fQRijZYxrqk$Zi86!B jr?YWNDsBxl`U$Fts>&*41HCGWVY1e0>#evxlmGxb6oz`@ literal 0 Hc-jL100001 diff --git a/doc/images/printer-stopped.gif b/doc/images/printer-stopped.gif new file mode 100644 index 0000000000000000000000000000000000000000..76f45649b132bde80d5a90530f0cf990aa4f5278 GIT binary patch literal 794 zc-jFP1LgcjNk%w1VOjuC0P+9;;Nak@s;d70099300001gk-vYDzkiXxA^8LW000F5 zEC2ui09pW0073))Si0Q)Fv>}*y^LtUxh7o*d<14vpEz!6>%LuB}(tM*u$=0 zh~*myj!5JnHzDkv&}e`-1OcxjAXDO$YNXGu%!(}weV8v8{Hb9z$++MQBS{AMyne4< zPg!tsf`dqaWG`DLdy9O1et%1cW{D@23XFLUVl$E}mY<-ZqN56DR9c&K9d@8jryiYU zvOce{9C&d{6`PNLh*qjAvjj$XH@joJy)|yLZ(7L9e^IH1F zLyI0wx-^8frUUk5m6{($lP6iX&TwkxP?)kaCyX2}-JSFs9tCLZ!0u1?hk zx4T9zA5O7W3S386j!j09Ix3mZRpw$`N+@{m&Z!V1q&>o0?%loOjx9b{`_quYOaEm? zeBmB*TIHu7fAQF47gS^=HD6Vck>^l?Vfa!Pbqz-Mo=eSm=fP9kC6i!R8dex!Qr>`w z9*6ENg&|ewfq>OPD^Oa}{c(S6uiji|^0mQ_G<_92nSAtu+6 z!Xz0%BoKbnq+e+5r`BDI%qXK(Sk8qNLTowarFngYDGoeAaEaH2Q@|I9nu$$_A_SFr zxno678s`-Tl`Rn=T!+QMrhK8~IpiZ692QAY4l0u8RvAT_sG=?*I$EIbHE3x=j+G)2 YPqX2ntm^8kuqFTiJFzuv761SM literal 0 Hc-jL100001 diff --git a/doc/images/reject-jobs.gif b/doc/images/reject-jobs.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d938e308475bdc9862421d2d21653ff105b4b3a GIT binary patch literal 252 zc-jH{00aL=Nk%v~VN?JV0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui08{`J z000BY2)ZFdCCW*wy*OhsL|7m*Xk=-g*6@XZfxd8D8KEoRxJfHP?*Et7$Z{waGY3=> zvn0X>fZnB9pyI3)tVBy{Fegppc6%f*#Z&XR9AR4=-*HubrrYD;c74uIL8eA|ZG(M# zU`T{~f?N{>e@=;kdy?5_ CZED;A literal 0 Hc-jL100001 diff --git a/doc/images/release-job.gif b/doc/images/release-job.gif new file mode 100644 index 0000000000000000000000000000000000000000..a05cd9cc7178499b395e08d26165b3e4a55adabe GIT binary patch literal 255 zc-jH~0093-Nk%v~VORhZ0KxzO%*>g9xnM%6F&Li`1DOH0N=$Kp;oL*3U;!!G@4w=Q7lH5t>$WadM2+c4lubub=v3ks-8Y)^Y><55f4pA zd4PL=VTy@@h>wgE1Q33ThIe#^XLX!oa)*Z&9deL(SAC_YkeHDZ9;APujkB?|i?x8P za8gCLo|bE4c4%*H#(c#SAVgWsIZ#o~(labB)7LvT*xML9A_2_Y+bb<04TR!Z9UmglrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui08s!G z000BV2)ZFdCCW*wy*O7gL|7m*Xk=-g)9{6Wfxd7o8KEoRxJD~M?*Ek4$Z{waQHN3z zvm}xRfZnB9plYns3|6wOG?$}%f0%g-h|3pUWz71AI9#MaO%EZGi_+&&y0EC~QRoy%)n literal 0 Hc-jL100001 diff --git a/doc/images/right.gif b/doc/images/right.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ae8213ceaa55668ad026fb2b09254c96ab59dfa GIT binary patch literal 145 zc-nLKbhEHb6kw2Gc+9|X=FH3^M<#CG+^}p}@w|E2GiRo)UR|+$dkc_(6)FB?VdP@q zV9;Rz0+1ODEOr|_Jli-FvJG~d+<4a8Zc)`#HtD8S(z^75Lh&ne8~hLZ{XFpC{PoW- eYqsCz@mxK1*18bwZ*%53NM|f8I+>=#U=0BM(LkI4 literal 0 Hc-jL100001 diff --git a/doc/images/show-active.gif b/doc/images/show-active.gif new file mode 100644 index 0000000000000000000000000000000000000000..d232ef9f84342b411b132828eb6cdff279469b68 GIT binary patch literal 303 zc-jFk0nq+ONk%v~VR!%(0KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0C)ft z000C02)ZFdCCW*wy*TU5F&RRzjLguTXsWK*Ad-N=&U9@@1}Wcs?^`)V;72U-UZ%@o zd5|=H&&)GAqf)G#0br<{OrZtrwI`00H4Tiox%9Tf&Ul4=eKXNk%v~VUGY50KxzO%*>glrgMjfRC01ZXJ<5KW;2nIUjP69EC2ui0FM9^ z000C22)ZFdCCW*wy*TU5yO+cu1WU;bU#hNb%MPRo7;bIfxM!Gj?*Bm7P7w$ik4Q`m zbvZZ>5@_xzwN)!uOqQ~Zss?~!b0Y1suI5xaP0p-W4Xp+0B-aboJXd?i`~QA@d3R3{ zg;8{Fh8$+~jPmYWzM&9A(uiCbp0$Hv5fxY)PUlBojI)xx{knA*z2 z?#AHaqwf_Xk*w*B&sc|}?19hv5z?249~xE!Gmv1CBnX>^Ho$~|=#Zk37&9#Tc&Hyy j#gGL(I*J@=;bVya3`wfA2t&q62ftRz^bul&j06BXGu)o0 literal 0 Hc-jL100001 diff --git a/doc/images/start-class.gif b/doc/images/start-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..2b6f43fad34cf9d50e46ca384a87ba7df433d834 GIT binary patch literal 238 zc-jH(01^L3Nk%v~VNL)P0KxzO%*>g9reH#cF&J_Z17`vNW&l@_LI3~%EC2ui08RiD z000BK2)ZFdCCW*wy*NuUL|7m*Xk=-g#qfoIfxd8Tgl=r#+N=b4?^CPMUZuY#1D0c8r05cbQa$7af*)oPV04j;4DR9&bfQRbfVwcddc2bgmg6 oLR`EtP*J_XFDos=#yK>{$`m>w0lUk=Dl8xkebG1^9xMp}JCE94=l}o! literal 0 Hc-jL100001 diff --git a/doc/images/start-printer.gif b/doc/images/start-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..017bb394aa59c23ee9b7b7058a49ad34c62840f9 GIT binary patch literal 255 zc-jH~0093-Nk%v~VN?JV0KxzO%*>g9xnM%6F&Li`1DOH6HT2X1t~bMr+JEvxO!Xn{FqM=W_b&#yGyxH`0t=@8^ASfq!%< z5E^u3eQjK7i+Y2Mj9?N3hf0rfONvp1o^zTS9Aj*dlYeY}r;(f(9i*R|kDauutFn?8 z9(ajwPH;$hPoI;%xELQpK+8W=Rm{*iD=pF0FFOl1*4r4^AOXtU;wmiP4wvFU93CtQ F06SU!YOeqQ literal 0 Hc-jL100001 diff --git a/doc/images/stop-class.gif b/doc/images/stop-class.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cb7adfd808058a01d565fc69abd5c96e0114cc3 GIT binary patch literal 245 zc-jH=01E#{Nk%v~VNL)P0KxzO%*>h0fMCo*G0Yee%mV_<007KaLI3~%EC2ui08RiD z000BR2)ZFdCCW*wy*NuUL|7m*Xk=-g#qfoIfxd8Tgl=r#+N=b4?^CPM*Ndr@55+lW<*U|+azvpRL;>e)IOgOr`#+u`JyX8T8>;DyXfp>5j z1P~>5OMn!DU}2AHhC*ahcZ-B{Qh1z%o)jHimU(h|qnDYeq!%7;kYiq$Z-K9iUsP9X v5g(L2x>+PoP+7mg87nP6#l{vo3pLEq7|tL8z0%SuEY%K(*ghN{EC~QRBm`$i literal 0 Hc-jL100001 diff --git a/doc/images/stop-printer.gif b/doc/images/stop-printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..b3accf3dfb2a3157d04b30385e2b0e11e6b0cb20 GIT binary patch literal 252 zc-jH{00aL=Nk%v~VN?JV0KxzO%*>h0fMCo*G0Yee%mV_<007KaLI3~%EC2ui08{`J z000BY2)ZFdCCW*wy*OhsL|7m*Xk=-g*6@XZfxd8D8KEoRxJfHP?*Et7=yE6?B*&Ps zXh}9@13-^BNjhKGD@luLV7SIeSX^LMvgD(+Y&DO|@QWj3Mw0LDb5*=%?4* CJ!;zk literal 0 Hc-jL100001 diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000000..051abb5b8f --- /dev/null +++ b/doc/index.html @@ -0,0 +1,36 @@ + + + Common UNIX Printing System + + + Easy Software Products Home Page + Do Administration Tasks + Manage Printer Classes Status + On-Line Help + Manage Jobs + Manage Printers + Download the Current CUPS Software + + + + +
+Common UNIX Printing System +
+ +

Do Administration Tasks

+

Manage Printer Classes

+

On-Line Help

+

Manage Jobs

+

Manage Printers

+

Download the Current CUPS Software

+ +
+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property of Easy Software +Products. CUPS is copyright 1997-2002 by Easy Software Products, +All Rights Reserved. + + + diff --git a/doc/ipp.html b/doc/ipp.html new file mode 100644 index 0000000000..3136c0dd3e --- /dev/null +++ b/doc/ipp.html @@ -0,0 +1,1552 @@ + + + +CUPS Implementation of IPP + + + + + + + +


+

CUPS Implementation of IPP


+CUPS-IPP-1.1
+Easy Software Products
+Copyright 1997-2002 All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Overview + +4 Operations + +5 Attributes + +A Glossary + +
+

1 Scope

+

1.1 Identification

+

This document provides an overview of the Internet Printing Protocol + ("IPP") version 1.1 as implemented in the Common UNIX Printing System + ("CUPS") version 1.1.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+

1.3 Document Overview

+

This document is organized into the following sections:

+ +

2 References

+

2.1 CUPS Documentation

+

The following CUPS documentation is referenced by this document:

+
    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.1: CUPS Software Security Report
  • +
  • CUPS-STP-1.1: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.1: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

The following non-CUPS documents are referenced by this document:

+ +

3 Overview

+

CUPS 1.1 implements IPP/1.1 and the operations and attributes defined + in the "IPP: Job and Printer Set Operations", "IPP/1.1: Output-bin + Attribute Extension", and "IPP/1.1: finishings 'fold',' trim', and + 'bale' attribute values extension" specifications.

+

CUPS also provides 13 new operations and many new attributes to + support multiple IPP printers and printer classes on a single host.

+

3.1 IPP URIs

+

CUPS supports both the "http" and "ipp" methods. The following + resource names are used:

+
+
method://hostname:port/
+
Can be used for all "get" operations.
+
method://hostname:port/admin
+
Used for all administrative operations.
+
method://hostname:port/classes/name
+
Specifies a printer class.
+
method://hostname:port/jobs/id
+
Specifies a job.
+
method://hostname:port/printers/name
+
Specifies a printer.
+
+

So a typical printer URI would be + "ipp://foo.bar.com/printers/LaserJet".

+

In addition, the CUPS server also supports normal browser access to + "method://hostname:port/admin/", "method://hostname:port/classes/", + "method://hostname:port/jobs/", and "method://hostname:port/printers/" + to view and manage resources on the server dynamically.

+

3.2 CUPS IPP Operations

+

CUPS provides 13 extension operations in addition to most of the + standard IPP and registered extension operations: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operation NameCUPS +CodeBrief Description
Print-Job1.0 +0x0002Print a file.
Validate-Job1.0 +0x0004Validate job attributes.
Create-Job1.1 +0x0005Create a print job.
Send-Document1.1 +0x0006Send a file for a print job.
Cancel-Job1.0 +0x0008Cancel a print job.
Get-Job-Attributes1.0 +0x0009Get job attributes.
Get-Jobs1.0 +0x000AGet all jobs.
Get-Printer-Attributes1.00x000BGet printer attributes.
Hold-Job1.1 +0x000CHold a job for printing.
Release-Job1.1 +0x000DRelease a job for printing.
Pause-Printer1.0 +0x0010Pause printing on a printer.
Resume-Printer1.0 +0x0011Resume printing on a printer.
Purge-Jobs1.0 +0x0012Purge all jobs.
Set-Job-Attributes1.1 +0x0014Set attributes for a pending or held job.
CUPS-Get-Default1.0 +0x4001Get the default destination.
CUPS-Get-Printers1.0 +0x4002Get all of the available printers.
CUPS-Add-Modify-Printer1.00x4003Add or modify a printer.
CUPS-Delete-Printer1.00x4004Delete a printer.
CUPS-Get-Classes1.0 +0x4005Get all of the available printer classes.
CUPS-Add-Modify-Class1.00x4006Add or modify a printer class.
CUPS-Delete-Class1.0 +0x4007Delete a printer class.
CUPS-Accept-Jobs1.0 +0x4008Accept jobs on a printer or printer class.
CUPS-Reject-Jobs1.0 +0x4009Reject jobs on a printer or printer class.
CUPS-Set-Default1.0 +0x400ASet the default destination.
CUPS-Get-Devices1.1 +0x400BGet all of the available devices.
CUPS-Get-PPDs1.1 +0x400CGet all of the available PPDs.
CUPS-Move-Job1.1 +0x400DMove a job to a different printer.
+
+

+

4 Operations

+

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.

+

4.1 Print-Job Operation

+

The Print-Job operation (0x0002) prints a file.

+

4.1.1 Print-Job Request

+

The following groups of attributes are supplied as part of the + Print-Job request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-billing" (text(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a billing string that is logged with + the page accounting information.

    +

    "job-sheets" (1setof type3 keyword | name(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies one or two banner pages that are + printed before and after any files in the print job. The name of "none" + is reserved to indicate that no banner page should be printed. If the + client does not specify this attribute then the value of the + "job-sheets-default" printer object attribute is used.

    +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value.

    +

    "media" (1setof type3 keyword | name(MAX)):

    +

    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 + "media-default" printer object attribute is used.

    +

    Note: Standard IPP only allows specification of a single media + attribute value.

    +

    Other Job Template Attributes

    +
+

The Print-Job request is followed by a file to be printed.

+

4.1.2 Print-Job Response

+

The following groups of attributes are send as part of the Print-Job + Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

Group 2: Job Attributes

+
    +

    Standard Job Attributes

    +
+

4.2 Create-Job Operation

+

The Create-Job operation (0x0005) creates a new, empty print job.

+

4.2.1 Create-Job Request

+

The following groups of attributes are supplied as part of the + Create-Job request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-billing" (text(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a billing string that is logged with + the page accounting information.

    +

    "job-sheets" (1setof type3 keyword | name(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies one or two banner pages that are + printed before and after any files in the print job. The name of "none" + is reserved to indicate that no banner page should be printed. If the + client does not specify this attribute then the value of the + "job-sheets-default" printer object attribute is used.

    +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value.

    +

    "media" (1setof type3 keyword | name(MAX)):

    +

    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 + "media-default" printer object attribute is used.

    +

    Note: Standard IPP only allows specification of a single media + attribute value.

    +

    Standard Job Template Attributes

    +
+

4.2.2 Create-Job Response

+

The following groups of attributes are send as part of the Create-Job + Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

Group 2: Job Attributes

+
    +

    Standard Job Attributes

    +
+

4.3 Set-Job-Attributes Operation

+

The Set-Job-Attributes operation (0x0014) changes the attributes of + an active (not completed) job.

+

4.3.1 Set-Job-Attributes Request

+

The following groups of attributes are supplied as part of the + Set-Job-Attributes request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri) and "job-id" (integer)

    +

    OR

    +

    "job-uri":

    +

    The client MUST supply a URI for the specified printer and a job ID + number, or the job URI.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-sheets" (1setof type3 keyword | name(MAX)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies one or two banner pages that are + printed before and after any files in the print job. The name of "none" + is reserved to indicate that no banner page should be printed. If the + client does not specify this attribute then the value of the + "job-sheets-default" printer object attribute is used.

    +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value.

    +

    "media" (1setof type3 keyword | name(MAX)):

    +

    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 + "media-default" printer object attribute is used.

    +

    Note: Standard IPP only allows specification of a single media + attribute value.

    +

    Other Job Template Attributes

    +
+

4.3.2 Set-Job-Attributes Response

+

The following groups of attributes are send as part of the + Set-Job-Attributes Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.4 CUPS-Get-Default Operation

+

The CUPS-Get-Default operation (0x4001) returns the default printer + URI and attributes.

+

4.4.1 CUPS-Get-Default Request

+

The following groups of attributes are supplied as part of the + CUPS-Get-Default request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "requested-attributes" (1setOf keyword) :

    +

    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'.

    +
+

4.4.2 CUPS-Get-Default Response

+

The following groups of attributes are send as part of the + CUPS-Get-Default Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

Group 2: Printer Object Attributes

+
    +

    The set of requested attributes and their current values.

    +
+

4.5 CUPS-Get-Printers Operation

+

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.

+

4.5.1 CUPS-Get-Printers Request

+

The following groups of attributes are supplied as part of the + CUPS-Get-Printers request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute limiting the number of + printers that are returned.

    +

    "printer-info" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to select which + printers are returned.

    +

    "printer-location" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to select which + printers are returned.

    +

    "printer-type" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type enumeration to select + which printers are returned.

    +

    "printer-type-mask" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type mask enumeration to + select which bits are used in the "printer-type" attribute.

    +

    "requested-attributes" (1setOf keyword) :

    +

    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'.

    +
+

4.5.2 CUPS-Get-Printers Response

+

The following groups of attributes are send as part of the + CUPS-Get-Printers Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

Group 2: Printer Object Attributes

+
    +

    The set of requested attributes and their current values for each + printer.

    +
+

4.6 CUPS-Add-Modify-Printer Operation

+

The CUPS-Add-Modify-Printer operation (0x4003) adds a new printer or + modifies an existing printer on the system. +

+ + +
Note: +

This operation requires administrative priviledges and must be POSTed + to "/admin/". POSTs to other paths will result in a + client-error-not-authorized (IPP_NOT_AUTHORIZED) error.

+
+
+

+

4.6.1 CUPS-Add-Modify-Printer Request

+

The following groups of attributes are supplied as part of the + CUPS-Add-Modify-Printer request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer.

    +
+

Group 2: Printer Object Attributes

+
    +

    "banner-end-default" (name(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a banner page name that is printed + after files in a job. The reserved name "none" is used to specify that + no banner page should be printed.

    +

    "banner-start-default" (name(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a banner page name that is printed + before files in a job. The reserved name "none" is used to specify that + no banner page should be printed.

    +

    "device-uri" (uri):

    +

    The client OPTIONALLY supplies a device URI for the specified + printer.

    +

    "ppd-name" (name(127)):

    +

    The client OPTIONALLY supplies a PPD name for the specified printer.

    +

    "printer-is-accepting-jobs" (boolean):

    +

    The client OPTIONALLY supplies this boolean attribute indicating + whether or not the printer object should accept new jobs.

    +

    "printer-info" (text(127)):

    +

    The client OPTIONALLY supplies this attribute indicating the printer + information string.

    +

    "printer-location" (text(127)):

    +

    The client OPTIONALLY supplies this attribute indicating a textual + location of the printer.

    +

    "printer-more-info" (uri):

    +

    The client OPTIONALLY supplies this attribute indicating a URI for + additional printer information.

    +

    "printer-state" (type2 enum):

    +

    The client OPTIONALLY supplies this attribute indicating the + initial/current state of the printer. Only the "idle" and "stopped" + enumerations are recognized.

    +

    "printer-state-message" (text(MAX)):

    +

    The client OPTIONALLY supplies this attribute indicating a textual + reason for the current printer state.

    +

    "requesting-user-name-allowed" (1setof name(127) | delete)

    +

    OR

    +

    "requesting-user-name-denied" (1setof name(127) | delete):

    +

    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.

    +
+

The CUPS-Add-Modify-Printer request can optionally be followed by a + PPD file or System V interface script to be used for the printer. The + "ppd-name" attribute overrides any file that is attached to the end of + the request with a local CUPS PPD file.

+

4.6.2 CUPS-Add-Modify-Printer Response

+

The following groups of attributes are send as part of the + CUPS-Add-Modify-Printer Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.7 CUPS-Delete-Printer Operation

+

The CUPS-Delete-Printer operation (0x4004) removes an existing + printer from the system. +

+ + +
Note: +

This operation requires administrative priviledges and must be POSTed + to "/admin/". POSTs to other paths will result in a + client-error-not-authorized (IPP_NOT_AUTHORIZED) error.

+
+
+

+

4.7.1 CUPS-Delete-Printer Request

+

The following groups of attributes are supplied as part of the + CUPS-Delete-Printer request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer.

    +
+

4.7.2 CUPS-Delete-Printer Response

+

The following groups of attributes are send as part of the + CUPS-Delete-Printer Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.8 CUPS-Get-Classes Operation

+

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.

+

4.8.1 CUPS-Get-Classes Request

+

The following groups of attributes are supplied as part of the + CUPS-Get-Classes request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute limiting the number of + printer classes that are returned.

    +

    "printer-info" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to select which printer + classes are returned.

    +

    "printer-location" (text(127)):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies this attribute to select which printer + classes are returned.

    +

    "printer-type" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type enumeration to select + which printer classes are returned.

    +

    "printer-type-mask" (type2 enum):

    +

    (CUPS 1.1 and higher)

    +

    The client OPTIONALLY supplies a printer type mask enumeration to + select which bits are used in the "printer-type" attribute.

    +

    "requested-attributes" (1setOf keyword) :

    +

    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'.

    +
+

4.8.2 CUPS-Get-Classes Response

+

The following groups of attributes are send as part of the + CUPS-Get-Classes Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

Group 2: Printer Class Object Attributes

+
    +

    The set of requested attributes and their current values for each + printer class.

    +
+

4.9 CUPS-Add-Modify-Class Operation

+

The CUPS-Add-Modify-Class operation (0x4006) adds a new printer class + or modifies and existing printer class on the system. +

+ + +
Note: +

This operation requires administrative priviledges and must be POSTed + to "/admin/". POSTs to other paths will result in a + client-error-not-authorized (IPP_NOT_AUTHORIZED) error.

+
+
+

+

4.9.1 CUPS-Add-Modify-Class Request

+

The following groups of attributes are supplied as part of the + CUPS-Add-Modify-Class request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer class.

    +
+

Group 2: Printer Object Attributes

+
    +

    "member-uris" (1setof uri):

    +

    The client OPTIONALLY supplies the "member-uris" set specifying the + printers and printer classes that are part of the class.

    +

    "printer-is-accepting-jobs" (boolean):

    +

    The client OPTIONALLY supplies this boolean attribute indicating + whether or not the class object should accept new jobs.

    +

    "printer-info" (text(127)):

    +

    The client OPTIONALLY supplies this attribute indicating the printer + information string.

    +

    "printer-location" (text(127)):

    +

    The client OPTIONALLY supplies this attribute indicating a textual + location of the class.

    +

    "printer-more-info" (uri):

    +

    The client OPTIONALLY supplies this attribute indicating a URI for + additional class information.

    +

    "printer-state" (type2 enum):

    +

    The client OPTIONALLY supplies this attribute indicating the + initial/current state of the class. Only the "idle" and "stopped" + enumerations are recognized.

    +

    "printer-state-message" (text(MAX)):

    +

    The client OPTIONALLY supplies this attribute indicating a textual + reason for the current class state.

    +

    "requesting-user-name-allowed" (1setof name(127))

    +

    OR

    +

    "requesting-user-name-denied" (1setof name(127)):

    +

    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.

    +
+

4.9.2 CUPS-Add-Modify-Class Response

+

The following groups of attributes are send as part of the + CUPS-Add-Modify-Class Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.10 CUPS-Delete-Class Operation

+

The CUPS-Delete-Class operation (0x4007) removes an existing printer + class from the system. +

+ + +
Note: +

This operation requires administrative priviledges and must be POSTed + to "/admin/". POSTs to other paths will result in a + client-error-not-authorized (IPP_NOT_AUTHORIZED) error.

+
+
+

+

4.10.1 CUPS-Delete-Class Request

+

The following groups of attributes are supplied as part of the + CUPS-Delete-Class request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer class.

    +
+

4.10.2 CUPS-Delete-Class Response

+

The following groups of attributes are send as part of the + CUPS-Delete-Class Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.11 CUPS-Accept-Jobs Operation

+

The CUPS-Accept-Jobs operation (0x4008) sets the + "printer-is-accepting-jobs" attribute to true for the specified printer + or printer class. +

+ + +
Note: +

This operation requires administrative priviledges and must be POSTed + to "/admin/". POSTs to other paths will result in a + client-error-not-authorized (IPP_NOT_AUTHORIZED) error.

+
+
+

+

4.11.1 CUPS-Accept-Jobs Request

+

The following groups of attributes are supplied as part of the + CUPS-Accept-Jobs request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer or printer + class.

    +
+

4.11.2 CUPS-Accept-Jobs Response

+

The following groups of attributes are send as part of the + CUPS-Accept-Jobs Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.12 CUPS-Reject-Jobs Operation

+

The CUPS-Reject-Jobs operation (0x4009) sets the + "printer-is-accepting-jobs" attribute to false for the specified + printer or printer class. +

+ + +
Note: +

This operation requires administrative priviledges and must be POSTed + to "/admin/". POSTs to other paths will result in a + client-error-not-authorized (IPP_NOT_AUTHORIZED) error.

+
+
+

+

4.12.1 CUPS-Reject-Jobs Request

+

The following groups of attributes are supplied as part of the + CUPS-Reject-Jobs request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer or printer + class.

    +
+

Group 2: Printer Object Attributes

+
    +

    "printer-state-message" (text(MAX)):

    +

    The client OPTIONALLY supplies this attribute indicating a textual + reason for the current printer state.

    +
+

4.12.2 CUPS-Reject-Jobs Response

+

The following groups of attributes are send as part of the + CUPS-Reject-Jobs Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.13 CUPS-Set-Default Operation

+

The CUPS-Set-Default operation (0x400A) sets the default printer + destination for all clients. +

+ + +
Note: +

This operation requires administrative priviledges and must be POSTed + to "/admin/". POSTs to other paths will result in a + client-error-not-authorized (IPP_NOT_AUTHORIZED) error.

+
+
+

+

4.13.1 CUPS-Set-Default Request

+

The following groups of attributes are supplied as part of the + CUPS-Set-Default request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri):

    +

    The client MUST supply a URI for the specified printer or printer + class.

    +
+

4.13.2 CUPS-Set-Default Response

+

The following groups of attributes are send as part of the + CUPS-Set-Default Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

4.14 CUPS-Get-Devices Operation

+

The CUPS-Get-Devices operation (0x400B) returns all of the supported + device-uri's for the server (CUPS 1.1 and higher).

+

4.14.1 CUPS-Get-Devices Request

+

The following groups of attributes are supplied as part of the + CUPS-Get-Devices request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "device-class" (type1 keyword):

    +

    The client OPTIONALLY supplies a device class keyword to select which + devices are returned.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute limiting the number of + devices that are returned.

    +

    "requested-attributes" (1setOf keyword) :

    +

    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'.

    +
+

4.14.2 CUPS-Get-Devices Response

+

The following groups of attributes are send as part of the + CUPS-Get-Devices Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

Group 2: Device Object Attributes

+
    +

    The set of requested attributes and their current values for each + device.

    +
+

4.15 CUPS-Get-PPDs Operation

+

The CUPS-Get-PPDs operation (0x400C) returns all of the locally + available PPD files on the system (CUPS 1.1 and higher).

+

4.15.1 CUPS-Get-PPDs Request

+

The following groups of attributes are supplied as part of the + CUPS-Get-PPDs request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "limit" (integer (1:MAX)):

    +

    The client OPTIONALLY supplies this attribute limiting the number of + PPDs that are returned.

    +

    "ppd-make" (text(127)):

    +

    The client OPTIONALLY supplies a printer manufacturer to select which + PPDs are returned.

    +

    "requested-attributes" (1setOf keyword) :

    +

    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'.

    +
+

4.15.2 CUPS-Get-PPDs Response

+

The following groups of attributes are send as part of the + CUPS-Get-PPDs Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

Group 2: PPD Attributes

+
    +

    The set of requested attributes and their current values for each PPD + file.

    +
+

4.16 CUPS-Move-Job Operation

+

The CUPS-Move-Job operation (0x400D) moves an active print job to a + different printer (CUPS 1.1 and higher).

+

4.16.1 CUPS-Move-Job Request

+

The following groups of attributes are supplied as part of the + CUPS-Move-Job request:

+

Group 1: Operation Attributes

+
    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.1 of the IPP Model and Semantics + document.

    +

    "printer-uri" (uri) and "job-id" (integer)

    +

    OR

    +

    "job-uri":

    +

    The client MUST supply a URI for the specified printer and a job ID + number, or the job URI.

    +
+

Group 2: Job Template Attributes

+
    +

    "job-printer-uri" (uri)

    +

    The client MUST supply a URI for a printer on the same server.

    +
+

4.16.2 CUPS-Move-Job Response

+

The following groups of attributes are send as part of the + CUPS-Move-Job Response:

+

Group 1: Operation Attributes

+
    +

    Status Message:

    +

    The standard response status message.

    +

    Natural Language and Character Set:

    +

    The "attributes-charset" and "attributes-natural-language" attributes + as described in section 3.1.4.2 of the IPP Model and Semantics + document.

    +
+

5 Attributes

+

CUPS provides many extension attributes to support multiple devices, + PPD files, standard job filters, printers, and printer classes.

+

5.1 Device Attributes

+

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.

+

5.1.1 device-class (type2 keyword)

+

The device-class attribute specifies the class of device and can be + one of the following:

+
    +
  • "file" - a disk file.
  • +
  • "direct" - a parallel or fixed-rate serial data port, currently used + for Centronics, IEEE-1284, and USB printer ports.
  • +
  • "serial" - a variable-rate serial port.
  • +
  • "network" - a network connection, typically via AppSocket, HTTP, + IPP, LPD, or SMB/CIFS protocols.
  • +
+

5.1.2 device-info (text(127))

+

The device-info attribute specifies a human-readable string + describing the device, e.g. "Parallel Port #1".

+

5.1.3 device-make-and-model (text(127))

+

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 "unknown".

+

5.1.4 device-uri (uri)

+

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:

+
    +
  • "file" - The device-uri will be of the form + "file:/path/to/filename".
  • +
  • "direct" - The device-uri will be of the form + "method:/dev/filename", where method may be "parallel" or "usb" in the + current implementation.
  • +
  • "serial" - The device-uri will be of the form + "serial:/dev/filename?baud=value+parity=value+flow=value". 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 "none", + "even", or "odd". The flow value can be one of "none", "soft" (XON/XOFF + handshaking), "hard" or "rts/cts" (RTS/CTS handshaking), or "dtrdsr" + (DTR/DSR handshaking). +

    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 ("soft" or "hard").

    +
  • "network" - The device-uri will be of the form + "method://[username:password@]hostname[:port]/[resource]", where method + may be "http", "ipp", "lpd", "smb", or "socket" in the current + implementation. +

    The URI returned by CUPS-Get-Devices will only contain the method + name followed by two slashes ("method://"). It is up to the client + application to add the appropriate host and other information when + adding a new printer.

    +

    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.

    +
  • + +
+

5.2 Job Template Attributes

+

5.2.1 blackplot (boolean)

+

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.

+

5.2.2 brightness (integer(0:200))

+

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.

+

Brightness is applied to the Cyan, Magenta, Yellow, and Black values + using the function "f(x) = brightness / 100 * x".

+

5.2.3 columns (integer(1:4))

+

The columns attribute specifies the number of columns to generate + when printing text files. The default value is 1.

+

5.2.4 cpi (type2 enum)

+

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.

+

5.2.5 fitplot (boolean)

+

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.

+

5.2.6 gamma (integer(1:10000))

+

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.

+

Gamma is applied to the Red, Green, and Blue values (or luminance for + grayscale output) using the function "f(x) = x(1000/gamma)".

+

5.2.7 hue (integer(-180:180))

+

The hue attribute specifies a color hue rotation when printing image + files. The default value is 0.

+

5.2.8 job-billing (text(MAX))

+

(CUPS 1.1 and higher)

+

The job-billing attribute provides a text value to associate with a + job for billing purposes.

+

5.2.9 job-hold-until (keyword | name(MAX))

+

(CUPS 1.1 and higher)

+

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 "HH:MM" and "HH:MM:SS" that specify a hold time. The hold time is + in Greenwich Mean Time (GMT) and not in the local time zone. If + the specified time is less than the current time, the job is held until + the next day.

+

5.2.10 job-sheets (1setof type3 keyword | + name(MAX))

+

(CUPS 1.1 and higher)

+

The job-sheets attribute specifies one or two banner files that are + printed before and after a job. The reserved value of "none" disables + banner printing. The default value is stored in the job-sheets-default + attribute.

+

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.

+

5.2.11 job-originating-host-name (name(MAX))

+

(CUPS 1.1.5 and higher)

+

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 always resolved to the name + "localhost".

+

This attribute is read-only.

+

5.2.12 lpi (type2 enum)

+

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.

+

5.2.13 mirror (boolean)

+

The mirror attribute specifies whether pages are mirrored on their X + axis, which is useful for printing transfer images on special media. + The default value is false.

+

5.2.14 natural-scaling (integer(1:1000))

+

(CUPS 1.1.9 and higher)

+

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.

+

The ppi option can be used to override the natural resolution of the + image, which controls the natural size.

+

5.2.15 number-up-layout (type2 keyword)

+

(CUPS 1.1.15 and higher)

+

The number-up-layout attribute specifies the order each input page is + placed on each output page. The following keywords are presently + defined:

+
    +
  • btlr - Bottom to top, left to right
  • +
  • btrl - Bottom to top, right to left
  • +
  • lrbt - Left to right, bottom to top
  • +
  • lrtb - Left to right, top to bottom (default)
  • +
  • rlbt - Right to left, bottom to top
  • +
  • rltb - Right to left, top to bottom
  • +
  • tblr - Top to bottom, left to right
  • +
  • tbrl - Top to bottom, right to left
  • +
+

5.2.16 page-border (type2 keyword)

+

(CUPS 1.1.15 and higher)

+

The page-border attribute specifies whether a border is draw around + each page. The following keywords are presently defined:

+
    +
  • double - Two hairline borders are drawn
  • +
  • double-thick - Two 1pt borders are drawn
  • +
  • none - No border is drawn (default)
  • +
  • single - A single hairline border is drawn
  • +
  • single-thick - A single 1pt border is drawn
  • +
+

5.2.17 page-bottom (integer(0:MAX))

+

The page-bottom attribute specifies the bottom margin in points (72 + points equals 1 inch). The default value is the device physical margin.

+

5.2.18 page-label (text(MAX))

+

(CUPS 1.1.7 and higher)

+

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.

+

5.2.19 page-left (integer(0:MAX))

+

The page-left attribute specifies the left margin in points (72 + points equals 1 inch). The default value is the device physical margin.

+

5.2.20 page-right (integer(0:MAX))

+

The page-right attribute specifies the right margin in points (72 + points equals 1 inch). The default value is the device physical margin.

+

5.2.21 page-set (type2 keyword)

+

The page-set attribute specifies which pages to print in a file. The + supported keywords are "all", "even", and "odd". The default value is + "all".

+

5.2.22 page-top (integer(0:MAX))

+

The page-top attribute specifies the top margin in points (72 points + equals 1 inch). The default value is the device physical margin.

+

5.2.23 penwidth (integer(0:MAX))

+

The penwidth attribute specifies the default pen width in micrometers + when printing HP-GL/2 plot files. The default value is 1000 (1 + millimeter).

+

5.2.24 position (type2 keyword)

+

The position attribute specifies the location of image files on the + media. The following keyword values are recognized:

+
    +
  • center - Center the image on the page (default)
  • +
  • top - Print the image centered at the top of the page
  • +
  • left - Print the image centered on the left of page
  • +
  • right - Print the image centered on the right of the + page
  • +
  • top-left - Print the image at the top left corner of + the page
  • +
  • top-right - Print the image at the top right corner of + the page
  • +
  • bottom - Print the image centered at the bottom of the + page
  • +
  • bottom-left - Print the image at the bottom left corner + of the page
  • +
  • bottom-right - Print the image at the bottom right + corner of the page
  • +
+

5.2.25 ppi (integer(1:MAX))

+

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.

+

5.2.26 prettyprint (boolean)

+

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.

+

5.2.27 saturation (integer(0:200))

+

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.

+

5.2.28 scaling (integer(1:1000))

+

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.

+

The scaling attribute overrides the ppi attribute if specified.

+

5.2.29 wrap (boolean)

+

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.

+

5.3 PPD Attributes

+

5.3.1 ppd-natural-language (naturalLanguage)

+

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 "en" (English) is assumed.

+

5.3.2 ppd-make (text(127))

+

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.

+

5.3.3 ppd-make-and-model (text(127))

+

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.

+

5.3.4 ppd-name (name(255))

+

The ppd-name attribute specifies the PPD filename on the server + relative to the model directory. The forward slash (/) is used to + delineate directories.

+

5.4 Printer Attributes

+

5.4.1 job-k-limit (integer)

+

(CUPS 1.1 and higher)

+

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.

+

5.4.2 job-page-limit (integer)

+

(CUPS 1.1 and higher)

+

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.

+

5.4.3 job-quota-period (integer)

+

(CUPS 1.1 and higher)

+

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.

+

5.4.4 job-sheets-supported (1setof type3 keyword | + name(MAX))

+

(CUPS 1.1 and higher)

+

The job-sheets-supported attribute specifies the available banner + files. There will always be at least one banner file available called + "none".

+

5.4.5 printer-type (type2 enum)

+

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: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitDescription
0x00000001Is a printer class.
0x00000002Is a remote + destination.
0x00000004Can print in black.
0x00000008Can print in color.
0x00000010Can print on both + sides of the page in hardware.
0x00000020Can staple output.
0x00000040Can do fast copies + in hardware.
0x00000080Can do fast copy + collation in hardware.
0x00000100Can punch output.
0x00000200Can cover output.
0x00000400Can bind output.
0x00000800Can sort output.
0x00001000Can handle media up + to US-Legal/A4.
0x00002000Can handle media + from US-Legal/A4 to ISO-C/A2.
0x00004000Can handle media + larger than ISO-C/A2.
0x00008000Can handle + user-defined media sizes.
0x00010000Is an implicit + (server-generated) class.
+
+

+

5.4.6 printer-type-mask (type2 enum)

+

(CUPS 1.1 and higher)

+

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.

+

5.4.7 requesting-user-name-allowed (1setof + name(127))

+

(CUPS 1.1 and higher)

+

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.

+

5.4.8 requesting-user-name-denied (1setof name(127)) +

+

(CUPS 1.1 and higher)

+

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.

+

5.5 Printer Class Attributes

+

5.5.1 member-names (1setof name(127))

+

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.

+

5.5.2 member-uris (1setof uri)

+

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.

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Page Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/ipp.pdf b/doc/ipp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b0486ec48afda3934256442881efdf81732547e3 GIT binary patch literal 107159 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 V + + + + + CUPS Implementation of IPP + + + +

Scope

+ +

Identification

+ +

This document provides an overview of the Internet Printing Protocol +("IPP") version 1.1 as implemented in the Common UNIX Printing System +("CUPS") version 1.1. + + + +

Document Overview

+ +

This document is organized into the following sections: + +

+ + + +

Overview

+ +

CUPS 1.1 implements IPP/1.1 and the operations and attributes +defined in the "IPP: Job and Printer Set Operations", +"IPP/1.1: Output-bin Attribute Extension", and "IPP/1.1: finishings +'fold',' trim', and 'bale' attribute values extension" specifications. + +

CUPS also provides 13 new operations and many new attributes to +support multiple IPP printers and printer classes on a single host. + +

IPP URIs

+ +

CUPS supports both the "http" and "ipp" methods. The following +resource names are used: + +

+ +
method://hostname:port/ + +
Can be used for all "get" operations. + +
method://hostname:port/admin + +
Used for all administrative operations. + +
method://hostname:port/classes/name + +
Specifies a printer class. + +
method://hostname:port/jobs/id + +
Specifies a job. + +
method://hostname:port/printers/name + +
Specifies a printer. + +
+ +

So a typical printer URI would be "ipp://foo.bar.com/printers/LaserJet". + +

In addition, the CUPS server also supports normal browser access to +"method://hostname:port/admin/", "method://hostname:port/classes/", +"method://hostname:port/jobs/", and "method://hostname:port/printers/" +to view and manage resources on the server dynamically. + +

CUPS IPP Operations

+ +

CUPS provides 13 extension operations in addition to most of the +standard IPP and registered extension operations: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operation NameCUPSCodeBrief Description
Print-Job1.00x0002Print a file.
Validate-Job1.00x0004Validate job attributes.
Create-Job1.10x0005Create a print job.
Send-Document1.10x0006Send a file for a print job.
Cancel-Job1.00x0008Cancel a print job.
Get-Job-Attributes1.00x0009Get job attributes.
Get-Jobs1.00x000AGet all jobs.
Get-Printer-Attributes1.00x000BGet printer attributes.
Hold-Job1.10x000CHold a job for printing.
Release-Job1.10x000DRelease a job for printing.
Pause-Printer1.00x0010Pause printing on a printer.
Resume-Printer1.00x0011Resume printing on a printer.
Purge-Jobs1.00x0012Purge all jobs.
Set-Job-Attributes1.10x0014Set attributes for a pending or held job.
CUPS-Get-Default1.00x4001Get the default destination.
CUPS-Get-Printers1.00x4002Get all of the available printers.
CUPS-Add-Modify-Printer1.00x4003Add or modify a printer.
CUPS-Delete-Printer1.00x4004Delete a printer.
CUPS-Get-Classes1.00x4005Get all of the available printer classes.
CUPS-Add-Modify-Class1.00x4006Add or modify a printer class.
CUPS-Delete-Class1.00x4007Delete a printer class.
CUPS-Accept-Jobs1.00x4008Accept jobs on a printer or printer class.
CUPS-Reject-Jobs1.00x4009Reject jobs on a printer or printer class.
CUPS-Set-Default1.00x400ASet the default destination.
CUPS-Get-Devices1.10x400BGet all of the available devices.
CUPS-Get-PPDs1.10x400CGet all of the available PPDs.
CUPS-Move-Job1.10x400DMove a job to a different printer.
+
+ +

Operations

+ +

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. + +

Print-Job Operation

+ +

The Print-Job operation (0x0002) prints a file. + +

Print-Job Request

+ +

The following groups of attributes are supplied as part of the +Print-Job request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-billing" (text(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a billing string that is logged + with the page accounting information. + +

    "job-sheets" (1setof type3 keyword | name(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies one or two banner pages that + are printed before and after any files in the print job. The + name of "none" is reserved to indicate that no banner page + should be printed. If the client does not specify this + attribute then the value of the "job-sheets-default" printer + object attribute is used. + +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value. + +

    "media" (1setof type3 keyword | name(MAX)): + +

    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 "media-default" printer object attribute is used. + +

    Note: Standard IPP only allows specification of a single + media attribute value. + +

    Other Job Template Attributes + +

+ +

The Print-Job request is followed by a file to be printed. + +

Print-Job Response

+ +

The following groups of attributes are send as part of the Print-Job +Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Job Attributes + +

    + +

    Standard Job Attributes + +

+ +

Create-Job Operation

+ +

The Create-Job operation (0x0005) creates a new, empty print job. + +

Create-Job Request

+ +

The following groups of attributes are supplied as part of the +Create-Job request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-billing" (text(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a billing string that is logged + with the page accounting information. + +

    "job-sheets" (1setof type3 keyword | name(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies one or two banner pages that + are printed before and after any files in the print job. The + name of "none" is reserved to indicate that no banner page + should be printed. If the client does not specify this + attribute then the value of the "job-sheets-default" printer + object attribute is used. + +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value. + +

    "media" (1setof type3 keyword | name(MAX)): + +

    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 "media-default" printer object attribute is used. + +

    Note: Standard IPP only allows specification of a single + media attribute value. + +

    Standard Job Template Attributes + +

+ +

Create-Job Response

+ +

The following groups of attributes are send as part of the +Create-Job Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Job Attributes + +

    + +

    Standard Job Attributes + +

+ +

Set-Job-Attributes Operation

+ +

The Set-Job-Attributes operation (0x0014) changes the attributes of +an active (not completed) job. + +

Set-Job-Attributes Request

+ +

The following groups of attributes are supplied as part of the +Set-Job-Attributes request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri) and "job-id" (integer) +

    OR +

    "job-uri": + +

    The client MUST supply a URI for the specified printer and + a job ID number, or the job URI. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-sheets" (1setof type3 keyword | name(MAX)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies one or two banner pages that + are printed before and after any files in the print job. The + name of "none" is reserved to indicate that no banner page + should be printed. If the client does not specify this + attribute then the value of the "job-sheets-default" printer + object attribute is used. + +

    Note: Standard IPP only allows specification of a single + job-sheets attribute value. + +

    "media" (1setof type3 keyword | name(MAX)): + +

    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 "media-default" printer object attribute is used. + +

    Note: Standard IPP only allows specification of a single + media attribute value. + +

    Other Job Template Attributes + +

+ +

Set-Job-Attributes Response

+ +

The following groups of attributes are send as part of the Set-Job-Attributes +Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Get-Default Operation

+ +

The CUPS-Get-Default operation (0x4001) returns the default printer +URI and attributes. + +

CUPS-Get-Default Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Default request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "requested-attributes" (1setOf keyword) : + +

    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'. + +

+ +

CUPS-Get-Default Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Default Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    The set of requested attributes and their current values. + +

+ +

CUPS-Get-Printers Operation

+ +

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. + +

CUPS-Get-Printers Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Printers request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the + number of printers that are returned. + +

    "printer-info" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printers are returned. + +

    "printer-location" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printers are returned. + +

    "printer-type" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type enumeration to + select which printers are returned. + +

    "printer-type-mask" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type mask + enumeration to select which bits are used in the "printer-type" + attribute. + +

    "requested-attributes" (1setOf keyword) : + +

    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'. + +

+ +

CUPS-Get-Printers Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Printers Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    The set of requested attributes and their current values for + each printer. + +

+ +

CUPS-Add-Modify-Printer Operation

+ +

The CUPS-Add-Modify-Printer operation (0x4003) adds a new printer or +modifies an existing printer on the system. + +

+ + +
Note: + +

This operation requires administrative priviledges + and must be POSTed to "/admin/". POSTs to other paths + will result in a client-error-not-authorized + (IPP_NOT_AUTHORIZED) error. + +

+ +

CUPS-Add-Modify-Printer Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Add-Modify-Printer request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    "banner-end-default" (name(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a banner page name that is + printed after files in a job. The reserved name "none" is used to + specify that no banner page should be printed. + +

    "banner-start-default" (name(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a banner page name that is + printed before files in a job. The reserved name "none" is used to + specify that no banner page should be printed. + +

    "device-uri" (uri): + +

    The client OPTIONALLY supplies a device URI for the + specified printer. + +

    "ppd-name" (name(127)): + +

    The client OPTIONALLY supplies a PPD name for the specified + printer. + +

    "printer-is-accepting-jobs" (boolean): + +

    The client OPTIONALLY supplies this boolean attribute + indicating whether or not the printer object should accept new jobs. + +

    "printer-info" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating the + printer information string. + +

    "printer-location" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual location of the printer. + +

    "printer-more-info" (uri): + +

    The client OPTIONALLY supplies this attribute indicating a + URI for additional printer information. + +

    "printer-state" (type2 enum): + +

    The client OPTIONALLY supplies this attribute indicating the + initial/current state of the printer. Only the "idle" and "stopped" + enumerations are recognized. + +

    "printer-state-message" (text(MAX)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual reason for the current printer state. + +

    "requesting-user-name-allowed" (1setof name(127) | delete) +

    OR +

    "requesting-user-name-denied" (1setof name(127) | delete): + +

    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. + +

+ +

The CUPS-Add-Modify-Printer request can optionally be followed by a PPD +file or System V interface script to be used for the printer. The +"ppd-name" attribute overrides any file that is attached to the end of +the request with a local CUPS PPD file. + +

CUPS-Add-Modify-Printer Response

+ +

The following groups of attributes are send as part of the +CUPS-Add-Modify-Printer Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Delete-Printer Operation

+ +

The CUPS-Delete-Printer operation (0x4004) removes an existing +printer from the system. + +

+ + +
Note: + +

This operation requires administrative priviledges + and must be POSTed to "/admin/". POSTs to other paths + will result in a client-error-not-authorized + (IPP_NOT_AUTHORIZED) error. + +

+ +

CUPS-Delete-Printer Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Delete-Printer request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer. + +

+ +

CUPS-Delete-Printer Response

+ +

The following groups of attributes are send as part of the +CUPS-Delete-Printer Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Get-Classes Operation

+ +

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. + +

CUPS-Get-Classes Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Classes request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the + number of printer classes that are returned. + +

    "printer-info" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printer classes are returned. + +

    "printer-location" (text(127)): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies this attribute to + select which printer classes are returned. + +

    "printer-type" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type enumeration to + select which printer classes are returned. + +

    "printer-type-mask" (type2 enum): + +

    (CUPS 1.1 and higher) + +

    The client OPTIONALLY supplies a printer type mask + enumeration to select which bits are used in the "printer-type" + attribute. + +

    "requested-attributes" (1setOf keyword) : + +

    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'. + +

+ +

CUPS-Get-Classes Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Classes Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Printer Class Object Attributes + +

    + +

    The set of requested attributes and their current values for + each printer class. + +

+ +

CUPS-Add-Modify-Class Operation

+ +

The CUPS-Add-Modify-Class operation (0x4006) adds a new printer class or +modifies and existing printer class on the system. + +

+ + +
Note: + +

This operation requires administrative priviledges + and must be POSTed to "/admin/". POSTs to other paths + will result in a client-error-not-authorized + (IPP_NOT_AUTHORIZED) error. + +

+ +

CUPS-Add-Modify-Class Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Add-Modify-Class request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer class. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    "member-uris" (1setof uri): + +

    The client OPTIONALLY supplies the "member-uris" set + specifying the printers and printer classes that are part of the class. + +

    "printer-is-accepting-jobs" (boolean): + +

    The client OPTIONALLY supplies this boolean attribute + indicating whether or not the class object should accept new jobs. + +

    "printer-info" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating the + printer information string. + +

    "printer-location" (text(127)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual location of the class. + +

    "printer-more-info" (uri): + +

    The client OPTIONALLY supplies this attribute indicating a + URI for additional class information. + +

    "printer-state" (type2 enum): + +

    The client OPTIONALLY supplies this attribute indicating the + initial/current state of the class. Only the "idle" and "stopped" + enumerations are recognized. + +

    "printer-state-message" (text(MAX)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual reason for the current class state. + +

    "requesting-user-name-allowed" (1setof name(127)) +

    OR +

    "requesting-user-name-denied" (1setof name(127)): + +

    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. + +

+ +

CUPS-Add-Modify-Class Response

+ +

The following groups of attributes are send as part of the CUPS-Add-Modify-Class Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Delete-Class Operation

+ +

The CUPS-Delete-Class operation (0x4007) removes an existing printer +class from the system. + +

+ + +
Note: + +

This operation requires administrative priviledges + and must be POSTed to "/admin/". POSTs to other paths + will result in a client-error-not-authorized + (IPP_NOT_AUTHORIZED) error. + +

+ +

CUPS-Delete-Class Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Delete-Class request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer class. + +

+ +

CUPS-Delete-Class Response

+ +

The following groups of attributes are send as part of the +CUPS-Delete-Class Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Accept-Jobs Operation

+ +

The CUPS-Accept-Jobs operation (0x4008) sets the +"printer-is-accepting-jobs" attribute to true for the specified printer +or printer class. + +

+ + +
Note: + +

This operation requires administrative priviledges + and must be POSTed to "/admin/". POSTs to other paths + will result in a client-error-not-authorized + (IPP_NOT_AUTHORIZED) error. + +

+ +

CUPS-Accept-Jobs Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Accept-Jobs request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer or printer class. + +

+ +

CUPS-Accept-Jobs Response

+ +

The following groups of attributes are send as part of the +CUPS-Accept-Jobs Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Reject-Jobs Operation

+ +

The CUPS-Reject-Jobs operation (0x4009) sets the +"printer-is-accepting-jobs" attribute to false for the specified +printer or printer class. + +

+ + +
Note: + +

This operation requires administrative priviledges + and must be POSTed to "/admin/". POSTs to other paths + will result in a client-error-not-authorized + (IPP_NOT_AUTHORIZED) error. + +

+ +

CUPS-Reject-Jobs Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Reject-Jobs request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer or printer class. + +

+ +

Group 2: Printer Object Attributes + +

    + +

    "printer-state-message" (text(MAX)): + +

    The client OPTIONALLY supplies this attribute indicating a + textual reason for the current printer state. + +

+ +

CUPS-Reject-Jobs Response

+ +

The following groups of attributes are send as part of the +CUPS-Reject-Jobs Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Set-Default Operation

+ +

The CUPS-Set-Default operation (0x400A) sets the default printer +destination for all clients. + +

+ + +
Note: + +

This operation requires administrative priviledges + and must be POSTed to "/admin/". POSTs to other paths + will result in a client-error-not-authorized + (IPP_NOT_AUTHORIZED) error. + +

+ +

CUPS-Set-Default Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Set-Default request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri): + +

    The client MUST supply a URI for the specified printer or + printer class. + +

+ +

CUPS-Set-Default Response

+ +

The following groups of attributes are send as part of the +CUPS-Set-Default Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

CUPS-Get-Devices Operation

+ +

The CUPS-Get-Devices operation (0x400B) returns all of the supported +device-uri's for the server (CUPS 1.1 and higher). + +

CUPS-Get-Devices Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-Devices request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "device-class" (type1 keyword): + +

    The client OPTIONALLY supplies a device class keyword to select + which devices are returned. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the number of + devices that are returned. + +

    "requested-attributes" (1setOf keyword) : + +

    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'. + +

+ +

CUPS-Get-Devices Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-Devices Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: Device Object Attributes + +

    + +

    The set of requested attributes and their current values for + each device. + +

+ +

CUPS-Get-PPDs Operation

+ +

The CUPS-Get-PPDs operation (0x400C) returns all of the locally +available PPD files on the system (CUPS 1.1 and higher). + +

CUPS-Get-PPDs Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Get-PPDs request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "limit" (integer (1:MAX)): + +

    The client OPTIONALLY supplies this attribute limiting the number of + PPDs that are returned. + +

    "ppd-make" (text(127)): + +

    The client OPTIONALLY supplies a printer manufacturer to select + which PPDs are returned. + +

    "requested-attributes" (1setOf keyword) : + +

    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'. + +

+ +

CUPS-Get-PPDs Response

+ +

The following groups of attributes are send as part of the +CUPS-Get-PPDs Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Group 2: PPD Attributes + +

    + +

    The set of requested attributes and their current values for each + PPD file. + +

+ +

CUPS-Move-Job Operation

+ +

The CUPS-Move-Job operation (0x400D) moves an active print job to a +different printer (CUPS 1.1 and higher). + +

CUPS-Move-Job Request

+ +

The following groups of attributes are supplied as part of the +CUPS-Move-Job request: + +

Group 1: Operation Attributes + +

    + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.1 of the IPP Model and + Semantics document. + +

    "printer-uri" (uri) and "job-id" (integer) +

    OR +

    "job-uri": + +

    The client MUST supply a URI for the specified printer and + a job ID number, or the job URI. + +

+ +

Group 2: Job Template Attributes + +

    + +

    "job-printer-uri" (uri) + +

    The client MUST supply a URI for a printer on the same server. + +

+ +

CUPS-Move-Job Response

+ +

The following groups of attributes are send as part of the +CUPS-Move-Job Response: + +

Group 1: Operation Attributes + +

    + +

    Status Message: + +

    The standard response status message. + +

    Natural Language and Character Set: + +

    The "attributes-charset" and "attributes-natural-language" + attributes as described in section 3.1.4.2 of the IPP Model and + Semantics document. + +

+ +

Attributes

+ +

CUPS provides many extension attributes to support multiple devices, +PPD files, standard job filters, printers, and printer classes. + +

Device Attributes

+ +

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. + +

device-class (type2 keyword)

+ +

The device-class attribute specifies the class of device and can be +one of the following: + +

    + +
  • "file" - a disk file. + +
  • "direct" - a parallel or fixed-rate serial data port, + currently used for Centronics, IEEE-1284, and USB printer + ports. + +
  • "serial" - a variable-rate serial port. + +
  • "network" - a network connection, typically via AppSocket, + HTTP, IPP, LPD, or SMB/CIFS protocols. + +
+ +

device-info (text(127))

+ +

The device-info attribute specifies a human-readable string describing +the device, e.g. "Parallel Port #1". + +

device-make-and-model (text(127))

+ +

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 "unknown". + +

device-uri (uri)

+ +

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: + +

    + +
  • "file" - The device-uri will be of the form + "file:/path/to/filename". + +
  • "direct" - The device-uri will be of the form + "method:/dev/filename", where method may be "parallel" or "usb" + in the current implementation. + +
  • "serial" - The device-uri will be of the form + "serial:/dev/filename?baud=value+parity=value+flow=value". + 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 "none", "even", or "odd". + The flow value can be one of "none", "soft" (XON/XOFF + handshaking), "hard" or "rts/cts" (RTS/CTS handshaking), + or "dtrdsr" (DTR/DSR handshaking). + +

    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 ("soft" or "hard"). + +

  • "network" - The device-uri will be of the form + "method://[username:password@]hostname[:port]/[resource]", + where method may be "http", "ipp", "lpd", "smb", or + "socket" in the current implementation. + +

    The URI returned by CUPS-Get-Devices will only contain + the method name followed by two slashes ("method://"). + It is up to the client application to add the appropriate + host and other information when adding a new printer. + +

    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. + +

+ +

Job Template Attributes

+ +

blackplot (boolean)

+ +

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. + +

brightness (integer(0:200))

+ +

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. + +

Brightness is applied to the Cyan, Magenta, Yellow, and Black values using +the function "f(x) = brightness / 100 * x". + +

columns (integer(1:4))

+ +

The columns attribute specifies the number of columns to generate when +printing text files. The default value is 1. + +

cpi (type2 enum)

+ +

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. + +

fitplot (boolean)

+ +

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. + +

gamma (integer(1:10000))

+ +

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. + +

Gamma is applied to the Red, Green, and Blue values (or luminance for +grayscale output) using the function "f(x) = x(1000/gamma)". + +

hue (integer(-180:180))

+ +

The hue attribute specifies a color hue rotation when printing image +files. The default value is 0. + +

job-billing (text(MAX))

+ +

(CUPS 1.1 and higher) + +

The job-billing attribute provides a text value to associate with a job +for billing purposes. + +

job-hold-until (keyword | name(MAX))

+ +

(CUPS 1.1 and higher) + +

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 +"HH:MM" and "HH:MM:SS" that specify a hold time. The hold time is in +Greenwich Mean Time (GMT) and not in the local time zone. If the +specified time is less than the current time, the job is held until the +next day. + +

job-sheets (1setof type3 keyword | name(MAX))

+ +

(CUPS 1.1 and higher) + +

The job-sheets attribute specifies one or two banner files that are printed +before and after a job. The reserved value of "none" disables banner printing. +The default value is stored in the job-sheets-default attribute. + +

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. + +

job-originating-host-name (name(MAX))

+ +

(CUPS 1.1.5 and higher) + +

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 +always resolved to the name "localhost". + +

This attribute is read-only. + +

lpi (type2 enum)

+ +

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. + +

mirror (boolean)

+ +

The mirror attribute specifies whether pages are mirrored on +their X axis, which is useful for printing transfer images on +special media. The default value is false. + +

natural-scaling (integer(1:1000))

+ +

(CUPS 1.1.9 and higher) + +

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. + +

The ppi option can be used to override the natural resolution of the +image, which controls the natural size. + +

number-up-layout (type2 keyword)

+ +

(CUPS 1.1.15 and higher) + +

The number-up-layout attribute specifies the order each input +page is placed on each output page. The following keywords are +presently defined: + +

    + +
  • btlr - Bottom to top, left to right
  • + +
  • btrl - Bottom to top, right to left
  • + +
  • lrbt - Left to right, bottom to top
  • + +
  • lrtb - Left to right, top to bottom (default)
  • + +
  • rlbt - Right to left, bottom to top
  • + +
  • rltb - Right to left, top to bottom
  • + +
  • tblr - Top to bottom, left to right
  • + +
  • tbrl - Top to bottom, right to left
  • + +
+ +

page-border (type2 keyword)

+ +

(CUPS 1.1.15 and higher) + +

The page-border attribute specifies whether a border is +draw around each page. The following keywords are presently +defined: + +

    + +
  • double - Two hairline borders are drawn
  • + +
  • double-thick - Two 1pt borders are drawn
  • + +
  • none - No border is drawn (default)
  • + +
  • single - A single hairline border is drawn
  • + +
  • single-thick - A single 1pt border is drawn
  • + +
+ +

page-bottom (integer(0:MAX))

+ +

The page-bottom attribute specifies the bottom margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

page-label (text(MAX))

+ +

(CUPS 1.1.7 and higher) + +

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. + +

page-left (integer(0:MAX))

+ +

The page-left attribute specifies the left margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

page-right (integer(0:MAX))

+ +

The page-right attribute specifies the right margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

page-set (type2 keyword)

+ +

The page-set attribute specifies which pages to print in a file. The +supported keywords are "all", "even", and "odd". The default value is +"all". + +

page-top (integer(0:MAX))

+ +

The page-top attribute specifies the top margin in points (72 points +equals 1 inch). The default value is the device physical margin. + +

penwidth (integer(0:MAX))

+ +

The penwidth attribute specifies the default pen width in micrometers +when printing HP-GL/2 plot files. The default value is 1000 (1 millimeter). + +

position (type2 keyword)

+ +

The position attribute specifies the location of image files on the +media. The following keyword values are recognized: + +

    + +
  • center - Center the image on the page (default) + +
  • top - Print the image centered at the top of the page + +
  • left - Print the image centered on the left of page + +
  • right - Print the image centered on the right of the page + +
  • top-left - Print the image at the top left corner of + the page + +
  • top-right - Print the image at the top right corner of + the page + +
  • bottom - Print the image centered at the bottom of + the page + +
  • bottom-left - Print the image at the bottom left + corner of the page + +
  • bottom-right - Print the image at the bottom right + corner of the page + +
+ +

ppi (integer(1:MAX))

+ +

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. + +

prettyprint (boolean)

+ +

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. + +

saturation (integer(0:200))

+ +

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. + +

scaling (integer(1:1000))

+ +

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. + +

The scaling attribute overrides the ppi attribute if specified. + +

wrap (boolean)

+ +

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. + +

PPD Attributes

+ +

ppd-natural-language (naturalLanguage)

+ +

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 "en" (English) is assumed. + +

ppd-make (text(127))

+ +

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. + +

ppd-make-and-model (text(127))

+ +

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. + +

ppd-name (name(255))

+ +

The ppd-name attribute specifies the PPD filename on the server +relative to the model directory. The forward slash (/) is used to +delineate directories. + +

Printer Attributes

+ +

job-k-limit (integer)

+ +

(CUPS 1.1 and higher) + +

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. + +

job-page-limit (integer)

+ +

(CUPS 1.1 and higher) + +

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. + +

job-quota-period (integer)

+ +

(CUPS 1.1 and higher) + +

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. + +

job-sheets-supported (1setof type3 keyword | name(MAX))

+ +

(CUPS 1.1 and higher) + +

The job-sheets-supported attribute specifies the available banner files. +There will always be at least one banner file available called "none". + +

printer-type (type2 enum)

+ +

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: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitDescription
0x00000001Is a printer class.
0x00000002Is a remote destination.
0x00000004Can print in black.
0x00000008Can print in color.
0x00000010Can print on both sides of the page in hardware.
0x00000020Can staple output.
0x00000040Can do fast copies in hardware.
0x00000080Can do fast copy collation in hardware.
0x00000100Can punch output.
0x00000200Can cover output.
0x00000400Can bind output.
0x00000800Can sort output.
0x00001000Can handle media up to US-Legal/A4.
0x00002000Can handle media from US-Legal/A4 to ISO-C/A2.
0x00004000Can handle media larger than ISO-C/A2.
0x00008000Can handle user-defined media sizes.
0x00010000Is an implicit (server-generated) class.
+ +

printer-type-mask (type2 enum)

+ +

(CUPS 1.1 and higher) + +

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. + +

requesting-user-name-allowed (1setof name(127))

+ +

(CUPS 1.1 and higher) + +

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. + +

requesting-user-name-denied (1setof name(127))

+ +

(CUPS 1.1 and higher) + +

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. + +

Printer Class Attributes

+ +

member-names (1setof name(127))

+ +

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. + +

member-uris (1setof uri)

+ +

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. + + + + + diff --git a/doc/overview.html b/doc/overview.html new file mode 100644 index 0000000000..754e55d6f8 --- /dev/null +++ b/doc/overview.html @@ -0,0 +1,500 @@ + + + + An Overview of the Common UNIX Printing System + + + + + + + + +

An Overview of the
+ Common UNIX Printing System,
+ Version 1.1

+ +

July 10, 2000
+ Michael Sweet, Easy Software Products
+ Copyright 1998-2002, All Rights Reserved.

+
+ +

This whitepaper describes the Common UNIX Printing +SystemTM ("CUPSTM"), a portable and extensible +printing system for UNIX®. CUPS is being developed by +Easy Software Products, a software +firm located in Hollywood, Maryland that has been selling commercial +software for UNIX since 1993 through more than 40 distributors serving +over 80 countries worldwide. + +

Additional information on CUPS is available on the World Wide Web at +"http://www.cups.org". + +

Background

+ +

Printing within UNIX has historically been done using one of two +printing systems - the Berkeley Line Printer Daemon ("LPD") [RFC1179] +and the AT&T Line Printer system. These printing systems were +designed in the 70's for printing text to line printers; vendors have +since added varying levels of support for other types of printers. + +

Replacements for these printing systems have emerged [LPRng, +Palladin, PLP], however none of the replacements change the fundamental +capabilities of these systems. + +

Over the last few years several attempts at developing a standard +printing interface have been made, including the draft POSIX Printing +standard developed by the Institute of Electrical and Electronics +Engineers, Inc. ("IEEE") [IEEE-1387.4] and Internet Printing Protocol +("IPP") developed by the Internet Engineering Task Force ("IETF") +through the Printer Working Group ("PWG") [IETF-IPP]. The POSIX +printing standard defines a common set of command-line tools as well as +a C interface for printer administration and print jobs, but has been +shelved by the IEEE. + +

The Internet Printing Protocol defines extensions to the HyperText +Transport Protocol 1.1 [RFC2616] to provide support for remote printing +services. IPP/1.0 was accepted by the IETF as an experimental Request +For Comments [RFC] document in October of 1999. Since then the Printer +Working Group has developed an updated set of specifications for +IPP/1.1 which have been accepted by the IETF and are awaiting +publication as proposed standards. Unlike POSIX Printing, IPP enjoys +widespread industry support and is poised to become the standard +network printing solution for all operating systems. + +

CUPS uses IPP/1.1 to provide a complete, modern printing system for +UNIX that can be extended to support new printers, devices, and +protocols while providing compatibility with existing UNIX +applications. CUPS is free software provided under the terms of the +GNU General Public License and GNU Library General Public License. + +

History

+ +

The first production release of CUPS (based on IPP/1.0) was released +in October of 1999. Since then, we have released several patch updates +to the original CUPS 1.0 release that addressed security, portability, +and bugs found, but no new functionality was added to improve the +stability of the CUPS code. + +

CUPS 1.1 is based on IPP/1.1 and adds many of the functional +enhancements that have been requested by our users. As with 1.0, CUPS +1.1 will be followed by patch releases that address any problems found +with the software but add no new features. + +

Design Overview

+ +

Like most printing systems, CUPS is designed around a central print +scheduling process that dispatches print jobs, processes administrative +commands, provides printer status information to local and remote +programs, and informs users as needed. Figure 1 shows the basic +organization of CUPS. + +

+

Figure 1 - CUPS Block Diagram

+ +

Scheduler

+ +

The scheduler is a HTTP/1.1 server application that handles HTTP +requests. Besides handling printer requests via IPP POST requests, the +scheduler also acts as a full-featured web server for documentation, +status monitoring, and administration. + +

The scheduler also manages a list of available printers on the LAN +and dispatches print jobs as needed using the appropriate filters and +backends. + +

Configuration Files

+ +The configuration files consist of: + +
    + +
  • The HTTP server configuration file. + +
  • Printer and class definition files. + +
  • MIME type and conversion rule files. + +
  • PostScript Printer Description ("PPD") files. + +
+ +

The HTTP server configuration file is purposely similar to the +Apache server configuration file and defines all of the access control +properties for the server. + +

The printer and class definition files list the available printer +queues and classes. Printer classes are collections of printers. Jobs +sent to a class are forwarded to the first available printer in the +class, round-robin fashion. + +

The MIME type files list the supported MIME types (text/plain, +application/postscript, etc.) and "magic" rules for automatically +detecting the format of a file. These are used by the HTTP server to +determine the Content-Type field for GET and HEAD +requests and by the IPP request handler to determine the file type +when a Print-Job or Send-File request is received with a +document-format of application/octet-stream. + +

The MIME conversion rule files list the available filters. The +filters are used when a job is dispatched so that an application can +send a convenient file format to the printing system which then +converts the document into a printable format as needed. Each filter +has a relative cost associated with it, and the filtering algorithm +chooses the set of filters that will convert the file to the needed +format with the lowest total "cost". + +

The PPD files describe the capabilities of all printers, not just +PostScript printers. There is one PPD file for each printer. PPD files +for non-PostScript printers define additional filters through +cupsFilter attributes to support printer drivers. + +

CUPS API

+ +

The CUPS API contains CUPS-specific convenience functions for queuing +print jobs, getting printer information, accessing resources via HTTP +and IPP, and manipulating PPD files. Unlike the rest of CUPS, the CUPS +API is provided under the terms of the GNU LGPL so it may be used by +non-GPL applications. + +

Berkeley and System V Commands

+ +

CUPS provides the System V and Berkeley command-line interfaces for +submitting jobs and checking the printer status. The +lpstat and lpc status commands also show +network printers ("printer@server") when printer browsing is enabled. + +

The System V administation commands are supplied for managing +printers and classes. The Berkeley printer administration tool +(lpc) is only supported in a "read-only" mode to check the +current status of the printer queues and scheduler. + +

Filters

+ +

A filter program reads from the standard input or from a file if a +filename is supplied. All filters must support a common set of options +including printer name, job ID, username, job title, number of copies, +and job options. All output is sent to the standard output. + +

Filters are provided for many file formats and include image file +and PostScript raster filters that support non-PostScript printers. Multiple +filters are run in parallel to produce the required output format. + +

The PostScript raster filter is based on the GNU Ghostscript 5.50 +core. Instead of using the Ghostscript printer drivers and front-end, +the CUPS filter uses a generic raster printer driver and CUPS-compliant +front-end to support any kind of raster printer. This allows the same +printer driver filter to be used for printing raster data from any +filter. + +

CUPS Imaging

+ +

The CUPS Imaging library provides functions for managing large +images, doing colorspace conversion and color management, scaling +images for printing, and managing raster page streams. It is used by +the CUPS image file filters, the PostScript RIP, and all raster +printers drivers. + +

Backends

+ +

A backend program is a special filter that sends print data to a +device or network connection. Backends for parallel, serial, USB, LPD, IPP, +and AppSocket (JetDirect) connections are provided in CUPS 1.1. + +

SAMBA version 2.0.6 and higher includes a SMB backend +(smbspool(1)) that can be used with CUPS 1.0 or 1.1 for +printing to Windows. + +

Network Printing

+ +

Traditionally, network printing has been one of the hardest things to +get working under UNIX. One reason is because each vendor added their +own extensions to the LPD protocol (the previous standard for network +printing), making cross-platform printing difficult if not impossible. + +

Another reason is that you have to administer every network printer +on every client machine. In some cases you can "clone" the printer +configuration from a "master" client to each of the others, but even +that can be time-consuming and error-prone. Something better is needed. + +

CUPS provides "printer browsing", which allows clients to +automatically see and use printers from any server on a LAN. This means +that you only need to configure the server and the clients will +automatically see the printers and classes on it. + +

In addition, CUPS can automatically merge multiple identical network +printers into "implicit classes". This allows clients to send jobs to +the implicit class and have them print on the first available printer +or server. In addition, failsafe and load-balancing functions are +enabled simply by defining the same printer on multiple servers! + +

New Features in CUPS 1.1

+ +

CUPS 1.1 includes many new features and capabilities: + +

    + +
  1. Backends + +
  2. Banner Page Support + +
  3. Digest Authentication + +
  4. Directory Services + +
  5. Directory Structure Changes + +
  6. Documentation + +
  7. Drivers + +
  8. Filters + +
  9. IPP Support + +
  10. Job Persistence + +
  11. LPD Client Support + +
  12. User-Defined Printers and Options + +
  13. Web Administration Interface + +
+ +

1. Backends

+ +

CUPS 1.1 implements a new backend interface for retrieving a list of +available devices for CUPS clients. This allows administration +interfaces to query the CUPS scheduler for a list of available devices, +automatically configure printers if the device identification +information is available, and present the user with a list of available +devices rather than relying on the user to know what devices are +configured on the system. + +

The new release also includes a backend for USB printers under +*BSD and Linux. Support for USB under Solaris 8 will be provided in +a subsequent patch release. + +

2. Banner Page Support

+ +

CUPS 1.1 includes support for banner pages at the beginning and end +of a job. Banner pages may be of any file format and support variable +substitution for job titles, usernames, etc. Default banner pages are +associated with each printer and can be overridden with command-line +options by the user. + +

3. Digest Authentication

+ +

Digest authentication provides a more secure method of authenticating +access to the printing system. Unlike Basic authentication, Digest +authentication does not send passwords "in the clear" so it is more +difficult to gain unauthorized access to your system. + +

CUPS 1.1 implements Digest authentication using a special MD5 +password file instead of the UNIX password file. This file is managed +using the new lppasswd command. + +

4. Directory Services

+ +

CUPS 1.1 adds new directory service ("printer browsing") features to +make using CUPS on large LANs and WANs easier. You can now poll a +remote server for printer information and relay it to the LAN as well +as restrict what printer information is processed (e.g. to "hide" +servers, domains, or networks that you don't want to see.) + +

5. Directory Structure Changes

+ +

CUPS 1.1 now uses a directory structure that complies with the +Filesystem Hierarchy Standard ("FHS"), version 2.0. This should make +integration into existing Linux and *BSD distributions a lot easier. + +

6. Documentation

+ +

The CUPS 1.1 documentation has gone through many revisions, +including a completely rewritten administrators manual, a new +programmers manual, and an IPP implementation reference manual. + +

7. Drivers

+ +

CUPS 1.1 includes drivers for EPSON dot-matrix and inkjet printers. +As with the HP PCL drivers, the EPSON drivers don't necessarily provide +the best possible output for each printer but should provide adequate +printing quality for general day-to-day printing. + +

8. Filters

+ +

CUPS 1.1 includes new image, PostScript, PDF, and text filters. The image +filters have been upgraded to support Windows BMP and Alias PIX files. + +

The PostScript filter is now based off GNU Ghostscript 5.50. The new +filter provides much better performance with higher-resolution printers +and supports most Level 3 PostScript language features. + +

The new PDF filter is based off the excellent Xpdf software from +Derek Noonburg and supports automatic page scaling. The new filter is a +faster, smaller, more reliable replacement for the GNU Ghostscript PDF +filtering that was used in CUPS 1.0. + +

The new text filter now supports bidirectional text and can embed +fonts as needed. + +

9. IPP Support

+ +

Probably the least visible portion of CUPS is the IPP support. CUPS +1.1 implements all of the required IPP/1.1 operations and attributes +and most of the optional ones. The optional Create-Job and Send-File +operations are now implemented, allowing for better System V printing +system compatibility (one job ID per lp command) and +support for banner pages. + +

10. Job Persistence

+ +

CUPS 1.1 supports job persistence. This means that jobs are preserved +even after a reboot, a feature that was sorely missing from CUPS 1.0. + +

In addition, CUPS 1.1 allows you to keep job information after the +job has printed. The basic post-job persistence mode provides a job +history (number of pages printed, time job was printed, etc.) but does +not preserve the actual job files. This can be changed to discard all +information after a job is printed or keep the job files after printing +so you can reprint a job at some later time. + +

11. LPD Client Support

+ +

By popular request, CUPS 1.1 supports LPD-based clients using a new +mini-daemon that handles LPD requests and passes them on to the main +server. + +

12. User-Defined Printers and Options

+ +

CUPS 1.1 includes support for user-defined printers and options via +a new lpoptions command. User-defined printers are special +instances of the available printers (e.g. "printer/instance" or +"printer@server/instance") that can have their own default options such +as media size, resolution, and so forth. The lpoptions +command can also be used to set a different default printer queue. + +

13. Web Administration Interface

+ +

CUPS 1.0 provided a simple class, job, and printer monitoring +interface for web browsers. CUPS 1.1 replaces this interface with an +enhanced administration interface that allows you to add, modify, +delete, configure, and control classes, jobs, and printers. + +

Software Using CUPS

+ +

A lot has happened since CUPS 1.0 came out, and many software packages +are supporting CUPS. We have contributed code to the SAMBA team to support +CUPS, and parts of that are already available in SAMBA 2.0.6 and 2.0.7. +With any luck the final pieces that provide a complete integration with +SAMBA will be available in the next release of SAMBA. + +

Two graphical interfaces have appeared on the scene that use CUPS as +well. The KUPS project provides a KDE-based interface for CUPS and can be +found at: + +

+ +

The X Printing Panel ("XPP") project provides a graphical printing +panel for CUPS and can be found at: + +

+ +

Numerous other filters, drivers, tutorials, etc. have been made available +on the CUPS Links web page, available at: + +

+ +

Finally, our own ESP Print Pro software uses CUPS to provide drivers +for thousands of printers and can be found at: + +

+ +

Operating Systems Using CUPS

+ +

One of our goals has always been to get as many UNIX/Linux +distributions using CUPS as possible. Debian is currently providing +CUPS as part of its stable distribution, and many other distributions +are considering it in their next releases. + +

Summary

+ +

The Common UNIX Printing System provides a modern printing interface +for UNIX applications that is both flexible and user-friendly. The +software provides System V and Berkeley compatible command-line +interfaces to ensure compatibility with existing applications. CUPS 1.1 +adds many new features that make it an even better choice for printing +under UNIX. + +

Who to Contact

+ +

For more information on CUPS please contact us at: + +

    +Attn: CUPS Information
    +Easy Software Products
    +44141 Airport View Drive Suite 204
    +Hollywood, Maryland 20636-3111 USA
    +
    ++1.301.373.9600
    +
    +cups-info@cups.org
    +
+ +

References

+ +
+ +
IEEE-1387.4
+ +
System Administration - Part 4: Printing Interfaces (draft)
+ +
IETF-IPP
+ +
Internet Printing Protocol/1.1
+ +
LPRng
+ +
An enhanced, extended, and portable implementation of the + Berkeley LPR print spooler functionality
+ +
Palladin
+ +
A printing system developed at the Massachussetts Institute + of Technology
+ +
PLP
+ +
The Portable Line Printer spooler system
+ +
RFC1179
+ +
Line Printer Daemon Protocol
+ +
RFC2046
+ +
Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types
+ +
RFC2616
+ +
Hypertext Transfer Protocol -- HTTP/1.1
+ +
+ +

Trademarks

+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property of Easy Software Products. All other trademarks are +the property of their respective owners. + + + diff --git a/doc/overview.pdf b/doc/overview.pdf new file mode 100644 index 0000000000000000000000000000000000000000..93af94cde4db185a7c6a783a50b4b916c4cd2065 GIT binary patch literal 37837 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 O0fQ5Aa$Zr9CHz1CwJEIt literal 0 Hc-jL100001 diff --git a/doc/printing-overview.shtml b/doc/printing-overview.shtml new file mode 100644 index 0000000000..1682dae7f4 --- /dev/null +++ b/doc/printing-overview.shtml @@ -0,0 +1,125 @@ +

1 - Printing System Overview

+ +

This chapter provides an overview of how the Common UNIX Printing System +works. + +

The Printing Problem

+ +

For years the printing problem has plagued UNIX. Unlike +Microsoft® Windows® 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. + +

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. + +

CUPS is designed to eliminate the printing problem. 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. + +

The Technology

+ +

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. + +

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. + +

IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP") +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. + +

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. + +

Jobs

+ +

Each file or set of files that is submitted for printing is called a +job. 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. + +

Classes

+ +

CUPS supports collections of printers known as classes. Jobs +sent to a class are forwarded to the first available printer in the +class. + +

Filters

+ +

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. + +

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 ("RIP") filters that convert +PostScript or image files into bitmaps that can be sent to a raster +printer. + +

Backends

+ +

Backends perform the most important task of all - they send the +filtered print data to the printer. + +

CUPS provides backends for printing over parallel, serial, and USB +ports, and over the network via the IPP, JetDirect (AppSocket), and +Line Printer Daemon ("LPD") protocols. Additional backends are +available in network service packages such as the SMB backend +included with the popular SAMBA software. + +

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. + +

Printer Drivers

+ +

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. + +

Networking

+ +

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 "name@server". + +

CUPS also provides implicit classes, 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! diff --git a/doc/references.shtml b/doc/references.shtml new file mode 100644 index 0000000000..8bd979c76c --- /dev/null +++ b/doc/references.shtml @@ -0,0 +1,43 @@ +

References

+ +

CUPS Documentation

+ +

The following CUPS documentation is referenced by this document: + +

    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan +
  • CUPS-IDD-1.1: CUPS System Interface Design Description +
  • CUPS-IPP-1.1: CUPS Implementation of IPP +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.1: CUPS Software Design Description +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual +
  • CUPS-SSR-1.1: CUPS Software Security Report +
  • CUPS-STP-1.1: CUPS Software Test Plan +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual +
  • CUPS-SVD-1.1: CUPS Software Version Description +
+ +

Other Documents

+ +

The following non-CUPS documents are referenced by this document: + +

diff --git a/doc/sam.html b/doc/sam.html new file mode 100644 index 0000000000..483c0ad55f --- /dev/null +++ b/doc/sam.html @@ -0,0 +1,6041 @@ + + + +CUPS Software Administrators Manual + + + + + + + +

+

CUPS Software Administrators Manual


+CUPS-SAM-1.1.17
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
Preface + +1 - Printing System Overview + +2 - Building and Installing CUPS + +3 - Managing Printers + +4 - Printer Classes + +5 - Client Setup + +6 - Printing System Management + +7 - Printing with Other Systems + +A - Software License Agreement + +B - Common Network Settings + +C - Printer Drivers + +D - List of Files +
+
E - Troubleshooting Common Problems + +
+

Preface

+

This software administrators manual provides printer administration + information for the Common UNIX Printing SystemTM ("CUPS +TM"), version 1.1.17.

+

System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+ + +

Document Overview

+

This software administrators manual is organized into the following + sections:

+ +

Notation Conventions

+

Various font and syntax conventions are used in this guide. Examples + and their meanings and uses are explained below: +

+ + + + + + + + + + + + +
Example   Description
 
lpstat +
lpstat(1)
   The names of commands; + the first mention of a command or function in a chapter is followed by + a manual page section number.
 
/var +
/usr/share/cups/data/testprint.ps
    +File and directory names.
 
Request ID is Printer-123 +   Screen output.
 
lp -d printer filename ENTER +   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are + written using the period (.) to indicate the decimal point.
+
+ + +

+

Abbreviations

+ The following abbreviations are used throughout this manual: +
    +
    +
    kb
    +
    Kilobytes, or 1024 bytes +
     
    +
    Mb
    +
    Megabytes, or 1048576 bytes +
     
    +
    Gb
    +
    Gigabytes, or 1073741824 bytes +
     
    +
    +
+

Other References

+
    +
    +
    CUPS Software Programmers Manual
    +
    A programmer guide for interfacing with and/or extending the CUPS + software. +
     
    +
    CUPS Software Users Manual
    +
    An end-user guide for using the CUPS software. +
     
    +
    +
+

1 - Printing System Overview

+

This chapter provides an overview of how the Common UNIX Printing + System works.

+

The Printing Problem

+

For years the printing problem has plagued UNIX. Unlike + Microsoft® Windows® 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.

+

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.

+

CUPS is designed to eliminate the printing problem. 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.

+

The Technology

+

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.

+

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.

+

IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP") + 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.

+

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.

+

Jobs

+

Each file or set of files that is submitted for printing is called a + job. 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.

+

Classes

+

CUPS supports collections of printers known as classes. Jobs + sent to a class are forwarded to the first available printer in the + class.

+

Filters

+

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.

+

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 ("RIP") filters that convert + PostScript or image files into bitmaps that can be sent to a raster + printer.

+

Backends

+

Backends perform the most important task of all - they send the + filtered print data to the printer.

+

CUPS provides backends for printing over parallel, serial, and USB + ports, and over the network via the IPP, JetDirect (AppSocket), and + Line Printer Daemon ("LPD") protocols. Additional backends are + available in network service packages such as the SMB backend included + with the popular SAMBA software.

+

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.

+

Printer Drivers

+

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.

+

Networking

+

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 "name@server".

+

CUPS also provides implicit classes, 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!

+

2 - Building and + Installing CUPS

+

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, Installing a + Binary Distribution.

+

Installing a Source Distribution

+

This section describes how to compile and install CUPS on your system + from the source code.

+

Requirements

+

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.

+

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:

+ +

If you make changes to the man pages you'll need GNU groff or another + nroff-like package. GNU groff is available from:

+ +

The documentation is formatted using the HTMLDOC software. If you + need to make changes you can get the HTMLDOC software from:

+ +

Finally, you'll need a make program that understands the + include directive - FreeBSD, NetBSD, and OpenBSD + developers should use the gmake program.

+

Compiling CUPS

+

CUPS uses GNU autoconf to configure the makefiles and source code for + your system. Type the following command to configure CUPS for your + system:

+
    +
    +./configure ENTER
    +
    +
+

The default installation will put the CUPS software in the /etc +, /usr, and /var directories on your system, which + will overwrite any existing printing commands on your system. Use the +--prefix option to install the CUPS software in another location:

+
    +
    +./configure --prefix=/some/directory ENTER
    +
    +
+

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:

+
    +
    +setenv CFLAGS "-I/some/directory" ENTER
    +setenv CXXFLAGS "-I/some/directory" ENTER
    +setenv LDFLAGS "-L/some/directory" ENTER
    +setenv DSOFLAGS "-L/some/directory" ENTER
    +./configure ... ENTER
    +
    +
+

or:

+
    +
    +CFLAGS="-I/some/directory"; export CFLAGS ENTER
    +CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER
    +LDFLAGS="-L/some/directory"; export LDFLAGS ENTER
    +DSOFLAGS="-L/some/directory"; export DSOFLAGS ENTER
    +./configure ... ENTER
    +
    +
+

To enable support for encryption, you'll also want to add the + "--enable-ssl" option:

+
    +
    +./configure --enable-ssl
    +
    +
+

SSL and TLS support require the OpenSSL library, available at:

+ +

If the OpenSSL headers and libraries are not installed in the + standard directories, use the --with-openssl-includes and +--with-openssl-libs options:

+
    +
    +./configure --enable-ssl \
    +    --with-openssl-includes=/foo/bar/include \
    +    --with-openssl-libs=/foo/bar/lib
    +
    +
+

Once you have configured things, just type:

+
    +
    +make ENTER
    +
    +
+

to build the software. + +

+

Installing the Software

+

Use the "install" target to install the software:

+
    +
    +make install ENTER
    +
    +
+
+ + +
WARNING: +

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.

+
+
+

Running the Software

+

Once you have installed the software you can start the CUPS server by + typing:

+
    +
    +/usr/sbin/cupsd ENTER
    +
    +
+ + +

Installing a Binary Distribution

+

CUPS comes in a variety of binary distribution formats. Easy Software + Products provides binaries in TAR format with installation and removal + scripts ("portable" 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. +

+ + +
WARNING: +

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.

+
+
+

+

Installing a Portable Distribution

+

To install the CUPS software from a portable distribution you will + need to be logged in as root; doing an su is good enough. + Once you are the root user, run the installation script with:

+
    +
    +./cups.install ENTER
    +
    +
+

After asking you a few yes/no questions the CUPS software will be + installed and the scheduler will be started automatically. + +

+

Installing an RPM Distribution

+

To install the CUPS software from an RPM distribution you will need + to be logged in as root; doing an su is good enough. Once + you are the root user, run RPM with:

+
    +
    +rpm -e lpr
    +rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTER
    +
    +
+

After a short delay the CUPS software will be installed and the + scheduler will be started automatically.

+

Installing an Debian Distribution

+

To install the CUPS software from a Debian distribution you will need + to be logged in as root; doing an su is good enough. Once + you are the root user, run dpkg with:

+
    +
    +dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTER
    +
    +
+

After a short delay the CUPS software will be installed and the + scheduler will be started automatically.

+

3 - Managing Printers

+

This chapter describes how to add your first printer and how to + manage your printers.

+

The Basics

+

Each printer queue has a name associated with it; the printer name + must start with any printable character except " ", "/", and "@". It + can contain up to 127 letters, numbers, and the underscore (_). Case is + not significant, e.g. "PRINTER", "Printer", and "printer" are + considered to be the same name.

+

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 ("URIs") which are a more + general form of Uniform Resource Locators ("URLs") that are used in + your web browser. For example, the first parallel port in Linux usually + uses a device URI of parallel:/dev/lp1. + +

+

You can see a complete list of supported devices by running the +lpinfo(8) command:

+
    +
    +lpinfo -v ENTER
    +network socket
    +network http
    +network ipp
    +network lpd
    +direct parallel:/dev/lp1
    +serial serial:/dev/ttyS1?baud=115200
    +serial serial:/dev/ttyS2?baud=115200
    +direct usb:/dev/usb/lp0
    +network smb
    +
    +
+

The -v 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 +file:/directory/filename while network devices use the more + familiar method://server or method://server/path + format.

+

Finally, printer queues usually have a PostScript Printer Description + ("PPD") 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.

+

Adding Your First Printer

+

CUPS provides two methods for adding printers: a command-line program + called lpadmin(8) and a Web interface. The lpadmin + command allows you to perform most printer administration tasks from + the command-line and is located in /usr/sbin. The Web + interface is located at:

+ +

and steps you through printer configuration. If you don't like + command-line interfaces, try the Web interface + instead.

+

Adding Your First Printer from the Command-Line

+

Run the lpadmin command with the -p option + to add a printer to CUPS:

+
    +
    +/usr/sbin/lpadmin -p printer -E -v device -m ppd ENTER
    +
    +
+

For a HP DeskJet printer connected to the parallel port this would + look like:

+
    +
    +/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTER
    +
    +
+

Similarly, a HP LaserJet printer using a JetDirect network interface + at IP address 11.22.33.44 would be added with the command:

+
    +
    +/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTER
    +
    +
+

As you can see, deskjet.ppd and laserjet.ppd + 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 Appendix C, "Printer + Drivers".

+

For a dot matrix printer connected to the serial port this would + might look like:

+
    +
    +/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTER
    +
    +
+

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.

+

Adding Your First Printer from the Web

+

The CUPS web server provides a user-friendly "wizard" 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:

+ +

Click on the Add Printer button to add a printer.

+

Managing Printers from the Command-Line

+

The lpadmin command enables you to perform most printer + administration tasks from the command-line. You'll find lpadmin + in the /usr/sbin directory.

+

Adding and Modifying Printers

+

Run the lpadmin command with the -p option + to add or modify a printer:

+
    +
    +/usr/sbin/lpadmin -p printer options ENTER
    +
    +
+

The options arguments can be any of the following:

+
    +
    +
    -c class
    +
    Adds the named printer to printer class class. If the + class does not exist then it is created.
    +
    -i interface
    +
    Copies the named interface 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.
    +
    -m model
    +
    Specifies a standard printer driver which is usually a PPD file. A + list of all available models can be displayed using the lpinfo + command with the -m option. A list of printer drivers + included with CUPS can be found in Appendix + C, "Printer Drivers".
    +
    -r class
    +
    Removes the named printer from printer class class. If + the resulting class becomes empty then it is removed.
    +
    -v device-uri
    +
    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.
    +
    -D info
    +
    Provides a textual description of the printer, e.g. "John's Personal + Printer".
    +
    -E
    +
    Enables the printer and accepts job. This option is equivalent to + running the enable(1) and accept(8) commands + on the printer.
    +
    -L location
    +
    Provides a textual location for the printer, e.g. "Computer Lab 5".
    +
    -P ppd-file
    +
    Specifies a local PPD file for the printer driver.
    +
    +
+

Deleting Printers

+

Run the lpadmin command with the -x option + to delete a printer:

+
    +
    +/usr/sbin/lpadmin -x printer ENTER
    +
    +
+

Setting the Default Printer

+

Run the lpadmin command with the -d option + to set a default printer:

+
    +
    +/usr/sbin/lpadmin -d printer ENTER
    +
    +
+

The default printer can be overridden by the user using the +lpoptions(1) command.

+

Starting and Stopping Printers

+

The enable and disable commands start and + stop printer queues, respectively:

+
    +
    +/usr/bin/enable printer ENTER
    +/usr/bin/disable printer ENTER
    +
    +
+

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).

+

Accepting and Rejecting Print Jobs

+

The accept and reject commands accept and + reject print jobs for the named printer, respectively:

+
    +
    +/usr/sbin/accept printer ENTER
    +/usr/sbin/reject printer ENTER
    +
    +
+

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.

+

Setting Quotas on a Printer

+

CUPS supports page and size-based quotas for each printer. The quotas + are tracked individually for each user, but a single set of limits + applies to all users for a partiuclar printer. For example, you can + limit every user to 5 pages per day on an expensive printer, but you + cannot limit every user except Johnny.

+

The job-k-limit, job-page-limit, and job-quota-peiod + options determine whether and how quotas are enforced for a printer. + The job-quota-period option determines the time interval for + quota tracking. The interval is expressed in seconds, so a day is + 86,400, a week is 604,800 and a month is 2,592,000 seconds. The + job-k-limit option specifies the job size limit in killobytes. The + job-page-limit option specifies the number of pages limit.

+

For quotas to be enforced, the period and at least one of the limits + must be set to a non-zero value. The following options will enable + quotas:

+
    +
    +/usr/sbin/lpadmin -p printer -o job-quota-period=604800 -o job-k-limit=1024 ENTER
    +/usr/sbin/lpadmin -p printer -o job-quota-period=604800 -o job-page-limit=100 ENTER
    +
    +
+

Or, you can combine all three options on the same line.

+

Restricting User Access to a Printer

+

The -u option of the lpadmin command + controls which users can print to a printer. The default configuration + allows all users to print to a printer:

+
    +
    +/usr/sbin/lpadmin -p printer -u allow:all ENTER
    +
    +
+

CUPS supports allow and deny lists so that you can specify a list of + users who are allowed to print or not allowed to print. Along with your + list of users, you can specify whether they are allowed or not allowed + to use the printer:

+
    +
    +/usr/sbin/lpadmin -p printer -u allow:peter,paul,mary ENTER
    +
    +
+

This command allows peter, paul, and mary to print to the named + printer, but all other users cannot print. The command:

+
    +
    +/usr/sbin/lpadmin -p printer -u deny:peter,paul,mary ENTER
    +
    +
+

has the opposite effect. All users except peter, paul, and mary will + be able to print to the named printer.

+
+ + +
NOTE: +

The allow and deny options are not cummulative. That + is, you must provide the complete list of users to allow or deny each + time.

+

Also, CUPS only maintains one list of users - the list can allow or + deny users from printing. If you specify an allow list and then specify + a deny list, the deny list will replace the allow list - only one list + is active at any time.

+
+
+

Managing Printers from the Web

+

The Web interface is located at:

+ +

From there you can perform all printer management tasks with a few + simple mouse clicks.

+

4 - Printer Classes

+

This chapter describes what printer classes are and how to manage + them.

+

The Basics

+

CUPS provides collections of printers called printer classes. + 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.

+

CUPS also supports implicit classes. 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.

+

Managing Printer Classes from the Command-Line

+

Run the lpadmin command with the -p and +-c options to add a printer to a class:

+
    +
    +/usr/sbin/lpadmin -p printer -c class ENTER
    +
    +
+

The class is created automatically if it doesn't exist. To + remove a printer from a class use the -r option:

+
    +
    +/usr/sbin/lpadmin -p printer -r class ENTER
    +
    +
+

To remove the entire class just use the -x option:

+
    +
    +/usr/sbin/lpadmin -x class ENTER
    +
    +
+

Managing Printer Classes from the Web Interface

+

The Web interface is located at:

+ +

The Add Class and Modify Class interfaces + provide a list of available printers; click on the printers of interest + to add them to the class.

+

Implicit Classes

+

A noted earlier, implicit classes are created automatically from the + available network printers and classes. To disable this functionality, + set the ImplicitClasses + directive to Off in the cupsd.conf file. You + will find more information on doing this in + Chapter 6, "Printing System Management".

+

5 - Client Setup

+

This chapter discusses several ways to configure CUPS clients for + printing.

+

The Basics

+

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.

+

CUPS supports several methods of configuring client machines:

+ +

Manual Configuration of Print Queues

+

The most tedious method of configuring client machines is to + configure each remote queue by hand using the lpadmin + command:

+
    +
    +lpadmin -p printer -E -v ipp://server/printers/printer ENTER
    +
    +
+

The printer name is the name of the printer on the + server machine. The server name is the hostname or IP + address of the server machine. Repeat the lpadmin command + for each remote printer you wish to use.

+
+ + +
NOTE: +

Manual configuration of print queues is not recommended for large + numbers of client machines because of the administration nightmare it + creates. For busy networks, consider subnetting groups of clients and + polling and relaying printer information instead.

+
+
+

Specifying a Single Server for Printing

+

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.

+

The default server is normally "localhost". To override the default + server create a file named /etc/cups/client.conf and add a + line reading:

+
    +
    +ServerName server
    +
    +
+

to the file. The server name can be the hostname or IP + address of the default server.

+

The default server can also be customized on a per-user basis. To set + a user-specific server create a file named ~/.cupsrc and add + a line reading:

+
    +
    +ServerName server
    +
    +
+

to the file. The server name can be the hostname or IP + address of the default server.

+

Automatic Configuration of Print Queues

+

CUPS supports automatic client configuration of printers on the same + subnet. To configure printers on the same subnet, do nothing. + 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.

+

If you want to see printers on other subnets as well, use the + BrowsePoll directive as described next.

+
+ + +
NOTE: +

The BrowseAddress directive + enables broadcast traffic from your server. The default configuration + braodcasts printer information every 30 seconds. Although this printer + information does not use much bandwidth, typically about 80 bytes per + printer, it can add up with large numbers of servers and printers.

+

Use the BrowseInterval and BrowseTimeout directives to tune + the amount of data that is added to your network load. In addition, + subnets can be used to minimize the amount of traffic that is carried + by the "backbone" of your large network.

+
+
+

Specifying Multiple Servers for Printing

+

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.

+

Polling is enabled by specifying one or more +BrowsePoll directives in the /etc/cups/cupsd.conf + file. For information on making these changes, see + Chapter 6, "Printing System Management".

+

Multiple BrowsePoll lines can + be used to poll multiple CUPS servers. To limit the amount of polling + you do from client machines, you can have only one of the clients do + the polling and relay that information to the others on the same subnet + (described next).

+

Relaying Printers to Other Clients

+

When you have clients and servers spread across multiple subnets, the + polling method is inefficient. CUPS provides a +BrowseRelay directive that enables a single client to relay + (broadcast) the polled printer information to the local subnet.

+

For example, Server A and Server B are on subnet 1 and subnet 2, + while the clients are on subnet 3. To provide printers to all of the + clients in subnet 3, client C will be configured with the following + directives in /etc/cups/cupsd.conf:

+
    +
    +# Poll the two servers
    +
    +BrowsePoll ServerA ENTER
    +BrowsePoll ServerB ENTER
    +
    +
    +# Relay the printers to the local subnet
    +
    +BrowseRelay 127.0.0.1 192.168.3.255 ENTER
    +
    +
+

The BrowseRelay line + specifies a source address and mask. Any browse packets coming from a + matching address wil be sent to the given broadcast address. In this + case, we want the packets from the local machine (127.0.0.1) relayed to + the other clients.

+

As printers are found using polling, they are relayed from client C + to the rest of the clients through a broadcast on subnet 3. The rest of + the clients can use the standard cupsd.conf configuration.

+

The BrowseRelay directive can + also be used to relay browsing packets from one network interface to + another. For example, if client C in the previous example had network + interfaces attaches to both subnet 1 and subnet 2, it could use the + BrowseRelay directive exclusively:

+
    +
    +# Relay the printers from subnet 1 and 2 to subnet 3
    +
    +BrowseRelay 192.168.1 192.168.3.255 ENTER
    +BrowseRelay 192.168.2 192.168.3.255 ENTER
    +
    +
+

Load Balancing and Failsafe Operation

+

When using server polling or broadcasting, CUPS clients can + automatically merge identical printers on multiple servers into a + single implicit class queue. Clients assume that printers with + the same name on multiple servers are in fact the same printer or type + of printer being served by multiple machines.

+

If you have two printers, LaserJet@ServerA and LaserJet@ServerB, a + third implicit class called LaserJet will be created + automatically on the client that refers to both printers. If the client + also has a local printer with the name LaserJet then an implicit class + named AnyLaserJet will be created instead.

+

The client will alternate between servers and automatically stop + sending jobs to a server if it goes down, providing a load-balancing + effect and fail-safe operation with automatic switchover.

+
+ + +
NOTE: +

Note that implicit classes ( +ImplicitClasses) are enabled by default.

+
+
+

6 - Printing System + Management

+

This chapter shows how you can configure the CUPS server.

+

The Basics

+

Several text files are used to configure CUPS. All of the server + configuration files are located in the /etc/cups directory:

+
    +
    + + +
    classes.conf
    +
    This file contains information on each printer class. Normally you + manipulate this file using the lpadmin command or the Web + interface. +
      + +
    +
    client.conf
    +
    This file provides the default server name for client machines. See Chapter 5, "Client Setup" for more + information. +
      + +
    +
    cupsd.conf
    +
    This file controls how the CUPS server (/usr/sbin/cupsd) + operates and is normally edited by hand. +
      + +
    +
    mime.convs
    +
    This file contains a list of standard file conversion filters and + their costs. You normally do not edit this file. +
      + +
    +
    mime.types
    +
    This file contains a list of standard file formats and how to + recognize them. You normally do not edit this file. +
      + +
    +
    printers.conf
    +
    This file contains information on each printer. Normally you + manipulate this file using the lpadmin command or the Web + Interface. +
     
    +
    +
+

Restarting the CUPS Server

+

Once you have made a change to a configuration file you need to + restart the CUPS server by sending it a HUP signal or + using the supplied initialization script. The CUPS distributions + install the script in the init.d directory with the name + cups. The location varies based upon the operating system:

+
    +
    +/etc/software/init.d/cups restart ENTER
    +/etc/rc.d/init.d/cups restart ENTER
    +/etc/init.d/cups restart ENTER
    +/sbin/init.d/cups restart ENTER
    +
    +
+

Changing the Server Configuration

+

The /etc/cups/cupsd.conf file contains configuration + directives 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 ("#") 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. + +

+

Server Directives

+

The cupsd.conf file contains many directives that + determine how the server operates:

+ + + +

AccessLog

+
+

Examples

+
    +
    +AccessLog /var/log/cups/access_log
    +AccessLog /var/log/cups/access_log-%s
    +AccessLog syslog
    +
    +
+

Description

+

The AccessLog directive sets the name of the access log + file. If the filename is not absolute then it is assumed to be relative + to the ServerRoot directory. The + access log file is stored in "common log format" and can be used by any + web access reporting tool to generate a report on CUPS server activity.

+

The server name can be included in the filename by using %s + in the name.

+

The special name "syslog" can be used to send the access information + to the system log instead of a plain file.

+

The default access log file is /var/log/cups/access_log. + +

+

Allow

+
+

Examples

+
    +
    +Allow from All
    +Allow from None
    +Allow from *.domain.com
    +Allow from .domain.com
    +Allow from host.domain.com
    +Allow from nnn.*
    +Allow from nnn.nnn.*
    +Allow from nnn.nnn.nnn.*
    +Allow from nnn.nnn.nnn.nnn
    +Allow from nnn.nnn.nnn.nnn/mm
    +Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +Allow from @LOCAL
    +Allow from @IF(name)
    +
    +
+

Description

+

The Allow directive specifies a hostname, IP address, or + network that is allowed access to the server. Allow + directives are cummulative, so multiple Allow directives + can be used to allow access for multiple hosts or networks. The +/mm notation specifies a CIDR netmask: +

+ + + + + + +
mmnetmask +mmnetmask
00.0.0.0 +8255.0.0.0
1128.0.0.0 +16255.255.0.0
2192.0.0.0 +24255.255.255.0
...... +32255.255.255.255
+
+

+

The @LOCAL name will allow access from all local network + interfaces, but not remote point-to-point interfaces. The +@IF(name) name will allow access from the named interface.

+

The Allow directive must appear inside a + Location directive. + +

+

AuthClass

+
+

Examples

+
    +
    +AuthClass Anonymous
    +AuthClass User
    +AuthClass System
    +AuthClass Group
    +
    +
+

Description

+

The AuthClass directive defines what level of + authentication is required:

+
    +
  • Anonymous - No authentication should be performed + (default.)
  • +
  • User - A valid username and password is required.
  • +
  • System - A valid username and password is required, and + the username must belong to the "sys" group; this can be changed using + the SystemGroup directive.
  • +
  • Group - A valid username and password is required, and + the username must belong to the group named by the AuthGroupName + directive.
  • +
+

The AuthClass directive must appear inside a + Location directive. + +

+

AuthGroupName

+
+

Examples

+
    +
    +AuthGroupName mygroup
    +AuthGroupName lp
    +
    +
+

Description

+

The AuthGroupName directive sets the group to use for +Group authentication.

+

The AuthGroupName directive must appear inside a + Location directive. + +

+

AuthType

+
+

Examples

+
    +
    +AuthType None
    +AuthType Basic
    +AuthType Digest
    +AuthType BasicDigest
    +
    +
+

Description

+

The AuthType directive defines the type of + authentication to perform:

+
    +
  • None - No authentication should be performed (default.)
  • +
  • Basic - Basic authentication should be performed using + the UNIX password and group files.
  • +
  • Digest - Digest authentication should be performed + using the /etc/cups/passwd.md5 file.
  • +
  • BasicDigest - Basic authentication should be performed + using the /etc/cups/passwd.md5 file.
  • +
+

When using Basic, Digest, or +BasicDigest authentication, clients connecting through the +localhost interface can also authenticate using + certificates.

+

The AuthType directive must appear inside a + Location directive. + +

+

AutoPurgeJobs

+
+

Examples

+
    +
    +AutoPurgeJobs Yes
    +AutoPurgeJobs No
    +
    +
+

Description

+

The AutoPurgeJobs 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 +No. + +

+

BrowseAddress

+
+

Examples

+
    +
    +BrowseAddress 255.255.255.255:631
    +BrowseAddress 192.0.2.255:631
    +BrowseAddress host.domain.com:631
    +BrowseAddress @LOCAL
    +BrowseAddress @IF(name)
    +
    +
+

Description

+

The BrowseAddress directive specifies an address to send + browsing information to. Multiple BrowseAddress directives + can be specified to send browsing information to different networks or + systems.

+

The @LOCAL name will broadcast printer information to + all local interfaces. The @IF(name) name will broadcast to + the named interface.

+

No browse addresses are set by default.

+
+ + +
NOTE: +

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.

+
+
+ + +

BrowseAllow

+
+

Examples

+
    +
    +BrowseAllow from all
    +BrowseAllow from none
    +BrowseAllow from 192.0.2
    +BrowseAllow from 192.0.2.0/24
    +BrowseAllow from 192.0.2.0/255.255.255.0
    +BrowseAllow from *.domain.com
    +BrowseAllow from @LOCAL
    +BrowseAllow from @IF(name)
    +
    +
+

Description

+

The BrowseAllow directive specifies a system or network + to accept browse packets from. The default is to accept browse packets + from all hosts.

+

Host and domain name matching require that you enable the + HostNameLookups directive.

+

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.

+

The @LOCAL name will allow browse data from all local + network interfaces, but not remote point-to-point interfaces. The +@IF(name) name will allow browse data from the named interface. + +

+

BrowseDeny

+
+

Examples

+
    +
    +BrowseDeny from all
    +BrowseDeny from none
    +BrowseDeny from 192.0.2
    +BrowseDeny from 192.0.2.0/24
    +BrowseDeny from 192.0.2.0/255.255.255.0
    +BrowseDeny from *.domain.com
    +BrowseDeny from @LOCAL
    +BrowseDeny from @IF(name)
    +
    +
+

Description

+

The BrowseDeny directive specifies a system or network + to reject browse packets from. The default is to deny browse packets + from no hosts.

+

Host and domain name matching require that you enable the + HostNameLookups directive.

+

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.

+

The @LOCAL name will block browse data from all local + network interfaces, but not remote point-to-point interfaces. The +@IF(name) name will block browse data from the named interface. + +

+

BrowseOrder

+
+

Examples

+
    +
    +BrowseOrder allow,deny
    +BrowseOrder deny,allow
    +
    +
+

Description

+

The BrowseOrder directive specifies the order of + allow/deny processing. The default order is deny,allow:

+
    +
  • allow,deny - Browse packets are accepted unless + specifically denied.
  • +
  • deny,allow - Browse packets are rejected unless + specifically allowed.
  • +
+ + +

BrowseInterval

+
+

Examples

+
    +
    +BrowseInterval 0
    +BrowseInterval 30
    +
    +
+

Description

+

The BrowseInterval 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.

+

The BrowseInterval value should always be less than the BrowseTimeout value. Otherwise + printers and classes will disappear from client systems between + updates. + +

+

BrowsePoll

+
+

Examples

+
    +
    +BrowsePoll 192.0.2.2:631
    +BrowsePoll host.domain.com:631
    +
    +
+

Description

+

The BrowsePoll directive polls a server for available + printers once every BrowseInterval + seconds. Multiple BrowsePoll directives can be + specified to poll multiple servers.

+

If BrowseInterval is set to 0 then the server is polled + once every 30 seconds. + +

+

BrowsePort

+
+

Examples

+
    +
    +BrowsePort 631
    +BrowsePort 9999
    +
    +
+

Description

+

The BrowsePort directive specifies the UDP port number + used for browse packets. The default port number is 631.

+
+ + +
NOTE: +

You must set the BrowsePort to the same value on all of + the systems that you want to see.

+
+
+ + +

BrowseProtocols

+
+

Examples

+
    +
    +BrowseProtocols CUPS
    +BrowseProtocols SLP
    +BrowseProtocols CUPS SLP
    +BrowseProtocols all
    +
    +
+

Description

+

The BrowseProtocols directive specifies the protocols to + use when collecting and distributing shared printers on the local + network. The default protocol is CUPS, which is a + broadcast-based protocol.

+
+ + +
NOTE: +

When using the SLP protocol, you must have at least one + Directory Agent (DA) server on your network. Otherwise the CUPS + scheduler (cupsd) will not respond to client requests for + several seconds while polling the network.

+
+
+ + +

BrowseRelay

+
+

Examples

+
    +
    +BrowseRelay 193.0.2.1 192.0.2.255
    +BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
    +BrowseRelay 193.0.2.0/24 192.0.2.255
    +BrowseRelay *.domain.com 192.0.2.255
    +BrowseRelay host.domain.com 192.0.2.255
    +
    +
+

Description

+

The BrowseRelay directive specifies source and + destination addresses for relaying browsing information from one host + or network to another. Multiple BrowseRelay directives can + be specified as needed.

+

BrowseRelay 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:

+
    +
    +BrowseRelay 127.0.0.1 255.255.255.255
    +
    +
+

This effectively provides access to printers on a WAN for all clients + on the LAN(s). + +

+

BrowseShortNames

+
+

Examples

+
    +
    +BrowseShortNames Yes
    +BrowseShortNames No
    +
    +
+

Description

+

The BrowseShortNames 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 ("printer"). If more + than one remote printer is detected with the same name, the printers + will have long names ("printer@server1", "printer@server2".)

+

The default value for this option is Yes. + +

+

BrowseTimeout

+
+

Examples

+
    +
    +BrowseTimeout 300
    +BrowseTimeout 60
    +
    +
+

Description

+

The BrowseTimeout 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.

+

The BrowseTimeout value should always be greater than + the BrowseInterval value. + Otherwise printers and classes will disappear from client systems + between updates. + +

+

Browsing

+
+

Examples

+
    +
    +Browsing On
    +Browsing Off
    +
    +
+

Description

+

The Browsing directive controls whether or not network + printer browsing is enabled. The default setting is On.

+
+ + +
NOTE: +

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.

+
+
+ + +

Classification

+
+

Examples

+
    +
    +Classification
    +Classification classified
    +Classification confidential
    +Classification secret
    +Classification topsecret
    +Classification unclassified
    +
    +
+

Description

+

The Classification 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. + +

+

ClassifyOverride

+
+

Examples

+
    +
    +ClassifyOverride Yes
    +ClassifyOverride No
    +
    +
+

Description

+

The ClassifyOverride 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 job-sheets option and can choose to only print one + security banner before or after the job. If the job-sheets + option is set to none then the server default + classification is used.

+

The default is to not allow classification overrides. + +

+

ConfigFilePerm

+
+

Examples

+
    +
    +ConfigFilePerm 0644
    +ConfigFilePerm 0600
    +
    +
+

Description

+

The ConfigFilePerm directive specifies the permissions + to use when writing configuration files. The default is 0600. + +

+

DataDir

+
+

Examples

+
    +
    +DataDir /usr/share/cups
    +
    +
+

Description

+

The DataDir directive sets the directory to use for data + files. + +

+

DefaultCharset

+
+

Examples

+
    +
    +DefaultCharset utf-8
    +DefaultCharset iso-8859-1
    +DefaultCharset windows-1251
    +
    +
+

Description

+

The DefaultCharset directive sets the default character + set to use for client connections. The default character set is +utf-8 but is overridden by the character set for the language + specified by the client or the DefaultLanguage directive. + +

+

DefaultLanguage

+
+

Examples

+
    +
    +DefaultLanguage de
    +DefaultLanguage en
    +DefaultLanguage es
    +DefaultLanguage fr
    +DefaultLanguage it
    +
    +
+

Description

+

The DefaultLanguage 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 "en" for English. + +

+

Deny

+
+

Examples

+
    +
    +Deny from All
    +Deny from None
    +Deny from *.domain.com
    +Deny from .domain.com
    +Deny from host.domain.com
    +Deny from nnn.*
    +Deny from nnn.nnn.*
    +Deny from nnn.nnn.nnn.*
    +Deny from nnn.nnn.nnn.nnn
    +Deny from nnn.nnn.nnn.nnn/mm
    +Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +Deny from @LOCAL
    +Deny from @IF(name)
    +
    +
+

Description

+

The Deny directive specifies a hostname, IP address, or + network that is allowed access to the server. Deny + directives are cummulative, so multiple Deny directives + can be used to allow access for multiple hosts or networks. The +/mm notation specifies a CIDR netmask: +

+ + + + + + +
mmnetmask +mmnetmask
00.0.0.0 +8255.0.0.0
1128.0.0.0 +16255.255.0.0
2192.0.0.0 +24255.255.255.0
...... +32255.255.255.255
+
+

+

The @LOCAL name will deny access from all local network + interfaces, but not remote point-to-point interfaces. The +@IF(name) name will deny access from the named interface.

+

The Deny directive must appear inside a + Location directive. + +

+

DocumentRoot

+
+

Examples

+
    +
    +DocumentRoot /usr/share/doc/cups
    +DocumentRoot /foo/bar/doc/cups
    +
    +
+

Description

+

The DocumentRoot 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 + ServerRoot directory. The default directory is + /usr/share/doc/cups.

+

Documents are first looked up in a sub-directory for the primary + language requested by the client (e.g. /usr/share/doc/cups/fr/... +) and then directly under the DocumentRoot directory (e.g. + /usr/share/doc/cups/...), so it is possible to localize the web + content by providing subdirectories for each language needed. + +

+

Encryption

+
+

Examples

+
    +
    +Encryption Never
    +Encryption IfRequested
    +Encryption Required
    +Encryption Always
    +
    +
+

Description

+

The Encryption directive must appear instead a + Location section and specifies the encryption settings + for that location. The default setting is IfRequested for + all locations. + +

+

ErrorLog

+
+

Examples

+
    +
    +ErrorLog /var/log/cups/error_log
    +ErrorLog /var/log/cups/error_log-%s
    +ErrorLog syslog
    +
    +
+

Description

+

The ErrorLog directive sets the name of the error log + file. If the filename is not absolute then it is assumed to be relative + to the ServerRoot directory. The + default error log file is /var/log/cups/error_log.

+

The server name can be included in the filename by using %s + in the name.

+

The special name "syslog" can be used to send the error information + to the system log instead of a plain file. + +

+

FilterLimit

+
+

Examples

+
    +
    +FilterLimit 0
    +FilterLimit 200
    +FilterLimit 1000
    +
    +
+

Description

+

The FilterLimit 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.

+

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.

+

The default limit is 0. + +

+

FilterNice

+
+

Examples

+
    +
    +FilterNice 0
    +FilterNice 39
    +FilterNice -10
    +
    +
+

Description

+

The FilterNice directive sets the scheduling priority of + job filters. Values larger than 0 give filters a lower priority while + values smaller than 0 give filters a higher priority. The +FilterNice value does not affect the priority of job backends.

+

The default priority is 0. + +

+

FontPath

+
+

Examples

+
    +
    +FontPath /foo/bar/fonts
    +FontPath /usr/share/cups/fonts:/foo/bar/fonts
    +
    +
+

Description

+

The FontPath directive specifies the font path to use + when searching for fonts. The default font path is +/usr/share/cups/fonts. + +

+

Group

+
+

Examples

+
    +
    +Group sys
    +Group system
    +Group root
    +
    +
+

Description

+

The Group directive specifies the UNIX group that filter + and CGI programs run as. The default group is sys, +system, or root depending on the operating system. + +

+

HideImplicitMembers

+
+

Examples

+
    +
    +HideImplicitMembers Yes
    +HideImplicitMembers No
    +
    +
+

Description

+

The HideImplicitMembers directive controls whether the + individual printers in an implicit class are shown to the user. The + default is No.

+

ImplicitClasses must be + enabled for this directive to have any effect.

+ + +

HostNameLookups

+
+

Examples

+
    +
    +HostNameLookups On
    +HostNameLookups Off
    +HostNameLookups Double
    +
    +
+

Description

+

The HostNameLookups directive controls whether or not + CUPS looks up the hostname for connecting clients. The Double + setting causes CUPS to verify that the hostname resolved from the + address matches one of the addresses returned for that hostname. +Double lookups also prevent clients with unregistered addresses + from connecting to your server. The default is Off to + avoid the potential server performance problems with hostname lookups. + Set this option to On or Double only if + absolutely required. + +

+

ImplicitClasses

+
+

Examples

+
    +
    +ImplicitClasses On
    +ImplicitClasses Off
    +
    +
+

Description

+

The ImplicitClasses directive controls whether implicit + classes are created based upon the available network printers and + classes. The default setting is On but is automatically + turned Off if Browsing + is turned Off. + +

+

ImplicitAnyClasses

+
+

Examples

+
    +
    +ImplicitAnyClasses On
    +ImplicitAnyClasses Off
    +
    +
+

Description

+

The ImplicitAnyClasses directive controls whether + implicit classes for local and remote printers are created with the + name AnyPrinter. The default setting is Off.

+

ImplicitClasses must be + enabled for this directive to have any effect.

+ + +

Include

+
+

Examples

+
    +
    +Include filename
    +Include /foo/bar/filename
    +
    +
+

Description

+

The Include directive includes the named file in the +cupsd.conf file. If no leading path is provided, the file is + assumed to be relative to the ServerRoot + directory.

+ + +

KeepAlive

+
+

Examples

+
    +
    +KeepAlive On
    +KeepAlive Off
    +
    +
+

Description

+

The KeepAlive directive controls whether or not to + support persistent HTTP connections. The default is On.

+

HTTP/1.1 clients automatically support persistent connections, while + HTTP/1.0 clients must specifically request them using the +Keep-Alive attribute in the Connection: field of + each request. + +

+

KeepAliveTimeout

+
+

Examples

+
    +
    +KeepAliveTimeout 60
    +KeepAliveTimeout 30
    +
    +
+

Description

+

The KeepAliveTimeout directive controls how long a + persistent HTTP connection will remain open after the last request. The + default is 60 seconds. + +

+

Limit

+
+

Examples

+
    +
    +<Limit GET POST>
    +...
    +</Limit>
    +
    +<Limit ALL>
    +...
    +</Limit>
    +
    +
+

Description

+

The Limit directive groups access control directives for + specific types of HTTP requests and must appear inside a + Location section. Access can be limited for individual + request types (DELETE, GET, HEAD +, OPTIONS, POST, PUT, and +TRACE) or for all request types (ALL). The request + type names are case-sensitive for compatibility with Apache. + +

+

LimitExcept

+
+

Examples

+
    +
    +<LimitExcept GET POST>
    +...
    +</LimitExcept>
    +
    +
+

Description

+

The LimitExcept directive groups access control + directives for specific types of HTTP requests and must appear inside a Location section. Unlike the + Limit directive, LimitExcept restricts + access for all requests except those listed on the +LimitExcept line. + +

+

LimitRequestBody

+
+

Examples

+
    +
    +LimitRequestBody 10485760
    +LimitRequestBody 10m
    +LimitRequestBody 0
    +
    +
+

Description

+

The LimitRequestBody 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.

+

Also see the identical MaxRequestSize + directive. + +

+

Listen

+
+

Examples

+
    +
    +Listen 127.0.0.1:631
    +Listen 192.0.2.1:631
    +
    +
+

Description

+

The Listen directive specifies a network address and + port to listen for connections. Multiple Listen directives + can be provided to listen on multiple addresses.

+

The Listen directive is similar to the +Port directive but allows you to restrict access to specific + interfaces or networks. + +

+

Location

+
+

Examples

+
    +
    +<Location />
    +...
    +</Location>
    +
    +<Location /admin>
    +...
    +</Location>
    +
    +<Location /printers>
    +...
    +</Location>
    +
    +<Location /printers/name>
    +...
    +</Location>
    +
    +<Location /classes>
    +...
    +</Location>
    +
    +<Location /classes/name>
    +...
    +</Location>
    +
    +
+

Description

+

The Location directive specifies access control and + authentication options for the specified HTTP resource or path. The + Allow, AuthClass +, AuthGroupName, + AuthType, Deny, + Encryption, Limit, + LimitExcept, Order, Require, and +Satisfy directives may all appear inside a location. +

+ + + + + + + + + + + + + + +
Locations on the Server.
LocationDescription
/The path for all get operations (get-printers, + get-jobs, etc.)
/adminThe path for all administration operations + (add-printer, delete-printer, start-printer, etc.)
/admin/confThe path for access to the ESP Print Pro + configuration files (cupsd.conf, client.conf, etc.)
/classesThe path for all classes
/classes/nameThe resource for class name
/jobsThe path for all jobs (hold-job, release-job, + etc.)
/jobs/idThe resource for job id
/printersThe path for all printers
/printers/nameThe path for printer name
/printers/name.ppdThe PPD file path for printer +name
+
+

+

Note that more specific resources override the less specific ones. So + the directives inside the /printers/name location will + override ones from /printers. Directives inside +/printers will override ones from /.   None of the + directives are inherited. More information can be found in section + "Printing System Security". + +

+

LogFilePerm

+
+

Examples

+
    +
    +LogFilePerm 0644
    +LogFilePerm 0600
    +
    +
+

Description

+

The LogFilePerm directive specifies the permissions to + use when writing configuration files. The default is 0644. + +

+

LogLevel

+
+

Examples

+
    +
    +LogLevel none
    +LogLevel emerg
    +LogLevel alert
    +LogLevel crit
    +LogLevel error
    +LogLevel warn
    +LogLevel notice
    +LogLevel info
    +LogLevel debug
    +LogLevel debug2
    +
    +
+

Description

+

The LogLevel directive specifies the level of logging + for the ErrorLog file. The + following values are recognized (each level logs everything under the + preceding levels):

+
    +
  • none - Log nothing.
  • +
  • emerg - Log emergency conditions that prevent the + server from running.
  • +
  • alert - Log alerts that must be handled immediately.
  • +
  • crit - Log critical errors that don't prevent the + server from running.
  • +
  • error - Log general errors.
  • +
  • warn - Log errors and warnings.
  • +
  • notice - Log temporary error conditions.
  • +
  • info - Log all requests and state changes (default).
  • +
  • debug - Log basic debugging information.
  • +
  • debug2 - Log all debugging information.
  • +
+ + +

MaxClients

+
+

Examples

+
    +
    +MaxClients 100
    +MaxClients 1024
    +
    +
+

Description

+

The MaxClients directive controls the maximum number of + simultaneous clients that will be allowed by the server. The default is + 100 clients.

+
+ + +
NOTE: +

Since each print job requires a file descriptor for the status pipe, + the CUPS server internally limits the MaxClients value to + 1/3 of the available file descriptors to avoid possible problems when + printing large numbers of jobs.

+
+
+ + +

MaxCopies

+
+

Examples

+
    +
    +MaxCopies 100
    +MaxCopies 65535
    +
    +
+

Description

+

The MaxCopies directive controls the maximum number of + copies that a user can print of a job. The default is 100 copies.

+
+ + +
NOTE: +

Most HP PCL laser printers internally limit the number of copies to + 100.

+
+
+ + +

MaxJobs

+
+

Examples

+
    +
    +MaxJobs 100
    +MaxJobs 9999
    +MaxJobs 0
    +
    +
+

Description

+

The MaxJobs 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.

+

Setting the maximum to 0 disables this functionality. The default + setting is 0. + +

+

MaxJobsPerPrinter

+
+

Examples

+
    +
    +MaxJobsPerPrinter 100
    +MaxJobsPerPrinter 9999
    +MaxJobsPerPrinter 0
    +
    +
+

Description

+

The MaxJobsPerPrinter 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.

+

Setting the maximum to 0 disables this functionality. The default + setting is 0. + +

+

MaxJobsPerUser

+
+

Examples

+
    +
    +MaxJobsPerUser 100
    +MaxJobsPerUser 9999
    +MaxJobsPerUser 0
    +
    +
+

Description

+

The MaxJobsPerUser 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.

+

Setting the maximum to 0 disables this functionality. The default + setting is 0. + +

+

MaxLogSize

+
+

Examples

+
    +
    +MaxLogSize 1048576
    +MaxLogSize 1m
    +MaxLogSize 0
    +
    +
+

Description

+

The MaxLogSize 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 filename.O. This allows you to + rotate the logs automatically. The default size is 1048576 bytes (1MB).

+

Setting the maximum size to 0 disables log rotation. + +

+

MaxRequestSize

+
+

Examples

+
    +
    +MaxRequestSize 10485760
    +MaxRequestSize 10m
    +MaxRequestSize 0
    +
    +
+

Description

+

The MaxRequestSize 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.

+

Also see the identical +LimitRequestBody directive. + +

+

Order

+
+

Examples

+
    +
    +Order Allow,Deny
    +Order Deny,Allow
    +
    +
+

Description

+

The Order directive defines the default access control. + The following values are supported:

+
    +
  • Allow,Deny - Allow requests from all systems except + for those listed in a Deny directive.
  • +
  • Deny,Allow - Allow requests only from those listed in + an Allow directive.
  • +
+

The Order directive must appear inside a + Location directive. + +

+

PageLog

+
+

Examples

+
    +
    +PageLog /var/log/cups/page_log
    +PageLog /var/log/cups/page_log-%s
    +PageLog syslog
    +
    +
+

Description

+

The PageLog directive sets the name of the page log + file. If the filename is not absolute then it is assumed to be relative + to the ServerRoot directory. The + default page log file is /var/log/cups/page_log.

+

The server name can be included in the filename by using %s + in the name.

+

The special name "syslog" can be used to send the page information to + the system log instead of a plain file. + +

+

Port

+
+

Examples

+
    +
    +Port 631
    +Port 80
    +
    +
+

Description

+

The Port directive specifies a port to listen on. + Multiple Port lines can be specified to listen on multiple + ports. The default port is 631. + +

+

PreserveJobHistory

+
+

Examples

+
    +
    +PreserveJobHistory On
    +PreserveJobHistory Off
    +
    +
+

Description

+

The PreserveJobHistory directive controls whether the + history of completed, cancelled, or aborted print jobs is stored on + disk.

+

A value of On (the default) preserves job information + until the administrator purges it with the cancel command.

+

A value of Off removes the job information as soon as + each job is completed, cancelled, or aborted. + +

+

PreserveJobFiles

+
+

Examples

+
    +
    +PreserveJobFiles On
    +PreserveJobFiles Off
    +
    +
+

Description

+

The PreserveJobFiles directive controls whether the + document files of completed, cancelled, or aborted print jobs are + stored on disk.

+

A value of On preserves job files until the + administrator purges them with the cancel command. Jobs + can be restarted (and reprinted) as desired until they are purged.

+

A value of Off (the default) removes the job files as + soon as each job is completed, cancelled, or aborted. + +

+

Printcap

+
+

Examples

+
    +
    +Printcap
    +Printcap /etc/printcap
    +Printcap /etc/printers.conf
    +
    +
+

Description

+

The Printcap 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 + /etc/printcap.

+

When a filename is specified (e.g. /etc/printcap), 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. + +

+

PrintcapFormat

+
+

Examples

+
    +
    +PrintcapFormat BSD
    +PrintcapFormat Solaris
    +
    +
+

Description

+

The PrintcapFormat directive controls the output format + of the printcap file. The default is to generate a BSD printcap file. + +

+

PrintcapGUI

+
+

Example

+
    +
    +PrintcapGUI /usr/bin/glpoptions
    +
    +
+

Description

+

The PrintcapGUI directive sets the program to use when + displaying an option panel from an IRIX application that uses the + Impressario print API. The default program is the ESP Print Pro + "glpoptions" GUI.

+

The program must accept the -d option to specify a + printer and the -o option to specify one or more options. + After allowing the user to select/change options, the program must then + write the list of printing options without the -o to the + standard output. + +

+

RemoteRoot

+
+

Examples

+
    +
    +RemoteRoot remroot
    +RemoteRoot root
    +
    +
+

Description

+

The RemoteRoot directive sets the username for + unauthenticated root requests from remote hosts. The default username + is remroot. Setting RemoteRoot to root + effectively disables this security mechanism. + +

+

RequestRoot

+
+

Examples

+
    +
    +RequestRoot /var/spool/cups
    +RequestRoot /foo/bar/spool/cups
    +
    +
+

Description

+

The RequestRoot 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 + ServerRoot directory. The default request directory is + /var/spool/cups. + +

+

Require

+
+

Examples

+
    +
    +Require group foo bar
    +Require user john mary
    +Require valid-user
    +
    +
+

Description

+

The Require directive specifies that authentication is + required for the resource. The group keyword specifies + that the authenticated user must be a member of one or more of the + named groups that follow.

+

The user keyboard specifies that the authenticated user + must be one of the named users that follow.

+

The valid-user keyword specifies that any authenticated + user may access the resource.

+

The default is to do no authentication. This directive must appear + inside a Location directive. + +

+

RIPCache

+
+

Examples

+
    +
    +RIPCache 8m
    +RIPCache 1g
    +RIPCache 2048k
    +
    +
+

Description

+

The RIPCache directive sets the size of the memory cache + used by Raster Image Processor ("RIP") filters such as +imagetoraster and pstoraster. The size can be + suffixed with a "k" for kilobytes, "m" for megabytes, or "g" for + gigabytes. The default cache size is "8m", or 8 megabytes. + +

+

RootCertDuration

+
+

Examples

+
    +
    +RootCertDuration 300
    +RootCertDuration 0
    +
    +
+

Description

+

The RootCertDuration directive controls the interval + between updates of the root authentication certificate. The default is +300 seconds which updates the root certificate approximately once + every 5 minutes. Set the interval to 0 to disable certificate updates + entirely. + +

+

RunAsUser

+
+

Examples

+
    +
    +RunAsUser Yes
    +RunAsUser No
    +
    +
+

Description

+

The RunAsUser directive controls whether the scheduler + runs as the unpriviledged user account (usually lp). The + default is No which leaves the scheduler running as the +root user.

+

Note: Running as a non-priviledged user may prevent LPD and + locally connected printers from working due to permission problems. The + lpd backend will automatically use a non-priviledged mode + that is not 100% compliant with RFC 1179. The parallel, +serial, and usb backends will need write access to + the corresponding device files. + +

+

Satisfy

+
+

Examples

+
    +
    +Satisfy all
    +Satisfy any
    +
    +
+

Description

+

The Satisfy directive specifies whether all conditions + must be satisfied to allow access to the resource. If set to all +, then all authentication and access control conditions must be satified + to allow access.

+

Setting Satisfy to any allows a user to + gain access if the authentication or access control requirements are + satisfied. For example, you might require authentication for remote + access, but allow local access without authentication.

+

The default is all. This directive must appear inside a Location directive. + +

+

ServerAdmin

+
+

Examples

+
    +
    +ServerAdmin user@host
    +ServerAdmin root@foo.bar.com
    +
    +
+

Description

+

The ServerAdmin directive identifies the email address + for the administrator on the system. By default the administrator email + address is root@server, where server is the + server name. + +

+

ServerBin

+
+

Examples

+
    +
    +ServerBin /usr/lib/cups
    +ServerBin /foo/bar/lib/cups
    +
    +
+

Description

+

The ServerBin directive sets the directory for + server-run executables. If an absolute path is not provided then it is + assumed to be relative to the ServerRoot + directory. The default executable directory is /usr/lib/cups +. + +

+

ServerCertificate

+
+

Examples

+
    +
    +ServerCertificate /etc/cups/ssl/server.crt
    +
    +
+

Description

+

The ServerCertificate 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 + /etc/cups/ssl/server.crt. + +

+

ServerKey

+
+

Examples

+
    +
    +ServerKey /etc/cups/ssl/server.key
    +
    +
+

Description

+

The ServerKey directive specifies the location of the + SSL private key file used by the server when negotiating encrypted + connections. The default key file is /etc/cups/ssl/server.crt +. + +

+

ServerName

+
+

Examples

+
    +
    +ServerName foo.domain.com
    +ServerName myserver.domain.com
    +
    +
+

Description

+

The ServerName directive specifies the hostname that is + reported to clients. By default the server name is the hostname. + +

+

ServerRoot

+
+

Examples

+
    +
    +ServerRoot /etc/cups
    +ServerRoot /foo/bar/cups
    +
    +
+

Description

+

The ServerRoot directive specifies the absolute path to + the server configuration and state files. It is also used to resolve + relative paths in the cupsd.conf file. The default server + directory is /etc/cups. + +

+

SSLListen

+
+

Examples

+
    +
    +SSLListen 127.0.0.1:443
    +SSLListen 192.0.2.1:443
    +
    +
+

Description

+

The SSLListen directive specifies a network address and + port to listen for secure connections. Multiple SSLListen + directives can be provided to listen on multiple addresses.

+

The SSLListen directive is similar to the + SSLPort directive but allows you to restrict access to + specific interfaces or networks. + +

+

SSLPort

+
+

Examples

+
    +
    +SSLPort 443
    +
    +
+

Description

+

The SSLPort directive specifies a port to listen on for + secure connections. Multiple SSLPort lines can be + specified to listen on multiple ports. + +

+

SystemGroup

+
+

Examples

+
    +
    +SystemGroup sys
    +SystemGroup system
    +SystemGroup root
    +
    +
+

Description

+

The SystemGroup directive specifies the system + administration group for System authentication. More + information can be found later in this chapter in + "Printing System Security". + +

+

TempDir

+
+

Examples

+
    +
    +TempDir /var/tmp
    +TempDir /foo/bar/tmp
    +
    +
+

Description

+

The TempDir directive specifies an absolute path for the + directory to use for temporary files. The default directory is + /var/tmp.

+

Temporary directories must be world-writable and should have the + "sticky" permission bit enabled so that other users cannot delete + filter temporary files. The following commands will create an + appropriate temporary directory called /foo/bar/tmp:

+
    +
    +mkdir /foo/bar/tmp ENTER
    +chmod a+rwxt /foo/bar/tmp ENTER
    +
    +
+ + +

Timeout

+
+

Examples

+
    +
    +Timeout 300
    +Timeout 90
    +
    +
+

Description

+

The Timeout directive controls the amount of time to + wait before an active HTTP or IPP request times out. The default + timeout is 300 seconds. + +

+

User

+
+

Examples

+
    +
    +User lp
    +User guest
    +
    +
+

Description

+

The User directive specifies the UNIX user that filter + and CGI programs run as. The default user is lp.

+

Changing the Client Configuration

+

The CUPS client application (lp, lpr, and + so forth) use the /etc/cups/client.conf file for default + settings. The client application also look in the user's home directory + for a file called .cupsrc. Each directive is listed on a + line by itself followed by its value. Comments are introduced using the + number sign ("#") character at the beginning of a line.

+

Since the client configuration file consists of plain text, you can + use your favorite text editor to make changes to it. + +

+

Client Directives

+

The client.conf file contains many directives that + determine how the client behaves:

+ + + +

Encryption

+
+

Examples

+
    +
    +Encryption Never
    +Encryption IfRequested
    +Encryption Required
    +Encryption Always
    +
    +
+

Description

+

The Encryption directive specifies the default + encryption settings for the client. The default setting is + IfRequested. + +

+

ServerName

+
+

Examples

+
    +
    +ServerName foo.bar.com
    +ServerName 11.22.33.44
    +
    +
+

Description

+

The ServerName directive specifies sets the remote + server that is to be used for all client operations. That is, it + redirects all client requests to the remote server. The default is to + use the local server ("localhost").

+

Changing the Printer Configuration

+

The CUPS scheduler (cupsd) uses the /etc/cups/printers.conf + file to store the list of available printers. This file contains only + locally defined printers, but not remote printers that are created + automatically. Each directive is listed on a line by itself followed by + its value. Comments are introduced using the number sign ("#") + character at the beginning of a line.

+

Since the printer configuration file consists of plain text, you can + use your favorite text editor to make changes to it. + +

+

Printer Directives

+

The printers.conf file contains many directives that + determine how the printer behaves:

+ + + +

Accepting

+
+

Examples

+
    +
    +Accepting yes
    +
    +Accepting no
    +
    +
+

Description

+

The Accepting directive defines the initial Boolean + value for the printer-is-accepting-job attribute which can + be set by the accept and reject commands.

+

This directive must appear inside a Printer + or DefaultPrinter + directive. + +

+

AllowUser

+
+

Examples

+
    +
    +AllowUser foo_user
    +AllowUser bar_user
    +
    +
+

Description

+

The AllowUser directive adds a username to the + requesting-user-name-allowed attribute which can be set by the +lpadmin -u command.

+

This directive must appear inside a Printer + or DefaultPrinter + directive. + +

+

DefaultPrinter

+
+

Examples

+
    +
    +<DefaultPrinter name/>
    +...
    +</Printer>
    +
    +
+

Description

+

The DefaultPrinter directive begins a printer definition + for the default server destination. It can be added by the +lpadmin command or if already defined, set as default by the +lpoptions -d command.

+ + +

DenyUser

+
+

Examples

+
    +
    +DenyUser foo_user
    +DenyUser bar_user
    +
    +
+

Description

+

The DenyUser directive adds a username to the + requesting-user-name-allowed attribute which can be set by the +lpadmin -u command.

+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+ + +

DeviceURI

+
+

Examples

+
    +
    +DeviceURI socket://foo.bar.com:9100
    +
    +
+

Description

+

The DeviceURI directive defines the value of the + device-uri-attribute attribute which can be set by the +lpadmin -v command.

+

This directive must appear inside a Printer + or DefaultPrinter + directive. + +

+

Info

+
+

Examples

+
    +
    +Info My Printer
    +
    +
+

Description

+

The Info directive defines the string for the + printer-info attribute which can be set by the lpadmin -D + command.

+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+ + +

JobSheets

+
+

Examples

+
    +
    +JobSheets none,standard
    +
    +
+

Description

+

The JobSheets directive specifies the default banner + pages to print before and after a print job. In the above example, only + a standard banner will print after each job.

+

The lpoptions -o job-sheets= command can be used to set + banners. For example, the following command would produce the same + results of a standard banner at the end of each print job + for the default printer.

+
    lpoptions -o job-sheets=none,standard
+

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.

+

The available banner pages depend on the local system configuration; + CUPS includes the following banner files:

+
    +
  • none - Do not produce a banner page.
  • +
  • classified - A banner page with a "classified" label at + the top and bottom.
  • +
  • confidential - A banner page with a "confidential" + label at the top and bottom.
  • +
  • secret - A banner page with a "secret" label at the top + and bottom.
  • +
  • standard - A banner page with no label at the top and + bottom.
  • +
  • topsecret - A banner page with a "top secret" label at + the top and bottom.
  • +
  • unclassified - A banner page with an "unclassified" + label at the top and bottom.
  • +
+

This directive must appear inside a Printer + or DefaultPrinter + directive. + +

+

KLimit

+
+

Examples

+
    +
    +KLimit 1234
    +
    +
+

Description

+

The KLimit directive defines the value of the + job-k-limit attribute which can be set by the lpadmin -o + job-k-limit= command.

+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+ + +

Location

+
+

Examples

+
    +
    +Location Building 3321
    +
    +
+

Description

+

The Location directive defines the string for the + printer-location attribute which can be set by the lpadmin + -L command.

+
+ + +
NOTE: +

Do not confuse this Location directive with the one for + cupsd.conf. They are completely different.

+
+
+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+ + +

PageLimit

+
+

Examples

+
    +
    +PageLimit 1234
    +
    +
+

Description

+

The PageLimit directive defines the value of the + job-page-limit attribute which can be set by the lpadmin -o + job-page-limit= command.

+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+ + +

Printer

+
+

Examples

+
    +
    +<Printer name/>
    +...
    +</Printer>
    +
    +
+

Description

+

The Printer directive begins a printer definition. It + can be added by the lpadmin command. + +

+

QuotaPeriod

+
+

Examples

+
    +
    +QuotaPeriod 604800
    +
    +
+

Description

+

The QuotaPeriod directive defines the value of the + job-quota-period attribute which can be set by the lpadmin + -o job-quota-period= command.

+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+ + +

State

+
+

Examples

+
    +
    +State stopped
    +
    +
+

Description

+

The State directive defines the initial value of the + printer-state attribute. The strings idle and + stopped correspond to the IPP enumeration values.

+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+ + +

StateMessage

+
+

Examples

+
    +
    +StateMessage Ready to print.
    +
    +
+

Description

+

The StateMessage directive defines the initial string + for the printer-state-message attribute. The following are + some example messages:

+
    +
  • Connected to host_name...
  • +
  • Connecting to printer_queue on port port_number +...
  • +
  • Network host host_name is busy; will retry in 30 + seconds...
  • +
  • Printer busy; will retry in 10 seconds...
  • +
  • Printer is busy; retrying print job...
  • +
  • Print file accepted - job ID id_number.
  • +
  • Ready to print.
  • +
  • Waiting for job to complete
  • +
+

This directive must appear inside a Printer + or DefaultPrinter + directive.

+

Changing the Classes Configuration

+

The CUPS scheduler (cupsd) uses the /etc/cups/classes.conf + file to store the list of available classes. This file contains only + locally defined classes, but not remote or implicit classes that are + created automatically. Each directive is listed on a line by itself + followed by its value. Comments are introduced using the number sign + ("#") character at the beginning of a line.

+

Since the classes configuration file consists of plain text, you can + use your favorite text editor to make changes to it. + +

+

Classes Directives

+

The classes.conf file contains many directives that + determine how the classes behaves:

+ + + +

Accepting

+
+

Examples

+
    +
    +Accepting yes
    +
    +Accepting no
    +
    +
+

Description

+

The Accepting directive defines the initial Boolean + value for the printer-is-accepting-job attribute which can + be set by the accept and reject commands.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

AllowUser

+
+

Examples

+
    +
    +AllowUser foo_user
    +AllowUser bar_user
    +
    +
+

Description

+

The AllowUser directive adds a username to the + requesting-user-name-allowed attribute which can be set by the +lpadmin -u command.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

Class

+
+

Examples

+
    +
    +<Class name/>
    +...
    +</Class>
    +
    +
+

Description

+

The Class directive begins a class definition. It can be + added by the lpadmin -c command.

+ + +

DefaultClass

+
+

Examples

+
    +
    +<DefaultClass name/>
    +...
    +</DefaultClass>
    +
    +
+

Description

+

The DefaultClass directive begins a class definition for + the default server destination. It can be added by the lpadmin -c + command or if already defined, set as default by the lpoptions -d + command.

+ + +

DenyUser

+
+

Examples

+
    +
    +DenyUser foo_user
    +DenyUser bar_user
    +
    +
+

Description

+

The DenyUser directive adds a username to the + requesting-user-name-allowed attribute which can be set by the +lpadmin -u command.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

Info

+
+

Examples

+
    +
    +Info My Printer
    +
    +
+

Description

+

The Info directive defines the string for the + printer-info attribute which can be set by the lpadmin -D + command.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

JobSheets

+
+

Examples

+
    +
    +JobSheets none,standard
    +
    +
+

Description

+

The JobSheets directive specifies the default banner + pages to print before and after a print job. In the above example, only + a standard banner will print after each job.

+

The lpoptions -o job-sheets= command can be used to set + banners. For example, the following command would produce the same + results of a standard banner at the end of each print job + for the default class.

+
    lpoptions -o job-sheets=none,standard
+

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.

+

The available banner pages depend on the local system configuration; + CUPS includes the following banner files:

+
    +
  • none - Do not produce a banner page.
  • +
  • classified - A banner page with a "classified" label at + the top and bottom.
  • +
  • confidential - A banner page with a "confidential" + label at the top and bottom.
  • +
  • secret - A banner page with a "secret" label at the top + and bottom.
  • +
  • standard - A banner page with no label at the top and + bottom.
  • +
  • topsecret - A banner page with a "top secret" label at + the top and bottom.
  • +
  • unclassified - A banner page with an "unclassified" + label at the top and bottom.
  • +
+

This directive must appear inside a Class + or DefaultClass directive. + +

+

KLimit

+
+

Examples

+
    +
    +KLimit 1234
    +
    +
+

Description

+

The KLimit directive defines the value of the + job-k-limit attribute which can be set by the lpadmin -o + job-k-limit= command.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

Location

+
+

Examples

+
    +
    +Location Building 3321
    +
    +
+

Description

+

The Location directive defines the string for the + printer-location attribute which can be set by the lpadmin + -L command.

+
+ + +
NOTE: +

Do not confuse this Location directive with the one for + cupsd.conf. They are completely different.

+
+
+

This directive must appear inside a Class + or DefaultClass directive. + +

+

PageLimit

+
+

Examples

+
    +
    +PageLimit 1234
    +
    +
+

Description

+

The PageLimit directive defines the value of the + job-page-limit attribute which can be set by the lpadmin -o + job-page-limit= command.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

Printer

+
+

Examples

+
    +
    +Printer foo
    +Printer bar
    +Printer foo@bar
    +
    +
+

Description

+

The Printer directive adds a printer to the class. It + can be added by the lpadmin -c command.

+
+ + +
NOTE: +

Do not confuse this Printer directive with the one for + printers.conf. They are completely different.

+
+
+

This directive must appear inside a Class + or DefaultClass directive.

+ + +

QuotaPeriod

+
+

Examples

+
    +
    +QuotaPeriod 604800
    +
    +
+

Description

+

The QuotaPeriod directive defines the value of the + job-quota-period attribute which can be set by the lpadmin + -o job-quota-period= command.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

State

+
+

Examples

+
    +
    +State stopped
    +
    +
+

Description

+

The State directive defines the initial value of the + printer-state attribute. The strings idle and + stopped correspond to the IPP enumeration values.

+

This directive must appear inside a Class + or DefaultClass directive. + +

+

StateMessage

+
+

Examples

+
    +
    +StateMessage Ready to print.
    +
    +
+

Description

+

The StateMessage directive defines the initial string + for the printer-state-message attribute. The following are + some example messages:

+
    +
  • Connected to host_name...
  • +
  • Connecting to class_queue on port port_number +...
  • +
  • Network host host_name is busy; will retry in 30 + seconds...
  • +
  • Printer busy; will retry in 10 seconds...
  • +
  • Printer is busy; retrying print job...
  • +
  • Print file accepted - job ID id_number.
  • +
  • Ready to print.
  • +
  • Waiting for job to complete
  • +
+

This directive must appear inside a Class + or DefaultClass directive.

+ + +

Printing System Security

+

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.

+

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.

+

CUPS maintains a list of locations that have access control and/or + authentication enabled. Locations are specified using the + Location directive:

+ +

Locations generally follow the directory structure of the + DocumentRoot directory, however CUPS does have several + virtual locations for administration, classes, jobs, and printers: +

+ + + + + + + + + + + + +
LocationDescription
/adminThe path for all administration operations.
/classesThe path for all classes.
/classes/nameThe resource for class name.
/jobsThe path for all jobs.
/jobs/idThe resource for job id.
/printersThe path for all printers.
/printers/nameThe path for printer name.
/printers/name.ppdThe PPD file path for printer +name.
+
+

+

Authentication Using Certificates

+

CUPS supports a local certificate-based authentication scheme that + can be used in place of Basic or Digest + authentication by clients connecting through the localhost + interface. Certificate authentication is not supported or allowed from + clients on any other interface.

+

Certificates are 128-bit random numbers that refer to an internal + authentication record in the server. A client connecting via the +localhost interface sends a request with an authorization header + of:

+
    +
    +Authorization: Local 0123456789ABCDEF0123456789ABCDEF
    +
    +
+

The server then looks up the local certificate and authenticates + using the username associated with it.

+

Certificates are generated by the server automatically and stored in + the /etc/cups/certs directory using the process ID of the + CGI program started by the server. Certificate files are only readable + by the User and +Group defined in the cupsd.conf file. When the CGI + program ends the certificate is removed and invalidated automatically.

+

The special file /etc/cups/certs/0 defines the root + certificate which can be used by any client running as the + super-user or another user that is part of the group defined by the + SystemGroup directive. The root certificate is + automatically regenerated every 5 minutes.

+

Using Basic Authentication

+

Basic authentication uses UNIX users and passwords to authenticate + access to resources such as printers and classes, and to limit access + to administrative functions.

+
+ + +
NOTE: +

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.

+
+
+

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.

+

Once a valid username and password is authenticated by CUPS, any + additional group membership requirements are checked.

+
+ + +
NOTE: +

The root user is considered by CUPS to be a member of every group.

+
+
+ + +

Use the AuthType directive to enable Basic + authentication:

+
    +
    +AuthType Basic
    +
    +
+ + +

Using Digest Authentication

+

Digest authentication uses users and passwords defined in the + /etc/cups/passwd.md5 file to authenticate access to resources + such as printers and classes, and to limit access to administrative + functions.

+
+ + +
NOTE: +

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.

+

The current CUPS implementation of Digest authentication uses the + client's hostname or IP address for the "nonce" 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 "session" + authentication which adds the request data to the MD5 sum, providing + even better authentication and security.

+

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. + Support for Digest authentication in web browsers is not yet + universally available.

+
+
+ + +

The lppasswd(1) command is used to add, change, or + remove accounts from the passwd.md5 file. To add a user to + the default system group, type:

+
    +
    +lppasswd -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
    +
+ + +

Once added, a user can change his/her password by typing:

+
    +
    +lppasswd ENTER
    +Old password: (password) ENTER [password is not echoed]
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
    +
+ + +

To remove a user from the password file, type:

+
    +
    +lppasswd -x user ENTER
    +
    +
+

Once a valid username and password is authenticated by CUPS, any + additional group membership requirements are checked.

+
+ + +
NOTE: +

The root user is considered by CUPS to be a member of every group.

+
+
+

Use the AuthType directive to enable Digest + authentication:

+
    +
    +AuthType Digest
    +
    +
+

System and Group Authentication

+

The AuthClass directive + controls the level of authentication to perform. System + and Group authentication extend the normal user-based + authentication to require membership in a UNIX group. For System + authentication each user must belong to the sys, +system, or root group; the actual group depends on + the operating system.

+

For Group authentication each user must belong to the + group named by the AuthGroupName + directive:

+
    +
    +<Location /path>
    +AuthType Digest
    +AuthClass Group
    +AuthGroupName mygroup
    +</Location>
    +
    +
+

The named group must be a valid UNIX user group, usually defined in + the /etc/group or /etc/netgroup files. + Additionally, when using Digest authentication you need to create user + accounts with the named group:

+
    +
    +lppasswd -g mygroup -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
    +
+ + +

Printer Accounting

+

CUPS maintains a log of all accesses, errors, and pages that are + printed. The log files are normally stored in the /var/log/cups + directory. You can change this by editing the /etc/cups/cupsd.conf + configuration file.

+

The access_log File

+

The access_log file lists each HTTP resource that is + accessed by a web browser or CUPS/IPP client. Each line is in the + so-called "Common Log Format" used by many web servers and web + reporting tools:

+
    +
    +host group user date-time \"method resource version\" status bytes
    +
    +127.0.0.1 - - [20/May/1999:19:20:29 +0000] "POST /admin/ HTTP/1.1" 401 0
    +127.0.0.1 - mike [20/May/1999:19:20:31 +0000] "POST /admin/ HTTP/1.1" 200 0
    +
    +
+

The host field will normally only be an IP address unless you + have enabled the HostNameLookups + directive in the cupsd.conf file.

+

The group field always contains "-" in CUPS.

+

The user field is the authenticated username of the requesting + user. If no username and password is supplied for the request then this + field contains "-".

+

The date-time field is the date and time of the request in + local time and is in the format:

+
    +
    +[DD/MON/YYYY:HH:MM:SS +ZZZZ]
    +
    +
+

where ZZZZ is the timezone offset in hours and minutes from + coordinated universal time (UTC). UTC may sometimes be referred to as + GMT or ZULU on legacy systems.

+

The method field is the HTTP method used ("GET", "PUT", + "POST", etc.)

+

The resource field is the filename of the requested resource.

+

The version field is the HTTP specification version used by + the client. For CUPS clients this will always be "HTTP/1.1".

+

The status field contains the HTTP result status of the + request. Usually it is "200", but other HTTP status codes are possible. + For example, 401 is the "unauthorized access" status in the example + above.

+

The bytes field contains the number of bytes in the request. + For POST requests the bytes field contains the number of bytes + that was received from the client.

+

The error_log File

+

The error_log file lists messages from the scheduler + (errors, warnings, etc.):

+
    +
    +level date-time message
    +
    +I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
    +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'.
    +
    +
+

The level field contains the type of message:

+
    +
  • E - An error occurred.
  • +
  • W - The server was unable to perform some action.
  • +
  • I - Informational message.
  • +
  • D - Debugging message.
  • +
+

The date-time field contains the date and time of when the + page started printing. The format of this field is identical to the + data-time field in the access_log file.

+

The message fields contains a free-form textual message.

+

The page_log File

+

The page_log file lists each page that is sent to a + printer. Each line contains the following information:

+
    +
    +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
    +
    +
+

The printer 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.

+

The user field contains the name of the user (the IPP +requesting-user-name attribute) that submitted this file for + printing.

+

The job-id 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!

+

The date-time field contains the date and time of when the + page started printing. The format of this field is identical to the + data-time field in the access_log file.

+

The page-number and num-pages 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 num-pages field + will always be 1.

+

The job-billing field contains a copy of the job-billing + attribute provided with the IPP create-job or +print-job requests or "-" if none was provided. + +

+

File Typing and Filtering

+

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 /etc/cups + directory (or a directory specified by the +ServerRoot 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.

+

The mime.types and mime.convs files define the + standard file types and filters that are available on the system.

+

mime.types

+

The mime.types 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 text/html + file type is defined as:

+
    +
    +text/html       html htm \
    +	printable(0,1024) + \
    +	(string(0,"<HTML>") string(0,"<!DOCTYPE"))
    +
    +
+

The first two rules say that any file with an extension of .html + or .htm is a HTML file. The third rule says that any file + whose first 1024 characters are printable text and starts with the + strings <HTML> or <!DOCTYPE is a HTML file as + well.

+

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.

+

The available tests are:

+
    +
  • ( expr ) - Parenthesis for expression grouping
  • +
  • + - Logical AND
  • +
  • , or whitespace - Logical OR
  • +
  • ! - Logical NOT
  • +
  • match("pattern") - Pattern match on filename
  • +
  • extension - Pattern match on "*.extension"
  • +
  • ascii(offset,length) - True if bytes are valid + printable ASCII (CR, NL, TAB, BS, 32-126)
  • +
  • printable(offset,length) - True if bytes are printable + 8-bit chars (CR, NL, TAB, BS, 32-126, 160-254)
  • +
  • string(offset,"string") - True if bytes are identical + to string
  • +
  • contains(offset,range,"string") - True if the range of + bytes contains the string
  • +
  • char(offset,value) - True if byte is identical
  • +
  • short(offset,value) - True if 16-bit integer is + identical (network or "big-endian" byte order)
  • +
  • int(offset,value) - True if 32-bit integer is identical + (network or "big-endian" byte order)
  • +
  • locale("string") - True if current locale matches + string
  • +
+

All numeric values can be in decimal (123), octal (0123), or + hexadecimal (0x123) as desired. + +

+

Strings can be in quotes, all by themselves, as a string of + hexadecimal values, or some combination:

+
    +
    +"string"
    +'string'
    +string
    +<737472696e67>
    +<7374>ring
    +
    +
+

As shown in the text/html example, rules can continue on + multiple lines using the backslash (\) character. A more complex + example is the image/jpeg rules:

+
    +
    +image/jpeg      jpeg jpg jpe string(0,<FFD8FF>) &&\
    +	(char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
    +	 char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
    +	 char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
    +	 char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
    +
    +
+

This rule states that any file with an extension of .jpeg, + .jpg, or .jpe is a JPEG file. In addition, any file + starting with the hexadecimal string <FFD8FF> (JPEG + Start-Of-Image) followed by a character between and including +0xe0 and 0xef (JPEG APPn markers) is also a JPEG + file.

+

mime.convs

+

The mime.convs file defines all of the filter programs + that are known to the system. Each line consists of:

+
    +
    +source destination cost program
    +
    +text/plain application/postscript 50 texttops
    +application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
    +image/* application/vnd.cups-postscript 50 imagetops
    +image/* application/vnd.cups-raster 50 imagetoraster
    +
    +
+

The source field is a MIME type, optionally using a wildcard + for the super-type or sub-type (e.g. "text/plain", "image/*", + "*/postscript").

+

The destination field is a MIME type defined in the + mime.types file.

+

The cost 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 image/jpeg to +application/vnd.cups-raster, you could use the imagetops + and pstoraster filters for a total cost of 100, or the +imagetoraster filter for a total cost of 50.

+

The program field defines the filter program to run; the + special program "-" 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:

+
    +
    +program job user title options [filename]
    +
    +
+

If specified, the filename 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. + +

+

Adding Filetypes and Filters

+

Adding a new file type or filter is fairly straight-forward. Rather + than adding the new type and filter to the mime.types and + mime.convs files which are overwritten when you upgrade to a new + version of CUPS, you simple need to create new files with .types + and .convs extensions in the /etc/cups directory. + We recommend that you use the product or format name, e.g.:

+
    +
    +myproduct.types
    +myproduct.convs
    +
    +
+

If you are providing a filter for a common file format or printer, + add the company or author name:

+
    +
    +acme-msword.types
    +acme.msword.convs
    +
    +
+

This will help to prevent name collisions if you install many + different file types and filters.

+

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 cupsd process as + described earlier in "Restarting the CUPS Server" +.

+

Printer Drivers and PPD Files

+

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 cupsFilter + attributes:

+
    +
    +*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
    +
    +
+

The filter is specified using the source file type only; the + destination file type is assumed to be printer/name - + suitable for sending to the printer.

+

Writing Your Own Filter or Printer Driver

+

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.

+

7 - Printing with Other + Systems

+

This chapter describes how to print from client systems that use the + LPD, Mac OS, or Windows printing protocols.

+

The Basics

+

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.

+

Printing from LPD Clients

+

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.

+

The cups-lpd(8) program provides support for LPD clients + and can be used from either the inetd(8) or +xinetd(8) programs. Add the following line to the + /etc/inetd.conf file to enable LPD support on your server through + the inetd program:

+
    +
    +printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
    +
    +
+

The path to the cups-lpd may vary depending on your + installation.

+

Once you have added this line, send the inetd process a +HUP signal or reboot the system:

+
    +
    +killall -HUP inetd ENTER [IRIX and some versions of Linux]
    +kill -HUP pid ENTER [Others]
    +reboot ENTER [For all systems if the HUP signal fails]
    +
    +
+

If you are using the xinetd program, create a file named + /etc/xinetd.d/printer containing the following lines:

+
    +
    +service printer
    +{
    +socket_type = stream
    +protocol = tcp
    +wait = no
    +user = lp
    +server = /usr/lib/cups/daemon/cups-lpd
    +}
    +
    +
+

The xinetd program automatically reads the new + configuration file and enables LPD printing support. +

+ + +
Warning: +

cups-lpd currently does not perform any access control + based on the settings in cupsd.conf or in the + hosts.allow or hosts.deny files used by TCP wrappers. + Therefore, running cups-lpd on your server will allow any + computer on your network (and perhaps the entire Internet) to print to + your server.

+

While xinetd has built-in access control support, you + should use the TCP wrappers package with inetd to limit + access to only those computers that should be able to print through + your server.

+
+
+

+

Printing to LPD Servers

+

CUPS provides the lpd backend for printing to LPD-based + servers and printers. Use a device URI of lpd://server/name + to print to a printer on an LPD server, where server is + the hostname or IP address of the server and name is the + queue name.

+

Microsoft Windows NT provides an LPD service under the name "TCP/IP + Printing Services". To enable LPD printing on NT, open the "Services" + control panel, select the "TCP/IP Printing Services" service, and click + on the "Start" button. Any shared printer will then be available via + the LPD protocol.

+

Printing from Mac OS Clients

+

CUPS does not provide Mac OS support directly. However, there are + several free and commercial software packages that do.

+

Columbia Appletalk Package (CAP)

+

Because the CAP LaserWriter server (lwsrv(8)) does not + support specification of PPD files, we do not recommend that you use + CAP with CUPS. However, you can run the lpsrv program for + limited printing with the command:

+
    +
    +lwsrv -n "Name" -p printer -a /usr/lib/adicts -f /usr/lib/LW+Fonts
    +
    +
+

where Name is the name you want to use when sharing the + printer, and printer is the name of the CUPS print queue. + +

+

XINET KA/Spool

+

To use your system as a print server for Mac OS clients, configure + each printer using a papserver(8) in the + /usr/adm/appletalk/services file, specifying the corresponding + PPD file in the /etc/cups/ppd directory for each printer. + For a printer named MyPrinter the entry would look like:

+
    +
    +/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/MyPrinter.ppd \
    +"Printer Description" MyPrinter
    +
    +
+
+ + +
NOTE: +

Enter the text above on a single line without the backslash (\) + character.

+
+
+

NetATalk

+

To use your system as a print server for Mac OS clients, configure + each printer in the papd.conf file, specifying the + corresponding PPD file in the /etc/cups/ppd directory for + each printer. For a printer named MyPrinter the entry + would look like:

+
    +
    +Printer Description:MyPrinter@MyServer:\
    +:pr=|/usr/bin/lp -d MyPrinter:\
    +:op=daemon:\
    +:pd=/etc/cups/ppd/MyPrinter.ppd:
    +
    +
+ + +

Printing to Mac OS Servers

+

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 /usr/lib/cups/backend directory that sends a print file + using the appropriate command. The following is a short script that + will run the papif command provided with CAP.

+

After copying this script to /usr/lib/cups/backend/cap, + specify a device URI of cap://server/printer to use this + backend with a print queue. + +

+
    +
    +"/usr/lib/cups/backend/cap"
    +#!/bin/sh
    +#
    +# Usage: cap job user title copies options [filename]
    +#
    +
    +# No arguments means show available devices...
    +
    +if test ${#argv} = 0; then
    +echo "network cap \"Unknown\" \"Mac OS Printer via CAP\""
    +exit 0
    +fi
    +
    +# Collect arguments...
    +
    +user=$2
    +copies=$4
    +
    +if test ${#argv} = 5; then
    +# Get print file from stdin; copies have already been handled...
    +file=/var/tmp/$$.prn
    +copies=1
    +cat > $file
    +else
    +# Print file is on command-line...
    +file=$6
    +fi
    +
    +# Create a dummy cap.printers file for this printer based
    +# upon a device URI of "cap://server/printer"...
    +
    +echo $PRINTER/$DEVICE_URI | \
    +awk -F/ '{print $1 "=" $5 ":LaserWriter@" $4}' > /var/tmp/$$.cap
    +
    +CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
    +
    +# Send the file to the printer, once for each copy. This assumes that you
    +# have properly initialized the cap.printers file...
    +
    +while [ $copies -gt 0 ]; do
    +papif -n $user < $file
    +
    +copies=`expr $copies - 1`
    +done
    +
    +# Remove any temporary files...
    +if test ${#argv} = 5; then
    +/bin/rm -f $file
    +fi
    +
    +/bin/rm -f /var/tmp/$$.cap
    +
    +exit 0
    +
    +
+ + +

Printing from Windows Clients

+

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:

+ +

To configure SAMBA for CUPS, edit the smb.conf file and + replace the existing printing commands and options with the line:

+
    +
    +printing = cups
    +printcap name = cups
    +
    +
+

That's all there is to it! Remote users will now be able to browse + and print to printers on your system.

+

Exporting Printer Drivers

+

You can optionally export printer drivers from your CUPS server using + the cupsaddsmb command and the SAMBA 2.2.0 or higher + software.

+

Before you can export the printers you must download the current + Adobe PostScript printer drivers from the Adobe web site ( +http://www.adobe.com/). Use the free unzip software to + extract the files from the self-extracting ZIP file containing the + drivers; you will need the following files:

+
    +
    +ADFONTS.MFM
    +ADOBEPS4.DRV
    +ADOBEPS4.HLP
    +ADOBEPS5.DLL
    +ADOBEPSU.DLL
    +ADOBEPSU.HLP
    +DEFPRTR2.PPD
    +ICONLIB.DLL
    +PSMON.DLL
    +
    +
+

Copy these files to the /usr/share/cups/drivers directory + - you may need to rename some of the files so the filenames are all + UPPERCASE.

+

Next, configure SAMBA (via the smb.conf file) to support + printing through CUPS and provide a printer driver download share, as + follows:

+
    +
    +[global]
    +load printers = yes
    +printing = cups
    +printcap name = cups
    +
    +[printers]
    +comment = All Printers
    +path = /var/spool/samba
    +browseable = no
    +public = yes
    +guest ok = yes
    +writable = no
    +printable = yes
    +printer admin = root
    +
    +[print$]
    +comment = Printer Drivers
    +path = /etc/samba/drivers
    +browseable = yes
    +guest ok = no
    +read only = yes
    +write list = root
    +
    +
+

This configuration assumes a FHS-compliant installation of SAMBA; + adjust the [printers] and [print$] share paths accordingly on your + system as needed. That is, the directory for your printer drivers can + be anywhere on the system; just make sure it is writable by the users + specified by the write list directive plus readable and + executable by all users. Also, make sure that you have SAMBA passwords + defined for each user in the write list using SAMBA's +smbpasswd(1) command. Otherwise you will not be able to + authenticate.

+

Finally, run the cupsaddsmb command to export the + printer drivers for one or more queues:

+
    +
    +cupsaddsmb -U root printer1 ... printerN ENTER
    +
    +
+

Running cupsaddsmb with the -a option will + export all printers:

+
    +
    +cupsaddsmb -U root -a ENTER
    +
    +
+

Notice in the above examples that the user root was used + which was defined in the write list of the smb.conf + file.

+

Printing to Windows Servers

+

CUPS can print to Windows servers in one of two ways. The first way + uses the LPD protocol on the CUPS system and the "TCP/IP Printing + Services" on the Windows system. You can find out more about this + configuration in the LPD section earlier in this + chapter.

+

The second way is through the Microsoft Server Message Block ("SMB") + protocol. Support for this protocol is provided with the free SAMBA + software package. You can download SAMBA from:

+ +

To configure CUPS for SAMBA, run the following command:

+
    +
    +ln -s `which smbspool` /usr/lib/cups/backend/smb ENTER
    +
    +
+

The smbspool(1) 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:

+
    +
    +smb://workgroup/server/sharename
    +smb://server/sharename
    +smb://user:pass@workgroup/server/sharename
    +smb://user:pass@server/sharename
    +
    +
+

The workgroup name need only be specified if your system + is using a different workgroup. The user:pass strings are + required when printing to Windows NT servers or to shares with + passwords enabled under Windows 95 and 98.

+

A - Software License Agreement

+

Common UNIX Printing System License + Agreement

+

Copyright 1997-2002 by Easy Software Products +
44141 AIRPORT VIEW DR STE 204 +
HOLLYWOOD, MARYLAND 20636-3111 USA +
+
Voice: +1.301.373.9600 +
Email: cups-info@cups.org +
WWW: http://www.cups.org

+

Introduction

+

The Common UNIX Printing SystemTM, ("CUPSTM"), + is provided under the GNU General Public License ("GPL") and GNU + Library General Public License ("LGPL"), Version 2, with exceptions for + Apple operating systems and the OpenSSL toolkit. A copy of the + exceptions and licenses follow this introduction.

+

The GNU LGPL applies to the CUPS API library, located in the "cups" + subdirectory of the CUPS source distribution and in the "cups" include + directory and library files in the binary distributions. The GNU GPL + applies to the remainder of the CUPS distribution, including the + "pdftops" filter which is based upon Xpdf and the CUPS imaging library.

+

For those not familiar with the GNU GPL, the license basically allows + you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in source or binary form.
  • +
  • Sell verbatim copies of the software for a media fee, or sell + support for the software.
  • +
  • Distribute or sell printer drivers and filters that use CUPS so long + as source code is made available under the GPL.
  • +
+

What this license does not 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. The only exceptions to this are the portions of + the CUPS software covered by the Apple operating system license + exceptions outlined later in this license agreement.

+

The GNU LGPL relaxes the "link-to" restriction, allowing you to + develop applications that use the CUPS API library under other licenses + and/or conditions as appropriate for your application.

+

License Exceptions

+

In addition, as the copyright holder of CUPS, Easy Software Products + grants the following special exceptions:

+
    +
  1. Apple Operating System Development License Exception; +
      +
    1. Software that is developed by any person or entity for an Apple + Operating System ("Apple OS-Developed Software"), including but not + limited to Apple and third party printer drivers, filters, and backends + for an Apple Operating System, that is linked to the CUPS imaging + library or based on any sample filters or backends provided with CUPS + shall not be considered to be a derivative work or collective work + based on the CUPS program and is exempt from the mandatory source code + release clauses of the GNU GPL. You may therefore distribute linked + combinations of the CUPS imaging library with Apple OS-Developed + Software without releasing the source code of the Apple OS-Developed + Software. You may also use sample filters and backends provided with + CUPS to develop Apple OS-Developed Software without releasing the + source code of the Apple OS-Developed Software.
    2. +
    3. An Apple Operating System means any operating system software + developed and/or marketed by Apple Computer, Inc., including but not + limited to all existing releases and versions of Apple's Darwin, Mac OS + X, and Mac OS X Server products and all follow-on releases and future + versions thereof.
    4. +
    5. This exception is only available for Apple OS-Developed Software and + does not apply to software that is distributed for use on other + operating systems.
    6. +
    7. All CUPS software that falls under this license exception have the + following text at the top of each source file:
      This file is + subject to the Apple OS-Developed Software exception.
    8. +
    +
  2. +
  3. OpenSSL Toolkit License Exception; +
      +
    1. Easy Software Products explicitly allows the compilation and + distribution of the CUPS software with the OpenSSL Toolkit.
    2. +
    +
  4. +
+

No developer is required to provide these exceptions in a derived + work.

+

Trademarks

+

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. Please contract Easy + Software Products for written permission to use them in derivative + products. 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.

+

Binary Distribution Rights

+

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.

+

The Common UNIX Printing System provides a "pdftops" filter that is + based on the Xpdf software. For binary distribution licensing of this + software, please contact:

Derek B. Noonburg +
Email: derekn@foolabs.com +
WWW: + http://www.foolabs.com/xpdf/

+

Support

+

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:

+ + + +

GNU GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow.

+

GNU GENERAL PUBLIC LICENSE +
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+
    +
  1. 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 "Program", below, + refers to any such program or work, and a "work based on the Program" + 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 "modification".) Each licensee is addressed as "you". +

    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.

    +
  2. 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. +

    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.

    +
  3. 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: +
      +
    1. You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change.
    2. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +

    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.

    +

    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.

    +

    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.

    +
  4. 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: +
      +
    1. 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,
    2. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +

    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.

    +

    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.

    +
  5. 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.
  6. +
  7. 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.
  8. +
  9. 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.
  10. +
  11. 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. +

    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.

    +

    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.

    +

    This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

    +
  12. 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.
  13. +
  14. 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. +

    Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", 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.

    +
  15. 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.
  16. + + + + + + +
+

NO WARRANTY

+
    +
  1. 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 "AS IS" 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.
  2. +
  3. 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.
  4. +
+

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, while the latter only + works together with the library.

+

Note that it is possible for a library to be covered by the ordinary + General Public License rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+

0. 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 "this License"). Each + licensee is addressed as "you".

+

A "library" 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.

+

The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" 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 "modification".)

+

"Source code" 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.

+

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.

+

1. 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.

+

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.

+

2. 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:

+
    +
  1. The modified work must itself be a software library. +

    +
  2. You must cause the files modified to carry prominent notices stating + that you changed the files and the date of any change. +

    +
  3. You must cause the whole of the work to be licensed at no charge to + all third parties under the terms of this License. +

    +
  4. 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. +

    (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.)

    +
  5. + + + +
+

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.

+

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.

+

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.

+

3. 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.

+

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.

+

This option is useful when you wish to copy part of the code of the + Library into a program that is not a library.

+

4. 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.

+

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.

+

5. 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 "work that uses the + Library". Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License.

+

However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. Section + 6 states terms for distribution of such executables.

+

When a "work that uses the Library" 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.

+

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.)

+

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.

+

6. As an exception to the Sections above, you may + also compile or link a "work that uses the Library" 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.

+

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:

+
    +
  1. 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 "work that uses the Library", 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.) +

    +
  2. 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. +

    +
  3. 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. +

    +
  4. Verify that the user has already received a copy of these materials + or that you have already sent this user a copy.
  5. + + + +
+

For an executable, the required form of the "work that uses the + Library" 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.

+

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.

+

7. 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:

+
    +
  1. 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. +

    +
  2. 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.
  3. + +
+

8. 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.

+

9. 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.

+

10. 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.

+

11. 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.

+

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.

+

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.

+

This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

+

12. 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.

+

13. 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.

+

Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and "any + later version", 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.

+

14. 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.

+

NO WARRANTY

+

15. 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 "AS IS" 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.

+

16. 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.

+

END OF TERMS AND CONDITIONS

+

B - Common Network Settings +

+

This appendix covers many of the popular TCP/IP network interfaces + and printer servers available on the market today.

+

Configuring a Network Interface

+

When you first install a network printer or print server on your LAN, + you need to set the Internet Protocol ("IP") address. On most + higher-end "workgroup" 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.

+

To setup your printer or print server for remote address assignment, + you'll need the Ethernet Media Access Control ("MAC") 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. + +

+

Configuring the IP Address Using ARP

+

The easiest way to set the IP address of a network device is to use + the arp(8) command. The arp sends an Address + Resolution Protocol ("ARP") packet to the specified Ethernet MAC + address, setting the network device's IP address:

+
    +
    +arp -s ip-address ethernet-address ENTER
    +arp -s host.domain.com 08:00:69:00:12:34 ENTER
    +arp -s 192.0.2.2 08:00:69:00:12:34 ENTER
    +
    +
+

Configuring the IP Address Using RARP

+

The most flexible way to remotely assign IP addresses under UNIX is + through the Reverse Address Resolution Protocol ("RARP"). 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.

+

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 arp command is the way to go.

+

Some UNIX operating systems use a program called rarpd(8) + to manage RARP. Others, like Linux, support this protocol in the + kernel. For systems that provide the rarpd program you + will need to start it before RARP lookups will work:

+
    +
    +rarpd ENTER
    +
    +
+

Under IRIX you can enable this functionality by default using:

+
    +
    +chkconfig rarpd on ENTER
    +
    +
+

Both the rarpd program and kernel RARP support read a + list of Ethernet and IP addresses from the file /etc/ethers. + Each line contains the Ethernet address (colon delimited) followed by + an IP address or hostname like:

+
    +
    +08:00:69:00:12:34 myprinter.mydomain.com
    +08:00:69:00:12:34 192.0.2.2
    +
    +
+

Add a line to this file and cycle the power on the printer or print + server to set its address. + +

+

Configuring the IP Address Using BOOTP

+

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 bootpd(8) program supplied + with UNIX you simply need to add a line to the /etc/bootptab + file; for IRIX:

+
    +
    +myprinter 08:00:69:00:12:34 192.0.2.2 myprinter.boot
    +
    +
+ + +

Newer versions of bootpd use a different format:

+
    +
    +myprinter:ha=080069001234:ip=192.0.2.2:t144=myprinter.boot
    +
    +
+

The myprinter.boot file resides in the + /usr/local/boot directory by default. If you do not need to + provide a boot file you may leave the last part of the line blank.

+ + +
+ + +
NOTE: +

Some versions of UNIX do not enable the BOOTP service by default. The + /etc/inetd.conf usually contains a line for the BOOTP service + that can be uncommented if needed.

+
+
+

Verifying the Printer Connection

+

To test that the IP address has been successfully assigned and that + the printer is properly connected to your LAN, type:

+
    +
    +ping ip-address ENTER
    +
    +
+

If the connection is working properly you will see something like:

+
    +
    +ping myprinter ENTER
    +PING myprinter (192.0.2.2): 56 data bytes
    +64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
    +64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
    +
    +
+

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. + +

+

Common Network Interface Settings

+

Once you have set the IP address you can access the printer or print + server using the ipp, lpd, or socket + backends. The following is a list of common network interfaces and + printer servers and the settings you should use with CUPS: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Model/ManufacturerDevice + URI(s)
Apple LaserWriterlpd:// +address/PASSTHRU
Axis w/o IPP +
(see directions)
socket://address +:9100 +
socket://address:9101 +
socket://address:9102
Axis w/IPPipp://address +/LPT1 +
ipp://address/LPT2 +
ipp://address/COM1
Castelle LANpressTM +lpd://address/pr1 +
lpd://address/pr2 +
lpd://address/pr3
DPI NETPrintlpd://address +/pr1 +
lpd://address/pr2 +
lpd://address/pr3
EFI® Fiery® RIPlpd:// +address/print
EPSON® Multiprotocol Ethernet + Interface Boardsocket://address
Extended System ExtendNET +lpd://address/pr1 +
lpd://address/pr2 +
lpd://address/pr3
Hewlett Packard JetDirect w/o IPP +socket://address:9100 +
socket://address:9101 +
socket://address:9102
Hewlett Packard JetDirect w/IPP +ipp://address/ipp +
ipp://address/ipp/port1 +
ipp://address/ipp/port2 +
ipp://address/ipp/port3
Intel® NetportExpress XL, PRO/100 +lpd://address/LPT1_PASSTHRU +
lpd://address/LPT2_PASSTHRU +
lpd://address/COM1_PASSTHRU
LexmarkTM MarkNet +lpd://address/ps
Linksys EtherFast® +
(see directions)
socket://address +:4010 +
socket://address:4020 +
socket://address:4030
Kodak®lpd://address/ps
QMS® CrownNetTM +lpd://address/ps
Tektronix® PhaserShareTM +socket://address:9100
XEROX® 4512 NIClpd:// +address/PORT1
XEROX® XNIClpd://address +/PASSTHRU
XEROX® (most others)socket:// +address:5503
+
+

+

Configuring Axis Print Servers

+

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. + +

+

Each print server contains a configuration file named config + 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 ftp(1) program:

+
    +
    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> get config ENTER
    +local: config remote: config
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2),
    +(mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+ + +

Next, edit the file with your favorite text editor and locate the + lines beginning with:

+
    +
    +RTN_OPT.     : YES
    +RTEL_PR1.    : 0
    +RTEL_PR2.    : 0
    +RTEL_PR3.    : 0
    +RTEL_PR4.    : 0
    +RTEL_PR5.    : 0
    +RTEL_PR6.    : 0
    +RTEL_PR7.    : 0
    +RTEL_PR8.    : 0
    +
    +
+ + + Change the RTN_OPT line to read: +
    +
    +RTN_OPT.     : NO
    +
    +
+ + +

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:

+
    +
    +RTEL_PR1.    : 9100
    +RTEL_PR2.    : 9101
    +RTEL_PR3.    : 9102
    +RTEL_PR4.    : 9103
    +RTEL_PR5.    : 9104
    +RTEL_PR6.    : 9105
    +RTEL_PR7.    : 9106
    +RTEL_PR8.    : 9107
    +
    +
+ + +

This essentially makes the Axis print server look like a Hewlett + Packard JetDirect EX print server. Save the file and then upload the + new config file using the ftp command:

+
    +
    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> put config CONFIG ENTER
    +local: config remote: CONFIG
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2), (mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> get hardreset ENTER
    +local: hardreset remote: hardreset
    +200 PORT command successful.
    +421 Axis NPS ### hard reset, closing connection.
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+

Your Axis print server is now ready for use!

+

Configuring Linksys Print Servers

+

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. + +

+

Each print server contains a configuration file named CONFIG + 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 ftp(1) program:

+
    +
    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> get CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +WARNING! 68 bare linefeeds received in ASCII mode
    +File may not have transferred correctly.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+ + +

Next, edit the file with your favorite text editor and locate the + lines beginning with:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P1
    +0140 L3_PROUT:P1
    +
    +
+

Change the port number for each parallel and serial port on the + server as follows:

+
    +
    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P2
    +0140 L3_PROUT:P3
    +
    +
+ + +

This maps each virtual printer with a physical port. Save the file + and then upload the new CONFIG file using the ftp + command:

+
    +
    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> put CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
    +
+

Your Linksys print server is now ready for use!

+

C - Printer Drivers

+

This appendix lists the printer drivers that are provided with CUPS.

+

Printer Drivers

+

CUPS includes the following printer drivers:

+ +

EPSON 9-pin Dot Matrix

+

The EPSON 9-pin Dot Matrix driver (epson9.ppd) supports + 9-pin dot matrix printers that implement the ESC/P command set. It + provides 60x72, 120x72, and 240x72 DPI output in black only.

+

EPSON 24-pin Dot Matrix

+

The EPSON 24-pin Dot Matrix driver (epson9.ppd) 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.

+

EPSON Stylus Color

+

The EPSON Stylus Color driver (stcolor.ppd) 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).

+

EPSON Stylus Photo

+

The EPSON Stylus Photo driver (stphoto.ppd) 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).

+

HP DeskJet

+

The HP DeskJet driver (deskjet.ppd) supports HP DeskJet + printers that implement the PCL command set. It provides 150, 300, and + 600 DPI output in black and color (CMYK).

+

The DeskJet printers that implement the HP-PPA command set (720C, + 722C, 820C, and 1100C) are not supported due to a complete lack + of documentation and support from Hewlett Packard.

+

The duplexer provided with the HP DeskJet 900 series printers is also + not supported for similar reasons.

+

HP LaserJet

+

The HP LaserJet driver (laserjet.ppd) 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.

+

LaserJet printers that do not implement PCL (3100, 3150) are not + supported due to a complete lack of documentation and support from + Hewlett Packard.

+

D - List of Files

+

This appendix lists the files and directories that are installed for + the Common UNIX Printing System. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathnameDescription
/etc/cups/certs/The location of + authentication certificate files for local HTTP clients.
/etc/cups/classes.confThe printer classes + configuration file for the scheduler.
/etc/cups/cupsd.confThe scheduler + configuration file.
/etc/cups/interfaces/The location of + System V interface scripts for printers.
/etc/cups/mime.convsThe list of standard + file filters included with CUPS.
/etc/cups/mime.typesThe list of recognized + file types for CUPS.
/etc/cups/ppd/The location of PostScript + Printer Description ("PPD") files for printers.
/etc/cups/printers.confThe printer + configuration file for the scheduler.
/usr/bin/cancelThe System V cancel job(s) + command.
/usr/bin/disableThe System V disable + printer command.
/usr/bin/enableThe System V enable printer + command.
/usr/bin/lpThe System V print command.
/usr/bin/lpoptionsSets user-defined + printing options and defaults.
/usr/bin/lppasswdAdds, changes, or removes + Digest password accounts.
/usr/bin/lpqThe Berkeley status command.
/usr/bin/lprThe Berkeley print command.
/usr/bin/lprmThe Berkeley cancel job(s) + command.
/usr/bin/lpstatThe System V status + command.
/usr/include/cups/CUPS API header files.
/usr/lib32/libcups.a +
/usr/lib32/libcupsimage.a
Static libraries (IRIX 6.5)
/usr/lib/libcups.a +
/usr/lib/libcupsimage.a
Static libraries (all others)
/usr/lib/libcups.sl.2 +
/usr/lib/libcupsimage.sl.2
Shared libraries (HP-UX)
/usr/lib32/libcups.so.2 +
/usr/lib32/libcupsimage.so.2
Shared libraries (IRIX 6.5)
/usr/lib/libcups.so.2 +
/usr/lib/libcupsimage.so.2
Shared libraries (all others)
/usr/lib/cups/backend/Backends for various + types of printer connections.
/usr/lib/cups/cgi-bin/CGI programs for the + scheduler.
/usr/lib/cups/daemon/Daemons for polling + and LPD support.
/usr/lib/cups/filter/Filters for various + types of files.
/usr/lib/locale/The location of + language-specific message files. (System V)
/usr/lib/nls/msg/The location of + language-specific message files. (Compaq Tru64 UNIX)
/usr/share/locale/The location of + language-specific message files. (Linux, *BSD)
/usr/sbin/acceptThe accept-jobs command.
/usr/sbin/cupsdThe CUPS print scheduler.
/usr/sbin/lpadminThe System V printer + administration tool.
/usr/sbin/lpcThe Berkeley printer + administration tool.
/usr/sbin/lpinfoThe get-devices and + get-ppds command.
/usr/sbin/lpmoveThe move-jobs command.
/usr/sbin/rejectThe reject-jobs command.
/usr/share/catman/a_man/ +
/usr/share/catman/u_man/
Man pages (IRIX)
/usr/share/man/Man pages (Compaq Tru64 + UNIX, HP-UX, Solaris)
/usr/man/Man pages (all others)
/usr/share/cups/data/The location of + filter data files.
/usr/share/cups/data/testprint.psThe + PostScript test page file.
/usr/share/cups/fonts/The location of + PostScript fonts for the PostScript RIP.
/usr/share/cups/model/The location of + PostScript Printer Description ("PPD") files and interface scripts that + may be used to setup a printer queue.
/usr/share/cups/pstoraster/Other + PostScript RIP initialization files.
/usr/share/cups/pstoraster/FontmapThe font + mapping file (converts filenames to fontnames)
/usr/share/cups/templates/The location of + HTML template files for the web interfaces.
/usr/share/doc/cups/Documentation and web + page data for the scheduler.
/var/log/cups/The location of scheduler + log files.
/var/spool/cups/The location of print + files waiting to be printed.
+
+

+

E - Troubleshooting Common Problems

+

This appendix covers some of the common problems first-time users + encounter when installing and configuring CUPS.

+

Commercial support for CUPS is available from Easy Software Products. + For more information please contact us at:

+ +

My Applications Don't See the Available Printers

+

Many applications read the /etc/printcap file to get a + list of available printers.

+

The default CUPS configuration creates the /etc/printcap + file automatically. To enable or disable automatic creation and + updating of this file, use the Printcap + directive described in Chapter 6, + "Printing System Management".

+

CUPS Doesn't Recognize My Username or Password!

+

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 root username and + the corresponding password to authenticate the request.

+

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 root account then you won't be + able to add printers remotely or via the web interface! + +

+

To disable password authentication you need to edit the + /etc/cups/cupsd.conf file and comment out the lines reading:

+
    +
    +AuthType Basic
    +AuthClass System
    +
    +
+

for the /admin location. Then restart the CUPS server as + described in Chapter 6, "Printing System + Management".

+
+ + +
NOTE: +

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.

+
+
+

I Can't Do Administration Tasks from Another + Machine!

+

The default CUPS configuration limits administration to the local + machine. To open up access, edit the /etc/cups/cupsd.conf + and comment out the lines reading:

+
    +
    +Order deny,allow
    +Deny from all
    +Allow from 127.0.0.1
    +
    +
+

for the /admin location. Then restart the CUPS server as + described in Chapter 6, "Printing System + Management".

+
+ + +
NOTE: +

Allowing administration access from all hosts is a potential security + risk. Please read Chapter 6, "Printing + System Management" for a description of these risks and ways to + minimize them.

+
+
+ + +

I Can't Do Administration Tasks from My Web Browser! +

+

This problem is usually caused by:

+
    +
  1. not specifying the correct password for the root account.
  2. +
  3. 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 + "I Can't Do Administration Tasks from Another Machine!" section + earlier in this appendix.
  4. +
  5. not setting a password on the root account. CUPS will not + authenticate a user account that does not have a password for security + reasons.
  6. +
  7. authenticating using an account other than root, but the account you + are using is not a member of the system group.
  8. +
  9. configuring CUPS to use Digest authentication, but your web browser + does not support Digest authentication.
  10. +
+

Connection Refused Messages

+

Under normal circumstances, "connection refused" 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.

+

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.

+

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.

+

Write Error Messages

+

If you get "write error" 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.

+

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. + +

+

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:

+
    +
    +telnet ip-address ENTER
    +
    +Trying ip-address...
    +Connected to ip-address.
    +Escape character is `^]'.
    +
    +Please type [Return] two times, to initialize telnet configuration
    +For HELP type "?"
    +> idle-timeout: 180 ENTER
    +> quit ENTER
    +
    +
+ + diff --git a/doc/sam.pdf b/doc/sam.pdf new file mode 100644 index 0000000000000000000000000000000000000000..18354a58f715b5dbdab15f32e41d348ea27bb6a8 GIT binary patch literal 305416 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 A!2kdN literal 0 Hc-jL100001 diff --git a/doc/sam.shtml b/doc/sam.shtml new file mode 100644 index 0000000000..bbb82e4f23 --- /dev/null +++ b/doc/sam.shtml @@ -0,0 +1,5882 @@ + + + + + + CUPS Software Administrators Manual + + + +

Preface

+ +

This software administrators manual provides printer administration +information for the Common UNIX Printing SystemTM +("CUPSTM"), version 1.1.17. + + + + +

Document Overview

+ +

This software administrators manual is organized into the following sections:

+ + + +

Notation Conventions

+ +

Various font and syntax conventions are used in this guide. Examples and +their meanings and uses are explained below: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Example   Description
 
lpstat
+ lpstat(1)
   The names of commands; the first mention of a command or + function in a chapter is followed by a manual page section + number.
 
/var
+ /usr/share/cups/data/testprint.ps
   File and directory names.
 
Request ID is Printer-123   Screen output.
 
lp -d printer filename ENTER   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are written using the period (.) to indicate + the decimal point.
+ + +

Abbreviations

+ +The following abbreviations are used throughout this manual: + +
    +
    + +
    kb +
    Kilobytes, or 1024 bytes
      + +
    Mb +
    Megabytes, or 1048576 bytes
      + +
    Gb +
    Gigabytes, or 1073741824 bytes
      + +
    +
+ +

Other References

+ +
    +
    + +
    CUPS Software Programmers Manual + +
    A programmer guide for interfacing with and/or extending the CUPS + software.
      + +
    CUPS Software Users Manual + +
    An end-user guide for using the CUPS software.
      + +
    +
+ + + + + +

2 - Building and Installing CUPS

+ +

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, Installing a Binary Distribution. + +

Installing a Source Distribution

+ +

This section describes how to compile and install CUPS on your system +from the source code. + +

Requirements

+ +

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. + +

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: + +

+ +

If you make changes to the man pages you'll need GNU groff or another +nroff-like package. GNU groff is available from: + +

+ +

The documentation is formatted using the HTMLDOC software. If you need to +make changes you can get the HTMLDOC software from: + +

+ +

Finally, you'll need a make program that +understands the include directive - FreeBSD, +NetBSD, and OpenBSD developers should use the gmake +program. + +

Compiling CUPS

+ +

CUPS uses GNU autoconf to configure the makefiles and source code +for your system. Type the following command to configure CUPS for your +system: + +

    +./configure ENTER
    +
+ +

The default installation will put the CUPS software in the +/etc, /usr, and /var directories on +your system, which will overwrite any existing printing commands on +your system. Use the --prefix option to install the CUPS +software in another location: + +

    +./configure --prefix=/some/directory ENTER
    +
+ +

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: + +

    +setenv CFLAGS "-I/some/directory" ENTER
    +setenv CXXFLAGS "-I/some/directory" ENTER
    +setenv LDFLAGS "-L/some/directory" ENTER
    +setenv DSOFLAGS "-L/some/directory" ENTER
    +./configure ... ENTER
    +
+ +

or: + +

    +CFLAGS="-I/some/directory"; export CFLAGS ENTER
    +CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER
    +LDFLAGS="-L/some/directory"; export LDFLAGS ENTER
    +DSOFLAGS="-L/some/directory"; export DSOFLAGS ENTER
    +./configure ... ENTER
    +
+ +

To enable support for encryption, you'll also want to add the +"--enable-ssl" option: + +

    +./configure --enable-ssl
    +
+ +

SSL and TLS support require the OpenSSL library, available at: + +

+ +

If the OpenSSL headers and libraries are not installed in the +standard directories, use the --with-openssl-includes +and --with-openssl-libs options:

+ +
    +./configure --enable-ssl \
    +    --with-openssl-includes=/foo/bar/include \
    +    --with-openssl-libs=/foo/bar/lib
    +
+ +

Once you have configured things, just type: + +

    +make ENTER
    +
+ +

to build the software. + + +

Installing the Software

+ +

Use the "install" target to install the software: + +

    +make install ENTER
    +
+ +
+ + + +
+ WARNING: + +

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. +

+ +

Running the Software

+ +

Once you have installed the software you can start the CUPS server by +typing: + +

    +/usr/sbin/cupsd ENTER
    +
+ + +

Installing a Binary Distribution

+ +

CUPS comes in a variety of binary distribution formats. Easy +Software Products provides binaries in TAR format with installation and +removal scripts ("portable" 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. + +

+ + + +
+ WARNING: + +

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. +

+ + +

Installing a Portable Distribution

+ +

To install the CUPS software from a portable distribution you will +need to be logged in as root; doing an su is good enough. +Once you are the root user, run the installation script with: + +

    +./cups.install ENTER
    +
+ +

After asking you a few yes/no questions the CUPS software will be +installed and the scheduler will be started automatically. + + +

Installing an RPM Distribution

+ +

To install the CUPS software from an RPM distribution you will need +to be logged in as root; doing an su is good enough. Once +you are the root user, run RPM with: + +

    +rpm -e lpr
    +rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTER
    +
+ +

After a short delay the CUPS software will be +installed and the scheduler will be started automatically. + +

Installing an Debian Distribution

+ +

To install the CUPS software from a Debian distribution you will +need to be logged in as root; doing an su is good enough. +Once you are the root user, run dpkg with: + +

    +dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTER
    +
+ +

After a short delay the CUPS software will be installed and the +scheduler will be started automatically. + + +

3 - Managing Printers

+ +

This chapter describes how to add your first printer and how to +manage your printers. + +

The Basics

+ +

Each printer queue has a name associated with it; the printer name +must start with any printable character except " ", "/", and "@". +It can contain up to 127 letters, numbers, and the underscore (_). +Case is not significant, e.g. "PRINTER", "Printer", +and "printer" are considered to be the same name. + +

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 ("URIs") which are a more general form of +Uniform Resource Locators ("URLs") that are used in your web browser. For +example, the first parallel port in Linux usually uses a device URI of +parallel:/dev/lp1. + + +

You can see a complete list of supported devices by running the +lpinfo(8) command: + +

    +lpinfo -v ENTER
    +network socket
    +network http
    +network ipp
    +network lpd
    +direct parallel:/dev/lp1
    +serial serial:/dev/ttyS1?baud=115200
    +serial serial:/dev/ttyS2?baud=115200
    +direct usb:/dev/usb/lp0
    +network smb
    +
+ +

The -v 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 +file:/directory/filename while network devices use the more +familiar method://server or method://server/path +format. + +

Finally, printer queues usually have a PostScript Printer Description +("PPD") 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. + +

Adding Your First Printer

+ +

CUPS provides two methods for adding printers: a command-line +program called lpadmin(8) and a Web interface. The +lpadmin command allows you to perform most printer +administration tasks from the command-line and is located in +/usr/sbin. The Web interface is located at: + +

+ +

and steps you through printer configuration. If you don't like +command-line interfaces, try the Web interface instead. + +

Adding Your First Printer from the Command-Line

+ +

Run the lpadmin command with the -p option to add a +printer to CUPS: + +

    +/usr/sbin/lpadmin -p printer -E -v device -m ppd ENTER
    +
+ +

For a HP DeskJet printer connected to the parallel port this would look +like: + +

    +/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTER
    +
+ +

Similarly, a HP LaserJet printer using a JetDirect network interface at +IP address 11.22.33.44 would be added with the command: + +

    +/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTER
    +
+ +

As you can see, deskjet.ppd and laserjet.ppd 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 Appendix C, "Printer Drivers". + + +

For a dot matrix printer connected to the serial port this would might look like: + +

    +/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTER
    +
+ +

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. + + +

Adding Your First Printer from the Web

+ +

The CUPS web server provides a user-friendly "wizard" 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: + +

+ +

Click on the Add Printer button to add a printer. + +

Managing Printers from the Command-Line

+ +

The lpadmin command enables you to perform most printer +administration tasks from the command-line. You'll find lpadmin +in the /usr/sbin directory. + +

Adding and Modifying Printers

+ +

Run the lpadmin command with the -p option +to add or modify a printer: + +

    +/usr/sbin/lpadmin -p printer options ENTER
    +
+ +

The options arguments can be any of the following: + +

    +
    + +
    -c class + +
    Adds the named printer to printer class class. + If the class does not exist then it is created. + +
    -i interface + +
    Copies the named interface 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. + +
    -m model + +
    Specifies a standard printer driver which is usually a PPD + file. A list of all available models can be displayed using the + lpinfo command with the -m option. A + list of printer drivers included with CUPS can be found in + Appendix C, "Printer Drivers". + +
    -r class + +
    Removes the named printer from printer class class. + If the resulting class becomes empty then it is removed. + +
    -v device-uri + +
    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. + +
    -D info + +
    Provides a textual description of the printer, e.g. + "John's Personal Printer". + +
    -E + +
    Enables the printer and accepts job. This option is + equivalent to running the enable(1) and + accept(8) commands on the printer. + +
    -L location + +
    Provides a textual location for the printer, e.g. + "Computer Lab 5". + +
    -P ppd-file + +
    Specifies a local PPD file for the printer driver. + +
    +
+ +

Deleting Printers

+ +

Run the lpadmin command with the -x option +to delete a printer: + +

    +/usr/sbin/lpadmin -x printer ENTER
    +
+ +

Setting the Default Printer

+ +

Run the lpadmin command with the -d option +to set a default printer: + +

    +/usr/sbin/lpadmin -d printer ENTER
    +
+ +

The default printer can be overridden by the user using the +lpoptions(1) command. + +

Starting and Stopping Printers

+ +

The enable and disable commands start and stop +printer queues, respectively: + +

    +/usr/bin/enable printer ENTER
    +/usr/bin/disable printer ENTER
    +
+ +

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). + +

Accepting and Rejecting Print Jobs

+ +

The accept and reject commands accept and reject +print jobs for the named printer, respectively: + +

    +/usr/sbin/accept printer ENTER
    +/usr/sbin/reject printer ENTER
    +
+ +

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. + +

Setting Quotas on a Printer

+ +

CUPS supports page and size-based quotas for each printer. +The quotas are tracked individually for each user, but a single set of +limits applies to all users for a partiuclar printer. For example, you +can limit every user to 5 pages per day on an expensive printer, but +you cannot limit every user except Johnny.

+ +

The job-k-limit, job-page-limit, and job-quota-peiod +options determine whether and how quotas are enforced for a printer. +The job-quota-period option determines the time interval for +quota tracking. The interval is expressed in seconds, so a day is +86,400, a week is 604,800 and a month is 2,592,000 seconds. The +job-k-limit option specifies the job size limit in killobytes. The +job-page-limit option specifies the number of pages limit.

+ +

For quotas to be enforced, the period and at least one of the limits +must be set to a non-zero value. The following options will enable +quotas:

+ +
    +
    +/usr/sbin/lpadmin -p printer -o job-quota-period=604800 -o job-k-limit=1024 ENTER
    +/usr/sbin/lpadmin -p printer -o job-quota-period=604800 -o job-page-limit=100 ENTER
    +
    +
+ +

Or, you can combine all three options on the same line.

+ +

Restricting User Access to a Printer

+ +

The -u option of the lpadmin command controls which users can +print to a printer. The default configuration allows all users to print +to a printer:

+ +
    +
    +/usr/sbin/lpadmin -p printer -u allow:all ENTER
    +
    +
+ +

CUPS supports allow and deny lists so that you can specify a +list of users who are allowed to print or not allowed to print. Along +with your list of users, you can specify whether they are allowed or +not allowed to use the printer:

+ +
    +
    +/usr/sbin/lpadmin -p printer -u allow:peter,paul,mary ENTER
    +
    +
+ +

This command allows peter, paul, and mary to print to the named +printer, but all other users cannot print. The command:

+ +
    +
    +/usr/sbin/lpadmin -p printer -u deny:peter,paul,mary ENTER
    +
    +
+ +

has the opposite effect. All users except peter, paul, and mary will +be able to print to the named printer.

+ +
+ + + + +
NOTE: + +

The allow and deny options are not cummulative. That + is, you must provide the complete list of users to allow or deny each + time.

+ +

Also, CUPS only maintains one list of users - the list can + allow or deny users from printing. If you specify an allow list and + then specify a deny list, the deny list will replace the allow list - + only one list is active at any time.

+ +
+
+ +

Managing Printers from the Web

+ +

The Web interface is located at: + +

+ +

From there you can perform all printer management tasks with a few +simple mouse clicks. + + +

4 - Printer Classes

+ +

This chapter describes what printer classes are and how to manage them. + +

The Basics

+ +

CUPS provides collections of printers called printer classes. 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. + +

CUPS also supports implicit classes. 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. + +

Managing Printer Classes from the Command-Line

+ +

Run the lpadmin command with the -p and -c options +to add a printer to a class: + +

    +/usr/sbin/lpadmin -p printer -c class ENTER
    +
+ +

The class is created automatically if it doesn't exist. To remove a +printer from a class use the -r option: + +

    +/usr/sbin/lpadmin -p printer -r class ENTER
    +
+ +

To remove the entire class just use the -x option: + +

    +/usr/sbin/lpadmin -x class ENTER
    +
+ +

Managing Printer Classes from the Web Interface

+ +

The Web interface is located at: + +

+ +

The Add Class and Modify Class interfaces provide a +list of available printers; click on the printers of interest to add them to +the class. + +

Implicit Classes

+ +

A noted earlier, implicit classes are created automatically from the +available network printers and classes. To disable this functionality, +set the ImplicitClasses +directive to Off in the cupsd.conf file. You +will find more information on doing this in +Chapter 6, "Printing System +Management". + + +

5 - Client Setup

+ +

This chapter discusses several ways to configure CUPS clients for +printing. + +

The Basics

+ +

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. + +

CUPS supports several methods of configuring client machines: + +

+ +

Manual Configuration of Print Queues

+ +

The most tedious method of configuring client machines is to configure +each remote queue by hand using the lpadmin command: + +

    +lpadmin -p printer -E -v ipp://server/printers/printer ENTER
    +
+ +

The printer name is the name of the printer on the server +machine. The server name is the hostname or IP address of the +server machine. Repeat the lpadmin command for each remote +printer you wish to use.

+ +
+ + + + +
NOTE: +

Manual configuration of print queues is not recommended for large + numbers of client machines because of the administration nightmare it + creates. For busy networks, consider subnetting groups of clients and + polling and relaying printer information instead.

+
+
+ +

Specifying a Single Server for Printing

+ +

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. + +

The default server is normally "localhost". To override the default +server create a file named /etc/cups/client.conf and add +a line reading: + +

    +ServerName server
    +
+ +

to the file. The server name can be the hostname or IP address +of the default server. + +

The default server can also be customized on a per-user basis. To set a +user-specific server create a file named ~/.cupsrc and add a line +reading: + +

    +ServerName server
    +
+ +

to the file. The server name can be the hostname or IP +address of the default server. + +

Automatic Configuration of Print Queues

+ +

CUPS supports automatic client configuration of printers on the same +subnet. To configure printers on the same subnet, do nothing. +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. + +

If you want to see printers on other subnets as well, use the +BrowsePoll +directive as described next.

+ +
+ + + + +
NOTE: +

The BrowseAddress directive + enables broadcast traffic from your server. The default configuration + braodcasts printer information every 30 seconds. Although this printer + information does not use much bandwidth, typically about 80 bytes per + printer, it can add up with large numbers of servers and printers.

+

Use the BrowseInterval + and BrowseTimeout directives to tune + the amount of data that is added to your network load. In addition, + subnets can be used to minimize the amount of traffic that is carried + by the "backbone" of your large network.

+
+
+ +

Specifying Multiple Servers for Printing

+ +

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. + +

Polling is enabled by specifying one or more +BrowsePoll +directives in the /etc/cups/cupsd.conf file. +For information on making these changes, see +Chapter 6, "Printing System Management". + +

Multiple BrowsePoll lines can +be used to poll multiple CUPS servers. To limit the amount of +polling you do from client machines, you can have only one of the +clients do the polling and relay that information to the others on the +same subnet (described next).

+ +

Relaying Printers to Other Clients

+ +

When you have clients and servers spread across multiple subnets, the +polling method is inefficient. CUPS provides a +BrowseRelay directive that enables a +single client to relay (broadcast) the polled printer information to the local subnet.

+ +

For example, Server A and Server B are on subnet 1 and subnet 2, +while the clients are on subnet 3. +To provide printers to all of the clients in subnet 3, +client C will be configured with the following directives in /etc/cups/cupsd.conf:

+ +
    +# Poll the two servers
    +
    +BrowsePoll ServerA ENTER
    +BrowsePoll ServerB ENTER
    +
    +
    +# Relay the printers to the local subnet
    +
    +BrowseRelay 127.0.0.1 192.168.3.255 ENTER
    +
+ +

The BrowseRelay line specifies a source address and mask. +Any browse packets coming from a matching address wil be sent to the given broadcast address. +In this case, we want the packets from the local machine (127.0.0.1) relayed to the other clients.

+ +

As printers are found using polling, +they are relayed from client C to the rest of the clients through a broadcast on subnet 3. +The rest of the clients can use the standard cupsd.conf configuration.

+ +

The BrowseRelay directive can also be used to relay +browsing packets from one network interface to another. +For example, if client C in the previous example had network interfaces attaches to both +subnet 1 and subnet 2, it could use the BrowseRelay directive exclusively: + +

    +# Relay the printers from subnet 1 and 2 to subnet 3
    +
    +BrowseRelay 192.168.1 192.168.3.255 ENTER
    +BrowseRelay 192.168.2 192.168.3.255 ENTER
    +
+ +

Load Balancing and Failsafe Operation

+ +

When using server polling or broadcasting, CUPS clients can +automatically merge identical printers on multiple servers into a +single implicit class queue. Clients assume that printers with +the same name on multiple servers are in fact the same printer or type +of printer being served by multiple machines.

+ +

If you have two printers, LaserJet@ServerA and LaserJet@ServerB, a +third implicit class called LaserJet will be created +automatically on the client that refers to both printers. If the client +also has a local printer with the name LaserJet then an implicit class +named AnyLaserJet will be created instead.

+ +

The client will alternate between servers and automatically stop +sending jobs to a server if it goes down, providing a load-balancing +effect and fail-safe operation with automatic switchover.

+ +
+ + + +
NOTE: +

Note that implicit classes (ImplicitClasses) + are enabled by default.

+
+ +

6 - Printing System Management

+ +

This chapter shows how you can configure the CUPS server. + +

The Basics

+ +

Several text files are used to configure CUPS. All of the server +configuration files are located in the /etc/cups directory: + +

    +
    + + +
    classes.conf + +
    This file contains information on each printer class. + Normally you manipulate this file using the + lpadmin command or the Web interface.
      + + +
    client.conf + +
    This file provides the default server name for client + machines. See Chapter 5, "Client + Setup" for more information.
      + + +
    cupsd.conf + +
    This file controls how the CUPS server + (/usr/sbin/cupsd) operates and is normally edited by + hand.
      + + +
    mime.convs + +
    This file contains a list of standard file conversion filters + and their costs. You normally do not edit this file.
      + + +
    mime.types + +
    This file contains a list of standard file formats and how to + recognize them. You normally do not edit this file.
      + + +
    printers.conf + +
    This file contains information on each printer. Normally + you manipulate this file using the lpadmin command + or the Web Interface.
      + +
    +
+ +

Restarting the CUPS Server

+ +

Once you have made a change to a configuration file you need to +restart the CUPS server by sending it a HUP signal or using the +supplied initialization script. The CUPS distributions install the +script in the init.d directory with the name +cups. The location varies based upon the operating system: + +

    +/etc/software/init.d/cups restart ENTER
    +/etc/rc.d/init.d/cups restart ENTER
    +/etc/init.d/cups restart ENTER
    +/sbin/init.d/cups restart ENTER
    +
+ +

Changing the Server Configuration

+ +

The /etc/cups/cupsd.conf file contains configuration +directives 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 ("#") 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. + + +

Server Directives

+ +

The cupsd.conf file contains many directives that +determine how the server operates: + +

+ + +

AccessLog

+
+ +

Examples

+ +
    +AccessLog /var/log/cups/access_log
    +AccessLog /var/log/cups/access_log-%s
    +AccessLog syslog
    +
+ +

Description

+ +

The AccessLog directive sets the name of the access log +file. If the filename is not absolute then it is assumed to be relative +to the ServerRoot directory. The +access log file is stored in "common log format" and can be used by any +web access reporting tool to generate a report on CUPS server activity. + +

The server name can be included in the filename by using +%s in the name. + +

The special name "syslog" can be used to send the access information +to the system log instead of a plain file. + +

The default access log file is /var/log/cups/access_log. + + +

Allow

+
+ +

Examples

+ +
    +Allow from All
    +Allow from None
    +Allow from *.domain.com
    +Allow from .domain.com
    +Allow from host.domain.com
    +Allow from nnn.*
    +Allow from nnn.nnn.*
    +Allow from nnn.nnn.nnn.*
    +Allow from nnn.nnn.nnn.nnn
    +Allow from nnn.nnn.nnn.nnn/mm
    +Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +Allow from @LOCAL
    +Allow from @IF(name)
    +
+ +

Description

+ +

The Allow directive specifies a hostname, IP address, +or network that is allowed access to the server. Allow +directives are cummulative, so multiple Allow directives +can be used to allow access for multiple hosts or networks. The +/mm notation specifies a CIDR netmask: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mmnetmaskmmnetmask
00.0.0.08255.0.0.0
1128.0.0.016255.255.0.0
2192.0.0.024255.255.255.0
......32255.255.255.255
+ +

The @LOCAL name will allow access from all local +network interfaces, but not remote point-to-point interfaces. The +@IF(name) name will allow access from the named +interface. + +

The Allow directive must appear inside a +Location directive. + + +

AuthClass

+
+ +

Examples

+ +
    +AuthClass Anonymous
    +AuthClass User
    +AuthClass System
    +AuthClass Group
    +
+ +

Description

+ +

The AuthClass directive defines what level of authentication +is required: + +

    + +
  • Anonymous - No authentication should be performed + (default.) + +
  • User - A valid username and password is required. + +
  • System - A valid username and password is + required, and the username must belong to the "sys" group; this + can be changed using the + SystemGroup directive. + +
  • Group - A valid username and password is + required, and the username must belong to the group named by + the AuthGroupName directive. + +
+ +

The AuthClass directive must appear inside a +Location directive. + + +

AuthGroupName

+
+ +

Examples

+ +
    +AuthGroupName mygroup
    +AuthGroupName lp
    +
+ +

Description

+ +

The AuthGroupName directive sets the group to use for +Group authentication. + +

The AuthGroupName directive must appear inside a +Location directive. + + +

AuthType

+
+ +

Examples

+ +
    +AuthType None
    +AuthType Basic
    +AuthType Digest
    +AuthType BasicDigest
    +
+ +

Description

+ +

The AuthType directive defines the type of authentication to +perform: + +

    + +
  • None - No authentication should be performed + (default.) + +
  • Basic - Basic authentication should be + performed using the UNIX password and group files. + +
  • Digest - Digest authentication should be + performed using the /etc/cups/passwd.md5 file. + +
  • BasicDigest - Basic authentication should be + performed using the /etc/cups/passwd.md5 file. + +
+ +

When using Basic, Digest, or +BasicDigest authentication, clients connecting +through the localhost interface can also +authenticate using certificates. + +

The AuthType directive must appear inside a +Location directive. + + +

AutoPurgeJobs

+
+ +

Examples

+ +
    +AutoPurgeJobs Yes
    +AutoPurgeJobs No
    +
+ +

Description

+ +

The AutoPurgeJobs 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 No. + + +

BrowseAddress

+
+ +

Examples

+ +
    +BrowseAddress 255.255.255.255:631
    +BrowseAddress 192.0.2.255:631
    +BrowseAddress host.domain.com:631
    +BrowseAddress @LOCAL
    +BrowseAddress @IF(name)
    +
+ +

Description

+ +

The BrowseAddress directive specifies an address to +send browsing information to. Multiple BrowseAddress +directives can be specified to send browsing information to different +networks or systems. + +

The @LOCAL name will broadcast printer +information to all local interfaces. The @IF(name) +name will broadcast to the named interface. + +

No browse addresses are set by default.

+ +
+ + + +
+ NOTE: + +

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. +

+ + +

BrowseAllow

+
+ +

Examples

+ +
    +BrowseAllow from all
    +BrowseAllow from none
    +BrowseAllow from 192.0.2
    +BrowseAllow from 192.0.2.0/24
    +BrowseAllow from 192.0.2.0/255.255.255.0
    +BrowseAllow from *.domain.com
    +BrowseAllow from @LOCAL
    +BrowseAllow from @IF(name)
    +
+ +

Description

+ +

The BrowseAllow directive specifies a system or network +to accept browse packets from. The default is to accept browse packets +from all hosts. + +

Host and domain name matching require that you enable the +HostNameLookups directive. + +

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. + +

The @LOCAL name will allow browse data from all +local network interfaces, but not remote point-to-point +interfaces. The @IF(name) name will allow browse +data from the named interface. + + + +

BrowseDeny

+
+ +

Examples

+ +
    +BrowseDeny from all
    +BrowseDeny from none
    +BrowseDeny from 192.0.2
    +BrowseDeny from 192.0.2.0/24
    +BrowseDeny from 192.0.2.0/255.255.255.0
    +BrowseDeny from *.domain.com
    +BrowseDeny from @LOCAL
    +BrowseDeny from @IF(name)
    +
+ +

Description

+ +

The BrowseDeny directive specifies a system or network +to reject browse packets from. The default is to deny browse packets +from no hosts. + +

Host and domain name matching require that you enable the +HostNameLookups directive. + +

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. + +

The @LOCAL name will block browse data from all +local network interfaces, but not remote point-to-point +interfaces. The @IF(name) name will block browse +data from the named interface. + + + +

BrowseOrder

+
+ +

Examples

+ +
    +BrowseOrder allow,deny
    +BrowseOrder deny,allow
    +
+ +

Description

+ +

The BrowseOrder directive specifies the order of allow/deny +processing. The default order is deny,allow: + +

    + +
  • allow,deny - Browse packets are accepted unless + specifically denied. + +
  • deny,allow - Browse packets are rejected unless + specifically allowed. + +
+ + +

BrowseInterval

+
+ +

Examples

+ +
    +BrowseInterval 0
    +BrowseInterval 30
    +
+ +

Description

+ +

The BrowseInterval 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. + +

The BrowseInterval value should always be less than the +BrowseTimeout value. Otherwise +printers and classes will disappear from client systems between updates. + + +

BrowsePoll

+
+ +

Examples

+ +
    +BrowsePoll 192.0.2.2:631
    +BrowsePoll host.domain.com:631
    +
+ +

Description

+ +

The BrowsePoll directive polls a server for available +printers once every +BrowseInterval seconds. +Multiple BrowsePoll directives can be specified to poll +multiple servers. + +

If BrowseInterval is set to 0 then the server is polled +once every 30 seconds. + + +

BrowsePort

+
+ +

Examples

+ +
    +BrowsePort 631
    +BrowsePort 9999
    +
+ +

Description

+ +

The BrowsePort directive specifies the UDP port number +used for browse packets. The default port number is 631.

+ +
+ + + +
+ NOTE: + +

You must set the BrowsePort to the same value + on all of the systems that you want to see. +

+ + +

BrowseProtocols

+
+ +

Examples

+ +
    +BrowseProtocols CUPS
    +BrowseProtocols SLP
    +BrowseProtocols CUPS SLP
    +BrowseProtocols all
    +
+ +

Description

+ +

The BrowseProtocols directive specifies the protocols to +use when collecting and distributing shared printers on the local network. +The default protocol is CUPS, which is a broadcast-based +protocol.

+ +
+ + + +
+ NOTE: + +

When using the SLP protocol, you must have at least + one Directory Agent (DA) server on your network. Otherwise the + CUPS scheduler (cupsd) will not respond to client + requests for several seconds while polling the network. +

+ + +

BrowseRelay

+
+ +

Examples

+ +
    +BrowseRelay 193.0.2.1 192.0.2.255
    +BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
    +BrowseRelay 193.0.2.0/24 192.0.2.255
    +BrowseRelay *.domain.com 192.0.2.255
    +BrowseRelay host.domain.com 192.0.2.255
    +
+ +

Description

+ +

The BrowseRelay directive specifies source and destination +addresses for relaying browsing information from one host or network to +another. Multiple BrowseRelay directives can be specified +as needed. + +

BrowseRelay 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: + +

    +BrowseRelay 127.0.0.1 255.255.255.255
    +
+ +

This effectively provides access to printers on a WAN for all clients +on the LAN(s). + + +

BrowseShortNames

+
+ +

Examples

+ +
    +BrowseShortNames Yes
    +BrowseShortNames No
    +
+ +

Description

+ +

The BrowseShortNames 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 ("printer"). If more than +one remote printer is detected with the same name, the printers will have +long names ("printer@server1", "printer@server2".) + +

The default value for this option is Yes. + + +

BrowseTimeout

+
+ +

Examples

+ +
    +BrowseTimeout 300
    +BrowseTimeout 60
    +
+ +

Description

+ +

The BrowseTimeout 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. + +

The BrowseTimeout value should always be greater than the +BrowseInterval value. Otherwise +printers and classes will disappear from client systems between updates. + + +

Browsing

+
+ +

Examples

+ +
    +Browsing On
    +Browsing Off
    +
+ +

Description

+ +

The Browsing directive controls whether or not network printer +browsing is enabled. The default setting is On.

+ +
+ + + +
+ NOTE: + +

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. +

+ + +

Classification

+
+ +

Examples

+ +
    +Classification
    +Classification classified
    +Classification confidential
    +Classification secret
    +Classification topsecret
    +Classification unclassified
    +
+ +

Description

+ +

The Classification 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. + + +

ClassifyOverride

+
+ +

Examples

+ +
    +ClassifyOverride Yes
    +ClassifyOverride No
    +
+ +

Description

+ +

The ClassifyOverride 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 job-sheets option and can choose to only print one +security banner before or after the job. If the job-sheets +option is set to none then the server default classification +is used. + +

The default is to not allow classification overrides. + + +

ConfigFilePerm

+
+ +

Examples

+ +
    +ConfigFilePerm 0644
    +ConfigFilePerm 0600
    +
+ +

Description

+ +

The ConfigFilePerm directive specifies the permissions +to use when writing configuration files. The default is 0600. + + +

DataDir

+
+ +

Examples

+ +
    +DataDir /usr/share/cups
    +
+ +

Description

+ +

The DataDir directive sets the directory to use for data +files. + + +

DefaultCharset

+
+ +

Examples

+ +
    +DefaultCharset utf-8
    +DefaultCharset iso-8859-1
    +DefaultCharset windows-1251
    +
+ +

Description

+ +

The DefaultCharset directive sets the default character set +to use for client connections. The default character set is +utf-8 but is overridden by the character set for the language +specified by the client or the DefaultLanguage directive. + + +

DefaultLanguage

+
+ +

Examples

+ +
    +DefaultLanguage de
    +DefaultLanguage en
    +DefaultLanguage es
    +DefaultLanguage fr
    +DefaultLanguage it
    +
+ +

Description

+ +

The DefaultLanguage 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 "en" for English. + + +

Deny

+
+ +

Examples

+ +
    +Deny from All
    +Deny from None
    +Deny from *.domain.com
    +Deny from .domain.com
    +Deny from host.domain.com
    +Deny from nnn.*
    +Deny from nnn.nnn.*
    +Deny from nnn.nnn.nnn.*
    +Deny from nnn.nnn.nnn.nnn
    +Deny from nnn.nnn.nnn.nnn/mm
    +Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
    +Deny from @LOCAL
    +Deny from @IF(name)
    +
+ +

Description

+ +

The Deny directive specifies a hostname, IP address, or +network that is allowed access to the server. Deny +directives are cummulative, so multiple Deny directives +can be used to allow access for multiple hosts or networks. The +/mm notation specifies a CIDR netmask: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mmnetmaskmmnetmask
00.0.0.08255.0.0.0
1128.0.0.016255.255.0.0
2192.0.0.024255.255.255.0
......32255.255.255.255
+ +

The @LOCAL name will deny access from all local +network interfaces, but not remote point-to-point interfaces. The +@IF(name) name will deny access from the named +interface. + +

The Deny directive must appear inside a +Location directive. + + +

DocumentRoot

+
+ +

Examples

+ +
    +DocumentRoot /usr/share/doc/cups
    +DocumentRoot /foo/bar/doc/cups
    +
+ +

Description

+ +

The DocumentRoot 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 +ServerRoot directory. The +default directory is /usr/share/doc/cups. + +

Documents are first looked up in a sub-directory for the primary +language requested by the client (e.g. /usr/share/doc/cups/fr/...) +and then directly under the DocumentRoot directory +(e.g. /usr/share/doc/cups/...), so it is possible to localize +the web content by providing subdirectories for each language needed. + + +

Encryption

+
+ +

Examples

+ +
    +Encryption Never
    +Encryption IfRequested
    +Encryption Required
    +Encryption Always
    +
+ +

Description

+ +

The Encryption directive must appear instead a +Location +section and specifies the encryption settings for that location. +The default setting is IfRequested for all locations. + + +

ErrorLog

+
+ +

Examples

+ +
    +ErrorLog /var/log/cups/error_log
    +ErrorLog /var/log/cups/error_log-%s
    +ErrorLog syslog
    +
+ +

Description

+ +

The ErrorLog directive sets the name of the error log +file. If the filename is not absolute then it is assumed to be relative +to the ServerRoot directory. The +default error log file is /var/log/cups/error_log. + +

The server name can be included in the filename by using +%s in the name. + +

The special name "syslog" can be used to send the error information +to the system log instead of a plain file. + + +

FilterLimit

+
+ +

Examples

+ +
    +FilterLimit 0
    +FilterLimit 200
    +FilterLimit 1000
    +
+ +

Description

+ +

The FilterLimit 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. + +

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. + +

The default limit is 0. + + +

FilterNice

+
+ +

Examples

+ +
    +FilterNice 0
    +FilterNice 39
    +FilterNice -10
    +
+ +

Description

+ +

The FilterNice directive sets the scheduling +priority of job filters. Values larger than 0 give filters a +lower priority while values smaller than 0 give filters a higher +priority. The FilterNice value does not affect the +priority of job backends. + +

The default priority is 0. + + +

FontPath

+
+ +

Examples

+ +
    +FontPath /foo/bar/fonts
    +FontPath /usr/share/cups/fonts:/foo/bar/fonts
    +
+ +

Description

+ +

The FontPath directive specifies the font path to use when +searching for fonts. The default font path is +/usr/share/cups/fonts. + + +

Group

+
+ +

Examples

+ +
    +Group sys
    +Group system
    +Group root
    +
+ +

Description

+ +

The Group directive specifies the UNIX group that +filter and CGI programs run as. The default group is sys, +system, or root depending on the operating +system. + + +

HideImplicitMembers

+
+ +

Examples

+ +
    +HideImplicitMembers Yes
    +HideImplicitMembers No
    +
+ +

Description

+ +

The HideImplicitMembers directive controls +whether the individual printers in an implicit class are shown +to the user. The default is No.

+ +

ImplicitClasses +must be enabled for this directive to have any effect.

+ + +

HostNameLookups

+
+ +

Examples

+ +
    +HostNameLookups On
    +HostNameLookups Off
    +HostNameLookups Double
    +
+ +

Description

+ +

The HostNameLookups directive controls whether +or not CUPS looks up the hostname for connecting clients. The +Double setting causes CUPS to verify that the +hostname resolved from the address matches one of the addresses +returned for that hostname. Double lookups also +prevent clients with unregistered addresses from connecting +to your server. + +The default is Off to avoid the potential server +performance problems with hostname lookups. Set this option to +On or Double only if absolutely +required. + + +

ImplicitClasses

+
+ +

Examples

+ +
    +ImplicitClasses On
    +ImplicitClasses Off
    +
+ +

Description

+ +

The ImplicitClasses directive controls whether implicit +classes are created based upon the available network printers and classes. +The default setting is On but is automatically turned +Off if Browsing is +turned Off. + + +

ImplicitAnyClasses

+
+ +

Examples

+ +
    +ImplicitAnyClasses On
    +ImplicitAnyClasses Off
    +
+ +

Description

+ +

The ImplicitAnyClasses directive controls +whether implicit classes for local and remote printers are +created with the name AnyPrinter. The default +setting is Off.

+ +

ImplicitClasses +must be enabled for this directive to have any effect.

+ + +

Include

+
+ +

Examples

+ +
    +Include filename
    +Include /foo/bar/filename
    +
+ +

Description

+ +

The Include directive includes the named file in +the cupsd.conf file. If no leading path is +provided, the file is assumed to be relative to the +ServerRoot directory.

+ + +

KeepAlive

+
+ +

Examples

+ +
    +KeepAlive On
    +KeepAlive Off
    +
+ +

Description

+ +

The KeepAlive directive controls whether or not to support +persistent HTTP connections. The default is On. + +

HTTP/1.1 clients automatically support persistent connections, while +HTTP/1.0 clients must specifically request them using the +Keep-Alive attribute in the Connection: +field of each request. + + +

KeepAliveTimeout

+
+ +

Examples

+ +
    +KeepAliveTimeout 60
    +KeepAliveTimeout 30
    +
+ +

Description

+ +

The KeepAliveTimeout directive controls how long a +persistent HTTP connection will remain open after the last request. The +default is 60 seconds. + + +

Limit

+
+ +

Examples

+ +
    +<Limit GET POST>
    +...
    +</Limit>
    +
    +<Limit ALL>
    +...
    +</Limit>
    +
+ +

Description

+ +

The Limit directive groups access control directives for +specific types of HTTP requests and must appear inside a +Location section. Access can be limited +for individual request types (DELETE, GET, +HEAD, OPTIONS, POST, PUT, +and TRACE) or for all request types (ALL). The +request type names are case-sensitive for compatibility with Apache. + + +

LimitExcept

+
+ +

Examples

+ +
    +<LimitExcept GET POST>
    +...
    +</LimitExcept>
    +
+ +

Description

+ +

The LimitExcept directive groups access control directives for +specific types of HTTP requests and must appear inside a +Location section. Unlike the +Limit directive, LimitExcept +restricts access for all requests except those listed on the +LimitExcept line. + + +

LimitRequestBody

+
+ +

Examples

+ +
    +LimitRequestBody 10485760
    +LimitRequestBody 10m
    +LimitRequestBody 0
    +
+ +

Description

+ +

The LimitRequestBody 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. + +

Also see the identical +MaxRequestSize directive. + + +

Listen

+
+ +

Examples

+ +
    +Listen 127.0.0.1:631
    +Listen 192.0.2.1:631
    +
+ +

Description

+ +

The Listen directive specifies a network address and port +to listen for connections. Multiple Listen directives can be +provided to listen on multiple addresses. + +

The Listen directive is similar to the +Port directive but allows you to restrict +access to specific interfaces or networks. + + +

Location

+
+ +

Examples

+ +
    +<Location />
    +...
    +</Location>
    +
    +<Location /admin>
    +...
    +</Location>
    +
    +<Location /printers>
    +...
    +</Location>
    +
    +<Location /printers/name>
    +...
    +</Location>
    +
    +<Location /classes>
    +...
    +</Location>
    +
    +<Location /classes/name>
    +...
    +</Location>
    +
+ +

Description

+ +

The Location directive specifies access control and +authentication options for the specified HTTP resource or path. +The +Allow, +AuthClass, +AuthGroupName, +AuthType, +Deny, +Encryption, +Limit, +LimitExcept, +Order, +Require, and +Satisfy +directives may all appear inside a location. + +

+ + + + + + + + + + + +
Locations on the Server.
LocationDescription
/The path for all get operations (get-printers, get-jobs, etc.)
/adminThe path for all administration operations (add-printer, delete-printer, start-printer, etc.)
/admin/confThe path for access to the ESP Print Pro configuration files (cupsd.conf, client.conf, etc.)
/classesThe path for all classes
/classes/nameThe resource for class name
/jobsThe path for all jobs (hold-job, release-job, etc.)
/jobs/idThe resource for job id
/printersThe path for all printers
/printers/nameThe path for printer name
/printers/name.ppdThe PPD file path for printer name
+ +

Note that more specific resources override the less specific ones. +So the directives inside the /printers/name location will override ones from /printers. +Directives inside /printers will override ones from /.   +None of the directives are inherited. +More information can be found in section "Printing System Security". + + +

LogFilePerm

+
+ +

Examples

+ +
    +LogFilePerm 0644
    +LogFilePerm 0600
    +
+ +

Description

+ +

The LogFilePerm directive specifies the permissions +to use when writing configuration files. The default is 0644. + + +

LogLevel

+
+ +

Examples

+ +
    +LogLevel none
    +LogLevel emerg
    +LogLevel alert
    +LogLevel crit
    +LogLevel error
    +LogLevel warn
    +LogLevel notice
    +LogLevel info
    +LogLevel debug
    +LogLevel debug2
    +
+ +

Description

+ +

The LogLevel directive specifies the level of logging +for the ErrorLog file. The +following values are recognized (each level logs everything under the +preceding levels): + +

    + +
  • none - Log nothing. + +
  • emerg - Log emergency conditions that prevent the + server from running. + +
  • alert - Log alerts that must be handled immediately. + +
  • crit - Log critical errors that don't prevent + the server from running. + +
  • error - Log general errors. + +
  • warn - Log errors and warnings. + +
  • notice - Log temporary error conditions. + +
  • info - Log all requests and state changes (default). + +
  • debug - Log basic debugging information. + +
  • debug2 - Log all debugging information. + +
+ + +

MaxClients

+
+ +

Examples

+ +
    +MaxClients 100
    +MaxClients 1024
    +
+ +

Description

+ +

The MaxClients directive controls the maximum number of +simultaneous clients that will be allowed by the server. The default is +100 clients.

+ +
+ + + +
+ NOTE: + +

Since each print job requires a file descriptor for the + status pipe, the CUPS server internally limits the + MaxClients value to 1/3 of the available file descriptors + to avoid possible problems when printing large numbers of jobs. +

+ + +

MaxCopies

+
+ +

Examples

+ +
    +MaxCopies 100
    +MaxCopies 65535
    +
+ +

Description

+ +

The MaxCopies directive controls the maximum +number of copies that a user can print of a job. The default is +100 copies.

+ +
+ + + +
+ NOTE: + +

Most HP PCL laser printers internally limit the + number of copies to 100. + +

+ + +

MaxJobs

+
+ +

Examples

+ +
    +MaxJobs 100
    +MaxJobs 9999
    +MaxJobs 0
    +
+ +

Description

+ +

The MaxJobs 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. + +

Setting the maximum to 0 disables this functionality. The default +setting is 0. + + +

MaxJobsPerPrinter

+
+ +

Examples

+ +
    +MaxJobsPerPrinter 100
    +MaxJobsPerPrinter 9999
    +MaxJobsPerPrinter 0
    +
+ +

Description

+ +

The MaxJobsPerPrinter 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. + +

Setting the maximum to 0 disables this functionality. The default +setting is 0. + + +

MaxJobsPerUser

+
+ +

Examples

+ +
    +MaxJobsPerUser 100
    +MaxJobsPerUser 9999
    +MaxJobsPerUser 0
    +
+ +

Description

+ +

The MaxJobsPerUser 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. + +

Setting the maximum to 0 disables this functionality. The default +setting is 0. + + +

MaxLogSize

+
+ +

Examples

+ +
    +MaxLogSize 1048576
    +MaxLogSize 1m
    +MaxLogSize 0
    +
+ +

Description

+ +

The MaxLogSize 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 filename.O. This allows you to rotate the logs +automatically. The default size is 1048576 bytes (1MB). + +

Setting the maximum size to 0 disables log rotation. + + +

MaxRequestSize

+
+ +

Examples

+ +
    +MaxRequestSize 10485760
    +MaxRequestSize 10m
    +MaxRequestSize 0
    +
+ +

Description

+ +

The MaxRequestSize 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. + +

Also see the identical +LimitRequestBody directive. + + +

Order

+
+ +

Examples

+ +
    +Order Allow,Deny
    +Order Deny,Allow
    +
+ +

Description

+ +

The Order directive defines the default access control. +The following values are supported: + +

    + +
  • Allow,Deny - Allow requests from all + systems except for those listed in a Deny + directive. + +
  • Deny,Allow - Allow requests only from + those listed in an Allow directive. + +
+ +

The Order directive must appear inside a +Location directive. + + +

PageLog

+
+ +

Examples

+ +
    +PageLog /var/log/cups/page_log
    +PageLog /var/log/cups/page_log-%s
    +PageLog syslog
    +
+ +

Description

+ +

The PageLog directive sets the name of the page log +file. If the filename is not absolute then it is assumed to be relative +to the ServerRoot directory. The +default page log file is /var/log/cups/page_log. + +

The server name can be included in the filename by using +%s in the name. + +

The special name "syslog" can be used to send the page information +to the system log instead of a plain file. + + +

Port

+
+ +

Examples

+ +
    +Port 631
    +Port 80
    +
+ +

Description

+ +

The Port directive specifies a port to listen on. +Multiple Port lines can be specified to listen on multiple +ports. The default port is 631. + + +

PreserveJobHistory

+
+ +

Examples

+ +
    +PreserveJobHistory On
    +PreserveJobHistory Off
    +
+ +

Description

+ +

The PreserveJobHistory directive controls whether +the history of completed, cancelled, or aborted print jobs is stored +on disk. + +

A value of On (the default) preserves job information +until the administrator purges it with the cancel +command. + +

A value of Off removes the job information as soon as +each job is completed, cancelled, or aborted. + + +

PreserveJobFiles

+
+ +

Examples

+ +
    +PreserveJobFiles On
    +PreserveJobFiles Off
    +
+ +

Description

+ +

The PreserveJobFiles directive controls whether the +document files of completed, cancelled, or aborted print jobs are +stored on disk. + +

A value of On preserves job files until the +administrator purges them with the cancel command. Jobs +can be restarted (and reprinted) as desired until they are purged. + +

A value of Off (the default) removes the job files as +soon as each job is completed, cancelled, or aborted. + + +

Printcap

+
+ +

Examples

+ +
    +Printcap
    +Printcap /etc/printcap
    +Printcap /etc/printers.conf
    +
+ +

Description

+ +

The Printcap 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 /etc/printcap. + +

When a filename is specified (e.g. /etc/printcap), 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. + + +

PrintcapFormat

+
+ +

Examples

+ +
    +PrintcapFormat BSD
    +PrintcapFormat Solaris
    +
+ +

Description

+ +

The PrintcapFormat directive controls the output +format of the printcap file. The default is to generate a BSD +printcap file. + + +

PrintcapGUI

+
+ +

Example

+ +
    +PrintcapGUI /usr/bin/glpoptions
    +
+ +

Description

+ +

The PrintcapGUI directive sets the program to +use when displaying an option panel from an IRIX application +that uses the Impressario print API. The default program is the +ESP Print Pro "glpoptions" GUI. + +

The program must accept the -d option to specify +a printer and the -o option to specify one or more +options. After allowing the user to select/change options, the +program must then write the list of printing options without the +-o to the standard output. + + +

RemoteRoot

+
+ +

Examples

+ +
    +RemoteRoot remroot
    +RemoteRoot root
    +
+ +

Description

+ +

The RemoteRoot directive sets the username for +unauthenticated root requests from remote hosts. The default +username is remroot. Setting RemoteRoot +to root effectively disables this security mechanism. + + +

RequestRoot

+
+ +

Examples

+ +
    +RequestRoot /var/spool/cups
    +RequestRoot /foo/bar/spool/cups
    +
+ +

Description

+ +

The RequestRoot 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 +ServerRoot directory. The +default request directory is /var/spool/cups. + + +

Require

+
+ +

Examples

+ +
    +Require group foo bar
    +Require user john mary
    +Require valid-user
    +
+ +

Description

+ +

The Require directive specifies that +authentication is required for the resource. The +group keyword specifies that the authenticated user +must be a member of one or more of the named groups that follow. + +

The user keyboard specifies that the +authenticated user must be one of the named users that follow. + +

The valid-user keyword specifies that any +authenticated user may access the resource. + +

The default is to do no authentication. This directive must +appear inside a Location +directive. + + +

RIPCache

+
+ +

Examples

+ +
    +RIPCache 8m
    +RIPCache 1g
    +RIPCache 2048k
    +
+ +

Description

+ +

The RIPCache directive sets the size of the memory +cache used by Raster Image Processor ("RIP") filters such as +imagetoraster and pstoraster. The size can +be suffixed with a "k" for kilobytes, "m" for megabytes, or +"g" for gigabytes. The default cache size is "8m", or 8 megabytes. + + +

RootCertDuration

+
+ +

Examples

+ +
    +RootCertDuration 300
    +RootCertDuration 0
    +
+ +

Description

+ +

The RootCertDuration directive controls the +interval between updates of the root authentication certificate. +The default is 300 seconds which updates the root +certificate approximately once every 5 minutes. Set the interval +to 0 to disable certificate updates entirely. + + + +

RunAsUser

+
+ +

Examples

+ +
    +RunAsUser Yes
    +RunAsUser No
    +
+ +

Description

+ +

The RunAsUser directive controls whether the +scheduler runs as the unpriviledged user account (usually lp). +The default is No which leaves the scheduler running as +the root user. + +

Note: Running as a non-priviledged user may prevent +LPD and locally connected printers from working due to +permission problems. The lpd backend will +automatically use a non-priviledged mode that is not 100% +compliant with RFC 1179. The parallel, +serial, and usb backends will need +write access to the corresponding device files. + + +

Satisfy

+
+ +

Examples

+ +
    +Satisfy all
    +Satisfy any
    +
+ +

Description

+ +

The Satisfy directive specifies whether all +conditions must be satisfied to allow access to the resource. If +set to all, then all authentication and access +control conditions must be satified to allow access. + +

Setting Satisfy to any allows a user to +gain access if the authentication or access control requirements are +satisfied. For example, you might require authentication for remote +access, but allow local access without authentication. + +

The default is all. This directive must appear +inside a Location +directive. + + +

ServerAdmin

+
+ +

Examples

+ +
    +ServerAdmin user@host
    +ServerAdmin root@foo.bar.com
    +
+ +

Description

+ +

The ServerAdmin directive identifies the email address for the +administrator on the system. By default the administrator email address is +root@server, where server is the server name. + + +

ServerBin

+
+ +

Examples

+ +
    +ServerBin /usr/lib/cups
    +ServerBin /foo/bar/lib/cups
    +
+ +

Description

+ +

The ServerBin directive sets the directory for +server-run executables. If an absolute path is not provided then it is +assumed to be relative to the +ServerRoot directory. The +default executable directory is /usr/lib/cups. + + +

ServerCertificate

+
+ +

Examples

+ +
    +ServerCertificate /etc/cups/ssl/server.crt
    +
+ +

Description

+ +

The ServerCertificate 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 /etc/cups/ssl/server.crt. + + +

ServerKey

+
+ +

Examples

+ +
    +ServerKey /etc/cups/ssl/server.key
    +
+ +

Description

+ +

The ServerKey directive specifies the location +of the SSL private key file used by the server when negotiating +encrypted connections. The default key file is +/etc/cups/ssl/server.crt. + + +

ServerName

+
+ +

Examples

+ +
    +ServerName foo.domain.com
    +ServerName myserver.domain.com
    +
+ +

Description

+ +

The ServerName directive specifies the hostname that is +reported to clients. By default the server name is the hostname. + + +

ServerRoot

+
+ +

Examples

+ +
    +ServerRoot /etc/cups
    +ServerRoot /foo/bar/cups
    +
+ +

Description

+ +

The ServerRoot directive specifies the absolute path to +the server configuration and state files. It is also used to resolve +relative paths in the cupsd.conf file. The default server +directory is /etc/cups. + + +

SSLListen

+
+ +

Examples

+ +
    +SSLListen 127.0.0.1:443
    +SSLListen 192.0.2.1:443
    +
+ +

Description

+ +

The SSLListen directive specifies a network +address and port to listen for secure connections. Multiple +SSLListen directives can be provided to listen on +multiple addresses. + +

The SSLListen directive is similar to the +SSLPort directive but allows +you to restrict access to specific interfaces or networks. + + +

SSLPort

+
+ +

Examples

+ +
    +SSLPort 443
    +
+ +

Description

+ +

The SSLPort directive specifies a port to listen +on for secure connections. Multiple SSLPort lines +can be specified to listen on multiple ports. + + +

SystemGroup

+
+ +

Examples

+ +
    +SystemGroup sys
    +SystemGroup system
    +SystemGroup root
    +
+ +

Description

+ +

The SystemGroup directive specifies the system +administration group for System authentication. More +information can be found later in this chapter in +"Printing System Security". + + +

TempDir

+
+ +

Examples

+ +
    +TempDir /var/tmp
    +TempDir /foo/bar/tmp
    +
+ +

Description

+ +

The TempDir directive specifies an absolute path for +the directory to use for temporary files. The default directory is +/var/tmp. + +

Temporary directories must be world-writable and should have the +"sticky" permission bit enabled so that other users cannot delete +filter temporary files. The following commands will create an +appropriate temporary directory called /foo/bar/tmp: + +

    +mkdir /foo/bar/tmp ENTER
    +chmod a+rwxt /foo/bar/tmp ENTER
    +
+ + +

Timeout

+
+ +

Examples

+ +
    +Timeout 300
    +Timeout 90
    +
+ +

Description

+ +

The Timeout directive controls the amount of time to +wait before an active HTTP or IPP request times out. The default +timeout is 300 seconds. + + +

User

+
+ +

Examples

+ +
    +User lp
    +User guest
    +
+ +

Description

+ +

The User directive specifies the UNIX user that +filter and CGI programs run as. The default user is lp. + + + +

Changing the Client Configuration

+ +

The CUPS client application (lp, lpr, and so forth) +use the /etc/cups/client.conf file for default settings. +The client application also look in the user's home directory for a file called .cupsrc. +Each directive is listed on a line by itself followed by its value. Comments are introduced +using the number sign ("#") character at the beginning of a line. + +

Since the client configuration file consists of plain text, you can +use your favorite text editor to make changes to it. + + +

Client Directives

+ +

The client.conf file contains many directives that +determine how the client behaves:

+ + + + +

Encryption

+
+ +

Examples

+ +
    +Encryption Never
    +Encryption IfRequested
    +Encryption Required
    +Encryption Always
    +
+ +

Description

+ +

The Encryption directive specifies the default encryption settings for the client. +The default setting is IfRequested. + + + +

ServerName

+
+ +

Examples

+ +
    +ServerName foo.bar.com
    +ServerName 11.22.33.44
    +
+ +

Description

+ +

The ServerName directive specifies sets the remote server that is to be used +for all client operations. That is, it redirects all client requests to the remote server. + +The default is to use the local server ("localhost"). + + + +

Changing the Printer Configuration

+ +

The CUPS scheduler (cupsd) uses the /etc/cups/printers.conf file +to store the list of available printers. This file contains only locally defined +printers, but not remote printers that are created automatically. Each directive +is listed on a line by itself followed by its value. Comments are introduced +using the number sign ("#") character at the beginning of a line. + +

Since the printer configuration file consists of plain text, you can +use your favorite text editor to make changes to it. + + +

Printer Directives

+ +

The printers.conf file contains many directives that +determine how the printer behaves:

+ + + + +

Accepting

+
+ +

Examples

+ +
    +Accepting yes
    +
    +Accepting no
    +
+ +

Description

+ +

The Accepting directive defines the initial Boolean +value for the printer-is-accepting-job attribute which can +be set by the accept and reject commands. + +

This directive must appear inside a Printer +or DefaultPrinter directive. + + +

AllowUser

+
+ +

Examples

+ +
    +AllowUser foo_user
    +AllowUser bar_user
    +
+ +

Description

+ +

The AllowUser directive adds a username to the +requesting-user-name-allowed attribute which can be set +by the lpadmin -u command. + +

This directive must appear inside a Printer +or DefaultPrinter directive. + + +

DefaultPrinter

+
+ +

Examples

+ +
    +<DefaultPrinter name/>
    +...
    +</Printer>
    +
+ +

Description

+ +

The DefaultPrinter directive begins a printer definition +for the default server destination. +It can be added by the lpadmin command or if already defined, +set as default by the lpoptions -d command.

+ + +

DenyUser

+
+ +

Examples

+ +
    +DenyUser foo_user
    +DenyUser bar_user
    +
+ +

Description

+ +

The DenyUser directive adds a username to the +requesting-user-name-allowed attribute which can be set +by the lpadmin -u command.

+ +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + +

DeviceURI

+
+ +

Examples

+ +
    +DeviceURI socket://foo.bar.com:9100
    +
+ +

Description

+ +

The DeviceURI directive defines the value of the +device-uri-attribute attribute which can be set by +the lpadmin -v command. + +

This directive must appear inside a Printer +or DefaultPrinter directive. + + +

Info

+
+ +

Examples

+ +
    +Info My Printer
    +
+ +

Description

+ +

The Info directive defines the string for the +printer-info attribute which can be set by the +lpadmin -D command.

+ +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + +

JobSheets

+
+ +

Examples

+ +
    +JobSheets none,standard
    +
+ +

Description

+ +

The JobSheets directive specifies the default banner pages +to print before and after a print job. +In the above example, only a standard banner will print after each job.

+ +

The lpoptions -o job-sheets= command can be used to set banners. +For example, the following command would produce the same results of a +standard banner at the end of each print job for the default printer.

+ +
    +lpoptions -o job-sheets=none,standard +
+ +

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.

+ +

The available banner pages depend on the local system configuration; + CUPS includes the following banner files:

+ +
    +
  • none - Do not produce a banner page.
  • +
  • classified - A banner page with a "classified" label at the top and bottom.
  • +
  • confidential - A banner page with a "confidential" label at the top and bottom.
  • +
  • secret - A banner page with a "secret" label at the top and bottom.
  • +
  • standard - A banner page with no label at the top and bottom.
  • +
  • topsecret - A banner page with a "top secret" label at the top and bottom.
  • +
  • unclassified - A banner page with an "unclassified" label at the top and bottom.
  • +
+ +

This directive must appear inside a Printer +or DefaultPrinter directive. + + +

KLimit

+
+ +

Examples

+ +
    +KLimit 1234
    +
+ +

Description

+ +

The KLimit directive defines the value of the +job-k-limit attribute which can be set by the +lpadmin -o job-k-limit= command. + +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + +

Location

+
+ +

Examples

+ +
    +Location Building 3321
    +
+ +

Description

+ +

The Location directive defines the string for the +printer-location attribute which can be set by the +lpadmin -L command.

+ +
+ + + +
+ NOTE: + +

Do not confuse this Location directive with the + one for cupsd.conf. They are completely different. +

+ +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + +

PageLimit

+
+ +

Examples

+ +
    +PageLimit 1234
    +
+ +

Description

+ +

The PageLimit directive defines the value of the +job-page-limit attribute which can be set +by the lpadmin -o job-page-limit= command.

+ +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + +

Printer

+
+ +

Examples

+ +
    +<Printer name/>
    +...
    +</Printer>
    +
+ +

Description

+ +

The Printer directive begins a printer definition. +It can be added by the lpadmin command. + + +

QuotaPeriod

+
+ +

Examples

+ +
    +QuotaPeriod 604800
    +
+ +

Description

+ +

The QuotaPeriod directive defines the value of the +job-quota-period attribute which can be set +by the lpadmin -o job-quota-period= command.

+ +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + +

State

+
+ +

Examples

+ +
    +State stopped
    +
+ +

Description

+ +

The State directive defines the initial value of the +printer-state attribute. The strings idle and +stopped correspond to the IPP enumeration values.

+ +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + +

StateMessage

+
+ +

Examples

+ +
    +StateMessage Ready to print.
    +
+ +

Description

+ +

The StateMessage directive defines the initial string for the +printer-state-message attribute. +The following are some example messages:

+ +
    +
  • Connected to host_name... +
  • Connecting to printer_queue on port port_number... +
  • Network host host_name is busy; will retry in 30 seconds... +
  • Printer busy; will retry in 10 seconds... +
  • Printer is busy; retrying print job... +
  • Print file accepted - job ID id_number. +
  • Ready to print. +
  • Waiting for job to complete +
+ +

This directive must appear inside a Printer +or DefaultPrinter directive.

+ + + +

Changing the Classes Configuration

+ +

The CUPS scheduler (cupsd) uses the /etc/cups/classes.conf file +to store the list of available classes. This file contains only locally defined +classes, but not remote or implicit classes that are created automatically. +Each directive is listed on a line by itself followed by its value. +Comments are introduced using the number sign ("#") character at the beginning of a line. + +

Since the classes configuration file consists of plain text, you can +use your favorite text editor to make changes to it. + + +

Classes Directives

+ +

The classes.conf file contains many directives that +determine how the classes behaves:

+ + + + +

Accepting

+
+ +

Examples

+ +
    +Accepting yes
    +
    +Accepting no
    +
+ +

Description

+ +

The Accepting directive defines the initial Boolean +value for the printer-is-accepting-job attribute which can +be set by the accept and reject commands. + +

This directive must appear inside a Class +or DefaultClass directive. + + +

AllowUser

+
+ +

Examples

+ +
    +AllowUser foo_user
    +AllowUser bar_user
    +
+ +

Description

+ +

The AllowUser directive adds a username to the +requesting-user-name-allowed attribute which can be set +by the lpadmin -u command. + +

This directive must appear inside a Class +or DefaultClass directive. + + + +

Class

+
+ +

Examples

+ +
    +<Class name/>
    +...
    +</Class>
    +
+ +

Description

+ +

The Class directive begins a class definition. +It can be added by the lpadmin -c command.

+ + +

DefaultClass

+
+ +

Examples

+ +
    +<DefaultClass name/>
    +...
    +</DefaultClass>
    +
+ +

Description

+ +

The DefaultClass directive begins a class definition +for the default server destination. +It can be added by the lpadmin -c command or if already defined, +set as default by the lpoptions -d command.

+ + +

DenyUser

+
+ +

Examples

+ +
    +DenyUser foo_user
    +DenyUser bar_user
    +
+ +

Description

+ +

The DenyUser directive adds a username to the +requesting-user-name-allowed attribute which can be set +by the lpadmin -u command.

+ +

This directive must appear inside a Class +or DefaultClass directive. + + +

Info

+
+ +

Examples

+ +
    +Info My Printer
    +
+ +

Description

+ +

The Info directive defines the string for the +printer-info attribute which can be set by the +lpadmin -D command.

+ +

This directive must appear inside a Class +or DefaultClass directive. + + +

JobSheets

+
+ +

Examples

+ +
    +JobSheets none,standard
    +
+ +

Description

+ +

The JobSheets directive specifies the default banner pages +to print before and after a print job. +In the above example, only a standard banner will print after each job.

+ +

The lpoptions -o job-sheets= command can be used to set banners. +For example, the following command would produce the same results of a +standard banner at the end of each print job for the default class.

+ +
    +lpoptions -o job-sheets=none,standard +
+ +

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.

+ +

The available banner pages depend on the local system configuration; + CUPS includes the following banner files:

+ +
    +
  • none - Do not produce a banner page.
  • +
  • classified - A banner page with a "classified" label at the top and bottom.
  • +
  • confidential - A banner page with a "confidential" label at the top and bottom.
  • +
  • secret - A banner page with a "secret" label at the top and bottom.
  • +
  • standard - A banner page with no label at the top and bottom.
  • +
  • topsecret - A banner page with a "top secret" label at the top and bottom.
  • +
  • unclassified - A banner page with an "unclassified" label at the top and bottom.
  • +
+ +

This directive must appear inside a Class +or DefaultClass directive. + + +

KLimit

+
+ +

Examples

+ +
    +KLimit 1234
    +
+ +

Description

+ +

The KLimit directive defines the value of the +job-k-limit attribute which can be set by the +lpadmin -o job-k-limit= command. + +

This directive must appear inside a Class +or DefaultClass directive. + + +

Location

+
+ +

Examples

+ +
    +Location Building 3321
    +
+ +

Description

+ +

The Location directive defines the string for the +printer-location attribute which can be set by the +lpadmin -L command.

+ +
+ + + +
+ NOTE: + +

Do not confuse this Location directive with the + one for cupsd.conf. They are completely different. +

+ +

This directive must appear inside a Class +or DefaultClass directive. + + +

PageLimit

+
+ +

Examples

+ +
    +PageLimit 1234
    +
+ +

Description

+ +

The PageLimit directive defines the value of the +job-page-limit attribute which can be set +by the lpadmin -o job-page-limit= command.

+ +

This directive must appear inside a Class +or DefaultClass directive. + + +

Printer

+
+ +

Examples

+ +
    +Printer foo
    +Printer bar
    +Printer foo@bar
    +
+ +

Description

+ +

The Printer directive adds a printer to the class. +It can be added by the lpadmin -c command.

+ +
+ + + +
+ NOTE: + +

Do not confuse this Printer directive with the + one for printers.conf. They are completely different. +

+ +

This directive must appear inside a Class +or DefaultClass directive.

+ + +

QuotaPeriod

+
+ +

Examples

+ +
    +QuotaPeriod 604800
    +
+ +

Description

+ +

The QuotaPeriod directive defines the value of the +job-quota-period attribute which can be set +by the lpadmin -o job-quota-period= command.

+ +

This directive must appear inside a Class +or DefaultClass directive. + + +

State

+
+ +

Examples

+ +
    +State stopped
    +
+ +

Description

+ +

The State directive defines the initial value of the +printer-state attribute. The strings idle and +stopped correspond to the IPP enumeration values.

+ +

This directive must appear inside a Class +or DefaultClass directive. + + +

StateMessage

+
+ +

Examples

+ +
    +StateMessage Ready to print.
    +
+ +

Description

+ +

The StateMessage directive defines the initial string for the +printer-state-message attribute. +The following are some example messages:

+ +
    +
  • Connected to host_name... +
  • Connecting to class_queue on port port_number... +
  • Network host host_name is busy; will retry in 30 seconds... +
  • Printer busy; will retry in 10 seconds... +
  • Printer is busy; retrying print job... +
  • Print file accepted - job ID id_number. +
  • Ready to print. +
  • Waiting for job to complete +
+ +

This directive must appear inside a Class +or DefaultClass directive.

+ + + + + +

Printing System Security

+ +

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. + +

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. + +

CUPS maintains a list of locations that have access control and/or +authentication enabled. Locations are specified using the +Location directive: + +

+ +

Locations generally follow the directory structure of the +DocumentRoot directory, however +CUPS does have several virtual locations for administration, classes, jobs, +and printers: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LocationDescription
/adminThe path for all administration operations.
/classesThe path for all classes.
/classes/nameThe resource for class name.
/jobsThe path for all jobs.
/jobs/idThe resource for job id.
/printersThe path for all printers.
/printers/nameThe path for printer name.
/printers/name.ppdThe PPD file path for printer name.
+ +

Authentication Using Certificates

+ +

CUPS supports a local certificate-based authentication scheme that +can be used in place of Basic or Digest +authentication by clients connecting through the localhost +interface. Certificate authentication is not supported or allowed from +clients on any other interface. + +

Certificates are 128-bit random numbers that refer to an internal +authentication record in the server. A client connecting via the +localhost interface sends a request with an +authorization header of: + +

    +Authorization: Local 0123456789ABCDEF0123456789ABCDEF
    +
+ +

The server then looks up the local certificate and authenticates +using the username associated with it. + +

Certificates are generated by the server automatically and stored in +the /etc/cups/certs directory using the process ID of the +CGI program started by the server. Certificate files are only readable +by the User and +Group defined in the +cupsd.conf file. When the CGI program ends the certificate +is removed and invalidated automatically. + +

The special file /etc/cups/certs/0 defines the root +certificate which can be used by any client running as the super-user +or another user that is part of the group defined by the +SystemGroup directive. The +root certificate is automatically regenerated every 5 minutes. + +

Using Basic Authentication

+ +

Basic authentication uses UNIX users and passwords to authenticate +access to resources such as printers and classes, and to limit access +to administrative functions.

+ +
+ + + +
+NOTE: + +

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. +

+ +

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. + +

Once a valid username and password is authenticated by CUPS, any +additional group membership requirements are checked.

+ +
+ + + +
+NOTE: + +

The root user is considered by CUPS to be a member of every +group. +

+ + +

Use the AuthType directive to enable Basic authentication: + +

    +AuthType Basic
    +
+ + +

Using Digest Authentication

+ +

Digest authentication uses users and passwords defined in the +/etc/cups/passwd.md5 file to authenticate access to +resources such as printers and classes, and to limit access to +administrative functions.

+ +
+ + + +
+NOTE: + +

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. + +

The current CUPS implementation of Digest authentication +uses the client's hostname or IP address for the "nonce" 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 "session" authentication which adds +the request data to the MD5 sum, providing even better +authentication and security. + +

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. Support for Digest +authentication in web browsers is not yet universally +available. +

+ + +

The lppasswd(1) command is used to add, change, or +remove accounts from the passwd.md5 file. To add a +user to the default system group, type: + +

    +lppasswd -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
+ + +

Once added, a user can change his/her password by typing: + +

    +lppasswd ENTER
    +Old password: (password) ENTER [password is not echoed]
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
+ + +

To remove a user from the password file, type: + +

    +lppasswd -x user ENTER
    +
+ +

Once a valid username and password is authenticated by CUPS, any +additional group membership requirements are checked.

+ +
+ + + +
+NOTE: + +

The root user is considered by CUPS to be a member of every +group. +

+ +

Use the AuthType directive to enable Digest authentication: + +

    +AuthType Digest
    +
+ +

System and Group Authentication

+ +

The AuthClass directive controls +the level of authentication to perform. System and +Group authentication extend the normal user-based authentication +to require membership in a UNIX group. For System authentication +each user must belong to the sys, system, or +root group; the actual group depends on the operating system. + +

For Group authentication each user must belong to the +group named by the AuthGroupName +directive: + +

    +<Location /path>
    +AuthType Digest
    +AuthClass Group
    +AuthGroupName mygroup
    +</Location>
    +
+ +

The named group must be a valid UNIX user group, usually defined in the +/etc/group or /etc/netgroup files. Additionally, when +using Digest authentication you need to create user accounts with the named +group: + +

    +lppasswd -g mygroup -a user ENTER
    +Password: (password) ENTER [password is not echoed]
    +Password again: (password) ENTER [password is not echoed]
    +
+ + +

Printer Accounting

+ +

CUPS maintains a log of all accesses, errors, and +pages that are printed. The log files are normally stored in the +/var/log/cups directory. You can change this by +editing the /etc/cups/cupsd.conf configuration file. + +

The access_log File

+ +

The access_log file lists each HTTP resource that is accessed +by a web browser or CUPS/IPP client. Each line is in the so-called "Common +Log Format" used by many web servers and web reporting tools: + +

    +host group user date-time \"method resource version\" status bytes
    +
    +127.0.0.1 - - [20/May/1999:19:20:29 +0000] "POST /admin/ HTTP/1.1" 401 0
    +127.0.0.1 - mike [20/May/1999:19:20:31 +0000] "POST /admin/ HTTP/1.1" 200 0
    +
+ +

The host field will normally only be an IP address unless you +have enabled the HostNameLookups +directive in the cupsd.conf file. + +

The group field always contains "-" in CUPS. + +

The user field is the authenticated username of the requesting user. +If no username and password is supplied for the request then this field +contains "-". + +

The date-time field is the date and time of the request in local time +and is in the format: + +

    +[DD/MON/YYYY:HH:MM:SS +ZZZZ]
    +
+ +

where ZZZZ is the timezone offset in hours and minutes +from coordinated universal time (UTC). UTC may sometimes be +referred to as GMT or ZULU on legacy systems.

+ +

The method field is the HTTP method used ("GET", "PUT", "POST", etc.) + +

The resource field is the filename of the requested resource. + +

The version field is the HTTP specification version used by the +client. For CUPS clients this will always be "HTTP/1.1". + +

The status field contains the HTTP result status of the +request. Usually it is "200", but other HTTP status codes are possible. +For example, 401 is the "unauthorized access" status in the example +above. + +

The bytes field contains the number of bytes in the request. +For POST requests the bytes field contains the number of bytes +that was received from the client. + +

The error_log File

+ +

The error_log file lists messages from the scheduler (errors, +warnings, etc.): + +

    +level date-time message
    +
    +I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
    +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'.
    +
+ +

The level field contains the type of message: + +

    + +
  • E - An error occurred. + +
  • W - The server was unable to perform some action. + +
  • I - Informational message. + +
  • D - Debugging message. + +
+ +

The date-time field contains the date and time of when the page +started printing. The format of this field is identical to the data-time +field in the access_log file. + +

The message fields contains a free-form textual message. + +

The page_log File

+ +

The page_log file lists each page that is sent to a printer. +Each line contains the following information: + +

    +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
    +
+ +

The printer 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. + +

The user field contains the name of the user (the IPP +requesting-user-name attribute) that submitted this file for +printing. + +

The job-id 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! + +

The date-time field contains the date and time of when the page +started printing. The format of this field is identical to the data-time +field in the access_log file. + +

The page-number and num-pages 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 num-pages field will always be 1. + +

The job-billing field contains a copy of the +job-billing attribute provided with the IPP +create-job or print-job requests or "-" if none +was provided. + + +

File Typing and Filtering

+ +

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 /etc/cups +directory (or a directory specified by the +ServerRoot 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. + +

The mime.types and mime.convs files define the +standard file types and filters that are available on the system. + +

mime.types

+ +

The mime.types 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 +text/html file type is defined as: + +

    +text/html       html htm \
    +	printable(0,1024) + \
    +	(string(0,"<HTML>") string(0,"<!DOCTYPE"))
    +
+ +

The first two rules say that any file with an extension of +.html or .htm is a HTML file. The third rule +says that any file whose first 1024 characters are printable text and +starts with the strings <HTML> or +<!DOCTYPE is a HTML file as well. + +

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. + +

The available tests are: + +

    + +
  • ( expr ) - Parenthesis for expression grouping + +
  • + - Logical AND + +
  • , or whitespace - Logical OR + +
  • ! - Logical NOT + +
  • match("pattern") - Pattern match on filename + +
  • extension - Pattern match on "*.extension" + +
  • ascii(offset,length) - True if bytes are valid +printable ASCII (CR, NL, TAB, BS, 32-126) + +
  • printable(offset,length) - True if bytes are +printable 8-bit chars (CR, NL, TAB, BS, 32-126, 160-254) + +
  • string(offset,"string") - True if bytes are +identical to string + +
  • contains(offset,range,"string") - True if the +range of bytes contains the string + +
  • char(offset,value) - True if byte is identical + +
  • short(offset,value) - True if 16-bit integer +is identical (network or "big-endian" byte order) + +
  • int(offset,value) - True if 32-bit integer is +identical (network or "big-endian" byte order) + +
  • locale("string") - True if current locale +matches string + +
+ +

All numeric values can be in decimal (123), octal (0123), or hexadecimal +(0x123) as desired. + + +

Strings can be in quotes, all by themselves, as a string +of hexadecimal values, or some combination: + +

    +"string"
    +'string'
    +string
    +<737472696e67>
    +<7374>ring
    +
+ +

As shown in the text/html example, rules can continue on +multiple lines using the backslash (\) character. A more complex example is +the image/jpeg rules: + +

    +image/jpeg      jpeg jpg jpe string(0,<FFD8FF>) &&\
    +	(char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
    +	 char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
    +	 char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
    +	 char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
    +
+ +

This rule states that any file with an extension of +.jpeg, .jpg, or .jpe is a JPEG file. +In addition, any file starting with the hexadecimal string +<FFD8FF> (JPEG Start-Of-Image) followed by a +character between and including 0xe0 and 0xef +(JPEG APPn markers) is also a JPEG file. + +

mime.convs

+ +

The mime.convs file defines all of the filter programs that +are known to the system. Each line consists of: + +

    +source destination cost program
    +
    +text/plain application/postscript 50 texttops
    +application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
    +image/* application/vnd.cups-postscript 50 imagetops
    +image/* application/vnd.cups-raster 50 imagetoraster
    +
+ +

The source field is a MIME type, optionally using a wildcard for +the super-type or sub-type (e.g. "text/plain", "image/*", "*/postscript"). + +

The destination field is a MIME type defined in the +mime.types file. + +

The cost 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 image/jpeg to application/vnd.cups-raster, +you could use the imagetops and pstoraster +filters for a total cost of 100, or the imagetoraster filter +for a total cost of 50. + +

The program field defines the filter program to run; the +special program "-" 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: + +

    +program job user title options [filename]
    +
+ +

If specified, the filename 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. + + +

Adding Filetypes and Filters

+ +

Adding a new file type or filter is fairly straight-forward. Rather +than adding the new type and filter to the mime.types and +mime.convs files which are overwritten when you upgrade to a +new version of CUPS, you simple need to create new files with +.types and .convs extensions in the +/etc/cups directory. We recommend that you use the product +or format name, e.g.: + +

    +myproduct.types
    +myproduct.convs
    +
+ +

If you are providing a filter for a common file format or printer, +add the company or author name: + +

    +acme-msword.types
    +acme.msword.convs
    +
+ +

This will help to prevent name collisions if you install many +different file types and filters. + +

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 cupsd process as +described earlier in "Restarting the CUPS Server". + +

Printer Drivers and PPD Files

+ +

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 cupsFilter attributes: + +

    +*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
    +
+ +

The filter is specified using the source file type only; the destination +file type is assumed to be printer/name - suitable for sending +to the printer. + +

Writing Your Own Filter or Printer Driver

+ +

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. + + +

7 - Printing with Other Systems

+ +

This chapter describes how to print from client systems that use the +LPD, Mac OS, or Windows printing protocols. + +

The Basics

+ +

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. + +

Printing from LPD Clients

+ +

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. + +

The cups-lpd(8) program provides support for LPD +clients and can be used from either the inetd(8) or +xinetd(8) programs. Add the following line to the +/etc/inetd.conf file to enable LPD support on your +server through the inetd program: + +

    +printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
    +
+ +

The path to the cups-lpd may vary depending on your +installation. + +

Once you have added this line, send the inetd +process a HUP signal or reboot the system: + +

    +killall -HUP inetd ENTER [IRIX and some versions of Linux]
    +kill -HUP pid ENTER [Others]
    +reboot ENTER [For all systems if the HUP signal fails]
    +
+ +

If you are using the xinetd program, create a +file named /etc/xinetd.d/printer containing the +following lines: + +

    +service printer
    +{
    +socket_type = stream
    +protocol = tcp
    +wait = no
    +user = lp
    +server = /usr/lib/cups/daemon/cups-lpd
    +}
    +
+ +

The xinetd program automatically reads the new +configuration file and enables LPD printing support. + +

+ + + +
Warning: + +

cups-lpd currently does not perform any +access control based on the settings in +cupsd.conf or in the hosts.allow +or hosts.deny files used by TCP wrappers. +Therefore, running cups-lpd on your server +will allow any computer on your network (and perhaps the +entire Internet) to print to your server. + +

While xinetd has built-in access control +support, you should use the TCP wrappers package with +inetd to limit access to only those +computers that should be able to print through your +server. + +

+ +

Printing to LPD Servers

+ +

CUPS provides the lpd backend for printing to LPD-based +servers and printers. Use a device URI of lpd://server/name +to print to a printer on an LPD server, where server +is the hostname or IP address of the server and name is +the queue name. + +

Microsoft Windows NT provides an LPD service under the name "TCP/IP +Printing Services". To enable LPD printing on NT, open the "Services" +control panel, select the "TCP/IP Printing Services" service, and click +on the "Start" button. Any shared printer will then be available via +the LPD protocol. + +

Printing from Mac OS Clients

+ +

CUPS does not provide Mac OS support directly. However, there are several +free and commercial software packages that do. + +

Columbia Appletalk Package (CAP)

+ +

Because the CAP LaserWriter server (lwsrv(8)) does +not support specification of PPD files, we do not recommend that you +use CAP with CUPS. However, you can run the lpsrv program +for limited printing with the command: + +

    +lwsrv -n "Name" -p printer -a /usr/lib/adicts -f /usr/lib/LW+Fonts
    +
+ +

where Name is the name you want to use when sharing the +printer, and printer is the name of the CUPS print queue. + + +

XINET KA/Spool

+ +

To use your system as a print server for Mac OS clients, +configure each printer using a papserver(8) in the +/usr/adm/appletalk/services file, specifying the +corresponding PPD file in the /etc/cups/ppd directory for +each printer. For a printer named MyPrinter the entry +would look like: + +

    +/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/MyPrinter.ppd \
    +"Printer Description" MyPrinter
    +
+ +
+ + + +
+NOTE: + +

Enter the text above on a single line without the backslash (\) +character. +

+ +

NetATalk

+ +

To use your system as a print server for Mac OS clients, +configure each printer in the papd.conf file, specifying the +corresponding PPD file in the /etc/cups/ppd directory for +each printer. For a printer named MyPrinter the entry +would look like: + +

    +Printer Description:MyPrinter@MyServer:\
    +:pr=|/usr/bin/lp -d MyPrinter:\
    +:op=daemon:\
    +:pd=/etc/cups/ppd/MyPrinter.ppd:
    +
+ + + +

Printing to Mac OS Servers

+ +

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 /usr/lib/cups/backend directory that sends a print file +using the appropriate command. The following is a short script that will +run the papif command provided with CAP. + +

After copying this script to /usr/lib/cups/backend/cap, +specify a device URI of cap://server/printer to use this +backend with a print queue. + + +

    +
    +"/usr/lib/cups/backend/cap"
    +#!/bin/sh
    +#
    +# Usage: cap job user title copies options [filename]
    +#
    +
    +# No arguments means show available devices...
    +
    +if test ${#argv} = 0; then
    +echo "network cap \"Unknown\" \"Mac OS Printer via CAP\""
    +exit 0
    +fi
    +
    +# Collect arguments...
    +
    +user=$2
    +copies=$4
    +
    +if test ${#argv} = 5; then
    +# Get print file from stdin; copies have already been handled...
    +file=/var/tmp/$$.prn
    +copies=1
    +cat > $file
    +else
    +# Print file is on command-line...
    +file=$6
    +fi
    +
    +# Create a dummy cap.printers file for this printer based
    +# upon a device URI of "cap://server/printer"...
    +
    +echo $PRINTER/$DEVICE_URI | \
    +awk -F/ '{print $1 "=" $5 ":LaserWriter@" $4}' > /var/tmp/$$.cap
    +
    +CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
    +
    +# Send the file to the printer, once for each copy. This assumes that you
    +# have properly initialized the cap.printers file...
    +
    +while [ $copies -gt 0 ]; do
    +papif -n $user < $file
    +
    +copies=`expr $copies - 1`
    +done
    +
    +# Remove any temporary files...
    +if test ${#argv} = 5; then
    +/bin/rm -f $file
    +fi
    +
    +/bin/rm -f /var/tmp/$$.cap
    +
    +exit 0
    +
+ + +

Printing from Windows Clients

+ +

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: + +

+ +

To configure SAMBA for CUPS, edit the smb.conf file and +replace the existing printing commands and options with the line: + +

    +printing = cups
    +printcap name = cups
    +
+ +

That's all there is to it! Remote users will now be able to browse and +print to printers on your system. + +

Exporting Printer Drivers

+ +

You can optionally export printer drivers from your CUPS +server using the cupsaddsmb command and the SAMBA +2.2.0 or higher software. + +

Before you can export the printers you must download the +current Adobe PostScript printer drivers from the Adobe web +site (http://www.adobe.com/). +Use the free unzip software to extract the files +from the self-extracting ZIP file containing the drivers; you +will need the following files: + +

    +ADFONTS.MFM
    +ADOBEPS4.DRV
    +ADOBEPS4.HLP
    +ADOBEPS5.DLL
    +ADOBEPSU.DLL
    +ADOBEPSU.HLP
    +DEFPRTR2.PPD
    +ICONLIB.DLL
    +PSMON.DLL
    +
+ +

Copy these files to the /usr/share/cups/drivers +directory - you may need to rename some of the files so the +filenames are all UPPERCASE. + +

Next, configure SAMBA (via the smb.conf file) to support printing +through CUPS and provide a printer driver download share, as follows: + +

    +[global]
    +load printers = yes
    +printing = cups
    +printcap name = cups
    +
    +[printers]
    +comment = All Printers
    +path = /var/spool/samba
    +browseable = no
    +public = yes
    +guest ok = yes
    +writable = no
    +printable = yes
    +printer admin = root
    +
    +[print$]
    +comment = Printer Drivers
    +path = /etc/samba/drivers
    +browseable = yes
    +guest ok = no
    +read only = yes
    +write list = root
    +
+ +

This configuration assumes a FHS-compliant installation of SAMBA; +adjust the [printers] and [print$] share paths accordingly on your system as needed. +That is, the directory for your printer drivers can be anywhere on the +system; just make sure it is writable by the users specified by +the write list directive plus readable and executable by all users. +Also, make sure that you have SAMBA passwords defined for each user in the +write list using SAMBA's smbpasswd(1) command. +Otherwise you will not be able to authenticate. + +

Finally, run the cupsaddsmb command to export +the printer drivers for one or more queues: + +

    +cupsaddsmb -U root printer1 ... printerN ENTER
    +
+ + +

Running cupsaddsmb with the -a option +will export all printers: + +

    +cupsaddsmb -U root -a ENTER
    +
+ +

Notice in the above examples that the user root was used +which was defined in the write list of the smb.conf file. + +

Printing to Windows Servers

+ +

CUPS can print to Windows servers in one of two ways. The first way uses +the LPD protocol on the CUPS system and the "TCP/IP Printing Services" on +the Windows system. You can find out more about this configuration in the +LPD section earlier in this chapter. + +

The second way is through the Microsoft Server Message Block ("SMB") +protocol. Support for this protocol is provided with the free SAMBA +software package. You can download SAMBA from: + +

+ +

To configure CUPS for SAMBA, run the following command: + +

    +ln -s `which smbspool` /usr/lib/cups/backend/smb ENTER
    +
+ +

The smbspool(1) 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: + +

    +smb://workgroup/server/sharename
    +smb://server/sharename
    +smb://user:pass@workgroup/server/sharename
    +smb://user:pass@server/sharename
    +
+ +

The workgroup name need only be specified if your +system is using a different workgroup. The user:pass +strings are required when printing to Windows NT servers or to shares +with passwords enabled under Windows 95 and 98. + + +

A - Software License Agreement

+ + + + +

B - Common Network Settings

+ +

This appendix covers many of the popular TCP/IP network interfaces +and printer servers available on the market today. + +

Configuring a Network Interface

+ +

When you first install a network printer or print server on your +LAN, you need to set the Internet Protocol ("IP") address. On most +higher-end "workgroup" 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. + +

To setup your printer or print server for remote address assignment, +you'll need the Ethernet Media Access Control ("MAC") 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. + + +

Configuring the IP Address Using ARP

+ +

The easiest way to set the IP address of a network device is to use +the arp(8) command. The arp sends an Address +Resolution Protocol ("ARP") packet to the specified Ethernet MAC address, +setting the network device's IP address: + +

    +arp -s ip-address ethernet-address ENTER
    +arp -s host.domain.com 08:00:69:00:12:34 ENTER
    +arp -s 192.0.2.2 08:00:69:00:12:34 ENTER
    +
+ +

Configuring the IP Address Using RARP

+ +

The most flexible way to remotely assign IP addresses under UNIX +is through the Reverse Address Resolution Protocol ("RARP"). 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. + +

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 arp command is the way to go. + +

Some UNIX operating systems use a program called +rarpd(8) to manage RARP. Others, like Linux, support this +protocol in the kernel. For systems that provide the rarpd +program you will need to start it before RARP lookups will work: + +

    +rarpd ENTER
    +
+ +

Under IRIX you can enable this functionality by default using: + +

    +chkconfig rarpd on ENTER
    +
+ +

Both the rarpd program and kernel RARP support read a +list of Ethernet and IP addresses from the file /etc/ethers. +Each line contains the Ethernet address (colon delimited) followed by +an IP address or hostname like: + +

    +08:00:69:00:12:34 myprinter.mydomain.com
    +08:00:69:00:12:34 192.0.2.2
    +
+ +

Add a line to this file and cycle the power on the printer or print +server to set its address. + + +

Configuring the IP Address Using BOOTP

+ +

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 bootpd(8) program supplied with UNIX you simply need to +add a line to the /etc/bootptab file; for IRIX: + +

    +myprinter 08:00:69:00:12:34 192.0.2.2 myprinter.boot
    +
+ + +

Newer versions of bootpd use a different format: + +

    +myprinter:ha=080069001234:ip=192.0.2.2:t144=myprinter.boot
    +
+ +

The myprinter.boot file resides in the /usr/local/boot +directory by default. If you do not need to provide a boot file you may leave +the last part of the line blank.

+ + +
+ + + +
+NOTE: + +

Some versions of UNIX do not enable the BOOTP service by +default. The /etc/inetd.conf usually contains a +line for the BOOTP service that can be uncommented if +needed. +

+ +

Verifying the Printer Connection

+ +

To test that the IP address has been successfully assigned and that the +printer is properly connected to your LAN, type: + +

    +ping ip-address ENTER
    +
+ +

If the connection is working properly you will see something like: + +

    +ping myprinter ENTER
    +PING myprinter (192.0.2.2): 56 data bytes
    +64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
    +64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
    +64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
    +
+ +

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. + + +

Common Network Interface Settings

+ +

Once you have set the IP address you can access the printer or print +server using the ipp, lpd, or +socket backends. The following is a list of common network +interfaces and printer servers and the settings you should use with +CUPS: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Model/ManufacturerDevice URI(s)
Apple LaserWriterlpd://address/PASSTHRU
Axis w/o IPP
+(see directions)
socket://address:9100
+socket://address:9101
+socket://address:9102
Axis w/IPPipp://address/LPT1
+ipp://address/LPT2
+ipp://address/COM1
Castelle LANpressTMlpd://address/pr1
+lpd://address/pr2
+lpd://address/pr3
DPI NETPrintlpd://address/pr1
+lpd://address/pr2
+lpd://address/pr3
EFI® Fiery® RIPlpd://address/print
EPSON® Multiprotocol Ethernet Interface Boardsocket://address
Extended System ExtendNETlpd://address/pr1
+lpd://address/pr2
+lpd://address/pr3
Hewlett Packard JetDirect w/o IPPsocket://address:9100
+socket://address:9101
+socket://address:9102
Hewlett Packard JetDirect w/IPPipp://address/ipp
+ipp://address/ipp/port1
+ipp://address/ipp/port2
+ipp://address/ipp/port3
Intel® NetportExpress XL, PRO/100lpd://address/LPT1_PASSTHRU
+lpd://address/LPT2_PASSTHRU
+lpd://address/COM1_PASSTHRU
LexmarkTM MarkNetlpd://address/ps
Linksys EtherFast®
+(see directions)
socket://address:4010
+socket://address:4020
+socket://address:4030
Kodak®lpd://address/ps
QMS® CrownNetTMlpd://address/ps
Tektronix® PhaserShareTMsocket://address:9100
XEROX® 4512 NIClpd://address/PORT1
XEROX® XNIClpd://address/PASSTHRU
XEROX® (most others)socket://address:5503
+ +

Configuring Axis Print Servers

+ +

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. + + +

Each print server contains a configuration file named +config 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 ftp(1) program: + +

    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> get config ENTER
    +local: config remote: config
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2),
    +(mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ + +

Next, edit the file with your favorite text editor and locate the +lines beginning with: + +

    +RTN_OPT.     : YES
    +RTEL_PR1.    : 0
    +RTEL_PR2.    : 0
    +RTEL_PR3.    : 0
    +RTEL_PR4.    : 0
    +RTEL_PR5.    : 0
    +RTEL_PR6.    : 0
    +RTEL_PR7.    : 0
    +RTEL_PR8.    : 0
    +
+ + +Change the RTN_OPT line to read: + +
    +RTN_OPT.     : NO
    +
+ + +

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: + +

    +RTEL_PR1.    : 9100
    +RTEL_PR2.    : 9101
    +RTEL_PR3.    : 9102
    +RTEL_PR4.    : 9103
    +RTEL_PR5.    : 9104
    +RTEL_PR6.    : 9105
    +RTEL_PR7.    : 9106
    +RTEL_PR8.    : 9107
    +
+ + +

This essentially makes the Axis print server look like a Hewlett +Packard JetDirect EX print server. Save the file and then upload the +new config file using the ftp command: + +

    +ftp ip-address ENTER
    +Connected to ip-address.
    +220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
    +ftp> user root ENTER
    +331 User name ok, need password
    +Password: pass ENTER (this is not echoed)
    +230 User logged in
    +ftp> put config CONFIG ENTER
    +local: config remote: CONFIG
    +200 PORT command successful.
    +150 Opening data connection for config (192,0,2,2), (mode ascii).
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> get hardreset ENTER
    +local: hardreset remote: hardreset
    +200 PORT command successful.
    +421 Axis NPS ### hard reset, closing connection.
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ +

Your Axis print server is now ready for use! + +

Configuring Linksys Print Servers

+ +

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. + + +

Each print server contains a configuration file named +CONFIG 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 ftp(1) program: + +

    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> get CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +WARNING! 68 bare linefeeds received in ASCII mode
    +File may not have transferred correctly.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ + +

Next, edit the file with your favorite text editor and locate the +lines beginning with: + +

    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P1
    +0140 L3_PROUT:P1
    +
+ +

Change the port number for +each parallel and serial port on the server as follows: + +

    +0100 L1_PROUT:P1
    +0120 L2_PROUT:P2
    +0140 L3_PROUT:P3
    +
+ + +

This maps each virtual printer with a physical port. Save the file and then upload the +new CONFIG file using the ftp command: + +

    +ftp -n ip-address ENTER
    +Connected to ip-address.
    +220 Print Server Ready.
    +Remote system type is Print.
    +ftp> put CONFIG ENTER
    +local: CONFIG remote: CONFIG
    +200 Command OK.
    +150 Open ASCII Mode Connection.
    +226 Transfer complete.
    +##### bytes received in #.## seconds (##### Kbytes/s)
    +ftp> quit ENTER
    +221 Goodbye.
    +
+ +

Your Linksys print server is now ready for use! + + +

C - Printer Drivers

+ +

This appendix lists the printer drivers that are provided with CUPS. + +

Printer Drivers

+ +

CUPS includes the following printer drivers: + +

+ +

EPSON 9-pin Dot Matrix

+ +

The EPSON 9-pin Dot Matrix driver (epson9.ppd) supports +9-pin dot matrix printers that implement the ESC/P command set. It +provides 60x72, 120x72, and 240x72 DPI output in black only. + +

EPSON 24-pin Dot Matrix

+ +

The EPSON 24-pin Dot Matrix driver (epson9.ppd) 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. + +

EPSON Stylus Color

+ +

The EPSON Stylus Color driver (stcolor.ppd) 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). + +

EPSON Stylus Photo

+ +

The EPSON Stylus Photo driver (stphoto.ppd) 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). + +

HP DeskJet

+ +

The HP DeskJet driver (deskjet.ppd) supports HP DeskJet +printers that implement the PCL command set. It provides 150, 300, and +600 DPI output in black and color (CMYK). + +

The DeskJet printers that implement the HP-PPA command set (720C, +722C, 820C, and 1100C) are not supported due to a complete lack +of documentation and support from Hewlett Packard. + +

The duplexer provided with the HP DeskJet 900 series printers is also +not supported for similar reasons. + +

HP LaserJet

+ +

The HP LaserJet driver (laserjet.ppd) 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. + +

LaserJet printers that do not implement PCL (3100, 3150) are not +supported due to a complete lack of documentation and support from +Hewlett Packard. + + +

D - List of Files

+ +

This appendix lists the files and directories that are installed for +the Common UNIX Printing System. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathnameDescription
/etc/cups/certs/The location of authentication certificate files for local +HTTP clients.
/etc/cups/classes.confThe printer classes configuration file for the scheduler.
/etc/cups/cupsd.confThe scheduler configuration file.
/etc/cups/interfaces/The location of System V interface scripts for printers.
/etc/cups/mime.convsThe list of standard file filters included with CUPS.
/etc/cups/mime.typesThe list of recognized file types for CUPS.
/etc/cups/ppd/The location of PostScript Printer Description ("PPD") files for +printers.
/etc/cups/printers.confThe printer configuration file for the scheduler.
/usr/bin/cancelThe System V cancel job(s) command.
/usr/bin/disableThe System V disable printer command.
/usr/bin/enableThe System V enable printer command.
/usr/bin/lpThe System V print command.
/usr/bin/lpoptionsSets user-defined printing options and defaults.
/usr/bin/lppasswdAdds, changes, or removes Digest password accounts.
/usr/bin/lpqThe Berkeley status command.
/usr/bin/lprThe Berkeley print command.
/usr/bin/lprmThe Berkeley cancel job(s) command.
/usr/bin/lpstatThe System V status command.
/usr/include/cups/CUPS API header files.
/usr/lib32/libcups.a
+/usr/lib32/libcupsimage.a
Static libraries (IRIX 6.5)
/usr/lib/libcups.a
+/usr/lib/libcupsimage.a
Static libraries (all others)
/usr/lib/libcups.sl.2
+/usr/lib/libcupsimage.sl.2
Shared libraries (HP-UX)
/usr/lib32/libcups.so.2
+/usr/lib32/libcupsimage.so.2
Shared libraries (IRIX 6.5)
/usr/lib/libcups.so.2
+/usr/lib/libcupsimage.so.2
Shared libraries (all others)
/usr/lib/cups/backend/Backends for various types of printer connections.
/usr/lib/cups/cgi-bin/CGI programs for the scheduler.
/usr/lib/cups/daemon/Daemons for polling and LPD support.
/usr/lib/cups/filter/Filters for various types of files.
/usr/lib/locale/The location of language-specific message files. (System V)
/usr/lib/nls/msg/The location of language-specific message files. (Compaq Tru64 UNIX)
/usr/share/locale/The location of language-specific message files. (Linux, *BSD)
/usr/sbin/acceptThe accept-jobs command.
/usr/sbin/cupsdThe CUPS print scheduler.
/usr/sbin/lpadminThe System V printer administration tool.
/usr/sbin/lpcThe Berkeley printer administration tool.
/usr/sbin/lpinfoThe get-devices and get-ppds command.
/usr/sbin/lpmoveThe move-jobs command.
/usr/sbin/rejectThe reject-jobs command.
/usr/share/catman/a_man/
+/usr/share/catman/u_man/
Man pages (IRIX)
/usr/share/man/Man pages (Compaq Tru64 UNIX, HP-UX, Solaris)
/usr/man/Man pages (all others)
/usr/share/cups/data/The location of filter data files.
/usr/share/cups/data/testprint.psThe PostScript test page file.
/usr/share/cups/fonts/The location of PostScript fonts for the PostScript RIP.
/usr/share/cups/model/The location of PostScript Printer Description ("PPD") files and +interface scripts that may be used to setup a printer queue.
/usr/share/cups/pstoraster/Other PostScript RIP initialization files.
/usr/share/cups/pstoraster/FontmapThe font mapping file (converts filenames to fontnames)
/usr/share/cups/templates/The location of HTML template files for the web interfaces.
/usr/share/doc/cups/Documentation and web page data for the scheduler.
/var/log/cups/The location of scheduler log files.
/var/spool/cups/The location of print files waiting to be printed.
+ + +

E - Troubleshooting Common Problems

+ +

This appendix covers some of the common problems first-time users +encounter when installing and configuring CUPS. + +

Commercial support for CUPS is available from Easy Software Products. +For more information please contact us at: + +

+ +

My Applications Don't See the Available Printers

+ +

Many applications read the /etc/printcap file to +get a list of available printers. + +

The default CUPS configuration creates the +/etc/printcap file automatically. To enable or +disable automatic creation and updating of this file, use the Printcap directive described +in Chapter 6, "Printing System +Management". + +

CUPS Doesn't Recognize My Username or Password!

+ +

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 root username and +the corresponding password to authenticate the request. + +

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 root account then you won't be +able to add printers remotely or via the web interface! + + +

To disable password authentication you need to edit the +/etc/cups/cupsd.conf file and comment out the +lines reading: + +

    +AuthType Basic
    +AuthClass System
    +
+ +

for the /admin location. Then restart the CUPS server as +described in Chapter 6, "Printing System +Management".

+ +
+ + + +
+NOTE: + +

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. +

+ +

I Can't Do Administration Tasks from Another Machine!

+ +

The default CUPS configuration limits administration to the local +machine. To open up access, edit the /etc/cups/cupsd.conf +and comment out the lines reading: + +

    +Order deny,allow
    +Deny from all
    +Allow from 127.0.0.1
    +
+ +

for the /admin location. Then restart the CUPS server as +described in Chapter 6, "Printing System +Management".

+ +
+ + + +
+NOTE: + +

Allowing administration access from all hosts is a potential +security risk. Please read Chapter +6, "Printing System Management" for a description of these +risks and ways to minimize them. +

+ + +

I Can't Do Administration Tasks from My Web Browser!

+ +

This problem is usually caused by: + +

    + +
  1. not specifying the correct password for the +root account. + +
  2. 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 "I Can't Do +Administration Tasks from Another Machine!" section earlier +in this appendix. + +
  3. not setting a password on the root account. CUPS will not +authenticate a user account that does not have a password for +security reasons. + +
  4. authenticating using an account other than root, but the +account you are using is not a member of the system group. + +
  5. configuring CUPS to use Digest authentication, but +your web browser does not support Digest authentication. + +
+ +

Connection Refused Messages

+ +

Under normal circumstances, "connection refused" 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. + +

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. + +

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. + +

Write Error Messages

+ +

If you get "write error" 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. + +

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. + + +

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: + +

    +telnet ip-address ENTER
    +
    +Trying ip-address...
    +Connected to ip-address.
    +Escape character is `^]'.
    +
    +Please type [Return] two times, to initialize telnet configuration
    +For HELP type "?"
    +> idle-timeout: 180 ENTER
    +> quit ENTER
    +
+ + + + diff --git a/doc/sdd.html b/doc/sdd.html new file mode 100644 index 0000000000..e151d9a626 --- /dev/null +++ b/doc/sdd.html @@ -0,0 +1,596 @@ + + + +CUPS Software Design Description + + + + + + + +

+

CUPS Software Design Description


+CUPS-SDD-1.1
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Design Overview + +A Glossary + +
+

1 Scope

+

1.1 Identification

+ This software design description document provides general information + on the architecture and coding of the Common UNIX Printing System + ("CUPS") Version 1.1. +

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+

1.3 Document Overview

+ This software design description document is organized into the + following sections: +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Design Overview
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+

The following CUPS documentation is referenced by this document:

+
    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.1: CUPS Software Security Report
  • +
  • CUPS-STP-1.1: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.1: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

The following non-CUPS documents are referenced by this document:

+ +

3 Design Overview

+ CUPS is composed of 9 software sub-systems that operate together to + perform common printing tasks: +
    +
  • Backends
  • +
  • Berkeley Commands
  • +
  • CGI
  • +
  • CUPS Application Programmers Interface
  • +
  • CUPS Imaging Library
  • +
  • Daemons
  • +
  • Filters
  • +
  • Scheduler
  • +
  • System V Commands
  • +
+

3.1 Backends

+ The backends implement communications over a number of different + interfaces. All backends are called with a common set of arguments: +
    +
  • Device URI - the Uniform Resource Identifier for the output device + (e.g. parallel:/dev/plp, ipp://hostname/resource +).
  • +
  • Job Identifier - the job identifier for this job (integer).
  • +
  • User Name - the user associated with this job (name string).
  • +
  • Title - the title/job-name associated with this job (name string).
  • +
  • Copies - the number of copies required (integer).
  • +
  • Options - the options associated with this job (space separated + option strings).
  • +
  • Filename (optional) - the file to print; if this option is not + specified, the backend must read the print file from the standard + input.
  • +
+

Backends are named using the scheme of the URI, so a URI of + "ipp://hostname/resource" would be processed by the "ipp" backend.

+

3.1.1 ipp

+

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 +printer-uri-supported attribute from the printer or host.

+

3.1.2 lpd

+

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:

+
    +
    lpd://hostname/queue
    +
    +
+

3.1.3 parallel

+

The parallel backend sends the specified job to a local printer + connected via the specified parallel port device. The URI is of the + form:

+
    +
    parallel:/dev/file
    +
    +
+

3.1.4 serial

+

The serial backend sends the specified job to a local printer + connected via the specified serial port device. The URI is of the form:

+
    +
    serial:/dev/file?option[+option+...]
    +
    +
+ The options can be any combination of the following: +
    +
  • baud=rate - Sets the baud rate for the device.
  • +
  • bits=7 or 8 - Sets the number of data bits.
  • +
  • parity=even - Sets even parity checking.
  • +
  • parity=odd - Sets odd parity checking.
  • +
  • parity=none - Turns parity checking off.
  • +
  • flow=dtrdsr - Turns DTR/DSR (hardware) flow + control on.
  • +
  • flow=hard - Turns RTS/CTS (hardware) flow + control on.
  • +
  • flow=none - Turns flow control off.
  • +
  • flow=rtscts - Turns RTS/CTS (hardware) flow + control on.
  • +
  • flow=xonxoff - Turns XON/XOFF (software) flow + control on.
  • +
+

3.1.5 socket

+

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:

+
    +
    socket://hostname[:port]
    +
    +
+ The default port number is 9100. +

3.1.6 usb

+

The usb backend sends the specified job to a local printer connected + via the specified usb port device. The URI is of the form:

+
    +
    usb:/dev/file
    +
    +
+

3.2 Berkeley Commands

+

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.

+

3.2.1 lpc

+ The lpc command allows users and administrators to check the status and + control print queues. The version provided with CUPS supports the + following commands: +
    +
  • quit - Quits the lpc command.
  • +
  • status - Shows the status of printers and jobs in the queue.
  • +
+

3.2.2 lpq

+

The lpq command shows the current queue status.

+

3.2.3 lpr

+

The lpr command submits a job for printing. The CUPS version of lpr + silently ignores the "i", "t", "m", "h", and "s" options.

+

3.2.4 lprm

+

The lprm removes one or more print jobs.

+

3.3 CGI

+

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.

+

3.3.1 admin.cgi

+

The admin CGI provides administration interfaces for printers and + classes. The user can add, modify, delete, start, stop, and configure + printers and classes using "wizard" interfaces.

+

3.3.2 classes.cgi

+

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.

+

3.3.3 jobs.cgi

+

The jobs CGI lists the queued print jobs in order of priority. The + list can be limited by printer or job.

+

3.3.4 printers.cgi

+

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.

+

3.4 CUPS Application Programmers Interface

+

The CUPS Application Programmers Interface ("API") provides common + convenience, HTTP, IPP, language, and PPD functions used by the CUPS + software.

+

3.4.1 Convenience Functions

+

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.

+

3.4.2 HTTP Functions

+

The HTTP functions provide functions to connect to HTTP servers, + issue requests, read data from a server, and write data to a server.

+

3.4.3 IPP Functions

+

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.

+

3.4.4 Language Functions

+

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.)

+

3.4.5 PPD Functions

+

The PostScript Printer Description functions manage PPD files, select + options, check for option conflicts, and emit selected options in the + correct order.

+

3.5 CUPS Imaging Library

+

The CUPS imaging library provides colorspace conversion, color + management, image management, scaling, image file, and raster functions + used by the CUPS raster filters.

+

3.5.1 Colorspace Conversion Functions

+

The colorspace conversion functions handle conversion of grayscale + and RGB colors to grayscale, RGB, K, CMY, CMYK, and CMYKcm colorspaces.

+

3.5.2 Color Management Functions

+

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.

+

3.5.3 Image Management Functions

+

The image management functions manage a tiled image database that is + swapped to/from disk as needed.

+

3.5.4 Scaling Functions

+

The scaling functions provide image scaling services using + nearest-neighbor sampling and bilinear interpolation as appropriate.

+

3.5.5 Image File Functions

+

The image file functions handle loading of all image file formats.

+

3.5.6 Raster Functions

+

The raster functions manage streams of CUPS raster data (described in + the Interface Design Document) used by non-PostScript printer drivers + and raster filters.

+

3.6 Daemons

+

The daemons provide additional network functions for the scheduler. + Currently only two daemons are provided with CUPS.

+

3.6.1 Line Printer Daemon

+

The line printer daemon provides remote LPD client support and is run + by the inetd(8) daemon as needed.

+

3.6.2 Polling Daemon

+

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.

+

3.7 Filters

+

The filters implement file conversion services for CUPS. All filters + are called with a common set of arguments:

+
    +
  • Printer name - the name of the destination printer (name string).
  • +
  • Job Identifier - the job identifier for this job (integer).
  • +
  • User Name - the user associated with this job (name string).
  • +
  • Title - the title/job-name associated with this job (name string).
  • +
  • Copies - the number of copies required (integer).
  • +
  • Options - the options associated with this job (space separated + option strings).
  • +
  • Filename (optional) - the file to print; if this option is not + specified, the filter must read the input file from the standard input.
  • +
+

Filters are added to the MIME conversion data file and implement all + necessary conversions from one file type to another.

+

3.7.1 hpgltops

+

The hpgltops filter converts HP-GL/2 files into PostScript.

+

3.7.2 imagetops

+

The imagetops filter converts image files into PostScript.

+

3.7.3 imagetoraster

+

The imagetoraster filter converts image files into CUPS raster data.

+

3.7.4 pdftops

+

The pdftops filter converts PDF files into PostScript.

+

3.7.5 pstops

+

The pstops filter inserts printer-specific commands from PPD files + and performs page filtering as requested by the user.

+

3.7.6 pstoraster

+

The pstoraster filter converts PostScript program data into CUPS + raster data.

+

3.7.7 rastertoepson

+

The rastertoepson filter handles converting CUPS raster data to ESC/P + and supports both color and black-and-white printers.

+

3.7.8 rastertohp

+

The rastertohp filter handles converting CUPS raster data to HP-PCL + and supports both color and black-and-white printers.

+

3.7.9 texttops

+

The texttops filter converts text files into PostScript.

+

3.8 Scheduler

+

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.

+

3.8.1 Authorization

+

The authorization module is responsible for performing access control + and authentication for all HTTP and IPP requests entering the system.

+

3.8.2 Classes

+

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.

+

3.8.3 Client

+

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.

+

Once authorized, all IPP requests are sent to the IPP module.

+

3.8.4 Configuration

+

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.

+

3.8.5 Devices

+

The devices module is responsible for managing the list of available + devices for the CUPS-Get-Devices operation.

+

3.8.6 Directory Services

+

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.

+

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.

+

3.8.7 IPP

+

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.

+

3.8.8 Jobs

+

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.

+

3.8.9 Logging

+

The logging module manages the access, error, and page log files that + are generated by the scheduler.

+

3.8.10 Main

+

The main module is responsible for timing out and dispatching input + and output for client connections. It also watches for incoming +SIGHUP and SIGCHLD signals, reloads the server + configuration files as needed, and handles child process errors and + exits.

+

3.8.11 MIME

+

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.

+

3.8.12 PPDs

+

The PPDs module is responsible for managing the list of available PPD + files for the CUPS-Get-PPDs operation.

+

3.8.13 Printers

+

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.

+

3.9 System V Commands

+

The System V commands provide a robust command-line interface to CUPS + to submit and control printers and jobs.

+

3.9.1 accept

+

The accept command tells the scheduler to accept new jobs for + specific printers.

+

3.9.2 cancel

+

The cancel command tells the scheduler to cancel one or more jobs + that are queued for printing.

+

3.9.3 disable

+

The disable command tells the scheduler to stop printing jobs on the + specified printers.

+

3.9.4 enable

+

The enable command tells the scheduler to start printing jobs on the + specified printers.

+

3.9.5 lp

+

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 "f", + "H", "P", "S", and "y" options are silently ignored.

+

3.9.6 lpadmin

+

The lpadmin command manages printer queues and classes. The Solaris + "A", "F", "I", "M", "P", "Q", "S", "T", "U", "W", "f", "l", "m", "o", + "s", "t", and "u" options are not supported, and new options "P" (PPD + file) and "E" (enable and accept) are provided to configure + CUPS-specific features.

+

3.9.7 lpinfo

+

The lpinfo command lists the available PPD files or devices as + selected by the user.

+

3.9.8 lpmove

+

The lpmove command moves a print job to a new destination.

+

3.9.9 lpoptions

+

The lpoptions command manages user-defined printers and options.

+

3.9.10 lpstat

+

The lpstat command lists printers, classes, and jobs as requested by + the user.

+

3.9.11 reject

+

The reject command tells the scheduler not to accept new jobs for + specific printers.

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Page Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/sdd.pdf b/doc/sdd.pdf new file mode 100644 index 0000000000000000000000000000000000000000..40e89e78fa94661875cff4b2ba825165a131fc74 GIT binary patch literal 64258 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 + + + + + CUPS Software Design Description + + + +

Scope

+ +

Identification

+ +This software design description document provides general information +on the architecture and coding of the Common UNIX Printing System +("CUPS") Version 1.1. + + + +

Document Overview

+ +This software design description document is organized into the +following sections: + +
    + +
  • 1 - Scope + +
  • 2 - References + +
  • 3 - Design Overview + +
  • A - Glossary + +
+ + + +

Design Overview

+ +CUPS is composed of 9 software sub-systems that operate together to +perform common printing tasks: + +
    + +
  • Backends + +
  • Berkeley Commands + +
  • CGI + +
  • CUPS Application Programmers Interface + +
  • CUPS Imaging Library + +
  • Daemons + +
  • Filters + +
  • Scheduler + +
  • System V Commands + +
+ +

Backends

+ +The backends implement communications over a number of different interfaces. +All backends are called with a common set of arguments: + +
    + +
  • Device URI - the Uniform Resource Identifier for the output device + (e.g. parallel:/dev/plp, + ipp://hostname/resource). + +
  • Job Identifier - the job identifier for this job (integer). + +
  • User Name - the user associated with this job (name string). + +
  • Title - the title/job-name associated with this job (name string). + +
  • Copies - the number of copies required (integer). + +
  • Options - the options associated with this job (space separated + option strings). + +
  • Filename (optional) - the file to print; if this option is not + specified, the backend must read the print file from the standard + input. + +
+ +

Backends are named using the scheme of the URI, so a URI of +"ipp://hostname/resource" would be processed by the "ipp" backend. + +

ipp

+ +

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 +printer-uri-supported attribute from the printer or host. + +

lpd

+ +

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: + +

    lpd://hostname/queue
    +
+ +

parallel

+ +

The parallel backend sends the specified job to a local printer connected +via the specified parallel port device. The URI is of the form: + +

    parallel:/dev/file
    +
+ +

serial

+ +

The serial backend sends the specified job to a local printer connected +via the specified serial port device. The URI is of the form: + +

    serial:/dev/file?option[+option+...]
    +
+ +The options can be any combination of the following: + +
    + +
  • baud=rate - Sets the baud rate for the device. + +
  • bits=7 or 8 - Sets the number of data bits. + +
  • parity=even - Sets even parity checking. + +
  • parity=odd - Sets odd parity checking. + +
  • parity=none - Turns parity checking off. + +
  • flow=dtrdsr - Turns DTR/DSR (hardware) flow + control on. + +
  • flow=hard - Turns RTS/CTS + (hardware) flow control on. + +
  • flow=none - Turns flow control off. + +
  • flow=rtscts - Turns RTS/CTS + (hardware) flow control on. + +
  • flow=xonxoff - Turns XON/XOFF + (software) flow control on. + +
+ +

socket

+ +

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: + +

    socket://hostname[:port]
    +
+ +The default port number is 9100. + +

usb

+ +

The usb backend sends the specified job to a local printer connected +via the specified usb port device. The URI is of the form: + +

    usb:/dev/file
    +
+ +

Berkeley Commands

+ +

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. + +

lpc

+ +The lpc command allows users and administrators to check the status and +control print queues. The version provided with CUPS supports the following +commands: + +
    + +
  • quit - Quits the lpc command. + +
  • status - Shows the status of printers and jobs in the queue. + +
+ +

lpq

+ +

The lpq command shows the current queue status. + +

lpr

+ +

The lpr command submits a job for printing. The CUPS version of lpr silently +ignores the "i", "t", "m", "h", and "s" options. + +

lprm

+ +

The lprm removes one or more print jobs. + +

CGI

+ +

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. + +

admin.cgi

+ +

The admin CGI provides administration interfaces for printers and +classes. The user can add, modify, delete, start, stop, and configure +printers and classes using "wizard" interfaces. + +

classes.cgi

+ +

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. + +

jobs.cgi

+ +

The jobs CGI lists the queued print jobs in order of priority. The +list can be limited by printer or job. + +

printers.cgi

+ +

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. + +

CUPS Application Programmers Interface

+ +

The CUPS Application Programmers Interface ("API") provides common +convenience, HTTP, IPP, language, and PPD functions used by the CUPS +software. + +

Convenience Functions

+ +

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. + +

HTTP Functions

+ +

The HTTP functions provide functions to connect to HTTP servers, +issue requests, read data from a server, and write data to a server. + +

IPP Functions

+ +

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. + +

Language Functions

+ +

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.) + +

PPD Functions

+ +

The PostScript Printer Description functions manage PPD files, +select options, check for option conflicts, and emit selected options +in the correct order. + +

CUPS Imaging Library

+ +

The CUPS imaging library provides colorspace conversion, color +management, image management, scaling, image file, and raster functions +used by the CUPS raster filters. + +

Colorspace Conversion Functions

+ +

The colorspace conversion functions handle conversion of grayscale +and RGB colors to grayscale, RGB, K, CMY, CMYK, and CMYKcm colorspaces. + +

Color Management Functions

+ +

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. + +

Image Management Functions

+ +

The image management functions manage a tiled image database that is +swapped to/from disk as needed. + +

Scaling Functions

+ +

The scaling functions provide image scaling services using +nearest-neighbor sampling and bilinear interpolation as appropriate. + +

Image File Functions

+ +

The image file functions handle loading of all image file formats. + +

Raster Functions

+ +

The raster functions manage streams of CUPS raster data (described +in the Interface Design Document) used by non-PostScript printer +drivers and raster filters. + +

Daemons

+ +

The daemons provide additional network functions for the scheduler. +Currently only two daemons are provided with CUPS. + +

Line Printer Daemon

+ +

The line printer daemon provides remote LPD client support and is +run by the inetd(8) daemon as needed. + +

Polling Daemon

+ +

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. + +

Filters

+ +

The filters implement file conversion services for CUPS. All filters +are called with a common set of arguments: + +

    + +
  • Printer name - the name of the destination printer (name string). + +
  • Job Identifier - the job identifier for this job (integer). + +
  • User Name - the user associated with this job (name string). + +
  • Title - the title/job-name associated with this job (name string). + +
  • Copies - the number of copies required (integer). + +
  • Options - the options associated with this job (space separated + option strings). + +
  • Filename (optional) - the file to print; if this option is not + specified, the filter must read the input file from the standard + input. + +
+ +

Filters are added to the MIME conversion data file and implement all +necessary conversions from one file type to another. + +

hpgltops

+ +

The hpgltops filter converts HP-GL/2 files into PostScript. + +

imagetops

+ +

The imagetops filter converts image files into PostScript. + +

imagetoraster

+ +

The imagetoraster filter converts image files into CUPS raster data. + +

pdftops

+ +

The pdftops filter converts PDF files into PostScript. + +

pstops

+ +

The pstops filter inserts printer-specific commands from PPD files and +performs page filtering as requested by the user. + +

pstoraster

+ +

The pstoraster filter converts PostScript program data into CUPS +raster data. + +

rastertoepson

+ +

The rastertoepson filter handles converting CUPS raster data to +ESC/P and supports both color and black-and-white printers. + +

rastertohp

+ +

The rastertohp filter handles converting CUPS raster data to HP-PCL +and supports both color and black-and-white printers. + +

texttops

+ +

The texttops filter converts text files into PostScript. + +

Scheduler

+ +

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. + +

Authorization

+ +

The authorization module is responsible for performing access +control and authentication for all HTTP and IPP requests entering the +system. + +

Classes

+ +

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. + +

Client

+ +

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. + +

Once authorized, all IPP requests are sent to the IPP module. + +

Configuration

+ +

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. + +

Devices

+ +

The devices module is responsible for managing the list of available +devices for the CUPS-Get-Devices operation. + +

Directory Services

+ +

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. + +

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. + +

IPP

+ +

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. + +

Jobs

+ +

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. + +

Logging

+ +

The logging module manages the access, error, and page log files +that are generated by the scheduler. + +

Main

+ +

The main module is responsible for timing out and dispatching input +and output for client connections. It also watches for incoming +SIGHUP and SIGCHLD signals, reloads the +server configuration files as needed, and handles child process errors +and exits. + +

MIME

+ +

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. + +

PPDs

+ +

The PPDs module is responsible for managing the list of available +PPD files for the CUPS-Get-PPDs operation. + +

Printers

+ +

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. + +

System V Commands

+ +

The System V commands provide a robust command-line interface to +CUPS to submit and control printers and jobs. + +

accept

+ +

The accept command tells the scheduler to accept new jobs for specific +printers. + +

cancel

+ +

The cancel command tells the scheduler to cancel one or more jobs that are +queued for printing. + +

disable

+ +

The disable command tells the scheduler to stop printing jobs on the +specified printers. + +

enable

+ +

The enable command tells the scheduler to start printing jobs on the +specified printers. + +

lp

+ +

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 "f", "H", "P", "S", +and "y" options are silently ignored. + +

lpadmin

+ +

The lpadmin command manages printer queues and classes. The Solaris +"A", "F", "I", "M", "P", "Q", "S", "T", "U", "W", "f", "l", "m", "o", +"s", "t", and "u" options are not supported, and new options "P" (PPD +file) and "E" (enable and accept) are provided to configure +CUPS-specific features. + +

lpinfo

+ +

The lpinfo command lists the available PPD files or devices as selected +by the user. + +

lpmove

+ +

The lpmove command moves a print job to a new destination. + +

lpoptions

+ +

The lpoptions command manages user-defined printers and options. + +

lpstat

+ +

The lpstat command lists printers, classes, and jobs as requested by the +user. + +

reject

+ +

The reject command tells the scheduler not to accept new jobs for specific +printers. + + + + + diff --git a/doc/spm.html b/doc/spm.html new file mode 100644 index 0000000000..7c7c1ba154 --- /dev/null +++ b/doc/spm.html @@ -0,0 +1,8920 @@ + + + +CUPS Software Programmers Manual + + + + + + + +


+

CUPS Software Programmers Manual


+CUPS-SPM-1.1.17
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
Preface + +1 - Printing System Overview + +2 - The CUPS API + +3 - Writing Filters + +4 - Writing Printer Drivers + +5 - Writing Backends + +A - Software License Agreement + +B - Constants + +C - Structures + +D - Functions + +
+

Preface

+

This software programmers manual provides software programming + information for the Common UNIX Printing System ("CUPS") Version + 1.1.17.

+

System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+ + +

Document Overview

+

This software programmers manual is organized into the following + sections:

+ +

Notation Conventions

+

Various font and syntax conventions are used in this guide. Examples + and their meanings and uses are explained below: +

+ + + + + + + + + + + + +
Example   Description
 
lpstat +
lpstat(1)
   The names of commands; + the first mention of a command or function in a chapter is followed by + a manual page section number.
 
/var +
/usr/share/cups/data/testprint.ps
    +File and directory names.
 
Request ID is Printer-123 +   Screen output.
 
lp -d printer filename ENTER +   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are + written using the period (.) to indicate the decimal point.
+
+ + +

+

Abbreviations

+ The following abbreviations are used throughout this manual: +
    +
    +
    kb
    +
    Kilobytes, or 1024 bytes +
     
    +
    Mb
    +
    Megabytes, or 1048576 bytes +
     
    +
    Gb
    +
    Gigabytes, or 1073741824 bytes +
     
    +
    +
+

Other References

+
    +
    +
    CUPS Software Administrators Manual
    +
    An administration guide for the CUPS software. +
     
    +
    CUPS Software Users Manual
    +
    An end-user guide for using the CUPS software. +
     
    +
    +
+

1 - Printing System Overview

+

This chapter provides an overview of how the Common UNIX Printing + System works.

+

The Printing Problem

+

For years the printing problem has plagued UNIX. Unlike + Microsoft® Windows® 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.

+

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.

+

CUPS is designed to eliminate the printing problem. 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.

+

The Technology

+

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.

+

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.

+

IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP") + 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.

+

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.

+

Jobs

+

Each file or set of files that is submitted for printing is called a + job. 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.

+

Classes

+

CUPS supports collections of printers known as classes. Jobs + sent to a class are forwarded to the first available printer in the + class.

+

Filters

+

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.

+

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 ("RIP") filters that convert + PostScript or image files into bitmaps that can be sent to a raster + printer.

+

Backends

+

Backends perform the most important task of all - they send the + filtered print data to the printer.

+

CUPS provides backends for printing over parallel, serial, and USB + ports, and over the network via the IPP, JetDirect (AppSocket), and + Line Printer Daemon ("LPD") protocols. Additional backends are + available in network service packages such as the SMB backend included + with the popular SAMBA software.

+

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.

+

Printer Drivers

+

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.

+

Networking

+

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 "name@server".

+

CUPS also provides implicit classes, 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!

+

2 - The CUPS API

+

This chapter describes the CUPS Application Programmers Interface + ("API").

+

The CUPS API Library

+

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.

+

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.

+

Programs that use the CUPS API library typically will include the +<cups/cups.h> header file:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +jobid = cupsPrintFile("myprinter", "filename.ps", "title",
    +                      num_options, options);
    +
    +
+

Use the -lcups compiler option when linking to the CUPS + API library:

+
    +
    +cc -o program program.c -lcups ENTER
    +
    +
+

Additional options and libraries may be required depending on the + operating system and the location of the CUPS API library.

+

Detecting the CUPS API Library in GNU Autoconf

+

GNU autoconf is a popular configuration tool used by many programs. + Add the following lines to your configure.in file to check + for the CUPS API library in your configuration script:

+
    +
    +AC_CHECK_LIB(socket,socket,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lsocket $LIBS"
    +else
    +	echo "Not using -lsocket since you are running IRIX."
    +fi)
    +AC_CHECK_LIB(nsl,gethostbyaddr,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lnsl $LIBS"
    +else
    +	echo "Not using -lnsl since you are running IRIX."
    +fi)
    +
    +AC_CHECK_LIB(cups,httpConnect)
    +
    +
+

Printing Services

+

The CUPS API library provides some basic printing services for + applications that need to print files.

+

Include Files

+

The include file used by all of these functions is +<cups/cups.h>:

+
    +
    +#include <cups/cups.h>
    +
    +
+

Printing a File

+

The CUPS API provides two functions for printing files. The first is +cupsPrintFile which prints a single named file:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +jobid = cupsPrintFile("name", "filename", "title", 0, NULL);
    +
    +
+

The name string is the name of the printer or class to + print to. The filename string is the name of the file to + print. The title string is the name of the print job, e.g. + "Acme Word Document".

+

The return value is a unique ID number for the print job or 0 if + there was an error.

+

Printing Multiple Files

+

The second printing function is cupsPrintFiles:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int        jobid;
    +int        num_files;
    +const char *files[100];
    +...
    +
    +jobid = cupsPrintFiles("name", num_files, files, "title", 0, NULL);
    +
    +
+

Instead of passing a filename string as with cupsPrintFile() + you pass a file count (num_files) and filename pointer + array (files) for each file that you want to print.

+

As with cupsPrintFile() the return value is a unique ID + for the print job.

+

Cancelling Jobs

+

The cupsCancelJob() function cancels a queued print job:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +int status;
    +...
    +
    +status = cupsCancelJob("name", jobid);
    +
    +
+

The name string specifies the destination and is used to + determine the server to send the request to. The jobid + value is the integer returned from a previous cupsPrintFile() + or cupsPrintFiles() call.

+

cupsCancelJob() returns 1 if the job was + successfully cancelled and 0 if there was an error.

+

Getting the Available Printers and Classes

+

The cupsGetDests() function can be used to get a list of + the available printers, classes, and instances that a user has defined:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +
    +...
    +
    +num_dests = cupsGetDests(&dests);
    +
    +
+

Each destination is stored in a cups_dest_t 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:

+
    +
    +typedef struct               /**** Destination ****/
    +{
    +  char          *name,       /* Printer or class name */
    +                *instance;   /* Local instance name or NULL */
    +  int           is_default;  /* Is this printer the default? */
    +  int           num_options; /* Number of options */
    +  cups_option_t *options;    /* Options */
    +} cups_dest_t;
    +
    +
+

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 cupsGetDest() + function:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
    +
+

The name string is the printer or class name. You can + pass a value of NULL to get the default destination.

+

The instance string is the user-defined instance name. + Pass NULL to select the default instance, e.g. "name" + instead of "name/instance".

+

Printing with Options

+

All of the previous printing examples have passed 0 and +NULL for the last two arguments to the cupsPrintFile() + and cupsPrintFiles() functions. These last two arguments + are the number of options and a pointer to the option array:

+
    +
    +int cupsPrintFile(const char *name, const char *filename, const char *title,
    +                  int num_options, cups_option_t *options);
    +int cupsPrintFiles(const char *name, int num_files, const char **files,
    +                   const char *title, int num_options,
    +		   cups_option_t *options);
    +
    +
+

The cups_option_t structure holds each option and its + value. These are converted as needed and passed to the CUPS server when + printing a file.

+

The simplest way of handling options is to use the num_options + and options members of the cups_dest_t + structure described earlier:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int         jobid;
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
    +jobid  = cupsPrintFile(mydest->name, "filename", "title",
    +                       mydest->num_options, mydest->options);
    +
    +
+

This effectively uses the options a user has previous selected + without a lot of code.

+

Setting Printer Options

+

Options can also be set by your program using the +cupsAddOption() function:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int           num_options;
    +cups_option_t *options;
    +
    +...
    +
    +num_options = 0;
    +options     = NULL;
    +
    +...
    +
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +
    +
+

The name string is the name of the option, and the +value string is the value for that option.

+

Each call to cupsAddOption() 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 +cupsAddOptions() 20 times will result in 20 options.

+

Call cupsFreeOptions once you are done using the + options:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int           num_options;
    +cups_option_t *options;
    +
    +...
    +
    +cupsFreeOptions(num_options, options);
    +
    +
+

Getting Errors

+

If any of the CUPS API printing functions returns an error, the + reason for that error can be found by calling cupsLastError() + and cupsErrorString(). cupsLastError() + returns the last IPP error code that was encountered. +cupsErrorString() converts the error code to a localized message + string suitable for presentation to the user:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +if (jobid == 0)
    +  puts(cupsErrorString(cupsLastError()));
    +
    +
+

Passwords and Authentication

+

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.

+

To support other types of applications, in particular Graphical User + Interfaces ("GUIs"), the CUPS API provides functions to set the default + username and to register a callback function that returns a password + string.

+

The cupsSetPasswordCB() + function is used to set a password callback in your program. Only one + function can be used at any time.

+

The cupsSetUser() function + sets the current username for authentication. This function can be + called by your password callback function to change the current + username as needed.

+

The following example shows a simple password callback that gets a + username and password from the user:

+
    +
    +#include <cups/cups.h>
    +
    +const char *
    +my_password_cb(const char *prompt)
    +{
    +  char	user[65];
    +
    +
    +  puts(prompt);
    +
    + /* Get a username from the user */
    +  printf("Username: ");
    +  if (fgets(user, sizeof(user), stdin) == NULL)
    +    return (NULL);
    +
    + /* Strip the newline from the string and set the user */
    +  user[strlen(user) - 1] = '\0';
    +
    +  cupsSetUser(user);
    +
    + /* Use getpass() to ask for the password... */
    +  return (getpass("Password: "));
    +}
    +
    +...
    +
    +cupsSetPasswordCB(my_password_cb);
    +
    +
+

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 +cupsUser() to make things easier on the user.

+

PPD Services

+

CUPS includes functions to access and manipulate PostScript Printer + Description ("PPD") files that are used with the printer drivers in + CUPS.

+

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.)

+

Include Files

+

Include the <cups/ppd.h> header file to use the PPD + functions:

+
    +
    +#include <cups/ppd.h>
    +
    +
+

This header file is also included by the <cups/cups.h> + header file.

+

Getting a PPD File for a Printer

+

The cupsGetPPD() function retrieves the PPD file for the + named printer or class:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +const char *filename;
    +
    +filename = cupsGetPPD("name");
    +
    +
+

The name string is the name of the printer or class, + including the remote server name as appropriate (e.g. + "printer@server".)

+

The return value is a pointer to a filename in static storage; this + value is overwritten with each call to cupsGetPPD(). If + the printer or class does not exist, a NULL pointer will + be returned.

+

Loading a PPD File

+

The ppdOpenFile() function "opens" a PPD file and loads + it into memory:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +ppd = ppdOpenFile("filename");
    +
    +
+

The filename string is the name of the file to load, + such as the value returned by the cupsGetPPD() function.

+

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.

+

Freeing PPD File Information

+

Once you are done using a PPD file, call the ppdClose() + function to free all memory that has been used:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdClose(ppd);
    +
    +
+

The PPD File Structure

+

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 +ppd_file_t structure.

+

Capabilities

+

Each PPD file contains a number of informational attributes that + describe the capabilities of the printer. These are provided in the +ppd_file_t structure in the following members: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
accurate_screensint1 + = supports accurate screens
color_deviceint1 = + color device
colorspaceppd_cs_t +Default colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY, PPD_CS_RGB, + PPD_CS_RGBK, PPD_CS_N
contone_onlyint1 = + printer is continuous tone only
num_emulations +
emulations
int +
ppd_emul_t *
Emulations supported by the printer
flip_duplexint1 = + need to flip odd pages when duplexing
num_fonts +
fonts
int +
char **
The fonts available on the printer.
jcl_begin +
jcl_ps +
jcl_end
char *Job Control + Language commands for PostScript output
landscapeint +Landscape orientation, -90 or 90 degrees
lang_encodingchar * +The character used for the option strings
lang_versionchar * +The language used for the options strings (English, French, etc.)
language_levelint +PostScript language level, 1 to 3
manual_copiesint1 = + Copies are done manually
model_numberint +Driver-specific model number.
patcheschar *Patch + commands to send to the printer
manufacturerchar * +The Manufacturer attribute from the PPD file, if any
modelnamechar *The + ModelName attribute from the PPD file
nicknamechar *The + NickName attribute from the PPD file, if any
productchar *The + Product attribute from the PPD file, if any
shortnicknamechar * +The ShortNickName attribute from the PPD file, if any
throughputintNumber + of pages per minute
ttrasterizerchar * +The TruType font rasterizer (Type42)
variable_sizesint1 = + supports variable sizes
+
+

+

Options and Groups

+

PPD files support multiple options, which are stored in +ppd_option_t and ppd_choice_t structures by the PPD + functions.

+

Each option in turn is associated with a group stored in the +ppd_group_t structure. Groups can be specified in the PPD file; + if an option is not associated with a group then it is put in a + "General" or "Extra" group depending on the option.

+

Groups can also have sub-groups; CUPS currently limits the depth of + sub-groups to 1 level to reduce programming complexity.

+

Conflicts

+

PPD files support specification of conflict conditions between + different options. Conflicts are stored in ppd_conflict_t + structures which specify the options that conflict with each other.

+

Page Sizes

+

PPD files specify all of the available pages sizes and the physical + margins associated with them. These sizes are stored in +ppd_size_t structures and are available in the num_sizes + and sizes members of the ppd_file_t + structure. You can lookup a particular page size with the +ppdPageWidth(), ppdPageLength(), and +ppdPageSize() functions:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +ppd_size_t *size;
    +float      width;
    +float      length;
    +
    +...
    +
    +size   = ppdPageSize(ppd, "size");
    +width  = ppdPageWidth(ppd, "size");
    +length = ppdPageLength(ppd, "size");
    +
    +
+

The size string is the named page size option. The width + and length are in points; there are 72 points per inch. The +ppd_size_t structure contains the width, length, and margin + information:

+
    +
    +typedef struct    /**** Page Sizes ****/
    +{
    +  int   marked;   /* Page size selected? */
    +  char  name[41]; /* Media size option */
    +  float width,    /* Width of media in points */
    +        length,   /* Length of media in points */
    +        left,     /* Left printable margin in points */
    +        bottom,   /* Bottom printable margin in points */
    +        right,    /* Right printable margin in points */
    +        top;      /* Top printable margin in points */
    +} ppd_size_t;
    +
    +
+

Custom Page Sizes

+

Besides the standard page sizes listed in a PPD file, some printers + support variable or custom page sizes. If variables_sizes + is non-zero, the custom_min, custom_max, and +custom_margins members of the ppd_file_t structure + define the limits of the variable sizes.

+

To get the resulting media size, use a page size string of +Custom.widthxlength, where width and +length are integer values in points:

+
    +
    +Custom.612x792   [8.5 inches wide, 11 inches long]
    +Custom.1224x792  [17 inches wide, 11 inches long]
    +
    +
+

Marking Options

+

Before marking any user-defined options, call the +ppdMarkDefaults() function to mark the default options from the + PPD file:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdMarkDefaults(ppd);
    +
    +
+

Then call the ppdMarkOption() function to mark + individual options:

+
    +
    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdMarkOption(ppd, "name", "value");
    +
    +
+

The name and value strings choose a + particular option and choice, respectively. The return value is 0 if + there are not conflicts created by the selection.

+

CUPS also provides a convenience function for marking all options in + the cups_option_t structure:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +ppd_file_t    *ppd;
    +int           num_options;
    +cups_option_t *options;
    +int           conflicts;
    +
    +...
    +
    +conflicts = cupsMarkOptions(ppd, num_options, options);
    +
    +
+

The cupsMarkOptions() function also handles mapping the + IPP job template attributes to PPD options. The return value is the + number of conflicts present.

+

Checking for Conflicts

+

The ppdMarkOption() and cupsMarkOptions() + functions return the number of conflicts with the currently marked + options.

+

Call the ppdConflicts() function to get the number of + conflicts after you have marked all of the options:

+
    +
    +#include <cups/cups.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdConflicts(ppd);
    +
    +
+

The return value is the number of conflicting options, or 0 if there + are no conflicts.

+

3 - Writing Filters

+

This chapter describes how to write a file filter for CUPS.

+

Overview

+

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.

+

Security Considerations

+

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.

+

Users and Groups

+

The default CUPS configuration runs filters as user "lp" and group + "other".

+

Temporary Files

+

Temporary files should be created in the directory specified by the + "TMPDIR" environment variable. The +cupsTempFile() function can be used to safely choose + temporary files in this directory.

+

Sending Messages to the User

+

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 LogLevel directive.

+

The type of message is determined by an initial prefix sent on each + line:

+
    +
  • DEBUG: - a debug message
  • +
  • INFO: - an informational message
  • +
  • WARNING: - a warning message
  • +
  • ERROR: - an error message
  • +
  • PAGE: - a page accounting message
  • +
+

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 printer-state-message attribute for the printer, and + also added to the error_log unless it is an informational or + page accounting message.

+

Page Accounting

+

Page accounting messages are used to inform the server when one or + more pages are printed. Each line has the form:

+
    +
    +PAGE: page-number copy-count
    +
    +
+

The page-number field is the current page number, starting at + 1. The copy-count field specifies the number of copies of that + page that was produced.

+

Page account messages are added to the page_log file and + cause the job-sheets-completed attribute to be updated for + the job.

+

Command-Line Arguments

+

Every filter accepts exactly 6 or 7 command-line arguments:

+
    +
    +printer job user title copies options [filename]
    +
    +
  • printer - The name of the printer queue (normally this + is the name of the program being run)
  • +
  • job - The numeric job ID for the job being printed
  • +
  • user - The string from the originating-user-name + attribute
  • +
  • title - The string from the job-name + attribute
  • +
  • copies - The numeric value from the number-copies + attribute
  • +
  • options - String representations of the job template + attributes, separated by spaces. Boolean attributes are provided as + "name" for true values and "noname" for false values. All other + attributes are provided as "name=value" for single-valued attributes + and "name=value1,value2,...,valueN" for set attributes
  • +
  • filename - The request file
  • +
+

The filename argument is only provided to the first filter in + the chain; all filters must be prepared to read the print file + from the standard input if the filename argument is omitted.

+

Copy Generation

+

The copies argument specifies the number of copies to produce + of the input file. In general, you should only generate copies if the + filename 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 pstops is responsible for copy generation.

+

Environment Variables

+

Every filter receives a fixed set of environment variables that can + be used by the filter:

+
    +
  • CHARSET - The character set used by the client for this + print file
  • +
  • CONTENT_TYPE - The original document type, such as + "application/postscript"
  • +
  • CUPS_DATADIR - The location of CUPS data files
  • +
  • CUPS_SERVERROOT - The location of CUPS configuration + files
  • +
  • DEVICE_URI - The output device URI
  • +
  • LANG - The language used by the client for this print + file
  • +
  • PATH - The execution path exported to the filter
  • +
  • PPD - The full filename of the printer's PPD file
  • +
  • PRINTER - The name of the printer queue
  • +
  • RIP_CACHE - The maximum amount of memory each filter + should use
  • +
  • SOFTWARE - The name of the CUPS software, typically + "CUPS/1.1"
  • +
  • TZ - The local timezone
  • +
  • USER - The name of the current user
  • +
+

Dissecting the HP-GL/2 Filter

+

The HP-GL/2 filter (hpgltops) 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.

+

Initializing the Filter

+

The first task of any filter is to ensure that the correct number of + command-line arguments are present:

+
    +
    +if (argc < 6 || argc > 7)
    +{
    +  fputs("ERROR: hpgltops job-id user title copies options [file]\n", stderr);
    +  return (1);
    +}
    +
    +
+

After this you open the print file or read from the standard input as + needed:

+
    +
    +FILE *fp;
    +
    +/*
    + * If we have 7 arguments, print the file named on the command-line.
    + * Otherwise, send stdin instead...
    + */
    +
    +if (argc == 6)
    +  fp = stdin;
    +else
    +{
    + /*
    +  * Try to open the print file...
    +  */
    +
    +  if ((fp = fopen(argv[6], "rb")) == NULL)
    +  {
    +    perror("ERROR: unable to open print file - ");
    +    return (1);
    +  }
    +}
    +
    +
+

Once the print file has been opened, options can be processed using + the cupsParseOptions() and cupsGetOption() functions:

+
    +
    +int           num_options;
    +cups_option_t *options;
    +const char    *val;
    +
    +/*
    + * Process command-line options and write the prolog...
    + */
    +
    +options     = NULL;
    +num_options = cupsParseOptions(argv[5], 0, 
    +
    +if ((val = cupsGetOption("blackplot", num_options, options)) != NULL)
    +  shading = 0;
    +
    +if ((val = cupsGetOption("fitplot", num_options, options)) != NULL)
    +  FitPlot = 1;
    +
    +if ((val = cupsGetOption("penwidth", num_options, options)) != NULL)
    +  PenWidth = (float)atoi(val) * 0.001f;
    +
    +
+

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.

+

PostScript Output

+

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:

+
    +
    +%!PS-Adobe-3.0
    +%%BoundingBox: left bottom right top
    +%%Pages: (atend)
    +%%EndComments
    +
    +
+

The left, bottom, right, and top values + are integers in points from the lower-lefthand corner of the page.

+

Pages must be surrounded by:

+
    +
    +%%Page: number number
    +gsave
    +...
    +grestore
    +showpage
    +
    +
+

And the end of each file must contain:

+
    +
    +%%Trailer
    +%%Pages: number-pages
    +%%EOF
    +
    +
+

These comments allow the PostScript filter to correctly perform page + accounting, copy generation, N-up printing, and so forth.

+

4 - Writing Printer Drivers +

+

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.

+

Overview

+

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.

+

CUPS Raster Data

+

CUPS raster data (application/vnd.cups-raster) consists + of a stream of raster page descriptions produced by one of the RIP + filters, such as pstoraster or imagetoraster.

+

Each page of data begins with a page dictionary structure called + cups_raster_header_t. This structure contains the + colorspace, bits per color, media size, media type, hardware + resolution, and so forth.

+

After the page dictionary comes the page data which is a + full-resolution, uncompressed bitmap representing the page in the + printer's output colorspace.

+

Page Accounting

+

Printer drivers must handle all page accounting. This means they must + send "PAGE:" messages to the standard error file for each page (and in + many cases, copy) sent to the printer.

+

Color Management

+

Printer drivers can implement their color management via the +cupsColorProfile 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.

+

For example, the pstoraster 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.

+

Device and Bitmap Variables

+

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: +

+ + + + + + + + + + + + + + +
VariableTypeDescription
cupsWidthread-only integerWidth of bitmap in + pixels
cupsHeightread-only integerHeight of bitmap in + pixels
cupsMediaTyperead-write integerDevice-specific + media type code
cupsBitsPerColorread-write integerNumber of + bits per color; 1, 2, 4, and 8 are currently supported
cupsBitsPerPixelread-only integerNumber of + bits per pixel; 1 to 32
cupsBytesPerLineread-only integerNumber of + bytes per line of raster graphics
cupsColorOrderread-write enumThe order of + color values in the bitmap: +
    +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK
  • +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK
  • +
  • CUPS_ORDER_PLANAR - CCC ... MMM ... YYY ... KKK ...
  • +
+
cupsColorSpaceread-write enumThe colorspace of + the bitmap: +
    +
  • CUPS_CSPACE_W - White (luminance)
  • +
  • CUPS_CSPACE_RGB - Red, green, blue
  • +
  • CUPS_CSPACE_RGBA - Red, green, blue, alpha
  • +
  • CUPS_CSPACE_K - Black
  • +
  • CUPS_CSPACE_CMY - Cyan, magenta, yellow
  • +
  • CUPS_CSPACE_YMC - Yellow, magenta, cyan
  • +
  • CUPS_CSPACE_CMYK - Cyan, magenta, yellow, black
  • +
  • CUPS_CSPACE_YMCK - Yellow, magenta, cyan, black
  • +
  • CUPS_CSPACE_KCMY - Black, cyan, magenta, yellow
  • +
  • CUPS_CSPACE_KCMYcm - Black, cyan, magenta, yellow, + light cyan, light magenta
  • +
  • CUPS_CSPACE_GMCK - Metallic yellow (gold), metallic + magenta, metallic cyan, black
  • +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), metallic + magenta, metallic cyan, metallic grey (silver)
  • +
  • CUPS_CSPACE_WHITE - White pigment (black as white + pigment)
  • +
  • CUPS_CSPACE_GOLD - Gold foil (black as gold foil)
  • +
  • CUPS_CSPACE_SILVER - Silver foil (black as silver foil)
  • +
+
cupsCompressionread-write integer +Device-specific compression type code
cupsRowCountread-write integerDevice-specific + row count value
cupsRowFeedread-write integerDevice-specific + row feed value
cupsRowStepread-write integerDevice-specific + row step value
+
+

+

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.

+

Dissecting the HP-PCL Driver

+

The HP-PCL driver provided with CUPS (rastertohp) + 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 - deskjet.ppd or + laserjet.ppd.

+

PPD Files

+

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.

+

A typical CUPS printer driver will include ColorModel, +InputSlot, PageSize, PageRegion, and +Resolution options. Each option is shown using the standard PPD + format:

+
    +
    +*OpenUI *PageSize/Media Size: PickOne
    +*OrderDependency: 10 AnySetup *PageSize
    +*DefaultPageSize: Letter
    +*PageSize Letter/US Letter: "<<
    +/PageSize [612 792]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize Legal/US Legal: "<<
    +/PageSize [612 1008]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*CloseUI: *PageSize
    +
    +
+

The OpenUI 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.

+

Every option must have a default value, specified using the +DefaultOption keyword.

+

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:

+
    +
    +*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>> setpagedevice"
    +
    +
+

or broken down on separate lines using the End keyword + to terminate them:

+
    +
    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +
    +
+

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.

+

Reading Raster Data

+

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 cupsRasterOpen() + function opens a raster stream for printing:

+
    +
    +int           fd;   /* File descriptor */
    +cups_raster_t *ras; /* Raster stream for printing */
    +
    +
    +/*
    + * Check for valid arguments...
    + */
    +
    +if (argc < 6 || argc > 7)
    +{
    + /*
    +  * We don't have the correct number of arguments; write an error message
    +  * and return.
    +  */
    +
    +  fputs("ERROR: rastertopcl job-id user title copies options [file]\n", stderr);
    +  return (1);
    +}
    +
    +/*
    + * Open the page stream...
    + */
    +
    +if (argc == 7)
    +{
    +  if ((fd = open(argv[6], O_RDONLY)) == -1)
    +  {
    +    perror("ERROR: Unable to open raster file - ");
    +    sleep(1);
    +    return (1);
    +  }
    +}
    +else
    +  fd = 0;
    +
    +ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
    +
    +
+

Once you have opened the raster stream you just need to read each + page and print it:

+
    +
    +cups_raster_header_t header;
    +int                  y;
    +unsigned char        data[8192];
    +
    +while (cupsRasterReadHeader(ras, &header))
    +{
    +  ... initialize the printer ...
    +  for (y = header.cupsHeight; y > 0; y ++)
    +  {
    +    cupsRasterReadPixels(ras, data, header.cupsBytesPerLine);
    +    ... send raster line to printer ...
    +  }
    +}
    +
    +
+

After you have processed all pages, close the raster stream and + return:

+
    +
    +cupsRasterClose(ras);
    +
    +return (0);
    +
    +
+

5 - Writing Backends

+

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.

+

Overview

+

Backends are special filters that communicate with printers directly. + They are treated slightly differently than filters, however, and have + some unique requirements.

+

Security Considerations

+

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.

+

Command-Line Arguments

+

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.

+

Copy Generation

+

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.

+

Page Accounting

+

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 "raw" printing and no other accounting + information is possible.

+

Exclusive Access

+

Backends that talk to local character or block devices should open + the device file in exclusive mode (O_EXCL) to cooperate + with other printers defined for the same device.

+

Retries

+

All backends must 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.

+

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.

+

Dissecting the Serial Port Backend

+

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.

+

Supporting Device Discovery

+

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...)

+

The serial backend lists devices by looking at serial port files in + the /dev directory, by consulting a hardware inventory + (IRIX), and in some cases by trying to open the ports to see if they + actually exist.

+

Once it finds a serial port it writes a single line for each port to + the standard error file. Each line looks like this:

+
    +
    +serial serial:/dev/ttyS0?baud=115200 "Unknown" "Serial Port 1"
    +
    +
+

The first word "serial" is the device class; this identifies + the class of device which can be used to categorize it in user + interfaces. CUPS currently recognizes the following classes:

+
    +
  • "file" - a disk file.
  • +
  • "direct" - a parallel or fixed-rate serial data port, currently used + for Centronics, IEEE-1284, and USB printer ports.
  • +
  • "serial" - a variable-rate serial port.
  • +
  • "network" - a network connection, typically via AppSocket, HTTP, + IPP, LPD, or SMB/CIFS protocols.
  • +
+

After the device class is the device URI, in this case + "serial:/dev/ttyS0?baud=115200". This is the URI that should be used by + the user to select this port. For serial ports, the "baud=115200" + specifies the maximum baud rate supported by the port - the actual + value will vary based on the speed the user selects for the printer.

+

The last two strings are the model and description for the port. The + "Unknown" string means that the printer model is unknown - some devices + are able to provide a make and model such as "HP DeskJet" that allows + users and software to choose an appropriate printer driver more easily. + Both the model and description must be enclosed inside double quotes.

+

Opening the Serial Port

+

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 do-while loop:

+
    +
    +do
    +{
    +  if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1)
    +  {
    +    if (errno == EBUSY)
    +    {
    +      fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr);
    +      sleep(30);
    +    }
    +    else
    +    {
    +      perror("ERROR: Unable to open serial port device file");
    +      return (1);
    +    }
    +  }
    +}
    +while (fd < 0);
    +
    +
+

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.

+

Writing Data to the Port

+

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:

+
    +
    +while (nbytes > 0)
    +{
    +  if ((wbytes = write(fd, bufptr, nbytes)) < 0)
    +    if (errno == ENOTTY)
    +      wbytes = write(fd, bufptr, nbytes);
    +
    +  if (wbytes < 0)
    +  {
    +    perror("ERROR: Unable to send print file to printer");
    +    break;
    +  }
    +
    +  nbytes -= wbytes;
    +  bufptr += wbytes;
    +}
    +
    +
+

The check for the ENOTTY error is needed on some + platforms to clear an error from a previous ioctl() call.

+

Finishing Up

+

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.

+

A - Software License Agreement

+

Common UNIX Printing System License + Agreement

+

Copyright 1997-2002 by Easy Software Products +
44141 AIRPORT VIEW DR STE 204 +
HOLLYWOOD, MARYLAND 20636-3111 USA +
+
Voice: +1.301.373.9600 +
Email: cups-info@cups.org +
WWW: http://www.cups.org

+

Introduction

+

The Common UNIX Printing SystemTM, ("CUPSTM"), + is provided under the GNU General Public License ("GPL") and GNU + Library General Public License ("LGPL"), Version 2, with exceptions for + Apple operating systems and the OpenSSL toolkit. A copy of the + exceptions and licenses follow this introduction.

+

The GNU LGPL applies to the CUPS API library, located in the "cups" + subdirectory of the CUPS source distribution and in the "cups" include + directory and library files in the binary distributions. The GNU GPL + applies to the remainder of the CUPS distribution, including the + "pdftops" filter which is based upon Xpdf and the CUPS imaging library.

+

For those not familiar with the GNU GPL, the license basically allows + you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in source or binary form.
  • +
  • Sell verbatim copies of the software for a media fee, or sell + support for the software.
  • +
  • Distribute or sell printer drivers and filters that use CUPS so long + as source code is made available under the GPL.
  • +
+

What this license does not 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. The only exceptions to this are the portions of + the CUPS software covered by the Apple operating system license + exceptions outlined later in this license agreement.

+

The GNU LGPL relaxes the "link-to" restriction, allowing you to + develop applications that use the CUPS API library under other licenses + and/or conditions as appropriate for your application.

+

License Exceptions

+

In addition, as the copyright holder of CUPS, Easy Software Products + grants the following special exceptions:

+
    +
  1. Apple Operating System Development License Exception; +
      +
    1. Software that is developed by any person or entity for an Apple + Operating System ("Apple OS-Developed Software"), including but not + limited to Apple and third party printer drivers, filters, and backends + for an Apple Operating System, that is linked to the CUPS imaging + library or based on any sample filters or backends provided with CUPS + shall not be considered to be a derivative work or collective work + based on the CUPS program and is exempt from the mandatory source code + release clauses of the GNU GPL. You may therefore distribute linked + combinations of the CUPS imaging library with Apple OS-Developed + Software without releasing the source code of the Apple OS-Developed + Software. You may also use sample filters and backends provided with + CUPS to develop Apple OS-Developed Software without releasing the + source code of the Apple OS-Developed Software.
    2. +
    3. An Apple Operating System means any operating system software + developed and/or marketed by Apple Computer, Inc., including but not + limited to all existing releases and versions of Apple's Darwin, Mac OS + X, and Mac OS X Server products and all follow-on releases and future + versions thereof.
    4. +
    5. This exception is only available for Apple OS-Developed Software and + does not apply to software that is distributed for use on other + operating systems.
    6. +
    7. All CUPS software that falls under this license exception have the + following text at the top of each source file:
      This file is + subject to the Apple OS-Developed Software exception.
    8. +
    +
  2. +
  3. OpenSSL Toolkit License Exception; +
      +
    1. Easy Software Products explicitly allows the compilation and + distribution of the CUPS software with the OpenSSL Toolkit.
    2. +
    +
  4. +
+

No developer is required to provide these exceptions in a derived + work.

+

Trademarks

+

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. Please contract Easy + Software Products for written permission to use them in derivative + products. 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.

+

Binary Distribution Rights

+

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.

+

The Common UNIX Printing System provides a "pdftops" filter that is + based on the Xpdf software. For binary distribution licensing of this + software, please contact:

Derek B. Noonburg +
Email: derekn@foolabs.com +
WWW: + http://www.foolabs.com/xpdf/

+

Support

+

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:

+ + + +

GNU GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow.

+

GNU GENERAL PUBLIC LICENSE +
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+
    +
  1. 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 "Program", below, + refers to any such program or work, and a "work based on the Program" + 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 "modification".) Each licensee is addressed as "you". +

    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.

    +
  2. 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. +

    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.

    +
  3. 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: +
      +
    1. You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change.
    2. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +

    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.

    +

    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.

    +

    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.

    +
  4. 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: +
      +
    1. 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,
    2. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +

    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.

    +

    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.

    +
  5. 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.
  6. +
  7. 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.
  8. +
  9. 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.
  10. +
  11. 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. +

    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.

    +

    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.

    +

    This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

    +
  12. 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.
  13. +
  14. 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. +

    Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", 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.

    +
  15. 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.
  16. + + + + + + +
+

NO WARRANTY

+
    +
  1. 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 "AS IS" 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.
  2. +
  3. 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.
  4. +
+

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, while the latter only + works together with the library.

+

Note that it is possible for a library to be covered by the ordinary + General Public License rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+

0. 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 "this License"). Each + licensee is addressed as "you".

+

A "library" 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.

+

The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" 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 "modification".)

+

"Source code" 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.

+

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.

+

1. 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.

+

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.

+

2. 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:

+
    +
  1. The modified work must itself be a software library. +

    +
  2. You must cause the files modified to carry prominent notices stating + that you changed the files and the date of any change. +

    +
  3. You must cause the whole of the work to be licensed at no charge to + all third parties under the terms of this License. +

    +
  4. 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. +

    (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.)

    +
  5. + + + +
+

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.

+

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.

+

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.

+

3. 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.

+

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.

+

This option is useful when you wish to copy part of the code of the + Library into a program that is not a library.

+

4. 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.

+

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.

+

5. 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 "work that uses the + Library". Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License.

+

However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. Section + 6 states terms for distribution of such executables.

+

When a "work that uses the Library" 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.

+

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.)

+

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.

+

6. As an exception to the Sections above, you may + also compile or link a "work that uses the Library" 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.

+

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:

+
    +
  1. 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 "work that uses the Library", 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.) +

    +
  2. 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. +

    +
  3. 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. +

    +
  4. Verify that the user has already received a copy of these materials + or that you have already sent this user a copy.
  5. + + + +
+

For an executable, the required form of the "work that uses the + Library" 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.

+

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.

+

7. 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:

+
    +
  1. 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. +

    +
  2. 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.
  3. + +
+

8. 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.

+

9. 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.

+

10. 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.

+

11. 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.

+

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.

+

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.

+

This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

+

12. 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.

+

13. 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.

+

Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and "any + later version", 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.

+

14. 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.

+

NO WARRANTY

+

15. 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 "AS IS" 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.

+

16. 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.

+

END OF TERMS AND CONDITIONS

+

B - Constants

+

This appendix lists all of the constants that are defined by the CUPS + API.

+

CUPS Constants

+

Version Number

+

The CUPS_VERSION 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.

+

Printer Capabilities

+

The CUPS_PRINTER constants represent capability bits for + printers and classes:

+
    +
  • CUPS_PRINTER_LOCAL - Is a local printer or class.
  • +
  • CUPS_PRINTER_REMOTE - Is a remote printer or class.
  • +
  • CUPS_PRINTER_CLASS - Is a class.
  • +
  • CUPS_PRINTER_BW - Printer prints in black and white.
  • +
  • CUPS_PRINTER_COLOR - Printer prints in color.
  • +
  • CUPS_PRINTER_DUPLEX - Printer can print double-sided.
  • +
  • CUPS_PRINTER_STAPLE - Printer can staple output.
  • +
  • CUPS_PRINTER_COPIES - Printer can produce multiple + copies on its own.
  • +
  • CUPS_PRINTER_COLLATE - Printer can collate copies.
  • +
  • CUPS_PRINTER_PUNCH - Printer can punch holes in output.
  • +
  • CUPS_PRINTER_COVER - Printer can put covers on output.
  • +
  • CUPS_PRINTER_BIND - Printer can bind output.
  • +
  • CUPS_PRINTER_SORT - Printer can sort output.
  • +
  • CUPS_PRINTER_SMALL - Printer can print on media up to + 9x14 inches.
  • +
  • CUPS_PRINTER_MEDIUM - Printer can print on media from + 9x14 to 18x24 inches.
  • +
  • CUPS_PRINTER_LARGE - Printer can print on media larger + than 18x24 inches.
  • +
  • CUPS_PRINTER_VARIABLE - Printer can print on variable + or custom media sizes.
  • +
  • CUPS_PRINTER_IMPLICIT - Is an implicit class.
  • +
  • CUPS_PRINTER_OPTIONS - All of the printer capability + and option bits.
  • +
+

Encodings

+

CUPS defines the following character set encoding constants:

+
    +
  • CUPS_US_ASCII - US ASCII character set.
  • +
  • CUPS_UTF_8 - UTF-8 encoding of Unicode.
  • +
  • CUPS_ISO8859_1 - ISO-8859-1 character set.
  • +
  • CUPS_ISO8859_2 - ISO-8859-2 character set.
  • +
  • CUPS_ISO8859_3 - ISO-8859-3 character set.
  • +
  • CUPS_ISO8859_4 - ISO-8859-4 character set.
  • +
  • CUPS_ISO8859_5 - ISO-8859-5 character set.
  • +
  • CUPS_ISO8859_6 - ISO-8859-6 character set.
  • +
  • CUPS_ISO8859_7 - ISO-8859-7 character set.
  • +
  • CUPS_ISO8859_8 - ISO-8859-8 character set.
  • +
  • CUPS_ISO8859_9 - ISO-8859-9 character set.
  • +
  • CUPS_ISO8859_10 - ISO-8859-10 character set.
  • +
  • CUPS_ISO8859_13 - ISO-8859-13 character set.
  • +
  • CUPS_ISO8859_14 - ISO-8859-14 character set.
  • +
  • CUPS_ISO8859_15 - ISO-8859-15 character set.
  • +
  • CUPS_WINDOWS_874 - Windows code page 874.
  • +
  • CUPS_WINDOWS_1250 - Windows code page 1250.
  • +
  • CUPS_WINDOWS_1251 - Windows code page 1251.
  • +
  • CUPS_WINDOWS_1252 - Windows code page 1252.
  • +
  • CUPS_WINDOWS_1253 - Windows code page 1253.
  • +
  • CUPS_WINDOWS_1254 - Windows code page 1254.
  • +
  • CUPS_WINDOWS_1255 - Windows code page 1255.
  • +
  • CUPS_WINDOWS_1256 - Windows code page 1256.
  • +
  • CUPS_WINDOWS_1257 - Windows code page 1257.
  • +
  • CUPS_WINDOWS_1258 - Windows code page 1258.
  • +
  • CUPS_KOI8_R - Russian code page koi8-r.
  • +
  • CUPS_KOI8_U - Ukrainian code page koi8-r.
  • +
+

HTTP Constants

+

Limits

+

The following constants define the limits for strings:

+
    +
  • HTTP_MAX_BUFFER - Size of socket buffer.
  • +
  • HTTP_MAX_HOST - Maximum length of hostname.
  • +
  • HTTP_MAX_URI - Maximum length of URI.
  • +
  • HTTP_MAX_VALUE - Maximum length of field values.
  • +
+

Status Codes

+

The following status codes can be returned by httpUpdate() +:

+
    +
  • HTTP_ERROR - A network error occurred
  • +
  • HTTP_CONTINUE - Continue response from HTTP proxy
  • +
  • HTTP_OK - OPTIONS/GET/HEAD/POST/TRACE command was + successful
  • +
  • HTTP_CREATED - PUT command was successful
  • +
  • HTTP_ACCEPTED - DELETE command was successful
  • +
  • HTTP_NOT_AUTHORITATIVE - Information isn't + authoritative
  • +
  • HTTP_NO_CONTENT - Successful command
  • +
  • HTTP_RESET_CONTENT - Content was reset/recreated
  • +
  • HTTP_PARTIAL_CONTENT - Only a partial file was + recieved/sent
  • +
  • HTTP_MULTIPLE_CHOICES - Multiple files match request
  • +
  • HTTP_MOVED_PERMANENTLY - Document has moved permanently
  • +
  • HTTP_MOVED_TEMPORARILY - Document has moved temporarily
  • +
  • HTTP_SEE_OTHER - See this other link...
  • +
  • HTTP_NOT_MODIFIED - File not modified
  • +
  • HTTP_USE_PROXY - Must use a proxy to access this URI
  • +
  • HTTP_BAD_REQUEST - Bad request
  • +
  • HTTP_UNAUTHORIZED - Unauthorized to access host
  • +
  • HTTP_PAYMENT_REQUIRED - Payment required
  • +
  • HTTP_FORBIDDEN - Forbidden to access this URI
  • +
  • HTTP_NOT_FOUND - URI was not found
  • +
  • HTTP_METHOD_NOT_ALLOWED - Method is not allowed
  • +
  • HTTP_NOT_ACCEPTABLE - Not Acceptable
  • +
  • HTTP_PROXY_AUTHENTICATION - Proxy Authentication is + Required
  • +
  • HTTP_REQUEST_TIMEOUT - Request timed out
  • +
  • HTTP_CONFLICT - Request is self-conflicting
  • +
  • HTTP_GONE - Server has gone away
  • +
  • HTTP_LENGTH_REQUIRED - A content length or encoding is + required
  • +
  • HTTP_PRECONDITION - Precondition failed
  • +
  • HTTP_REQUEST_TOO_LARGE - Request entity too large
  • +
  • HTTP_URI_TOO_LONG - URI too long
  • +
  • HTTP_UNSUPPORTED_MEDIATYPE - The requested media type + is unsupported
  • +
  • HTTP_SERVER_ERROR - Internal server error
  • +
  • HTTP_NOT_IMPLEMENTED - Feature not implemented
  • +
  • HTTP_BAD_GATEWAY - Bad gateway
  • +
  • HTTP_SERVICE_UNAVAILABLE - Service is unavailable
  • +
  • HTTP_GATEWAY_TIMEOUT - Gateway connection timed out
  • +
  • HTTP_NOT_SUPPORTED - HTTP version not supported
  • +
+

Fields

+

The following fields are indices for each of the standard HTTP fields + in HTTP 1/1:

+
    +
  • HTTP_FIELD_ACCEPT_LANGUAGE - Accept-Language
  • +
  • HTTP_FIELD_ACCEPT_RANGES - Accept-Ranges
  • +
  • HTTP_FIELD_AUTHORIZATION - Authorization
  • +
  • HTTP_FIELD_CONNECTION - Connection
  • +
  • HTTP_FIELD_CONTENT_ENCODING - Content-Encoding
  • +
  • HTTP_FIELD_CONTENT_LANGUAGE - Content-Language
  • +
  • HTTP_FIELD_CONTENT_LENGTH - Content-Length
  • +
  • HTTP_FIELD_CONTENT_LOCATION - Content-Location
  • +
  • HTTP_FIELD_CONTENT_MD5 - Content-MD5
  • +
  • HTTP_FIELD_CONTENT_RANGE - Content-Range
  • +
  • HTTP_FIELD_CONTENT_TYPE - Content-Type
  • +
  • HTTP_FIELD_CONTENT_VERSION - Content-Version
  • +
  • HTTP_FIELD_DATE - Date
  • +
  • HTTP_FIELD_HOST - Host
  • +
  • HTTP_FIELD_IF_MODIFIED_SINCE - If-Modified-Since
  • +
  • HTTP_FIELD_IF_UNMODIFIED_SINCE - If-Unmodified-Since
  • +
  • HTTP_FIELD_KEEP_ALIVE - Keep-Alive
  • +
  • HTTP_FIELD_LAST_MODIFIED - Last-Modified
  • +
  • HTTP_FIELD_LINK - Link
  • +
  • HTTP_FIELD_LOCATION - Location
  • +
  • HTTP_FIELD_RANGE - Range
  • +
  • HTTP_FIELD_REFERER - Referer
  • +
  • HTTP_FIELD_RETRY_AFTER - Retry-After
  • +
  • HTTP_FIELD_TRANSFER_ENCODING - Transfer-Encoding
  • +
  • HTTP_FIELD_UPGRADE - Upgrade
  • +
  • HTTP_FIELD_USER_AGENT - User-Agent
  • +
  • HTTP_FIELD_WWW_AUTHENTICATE - WWW-Authenticate
  • +
+

IPP Constants

+

Limits

+

The following constants define array limits for IPP data:

+
    +
  • IPP_MAX_NAME - Maximum length of an attribute name
  • +
  • IPP_MAX_VALUES - Maximum number of set-of values that + can be read in a request.
  • +
+

Tags

+
    +
  • IPP_TAG_ZERO - Wildcard tag value for searches; also + used to separate groups of attributes
  • +
  • IPP_TAG_OPERATION - Tag for values of type operation
  • +
  • IPP_TAG_JOB - Tag for values of type job
  • +
  • IPP_TAG_END - Tag for values of type end
  • +
  • IPP_TAG_PRINTER - Tag for values of type printer
  • +
  • IPP_TAG_UNSUPPORTED_GROUP - Tag for values of type + unsupported_group
  • +
  • IPP_TAG_UNSUPPORTED_VALUE - Tag for values of type + unsupported_value
  • +
  • IPP_TAG_DEFAULT - Tag for values of type default
  • +
  • IPP_TAG_UNKNOWN - Tag for values of type unknown
  • +
  • IPP_TAG_NOVALUE - Tag for values of type novalue
  • +
  • IPP_TAG_NOTSETTABLE - Tag for values of type + notsettable
  • +
  • IPP_TAG_DELETEATTR - Tag for values of type deleteattr
  • +
  • IPP_TAG_ANYVALUE - Tag for values of type anyvalue
  • +
  • IPP_TAG_INTEGER - Tag for values of type integer
  • +
  • IPP_TAG_BOOLEAN - Tag for values of type boolean
  • +
  • IPP_TAG_ENUM - Tag for values of type enum
  • +
  • IPP_TAG_STRING - Tag for values of type string
  • +
  • IPP_TAG_DATE - Tag for values of type date
  • +
  • IPP_TAG_RESOLUTION - Tag for values of type resolution
  • +
  • IPP_TAG_RANGE - Tag for values of type range
  • +
  • IPP_TAG_COLLECTION - Tag for values of type collection
  • +
  • IPP_TAG_TEXTLANG - Tag for values of type textlang
  • +
  • IPP_TAG_NAMELANG - Tag for values of type namelang
  • +
  • IPP_TAG_TEXT - Tag for values of type text
  • +
  • IPP_TAG_NAME - Tag for values of type name
  • +
  • IPP_TAG_KEYWORD - Tag for values of type keyword
  • +
  • IPP_TAG_URI - Tag for values of type uri
  • +
  • IPP_TAG_URISCHEME - Tag for values of type urischeme
  • +
  • IPP_TAG_CHARSET - Tag for values of type charset
  • +
  • IPP_TAG_LANGUAGE - Tag for values of type language
  • +
  • IPP_TAG_MIMETYPE - Tag for values of type mimetype
  • +
+

Resolution Units

+

The IPP_RES_PER_INCH and IPP_RES_PER_CM + constants specify dots per inch and dots per centimeter, respectively.

+

Finishings

+

The finishing values specify special finishing operations to be + performed on the job.

+
    +
  • IPP_FINISH_NONE - Do no finishing
  • +
  • IPP_FINISH_STAPLE - Staple the job
  • +
  • IPP_FINISH_PUNCH - Punch the job
  • +
  • IPP_FINISH_COVER - Cover the job
  • +
  • IPP_FINISH_BIND - Bind the job
  • +
+

Orientations

+

The orientation values specify the orientation of the job.

+
    +
  • IPP_PORTRAIT - No rotation
  • +
  • IPP_LANDSCAPE - 90 degrees counter-clockwise
  • +
  • IPP_REVERSE_LANDSCAPE - 90 degrees clockwise
  • +
  • IPP_REVERSE_PORTRAIT - 180 degrees
  • +
+

Qualities

+

The quality values specify the desired quality of the print.

+
    +
  • IPP_QUALITY_DRAFT - Draft quality
  • +
  • IPP_QUALITY_NORMAL - Normal quality
  • +
  • IPP_QUALITY_HIGH - High quality
  • +
+

Job States

+

The job state values are used to represent the current job state.

+
    +
  • IPP_JOB_PENDING - Job is pending
  • +
  • IPP_JOB_HELD - Job is held
  • +
  • IPP_JOB_PROCESSING - Job is processing
  • +
  • IPP_JOB_STOPPED - Job is stopped
  • +
  • IPP_JOB_CANCELLED - Job is cancelled
  • +
  • IPP_JOB_ABORTED - Job is aborted
  • +
  • IPP_JOB_COMPLETED - Job is completed
  • +
+

Printer States

+

The printer state values are used to represent the current printer + state.

+
    +
  • IPP_PRINTER_IDLE - Printer is idle
  • +
  • IPP_PRINTER_PROCESSING - Printer is processing
  • +
  • IPP_PRINTER_STOPPED - Printer is stopped
  • +
+

Operations

+

The operation values represent the available IPP operations.

+
    +
  • IPP_PRINT_JOB - Print a file
  • +
  • IPP_PRINT_URI - Print a URI
  • +
  • IPP_VALIDATE_JOB - Validate job attributes
  • +
  • IPP_CREATE_JOB - Create a new job
  • +
  • IPP_SEND_DOCUMENT - Send a document to a job
  • +
  • IPP_SEND_URI - Send a URI to a job
  • +
  • IPP_CANCEL_JOB - Cancel a job
  • +
  • IPP_GET_JOB_ATTRIBUTES - Get job attributes
  • +
  • IPP_GET_JOBS - Get a list of all jobs
  • +
  • IPP_GET_PRINTER_ATTRIBUTES - Get printer attributes
  • +
  • IPP_HOLD_JOB - Hold a pending job
  • +
  • IPP_RELEASE_JOB - Release a held job
  • +
  • IPP_RESTART_JOB - Restart a completed job
  • +
  • IPP_PAUSE_PRINTER - Pause a printer
  • +
  • IPP_RESUME_PRINTER - Restart a paused printer
  • +
  • IPP_PURGE_JOBS - Purge jobs from the queue
  • +
  • IPP_SET_PRINTER_ATTRIBUTES - Set printer attributes
  • +
  • IPP_SET_JOB_ATTRIBUTES - Set job attributes
  • +
  • IPP_GET_PRINTER_SUPPORTED_VALUES - Get printer + supported values
  • +
  • CUPS_GET_DEFAULT - Get the default destination
  • +
  • CUPS_GET_PRINTERS - Get a list of all printers
  • +
  • CUPS_ADD_PRINTER - Add or modify a printer
  • +
  • CUPS_DELETE_PRINTER - Delete a printer
  • +
  • CUPS_GET_CLASSES - Get a list of all classes
  • +
  • CUPS_ADD_CLASS - Add or modify a class
  • +
  • CUPS_DELETE_CLASS - Delete a class
  • +
  • CUPS_ACCEPT_JOBS - Accept jobs on a printer or class
  • +
  • CUPS_REJECT_JOBS - Reject jobs on a printer or class
  • +
  • CUPS_SET_DEFAULT - Set the default destination
  • +
  • CUPS_GET_DEVICES - Get a list of all devices
  • +
  • CUPS_GET_PPDS - Get a list of all PPDs
  • +
  • CUPS_MOVE_JOB - Move a job to a new destination
  • +
+

Status Codes

+

Status codes are returned by all IPP requests.

+
    +
  • IPP_OK - Request completed with no errors
  • +
  • IPP_OK_SUBST - Request completed but some attribute + values were substituted
  • +
  • IPP_OK_CONFLICT - Request completed but some attributes + conflicted
  • +
  • IPP_BAD_REQUEST - The request was bad
  • +
  • IPP_FORBIDDEN - You don't have access to the resource
  • +
  • IPP_NOT_AUTHENTICATED - You are not authenticated for + the resource
  • +
  • IPP_NOT_AUTHORIZED - You not authorized to access the + resource
  • +
  • IPP_NOT_POSSIBLE - The requested operation cannot be + completed
  • +
  • IPP_TIMEOUT - A timeout occurred
  • +
  • IPP_NOT_FOUND - The resource was not found
  • +
  • IPP_GONE - The resource has gone away
  • +
  • IPP_REQUEST_ENTITY - The request was too large
  • +
  • IPP_REQUEST_VALUE - The request contained a value that + was unknown to the server
  • +
  • IPP_DOCUMENT_FORMAT - The document format is not + supported by the server
  • +
  • IPP_ATTRIBUTES - Required attributes are missing
  • +
  • IPP_URI_SCHEME - The URI scheme is not supported
  • +
  • IPP_CHARSET - The charset is not supported
  • +
  • IPP_CONFLICT - One or more attributes conflict
  • +
  • IPP_COMPRESSION_NOT_SUPPORTED - The specified + compression is not supported
  • +
  • IPP_COMPRESSION_ERROR - The compressed data contained + an error
  • +
  • IPP_DOCUMENT_FORMAT_ERROR - The document data contained + an error in it
  • +
  • IPP_DOCUMENT_ACCESS_ERROR - The remote document could + not be accessed
  • +
  • IPP_INTERNAL_ERROR - The server encountered an internal + error
  • +
  • IPP_OPERATION_NOT_SUPPORTED - The requested operation + is not supported
  • +
  • IPP_SERVICE_UNAVAILABLE - The requested service is + unavailable
  • +
  • IPP_VERSION_NOT_SUPPORTED - The IPP request version is + not supported
  • +
  • IPP_DEVICE_ERROR - The output device encountered an + error
  • +
  • IPP_TEMPORARY_ERROR - A temporary error occurred
  • +
  • IPP_NOT_ACCEPTING - The destination is not accepting + jobs
  • +
  • IPP_PRINTER_BUSY - The destination is busy
  • +
  • IPP_ERROR_JOB_CANCELLED - The requested job has been + cancelled
  • +
  • IPP_MULTIPLE_JOBS_NOT_SUPPORTED - The server does not + support multiple jobs
  • +
+

PPD Constants

+

PPD Format Version

+

The PPD_VERSION constant defines a floating point number + representing the newest format version that is supported by CUPS, + currently 4.3.

+

PPD User-Interface Types

+

Each printer option has a type associated with it:

+
    +
  • PPD_UI_BOOLEAN - The user can turn this option on or + off
  • +
  • PPD_UI_PICKONE - The user can choose one option value + to use.
  • +
  • PPD_UI_PICKMANY - The user can choose zero or more + option values.
  • +
+

PPD Sections

+

Some options must be output before others, or in different sections + of the output document. The ppd_section_t enumeration + defines which section the option must be output in:

+
    +
  • PPD_ORDER_ANY - The option can be output in any of the + document, page, or prolog sections of the document
  • +
  • PPD_ORDER_DOCUMENT - The option must be output in the + DocumentSetup section of the document
  • +
  • PPD_ORDER_EXIT - The option must be output before the + document
  • +
  • PPD_ORDER_JCL - The option must be output in the job + control section of the document
  • +
  • PPD_ORDER_PAGE - The option must be output in the + PageSetup section of the document
  • +
  • PPD_ORDER_PROLOG - The option must be output in the + Prolog section of the document
  • +
+

PPD Colorspaces

+

Each printer has a default colorspace:

+
    +
  • PPD_CS_CMYK - The printer uses CMYK colors by default
  • +
  • PPD_CS_CMY - The printer uses CMY colors by default
  • +
  • PPD_CS_GRAY - The printer uses grayscale by default
  • +
  • PPD_CS_RGB - The printer uses RGB colors by default
  • +
  • PPD_CS_RGBK - The printer uses RGBK colors by default
  • +
  • PPD_CS_N - The printer uses a DeviceN colorspace by + default
  • +
+

Raster Constants

+

Raster Sync Words

+

The CUPS_RASTER_SYNC and CUPS_RASTER_REVSYNC + constants define the standard sync words at the beginning of each CUPS + raster file.

+

Raster Stream Modes

+

The CUPS_RASTER_READ and CUPS_RASTER_WRITE + constants are used with the +cupsRasterOpen() function to specify a stream for reading or + writing.

+

Raster Boolean Constants

+

The CUPS_FALSE and CUPS_TRUE constants + represent boolean values in the page header.

+

Raster Jog Values

+

The cups_jog_t enumeration defines constants for the Jog + page device dictionary variable:

+
    +
  • CUPS_JOG_NONE - Do no jogging
  • +
  • CUPS_JOG_FILE - Jog pages after each file
  • +
  • CUPS_JOG_JOB - Jog pages after each job
  • +
  • CUPS_JOG_SET - Jog pages after each set of jobs
  • +
+

Raster Orientation Values

+

The cups_orient_t enumeration defines constants for the + Orientation page device dictionary variable:

+
    +
  • CUPS_ORIENT_0 - Portrait orientation
  • +
  • CUPS_ORIENT_90 - Landscape orientation
  • +
  • CUPS_ORIENT_180 - Reverse-portrait orientation
  • +
  • CUPS_ORIENT_270 - Reverse-landscape orientation
  • +
+

Raster CutMedia Values

+

The cups_cut_t enumeration defines constants for the + CutMedia page device dictionary variable:

+
    +
  • CUPS_CUT_NONE - Do no jogging
  • +
  • CUPS_CUT_FILE - Cut pages after each file
  • +
  • CUPS_CUT_JOB - Cut pages after each job
  • +
  • CUPS_CUT_SET - Cut pages after each set of jobs
  • +
  • CUPS_CUT_PAGE - Cut each page
  • +
+

Raster AdvanceMedia Values

+

The cups_advance_t enumeration defines constants for the + AdvanceMedia page device dictionary variable:

+
    +
  • CUPS_ADVANCE_NONE - Do no jogging
  • +
  • CUPS_ADVANCE_FILE - Advance media after each file
  • +
  • CUPS_ADVANCE_JOB - Advance media after each job
  • +
  • CUPS_ADVANCE_SET - Advance media after each set of jobs
  • +
  • CUPS_ADVANCE_PAGE - Advance media for each page
  • +
+

Raster LeadingEdge Values

+

The cups_edge_t enumeration defines constants for the + LeadingEdge page device dictionary variable:

+
    +
  • CUPS_EDGE_TOP - The top of the media is the leading + edge
  • +
  • CUPS_EDGE_RIGHT - The right of the media is the leading + edge
  • +
  • CUPS_EDGE_BOTTOM - The bottom of the media is the + leading edge
  • +
  • CUPS_EDGE_LEFT - The left of the media is the leading + edge
  • +
+

Raster Color Order Values

+

The cups_order_t enumeration defines the possible color + value orderings:

+
    +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK
  • +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK
  • +
  • CUPS_ORDER_PLANAR - CCC ... MMM ... YYY ... KKK ...
  • +
+

Raster Colorspace Values

+

The cups_cspace_t enumeration defines the possible + colorspaces:

+
    +
  • CUPS_CSPACE_W - White (luminance)
  • +
  • CUPS_CSPACE_RGB - Red, green, blue
  • +
  • CUPS_CSPACE_RGBA - Red, green, blue, alpha
  • +
  • CUPS_CSPACE_K - Black
  • +
  • CUPS_CSPACE_CMY - Cyan, magenta, yellow
  • +
  • CUPS_CSPACE_YMC - Yellow, magenta, cyan
  • +
  • CUPS_CSPACE_CMYK - Cyan, magenta, yellow, black
  • +
  • CUPS_CSPACE_YMCK - Yellow, magenta, cyan, black
  • +
  • CUPS_CSPACE_KCMY - Black, cyan, magenta, yellow
  • +
  • CUPS_CSPACE_KCMYcm - Black, cyan, magenta, yellow, + light cyan, light magenta
  • +
  • CUPS_CSPACE_GMCK - Metallic yellow (gold), metallic + magenta, metallic cyan, black
  • +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), metallic + magenta, metallic cyan, metallic grey (silver)
  • +
  • CUPS_CSPACE_WHITE - White pigment (black as white + pigment)
  • +
  • CUPS_CSPACE_GOLD - Gold foil (black as gold foil)
  • +
  • CUPS_CSPACE_SILVER - Silver foil (black as silver foil)
  • +
+

C - Structures

+

This appendix describes all of the structures that are defined by the + CUPS API.

+

CUPS Structures

+

CUPS Destinations

+

The CUPS destination structure (cups_dest_t) contains + information on a specific destination or instance: +

+ + + + + + + + +
MemberTypeDescription
namechar *The name of the printer or class.
instancechar *The instance of the printer or + class; NULL for the primary instance.
is_defaultint1 if the destination is set as + the default, 0 otherwise.
num_optionsintThe number of options associated + with this destination.
optionscups_option_t * +The options associated with this destination.
+
+

+

CUPS Jobs

+

The CUPS job structure (cups_job_t) contains information + on a specific job: +

+ + + + + + + + + + + + + + + +
MemberTypeDescription
idintThe job ID for this job.
destchar *The destination for this job + (printer or class name).
titlechar *The job-name for this job (title).
userchar *The job-originating-user-name for + this job (username).
formatchar *The document-format for this job + (MIME type string).
stateipp_jstateThe current state of the job.
sizeintThe size of this job in kilobytes.
priorityintThe priority of this job from 1 to + 100 (50 is normal).
completed_timetime_tThe time the job was + completed, or 0 if not yet completed.
creation_timetime_tThe time the job was + queued.
processing_timetime_tThe time the job started + printing.
+
+

+

CUPS Messages

+

The CUPS messages structure (cups_lang_t) contains the + character set, locale name, and messages array: +

+ + + + + + + + + +
MemberTypeDescription
nextcups_lang_t *Pointer to the next messages + structure in memory.
usedintThe number of active users of this + messages structure.
encodingcups_encoding_tThe character encoding + of the message strings.
languagechar [16]The language/locale name.
messageschar *[]The array of message strings.
+
+

+

CUPS Options

+

The CUPS option structure (cups_option_t) contains the + option name and string value: +

+ + + + + +
MemberTypeDescription
namechar *The name of the option.
valuechar *The string value of the option.
+
+

+

Networking Structures

+

HTTP State

+

The HTTP state structure (http_t) contains the current + state of a HTTP request or response: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
fdintThe socket for the HTTP connection.
blockingint1 if the HTTP functions should + block, 0 if not.
errorintThe last OS error that occurred on the + socket.
activitytime_tThe last time the HTTP + connection was used.
statehttp_state_tThe current HTTP + request/response state.
statusintThe last HTTP status seen.
versionhttp_version_tThe HTTP protocol version + in use.
keep_alivehttp_keep_alive_tWhether or not to + use Keep-Alive
hostaddrstruct sockaddr_inThe IPv4 address of + the HTTP server.
hostnamechar []The hostname of the HTTP + server.
fieldschar [][]The string values of all HTTP + request/response fields.
datachar *Current byte in data buffer.
data_encodinghttp_encoding_tThe transfer + encoding for the request/response.
data_remainingintThe number of bytes remaining + in the current request, response, or chunk.
usedintThe number of bytes that are used in + the buffer.
bufferchar []The read/write buffer.
auth_typeintThe type of authentication in use.
md5_statemd5_state_tThe current MD5 digest + state.
noncechar []The nonce value for Digest + authentication.
nonce_countintThe nonce count value.
tlsvoid *A pointer to private encryption data.
encryptionhttp_encryption_tThe current + encryption mode.
+
+

+

IPP State

+

The IPP state structure (ipp_t) contains the current + state of a IPP request or response: +

+ + + +
MemberTypeDescription
+
+

+

Raster Structures

+

Raster Page Header

+

The raster page header (cups_raster_header_t) consists + of the PostScript page device dictionary for the page: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
MediaClasschar[64]The media class name
MediaColorchar[64]The media color name
MediaTypechar[64]The media type name
OutputTypechar[64]The output type name
AdvanceDistanceunsignedThe distance to advance + the media in points
AdvanceMediacups_adv_tWhen to advance the + media
Collatecups_bool_tWhether or not to produce + collated copies
CutMediacups_cut_tWhen to cut the media
Duplexcups_bool_tWhether or not to print on + both sides of the paper
HWResolutionunsigned[2]The resolution of the + page image in pixels per inch; the HWResolution[0] represents the + horizontal resolution and HWResolution[1] represents the vertical + resolution
ImagingBoundingBoxunsigned[4]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)
InsertSheetcups_bool_tWhether or not to insert + a sheet before this page
Jogcups_jog_tWhen to jog copies of the page
LeadingEdgecups_edge_tThe leading edge of the + page
Marginsunsigned[2]The lower-lefthand margin of + the page in points
ManualFeedcups_bool_tWhether or not to + manually feed the page
MediaPositionunsignedThe input slot number to + use
MediaWeightunsignedThe weight of the output + media in grams/m2
MirrorPrintcups_bool_tWhether or not to mirror + the print
NegativePrintcups_bool_tWhether or not to + invert the print
NumCopiesunsignedThe number of copies to + produce
Orientationcups_orient_tThe orientation of the + page image
OutputFaceUpcups_bool_tWhether or not to + output the page face up
PageSizeunsigned[2]The width and height of the + page in points
Separationscups_bool_tWhether or not to output + separations
TraySwitchcups_bool_tWhether or not to + automatically switch trays for the requested media size/type
Tumblecups_bool_tWhether or not to rotate the + back side of the page
cupsWidthunsignedThe width of the page image + in pixels
cupsHeightunsignedThe height of the page image + in pixels
cupsMediaTypeunsignedThe device-specific media + type code
cupsBitsPerColorunsignedThe number of bits per + color
cupsBitsPerPixelunsignedThe number of bits per + pixel
cupsBytesPerLineunsignedThe number of bytes + per line of image data
cupsColorOrdercups_order_tThe order of color + values
cupsColorSpacecups_cspace_tThe type of color + values
cupsCompressionunsignedThe device-specific + compression code
cupsRowCountunsignedThe device-specific row + count
cupsRowFeedunsignedThe device-specific row + feed
cupsRowStepunsignedThe device-specific row + step
+
+

+

D - Functions

+

This appendix provides a reference for all of the CUPS API functions. + +

+

cupsAddDest()

+

Usage

+
+int
+cupsAddDest(const char  *name,
+            const char  *instance,
+            int         num_dests,
+	    cups_dest_t **dests);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
nameThe name of the destination.
instanceThe instance of the destination, or NULL for + the primary instance.
num_destsThe number of destinations in the array.
destA pointer to the destination array pointer.
+
+

Returns

+

The new number of destinations in the array.

+

Description

+

cupsAddDest() adds the named destination to the + destination array if it does not already exist.

+

Example

+
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+
+
+num_dests = cupsAddDests("foo", "bar", num_dests, &dests);
+
+

See Also

+

cupsFreeDests(), + cupsGetDest(), +cupsGetDests() + +

+

cupsAddOption()

+

Usage

+
+int
+cupsAddOption(const char    *name,
+              const char    *value,
+              int           num_options,
+	      cups_option_t **options);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
nameThe name of the option.
valueThe value of the option.
num_optionsNumber of options currently in the array.
optionsPointer to the options array.
+
+

Returns

+

The new number of options.

+

Description

+

cupsAddOption() adds an option to the specified array.

+

Example

+
+#include <cups.h>
+
+...
+
+/* Declare the options array */
+int           num_options;
+cups_option_t *options;
+
+/* Initialize the options array */
+num_options = 0;
+options     = (cups_option_t *)0;
+
+/* Add options using cupsAddOption() */
+num_options = cupsAddOption("media", "letter", num_options, &options);
+num_options = cupsAddOption("resolution", "300dpi", num_options, &options);
+
+

See Also

+ cupsEncodeOptions(), + cupsFreeOptions(), +cupsGetOption(), +cupsParseOptions() + + +

cupsCancelJob()

+

Usage

+
+int
+cupsCancelJob(const char *dest,
+              int        job);
+
+

Arguments

+
+ + + + +
ArgumentDescription
destPrinter or class name
jobJob ID
+
+

Returns

+

1 on success, 0 on failure. On failure the error can be found by + calling cupsLastError().

+

Description

+

cupsCancelJob() cancels the specifies job.

+

Example

+
+#include <cups.h>
+
+cupsCancelJob("LaserJet", 1);
+
+

See Also

+

cupsLastError(), + cupsPrintFile(), +cupsPrintFiles() + +

+

cupsDoFileRequest()

+

Usage

+
+ipp_t *
+cupsDoFileRequest(http_t     *http,
+                  ipp_t      *request,
+                  const char *resource,
+		  const char *filename);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
filenameFile to send with POST request (NULL + pointer if none.)
+
+

Returns

+

IPP response data or NULL if the request fails. On + failure the error can be found by calling +cupsLastError().

+

Description

+

cupsDoFileRequest() 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.

+

Example

+
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_PRINT_FILE;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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 != NULL ? language->language : "C");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+             NULL, "ipp://hostname/resource");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+             NULL, cupsUser());
+
+/* Do the request... */
+response = cupsDoFileRequest(http, request, "/resource", "filename.txt");
+
+

See Also

+

cupsLangDefault(), + cupsLangEncoding(), +cupsUser(), httpConnect() +, ippAddString(), + ippNew() + +

+

cupsDoRequest()

+

Usage

+
+ipp_t *
+cupsDoRequest(http_t *http,
+              ipp_t *request,
+              const char *resource);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
+
+

Returns

+

IPP response data or NULL if the request fails. On + failure the error can be found by calling +cupsLastError().

+

Description

+

cupsDoRequest() 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.

+

Example

+
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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 != NULL ? language->language : "C");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+             NULL, "ipp://hostname/resource");
+
+/* Do the request... */
+response = cupsDoRequest(http, request, "/resource");
+
+

See Also

+

cupsLangDefault(), + cupsLangEncoding(), +cupsUser(), httpConnect() +, ippAddString(), + ippNew() + +

+

cupsEncodeOptions()

+

Usage

+
+void
+cupsEncodeOptions(ipp_t         *ipp,
+                  int           num_options,
+		  cups_option_t *options);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ippThe IPP request.
num_optionsThe number of options.
optionsThe options.
+
+

Description

+

cupsEncodeOptions() encodes all of the options in the + specified array as IPP attributes and adds them to the IPP request.

+

Example

+
+#include <cups/cups.h>
+
+ipp_t         *ipp;
+int           num_options;
+cups_option_t *options;
+
+
+cupsEncodeOptions(ipp, num_options, options);
+
+

See Also

+

cupsAddOption(), + cupsParseOptions(), ippNew() + + +

+

cupsEncryption()

+

Usage

+
+http_encryption_t
+cupsEncryption(void);
+
+

Returns

+

The current encryption setting.

+

Description

+

cupsEncryption() returns the current encryption setting + for IPP requests such as printing.

+

Example

+
+#include <cups/cups.h>
+
+http_t *http;
+
+printf("The current encryption setting is %d.\n", cupsEncryption());
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+

See Also

+

cupsServer(), + httpConnectEncrypt(), +ippPort() + +

+

cupsFreeDests()

+

Usage

+
+void
+cupsFreeDests(int         num_dests,
+              cups_dest_t *dests);
+
+

Arguments

+
+ + + + +
ArgumentDescription
num_destsThe number of destinations in the array.
destsThe destination array.
+
+

Description

+

cupsFreeDests() frees a destination array that was + created using cupsGetDests().

+

Example

+
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&dests);
+dest      = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+  printf("The default destination is %s\n", dest->name);
+else
+  puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+
+

See Also

+

cupsGetDest(), + cupsGetDests() + +

+

cupsFreeJobs()

+

Usage

+
+void
+cupsFreeJobs(int        num_jobs,
+             cups_job_t *jobs);
+
+

Arguments

+
+ + + + +
ArgumentDescription
num_jobsThe number of jobs.
jobsThe job array.
+
+

Description

+

cupsFreeJobs() frees an array of print jobs created by + the cupsGetJobs() function.

+

Example

+
+#include <cups/cups.h>
+
+int        i;
+int        num_jobs;
+cups_job_t *jobs;
+
+
+num_jobs = cupsGetJobs(&jobs, NULL, 0, 0);
+
+printf("%d active job(s):\n", num_jobs);
+for (i = 0; i < num_jobs; i ++)
+  printf("%-16.16s %-6d %-12.12s %s (%s)\n", jobs[i].dest, jobs[i].id,
+         jobs[i].user, jobs[i].title,
+	 jobs[i].state != IPP_JOB_PENDING ? "printing" : "pending");
+
+cupsFreeJobs(num_jobs, jobs);
+
+

See Also

+

cupsGetJobs(), + cupsGetDests() + +

+

cupsFreeOptions()

+

Usage

+
+void
+cupsFreeOptions(int           num_options,
+                cups_option_t *options);
+
+

Arguments

+
+ + + + +
ArgumentDescription
num_optionsNumber of options in array.
optionsPointer to options array.
+
+

Description

+

cupsFreeOptions() frees all memory associated with the + option array specified.

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+
+

See Also

+

cupsAddOption(), + cupsEncodeOptions(), +cupsGetOption(), +cupsMarkOptions(), +cupsParseOptions() + +

+

cupsGetClasses()

+

Usage

+
+int
+cupsGetClasses(char ***classes);
+
+

Arguments

+
+ + + +
ArgumentDescription
classesPointer to character pointer array.
+
+

Returns

+

The number of printer classes available.

+

Description

+

cupsGetClasses() gets a list of the available printer + classes. The returned array should be freed using the free() + when it is no longer needed.

+

Example

+
+#include <cups/cups.h>
+
+int  i;
+int  num_classes;
+char **classes;
+
+...
+
+num_classes = cupsGetClasses(
+
+...
+
+if (num_classes > 0)
+{
+  for (i = 0; i < num_classes; i ++)
+    free(classes[i]);
+
+  free(classes);
+}
+
+

See Also

+

cupsGetDefault(), + cupsGetPrinters() + +

+

cupsGetDefault()

+

Usage

+
+const char *
+cupsGetDefault(void);
+
+

Returns

+

A pointer to the default destination.

+

Description

+

cupsGetDefault() 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.

+

Example

+
+#include <cups/cups.h>
+
+printf("The default destination is %s\n", cupsGetDefault());
+
+

See Also

+

cupsGetClasses(), + cupsGetPrinters() + +

+

cupsGetDest()

+

Usage

+
+cups_dest_t *
+cupsGetDest(const char  *name,
+            const char  *instance,
+            int         num_dests,
+            cups_dest_t *dests);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
nameThe name of the destination, or NULL for the + default destination.
instanceThe instance of the destination, or NULL for + the primary instance.
num_destsThe number of destinations.
destsThe destination array.
+
+

Returns

+

A pointer to the specified destination, or NULL if none exists.

+

Description

+

cupsGetDest() finds the specified destination in the + array of destinations created by the cupsGetDests() + function.

+

Example

+
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&dests);
+dest      = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+  printf("The default destination is %s\n", dest->name);
+else
+  puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+
+

See Also

+

cupsGetDests(), + cupsGetJobs() + +

+

cupsGetDests()

+

Usage

+
+int
+cupsGetDests(cups_dest_t **dests);
+
+

Arguments

+
+ + + +
ArgumentDescription
destsA pointer to a destination array pointer.
+
+

Returns

+

The number of available destinations.

+

Description

+

cupsGetDests() creates an array of available + destinations that the user can print to. The array should be freed + using the cupsFreeDests() function.

+

Example

+
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&dests);
+dest      = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+  printf("The default destination is %s\n", dest->name);
+else
+  puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+
+

See Also

+

cupsFreeDests(), + cupsGetDest(), +cupsGetJobs() + +

+

cupsGetJobs()

+

Usage

+
+int
+cupsGetJobs(cups_job_t **jobs,
+            const char *dest,
+            int        myjobs,
+            int        completed);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
jobsA pointer to the job array pointer.
destThe destination name, or NULL if jobs for all + destinations are requested.
myjobs1 if only those jobs submitted by the current +cupsUser() should be returned, 0 for jobs submitted by all users.
completed1 if only completed jobs should be returned, 0 + if only pending/processing jobs should be returned.
+
+

Returns

+

The number of jobs.

+

Description

+

cupsGetJobs() creates an array of print jobs based on + the arguments supplied in the function call. The returned array should + be freed using the cupsFreeJobs() function.

+

Example

+
+#include <cups/cups.h>
+
+int        i;
+int        num_jobs;
+cups_job_t *jobs;
+
+
+num_jobs = cupsGetJobs(&jobs, NULL, 0, 0);
+
+printf("%d active job(s):\n", num_jobs);
+for (i = 0; i < num_jobs; i ++)
+  printf("%-16.16s %-6d %-12.12s %s (%s)\n", jobs[i].dest, jobs[i].id,
+         jobs[i].user, jobs[i].title,
+	 jobs[i].state != IPP_JOB_PENDING ? "printing" : "pending");
+
+cupsFreeJobs(num_jobs, jobs);
+
+

See Also

+

cupsFreeJobs(), + cupsGetDests() + +

+

cupsGetOption()

+

Usage

+
+const char *
+cupsGetOption(const char    *name,
+              int           num_options,
+              cups_option_t *options);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
nameThe name of the option.
num_optionsThe number of options in the array.
optionsThe options array.
+
+

Returns

+

A pointer to the option values or NULL if the option is + not defined.

+

Description

+

cupsGetOption() returns the first occurrence of the + named option. If the option is not included in the options array then a + NULL pointer is returned.

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+const char    *media;
+
+...
+
+media = cupsGetOption("media", num_options, options);
+
+

See Also

+

cupsAddOption(), + cupsEncodeOptions(), +cupsFreeOptions(), +cupsMarkOptions(), +cupsParseOptions() + +

+

cupsGetPassword()

+

Usage

+
+const char *
+cupsGetPassword(const char *prompt);
+
+

Arguments

+
+ + + +
ArgumentDescription
promptThe prompt to display to the user.
+
+

Returns

+

A pointer to the password that was entered or NULL if no + password was entered.

+

Description

+

cupsGetPassword() displays the prompt string and asks + the user for a password. The password text is not echoed to the user.

+

Example

+
+#include <cups/cups.h>
+
+char *password;
+
+...
+
+password = cupsGetPassword("Please enter a password:");
+
+

See Also

+

cupsServer(), + cupsSetPasswordCB(), +cupsSetServer(), cupsSetUser() +, cupsUser() + +

+

cupsGetPPD()

+

Usage

+
+const char *
+cupsGetPPD(const char *printer);
+
+

Arguments

+
+ + + +
ArgumentDescription
printerThe name of the printer.
+
+

Returns

+

The name of a temporary file containing the PPD file or NULL + if the printer cannot be located or does not have a PPD file.

+

Description

+

cupsGetPPD() gets a copy of the PPD file for the named + printer. The printer name can be of the form "printer" or + "printer@hostname".

+

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 cupsGetPPD().

+

Example

+
+#include <cups/cups.h>
+
+char *ppd;
+
+...
+
+ppd = cupsGetPPD("printer@hostname");
+
+...
+
+unlink(ppd);
+
+ + +

cupsGetPrinters()

+

Usage

+
+int
+cupsGetPrinters(char ***printers);
+
+

Arguments

+
+ + + +
ArgumentDescription
printersPointer to character pointer array.
+
+

Returns

+

The number of printer printers available.

+

Description

+

cupsGetPrinters() gets a list of the available printers. + The returned array should be freed using the free() when + it is no longer needed.

+

Example

+
+#include <cups/cups.h>
+
+int  i;
+int  num_printers;
+char **printers;
+
+...
+
+num_printers = cupsGetPrinters(
+
+...
+
+if (num_printers > 0)
+{
+  for (i = 0; i < num_printers; i ++)
+    free(printers[i]);
+
+  free(printers);
+}
+
+

See Also

+

cupsGetClasses() + cupsGetDefault() + +

+

cupsLangDefault()

+

Usage

+
+const char *
+cupsLangDefault(void);
+
+

Returns

+

A pointer to the default language structure.

+

Description

+

cupsLangDefault() returns a language structure for the + default language. The default language is defined by the LANG + environment variable. If the specified language cannot be located then + the POSIX (English) locale is used.

+

Call cupsLangFree() to free any memory associated with + the language structure when you are done.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+language = cupsLangDefault();
+
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangEncoding(), + cupsLangFlush(), +cupsLangFree(), cupsLangGet() +, cupsLangString() + +

+

cupsLangEncoding()

+

Usage

+
+char *
+cupsLangEncoding(cups_lang_t *language);
+
+

Arguments

+
+ + + +
ArgumentDescription
languageThe language structure.
+
+

Returns

+

A pointer to the encoding string.

+

Description

+

cupsLangEncoding() returns the language encoding used + for the specified language, e.g. "iso-8859-1", "utf-8", etc.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *encoding;
+...
+
+language = cupsLangDefault();
+encoding = cupsLangEncoding(language);
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), + cupsLangFlush(), +cupsLangFree(), cupsLangGet() +, cupsLangString() + +

+

cupsLangFlush()

+

Usage

+
+void
+cupsLangFlush(void);
+
+

Description

+

cupsLangFlush() frees all language structures that have + been allocated.

+

Example

+
+#include <cups/language.h>
+
+...
+
+cupsLangFlush();
+
+

See Also

+

cupsLangDefault(), + cupsLangEncoding(), +cupsLangFree(), cupsLangGet() +, cupsLangString() + +

+

cupsLangFree()

+

Usage

+
+void
+cupsLangFree(cups_lang_t *language);
+
+

Arguments

+
+ + + +
ArgumentDescription
languageThe language structure to free.
+
+

Description

+

cupsLangFree() frees the specified language structure.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), + cupsLangEncoding(), +cupsLangFlush(), cupsLangGet() +, cupsLangString() + +

+

cupsLangGet()

+

Usage

+
+cups_lang_t *
+cupsLangGet(const char *name);
+
+

Arguments

+
+ + + +
ArgumentDescription
nameThe name of the locale.
+
+

Returns

+

A pointer to a language structure.

+

Description

+

cupsLangGet() returns a language structure for the + specified locale. If the locale is not defined then the POSIX (English) + locale is substituted.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+
+...
+
+language = cupsLangGet("fr");
+
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), + cupsLangEncoding(), +cupsLangFlush(), cupsLangFree() +, cupsLangString() + +

+

cupsLangString()

+

Usage

+
+char *
+cupsLangString(cups_lang_t *language,
+               int         message);
+
+

Arguments

+
+ + + + +
ArgumentDescription
languageThe language to query.
messageThe message number.
+
+

Returns

+

A pointer to the message string or NULL if the message + is not defined.

+

Description

+

cupsLangString() returns a pointer to the specified + message string in the specified language.

+

Example

+
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *s;
+...
+
+language = cupsLangGet("fr");
+
+s = cupsLangString(language, CUPS_MSG_YES);
+
+...
+
+cupsLangFree(language);
+
+

See Also

+

cupsLangDefault(), + cupsLangEncoding(), +cupsLangFlush(), cupsLangFree() +, cupsLangGet() + +

+

cupsLastError()

+

Usage

+
+ipp_status_t
+cupsLastError(void);
+
+

Returns

+

An enumeration containing the last IPP error.

+

Description

+

cupsLastError() returns the last IPP error that + occurred. If no error occurred then it will return IPP_OK + or IPP_OK_CONFLICT.

+

Example

+
+#include <cups/cups.h>
+
+ipp_status_t status;
+
+...
+
+status = cupsLastError();
+
+

See Also

+

cupsCancelJob(), + cupsPrintFile() + +

+

cupsMarkOptions()

+

Usage

+
+int
+cupsMarkOptions(ppd_file_t    *ppd,
+                int           num_options,
+                cups_option_t *options);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ppdThe PPD file to mark.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+
+

Returns

+

The number of conflicts found.

+

Description

+

cupsMarkOptions() marks options in the PPD file. It also + handles mapping of IPP option names and values to PPD option names.

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+ppd_file_t    *ppd;
+
+...
+
+cupsMarkOptions(ppd, num_options, options);
+
+

See Also

+

cupsAddOption(), + cupsFreeOptions(), +cupsGetOption(), +cupsParseOptions() + +

+

cupsParseOptions()

+

Usage

+
+int
+cupsParseOptions(const char    *arg,
+                 int           num_options,
+                 cups_option_t **options);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
argThe string containing one or more options.
num_optionsThe number of options in the options array.
optionsA pointer to the options array pointer.
+
+

Returns

+

The new number of options in the array.

+

Description

+

cupsParseOptions() parses the specifies string for one + or more options of the form "name=value", "name", or "noname". It can + be called multiple times to combine the options from several strings.

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+num_options = 0;
+options     = (cups_option_t *)0;
+num_options = cupsParseOptions(argv[5], num_options, &options);
+
+

See Also

+

cupsAddOption(), + cupsFreeOptions(), +cupsGetOption(), +cupsMarkOptions() + +

+

cupsPrintFile()

+

Usage

+
+int
+cupsPrintFile(const char    *printer,
+              const char    *filename,
+              const char    *title,
+	      int           num_options,
+	      cups_option_t *options);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
printerThe printer or class to print to.
filenameThe file to print.
titleThe job title.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+
+

Returns

+

The new job ID number or 0 on error.

+

Description

+

cupsPrintFile() 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 cupsLastError().

+

Example

+
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+int           jobid;
+
+...
+
+jobid = cupsPrintFile("printer@hostname", "filename.ps", "Job Title",
+                      num_options, options);
+
+

See Also

+

cupsCancelJob(), + cupsLastError(), +cupsPrintFiles() + +

+

cupsPrintFiles()

+

Usage

+
+int
+cupsPrintFiles(const char    *printer,
+               int           num_files,
+               const char    **files,
+               const char    *title,
+	       int           num_options,
+	       cups_option_t *options);
+
+

Arguments

+
+ + + + + + + + + +
ArgumentDescription
printerThe printer or class to print to.
num_filesThe number of files to print.
filesThe files to print.
titleThe job title.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+
+

Returns

+

The new job ID number or 0 on error.

+

Description

+

cupsPrintFiles() 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 cupsLastError().

+

Example

+
+#include <cups/cups.h>
+
+int           num_files;
+const char    *files[100];
+int           num_options;
+cups_option_t *options;
+int           jobid;
+
+...
+
+jobid = cupsPrintFiles("printer@hostname", num_files, files,
+                       "Job Title", num_options, options);
+
+

See Also

+

cupsCancelJob(), + cupsLastError(), +cupsPrintFile() + +

+

cupsRasterClose()

+

Usage

+
+void
+cupsRasterClose(cups_raster_t *ras);
+
+

Arguments

+
+ + + +
ArgumentDescription
rasThe raster stream to close.
+
+

Description

+

cupsRasterClose() closes the specified raster stream.

+

Example

+
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+cupsRasterClose(ras);
+
+

See Also

+

cupsRasterOpen(), + cupsRasterReadHeader(), + cupsRasterReadPixels(), + cupsRasterWriteHeader(), + cupsRasterWritePixels() + +

+

cupsRasterOpen()

+

Usage

+
+cups_raster_t *
+cupsRasterOpen(int         fd,
+               cups_mode_t mode);
+
+

Arguments

+
+ + + + +
ArgumentDescription
fdThe file descriptor to use.
modeThe mode to use; CUPS_RASTER_READ or +CUPS_RASTER_WRITE.
+
+

Returns

+

A pointer to a raster stream or NULL if there was an + error.

+

Description

+

cupsRasterOpen() opens a raster stream for reading or + writing.

+

Example

+
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+ras = cupsRasterOpen(0, CUPS_RASTER_READ);
+
+

See Also

+

cupsRasterClose(), + cupsRasterReadHeader(), + cupsRasterReadPixels(), + cupsRasterWriteHeader(), + cupsRasterWritePixels() + +

+

cupsRasterReadHeader()

+

Usage

+
+unsigned
+cupsRasterReadHeader(cups_raster_t      *ras,
+                     cups_page_header_t *header);
+
+

Arguments

+
+ + + + +
ArgumentDescription
rasThe raster stream to read from.
headerA pointer to a page header structure to read + into.
+
+

Returns

+

1 on success, 0 on EOF or error.

+

Description

+

cupsRasterReadHeader() reads a page header from the + specified raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+

See Also

+

cupsRasterClose(), + cupsRasterOpen(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

+

cupsRasterReadPixels()

+

Usage

+
+unsigned
+cupsRasterReadPixels(cups_raster_t *ras,
+                     unsigned char *pixels,
+		     unsigned      length);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
rasThe raster stream to read from.
pixelsThe pointer to a pixel buffer.
lengthThe number of bytes of pixel data to read.
+
+

Returns

+

The number of bytes read or 0 on EOF or error.

+

Description

+

cupsRasterReadPixels() reads pixel data from the + specified raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+

See Also

+

cupsRasterClose(), + cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + +

+

cupsRasterWriteHeader()

+

Usage

+
+unsigned
+cupsRasterWriteHeader(cups_raster_t      *ras,
+                      cups_page_header_t *header);
+
+

Arguments

+
+ + + + +
ArgumentDescription
rasThe raster stream to write to.
headerA pointer to the page header to write.
+
+

Returns

+

1 on success, 0 on error.

+

Description

+

cupsRasterWriteHeader() writes the specified page header + to a raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+

See Also

+

cupsRasterClose(), + cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWritePixels() + +

+

cupsRasterWritePixels()

+

Usage

+
+unsigned
+cupsRasterWritePixels(cups_raster_t *ras,
+                      unsigned char *pixels,
+		      unsigned      length);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
rasThe raster stream to write to.
pixelsThe pixel data to write.
lengthThe number of bytes to write.
+
+

Returns

+

The number of bytes written.

+

Description

+

cupsRasterWritePixels() writes the specified pixel data + to a raster stream.

+

Example

+
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+

See Also

+

cupsRasterClose(), + cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader() + +

+

cupsServer()

+

Usage

+
+const char *
+cupsServer(void);
+
+

Returns

+

A pointer to the default server name.

+

Description

+

cupsServer() 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 cupsServer().

+

The default server is determined from the following locations:

+
    +
  1. The CUPS_SERVER environment variable,
  2. +
  3. The ServerName directive in the client.conf + file,
  4. +
  5. The default host, "localhost".
  6. +
+

Example

+
+#include <cups/cups.h>
+
+const char *server;
+
+server = cupsServer();
+
+

See Also

+

cupsGetPassword(), + cupsSetPasswordCB(), +cupsSetServer(), cupsSetUser() +, cupsUser() + +

+

cupsSetDests()

+

Usage

+
+void
+cupsSetDests(int         num_dests,
+             cups_dest_t *dests);
+
+

Arguments

+
+ + + + +
ArgumentDescription
num_destsNumber of destinations.
destsArray of destinations.
+
+

Description

+

cupsSetDests() saves the destination array to disk. If + the current UID is 0, the destinations are saved in the + /etc/cups/lpoptions file, otherwise they are saved in the + ~/.lpoptions file. This function is typically used to save the + default options and instances that are set by the user.

+

Example

+
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+
+...
+
+cupsSetDests(num_dests, dests);
+
+

See Also

+

cupsGetDests() + +

+

cupsSetEncryption()

+

Usage

+
+void
+cupsSetEncryption(http_encryption_t encryption);
+
+

Arguments

+
+ + + +
ArgumentDescription
encryptionThe type of encryption to use.
+
+

Description

+

cupsSetEncryption() sets the default type of encryption + to use when connecting with the print server.

+

Example

+
+#include <cups/cups.h>
+
+cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+

See Also

+

cupsEncryption() + +

+

cupsSetPasswordCB()

+

Usage

+
+void
+cupsSetPasswordCB(const char *(*cb)(const char *prompt));
+
+

Arguments

+
+ + + +
ArgumentDescription
cbThe password callback function.
+
+

Description

+

cupsSetPasswordCB() 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 +NULL if the user did not enter a password string or a pointer to + the password string otherwise.

+

Example

+
+#include <cups/cups.h>
+
+const char *
+my_password_cb(const char *prompt)
+{
+  return (getpass(prompt));
+}
+
+...
+
+char *password;
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+password = cupsGetPassword("Please enter a password:");
+
+

See Also

+

cupsServer(), + cupsSetServer(), +cupsSetUser(), cupsUser() + + +

+

cupsSetServer()

+

Usage

+
+void
+cupsSetServer(const char *server);
+
+

Arguments

+
+ + + +
ArgumentDescription
serverThe default server to use.
+
+

Description

+

cupsSetServer() sets the default server to use for the + CUPS API. If the server argument is NULL, the + default server is used.

+

Example

+
+#include <cups/cups.h>
+
+cupsSetServer("foo.bar.com");
+
+

See Also

+

cupsServer(), + cupsSetPasswordCB(), +cupsSetUser(), cupsUser() + + +

+

cupsSetUser()

+

Usage

+
+void
+cupsSetUser(const char *user);
+
+

Arguments

+
+ + + +
ArgumentDescription
userThe user name string to use.
+
+

Description

+

cupsSetUser() sets the default user name for + authentication. If the user argument is NULL + then the current login user is used.

+

Example

+
+#include <cups/cups.h>
+
+...
+
+cupsSetUser("root");
+
+

See Also

+

cupsServer(), + cupsSetPasswordCB(), +cupsSetServer(), cupsUser() + + +

+

cupsTempFd()

+

Usage

+
+int
+cupsTempFd(char *filename,
+           int  length);
+
+

Arguments

+
+ + + + +
ArgumentDescription
filenameThe character string to hold the temporary + filename.
lengthThe size of the filename string in bytes.
+
+

Returns

+

A file descriptor open for reading and writing.

+

Description

+

cupsTempFd() create a temporary filename in the + /var/tmp directory or the directory specified by the TMPDIR + environment variable.

+

Example

+
+#include <cups/cups.h>
+
+int  fd;
+char filename[256];
+
+fd = cupsTempFd(filename, sizeof(filename));
+
+

See Also

+

cupsTempFile() + +

+

cupsTempFile()

+

Usage

+
+char *
+cupsTempFile(char *filename,
+             int  length);
+
+

Arguments

+
+ + + + +
ArgumentDescription
filenameThe character string to hold the temporary + filename.
lengthThe size of the filename string in bytes.
+
+

Returns

+

A pointer to filename.

+

Description

+

cupsTempFile() creates a temporary filename in the + /var/tmp directory or the directory specified by the TMPDIR + environment variable.

+

Example

+
+#include <cups/cups.h>
+
+char filename[256];
+
+cupsTempFile(filename, sizeof(filename));
+
+

See Also

+

cupsTempFd() + +

+

cupsUser()

+

Usage

+
+const char *
+cupsUser(void);
+
+

Returns

+

A pointer to the current username or NULL if the user ID + is undefined.

+

Description

+

cupsUser() returns the name associated with the current + user ID as reported by the getuid() system call.

+

Example

+
+#include <cups/cups.h>
+
+const char *user;
+
+user = cupsUser();
+
+

See Also

+

cupsGetPassword(), + cupsServer() + +

+

httpBlocking()

+

Usage

+
+void
+httpBlocking(http_t *http,
+             int    blocking)
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
blocking0 if the connection should be non-blocking, 1 + if it should be blocking
+
+

Description

+

The httpBlocking() 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.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect("server", port);
+httpBlocking(http, 0);
+
+

See Also

+ httpCheck(), + httpConnect() + + +

httpCheck()

+

Usage

+
+int
+httpCheck(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

0 if there is no data pending, 1 otherwise.

+

Description

+

The httpCheck() function checks to see if there is any + data pending on an HTTP connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpCheck(http))
+{
+  ... do something ...
+}
+
+

See Also

+ httpBlocking(), + httpConnect(), httpGets() +, httpRead() + + +

httpClearFields()

+

Usage

+
+void
+httpClearFields(http_t *http)
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Description

+

The httpClearFields() function clears all HTTP request + fields for the HTTP connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpClearFields(http);
+
+

See Also

+ httpConnect(), + httpGetField(), +httpSetField() + + +

httpClose()

+

Usage

+
+void
+httpClose(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Description

+

The httpClose() function closes an active HTTP + connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpClose(http);
+
+

See Also

+ httpConnect() + + +

httpConnect()

+

Usage

+
+http_t *
+httpConnect(const char *hostname,
+            int        port);
+
+

Arguments

+
+ + + + +
ArgumentDescription
hostnameThe name or IP address of the server to connect + to
portThe port number to use
+
+

Returns

+

A pointer to a HTTP connection structure or NULL if the connection + could not be made.

+

Description

+

The httpConnect() function opens a HTTP connection to + the specified server and port.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+

See Also

+ httpClose(), + httpConnectEncrypt(), +httpGet(), httpGets(), + httpPost(), httpRead() +, httpWrite() + + +

httpConnectEncrypt()

+

Usage

+
+http_t *
+httpConnectEncrypt(const char        *hostname,
+                   int               port,
+                   http_encryption_t encryption);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
hostnameThe name or IP address of the server to connect + to
portThe port number to use
encryptionThe level of encryption to use
+
+

Returns

+

A pointer to a HTTP connection structure or NULL if the connection + could not be made.

+

Description

+

The httpConnectEncrypt() function opens a HTTP + connection to the specified server, port, and encryption.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+

See Also

+ httpClose(), + httpConnect(), httpGet() +, httpGets(), + httpPost(), httpRead() +, httpWrite() + + +

httpDecode64()

+

Usage

+
+char *
+httpDecode64(char       *out,
+             const char *in);
+
+

Arguments

+
+ + + + +
ArgumentDescription
outThe output string
inThe input string
+
+

Returns

+

A pointer to the decoded string.

+

Description

+

The httpDecode64() function decodes a base-64 encoded + string to the original string.

+

Example

+
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpDecode64(original_string, encoded_string);
+
+

See Also

+ httpEncode64() + + +

httpDelete()

+

Usage

+
+int
+httpDelete(http_t     *http,
+           const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to delete
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpDelete() function sends a HTTP DELETE request to + the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+

See Also

+ httpConnect(), + httpSetField(), +httpUpdate() + + +

httpEncode64()

+

Usage

+
+char *
+httpEncode64(char       *out,
+             const char *in);
+
+

Arguments

+
+ + + + +
ArgumentDescription
outThe output string
inThe input string
+
+

Returns

+

A pointer to the encoded string.

+

Description

+

The httpEncode64() function decodes a base-64 encoded + string to the original string.

+

Example

+
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpEncode64(encoded_string, original_string);
+
+

See Also

+ httpDecode64() + + +

httpEncryption()

+

Usage

+
+int
+httpEncryption(http_t            *http,
+               http_encryption_t encryption);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection.
encryptionThe desired level of encryption.
+
+

Returns

+

0 on success, -1 on error.

+

Description

+

httpEncryption() sets the encryption level for the HTTP + connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+...
+
+httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+
+

See Also

+

httpConnectEncrypt() + +

+

httpError()

+

Usage

+
+int
+httpError(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

The last error that occurred or 0 if no error has occurred.

+

Description

+

The httpError() function returns the last error that + occurred on the HTTP connection.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpError(http))
+{
+  ... show an error message ...
+}
+
+

See Also

+ httpConnect() + + +

httpFlush()

+

Usage

+
+void
+httpFlush(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Description

+

The httpFlush() function flushes any remaining data left + from a GET or POST operation.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpFlush(http);
+
+

See Also

+ httpConnect(), + + +

httpGet()

+

Usage

+
+int
+httpGet(http_t     *http,
+        const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to get
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpGet() function sends a HTTP GET request to the + server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+
+

See Also

+ httpConnect(), + httpSetField(), +httpUpdate() + + +

httpGets()

+

Usage

+
+char *
+httpGets(char   *line,
+         int    length,
+         http_t *http)
+
+

Arguments

+
+ + + + + +
ArgumentDescription
lineThe string to fill with a line from the HTTP + connection
lengthThe maximum length of the string
httpThe HTTP connection
+
+

Returns

+

A pointer to the string or NULL if no line could be retrieved.

+

Description

+

The httpGets() function is used to read a request line + from the HTTP connection. It is not normally used by a client program.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+char   line[1024];
+
+if (httpGets(line, sizeof(line), http))
+{
+  ... process the line ...
+}
+
+

See Also

+ httpConnect(), + httpUpdate() + + +

httpGetDateString()

+

Usage

+
+const char *
+httpGetDateString(time_t time)
+
+

Arguments

+
+ + + +
ArgumentDescription
timeThe UNIX date/time value
+
+

Returns

+

A pointer to a static string containing the HTTP date/time string for + the specified UNIX time value.

+

Description

+

The httpGetDateString() function generates a date/time + string suitable for HTTP requests from a UNIX time value.

+

Example

+
+#include <cups/http.h>
+
+puts(httpGetDateString(time(NULL)));
+
+

See Also

+ httpGetDateTime() + + +

httpGetDateTime()

+

Usage

+
+time_t
+httpGetDateTime(const char *date)
+
+

Arguments

+
+ + + +
ArgumentDescription
dateThe HTTP date/time string
+
+

Returns

+

A UNIX time value.

+

Description

+

The httpGetDateTime() function converts a HTTP date/time + string to a UNIX time value.

+

Example

+
+#include <cups/http.h>
+
+printf("%d\n", httpGetDateTime("Fri, 30 June 2000 12:34:56 GMT"));
+
+

See Also

+ httpGetDateString() + + +

httpGetField()

+

Usage

+
+const char *
+httpGetField(http_t       *http,
+             http_field_t field);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
+
+

Returns

+

A pointer to the field value string.

+

Description

+

The httpGetField() function returns the current value + for the specified HTTP field.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetField(http, HTTP_FIELD_CONTENT_TYPE));
+
+

See Also

+ httpConnect(), + httpGetSubField(), +httpSetField() + + +

httpGetHostByName()

+

Usage

+
+struct hostent	*
+httpGetHostByName(const char *name);
+
+

Arguments

+
+ + + +
ArgumentDescription
nameName or IP address to lookup.
+
+

Returns

+

NULL if the host could not be found or a pointer to a host entry + containing one or more addresses.

+

Description

+

httpGetHostByName() is a portable wrapper around the +gethostbyname() function which handles both hostnames and IP + addresses.

+

Example

+
+#include <cups/http.h>
+
+struct hostent *hostaddr;
+
+hostaddr = httpGetHostByName("foo.bar.com");
+
+ + +

httpGetLength()

+

Usage

+
+int
+httpGetLength(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection.
+
+

Returns

+

The content length of the response or MAX_INT if chunking is used.

+

Description

+

httpGetLength() returns the content length of a + response.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+...
+
+printf("The length of the response is %d bytes.\n", httpGetLength(http));
+
+

See Also

+

httpGet(), +httpPost() + +

+

httpGetSubField()

+

Usage

+
+const char *
+httpGetSubField(http_t       *http,
+                http_field_t field,
+		const char   *name,
+		char         *value);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
httpThe HTTP connection.
fieldThe HTTP field.
nameThe name of the subfield.
valueThe string to hold the subfield value.
+
+

Returns

+

A pointer to the subfield value string or NULL if it does not exist.

+

Description

+

The httpGetSubField() function returns a subfield value + from the specified HTTP field. The destination string buffer must be at + least HTTP_MAX_VALUE bytes in length.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+char   value[HTTP_MAX_VALUE];
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetSubField(http, HTTP_FIELD_CONTENT_TYPE, "charset", value));
+
+

See Also

+ httpConnect(), + httpGetField(), +httpSetField() + + +

httpHead()

+

Usage

+
+int
+httpHead(http_t     *http,
+         const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to head
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpHead() function sends a HTTP HEAD request to the + server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpHead(http, "/some/uri");
+
+

See Also

+ httpConnect(), + httpSetField(), +httpUpdate() + + +

httpInitialize()

+

Usage

+
+void httpInitialize(void);
+
+

Description

+

The httpInitialize() function initializes the networking + code as needed by the underlying platform. It is called automatically + by the httpConnect() function.

+

Example

+
+#include <cups/http.h>
+
+httpInitialize();
+
+

See Also

+ httpConnect() + + +

httpMD5()

+

Usage

+
+char *
+httpMD5(const char *username,
+        const char *realm,
+        const char *passwd,
+        char       md5[33]);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
usernameThe authenticating user name.
realmThe authenticating realm name.
passwdThe authenticating password.
md5The MD5 sum string.
+
+

Returns

+

A pointer to the MD5 sum string.

+

Description

+

httpMD5() computes the MD5 hash of the username, realm, + and password as required by the HTTP Digest specification.

+

Example

+
+#include <cups/http.h>
+
+char md5[33];
+
+...
+
+httpMD5("user", "realm", "password", md5);
+
+

See Also

+

httpMD5Final(), + httpMD5String() + +

+

httpMD5Final()

+

Usage

+
+char *
+httpMD5Final(const char *nonce,
+             const char *method,
+             const char *resource,
+             char       md5[33]);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
nonceThe server nonce value.
methodThe HTTP method (GET, POST, etc.)
resourceThe resource path.
md5The MD5 sum string.
+
+

Returns

+

The MD5 sum string.

+

Description

+

httpMD5Final() appends the nonce, method, and resource + to the specified MD5 sum.

+

Example

+
+#include <cups/http.h>
+
+char md5[33];
+
+...
+
+httpMD5Final("nonce", "GET", "/jobs", md5);
+
+

See Also

+

httpMD5(), + httpMD5String() + +

+

httpMD5String()

+

Usage

+
+char *
+httpMD5String(const md5_byte_t *sum,
+              char             md5[33]);
+
+

Arguments

+
+ + + + +
ArgumentDescription
sumThe raw MD5 sum data.
md5The MD5 sum string.
+
+

Returns

+

The MD5 sum string.

+

Description

+

httpMD5String() converts the raw MD5 sum value to a + string.

+

Example

+
+#include <cups/http.h>
+
+md5_byte_t sum[16];
+char       md5[33];
+
+...
+
+httpMD5String(sum, md5);
+
+

See Also

+

httpMD5(), + httpMD5Final() + +

+

httpOptions()

+

Usage

+
+int
+httpOptions(http_t     *http,
+            const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to check for options
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpOptions() function sends a HTTP OPTIONS request + to the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpOptions(http, "/some/uri");
+
+

See Also

+ httpConnect(), + httpSetField(), +httpUpdate() + + +

httpPost()

+

Usage

+
+int
+httpPost(http_t     *http,
+         const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to post to
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpPost() function sends a HTTP POST request to the + server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpPost(http, "/some/uri");
+
+

See Also

+ httpConnect(), + httpSetField(), +httpUpdate() + + +

httpPrintf()

+

Usage

+
+int
+httpPrintf(http_t     *http,
+           const char *format,
+           ...);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
formatA printf-style format string
+
+

Returns

+

The number of bytes written.

+

Description

+

The httpPrintf() function sends a formatted string to + the HTTP connection. It is normally only used by the CUPS API and + scheduler.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpPrintf(http, "GET / HTTP/1.1 \r\n");
+
+

See Also

+ httpConnect() + + +

httpPut()

+

Usage

+
+int
+httpPut(http_t     *http,
+        const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to put
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpPut() function sends a HTTP PUT request to the + server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+

See Also

+ httpConnect(), + httpSetField(), +httpUpdate() + + +

httpRead()

+

Usage

+
+int
+httpRead(http_t *http,
+         char   *buffer,
+         int    length);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+
+

Returns

+

The number of bytes read or -1 on error.

+

Description

+

The httpRead() function reads data from the HTTP + connection, possibly the result of a GET or POST request.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+char buffer[1024];
+int  bytes;
+
+httpGet(http, "/");
+while (httpUpdate(http) != HTTP_CONTINUE);
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+

See Also

+ httpConnect(), + httpWrite() + + +

httpReconnect()

+

Usage

+
+int
+httpReconnect(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpReconnect() function reconnects to the HTTP + server. This is usually done automatically if the HTTP functions detect + that the server connection has terminated.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpReconnect(http);
+
+

See Also

+ httpConnect() + + +

httpSeparate()

+

Usage

+
+void
+httpSeparate(const char *uri,
+             char       *method,
+             char       *username,
+             char       *host,
+             int        *port,
+             char       *resource);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
uriThe URI to separate
methodThe method (scheme) of the URI
usernameThe username (and password) portion of the URI, + if any
hostThe hostname portion of the URI, if any
portThe port number for the URI, either as specified or + as default for the method/scheme
resourceThe resource string, usually a filename on the + server
+
+

Description

+

The httpSeparate() function separates the specified URI + into its component parts. The method, username, hostname, and resource + strings should be at least HTTP_MAX_URI characters long to + avoid potential buffer overflow problems.

+

Example

+
+char uri[HTTP_MAX_URI];
+char method[HTTP_MAX_URI];
+char username[HTTP_MAX_URI];
+char host[HTTP_MAX_URI];
+char resource[HTTP_MAX_URI];
+int  port;
+
+...
+
+httpSeparate(uri, method, username, host, &port, resource);
+
+

See Also

+ httpConnect() + + +

httpSetField()

+

Usage

+
+void
+httpSetField(http_t       *http,
+             http_field_t field,
+             const char   *value);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
valueThe string value for the field
+
+

Description

+

The httpSetField() function sets the current value for + the specified HTTP field.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpSetField(http, HTTP_FIELD_AUTHORIZATION, "Basic dfdr34453454325"));
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+

See Also

+ httpConnect(), + httpGetField() + + +

httpStatus()

+

Usage

+
+const char *
+httpStatus(http_status_t status);
+
+

Arguments

+
+ + + +
ArgumentDescription
statusThe HTTP status code from the server.
+
+

Returns

+

The standard HTTP status text associated with the status code.

+

Description

+

httpStatus() returns the standard HTTP status text + associated with the status code.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+...
+
+puts(httpStatus(http->status));
+
+ + +

httpTrace()

+

Usage

+
+int
+httpTrace(http_t     *http,
+          const char *uri);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to trace
+
+

Returns

+

0 on success, non-zero on failure.

+

Description

+

The httpTrace() function sends a HTTP TRACE request to + the server.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+
+httpTrace(http, "/some/uri");
+
+

See Also

+ httpConnect(), + httpSetField(), +httpUpdate() + + +

httpUpdate()

+

Usage

+
+http_status_t
+httpUpdate(http_t *http);
+
+

Arguments

+
+ + + +
ArgumentDescription
httpThe HTTP connection
+
+

Returns

+

The HTTP status of the current request.

+

Description

+

The httpUpdate() 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.

+

Since proxies and the current blocking mode can cause the request to + take longer, programs should continue calling httpUpdate() +until the return status is not the constant value HTTP_CONTINUE +.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+http_status_t status;
+
+httpGet(http, "/some/uri");
+while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+printf("Request status is %d\n", status);
+
+

See Also

+ httpConnect(), + httpDelete(), httpGet() +, httpHead(), + httpOptions(), httpPost() +, httpPut(), + httpTrace() + + +

httpWrite()

+

Usage

+
+int
+httpWrite(http_t *http,
+          char   *buffer,
+          int    length);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+
+

Returns

+

The number of bytes read or -1 on error.

+

Description

+

The httpWrite() function reads data from the HTTP + connection, possibly the result of a GET or POST request.

+

Example

+
+#include <cups/http.h>
+
+http_t *http;
+FILE *fp;
+char buffer[1024];
+int  bytes;
+
+httpPost(http, "/");
+
+while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+  httpWrite(http, buffer, bytes);
+
+while (httpUpdate(http) != HTTP_CONTINUE);
+
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+

See Also

+ httpConnect(), + httpRead() + + +

ippAddBoolean()

+

Usage

+
+ipp_attribute_t *
+ippAddBoolean(ipp_t      *ipp,
+              ipp_tag_t  group,
+              const char *name,
+	      char       value);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe boolean value
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddBoolean() function adds a single boolean + attribute value to the specified IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "my-jobs", 1);
+
+

See Also

+ ippAddBooleans(), + ippAddDate(), +ippAddInteger(), +ippAddIntegers(), ippAddRange() +, ippAddRanges(), + ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddBooleans()

+

Usage

+
+ipp_attribute_t *
+ippAddBooleans(ipp_t      *ipp,
+               ipp_tag_t  group,
+               const char *name,
+               int        num_values,
+               const char *values);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of values
valuesThe boolean values
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddBooleans() function adds one or more boolean + attribute values to the specified IPP request. If the values + pointer is NULL then an array of num_values + false values is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char values[10];
+
+ippAddBooleans(ipp, IPP_TAG_OPERATION, "some-attribute", 10, values);
+
+

See Also

+ ippAddBoolean(), + ippAddDate(), +ippAddInteger(), +ippAddIntegers(), ippAddRange() +, ippAddRanges(), + ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddDate()

+

Usage

+
+ipp_attribute_t *
+ippAddDate(ipp_t       *ipp,
+           ipp_tag_t   group,
+           const char  *name,
+           ipp_uchar_t *value);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe date value
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddDate() function adds a single date-time + attribute value to the specified IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddDate(ipp, IPP_TAG_OPERATION, "some-attribute", 
+           ippTimeToDate(time(NULL));
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddInteger(), +ippAddIntegers(), ippAddRange() +, ippAddRanges(), + ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings(), +ippTimeToDate() + + +

ippAddInteger()

+

Usage

+
+ipp_attribute_t *
+ippAddInteger(ipp_t      *ipp,
+              ipp_tag_t  group,
+              ipp_tag_t  tag,
+              const char *name,
+              int        value);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value (IPP_TAG_INTEGER or + IPP_TAG_ENUM)
nameThe name of attribute
valueThe integer value
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddInteger() function adds a single integer + attribute value to the specified IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddInteger(ipp, IPP_TAG_OPERATION, "limit", 100);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), +ippAddIntegers(), ippAddRange() +, ippAddRanges(), + ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddIntegers()

+

Usage

+
+ipp_attribute_t *
+ippAddIntegers(ipp_t      *ipp,
+               ipp_tag_t  group,
+               ipp_tag_t  tag,
+               const char *name,
+               int        num_values,
+               const int  *values);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value (IPP_TAG_INTEGER or + IPP_TAG_ENUM)
nameThe name of attribute
num_valuesThe number of values
valuesThe integer values
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddIntegers() function adds one or more integer + attribute values to the specified IPP request. If the values + pointer is NULL then an array of num_values 0 + values is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int values[100];
+
+ippAddIntegers(ipp, IPP_TAG_OPERATION, "some-attribute", 100, values);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddRange(), + ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRange()

+

Usage

+
+ipp_attribute_t *
+ippAddRange(ipp_t      *ipp,
+            ipp_tag_t  group,
+            const char *name,
+            int        low,
+            int        high);
+
+

Arguments

+
+ + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
lowThe lower value
highThe higher value
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddRange() function adds a single range attribute + value to the specified IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddRange(ipp, IPP_TAG_OPERATION, "page-ranges", 1, 10);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddIntegers(), + ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRanges()

+

Usage

+
+ipp_attribute_t *
+ippAddRanges(ipp_t      *ipp,
+             ipp_tag_t  group,
+             const char *name,
+             int        num_values,
+             const int  *lows,
+             const int  *highs);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of range values
lowsThe lower values
highsThe higher values
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddRanges() function adds one or more range + attribute values to the specified IPP request. If the values + pointer is NULL then an array of num_values + 0,0 ranges is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int lows[2];
+int highs[2];
+
+ippAddRanges(ipp, IPP_TAG_OPERATION, "page-ranges", 2, lows, highs);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddIntegers(), + ippAddRange(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolution()

+

Usage

+
+ipp_attribute_t *
+ippAddResolution(ipp_t      *ipp,
+                 ipp_tag_t  group,
+                 const char *name,
+                 int        xres,
+                 int        yres,
+                 ipp_res_t  units);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
xresThe horizontal resolution
yresThe vertical resolution
unitsThe resolution units
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddResolution() function adds a single resolution + attribute value to the specified IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolution",
+              720, 720, IPP_RES_PER_INCH);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddIntegers(), + ippAddRange(), +ippAddRanges(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolutions()

+

Usage

+
+ipp_attribute_t *
+ippAddResolutions(ipp_t           *ipp,
+                  ipp_tag_t       group,
+                  const char      *name,
+                  int             num_values,
+                  const int       *xres,
+                  const int       *yres,
+                  const ipp_res_t *units);
+
+

Arguments

+
+ + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of resolution values
xresThe horizontal resolutions
yresThe vertical resolutions
unitsThe resolution units
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddResolutions() function adds one or more + resolution attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values 0,0 resolutions is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int xres[5];
+int yres[5];
+ipp_res_t units[5];
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolutions-supported",
+              5, xres, yres, units);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddIntegers(), + ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddSeparator()

+

Usage

+
+ipp_attribute_t *
+ippAddSeparator(ipp_t *ipp);
+
+

Arguments

+
+ + + +
ArgumentDescription
ippThe IPP request
+
+

Returns

+

A pointer to the new separator or NULL if the separator could not be + created.

+

Description

+

The ippAddSeparator() function adds a group separator to + the specified IPP request.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddSeparator(ipp);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddIntegers(), + ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddString(), +ippAddStrings() + + +

ippAddString()

+

Usage

+
+ipp_attribute_t *
+ippAddString(ipp_t      *ipp,
+             ipp_tag_t  group,
+             ipp_tag_t  tag,
+             const char *name,
+             const char *charset,
+             const char *value);
+
+

Arguments

+
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
charsetThe character set for the string
valueThe string value
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddString() function adds a single string + attribute value to the specified IPP request. For +IPP_TAG_NAMELANG and IPP_TAG_TEXTLANG strings, the + charset value is provided with the string to identify the string + encoding used. Otherwise the charset value is ignored.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+             NULL, "abc123");
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddIntegers(), + ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddStrings() + + +

ippAddStrings()

+

Usage

+
+ipp_attribute_t *
+ippAddStrings(ipp_t      *ipp,
+              ipp_tag_t  group,
+              ipp_tag_t  tag,
+              const char *name,
+              int        num_values,
+              const char *charset,
+              const char **values);
+
+

Arguments

+
+ + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
num_valuesThe number of strings
charsetThe character set for the strings
valuesThe string values
+
+

Returns

+

A pointer to the new attribute or NULL if the attribute could not be + created.

+

Description

+

The ippAddStrings() function adds one or more string + attribute values to the specified IPP request. For +IPP_TAG_NAMELANG and IPP_TAG_TEXTLANG strings, the + charset value is provided with the strings to identify the string + encoding used. Otherwise the charset value is ignored. If the +values pointer is NULL then an array of +num_values NULL strings is created.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char *values[2] = { "one", "two" };
+
+ippAddStrings(ipp, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "attr-name",
+              2, NULL, values);
+
+

See Also

+ ippAddBoolean(), + ippAddBooleans(), +ippAddDate(), ippAddInteger() +, ippAddIntegers(), + ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString() + + +

ippDateToTime()

+

Usage

+
+time_t
+ippDateToTime(const ipp_uchar_t date[11]);
+
+

Arguments

+
+ + + +
ArgumentDescription
dateThe IPP date-time value
+
+

Returns

+

A UNIX time value.

+

Description

+

The ippDateToTime() function converts an IPP date-time + value to a UNIX time value.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_uchar_t date[11];
+
+printf("UNIX time is %d\n", ippDateToTime(date));
+
+

See Also

+ ippTimeToDate() + + +

ippDelete()

+

Usage

+
+void
+ippDelete(ipp_t *ipp);
+
+

Arguments

+
+ + + +
ArgumentDescription
ippThe IPP request or response
+
+

Description

+

The ippDelete() function deletes all memory used by an + IPP request or response.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippDelete(ipp);
+
+

See Also

+ ippNew() + + +

ippErrorString()

+

Usage

+
+const char *
+ippErrorString(ipp_status_t error);
+
+

Arguments

+
+ + + +
ArgumentDescription
errorIPP error code.
+
+

Returns

+

The standard text representation of the IPP error code.

+

Description

+

ippErrorString() returns the standard text + representation of the IPP error code.

+

Example

+
+#include <cups/ipp.h>
+
+puts(ippErrorString(IPP_OK));
+
+

See Also

+

cupsLastError() + +

+

ippFindAttribute()

+

Usage

+
+ipp_attribute_t *
+ippFindAttribute(ipp_t      *ipp,
+                 const char *name,
+                 ipp_tag_t  tag);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ippThe IPP request or response
nameThe name of the attribute
tagThe required value tag for the attribute or +IPP_TAG_ZERO for any type of value.
+
+

Returns

+

A pointer to the first occurrence of the requested attribute, or +NULL if it was not found.

+

Description

+

ippFindAttribute() finds the first occurrence of the + named attribute. The tag parameter restricts the search to + a specific value type - use IPP_TAG_ZERO to find any value + with the name.

+

The value tags IPP_TAG_NAME and IPP_TAG_TEXT + match the name/text values with or without the language code.

+

Example

+
+ipp_attribute_t *attr;
+
+attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+while (attr != NULL)
+{
+  puts(attr->values[0].string.text);
+
+  attr = ippFindNextAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+}
+
+

See Also

+ cupsDoFileRequest(), + cupsDoRequest(), +ippDelete(), +ippFindNextAttribute(), ippNew() + + + +

ippFindNextAttribute()

+

Usage

+
+ipp_attribute_t *
+ippFindNextAttribute(ipp_t      *ipp,
+                     const char *name,
+                     ipp_tag_t  tag);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ippThe IPP request or response
nameThe name of the attribute
tagThe required value tag for the attribute or +IPP_TAG_ZERO for any type of value.
+
+

Returns

+

A pointer to the next occurrence of the requested attribute, or +NULL if it was not found.

+

Description

+

ippFindNextAttribute() finds the next occurrence of the + named attribute. The tag parameter restricts the search to + a specific value type - use IPP_TAG_ZERO to find any value + with the name.

+

The value tags IPP_TAG_NAME and IPP_TAG_TEXT + match the name/text values with or without the language code.

+

Example

+
+ipp_attribute_t *attr;
+
+attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+while (attr != NULL)
+{
+  puts(attr->values[0].string.text);
+
+  attr = ippFindNextAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+}
+
+

See Also

+ cupsDoFileRequest(), + cupsDoRequest(), +ippDelete(), +ippFindNextAttribute(), ippNew() + + + +

ippLength()

+

Usage

+
+int
+ippLength(ipp_t *ipp);
+
+

Arguments

+
+ + + +
ArgumentDescription
ippThe IPP request or response
+
+

Returns

+

The total encoded length of the IPP request or response in bytes.

+

Description

+

ippLength() returns the length of the IPP request or + response in bytes.

+

Example

+
+printf("The length of the response is %d bytes.\n", ippLength(response));
+
+

See Also

+ ippDelete(), +ippNew() + + +

ippNew()

+

Usage

+
+ipp_t *
+ippNew(void);
+
+

Returns

+

A pointer to a new IPP request or response.

+

Description

+

The ippNew() function creates a new IPP request or + response.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ipp = ippNew();
+
+

See Also

+ ippDelete() + + +

ippPort()

+

Usage

+
+int
+ippPort(void);
+
+

Returns

+

The default TCP/IP port number for IPP requests.

+

Description

+

The ippPort() function returns the default IPP port + number for requests.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+

See Also

+ cupsServer(), + ippSetPort() + + +

ippRead()

+

Usage

+
+ipp_state_t
+ippRead(http_t *http,
+        ipp_t  *ipp);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+
+

Returns

+

The current read state.

+

Description

+

The ippRead() function reads IPP attributes from the + specified HTTP connection. Programs should continue calling +ippRead() until IPP_ERROR or IPP_DATA + is returned.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+
+while ((status = ippRead(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpRead() ...
+}
+
+

See Also

+ ippWrite() + + +

ippSetPort()

+

Usage

+
+void
+ippSetPort(int port);
+
+

Arguments

+
+ + + +
ArgumentDescription
portThe port number to use
+
+

Description

+

The ippSetPort() function sets the default IPP port + number for requests.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+...
+
+ippSetPort(8631);
+
+

See Also

+ ippPort() + + +

ippTimeToDate()

+

Usage

+
+ipp_uchar_t *
+ippTimeToDate(time_t time);
+
+

Arguments

+
+ + + +
ArgumentDescription
timeThe UNIX time value
+
+

Returns

+

A static pointer to an IPP date-time value.

+

Description

+

The ippTimeToDate() function converts a UNIX time to an + IPP date-time value.

+

Example

+
+#include <cups/ipp.h>
+
+ipp_uchar_t *date;
+
+date = ippTimeToDate(time(NULL));
+
+

See Also

+ ippDateToTime() + + +

ippWrite()

+

Usage

+
+ipp_state_t
+ippWrite(http_t *http,
+         ipp_t  *ipp);
+
+

Arguments

+
+ + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+
+

Returns

+

The current write state.

+

Description

+

The ippWrite() function writes IPP attributes to the + specified HTTP connection. Programs should continue calling +ippWrite() until IPP_ERROR or IPP_DATA + is returned.

+

Example

+
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+... add attributes ...
+
+while ((status = ippWrite(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpWrite() ...
+}
+
+

See Also

+ ippRead() + + +

ppdClose()

+

Usage

+
+void
+ppdClose(ppd_file_t *ppd);
+
+

Arguments

+
+ + + +
ArgumentDescription
ppdThe PPD file
+
+

Description

+

The ppdClose() function frees all memory associated with + the PPD file.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdClose(ppd);
+
+

See Also

+ ppdOpen(), +ppdOpenFd(), ppdOpenFile() + + + +

ppdCollect()

+

Usage

+
+int
+ppdCollect(ppd_file_t    *ppd,
+           ppd_section_t section,
+           ppd_choice_t  ***choices);
+
+

Arguments

+
+ + + + + + +
ArgumentDescription
ppdThe PPD file.
sectionThe document section to collect.
choicesThe array of option choices that are marked.
+
+

Returns

+

The number of options collected.

+

Description

+

ppdCollect() collects all of the marked options in the + specified section, sorts them by their order dependency values, and + returns an array that can be used to emit option commands in the proper + order. It is normally used by the ppdEmit*() functions.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t   *ppd;
+int          num_choices;
+ppd_choice_t **choices;
+
+...
+
+num_choices = ppdCollect(ppd, PPD_ORDER_JCL, &choices);
+
+

See Also

+

ppdEmit(), +ppdEmitFd(), ppdEmitJCL() + + +

+

ppdConflicts()

+

Usage

+
+int
+ppdConflicts(ppd_file_t *ppd);
+
+

Arguments

+
+ + + +
ArgumentDescription
ppdThe PPD file
+
+

Returns

+

The number of option conflicts in the file.

+

Description

+

The ppdConflicts() function returns the number of + conflicts with the currently selected options.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("%d conflicts\n", ppdConflicts(ppd));
+
+

See Also

+ cupsMarkOptions(), + ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdEmit()

+

Usage

+
+int
+ppdEmit(ppd_file_t    *ppd,
+        FILE          *file,
+        ppd_section_t section);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ppdThe PPD file
fileThe file to write to
sectionThe option section to write
+
+

Returns

+

0 on success, -1 on error.

+

Description

+

The ppdEmit() function sends printer-specific option + commands to the specified file.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+

See Also

+ ppdEmitFd() + + +

ppdEmitFd()

+

Usage

+
+int
+ppdEmitFd(ppd_file_t    *ppd,
+          int           fd,
+          ppd_section_t section);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ppdThe PPD file
fdThe file descriptor to write to
sectionThe option section to write
+
+

Returns

+

0 on success, -1 on error.

+

Description

+

The ppdEmitFd() function sends printer-specific option + commands to the specified file descriptor.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmitFd(ppd, 1, PPD_ORDER_PAGE);
+
+

See Also

+ ppdEmit() + + +

ppdFindChoice()

+

Usage

+
+ppd_choice_t *
+ppdFindChoice(ppd_option_t *option,
+              const char   *choice);
+
+

Arguments

+
+ + + + +
ArgumentDescription
optionA pointer to the option
choiceThe name of the choice
+
+

Returns

+

A pointer to the choice data or NULL if the choice does not exist.

+

Description

+

The ppdFindChoice() function returns a pointer to the + choice data for the specified option.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+ppd_choice_t *choice;
+
+option = ppdFindOption(ppd, "PageSize");
+choice = ppdFindChoice(option, "Letter");
+
+

See Also

+ ppdFindMarkedChoice(), ppdFindOption() + + +

ppdFindMarkedChoice()

+

Usage

+
+ppd_choice_t *
+ppdFindMarkedChoice(ppd_file_t *ppd,
+                    const char *keyword);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+
+

Returns

+

A pointer to the choice data or NULL if the choice does not exist or + is not marked.

+

Description

+

The ppdFindMarkedChoice() function returns a pointer to + the marked choice data for the specified option.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_choice_t *choice;
+
+choice = ppdFindMarkedChoice(ppd, "PageSize");
+
+

See Also

+ ppdFindChoice(), + ppdFindOption() + + +

ppdFindOption()

+

Usage

+
+ppd_option_t *
+ppdFindOption(ppd_file_t *ppd,
+              const char *keyword);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+
+

Returns

+

A pointer to the option data or NULL if the option does not exist.

+

Description

+

The ppdFindOption() function returns a pointer to the + option data for the specified option.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+
+option = ppdFindOption(ppd, "PageSize");
+
+

See Also

+ ppdFindChoice(), + ppdFindMarkedChoice() + + +

ppdIsMarked()

+

Usage

+
+int
+ppdIsMarked(ppd_file_t *ppd,
+            const char *keyword,
+            const char *choice);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the option choice
+
+

Returns

+

1 if the choice is marked, 0 otherwise.

+

Description

+

The ppdIsMarked() function returns whether or not the + specified option choice is marked.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Letter size %s selected.\n",
+       ppdIsMarked(ppd, "PageSize", "Letter") ? "is" : "is not");
+
+

See Also

+ cupsMarkOptions(), + ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkDefaults()

+

Usage

+
+void
+ppdMarkDefaults(ppd_file_t *ppd);
+
+

Arguments

+
+ + + +
ArgumentDescription
ppdThe PPD file
+
+

Description

+

The ppdMarkDefaults() function marks all of the default + choices in the PPD file.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkDefaults(ppd);
+
+

See Also

+ cupsMarkOptions(), + ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkOption()

+

Usage

+
+int
+ppdMarkOption(ppd_file_t *ppd,
+              const char *keyword,
+              const char *choice);
+
+

Arguments

+
+ + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the choice
+
+

Returns

+

The number of conflicts in the PPD file.

+

Description

+

The ppdMarkOption() function marks the specified option + choice.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkOption(ppd, "PageSize", "Letter");
+
+

See Also

+ cupsMarkOptions(), + ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdOpen()

+

Usage

+
+ppd_file_t *
+ppdOpen(FILE *file);
+
+

Arguments

+
+ + + +
ArgumentDescription
fileThe file to read from
+
+

Returns

+

A pointer to a PPD file structure or NULL if the PPD file could not + be read.

+

Description

+

The ppdOpen() function reads a PPD file from the + specified file into memory.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+FILE *file;
+
+file = fopen("filename.ppd", "rb");
+ppd = ppdOpen(file);
+fclose(file);
+
+

See Also

+ ppdClose(), +ppdOpenFd(), ppdOpenFile() + + + +

ppdOpenFd()

+

Usage

+
+ppd_file_t *
+ppdOpenFd(int fd);
+
+

Arguments

+
+ + + +
ArgumentDescription
fdThe file descriptor to read from
+
+

Returns

+

A pointer to a PPD file structure or NULL if the PPD file could not + be read.

+

Description

+

The ppdOpenFd() function reads a PPD file from the + specified file descriptor into memory.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+int        fd;
+
+fd = open("filename.ppd", O_RDONLY);
+ppd = ppdOpenFd(fd);
+close(fd);
+
+

See Also

+ ppdClose(), +ppdOpen(), ppdOpenFile() + + +

ppdOpenFile()

+

Usage

+
+ppd_file_t *
+ppdOpenFile(const char *filename);
+
+

Arguments

+
+ + + +
ArgumentDescription
filenameThe name of the file to read from
+
+

Returns

+

A pointer to a PPD file structure or NULL if the PPD file could not + be read.

+

Description

+

The ppdOpenFile() function reads a PPD file from the + named file into memory.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile("filename.ppd");
+
+

See Also

+ ppdClose(), +ppdOpen(), ppdOpenFd() + + +

ppdPageLength()

+

Usage

+
+float
+ppdPageLength(ppd_file_t *ppd,
+              const char *name);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+
+

Returns

+

The length of the specified page size in points or 0 if the page size + does not exist.

+

Description

+

The ppdPageLength() function returns the page length of + the specified page size.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Length = %.0f\n", ppdPageLength(ppd, "Letter"));
+
+

See Also

+ ppdPageLength(), + ppdPageSize(), +ppdPageWidth() + + +

ppdPageSize()

+

Usage

+
+ppd_size_t *
+ppdPageSize(ppd_file_t *ppd,
+            const char *name);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+
+

Returns

+

A pointer to the page size record of the specified page size in + points or NULL if the page size does not exist.

+

Description

+

The ppdPageSize() function returns the page size record + for the specified page size.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+
+size = ppdPageSize(ppd, "Letter");
+if (size != NULL)
+{
+  printf(" Width = %.0f\n", size->width);
+  printf("Length = %.0f\n", size->length);
+  printf("  Left = %.0f\n", size->left);
+  printf(" Right = %.0f\n", size->right);
+  printf("Bottom = %.0f\n", size->bottom);
+  printf("   Top = %.0f\n", size->top);
+}
+
+

See Also

+ ppdPageLength(), + ppdPageWidth() + + +

ppdPageWidth()

+

Usage

+
+float
+ppdPageWidth(ppd_file_t *ppd,
+             const char *name);
+
+

Arguments

+
+ + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+
+

Returns

+

The width of the specified page size in points or 0 if the page size + does not exist.

+

Description

+

The ppdPageWidth() function returns the page width of + the specified page size.

+

Example

+
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Width = %.0f\n", ppdPageWidth(ppd, "Letter"));
+
+

See Also

+ ppdPageLength(), + ppdPageSize() + diff --git a/doc/spm.pdf b/doc/spm.pdf new file mode 100644 index 0000000000000000000000000000000000000000..773c54baead5bf74d859b28bebb3788b485ba646 GIT binary patch literal 679448 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±@ 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

~vn^U_+qP}nwr$(C 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 + + + + + CUPS Software Programmers Manual + + + +

Preface

+ +

This software programmers manual provides software +programming information for the Common UNIX Printing System +("CUPS") Version 1.1.17. + + + + +

Document Overview

+ +

This software programmers manual is organized into the following sections: + +

+ +

Notation Conventions

+ +

Various font and syntax conventions are used in this guide. Examples and +their meanings and uses are explained below: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Example   Description
 
lpstat
+ lpstat(1)
   The names of commands; the first mention of a command or + function in a chapter is followed by a manual page section + number.
 
/var
+ /usr/share/cups/data/testprint.ps
   File and directory names.
 
Request ID is Printer-123   Screen output.
 
lp -d printer filename ENTER   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are written using the period (.) to indicate + the decimal point.
+ + +

Abbreviations

+ +The following abbreviations are used throughout this manual: + +
    +
    + +
    kb +
    Kilobytes, or 1024 bytes
      + +
    Mb +
    Megabytes, or 1048576 bytes
      + +
    Gb +
    Gigabytes, or 1073741824 bytes
      + +
    +
+ +

Other References

+ +
    +
    + +
    CUPS Software Administrators Manual + +
    An administration guide for the CUPS software.
      + +
    CUPS Software Users Manual + +
    An end-user guide for using the CUPS software.
      + +
    +
+ + + + + +

2 - The CUPS API

+ +

This chapter describes the CUPS Application Programmers Interface ("API"). + +

The CUPS API Library

+ +

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. + +

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. + +

Programs that use the CUPS API library typically will include the +<cups/cups.h> header file: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +jobid = cupsPrintFile("myprinter", "filename.ps", "title",
    +                      num_options, options);
    +
+ +

Use the -lcups compiler option when linking to the CUPS API +library: + +

    +cc -o program program.c -lcups ENTER
    +
+ +

Additional options and libraries may be required depending on the +operating system and the location of the CUPS API library. + +

Detecting the CUPS API Library in GNU Autoconf

+ +

GNU autoconf is a popular configuration tool used by many programs. +Add the following lines to your configure.in file to check +for the CUPS API library in your configuration script: + +

    +AC_CHECK_LIB(socket,socket,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lsocket $LIBS"
    +else
    +	echo "Not using -lsocket since you are running IRIX."
    +fi)
    +AC_CHECK_LIB(nsl,gethostbyaddr,
    +if test "$uname" != "IRIX"; then
    +	LIBS="-lnsl $LIBS"
    +else
    +	echo "Not using -lnsl since you are running IRIX."
    +fi)
    +
    +AC_CHECK_LIB(cups,httpConnect)
    +
+ +

Printing Services

+ +

The CUPS API library provides some basic printing services for applications +that need to print files. + +

Include Files

+ +

The include file used by all of these functions is +<cups/cups.h>: + +

    +#include <cups/cups.h>
    +
+ +

Printing a File

+ +

The CUPS API provides two functions for printing files. The first is +cupsPrintFile which prints a single named file: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +jobid = cupsPrintFile("name", "filename", "title", 0, NULL);
    +
+ +

The name string is the name of the printer or class to +print to. The filename string is the name of the file to +print. The title string is the name of the print job, e.g. +"Acme Word Document". + +

The return value is a unique ID number for the print job or 0 if there +was an error. + +

Printing Multiple Files

+ +

The second printing function is cupsPrintFiles: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int        jobid;
    +int        num_files;
    +const char *files[100];
    +...
    +
    +jobid = cupsPrintFiles("name", num_files, files, "title", 0, NULL);
    +
+ +

Instead of passing a filename string as with cupsPrintFile() +you pass a file count (num_files) and filename pointer array +(files) for each file that you want to print. + +

As with cupsPrintFile() the return value is a unique ID for +the print job. + +

Cancelling Jobs

+ +

The cupsCancelJob() function cancels a queued print job: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +int status;
    +...
    +
    +status = cupsCancelJob("name", jobid);
    +
+ +

The name string specifies the destination and is used +to determine the server to send the request to. The jobid +value is the integer returned from a previous cupsPrintFile() +or cupsPrintFiles() call. + +

cupsCancelJob() returns 1 if the job was +successfully cancelled and 0 if there was an error. + +

Getting the Available Printers and Classes

+ +

The cupsGetDests() function can be used to get a list +of the available printers, classes, and instances that a user has defined: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +
    +...
    +
    +num_dests = cupsGetDests(&dests);
    +
+ +

Each destination is stored in a cups_dest_t 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: + +

    +typedef struct               /**** Destination ****/
    +{
    +  char          *name,       /* Printer or class name */
    +                *instance;   /* Local instance name or NULL */
    +  int           is_default;  /* Is this printer the default? */
    +  int           num_options; /* Number of options */
    +  cups_option_t *options;    /* Options */
    +} cups_dest_t;
    +
+ +

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 cupsGetDest() function: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
+ +

The name string is the printer or class name. You can pass +a value of NULL to get the default destination. + +

The instance string is the user-defined instance name. Pass +NULL to select the default instance, e.g. "name" instead of +"name/instance". + +

Printing with Options

+ +

All of the previous printing examples have passed 0 and +NULL for the last two arguments to the cupsPrintFile() +and cupsPrintFiles() functions. These last two arguments are the +number of options and a pointer to the option array: + +

    +int cupsPrintFile(const char *name, const char *filename, const char *title,
    +                  int num_options, cups_option_t *options);
    +int cupsPrintFiles(const char *name, int num_files, const char **files,
    +                   const char *title, int num_options,
    +		   cups_option_t *options);
    +
+ +

The cups_option_t structure holds each option and its value. +These are converted as needed and passed to the CUPS server when printing a +file. + +

The simplest way of handling options is to use the num_options +and options members of the cups_dest_t +structure described earlier: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int         jobid;
    +int         num_dests;
    +cups_dest_t *dests;
    +cups_dest_t *mydest;
    +
    +...
    +
    +mydest = cupsGetDest("name", "instance", num_dests, dests);
    +
    +jobid  = cupsPrintFile(mydest->name, "filename", "title",
    +                       mydest->num_options, mydest->options);
    +
+ +

This effectively uses the options a user has previous selected without a +lot of code. + +

Setting Printer Options

+ +

Options can also be set by your program using the cupsAddOption() +function: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int           num_options;
    +cups_option_t *options;
    +
    +...
    +
    +num_options = 0;
    +options     = NULL;
    +
    +...
    +
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +num_options = cupsAddOption("name", "value", num_options, &options);
    +
+ +

The name string is the name of the option, and the +value string is the value for that option. + +

Each call to cupsAddOption() 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 +cupsAddOptions() 20 times will result in 20 options. + +

Call cupsFreeOptions once you are done using the options: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int           num_options;
    +cups_option_t *options;
    +
    +...
    +
    +cupsFreeOptions(num_options, options);
    +
+ +

Getting Errors

+ +

If any of the CUPS API printing functions returns an error, the reason for +that error can be found by calling cupsLastError() and +cupsErrorString(). cupsLastError() returns the +last IPP error code that was encountered. cupsErrorString() +converts the error code to a localized message string suitable for +presentation to the user: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +int jobid;
    +
    +...
    +
    +if (jobid == 0)
    +  puts(cupsErrorString(cupsLastError()));
    +
+ +

Passwords and Authentication

+ +

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. + +

To support other types of applications, in particular +Graphical User Interfaces ("GUIs"), the CUPS API provides +functions to set the default username and to register a callback +function that returns a password string. + +

The cupsSetPasswordCB() +function is used to set a password callback in your program. Only one +function can be used at any time. + +

The cupsSetUser() function sets +the current username for authentication. This function can be called by +your password callback function to change the current username as needed. + +

The following example shows a simple password callback that gets a +username and password from the user: + +

    +#include <cups/cups.h>
    +
    +const char *
    +my_password_cb(const char *prompt)
    +{
    +  char	user[65];
    +
    +
    +  puts(prompt);
    +
    + /* Get a username from the user */
    +  printf("Username: ");
    +  if (fgets(user, sizeof(user), stdin) == NULL)
    +    return (NULL);
    +
    + /* Strip the newline from the string and set the user */
    +  user[strlen(user) - 1] = '\0';
    +
    +  cupsSetUser(user);
    +
    + /* Use getpass() to ask for the password... */
    +  return (getpass("Password: "));
    +}
    +
    +...
    +
    +cupsSetPasswordCB(my_password_cb);
    +
+ +

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 +cupsUser() to make things easier +on the user. + +

PPD Services

+ +

CUPS includes functions to access and manipulate PostScript Printer +Description ("PPD") files that are used with the printer drivers in CUPS. + +

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.) + +

Include Files

+ +

Include the <cups/ppd.h> header file to use the PPD +functions: + +

    +#include <cups/ppd.h>
    +
+ +

This header file is also included by the +<cups/cups.h> header file. + +

Getting a PPD File for a Printer

+ +

The cupsGetPPD() function retrieves the PPD file for the +named printer or class: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +const char *filename;
    +
    +filename = cupsGetPPD("name");
    +
+ +

The name string is the name of the printer or class, including +the remote server name as appropriate (e.g. "printer@server".) + +

The return value is a pointer to a filename in static storage; this value +is overwritten with each call to cupsGetPPD(). If the printer +or class does not exist, a NULL pointer will be returned. + +

Loading a PPD File

+ +

The ppdOpenFile() function "opens" a PPD file and loads it +into memory: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +ppd = ppdOpenFile("filename");
    +
+ +

The filename string is the name of the file to load, such as +the value returned by the cupsGetPPD() function. + +

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. + +

Freeing PPD File Information

+ +

Once you are done using a PPD file, call the ppdClose() function +to free all memory that has been used: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdClose(ppd);
    +
+ +

The PPD File Structure

+ +

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 ppd_file_t structure. + +

Capabilities

+ +

Each PPD file contains a number of informational attributes that +describe the capabilities of the printer. These are provided in the +ppd_file_t structure in the following members: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
accurate_screensint1 = supports accurate screens
color_deviceint1 = color device
colorspaceppd_cs_tDefault colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY, + PPD_CS_RGB, PPD_CS_RGBK, PPD_CS_N
contone_onlyint1 = printer is continuous tone only
num_emulations
+ emulations
int
+ ppd_emul_t *
Emulations supported by the printer
flip_duplexint1 = need to flip odd pages when duplexing
num_fonts
+ fonts
int
+ char **
The fonts available on the printer.
jcl_begin
+ jcl_ps
+ jcl_end
char *Job Control Language commands for PostScript output
landscapeintLandscape orientation, -90 or 90 degrees
lang_encodingchar *The character used for the option strings
lang_versionchar *The language used for the options strings (English, French, etc.)
language_levelintPostScript language level, 1 to 3
manual_copiesint1 = Copies are done manually
model_numberintDriver-specific model number.
patcheschar *Patch commands to send to the printer
manufacturerchar *The Manufacturer attribute from the PPD file, if any
modelnamechar *The ModelName attribute from the PPD file
nicknamechar *The NickName attribute from the PPD file, if any
productchar *The Product attribute from the PPD file, if any
shortnicknamechar *The ShortNickName attribute from the PPD file, if any
throughputintNumber of pages per minute
ttrasterizerchar *The TruType font rasterizer (Type42)
variable_sizesint1 = supports variable sizes
+ +

Options and Groups

+ +

PPD files support multiple options, which are stored in +ppd_option_t and ppd_choice_t structures by +the PPD functions. + +

Each option in turn is associated with a group +stored in the ppd_group_t structure. Groups can be +specified in the PPD file; if an option is not associated with a group +then it is put in a "General" or "Extra" group depending on the option. + +

Groups can also have sub-groups; CUPS currently limits the depth of +sub-groups to 1 level to reduce programming complexity. + +

Conflicts

+ +

PPD files support specification of conflict conditions between +different options. Conflicts are stored in ppd_conflict_t +structures which specify the options that conflict with each other. + +

Page Sizes

+ +

PPD files specify all of the available pages sizes and the physical +margins associated with them. These sizes are stored in +ppd_size_t structures and are available in the +num_sizes and sizes members of the +ppd_file_t structure. You can lookup a particular page size +with the ppdPageWidth(), ppdPageLength(), and +ppdPageSize() functions: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +ppd_size_t *size;
    +float      width;
    +float      length;
    +
    +...
    +
    +size   = ppdPageSize(ppd, "size");
    +width  = ppdPageWidth(ppd, "size");
    +length = ppdPageLength(ppd, "size");
    +
+ +

The size string is the named page size option. The +width and length are in points; there are 72 points per inch. The +ppd_size_t structure contains the width, length, and +margin information: + +

    +typedef struct    /**** Page Sizes ****/
    +{
    +  int   marked;   /* Page size selected? */
    +  char  name[41]; /* Media size option */
    +  float width,    /* Width of media in points */
    +        length,   /* Length of media in points */
    +        left,     /* Left printable margin in points */
    +        bottom,   /* Bottom printable margin in points */
    +        right,    /* Right printable margin in points */
    +        top;      /* Top printable margin in points */
    +} ppd_size_t;
    +
+ +

Custom Page Sizes

+ +

Besides the standard page sizes listed in a PPD file, some printers +support variable or custom page sizes. If variables_sizes +is non-zero, the custom_min, custom_max, and +custom_margins members of the ppd_file_t +structure define the limits of the variable sizes. + +

To get the resulting media size, use a page size string of +Custom.widthxlength, where width +and length are integer values in points: + +

    +Custom.612x792   [8.5 inches wide, 11 inches long]
    +Custom.1224x792  [17 inches wide, 11 inches long]
    +
+ +

Marking Options

+ +

Before marking any user-defined options, call the ppdMarkDefaults() +function to mark the default options from the PPD file: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +
    +...
    +
    +ppdMarkDefaults(ppd);
    +
+ +

Then call the ppdMarkOption() function to mark individual +options: + +

    +#include <cups/ppd.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdMarkOption(ppd, "name", "value");
    +
+ +

The name and value strings choose a +particular option and choice, respectively. The return value is 0 +if there are not conflicts created by the selection. + +

CUPS also provides a convenience function for marking all options +in the cups_option_t structure: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +ppd_file_t    *ppd;
    +int           num_options;
    +cups_option_t *options;
    +int           conflicts;
    +
    +...
    +
    +conflicts = cupsMarkOptions(ppd, num_options, options);
    +
+ +

The cupsMarkOptions() function also handles mapping the +IPP job template attributes to PPD options. The return value is the number +of conflicts present. + +

Checking for Conflicts

+ +

The ppdMarkOption() and cupsMarkOptions() +functions return the number of conflicts with the currently marked options. + +

Call the ppdConflicts() function to get the number of +conflicts after you have marked all of the options: + +

    +#include <cups/cups.h>
    +
    +...
    +
    +ppd_file_t *ppd;
    +int        conflicts;
    +
    +...
    +
    +conflicts = ppdConflicts(ppd);
    +
+ +

The return value is the number of conflicting options, or 0 if there +are no conflicts. + + +

3 - Writing Filters

+ +

This chapter describes how to write a file filter for CUPS. + +

Overview

+ +

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. + +

Security Considerations

+ +

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. + +

Users and Groups

+ +

The default CUPS configuration runs filters as user "lp" and group "other". + +

Temporary Files

+ +

Temporary files should be created in the directory specified by the +"TMPDIR" environment variable. The +cupsTempFile() function can be +used to safely choose temporary files in this directory. + +

Sending Messages to the User

+ +

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 LogLevel directive. + +

The type of message is determined by an initial prefix sent on each +line: + +

    + +
  • DEBUG: - a debug message + +
  • INFO: - an informational message + +
  • WARNING: - a warning message + +
  • ERROR: - an error message + +
  • PAGE: - a page accounting message + +
+ +

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 +printer-state-message attribute for the printer, and also +added to the error_log unless it is an informational or page +accounting message. + +

Page Accounting

+ +

Page accounting messages are used to inform the server when one or more +pages are printed. Each line has the form: + +

    +PAGE: page-number copy-count
    +
+ +

The page-number field is the current page number, starting at 1. +The copy-count field specifies the number of copies of that page +that was produced. + +

Page account messages are added to the page_log file and +cause the job-sheets-completed attribute to be updated for +the job. + +

Command-Line Arguments

+ +

Every filter accepts exactly 6 or 7 command-line arguments: + +

    +printer job user title copies options [filename]
    +
    + +
  • printer - The name of the printer queue (normally + this is the name of the program being run) + +
  • job - The numeric job ID for the job being + printed + +
  • user - The string from the + originating-user-name attribute + +
  • title - The string from the + job-name attribute + +
  • copies - The numeric value from the + number-copies attribute + +
  • options - String representations of the + job template attributes, separated by spaces. Boolean attributes + are provided as "name" for true values and "noname" for false + values. All other attributes are provided as "name=value" for + single-valued attributes and "name=value1,value2,...,valueN" for + set attributes + +
  • filename - The request file + +
+ +

The filename argument is only provided to the first filter in the +chain; all filters must be prepared to read the print file from +the standard input if the filename argument is omitted. + +

Copy Generation

+ +

The copies argument specifies the number of copies to produce +of the input file. In general, you should only generate copies if the +filename 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 pstops is responsible for copy generation. + +

Environment Variables

+ +

Every filter receives a fixed set of environment variables that can +be used by the filter: + +

    + +
  • CHARSET - The character set used by the client for + this print file + +
  • CONTENT_TYPE - The original document type, such as + "application/postscript" + +
  • CUPS_DATADIR - The location of CUPS data files + +
  • CUPS_SERVERROOT - The location of CUPS configuration + files + +
  • DEVICE_URI - The output device URI + +
  • LANG - The language used by the client for + this print file + +
  • PATH - The execution path exported to the filter + +
  • PPD - The full filename of the printer's PPD file + +
  • PRINTER - The name of the printer queue + +
  • RIP_CACHE - The maximum amount of memory each filter + should use + +
  • SOFTWARE - The name of the CUPS software, typically + "CUPS/1.1" + +
  • TZ - The local timezone + +
  • USER - The name of the current user + +
+ +

Dissecting the HP-GL/2 Filter

+ +

The HP-GL/2 filter (hpgltops) 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. + +

Initializing the Filter

+ +

The first task of any filter is to ensure that the correct number of +command-line arguments are present: + +

    +if (argc < 6 || argc > 7)
    +{
    +  fputs("ERROR: hpgltops job-id user title copies options [file]\n", stderr);
    +  return (1);
    +}
    +
+ +

After this you open the print file or read from the standard input +as needed: + +

    +FILE *fp;
    +
    +/*
    + * If we have 7 arguments, print the file named on the command-line.
    + * Otherwise, send stdin instead...
    + */
    +
    +if (argc == 6)
    +  fp = stdin;
    +else
    +{
    + /*
    +  * Try to open the print file...
    +  */
    +
    +  if ((fp = fopen(argv[6], "rb")) == NULL)
    +  {
    +    perror("ERROR: unable to open print file - ");
    +    return (1);
    +  }
    +}
    +
+ +

Once the print file has been opened, options can be processed using +the cupsParseOptions() and +cupsGetOption() functions: + +

    +int           num_options;
    +cups_option_t *options;
    +const char    *val;
    +
    +/*
    + * Process command-line options and write the prolog...
    + */
    +
    +options     = NULL;
    +num_options = cupsParseOptions(argv[5], 0, &options);
    +
    +if ((val = cupsGetOption("blackplot", num_options, options)) != NULL)
    +  shading = 0;
    +
    +if ((val = cupsGetOption("fitplot", num_options, options)) != NULL)
    +  FitPlot = 1;
    +
    +if ((val = cupsGetOption("penwidth", num_options, options)) != NULL)
    +  PenWidth = (float)atoi(val) * 0.001f;
    +
+ +

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. + +

PostScript Output

+ +

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: + +

    +%!PS-Adobe-3.0
    +%%BoundingBox: left bottom right top
    +%%Pages: (atend)
    +%%EndComments
    +
+ +

The left, bottom, right, and top values +are integers in points from the lower-lefthand corner of the page. + +

Pages must be surrounded by: + +

    +%%Page: number number
    +gsave
    +...
    +grestore
    +showpage
    +
+ +

And the end of each file must contain: + +

    +%%Trailer
    +%%Pages: number-pages
    +%%EOF
    +
+ +

These comments allow the PostScript filter to correctly perform page +accounting, copy generation, N-up printing, and so forth. + +

4 - Writing Printer Drivers

+ +

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. + +

Overview

+ +

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. + +

CUPS Raster Data

+ +

CUPS raster data (application/vnd.cups-raster) consists of +a stream of raster page descriptions produced by one of the RIP filters, +such as pstoraster or imagetoraster. + +

Each page of data begins with a page dictionary structure called +cups_raster_header_t. This +structure contains the colorspace, bits per color, media size, media type, +hardware resolution, and so forth. + +

After the page dictionary comes the page data which is a full-resolution, +uncompressed bitmap representing the page in the printer's output colorspace. + +

Page Accounting

+ +

Printer drivers must handle all page accounting. This means they must +send "PAGE:" messages to the standard error file for each page (and in many +cases, copy) sent to the printer. + +

Color Management

+ +

Printer drivers can implement their color management via the +cupsColorProfile 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. + +

For example, the pstoraster 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. + +

Device and Bitmap Variables

+ +

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: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableTypeDescription
cupsWidthread-only integerWidth of bitmap in pixels
cupsHeightread-only integer Height of bitmap in pixels
cupsMediaTyperead-write integerDevice-specific media type code
cupsBitsPerColorread-write integerNumber of bits per color; 1, 2, 4, and 8 are currently + supported
cupsBitsPerPixelread-only integer Number of bits per pixel; 1 to 32
cupsBytesPerLineread-only integerNumber of bytes per line of raster graphics
cupsColorOrderread-write enumThe order of color values in the bitmap: +
    +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK +
  • CUPS_ORDER_PLANAR - CCC ... MMM ... YYY ... KKK ... +
+
cupsColorSpaceread-write enumThe colorspace of the bitmap: +
    +
  • CUPS_CSPACE_W - White (luminance) +
  • CUPS_CSPACE_RGB - Red, green, blue +
  • CUPS_CSPACE_RGBA - Red, green, blue, alpha +
  • CUPS_CSPACE_K - Black +
  • CUPS_CSPACE_CMY - Cyan, magenta, yellow +
  • CUPS_CSPACE_YMC - Yellow, magenta, cyan +
  • CUPS_CSPACE_CMYK - Cyan, magenta, yellow, black +
  • CUPS_CSPACE_YMCK - Yellow, magenta, cyan, black +
  • CUPS_CSPACE_KCMY - Black, cyan, magenta, yellow +
  • CUPS_CSPACE_KCMYcm - Black, cyan, magenta, yellow, + light cyan, light magenta +
  • CUPS_CSPACE_GMCK - Metallic yellow (gold), metallic magenta, + metallic cyan, black +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), metallic magenta, + metallic cyan, metallic grey (silver) +
  • CUPS_CSPACE_WHITE - White pigment (black as white pigment) +
  • CUPS_CSPACE_GOLD - Gold foil (black as gold foil) +
  • CUPS_CSPACE_SILVER - Silver foil (black as silver foil) +
+
cupsCompressionread-write integerDevice-specific compression type code
cupsRowCountread-write integerDevice-specific row count value
cupsRowFeedread-write integerDevice-specific row feed value
cupsRowStepread-write integerDevice-specific row step value
+ +

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. + +

Dissecting the HP-PCL Driver

+ +

The HP-PCL driver provided with CUPS (rastertohp) 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 - deskjet.ppd or laserjet.ppd. + +

PPD Files

+ +

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. + +

A typical CUPS printer driver will include ColorModel, +InputSlot, PageSize, PageRegion, +and Resolution options. Each option is shown using the +standard PPD format: + +

    +*OpenUI *PageSize/Media Size: PickOne
    +*OrderDependency: 10 AnySetup *PageSize
    +*DefaultPageSize: Letter
    +*PageSize Letter/US Letter: "<<
    +/PageSize [612 792]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize Legal/US Legal: "<<
    +/PageSize [612 1008]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +*CloseUI: *PageSize
    +
+ +

The OpenUI 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. + +

Every option must have a default value, specified using the +DefaultOption keyword. + +

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: + +

    +*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>> setpagedevice"
    +
+ +

or broken down on separate lines using the End keyword to +terminate them: + +

    +*PageSize A4/A4: "<<
    +/PageSize [595 842]
    +/ImagingBBox null
    +>> setpagedevice"
    +*End
    +
+ +

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. + +

Reading Raster Data

+ +

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 +cupsRasterOpen() function opens +a raster stream for printing: + +

    +int           fd;   /* File descriptor */
    +cups_raster_t *ras; /* Raster stream for printing */
    +
    +
    +/*
    + * Check for valid arguments...
    + */
    +
    +if (argc < 6 || argc > 7)
    +{
    + /*
    +  * We don't have the correct number of arguments; write an error message
    +  * and return.
    +  */
    +
    +  fputs("ERROR: rastertopcl job-id user title copies options [file]\n", stderr);
    +  return (1);
    +}
    +
    +/*
    + * Open the page stream...
    + */
    +
    +if (argc == 7)
    +{
    +  if ((fd = open(argv[6], O_RDONLY)) == -1)
    +  {
    +    perror("ERROR: Unable to open raster file - ");
    +    sleep(1);
    +    return (1);
    +  }
    +}
    +else
    +  fd = 0;
    +
    +ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
    +
+ +

Once you have opened the raster stream you just need to read each +page and print it: + +

    +cups_raster_header_t header;
    +int                  y;
    +unsigned char        data[8192];
    +
    +while (cupsRasterReadHeader(ras, &header))
    +{
    +  ... initialize the printer ...
    +  for (y = header.cupsHeight; y > 0; y ++)
    +  {
    +    cupsRasterReadPixels(ras, data, header.cupsBytesPerLine);
    +    ... send raster line to printer ...
    +  }
    +}
    +
+ +

After you have processed all pages, close the raster stream and +return: + +

    +cupsRasterClose(ras);
    +
    +return (0);
    +
+ +

5 - Writing Backends

+ +

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. + +

Overview

+ +

Backends are special filters that communicate with printers directly. +They are treated slightly differently than filters, however, and have some +unique requirements. + +

Security Considerations

+ +

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. + +

Command-Line Arguments

+ +

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. + +

Copy Generation

+ +

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. + +

Page Accounting

+ +

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 "raw" printing and no other accounting information is possible. + +

Exclusive Access

+ +

Backends that talk to local character or block devices should open the +device file in exclusive mode (O_EXCL) to cooperate with other +printers defined for the same device. + +

Retries

+ +

All backends must 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. + +

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. + +

Dissecting the Serial Port Backend

+ +

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. + +

Supporting Device Discovery

+ +

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...) + +

The serial backend lists devices by looking at serial port files in the +/dev directory, by consulting a hardware inventory (IRIX), and +in some cases by trying to open the ports to see if they actually exist. + +

Once it finds a serial port it writes a single line for each port to +the standard error file. Each line looks like this: + +

    +serial serial:/dev/ttyS0?baud=115200 "Unknown" "Serial Port 1"
    +
+ +

The first word "serial" is the device class; this identifies the +class of device which can be used to categorize it in user interfaces. CUPS +currently recognizes the following classes: + +

    + +
  • "file" - a disk file. + +
  • "direct" - a parallel or fixed-rate serial data port, + currently used for Centronics, IEEE-1284, and USB printer + ports. + +
  • "serial" - a variable-rate serial port. + +
  • "network" - a network connection, typically via AppSocket, + HTTP, IPP, LPD, or SMB/CIFS protocols. + +
+ +

After the device class is the device URI, in this case +"serial:/dev/ttyS0?baud=115200". This is the URI that should be used by +the user to select this port. For serial ports, the "baud=115200" +specifies the maximum baud rate supported by the port - the actual +value will vary based on the speed the user selects for the printer. + +

The last two strings are the model and description for the port. The +"Unknown" string means that the printer model is unknown - some devices +are able to provide a make and model such as "HP DeskJet" that allows +users and software to choose an appropriate printer driver more easily. +Both the model and description must be enclosed inside double quotes. + +

Opening the Serial Port

+ +

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 do-while loop: + +

    +do
    +{
    +  if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1)
    +  {
    +    if (errno == EBUSY)
    +    {
    +      fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr);
    +      sleep(30);
    +    }
    +    else
    +    {
    +      perror("ERROR: Unable to open serial port device file");
    +      return (1);
    +    }
    +  }
    +}
    +while (fd < 0);
    +
+ +

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. + +

Writing Data to the Port

+ +

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: + +

    +while (nbytes > 0)
    +{
    +  if ((wbytes = write(fd, bufptr, nbytes)) < 0)
    +    if (errno == ENOTTY)
    +      wbytes = write(fd, bufptr, nbytes);
    +
    +  if (wbytes < 0)
    +  {
    +    perror("ERROR: Unable to send print file to printer");
    +    break;
    +  }
    +
    +  nbytes -= wbytes;
    +  bufptr += wbytes;
    +}
    +
+ +

The check for the ENOTTY error is needed on some platforms +to clear an error from a previous ioctl() call. + +

Finishing Up

+ +

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. + +

A - Software License Agreement

+ + + + +

B - Constants

+ +

This appendix lists all of the constants that are defined by the CUPS +API. + +

CUPS Constants

+ +

Version Number

+ +

The CUPS_VERSION 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. + +

Printer Capabilities

+ +

The CUPS_PRINTER constants represent capability bits for +printers and classes: + +

    + +
  • CUPS_PRINTER_LOCAL - Is a local printer or class. + +
  • CUPS_PRINTER_REMOTE - Is a remote printer or class. + +
  • CUPS_PRINTER_CLASS - Is a class. + +
  • CUPS_PRINTER_BW - Printer prints in black and white. + +
  • CUPS_PRINTER_COLOR - Printer prints in color. + +
  • CUPS_PRINTER_DUPLEX - Printer can print double-sided. + +
  • CUPS_PRINTER_STAPLE - Printer can staple output. + +
  • CUPS_PRINTER_COPIES - Printer can produce multiple + copies on its own. + +
  • CUPS_PRINTER_COLLATE - Printer can collate copies. + +
  • CUPS_PRINTER_PUNCH - Printer can punch holes in output. + +
  • CUPS_PRINTER_COVER - Printer can put covers on output. + +
  • CUPS_PRINTER_BIND - Printer can bind output. + +
  • CUPS_PRINTER_SORT - Printer can sort output. + +
  • CUPS_PRINTER_SMALL - Printer can print on media up + to 9x14 inches. + +
  • CUPS_PRINTER_MEDIUM - Printer can print on media + from 9x14 to 18x24 inches. + +
  • CUPS_PRINTER_LARGE - Printer can print on media + larger than 18x24 inches. + +
  • CUPS_PRINTER_VARIABLE - Printer can print on + variable or custom media sizes. + +
  • CUPS_PRINTER_IMPLICIT - Is an implicit class. + +
  • CUPS_PRINTER_OPTIONS - All of the printer capability + and option bits. + +
+ +

Encodings

+ +

CUPS defines the following character set encoding constants: + +

    + +
  • CUPS_US_ASCII - US ASCII character set. + +
  • CUPS_UTF_8 - UTF-8 encoding of Unicode. + +
  • CUPS_ISO8859_1 - ISO-8859-1 character set. + +
  • CUPS_ISO8859_2 - ISO-8859-2 character set. + +
  • CUPS_ISO8859_3 - ISO-8859-3 character set. + +
  • CUPS_ISO8859_4 - ISO-8859-4 character set. + +
  • CUPS_ISO8859_5 - ISO-8859-5 character set. + +
  • CUPS_ISO8859_6 - ISO-8859-6 character set. + +
  • CUPS_ISO8859_7 - ISO-8859-7 character set. + +
  • CUPS_ISO8859_8 - ISO-8859-8 character set. + +
  • CUPS_ISO8859_9 - ISO-8859-9 character set. + +
  • CUPS_ISO8859_10 - ISO-8859-10 character set. + +
  • CUPS_ISO8859_13 - ISO-8859-13 character set. + +
  • CUPS_ISO8859_14 - ISO-8859-14 character set. + +
  • CUPS_ISO8859_15 - ISO-8859-15 character set. + +
  • CUPS_WINDOWS_874 - Windows code page 874. + +
  • CUPS_WINDOWS_1250 - Windows code page 1250. + +
  • CUPS_WINDOWS_1251 - Windows code page 1251. + +
  • CUPS_WINDOWS_1252 - Windows code page 1252. + +
  • CUPS_WINDOWS_1253 - Windows code page 1253. + +
  • CUPS_WINDOWS_1254 - Windows code page 1254. + +
  • CUPS_WINDOWS_1255 - Windows code page 1255. + +
  • CUPS_WINDOWS_1256 - Windows code page 1256. + +
  • CUPS_WINDOWS_1257 - Windows code page 1257. + +
  • CUPS_WINDOWS_1258 - Windows code page 1258. + +
  • CUPS_KOI8_R - Russian code page koi8-r. + +
  • CUPS_KOI8_U - Ukrainian code page koi8-r. + +
+ +

HTTP Constants

+ +

Limits

+ +

The following constants define the limits for strings: + +

    + +
  • HTTP_MAX_BUFFER - Size of socket buffer. + +
  • HTTP_MAX_HOST - Maximum length of hostname. + +
  • HTTP_MAX_URI - Maximum length of URI. + +
  • HTTP_MAX_VALUE - Maximum length of field values. + +
+ +

Status Codes

+ +

The following status codes can be returned by httpUpdate(): + +

    + +
  • HTTP_ERROR - A network error occurred + +
  • HTTP_CONTINUE - Continue response from HTTP proxy + +
  • HTTP_OK - OPTIONS/GET/HEAD/POST/TRACE command was successful + +
  • HTTP_CREATED - PUT command was successful + +
  • HTTP_ACCEPTED - DELETE command was successful + +
  • HTTP_NOT_AUTHORITATIVE - Information isn't authoritative + +
  • HTTP_NO_CONTENT - Successful command + +
  • HTTP_RESET_CONTENT - Content was reset/recreated + +
  • HTTP_PARTIAL_CONTENT - Only a partial file was recieved/sent + +
  • HTTP_MULTIPLE_CHOICES - Multiple files match request + +
  • HTTP_MOVED_PERMANENTLY - Document has moved permanently + +
  • HTTP_MOVED_TEMPORARILY - Document has moved temporarily + +
  • HTTP_SEE_OTHER - See this other link... + +
  • HTTP_NOT_MODIFIED - File not modified + +
  • HTTP_USE_PROXY - Must use a proxy to access this URI + +
  • HTTP_BAD_REQUEST - Bad request + +
  • HTTP_UNAUTHORIZED - Unauthorized to access host + +
  • HTTP_PAYMENT_REQUIRED - Payment required + +
  • HTTP_FORBIDDEN - Forbidden to access this URI + +
  • HTTP_NOT_FOUND - URI was not found + +
  • HTTP_METHOD_NOT_ALLOWED - Method is not allowed + +
  • HTTP_NOT_ACCEPTABLE - Not Acceptable + +
  • HTTP_PROXY_AUTHENTICATION - Proxy Authentication is Required + +
  • HTTP_REQUEST_TIMEOUT - Request timed out + +
  • HTTP_CONFLICT - Request is self-conflicting + +
  • HTTP_GONE - Server has gone away + +
  • HTTP_LENGTH_REQUIRED - A content length or encoding is required + +
  • HTTP_PRECONDITION - Precondition failed + +
  • HTTP_REQUEST_TOO_LARGE - Request entity too large + +
  • HTTP_URI_TOO_LONG - URI too long + +
  • HTTP_UNSUPPORTED_MEDIATYPE - The requested media type is unsupported + +
  • HTTP_SERVER_ERROR - Internal server error + +
  • HTTP_NOT_IMPLEMENTED - Feature not implemented + +
  • HTTP_BAD_GATEWAY - Bad gateway + +
  • HTTP_SERVICE_UNAVAILABLE - Service is unavailable + +
  • HTTP_GATEWAY_TIMEOUT - Gateway connection timed out + +
  • HTTP_NOT_SUPPORTED - HTTP version not supported + +
+ +

Fields

+ +

The following fields are indices for each of the standard HTTP fields in +HTTP 1/1: + +

    + +
  • HTTP_FIELD_ACCEPT_LANGUAGE - Accept-Language + +
  • HTTP_FIELD_ACCEPT_RANGES - Accept-Ranges + +
  • HTTP_FIELD_AUTHORIZATION - Authorization + +
  • HTTP_FIELD_CONNECTION - Connection + +
  • HTTP_FIELD_CONTENT_ENCODING - Content-Encoding + +
  • HTTP_FIELD_CONTENT_LANGUAGE - Content-Language + +
  • HTTP_FIELD_CONTENT_LENGTH - Content-Length + +
  • HTTP_FIELD_CONTENT_LOCATION - Content-Location + +
  • HTTP_FIELD_CONTENT_MD5 - Content-MD5 + +
  • HTTP_FIELD_CONTENT_RANGE - Content-Range + +
  • HTTP_FIELD_CONTENT_TYPE - Content-Type + +
  • HTTP_FIELD_CONTENT_VERSION - Content-Version + +
  • HTTP_FIELD_DATE - Date + +
  • HTTP_FIELD_HOST - Host + +
  • HTTP_FIELD_IF_MODIFIED_SINCE - If-Modified-Since + +
  • HTTP_FIELD_IF_UNMODIFIED_SINCE - If-Unmodified-Since + +
  • HTTP_FIELD_KEEP_ALIVE - Keep-Alive + +
  • HTTP_FIELD_LAST_MODIFIED - Last-Modified + +
  • HTTP_FIELD_LINK - Link + +
  • HTTP_FIELD_LOCATION - Location + +
  • HTTP_FIELD_RANGE - Range + +
  • HTTP_FIELD_REFERER - Referer + +
  • HTTP_FIELD_RETRY_AFTER - Retry-After + +
  • HTTP_FIELD_TRANSFER_ENCODING - Transfer-Encoding + +
  • HTTP_FIELD_UPGRADE - Upgrade + +
  • HTTP_FIELD_USER_AGENT - User-Agent + +
  • HTTP_FIELD_WWW_AUTHENTICATE - WWW-Authenticate + + +
+ +

IPP Constants

+ +

Limits

+ +

The following constants define array limits for IPP data: + +

    + +
  • IPP_MAX_NAME - Maximum length of an attribute name + +
  • IPP_MAX_VALUES - Maximum number of set-of values + that can be read in a request. + +
+ +

Tags

+ +
    + +
  • IPP_TAG_ZERO - Wildcard tag value for searches; also + used to separate groups of attributes + +
  • IPP_TAG_OPERATION - Tag for values of type operation + +
  • IPP_TAG_JOB - Tag for values of type job + +
  • IPP_TAG_END - Tag for values of type end + +
  • IPP_TAG_PRINTER - Tag for values of type printer + +
  • IPP_TAG_UNSUPPORTED_GROUP - Tag for values of type unsupported_group + +
  • IPP_TAG_UNSUPPORTED_VALUE - Tag for values of type unsupported_value + +
  • IPP_TAG_DEFAULT - Tag for values of type default + +
  • IPP_TAG_UNKNOWN - Tag for values of type unknown + +
  • IPP_TAG_NOVALUE - Tag for values of type novalue + +
  • IPP_TAG_NOTSETTABLE - Tag for values of type notsettable + +
  • IPP_TAG_DELETEATTR - Tag for values of type deleteattr + +
  • IPP_TAG_ANYVALUE - Tag for values of type anyvalue + +
  • IPP_TAG_INTEGER - Tag for values of type integer + +
  • IPP_TAG_BOOLEAN - Tag for values of type boolean + +
  • IPP_TAG_ENUM - Tag for values of type enum + +
  • IPP_TAG_STRING - Tag for values of type string + +
  • IPP_TAG_DATE - Tag for values of type date + +
  • IPP_TAG_RESOLUTION - Tag for values of type resolution + +
  • IPP_TAG_RANGE - Tag for values of type range + +
  • IPP_TAG_COLLECTION - Tag for values of type collection + +
  • IPP_TAG_TEXTLANG - Tag for values of type textlang + +
  • IPP_TAG_NAMELANG - Tag for values of type namelang + +
  • IPP_TAG_TEXT - Tag for values of type text + +
  • IPP_TAG_NAME - Tag for values of type name + +
  • IPP_TAG_KEYWORD - Tag for values of type keyword + +
  • IPP_TAG_URI - Tag for values of type uri + +
  • IPP_TAG_URISCHEME - Tag for values of type urischeme + +
  • IPP_TAG_CHARSET - Tag for values of type charset + +
  • IPP_TAG_LANGUAGE - Tag for values of type language + +
  • IPP_TAG_MIMETYPE - Tag for values of type mimetype + +
+ +

Resolution Units

+ +

The IPP_RES_PER_INCH and IPP_RES_PER_CM constants +specify dots per inch and dots per centimeter, respectively. + +

Finishings

+ +

The finishing values specify special finishing operations to be +performed on the job. + +

    + +
  • IPP_FINISH_NONE - Do no finishing + +
  • IPP_FINISH_STAPLE - Staple the job + +
  • IPP_FINISH_PUNCH - Punch the job + +
  • IPP_FINISH_COVER - Cover the job + +
  • IPP_FINISH_BIND - Bind the job + +
+ +

Orientations

+ +

The orientation values specify the orientation of the job. + +

    + +
  • IPP_PORTRAIT - No rotation + +
  • IPP_LANDSCAPE - 90 degrees counter-clockwise + +
  • IPP_REVERSE_LANDSCAPE - 90 degrees clockwise + +
  • IPP_REVERSE_PORTRAIT - 180 degrees + +
+ +

Qualities

+ +

The quality values specify the desired quality of the print. +

    + +
  • IPP_QUALITY_DRAFT - Draft quality + +
  • IPP_QUALITY_NORMAL - Normal quality + +
  • IPP_QUALITY_HIGH - High quality + +
+ +

Job States

+ +

The job state values are used to represent the current job state. + +

    + +
  • IPP_JOB_PENDING - Job is pending + +
  • IPP_JOB_HELD - Job is held + +
  • IPP_JOB_PROCESSING - Job is processing + +
  • IPP_JOB_STOPPED - Job is stopped + +
  • IPP_JOB_CANCELLED - Job is cancelled + +
  • IPP_JOB_ABORTED - Job is aborted + +
  • IPP_JOB_COMPLETED - Job is completed + +
+ +

Printer States

+ +

The printer state values are used to represent the current printer +state. + +

    + +
  • IPP_PRINTER_IDLE - Printer is idle + +
  • IPP_PRINTER_PROCESSING - Printer is processing + +
  • IPP_PRINTER_STOPPED - Printer is stopped + +
+ +

Operations

+ +

The operation values represent the available IPP operations. + +

    + +
  • IPP_PRINT_JOB - Print a file + +
  • IPP_PRINT_URI - Print a URI + +
  • IPP_VALIDATE_JOB - Validate job attributes + +
  • IPP_CREATE_JOB - Create a new job + +
  • IPP_SEND_DOCUMENT - Send a document to a job + +
  • IPP_SEND_URI - Send a URI to a job + +
  • IPP_CANCEL_JOB - Cancel a job + +
  • IPP_GET_JOB_ATTRIBUTES - Get job attributes + +
  • IPP_GET_JOBS - Get a list of all jobs + +
  • IPP_GET_PRINTER_ATTRIBUTES - Get printer attributes + +
  • IPP_HOLD_JOB - Hold a pending job + +
  • IPP_RELEASE_JOB - Release a held job + +
  • IPP_RESTART_JOB - Restart a completed job + +
  • IPP_PAUSE_PRINTER - Pause a printer + +
  • IPP_RESUME_PRINTER - Restart a paused printer + +
  • IPP_PURGE_JOBS - Purge jobs from the queue + +
  • IPP_SET_PRINTER_ATTRIBUTES - Set printer attributes + +
  • IPP_SET_JOB_ATTRIBUTES - Set job attributes + +
  • IPP_GET_PRINTER_SUPPORTED_VALUES - Get printer supported values + +
  • CUPS_GET_DEFAULT - Get the default destination + +
  • CUPS_GET_PRINTERS - Get a list of all printers + +
  • CUPS_ADD_PRINTER - Add or modify a printer + +
  • CUPS_DELETE_PRINTER - Delete a printer + +
  • CUPS_GET_CLASSES - Get a list of all classes + +
  • CUPS_ADD_CLASS - Add or modify a class + +
  • CUPS_DELETE_CLASS - Delete a class + +
  • CUPS_ACCEPT_JOBS - Accept jobs on a printer or class + +
  • CUPS_REJECT_JOBS - Reject jobs on a printer or class + +
  • CUPS_SET_DEFAULT - Set the default destination + +
  • CUPS_GET_DEVICES - Get a list of all devices + +
  • CUPS_GET_PPDS - Get a list of all PPDs + +
  • CUPS_MOVE_JOB - Move a job to a new destination + +
+ +

Status Codes

+ +

Status codes are returned by all IPP requests. + +

    + +
  • IPP_OK - Request completed with no errors + +
  • IPP_OK_SUBST - Request completed but some attribute + values were substituted + +
  • IPP_OK_CONFLICT - Request completed but some attributes + conflicted + +
  • IPP_BAD_REQUEST - The request was bad + +
  • IPP_FORBIDDEN - You don't have access to the resource + +
  • IPP_NOT_AUTHENTICATED - You are not authenticated for + the resource + +
  • IPP_NOT_AUTHORIZED - You not authorized to access + the resource + +
  • IPP_NOT_POSSIBLE - The requested operation cannot be + completed + +
  • IPP_TIMEOUT - A timeout occurred + +
  • IPP_NOT_FOUND - The resource was not found + +
  • IPP_GONE - The resource has gone away + +
  • IPP_REQUEST_ENTITY - The request was too large + +
  • IPP_REQUEST_VALUE - The request contained a value + that was unknown to the server + +
  • IPP_DOCUMENT_FORMAT - The document format is not + supported by the server + +
  • IPP_ATTRIBUTES - Required attributes are missing + +
  • IPP_URI_SCHEME - The URI scheme is not supported + +
  • IPP_CHARSET - The charset is not supported + +
  • IPP_CONFLICT - One or more attributes conflict + +
  • IPP_COMPRESSION_NOT_SUPPORTED - The specified + compression is not supported + +
  • IPP_COMPRESSION_ERROR - The compressed data + contained an error + +
  • IPP_DOCUMENT_FORMAT_ERROR - The document data + contained an error in it + +
  • IPP_DOCUMENT_ACCESS_ERROR - The remote document + could not be accessed + +
  • IPP_INTERNAL_ERROR - The server encountered an + internal error + +
  • IPP_OPERATION_NOT_SUPPORTED - The requested operation + is not supported + +
  • IPP_SERVICE_UNAVAILABLE - The requested service + is unavailable + +
  • IPP_VERSION_NOT_SUPPORTED - The IPP request + version is not supported + +
  • IPP_DEVICE_ERROR - The output device encountered + an error + +
  • IPP_TEMPORARY_ERROR - A temporary error occurred + +
  • IPP_NOT_ACCEPTING - The destination is not accepting + jobs + +
  • IPP_PRINTER_BUSY - The destination is busy + +
  • IPP_ERROR_JOB_CANCELLED - The requested job has been + cancelled + +
  • IPP_MULTIPLE_JOBS_NOT_SUPPORTED - The server + does not support multiple jobs + +
+ +

PPD Constants

+ +

PPD Format Version

+ +

The PPD_VERSION constant defines a floating point number +representing the newest format version that is supported by CUPS, currently +4.3. + +

PPD User-Interface Types

+ +

Each printer option has a type associated with it: + +

    + +
  • PPD_UI_BOOLEAN - The user can turn this option on or off + +
  • PPD_UI_PICKONE - The user can choose one option value + to use. + +
  • PPD_UI_PICKMANY - The user can choose zero or more + option values. + +
+ +

PPD Sections

+ +

Some options must be output before others, or in different sections of +the output document. The ppd_section_t enumeration defines +which section the option must be output in: + +

    + +
  • PPD_ORDER_ANY - The option can be output in any of + the document, page, or prolog sections of the document + +
  • PPD_ORDER_DOCUMENT - The option must be output in + the DocumentSetup section of the document + +
  • PPD_ORDER_EXIT - The option must be output before + the document + +
  • PPD_ORDER_JCL - The option must be output in the + job control section of the document + +
  • PPD_ORDER_PAGE - The option must be output in the + PageSetup section of the document + +
  • PPD_ORDER_PROLOG - The option must be output in the + Prolog section of the document + +
+ +

PPD Colorspaces

+ +

Each printer has a default colorspace: + +

    + +
  • PPD_CS_CMYK - The printer uses CMYK colors by default + +
  • PPD_CS_CMY - The printer uses CMY colors by default + +
  • PPD_CS_GRAY - The printer uses grayscale by default + +
  • PPD_CS_RGB - The printer uses RGB colors by default + +
  • PPD_CS_RGBK - The printer uses RGBK colors by default + +
  • PPD_CS_N - The printer uses a DeviceN colorspace + by default + +
+ +

Raster Constants

+ +

Raster Sync Words

+ +

The CUPS_RASTER_SYNC and CUPS_RASTER_REVSYNC +constants define the standard sync words at the beginning of each CUPS +raster file. + +

Raster Stream Modes

+ +

The CUPS_RASTER_READ and CUPS_RASTER_WRITE +constants are used with the +cupsRasterOpen() function to +specify a stream for reading or writing. + +

Raster Boolean Constants

+ +

The CUPS_FALSE and CUPS_TRUE constants +represent boolean values in the page header. + +

Raster Jog Values

+ +

The cups_jog_t enumeration defines constants for the +Jog page device dictionary variable: + +

    + +
  • CUPS_JOG_NONE - Do no jogging + +
  • CUPS_JOG_FILE - Jog pages after each file + +
  • CUPS_JOG_JOB - Jog pages after each job + +
  • CUPS_JOG_SET - Jog pages after each set of jobs + +
+ +

Raster Orientation Values

+ +

The cups_orient_t enumeration defines constants for the +Orientation page device dictionary variable: + +

    + +
  • CUPS_ORIENT_0 - Portrait orientation + +
  • CUPS_ORIENT_90 - Landscape orientation + +
  • CUPS_ORIENT_180 - Reverse-portrait orientation + +
  • CUPS_ORIENT_270 - Reverse-landscape orientation + +
+ +

Raster CutMedia Values

+ +

The cups_cut_t enumeration defines constants for the +CutMedia page device dictionary variable: + +

    + +
  • CUPS_CUT_NONE - Do no jogging + +
  • CUPS_CUT_FILE - Cut pages after each file + +
  • CUPS_CUT_JOB - Cut pages after each job + +
  • CUPS_CUT_SET - Cut pages after each set of jobs + +
  • CUPS_CUT_PAGE - Cut each page + +
+ +

Raster AdvanceMedia Values

+ +

The cups_advance_t enumeration defines constants for the +AdvanceMedia page device dictionary variable: + +

    + +
  • CUPS_ADVANCE_NONE - Do no jogging + +
  • CUPS_ADVANCE_FILE - Advance media after each file + +
  • CUPS_ADVANCE_JOB - Advance media after each job + +
  • CUPS_ADVANCE_SET - Advance media after each set of jobs + +
  • CUPS_ADVANCE_PAGE - Advance media for each page + +
+ +

Raster LeadingEdge Values

+ +

The cups_edge_t enumeration defines constants for the +LeadingEdge page device dictionary variable: + +

    + +
  • CUPS_EDGE_TOP - The top of the media is the leading + edge + +
  • CUPS_EDGE_RIGHT - The right of the media is the leading + edge + +
  • CUPS_EDGE_BOTTOM - The bottom of the media is the + leading edge + +
  • CUPS_EDGE_LEFT - The left of the media is the leading + edge + +
+ +

Raster Color Order Values

+ +

The cups_order_t enumeration defines the possible color +value orderings: + +

    + +
  • CUPS_ORDER_CHUNKED - CMYK CMYK CMYK + +
  • CUPS_ORDER_BANDED - CCC MMM YYY KKK + +
  • CUPS_ORDER_PLANAR - CCC ... MMM ... YYY ... KKK ... + +
+ +

Raster Colorspace Values

+ +

The cups_cspace_t enumeration defines the possible colorspaces: + +

    + +
  • CUPS_CSPACE_W - White (luminance) + +
  • CUPS_CSPACE_RGB - Red, green, blue + +
  • CUPS_CSPACE_RGBA - Red, green, blue, alpha + +
  • CUPS_CSPACE_K - Black + +
  • CUPS_CSPACE_CMY - Cyan, magenta, yellow + +
  • CUPS_CSPACE_YMC - Yellow, magenta, cyan + +
  • CUPS_CSPACE_CMYK - Cyan, magenta, yellow, black + +
  • CUPS_CSPACE_YMCK - Yellow, magenta, cyan, black + +
  • CUPS_CSPACE_KCMY - Black, cyan, magenta, yellow + +
  • CUPS_CSPACE_KCMYcm - Black, cyan, magenta, yellow, + light cyan, light magenta + +
  • CUPS_CSPACE_GMCK - Metallic yellow (gold), metallic magenta, + metallic cyan, black + +
  • CUPS_CSPACE_GMCS - Metallic yellow (gold), metallic magenta, + metallic cyan, metallic grey (silver) + +
  • CUPS_CSPACE_WHITE - White pigment (black as white pigment) + +
  • CUPS_CSPACE_GOLD - Gold foil (black as gold foil) + +
  • CUPS_CSPACE_SILVER - Silver foil (black as silver foil) + +
+ +

C - Structures

+ +

This appendix describes all of the structures that are +defined by the CUPS API. + +

CUPS Structures

+ +

CUPS Destinations

+ +

The CUPS destination structure (cups_dest_t) +contains information on a specific destination or instance: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
namechar *The name of the printer or class.
instancechar *The instance of the printer or class; NULL for the primary + instance.
is_defaultint1 if the destination is set as the default, 0 otherwise.
num_optionsintThe number of options associated with this destination.
optionscups_option_t *The options associated with this destination.
+ +

CUPS Jobs

+ +

The CUPS job structure (cups_job_t) contains +information on a specific job: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
idintThe job ID for this job.
destchar *The destination for this job (printer or class name).
titlechar *The job-name for this job (title).
userchar *The job-originating-user-name for this job (username).
formatchar *The document-format for this job (MIME type string).
stateipp_jstateThe current state of the job.
sizeintThe size of this job in kilobytes.
priorityintThe priority of this job from 1 to 100 (50 is normal).
completed_timetime_tThe time the job was completed, or 0 if not yet completed.
creation_timetime_tThe time the job was queued.
processing_timetime_tThe time the job started printing.
+ +

CUPS Messages

+ +

The CUPS messages structure (cups_lang_t) +contains the character set, locale name, and messages array: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
nextcups_lang_t *Pointer to the next messages structure in memory.
usedintThe number of active users of this messages structure.
encodingcups_encoding_tThe character encoding of the message strings.
languagechar [16]The language/locale name.
messageschar *[]The array of message strings.
+ +

CUPS Options

+ +

The CUPS option structure (cups_option_t) +contains the option name and string value: + +

+ + + + + + + + + + + + + + + +
MemberTypeDescription
namechar *The name of the option.
valuechar *The string value of the option.
+ +

Networking Structures

+ +

HTTP State

+ +

The HTTP state structure (http_t) contains the +current state of a HTTP request or response: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
fdintThe socket for the HTTP connection.
blockingint1 if the HTTP functions should block, 0 if not.
errorintThe last OS error that occurred on the socket.
activitytime_tThe last time the HTTP connection was used.
statehttp_state_tThe current HTTP request/response state.
statusintThe last HTTP status seen.
versionhttp_version_tThe HTTP protocol version in use.
keep_alivehttp_keep_alive_tWhether or not to use Keep-Alive
hostaddrstruct sockaddr_inThe IPv4 address of the HTTP server.
hostnamechar []The hostname of the HTTP server.
fieldschar [][]The string values of all HTTP request/response + fields.
datachar *Current byte in data buffer.
data_encodinghttp_encoding_tThe transfer encoding for the request/response.
data_remainingintThe number of bytes remaining in the current request, + response, or chunk.
usedintThe number of bytes that are used in the buffer.
bufferchar []The read/write buffer.
auth_typeintThe type of authentication in use.
md5_statemd5_state_tThe current MD5 digest state.
noncechar []The nonce value for Digest authentication.
nonce_countintThe nonce count value.
tlsvoid *A pointer to private encryption data.
encryptionhttp_encryption_tThe current encryption mode.
+ +

IPP State

+ +

The IPP state structure (ipp_t) contains the +current state of a IPP request or response: + +

+ + + + + + + + + + +
MemberTypeDescription
+ +

Raster Structures

+ +

Raster Page Header

+ +

The raster page header (cups_raster_header_t) +consists of the PostScript page device dictionary for the page: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MemberTypeDescription
MediaClasschar[64]The media class name
MediaColorchar[64]The media color name
MediaTypechar[64]The media type name
OutputTypechar[64]The output type name
AdvanceDistanceunsignedThe distance to advance the media in points
AdvanceMediacups_adv_tWhen to advance the media
Collatecups_bool_tWhether or not to produce collated copies
CutMediacups_cut_tWhen to cut the media
Duplexcups_bool_tWhether or not to print on both sides of the paper
HWResolutionunsigned[2]The resolution of the page image in pixels per inch; the + HWResolution[0] represents the horizontal resolution and + HWResolution[1] represents the vertical resolution
ImagingBoundingBoxunsigned[4]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)
InsertSheetcups_bool_tWhether or not to insert a sheet before this page
Jogcups_jog_tWhen to jog copies of the page
LeadingEdgecups_edge_tThe leading edge of the page
Marginsunsigned[2]The lower-lefthand margin of the page in points
ManualFeedcups_bool_tWhether or not to manually feed the page
MediaPositionunsignedThe input slot number to use
MediaWeightunsignedThe weight of the output media in grams/m2
MirrorPrintcups_bool_tWhether or not to mirror the print
NegativePrintcups_bool_tWhether or not to invert the print
NumCopiesunsignedThe number of copies to produce
Orientationcups_orient_tThe orientation of the page image
OutputFaceUpcups_bool_tWhether or not to output the page face up
PageSizeunsigned[2]The width and height of the page in points
Separationscups_bool_tWhether or not to output separations
TraySwitchcups_bool_tWhether or not to automatically switch trays for the requested + media size/type
Tumblecups_bool_tWhether or not to rotate the back side of the page
cupsWidthunsignedThe width of the page image in pixels
cupsHeightunsignedThe height of the page image in pixels
cupsMediaTypeunsignedThe device-specific media type code
cupsBitsPerColorunsignedThe number of bits per color
cupsBitsPerPixelunsignedThe number of bits per pixel
cupsBytesPerLineunsignedThe number of bytes per line of image data
cupsColorOrdercups_order_tThe order of color values
cupsColorSpacecups_cspace_tThe type of color values
cupsCompressionunsignedThe device-specific compression code
cupsRowCountunsignedThe device-specific row count
cupsRowFeedunsignedThe device-specific row feed
cupsRowStepunsignedThe device-specific row step
+ +

D - Functions

+ +

This appendix provides a reference for all of the CUPS API functions. + + +

cupsAddDest()

+ +

Usage

+ +
+int
+cupsAddDest(const char  *name,
+            const char  *instance,
+            int         num_dests,
+	    cups_dest_t **dests);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
nameThe name of the destination.
instanceThe instance of the destination, or NULL for the primary instance.
num_destsThe number of destinations in the array.
destA pointer to the destination array pointer.
+ +

Returns

+ +

The new number of destinations in the array. + +

Description

+ +

cupsAddDest() adds the named destination to the destination +array if it does not already exist. + +

Example

+ +
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+
+
+num_dests = cupsAddDests("foo", "bar", num_dests, &dests);
+
+ +

See Also

+ +

+cupsFreeDests(), +cupsGetDest(), +cupsGetDests() + + +

cupsAddOption()

+ +

Usage

+ +
+int
+cupsAddOption(const char    *name,
+              const char    *value,
+              int           num_options,
+	      cups_option_t **options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
nameThe name of the option.
valueThe value of the option.
num_optionsNumber of options currently in the array.
optionsPointer to the options array.
+ +

Returns

+ +

The new number of options. + +

Description

+ +

cupsAddOption() adds an option to the specified array. + +

Example

+ +
+#include <cups.h>
+
+...
+
+/* Declare the options array */
+int           num_options;
+cups_option_t *options;
+
+/* Initialize the options array */
+num_options = 0;
+options     = (cups_option_t *)0;
+
+/* Add options using cupsAddOption() */
+num_options = cupsAddOption("media", "letter", num_options, &options);
+num_options = cupsAddOption("resolution", "300dpi", num_options, &options);
+
+ +

See Also

+ +cupsEncodeOptions(), +cupsFreeOptions(), +cupsGetOption(), +cupsParseOptions() + + +

cupsCancelJob()

+ +

Usage

+ +
+int
+cupsCancelJob(const char *dest,
+              int        job);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
destPrinter or class name
jobJob ID
+ +

Returns

+ +

1 on success, 0 on failure. On failure the error can be found by calling +cupsLastError(). + +

Description

+ +

cupsCancelJob() cancels the specifies job. + +

Example

+ +
+#include <cups.h>
+
+cupsCancelJob("LaserJet", 1);
+
+ +

See Also

+ +

+cupsLastError(), +cupsPrintFile(), +cupsPrintFiles() + + +

cupsDoFileRequest()

+ +

Usage

+ +
+ipp_t *
+cupsDoFileRequest(http_t     *http,
+                  ipp_t      *request,
+                  const char *resource,
+		  const char *filename);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
filenameFile to send with POST request (NULL pointer if none.)
+ +

Returns

+ +

IPP response data or NULL if the request fails. On failure +the error can be found by calling +cupsLastError(). + +

Description

+ +

cupsDoFileRequest() 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. + +

Example

+ +
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_PRINT_FILE;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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 != NULL ? language->language : "C");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+             NULL, "ipp://hostname/resource");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+             NULL, cupsUser());
+
+/* Do the request... */
+response = cupsDoFileRequest(http, request, "/resource", "filename.txt");
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsUser(), +httpConnect(), +ippAddString(), +ippNew() + + +

cupsDoRequest()

+ +

Usage

+ +
+ipp_t *
+cupsDoRequest(http_t *http,
+              ipp_t *request,
+              const char *resource);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpHTTP connection to server.
requestIPP request data.
resourceHTTP resource name for POST.
+ +

Returns

+ +

IPP response data or NULL if the request fails. On failure +the error can be found by calling +cupsLastError(). + +

Description

+ +

cupsDoRequest() 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. + +

Example

+ +
+#include <cups.h>
+
+http_t      *http;
+cups_lang_t *language;
+ipp_t       *request;
+ipp_t       *response;
+
+...
+
+/* Get the default language */
+language = cupsLangDefault();
+
+/* Create a new IPP request */
+request  = ippNew();
+
+request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+request->request.op.request_id   = 1;
+
+/* Add required attributes */
+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 != NULL ? language->language : "C");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+             NULL, "ipp://hostname/resource");
+
+/* Do the request... */
+response = cupsDoRequest(http, request, "/resource");
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsUser(), +httpConnect(), +ippAddString(), +ippNew() + + +

cupsEncodeOptions()

+ +

Usage

+ +
+void
+cupsEncodeOptions(ipp_t         *ipp,
+                  int           num_options,
+		  cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request.
num_optionsThe number of options.
optionsThe options.
+ +

Description

+ +

cupsEncodeOptions() encodes all of the options +in the specified array as IPP attributes and adds them to the +IPP request. + +

Example

+ +
+#include <cups/cups.h>
+
+ipp_t         *ipp;
+int           num_options;
+cups_option_t *options;
+
+
+cupsEncodeOptions(ipp, num_options, options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsParseOptions(), +ippNew() + + +

cupsEncryption()

+ +

Usage

+ +
+http_encryption_t
+cupsEncryption(void);
+
+ +

Returns

+ +

The current encryption setting. + +

Description

+ +

cupsEncryption() returns the current encryption setting +for IPP requests such as printing. + +

Example

+ +
+#include <cups/cups.h>
+
+http_t *http;
+
+printf("The current encryption setting is %d.\n", cupsEncryption());
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ +

See Also

+ +

+cupsServer(), +httpConnectEncrypt(), +ippPort() + + +

cupsFreeDests()

+ +

Usage

+ +
+void
+cupsFreeDests(int         num_dests,
+              cups_dest_t *dests);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
num_destsThe number of destinations in the array.
destsThe destination array.
+ +

Description

+ +

cupsFreeDests() frees a destination array that was +created using cupsGetDests(). + +

Example

+ +
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&dests);
+dest      = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+  printf("The default destination is %s\n", dest->name);
+else
+  puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+
+ +

See Also

+ +

+cupsGetDest(), +cupsGetDests() + + +

cupsFreeJobs()

+ +

Usage

+ +
+void
+cupsFreeJobs(int        num_jobs,
+             cups_job_t *jobs);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
num_jobsThe number of jobs.
jobsThe job array.
+ +

Description

+ +

cupsFreeJobs() frees an array of print jobs created by +the cupsGetJobs() function. + +

Example

+ +
+#include <cups/cups.h>
+
+int        i;
+int        num_jobs;
+cups_job_t *jobs;
+
+
+num_jobs = cupsGetJobs(&jobs, NULL, 0, 0);
+
+printf("%d active job(s):\n", num_jobs);
+for (i = 0; i < num_jobs; i ++)
+  printf("%-16.16s %-6d %-12.12s %s (%s)\n", jobs[i].dest, jobs[i].id,
+         jobs[i].user, jobs[i].title,
+	 jobs[i].state != IPP_JOB_PENDING ? "printing" : "pending");
+
+cupsFreeJobs(num_jobs, jobs);
+
+ +

See Also

+ +

+cupsGetJobs(), +cupsGetDests() + + +

cupsFreeOptions()

+ +

Usage

+ +
+void
+cupsFreeOptions(int           num_options,
+                cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
num_optionsNumber of options in array.
optionsPointer to options array.
+ +

Description

+ +

cupsFreeOptions() frees all memory associated with the +option array specified. + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsEncodeOptions(), +cupsGetOption(), +cupsMarkOptions(), +cupsParseOptions() + + +

cupsGetClasses()

+ +

Usage

+ +
+int
+cupsGetClasses(char ***classes);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
classesPointer to character pointer array.
+ +

Returns

+ +

The number of printer classes available. + +

Description

+ +

cupsGetClasses() gets a list of the available printer classes. +The returned array should be freed using the free() when it is +no longer needed. + +

Example

+ +
+#include <cups/cups.h>
+
+int  i;
+int  num_classes;
+char **classes;
+
+...
+
+num_classes = cupsGetClasses(&classes);
+
+...
+
+if (num_classes > 0)
+{
+  for (i = 0; i < num_classes; i ++)
+    free(classes[i]);
+
+  free(classes);
+}
+
+ +

See Also

+ +

+cupsGetDefault(), +cupsGetPrinters() + + +

cupsGetDefault()

+ +

Usage

+ +
+const char *
+cupsGetDefault(void);
+
+ +

Returns

+ +

A pointer to the default destination. + +

Description

+ +

cupsGetDefault() 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. + +

Example

+ +
+#include <cups/cups.h>
+
+printf("The default destination is %s\n", cupsGetDefault());
+
+ +

See Also

+ +

+cupsGetClasses(), +cupsGetPrinters() + + +

cupsGetDest()

+ +

Usage

+ +
+cups_dest_t *
+cupsGetDest(const char  *name,
+            const char  *instance,
+            int         num_dests,
+            cups_dest_t *dests);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
nameThe name of the destination, or NULL for the default destination.
instanceThe instance of the destination, or NULL for the primary instance.
num_destsThe number of destinations.
destsThe destination array.
+ +

Returns

+ +

A pointer to the specified destination, or NULL if none exists. + +

Description

+ +

cupsGetDest() finds the specified destination in the array +of destinations created by the cupsGetDests() function. + +

Example

+ +
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&dests);
+dest      = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+  printf("The default destination is %s\n", dest->name);
+else
+  puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+
+ +

See Also

+ +

+cupsGetDests(), +cupsGetJobs() + + +

cupsGetDests()

+ +

Usage

+ +
+int
+cupsGetDests(cups_dest_t **dests);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
destsA pointer to a destination array pointer.
+ +

Returns

+ +

The number of available destinations. + +

Description

+ +

cupsGetDests() creates an array of available +destinations that the user can print to. The array should be +freed using the cupsFreeDests() function. + +

Example

+ +
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&dests);
+dest      = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+  printf("The default destination is %s\n", dest->name);
+else
+  puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+
+ +

See Also

+ +

+cupsFreeDests(), +cupsGetDest(), +cupsGetJobs() + + +

cupsGetJobs()

+ +

Usage

+ +
+int
+cupsGetJobs(cups_job_t **jobs,
+            const char *dest,
+            int        myjobs,
+            int        completed);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
jobsA pointer to the job array pointer.
destThe destination name, or NULL if jobs for all destinations are requested.
myjobs1 if only those jobs submitted by the current + cupsUser() should be returned, 0 for jobs + submitted by all users.
completed1 if only completed jobs should be returned, 0 if only + pending/processing jobs should be returned.
+ +

Returns

+ +

The number of jobs. + +

Description

+ +

cupsGetJobs() creates an array of print jobs based on the +arguments supplied in the function call. The returned array should be freed +using the cupsFreeJobs() function. + +

Example

+ +
+#include <cups/cups.h>
+
+int        i;
+int        num_jobs;
+cups_job_t *jobs;
+
+
+num_jobs = cupsGetJobs(&jobs, NULL, 0, 0);
+
+printf("%d active job(s):\n", num_jobs);
+for (i = 0; i < num_jobs; i ++)
+  printf("%-16.16s %-6d %-12.12s %s (%s)\n", jobs[i].dest, jobs[i].id,
+         jobs[i].user, jobs[i].title,
+	 jobs[i].state != IPP_JOB_PENDING ? "printing" : "pending");
+
+cupsFreeJobs(num_jobs, jobs);
+
+ +

See Also

+ +

+cupsFreeJobs(), +cupsGetDests() + + +

cupsGetOption()

+ +

Usage

+ +
+const char *
+cupsGetOption(const char    *name,
+              int           num_options,
+              cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
nameThe name of the option.
num_optionsThe number of options in the array.
optionsThe options array.
+ +

Returns

+ +

A pointer to the option values or NULL if the option is +not defined. + +

Description

+ +

cupsGetOption() returns the first occurrence of the +named option. If the option is not included in the options array then a +NULL pointer is returned. + +

+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+const char    *media;
+
+...
+
+media = cupsGetOption("media", num_options, options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsEncodeOptions(), +cupsFreeOptions(), +cupsMarkOptions(), +cupsParseOptions() + + +

cupsGetPassword()

+ +

Usage

+ +
+const char *
+cupsGetPassword(const char *prompt);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
promptThe prompt to display to the user.
+ +

Returns

+ +

A pointer to the password that was entered or NULL if no +password was entered. + +

Description

+ +

cupsGetPassword() displays the prompt string and asks the user +for a password. The password text is not echoed to the user. + +

Example

+ +
+#include <cups/cups.h>
+
+char *password;
+
+...
+
+password = cupsGetPassword("Please enter a password:");
+
+ +

See Also

+ +

+cupsServer(), +cupsSetPasswordCB(), +cupsSetServer(), +cupsSetUser(), +cupsUser() + + +

cupsGetPPD()

+ +

Usage

+ +
+const char *
+cupsGetPPD(const char *printer);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
printerThe name of the printer.
+ +

Returns

+ +

The name of a temporary file containing the PPD file or NULL +if the printer cannot be located or does not have a PPD file. + +

Description

+ +

cupsGetPPD() gets a copy of the PPD file for the named printer. +The printer name can be of the form "printer" or "printer@hostname". + +

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 cupsGetPPD(). + +

Example

+ +
+#include <cups/cups.h>
+
+char *ppd;
+
+...
+
+ppd = cupsGetPPD("printer@hostname");
+
+...
+
+unlink(ppd);
+
+ + +

cupsGetPrinters()

+ +

Usage

+ +
+int
+cupsGetPrinters(char ***printers);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
printersPointer to character pointer array.
+ +

Returns

+ +

The number of printer printers available. + +

Description

+ +

cupsGetPrinters() gets a list of the available printers. +The returned array should be freed using the free() when it is +no longer needed. + +

Example

+ +
+#include <cups/cups.h>
+
+int  i;
+int  num_printers;
+char **printers;
+
+...
+
+num_printers = cupsGetPrinters(&printers);
+
+...
+
+if (num_printers > 0)
+{
+  for (i = 0; i < num_printers; i ++)
+    free(printers[i]);
+
+  free(printers);
+}
+
+ +

See Also

+ +

+cupsGetClasses() +cupsGetDefault() + + +

cupsLangDefault()

+ +

Usage

+ +
+const char *
+cupsLangDefault(void);
+
+ +

Returns

+ +

A pointer to the default language structure. + +

Description

+ +

cupsLangDefault() returns a language structure for the default +language. The default language is defined by the LANG environment +variable. If the specified language cannot be located then the POSIX (English) +locale is used. + +

Call cupsLangFree() to free any memory associated with the +language structure when you are done. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+language = cupsLangDefault();
+
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangEncoding(), +cupsLangFlush(), +cupsLangFree(), +cupsLangGet(), +cupsLangString() + + +

cupsLangEncoding()

+ +

Usage

+ +
+char *
+cupsLangEncoding(cups_lang_t *language);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
languageThe language structure.
+ +

Returns

+ +

A pointer to the encoding string. + +

Description

+ +

cupsLangEncoding() returns the language encoding used for the +specified language, e.g. "iso-8859-1", "utf-8", etc. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *encoding;
+...
+
+language = cupsLangDefault();
+encoding = cupsLangEncoding(language);
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangFlush(), +cupsLangFree(), +cupsLangGet(), +cupsLangString() + + +

cupsLangFlush()

+ +

Usage

+ +
+void
+cupsLangFlush(void);
+
+ +

Description

+ +

cupsLangFlush() frees all language structures that have been +allocated. + +

Example

+ +
+#include <cups/language.h>
+
+...
+
+cupsLangFlush();
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFree(), +cupsLangGet(), +cupsLangString() + + +

cupsLangFree()

+ +

Usage

+ +
+void
+cupsLangFree(cups_lang_t *language);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
languageThe language structure to free.
+ +

Description

+ +

cupsLangFree() frees the specified language structure. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFlush(), +cupsLangGet(), +cupsLangString() + + +

cupsLangGet()

+ +

Usage

+ +
+cups_lang_t *
+cupsLangGet(const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
nameThe name of the locale.
+ +

Returns

+ +

A pointer to a language structure. + +

Description

+ +

cupsLangGet() returns a language structure for the specified +locale. If the locale is not defined then the POSIX (English) locale is +substituted. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+
+...
+
+language = cupsLangGet("fr");
+
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFlush(), +cupsLangFree(), +cupsLangString() + + +

cupsLangString()

+ +

Usage

+ +
+char *
+cupsLangString(cups_lang_t *language,
+               int         message);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
languageThe language to query.
messageThe message number.
+ +

Returns

+ +

A pointer to the message string or NULL if the message is +not defined. + +

Description

+ +

cupsLangString() returns a pointer to the specified message +string in the specified language. + +

Example

+ +
+#include <cups/language.h>
+
+cups_lang_t *language;
+char        *s;
+...
+
+language = cupsLangGet("fr");
+
+s = cupsLangString(language, CUPS_MSG_YES);
+
+...
+
+cupsLangFree(language);
+
+ +

See Also

+ +

+cupsLangDefault(), +cupsLangEncoding(), +cupsLangFlush(), +cupsLangFree(), +cupsLangGet() + + +

cupsLastError()

+ +

Usage

+ +
+ipp_status_t
+cupsLastError(void);
+
+ +

Returns

+ +

An enumeration containing the last IPP error. + +

Description

+ +

cupsLastError() returns the last IPP error that occurred. +If no error occurred then it will return IPP_OK or +IPP_OK_CONFLICT. + +

Example

+ +
+#include <cups/cups.h>
+
+ipp_status_t status;
+
+...
+
+status = cupsLastError();
+
+ +

See Also

+ +

+cupsCancelJob(), +cupsPrintFile() + + +

cupsMarkOptions()

+ +

Usage

+ +
+int
+cupsMarkOptions(ppd_file_t    *ppd,
+                int           num_options,
+                cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file to mark.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+ +

Returns

+ +

The number of conflicts found. + +

Description

+ +

cupsMarkOptions() marks options in the PPD file. It also +handles mapping of IPP option names and values to PPD option names. + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+ppd_file_t    *ppd;
+
+...
+
+cupsMarkOptions(ppd, num_options, options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsFreeOptions(), +cupsGetOption(), +cupsParseOptions() + + +

cupsParseOptions()

+ +

Usage

+ +
+int
+cupsParseOptions(const char    *arg,
+                 int           num_options,
+                 cups_option_t **options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
argThe string containing one or more options.
num_optionsThe number of options in the options array.
optionsA pointer to the options array pointer.
+ +

Returns

+ +

The new number of options in the array. + +

Description

+ +

cupsParseOptions() parses the specifies string for one +or more options of the form "name=value", "name", or "noname". It can +be called multiple times to combine the options from several strings. + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+
+...
+
+num_options = 0;
+options     = (cups_option_t *)0;
+num_options = cupsParseOptions(argv[5], num_options, &options);
+
+ +

See Also

+ +

+cupsAddOption(), +cupsFreeOptions(), +cupsGetOption(), +cupsMarkOptions() + + +

cupsPrintFile()

+ +

Usage

+ +
+int
+cupsPrintFile(const char    *printer,
+              const char    *filename,
+              const char    *title,
+	      int           num_options,
+	      cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
printerThe printer or class to print to.
filenameThe file to print.
titleThe job title.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+ +

Returns

+ +

The new job ID number or 0 on error. + +

Description

+ +

cupsPrintFile() 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 cupsLastError(). + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_options;
+cups_option_t *options;
+int           jobid;
+
+...
+
+jobid = cupsPrintFile("printer@hostname", "filename.ps", "Job Title",
+                      num_options, options);
+
+ +

See Also

+ +

+cupsCancelJob(), +cupsLastError(), +cupsPrintFiles() + + +

cupsPrintFiles()

+ +

Usage

+ +
+int
+cupsPrintFiles(const char    *printer,
+               int           num_files,
+               const char    **files,
+               const char    *title,
+	       int           num_options,
+	       cups_option_t *options);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
printerThe printer or class to print to.
num_filesThe number of files to print.
filesThe files to print.
titleThe job title.
num_optionsThe number of options in the options array.
optionsA pointer to the options array.
+ +

Returns

+ +

The new job ID number or 0 on error. + +

Description

+ +

cupsPrintFiles() 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 cupsLastError(). + +

Example

+ +
+#include <cups/cups.h>
+
+int           num_files;
+const char    *files[100];
+int           num_options;
+cups_option_t *options;
+int           jobid;
+
+...
+
+jobid = cupsPrintFiles("printer@hostname", num_files, files,
+                       "Job Title", num_options, options);
+
+ +

See Also

+ +

+cupsCancelJob(), +cupsLastError(), +cupsPrintFile() + + +

cupsRasterClose()

+ +

Usage

+ +
+void
+cupsRasterClose(cups_raster_t *ras);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
rasThe raster stream to close.
+ +

Description

+ +

cupsRasterClose() closes the specified raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+cupsRasterClose(ras);
+
+ +

See Also

+ +

+cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + + +

cupsRasterOpen()

+ +

Usage

+ +
+cups_raster_t *
+cupsRasterOpen(int         fd,
+               cups_mode_t mode);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
fdThe file descriptor to use.
modeThe mode to use; CUPS_RASTER_READ or + CUPS_RASTER_WRITE.
+ +

Returns

+ +

A pointer to a raster stream or NULL if there was an error. + +

Description

+ +

cupsRasterOpen() opens a raster stream for reading or writing. + +

Example

+ +
+#include <cups/raster.h>
+
+cups_raster_t *ras;
+
+...
+
+ras = cupsRasterOpen(0, CUPS_RASTER_READ);
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + + +

cupsRasterReadHeader()

+ +

Usage

+ +
+unsigned
+cupsRasterReadHeader(cups_raster_t      *ras,
+                     cups_page_header_t *header);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to read from.
headerA pointer to a page header structure to read into.
+ +

Returns

+ +

1 on success, 0 on EOF or error. + +

Description

+ +

cupsRasterReadHeader() reads a page header from the specified +raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadPixels(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + + +

cupsRasterReadPixels()

+ +

Usage

+ +
+unsigned
+cupsRasterReadPixels(cups_raster_t *ras,
+                     unsigned char *pixels,
+		     unsigned      length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to read from.
pixelsThe pointer to a pixel buffer.
lengthThe number of bytes of pixel data to read.
+ +

Returns

+ +

The number of bytes read or 0 on EOF or error. + +

Description

+ +

cupsRasterReadPixels() reads pixel data from the specified +raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &header))
+{
+  ...
+
+  for (line = 0; line < header.cupsHeight; line ++)
+  {
+    cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+    ...
+  }
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterWriteHeader(), +cupsRasterWritePixels() + + +

cupsRasterWriteHeader()

+ +

Usage

+ +
+unsigned
+cupsRasterWriteHeader(cups_raster_t      *ras,
+                      cups_page_header_t *header);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to write to.
headerA pointer to the page header to write.
+ +

Returns

+ +

1 on success, 0 on error. + +

Description

+ +

cupsRasterWriteHeader() writes the specified page header to +a raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWritePixels() + + +

cupsRasterWritePixels()

+ +

Usage

+ +
+unsigned
+cupsRasterWritePixels(cups_raster_t *ras,
+                      unsigned char *pixels,
+		      unsigned      length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
rasThe raster stream to write to.
pixelsThe pixel data to write.
lengthThe number of bytes to write.
+ +

Returns

+ +

The number of bytes written. + +

Description

+ +

cupsRasterWritePixels() writes the specified pixel data to a +raster stream. + +

Example

+ +
+#include <cups/raster.h>
+
+int                  line;
+cups_raster_t        *ras;
+cups_raster_header_t header;
+unsigned char        pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &header);
+
+for (line = 0; line < header.cupsHeight; line ++)
+{
+  ...
+
+  cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+
+ +

See Also

+ +

+cupsRasterClose(), +cupsRasterOpen(), +cupsRasterReadHeader(), +cupsRasterReadPixels(), +cupsRasterWriteHeader() + + +

cupsServer()

+ +

Usage

+ +
+const char *
+cupsServer(void);
+
+ +

Returns

+ +

A pointer to the default server name. + +

Description

+ +

cupsServer() 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 cupsServer(). + +

The default server is determined from the following locations: + +

    + +
  1. The CUPS_SERVER environment variable, + +
  2. The ServerName directive in the + client.conf file, + +
  3. The default host, "localhost". + +
+ +

Example

+ +
+#include <cups/cups.h>
+
+const char *server;
+
+server = cupsServer();
+
+ +

See Also

+ +

+cupsGetPassword(), +cupsSetPasswordCB(), +cupsSetServer(), +cupsSetUser(), +cupsUser() + + +

cupsSetDests()

+ +

Usage

+ +
+void
+cupsSetDests(int         num_dests,
+             cups_dest_t *dests);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
num_destsNumber of destinations.
destsArray of destinations.
+ +

Description

+ +

cupsSetDests() saves the destination array to +disk. If the current UID is 0, the destinations are saved in the +/etc/cups/lpoptions file, otherwise they are saved +in the ~/.lpoptions file. This function is typically used +to save the default options and instances that are set by the user. + +

Example

+ +
+#include <cups/cups.h>
+
+int         num_dests;
+cups_dest_t *dests;
+
+...
+
+cupsSetDests(num_dests, dests);
+
+ +

See Also

+ +

+cupsGetDests() + + +

cupsSetEncryption()

+ +

Usage

+ +
+void
+cupsSetEncryption(http_encryption_t encryption);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
encryptionThe type of encryption to use.
+ +

Description

+ +

cupsSetEncryption() sets the default type of encryption to +use when connecting with the print server. + +

Example

+ +
+#include <cups/cups.h>
+
+cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+ +

See Also

+ +

+cupsEncryption() + + +

cupsSetPasswordCB()

+ +

Usage

+ +
+void
+cupsSetPasswordCB(const char *(*cb)(const char *prompt));
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
cbThe password callback function.
+ +

Description

+ +

cupsSetPasswordCB() 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 NULL +if the user did not enter a password string or a pointer to the password +string otherwise. + +

Example

+ +
+#include <cups/cups.h>
+
+const char *
+my_password_cb(const char *prompt)
+{
+  return (getpass(prompt));
+}
+
+...
+
+char *password;
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+password = cupsGetPassword("Please enter a password:");
+
+ +

See Also

+ +

+cupsServer(), +cupsSetServer(), +cupsSetUser(), +cupsUser() + + +

cupsSetServer()

+ +

Usage

+ +
+void
+cupsSetServer(const char *server);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
serverThe default server to use.
+ +

Description

+ +

cupsSetServer() sets the default server to use for +the CUPS API. If the server argument is NULL, +the default server is used. + +

Example

+ +
+#include <cups/cups.h>
+
+cupsSetServer("foo.bar.com");
+
+ +

See Also

+ +

+cupsServer(), +cupsSetPasswordCB(), +cupsSetUser(), +cupsUser() + + +

cupsSetUser()

+ +

Usage

+ +
+void
+cupsSetUser(const char *user);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
userThe user name string to use.
+ +

Description

+ +

cupsSetUser() sets the default user name for authentication. +If the user argument is NULL then the current +login user is used. + +

Example

+ +
+#include <cups/cups.h>
+
+...
+
+cupsSetUser("root");
+
+ +

See Also

+ +

+cupsServer(), +cupsSetPasswordCB(), +cupsSetServer(), +cupsUser() + + +

cupsTempFd()

+ +

Usage

+ +
+int
+cupsTempFd(char *filename,
+           int  length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
filenameThe character string to hold the temporary filename.
lengthThe size of the filename string in bytes.
+ +

Returns

+ +

A file descriptor open for reading and writing. + +

Description

+ +

cupsTempFd() create a temporary filename in the +/var/tmp directory or the directory specified by the +TMPDIR environment variable. + +

Example

+ +
+#include <cups/cups.h>
+
+int  fd;
+char filename[256];
+
+fd = cupsTempFd(filename, sizeof(filename));
+
+ +

See Also

+ +

+cupsTempFile() + + +

cupsTempFile()

+ +

Usage

+ +
+char *
+cupsTempFile(char *filename,
+             int  length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
filenameThe character string to hold the temporary filename.
lengthThe size of the filename string in bytes.
+ +

Returns

+ +

A pointer to filename. + +

Description

+ +

cupsTempFile() creates a temporary filename in the +/var/tmp directory or the directory specified by the +TMPDIR environment variable. + +

Example

+ +
+#include <cups/cups.h>
+
+char filename[256];
+
+cupsTempFile(filename, sizeof(filename));
+
+ +

See Also

+ +

+cupsTempFd() + + +

cupsUser()

+ +

Usage

+ +
+const char *
+cupsUser(void);
+
+ +

Returns

+ +

A pointer to the current username or NULL if the user ID is +undefined. + +

Description

+ +

cupsUser() returns the name associated with the current +user ID as reported by the getuid() system call. + +

Example

+ +
+#include <cups/cups.h>
+
+const char *user;
+
+user = cupsUser();
+
+ +

See Also

+ +

+cupsGetPassword(), +cupsServer() + + +

httpBlocking()

+ +

Usage

+ +
+void
+httpBlocking(http_t *http,
+             int    blocking)
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
blocking0 if the connection should be non-blocking, 1 if it should + be blocking
+ +

Description

+ +

The httpBlocking() 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. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect("server", port);
+httpBlocking(http, 0);
+
+ +

See Also

+ +httpCheck(), +httpConnect() + + +

httpCheck()

+ +

Usage

+ +
+int
+httpCheck(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

0 if there is no data pending, 1 otherwise. + +

Description

+ +

The httpCheck() function checks to see if there is any data +pending on an HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpCheck(http))
+{
+  ... do something ...
+}
+
+ +

See Also

+ +httpBlocking(), +httpConnect(), +httpGets(), +httpRead() + + +

httpClearFields()

+ +

Usage

+ +
+void
+httpClearFields(http_t *http)
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Description

+ +

The httpClearFields() function clears all HTTP request fields +for the HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpClearFields(http);
+
+ +

See Also

+ +httpConnect(), +httpGetField(), +httpSetField() + + +

httpClose()

+ +

Usage

+ +
+void
+httpClose(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Description

+ +

The httpClose() function closes an active HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpClose(http);
+
+ +

See Also

+ +httpConnect() + + +

httpConnect()

+ +

Usage

+ +
+http_t *
+httpConnect(const char *hostname,
+            int        port);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
hostnameThe name or IP address of the server to connect to
portThe port number to use
+ +

Returns

+ +

A pointer to a HTTP connection structure or NULL if the connection could +not be made. + +

Description

+ +

The httpConnect() function opens a HTTP connection to the +specified server and port. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+ +

See Also

+ +httpClose(), +httpConnectEncrypt(), +httpGet(), +httpGets(), +httpPost(), +httpRead(), +httpWrite() + + +

httpConnectEncrypt()

+ +

Usage

+ +
+http_t *
+httpConnectEncrypt(const char        *hostname,
+                   int               port,
+                   http_encryption_t encryption);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
hostnameThe name or IP address of the server to connect to
portThe port number to use
encryptionThe level of encryption to use
+ +

Returns

+ +

A pointer to a HTTP connection structure or NULL if the connection could +not be made. + +

Description

+ +

The httpConnectEncrypt() function opens a HTTP +connection to the specified server, port, and encryption. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ +

See Also

+ +httpClose(), +httpConnect(), +httpGet(), +httpGets(), +httpPost(), +httpRead(), +httpWrite() + + +

httpDecode64()

+ +

Usage

+ +
+char *
+httpDecode64(char       *out,
+             const char *in);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
outThe output string
inThe input string
+ +

Returns

+ +

A pointer to the decoded string. + +

Description

+ +

The httpDecode64() function decodes a base-64 encoded string +to the original string. + +

Example

+ +
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpDecode64(original_string, encoded_string);
+
+ +

See Also

+ +httpEncode64() + + +

httpDelete()

+ +

Usage

+ +
+int
+httpDelete(http_t     *http,
+           const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to delete
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpDelete() function sends a HTTP DELETE request to +the server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpEncode64()

+ +

Usage

+ +
+char *
+httpEncode64(char       *out,
+             const char *in);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
outThe output string
inThe input string
+ +

Returns

+ +

A pointer to the encoded string. + +

Description

+ +

The httpEncode64() function decodes a base-64 encoded string +to the original string. + +

Example

+ +
+#include <cups/http.h>
+
+char encoded_string[255];
+char original_string[255];
+
+httpEncode64(encoded_string, original_string);
+
+ +

See Also

+ +httpDecode64() + + +

httpEncryption()

+ +

Usage

+ +
+int
+httpEncryption(http_t            *http,
+               http_encryption_t encryption);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection.
encryptionThe desired level of encryption.
+ +

Returns

+ +

0 on success, -1 on error. + +

Description

+ +

httpEncryption() sets the encryption level for the HTTP +connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+...
+
+httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+
+ +

See Also

+ +

+httpConnectEncrypt() + + +

httpError()

+ +

Usage

+ +
+int
+httpError(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

The last error that occurred or 0 if no error has occurred. + +

Description

+ +

The httpError() function returns the last error that occurred +on the HTTP connection. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+if (httpError(http))
+{
+  ... show an error message ...
+}
+
+ +

See Also

+ +httpConnect() + + +

httpFlush()

+ +

Usage

+ +
+void
+httpFlush(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Description

+ +

The httpFlush() function flushes any remaining data left from +a GET or POST operation. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpFlush(http);
+
+ +

See Also

+ +httpConnect(), + + +

httpGet()

+ +

Usage

+ +
+int
+httpGet(http_t     *http,
+        const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to get
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpGet() function sends a HTTP GET request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpGets()

+ +

Usage

+ +
+char *
+httpGets(char   *line,
+         int    length,
+         http_t *http)
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
lineThe string to fill with a line from the HTTP connection
lengthThe maximum length of the string
httpThe HTTP connection
+ +

Returns

+ +

A pointer to the string or NULL if no line could be retrieved. + +

Description

+ +

The httpGets() function is used to read a request line from +the HTTP connection. It is not normally used by a client program. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+char   line[1024];
+
+if (httpGets(line, sizeof(line), http))
+{
+  ... process the line ...
+}
+
+ +

See Also

+ +httpConnect(), +httpUpdate() + + +

httpGetDateString()

+ +

Usage

+ +
+const char *
+httpGetDateString(time_t time)
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
timeThe UNIX date/time value
+ +

Returns

+ +

A pointer to a static string containing the HTTP date/time string for +the specified UNIX time value. + +

Description

+ +

The httpGetDateString() function generates a date/time string +suitable for HTTP requests from a UNIX time value. + +

Example

+ +
+#include <cups/http.h>
+
+puts(httpGetDateString(time(NULL)));
+
+ +

See Also

+ +httpGetDateTime() + + +

httpGetDateTime()

+ +

Usage

+ +
+time_t
+httpGetDateTime(const char *date)
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
dateThe HTTP date/time string
+ +

Returns

+ +

A UNIX time value. + +

Description

+ +

The httpGetDateTime() function converts a HTTP +date/time string to a UNIX time value. + +

Example

+ +
+#include <cups/http.h>
+
+printf("%d\n", httpGetDateTime("Fri, 30 June 2000 12:34:56 GMT"));
+
+ +

See Also

+ +httpGetDateString() + + +

httpGetField()

+ +

Usage

+ +
+const char *
+httpGetField(http_t       *http,
+             http_field_t field);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
+ +

Returns

+ +

A pointer to the field value string. + +

Description

+ +

The httpGetField() function returns the current value for +the specified HTTP field. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetField(http, HTTP_FIELD_CONTENT_TYPE));
+
+ +

See Also

+ +httpConnect(), +httpGetSubField(), +httpSetField() + + +

httpGetHostByName()

+ +

Usage

+ +
+struct hostent	*
+httpGetHostByName(const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
nameName or IP address to lookup.
+ +

Returns

+ +

NULL if the host could not be found or a pointer to a host entry +containing one or more addresses. + +

Description

+ +

httpGetHostByName() is a portable wrapper around the +gethostbyname() function which handles both hostnames +and IP addresses. + +

Example

+ +
+#include <cups/http.h>
+
+struct hostent *hostaddr;
+
+hostaddr = httpGetHostByName("foo.bar.com");
+
+ + +

httpGetLength()

+ +

Usage

+ +
+int
+httpGetLength(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection.
+ +

Returns

+ +

The content length of the response or MAX_INT if chunking is used. + +

Description

+ +

httpGetLength() returns the content length of a response. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+...
+
+printf("The length of the response is %d bytes.\n", httpGetLength(http));
+
+ +

See Also

+ +

+httpGet(), +httpPost() + + +

httpGetSubField()

+ +

Usage

+ +
+const char *
+httpGetSubField(http_t       *http,
+                http_field_t field,
+		const char   *name,
+		char         *value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection.
fieldThe HTTP field.
nameThe name of the subfield.
valueThe string to hold the subfield value.
+ +

Returns

+ +

A pointer to the subfield value string or NULL if it does not exist. + +

Description

+ +

The httpGetSubField() function returns a subfield value +from the specified HTTP field. The destination string buffer must be at +least HTTP_MAX_VALUE bytes in length. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+char   value[HTTP_MAX_VALUE];
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetSubField(http, HTTP_FIELD_CONTENT_TYPE, "charset", value));
+
+ +

See Also

+ +httpConnect(), +httpGetField(), +httpSetField() + + +

httpHead()

+ +

Usage

+ +
+int
+httpHead(http_t     *http,
+         const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to head
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpHead() function sends a HTTP HEAD request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpHead(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpInitialize()

+ +

Usage

+ +
+void httpInitialize(void);
+
+ +

Description

+ +

The httpInitialize() function initializes the networking +code as needed by the underlying platform. It is called automatically by +the httpConnect() function. + +

Example

+ +
+#include <cups/http.h>
+
+httpInitialize();
+
+ +

See Also

+ +httpConnect() + + +

httpMD5()

+ +

Usage

+ +
+char *
+httpMD5(const char *username,
+        const char *realm,
+        const char *passwd,
+        char       md5[33]);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
usernameThe authenticating user name.
realmThe authenticating realm name.
passwdThe authenticating password.
md5The MD5 sum string.
+ +

Returns

+ +

A pointer to the MD5 sum string. + +

Description

+ +

httpMD5() computes the MD5 hash of the username, +realm, and password as required by the HTTP Digest specification. + +

Example

+ +
+#include <cups/http.h>
+
+char md5[33];
+
+...
+
+httpMD5("user", "realm", "password", md5);
+
+ +

See Also

+ +

+httpMD5Final(), +httpMD5String() + + +

httpMD5Final()

+ +

Usage

+ +
+char *
+httpMD5Final(const char *nonce,
+             const char *method,
+             const char *resource,
+             char       md5[33]);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
nonceThe server nonce value.
methodThe HTTP method (GET, POST, etc.)
resourceThe resource path.
md5The MD5 sum string.
+ +

Returns

+ +

The MD5 sum string. + +

Description

+ +

httpMD5Final() appends the nonce, method, and resource +to the specified MD5 sum. + +

Example

+ +
+#include <cups/http.h>
+
+char md5[33];
+
+...
+
+httpMD5Final("nonce", "GET", "/jobs", md5);
+
+ +

See Also

+ +

+httpMD5(), +httpMD5String() + + +

httpMD5String()

+ +

Usage

+ +
+char *
+httpMD5String(const md5_byte_t *sum,
+              char             md5[33]);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
sumThe raw MD5 sum data.
md5The MD5 sum string.
+ +

Returns

+ +

The MD5 sum string. + +

Description

+ +

httpMD5String() converts the raw MD5 sum value to a string. + +

Example

+ +
+#include <cups/http.h>
+
+md5_byte_t sum[16];
+char       md5[33];
+
+...
+
+httpMD5String(sum, md5);
+
+ +

See Also

+ +

+httpMD5(), +httpMD5Final() + + +

httpOptions()

+ +

Usage

+ +
+int
+httpOptions(http_t     *http,
+            const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to check for options
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpOptions() function sends a HTTP OPTIONS request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpOptions(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpPost()

+ +

Usage

+ +
+int
+httpPost(http_t     *http,
+         const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to post to
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpPost() function sends a HTTP POST request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpPost(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpPrintf()

+ +

Usage

+ +
+int
+httpPrintf(http_t     *http,
+           const char *format,
+           ...);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
formatA printf-style format string
+ +

Returns

+ +

The number of bytes written. + +

Description

+ +

The httpPrintf() function sends a formatted string to the +HTTP connection. It is normally only used by the CUPS API and scheduler. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpPrintf(http, "GET / HTTP/1.1 \r\n");
+
+ +

See Also

+ +httpConnect() + + +

httpPut()

+ +

Usage

+ +
+int
+httpPut(http_t     *http,
+        const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to put
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpPut() function sends a HTTP PUT request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpRead()

+ +

Usage

+ +
+int
+httpRead(http_t *http,
+         char   *buffer,
+         int    length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+ +

Returns

+ +

The number of bytes read or -1 on error. + +

Description

+ +

The httpRead() function reads data from the HTTP connection, +possibly the result of a GET or POST request. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+char buffer[1024];
+int  bytes;
+
+httpGet(http, "/");
+while (httpUpdate(http) != HTTP_CONTINUE);
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+ +

See Also

+ +httpConnect(), +httpWrite() + + +

httpReconnect()

+ +

Usage

+ +
+int
+httpReconnect(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpReconnect() function reconnects to the HTTP server. +This is usually done automatically if the HTTP functions detect that the +server connection has terminated. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpReconnect(http);
+
+ +

See Also

+ +httpConnect() + + +

httpSeparate()

+ +

Usage

+ +
+void
+httpSeparate(const char *uri,
+             char       *method,
+             char       *username,
+             char       *host,
+             int        *port,
+             char       *resource);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
uriThe URI to separate
methodThe method (scheme) of the URI
usernameThe username (and password) portion of the URI, if any
hostThe hostname portion of the URI, if any
portThe port number for the URI, either as specified or as + default for the method/scheme
resourceThe resource string, usually a filename on the server
+ +

Description

+ +

The httpSeparate() function separates the specified URI into +its component parts. The method, username, hostname, and resource strings should +be at least HTTP_MAX_URI characters long to avoid potential +buffer overflow problems. + +

Example

+ +
+char uri[HTTP_MAX_URI];
+char method[HTTP_MAX_URI];
+char username[HTTP_MAX_URI];
+char host[HTTP_MAX_URI];
+char resource[HTTP_MAX_URI];
+int  port;
+
+...
+
+httpSeparate(uri, method, username, host, &port, resource);
+
+ +

See Also

+ +httpConnect() + + +

httpSetField()

+ +

Usage

+ +
+void
+httpSetField(http_t       *http,
+             http_field_t field,
+             const char   *value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
fieldThe HTTP field
valueThe string value for the field
+ +

Description

+ +

The httpSetField() function sets the current value for +the specified HTTP field. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpSetField(http, HTTP_FIELD_AUTHORIZATION, "Basic dfdr34453454325"));
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+ +

See Also

+ +httpConnect(), +httpGetField() + + +

httpStatus()

+ +

Usage

+ +
+const char *
+httpStatus(http_status_t status);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
statusThe HTTP status code from the server.
+ +

Returns

+ +

The standard HTTP status text associated with the status code. + +

Description

+ +

httpStatus() returns the standard HTTP status text +associated with the status code. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+...
+
+puts(httpStatus(http->status));
+
+ + +

httpTrace()

+ +

Usage

+ +
+int
+httpTrace(http_t     *http,
+          const char *uri);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
uriThe URI to trace
+ +

Returns

+ +

0 on success, non-zero on failure. + +

Description

+ +

The httpTrace() function sends a HTTP TRACE request to the +server. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+
+httpTrace(http, "/some/uri");
+
+ +

See Also

+ +httpConnect(), +httpSetField(), +httpUpdate() + + +

httpUpdate()

+ +

Usage

+ +
+http_status_t
+httpUpdate(http_t *http);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
httpThe HTTP connection
+ +

Returns

+ +

The HTTP status of the current request. + +

Description

+ +

The httpUpdate() 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. + +

Since proxies and the current blocking mode can cause the request to +take longer, programs should continue calling httpUpdate() +until the return status is not the constant value HTTP_CONTINUE. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+http_status_t status;
+
+httpGet(http, "/some/uri");
+while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+printf("Request status is %d\n", status);
+
+ +

See Also

+ +httpConnect(), +httpDelete(), +httpGet(), +httpHead(), +httpOptions(), +httpPost(), +httpPut(), +httpTrace() + + +

httpWrite()

+ +

Usage

+ +
+int
+httpWrite(http_t *http,
+          char   *buffer,
+          int    length);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
bufferThe buffer to read into
lengthThe number of bytes to read
+ +

Returns

+ +

The number of bytes read or -1 on error. + +

Description

+ +

The httpWrite() function reads data from the HTTP connection, +possibly the result of a GET or POST request. + +

Example

+ +
+#include <cups/http.h>
+
+http_t *http;
+FILE *fp;
+char buffer[1024];
+int  bytes;
+
+httpPost(http, "/");
+
+while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+  httpWrite(http, buffer, bytes);
+
+while (httpUpdate(http) != HTTP_CONTINUE);
+
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+  buffer[bytes] = '\0';
+  fputs(buffer, stdout);
+}
+
+ +

See Also

+ +httpConnect(), +httpRead() + + +

ippAddBoolean()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddBoolean(ipp_t      *ipp,
+              ipp_tag_t  group,
+              const char *name,
+	      char       value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe boolean value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddBoolean() function adds a single boolean attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "my-jobs", 1);
+
+ +

See Also

+ +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddBooleans()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddBooleans(ipp_t      *ipp,
+               ipp_tag_t  group,
+               const char *name,
+               int        num_values,
+               const char *values);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of values
valuesThe boolean values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddBooleans() function adds one or more boolean +attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values false values is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char values[10];
+
+ippAddBooleans(ipp, IPP_TAG_OPERATION, "some-attribute", 10, values);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddDate()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddDate(ipp_t       *ipp,
+           ipp_tag_t   group,
+           const char  *name,
+           ipp_uchar_t *value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
valueThe date value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddDate() function adds a single date-time attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddDate(ipp, IPP_TAG_OPERATION, "some-attribute", 
+           ippTimeToDate(time(NULL));
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings(), +ippTimeToDate() + + +

ippAddInteger()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddInteger(ipp_t      *ipp,
+              ipp_tag_t  group,
+              ipp_tag_t  tag,
+              const char *name,
+              int        value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value (IPP_TAG_INTEGER or IPP_TAG_ENUM)
nameThe name of attribute
valueThe integer value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddInteger() function adds a single integer attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddInteger(ipp, IPP_TAG_OPERATION, "limit", 100);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddIntegers()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddIntegers(ipp_t      *ipp,
+               ipp_tag_t  group,
+               ipp_tag_t  tag,
+               const char *name,
+               int        num_values,
+               const int  *values);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of integer value (IPP_TAG_INTEGER or IPP_TAG_ENUM)
nameThe name of attribute
num_valuesThe number of values
valuesThe integer values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddIntegers() function adds one or more integer +attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values 0 values is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int values[100];
+
+ippAddIntegers(ipp, IPP_TAG_OPERATION, "some-attribute", 100, values);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRange()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddRange(ipp_t      *ipp,
+            ipp_tag_t  group,
+            const char *name,
+            int        low,
+            int        high);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
lowThe lower value
highThe higher value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddRange() function adds a single range attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddRange(ipp, IPP_TAG_OPERATION, "page-ranges", 1, 10);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddRanges()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddRanges(ipp_t      *ipp,
+             ipp_tag_t  group,
+             const char *name,
+             int        num_values,
+             const int  *lows,
+             const int  *highs);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of range values
lowsThe lower values
highsThe higher values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddRanges() function adds one or more range +attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values 0,0 ranges is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int lows[2];
+int highs[2];
+
+ippAddRanges(ipp, IPP_TAG_OPERATION, "page-ranges", 2, lows, highs);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolution()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddResolution(ipp_t      *ipp,
+                 ipp_tag_t  group,
+                 const char *name,
+                 int        xres,
+                 int        yres,
+                 ipp_res_t  units);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
xresThe horizontal resolution
yresThe vertical resolution
unitsThe resolution units
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddResolution() function adds a single resolution attribute +value to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolution",
+              720, 720, IPP_RES_PER_INCH);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddResolutions()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddResolutions(ipp_t           *ipp,
+                  ipp_tag_t       group,
+                  const char      *name,
+                  int             num_values,
+                  const int       *xres,
+                  const int       *yres,
+                  const ipp_res_t *units);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
nameThe name of attribute
num_valuesThe number of resolution values
xresThe horizontal resolutions
yresThe vertical resolutions
unitsThe resolution units
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddResolutions() function adds one or more +resolution attribute values to the specified IPP request. If the +values pointer is NULL then an array of +num_values 0,0 resolutions is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+int xres[5];
+int yres[5];
+ipp_res_t units[5];
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolutions-supported",
+              5, xres, yres, units);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddSeparator(), +ippAddString(), +ippAddStrings() + + +

ippAddSeparator()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddSeparator(ipp_t *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ippThe IPP request
+ +

Returns

+ +

A pointer to the new separator or NULL if the separator could not be +created. + +

Description

+ +

The ippAddSeparator() function adds a group separator +to the specified IPP request. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddSeparator(ipp);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddString(), +ippAddStrings() + + +

ippAddString()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddString(ipp_t      *ipp,
+             ipp_tag_t  group,
+             ipp_tag_t  tag,
+             const char *name,
+             const char *charset,
+             const char *value);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
charsetThe character set for the string
valueThe string value
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddString() function adds a single string attribute +value to the specified IPP request. For IPP_TAG_NAMELANG and +IPP_TAG_TEXTLANG strings, the charset value is provided with +the string to identify the string encoding used. Otherwise the charset value +is ignored. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+             NULL, "abc123");
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddStrings() + + +

ippAddStrings()

+ +

Usage

+ +
+ipp_attribute_t *
+ippAddStrings(ipp_t      *ipp,
+              ipp_tag_t  group,
+              ipp_tag_t  tag,
+              const char *name,
+              int        num_values,
+              const char *charset,
+              const char **values);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request
groupThe IPP group
tagThe type of string value
nameThe name of attribute
num_valuesThe number of strings
charsetThe character set for the strings
valuesThe string values
+ +

Returns

+ +

A pointer to the new attribute or NULL if the attribute could not be +created. + +

Description

+ +

The ippAddStrings() function adds one or more string +attribute values to the specified IPP request. For +IPP_TAG_NAMELANG and IPP_TAG_TEXTLANG +strings, the charset value is provided with the strings to identify the +string encoding used. Otherwise the charset value is ignored. If the +values pointer is NULL then an array of +num_values NULL strings is created. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+char *values[2] = { "one", "two" };
+
+ippAddStrings(ipp, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "attr-name",
+              2, NULL, values);
+
+ +

See Also

+ +ippAddBoolean(), +ippAddBooleans(), +ippAddDate(), +ippAddInteger(), +ippAddIntegers(), +ippAddRange(), +ippAddRanges(), +ippAddResolution(), +ippAddResolutions(), +ippAddSeparator(), +ippAddString() + + +

ippDateToTime()

+ +

Usage

+ +
+time_t
+ippDateToTime(const ipp_uchar_t date[11]);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
dateThe IPP date-time value
+ +

Returns

+ +

A UNIX time value. + +

Description

+ +

The ippDateToTime() function converts an IPP date-time value +to a UNIX time value. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_uchar_t date[11];
+
+printf("UNIX time is %d\n", ippDateToTime(date));
+
+ +

See Also

+ +ippTimeToDate() + + +

ippDelete()

+ +

Usage

+ +
+void
+ippDelete(ipp_t *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ippThe IPP request or response
+ +

Description

+ +

The ippDelete() function deletes all memory used by an IPP +request or response. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ippDelete(ipp);
+
+ +

See Also

+ +ippNew() + + +

ippErrorString()

+ +

Usage

+ +
+const char *
+ippErrorString(ipp_status_t error);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
errorIPP error code.
+ +

Returns

+ +

The standard text representation of the IPP error code. + +

Description

+ +

ippErrorString() returns the standard text representation +of the IPP error code. + +

Example

+ +
+#include <cups/ipp.h>
+
+puts(ippErrorString(IPP_OK));
+
+ +

See Also

+ +

+cupsLastError() + + +

ippFindAttribute()

+ +

Usage

+ +
+ipp_attribute_t *
+ippFindAttribute(ipp_t      *ipp,
+                 const char *name,
+                 ipp_tag_t  tag);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request or response
nameThe name of the attribute
tagThe required value tag for the attribute or + IPP_TAG_ZERO for any type of value.
+ +

Returns

+ +

A pointer to the first occurrence of the requested attribute, or +NULL if it was not found. + +

Description

+ +

ippFindAttribute() finds the first occurrence of the named +attribute. The tag parameter restricts the search to a specific +value type - use IPP_TAG_ZERO to find any value with the name. + +

The value tags IPP_TAG_NAME and IPP_TAG_TEXT +match the name/text values with or without the language code. + +

Example

+ +
+ipp_attribute_t *attr;
+
+attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+while (attr != NULL)
+{
+  puts(attr->values[0].string.text);
+
+  attr = ippFindNextAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+}
+
+ +

See Also

+ +cupsDoFileRequest(), +cupsDoRequest(), +ippDelete(), +ippFindNextAttribute(), +ippNew() + + +

ippFindNextAttribute()

+ +

Usage

+ +
+ipp_attribute_t *
+ippFindNextAttribute(ipp_t      *ipp,
+                     const char *name,
+                     ipp_tag_t  tag);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ippThe IPP request or response
nameThe name of the attribute
tagThe required value tag for the attribute or + IPP_TAG_ZERO for any type of value.
+ +

Returns

+ +

A pointer to the next occurrence of the requested attribute, or +NULL if it was not found. + +

Description

+ +

ippFindNextAttribute() finds the next occurrence of the named +attribute. The tag parameter restricts the search to a specific +value type - use IPP_TAG_ZERO to find any value with the name. + +

The value tags IPP_TAG_NAME and IPP_TAG_TEXT +match the name/text values with or without the language code. + +

Example

+ +
+ipp_attribute_t *attr;
+
+attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+while (attr != NULL)
+{
+  puts(attr->values[0].string.text);
+
+  attr = ippFindNextAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+}
+
+ +

See Also

+ +cupsDoFileRequest(), +cupsDoRequest(), +ippDelete(), +ippFindNextAttribute(), +ippNew() + + +

ippLength()

+ +

Usage

+ +
+int
+ippLength(ipp_t *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ippThe IPP request or response
+ +

Returns

+ +

The total encoded length of the IPP request or response in bytes. + +

Description

+ +

ippLength() returns the length of the IPP request or +response in bytes. + +

Example

+ +
+printf("The length of the response is %d bytes.\n", ippLength(response));
+
+ +

See Also

+ +ippDelete(), +ippNew() + + +

ippNew()

+ +

Usage

+ +
+ipp_t *
+ippNew(void);
+
+ +

Returns

+ +

A pointer to a new IPP request or response. + +

Description

+ +

The ippNew() function creates a new IPP request or response. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_t *ipp;
+
+ipp = ippNew();
+
+ +

See Also

+ +ippDelete() + + +

ippPort()

+ +

Usage

+ +
+int
+ippPort(void);
+
+ +

Returns

+ +

The default TCP/IP port number for IPP requests. + +

Description

+ +

The ippPort() function returns the default IPP port number +for requests. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+
+ +

See Also

+ +cupsServer(), +ippSetPort() + + +

ippRead()

+ +

Usage

+ +
+ipp_state_t
+ippRead(http_t *http,
+        ipp_t  *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+ +

Returns

+ +

The current read state. + +

Description

+ +

The ippRead() function reads IPP attributes from the specified +HTTP connection. Programs should continue calling ippRead() until +IPP_ERROR or IPP_DATA is returned. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+
+while ((status = ippRead(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpRead() ...
+}
+
+ +

See Also

+ +ippWrite() + + +

ippSetPort()

+ +

Usage

+ +
+void
+ippSetPort(int port);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
portThe port number to use
+ +

Description

+ +

The ippSetPort() function sets the default IPP port number +for requests. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+...
+
+ippSetPort(8631);
+
+ +

See Also

+ +ippPort() + + +

ippTimeToDate()

+ +

Usage

+ +
+ipp_uchar_t *
+ippTimeToDate(time_t time);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
timeThe UNIX time value
+ +

Returns

+ +

A static pointer to an IPP date-time value. + +

Description

+ +

The ippTimeToDate() function converts a UNIX time to an IPP +date-time value. + +

Example

+ +
+#include <cups/ipp.h>
+
+ipp_uchar_t *date;
+
+date = ippTimeToDate(time(NULL));
+
+ +

See Also

+ +ippDateToTime() + + +

ippWrite()

+ +

Usage

+ +
+ipp_state_t
+ippWrite(http_t *http,
+         ipp_t  *ipp);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
httpThe HTTP connection
ippThe IPP request or response
+ +

Returns

+ +

The current write state. + +

Description

+ +

The ippWrite() function writes IPP attributes to the specified +HTTP connection. Programs should continue calling ippWrite() until +IPP_ERROR or IPP_DATA is returned. + +

Example

+ +
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+... add attributes ...
+
+while ((status = ippWrite(http, ipp)) != IPP_ERROR)
+  if (status == IPP_DATA)
+    break;
+
+if (status == IPP_DATA)
+{
+  ... read additional non-IPP data using httpWrite() ...
+}
+
+ +

See Also

+ +ippRead() + + +

ppdClose()

+ +

Usage

+ +
+void
+ppdClose(ppd_file_t *ppd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ppdThe PPD file
+ +

Description

+ +

The ppdClose() function frees all memory associated with the +PPD file. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdClose(ppd);
+
+ +

See Also

+ +ppdOpen(), +ppdOpenFd(), +ppdOpenFile() + + +

ppdCollect()

+ +

Usage

+ +
+int
+ppdCollect(ppd_file_t    *ppd,
+           ppd_section_t section,
+           ppd_choice_t  ***choices);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file.
sectionThe document section to collect.
choicesThe array of option choices that are marked.
+ +

Returns

+ +

The number of options collected. + +

Description

+ +

ppdCollect() collects all of the marked options in the +specified section, sorts them by their order dependency values, and +returns an array that can be used to emit option commands in the proper +order. It is normally used by the ppdEmit*() functions. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t   *ppd;
+int          num_choices;
+ppd_choice_t **choices;
+
+...
+
+num_choices = ppdCollect(ppd, PPD_ORDER_JCL, &choices);
+
+ +

See Also

+ +

+ppdEmit(), +ppdEmitFd(), +ppdEmitJCL() + + +

ppdConflicts()

+ +

Usage

+ +
+int
+ppdConflicts(ppd_file_t *ppd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ppdThe PPD file
+ +

Returns

+ +

The number of option conflicts in the file. + +

Description

+ +

The ppdConflicts() function returns the number of conflicts +with the currently selected options. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("%d conflicts\n", ppdConflicts(ppd));
+
+ +

See Also

+ +cupsMarkOptions(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdEmit()

+ +

Usage

+ +
+int
+ppdEmit(ppd_file_t    *ppd,
+        FILE          *file,
+        ppd_section_t section);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
fileThe file to write to
sectionThe option section to write
+ +

Returns

+ +

0 on success, -1 on error. + +

Description

+ +

The ppdEmit() function sends printer-specific option +commands to the specified file. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+ +

See Also

+ +ppdEmitFd() + + +

ppdEmitFd()

+ +

Usage

+ +
+int
+ppdEmitFd(ppd_file_t    *ppd,
+          int           fd,
+          ppd_section_t section);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
fdThe file descriptor to write to
sectionThe option section to write
+ +

Returns

+ +

0 on success, -1 on error. + +

Description

+ +

The ppdEmitFd() function sends printer-specific option +commands to the specified file descriptor. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmitFd(ppd, 1, PPD_ORDER_PAGE);
+
+ +

See Also

+ +ppdEmit() + + +

ppdFindChoice()

+ +

Usage

+ +
+ppd_choice_t *
+ppdFindChoice(ppd_option_t *option,
+              const char   *choice);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
optionA pointer to the option
choiceThe name of the choice
+ +

Returns

+ +

A pointer to the choice data or NULL if the choice does not exist. + +

Description

+ +

The ppdFindChoice() function returns a pointer to the choice +data for the specified option. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+ppd_choice_t *choice;
+
+option = ppdFindOption(ppd, "PageSize");
+choice = ppdFindChoice(option, "Letter");
+
+ +

See Also

+ +ppdFindMarkedChoice(), +ppdFindOption() + + +

ppdFindMarkedChoice()

+ +

Usage

+ +
+ppd_choice_t *
+ppdFindMarkedChoice(ppd_file_t *ppd,
+                    const char *keyword);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+ +

Returns

+ +

A pointer to the choice data or NULL if the choice does not exist or +is not marked. + +

Description

+ +

The ppdFindMarkedChoice() function returns a pointer to +the marked choice data for the specified option. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_choice_t *choice;
+
+choice = ppdFindMarkedChoice(ppd, "PageSize");
+
+ +

See Also

+ +ppdFindChoice(), +ppdFindOption() + + +

ppdFindOption()

+ +

Usage

+ +
+ppd_option_t *
+ppdFindOption(ppd_file_t *ppd,
+              const char *keyword);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
+ +

Returns

+ +

A pointer to the option data or NULL if the option does not exist. + +

Description

+ +

The ppdFindOption() function returns a pointer to the option +data for the specified option. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+
+option = ppdFindOption(ppd, "PageSize");
+
+ +

See Also

+ +ppdFindChoice(), +ppdFindMarkedChoice() + + +

ppdIsMarked()

+ +

Usage

+ +
+int
+ppdIsMarked(ppd_file_t *ppd,
+            const char *keyword,
+            const char *choice);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the option choice
+ +

Returns

+ +

1 if the choice is marked, 0 otherwise. + +

Description

+ +

The ppdIsMarked() function returns whether or not the +specified option choice is marked. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Letter size %s selected.\n",
+       ppdIsMarked(ppd, "PageSize", "Letter") ? "is" : "is not");
+
+ +

See Also

+ +cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkDefaults()

+ +

Usage

+ +
+void
+ppdMarkDefaults(ppd_file_t *ppd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
ppdThe PPD file
+ +

Description

+ +

The ppdMarkDefaults() function marks all of the default +choices in the PPD file. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkDefaults(ppd);
+
+ +

See Also

+ +cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdMarkOption()

+ +

Usage

+ +
+int
+ppdMarkOption(ppd_file_t *ppd,
+              const char *keyword,
+              const char *choice);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
keywordThe name of the option
choiceThe name of the choice
+ +

Returns

+ +

The number of conflicts in the PPD file. + +

Description

+ +

The ppdMarkOption() function marks the specified option +choice. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkOption(ppd, "PageSize", "Letter");
+
+ +

See Also

+ +cupsMarkOptions(), +ppdConflicts(), +ppdIsMarked(), +ppdMarkDefaults(), +ppdMarkOption() + + +

ppdOpen()

+ +

Usage

+ +
+ppd_file_t *
+ppdOpen(FILE *file);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
fileThe file to read from
+ +

Returns

+ +

A pointer to a PPD file structure or NULL if the PPD file could not be +read. + +

Description

+ +

The ppdOpen() function reads a PPD file from the specified +file into memory. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+FILE *file;
+
+file = fopen("filename.ppd", "rb");
+ppd = ppdOpen(file);
+fclose(file);
+
+ +

See Also

+ +ppdClose(), +ppdOpenFd(), +ppdOpenFile() + + +

ppdOpenFd()

+ +

Usage

+ +
+ppd_file_t *
+ppdOpenFd(int fd);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
fdThe file descriptor to read from
+ +

Returns

+ +

A pointer to a PPD file structure or NULL if the PPD file could not be +read. + +

Description

+ +

The ppdOpenFd() function reads a PPD file from the specified +file descriptor into memory. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+int        fd;
+
+fd = open("filename.ppd", O_RDONLY);
+ppd = ppdOpenFd(fd);
+close(fd);
+
+ +

See Also

+ +ppdClose(), +ppdOpen(), +ppdOpenFile() + + +

ppdOpenFile()

+ +

Usage

+ +
+ppd_file_t *
+ppdOpenFile(const char *filename);
+
+ +

Arguments

+ +
+ + + + + + + + +
ArgumentDescription
filenameThe name of the file to read from
+ +

Returns

+ +

A pointer to a PPD file structure or NULL if the PPD file could not be +read. + +

Description

+ +

The ppdOpenFile() function reads a PPD file from the named +file into memory. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile("filename.ppd");
+
+ +

See Also

+ +ppdClose(), +ppdOpen(), +ppdOpenFd() + + +

ppdPageLength()

+ +

Usage

+ +
+float
+ppdPageLength(ppd_file_t *ppd,
+              const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+ +

Returns

+ +

The length of the specified page size in points or 0 if the page size +does not exist. + +

Description

+ +

The ppdPageLength() function returns the page length of the +specified page size. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Length = %.0f\n", ppdPageLength(ppd, "Letter"));
+
+ +

See Also

+ +ppdPageLength(), +ppdPageSize(), +ppdPageWidth() + + +

ppdPageSize()

+ +

Usage

+ +
+ppd_size_t *
+ppdPageSize(ppd_file_t *ppd,
+            const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+ +

Returns

+ +

A pointer to the page size record of the specified page size in +points or NULL if the page size does not exist. + +

Description

+ +

The ppdPageSize() function returns the page size record for the +specified page size. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+
+size = ppdPageSize(ppd, "Letter");
+if (size != NULL)
+{
+  printf(" Width = %.0f\n", size->width);
+  printf("Length = %.0f\n", size->length);
+  printf("  Left = %.0f\n", size->left);
+  printf(" Right = %.0f\n", size->right);
+  printf("Bottom = %.0f\n", size->bottom);
+  printf("   Top = %.0f\n", size->top);
+}
+
+ +

See Also

+ +ppdPageLength(), +ppdPageWidth() + + +

ppdPageWidth()

+ +

Usage

+ +
+float
+ppdPageWidth(ppd_file_t *ppd,
+             const char *name);
+
+ +

Arguments

+ +
+ + + + + + + + + + + + +
ArgumentDescription
ppdThe PPD file
nameThe name of the page size
+ +

Returns

+ +

The width of the specified page size in points or 0 if the page size +does not exist. + +

Description

+ +

The ppdPageWidth() function returns the page width of the +specified page size. + +

Example

+ +
+#include <cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Width = %.0f\n", ppdPageWidth(ppd, "Letter"));
+
+ +

See Also

+ +ppdPageLength(), +ppdPageSize() + + + + diff --git a/doc/sps.html b/doc/sps.html new file mode 100644 index 0000000000..d1cd7fd579 --- /dev/null +++ b/doc/sps.html @@ -0,0 +1,302 @@ + + + +CUPS Software Performance Specification + + + + + + + +

+

CUPS Software Performance Specification


+CUPS-SPS-1.1
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Programs +
+
4 Scheduler Objects +
+
A Glossary + +
+

1 Scope

+

1.1 Identification

+

This software performance specification provides an analysis of the + memory, disk, and processor utilitization of each program in the Common + UNIX Printing System ("CUPS") Version 1.1.

+

For the purposes of comparison, all figures are for the Linux Intel + platform. Memory utilization on other platforms should be similar.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+

1.3 Document Overview

+

This software performance specification is organized into the + following sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Programs
  • +
  • 4 - Scheduler Objects
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+

The following CUPS documentation is referenced by this document:

+
    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.1: CUPS Software Security Report
  • +
  • CUPS-STP-1.1: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.1: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

The following non-CUPS documents are referenced by this document:

+ +

3 Programs

+

The following table describes the average memory, disk, and CPU usage + of each program in CUPS.

+

The base memory column shows the initial memory requirements for each + program, including any shared libraries that are provided by CUPS.

+

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.

+

The temp files column indicates whether any temporary files are + created.

+

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. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Backends
ProgramBase MemoryMax MemoryTemp + FilesCPU Usage
ipp91k256kUp to size of print file +Low
lpd89k89kUp to size of print file +Low
parallel85k85kUp to size of print + fileLow
serial85k85kUp to size of print file +Low
socket85k85kUp to size of print file +Low
usb85k85kUp to size of print file +Low
CGIs
ProgramBase MemoryMax MemoryTemp + FilesCPU Usage
admin.cgi107k256kUp to size of PPD + fileMedium
classes.cgi95kSize of class objects +NoneMedium
jobs.cgi93kSize of job objectsNone +Medium
printers.cgi95kSize of printer objects +NoneMedium
Command-Line Programs
ProgramBase MemoryMax MemoryTemp + FilesCPU Usage
accept88k128kNoneLow
cancel88k128kNoneLow
disable88k128kNoneLow
enable88k128kNoneLow
lp90k256kNoneLow
lpadmin148k256kNoneLow
lpc86kSize of job and printer objects +NoneMedium
lpinfo89kSize of device and PPD objects +NoneMedium
lpmove88k128kNoneLow
lpoptions89k128kNoneLow
lppasswd90k90kNoneLow
lpq87kSize of job objectsNone +Medium
lpr87k256kNoneLow
lprm84k128kNoneLow
lpstat119kSize of job, printer, and class + objectsNoneMedium
reject88k128kNoneLow
Daemons
ProgramBase MemoryMax MemoryTemp + FilesCPU Usage
cups-lpd92k256kOne file per control + or data file from clientLow
cupsd308kSee Scheduler Requirements +See Scheduler RequirementsMedium
cups-polld84kSize of printer and class objects +NoneLow
Filters
ProgramBase MemoryMax MemoryTemp + FilesCPU Usage
hpgltops263k320kNoneMedium
imagetops628k10MSwap file for + uncompressed image dataMedium
imagetoraster652k10MSwap file for + uncompressed image dataHigh
pstops775k840kUp to size of print + fileMedium
pstoraster4M14MSwap file for command + listsHigh
rastertoepson693k1MNoneLow
rastertohp690k1MNoneLow
texttops638k4*cols*rowsNone +Low
+
+

+

4 Scheduler Objects

+

The cupsd program is the CUPS scheduler process. It + manages many interdependent server objects that are used to manage and + print files to printers.

+

The following table provides the memory and disk cost associated with + each server object. +

+ + + + + + + + + + + + + + + +
ObjectMemory PerDisk Per
Browse ACL1k120
Browse Poll2480
Browse Relay2880
Certificate7632
Class9k200
Client13k-
Device256-
Job2k1k + size of document files
Location ACL1k120
MIME Filter26880
MIME Type34080
PPD200656
Printer11k32k
+
+

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Page Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/sps.pdf b/doc/sps.pdf new file mode 100644 index 0000000000000000000000000000000000000000..403ee2dd0d70a35a95a696cb3c5bac0ca4ac9b31 GIT binary patch literal 33900 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 literal 0 Hc-jL100001 diff --git a/doc/sps.shtml b/doc/sps.shtml new file mode 100644 index 0000000000..88959006e7 --- /dev/null +++ b/doc/sps.shtml @@ -0,0 +1,457 @@ + + + + + + CUPS Software Performance Specification + + + +

Scope

+ +

Identification

+ +

This software performance specification provides an analysis of the +memory, disk, and processor utilitization of each program in the +Common UNIX Printing System ("CUPS") Version 1.1.

+ +

For the purposes of comparison, all figures are for the Linux Intel +platform. Memory utilization on other platforms should be similar. + + + +

Document Overview

+ +

This software performance specification is organized into the +following sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Programs
  • +
  • 4 - Scheduler Objects
  • +
  • A - Glossary
  • +
+ + + +

Programs

+ +

The following table describes the average memory, disk, and CPU usage of +each program in CUPS. + +

The base memory column shows the initial memory requirements for each +program, including any shared libraries that are provided by CUPS. + +

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. + +

The temp files column indicates whether any temporary files are created. + +

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. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Backends
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
ipp91k256kUp to size of print fileLow
lpd89k89kUp to size of print fileLow
parallel85k85kUp to size of print fileLow
serial85k85kUp to size of print fileLow
socket85k85kUp to size of print fileLow
usb85k85kUp to size of print fileLow
CGIs
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
admin.cgi107k256kUp to size of PPD fileMedium
classes.cgi95kSize of class objectsNoneMedium
jobs.cgi93kSize of job objectsNoneMedium
printers.cgi95kSize of printer objectsNoneMedium
Command-Line Programs
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
accept88k128kNoneLow
cancel88k128kNoneLow
disable88k128kNoneLow
enable88k128kNoneLow
lp90k256kNoneLow
lpadmin148k256kNoneLow
lpc86kSize of job and printer objectsNoneMedium
lpinfo89kSize of device and PPD objectsNoneMedium
lpmove88k128kNoneLow
lpoptions89k128kNoneLow
lppasswd90k90kNoneLow
lpq87kSize of job objectsNoneMedium
lpr87k256kNoneLow
lprm84k128kNoneLow
lpstat119kSize of job, printer, and class objectsNoneMedium
reject88k128kNoneLow
Daemons
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
cups-lpd92k256kOne file per control or data file from clientLow
cupsd308kSee Scheduler RequirementsSee Scheduler RequirementsMedium
cups-polld84kSize of printer and class objectsNoneLow
Filters
ProgramBase MemoryMax MemoryTemp FilesCPU Usage
hpgltops263k320kNoneMedium
imagetops628k10MSwap file for uncompressed image dataMedium
imagetoraster652k10MSwap file for uncompressed image dataHigh
pstops775k840kUp to size of print fileMedium
pstoraster4M14MSwap file for command listsHigh
rastertoepson693k1MNoneLow
rastertohp690k1MNoneLow
texttops638k4*cols*rowsNoneLow
+ + +

Scheduler Objects

+ +

The cupsd program is the CUPS scheduler process. It manages +many interdependent server objects that are used to manage and print files +to printers. + +

The following table provides the memory and disk cost associated with each +server object. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ObjectMemory PerDisk Per
Browse ACL1k120
Browse Poll2480
Browse Relay2880
Certificate7632
Class9k200
Client13k-
Device256-
Job2k1k + size of document files
Location ACL1k120
MIME Filter26880
MIME Type34080
PPD200656
Printer11k32k
+ + + + + diff --git a/doc/ssr.html b/doc/ssr.html new file mode 100644 index 0000000000..ad8a960497 --- /dev/null +++ b/doc/ssr.html @@ -0,0 +1,280 @@ + + + +CUPS Software Security Report + + + + + + + +

+

CUPS Software Security Report


+CUPS-SSR-1.1
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Local Access Risks + +4 Remote Access Risks + +A Glossary + +
+

1 Scope

+

1.1 Identification

+

This software security report provides an analysis of possible + security concerns for the Common UNIX Printing System ("CUPS") Version + 1.1.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+

1.3 Document Overview

+

This software security report is organized into the following + sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Local Access Risks
  • +
  • 4 - Remote Access Risks
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+

The following CUPS documentation is referenced by this document:

+
    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.1: CUPS Software Security Report
  • +
  • CUPS-STP-1.1: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.1: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

The following non-CUPS documents are referenced by this document:

+ +

3 Local Access Risks

+

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.

+

3.1 Security Breaches

+

There is one known security vulnerability with local access:

+
    +
  1. 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. +

    We recommend that any password-protected accounts used for remote + printing have limited access priviledges so that the possible damages + can be minimized.

    +

    The device URI is "sanitized" (the username and password are removed) + when sent to an IPP client so that a remote user cannot exploit this + vulnerability.

    +
  2. +
+

4 Remote Access Risks

+

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.

+

4.1 Denial of Service Attacks

+

Like all Internet services, the CUPS server is vulnerable to denial + of service attacks, including:

+
    +
  1. Establishing multiple connections to the server until the server + will accept no more. +

    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.

    +
  2. Repeatedly opening and closing connections to the server as fast as + possible. +

    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.

    +
  3. Flooding the network with broadcast packets on port 631. +

    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.

    +
  4. Sending partial IPP requests; specifically, sending part of an + attribute value and then stopping transmission. +

    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.

    +
  5. Sending large/long print jobs to printers, preventing other users + from printing. +

    There are limited facilities for protecting against large print jobs + (the MaxRequestSize 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.

    +
  6. + + + + +
+

4.2 Security Breaches

+

The current CUPS server supports Basic, Digest, and local certificate + authentication:

+
    +
  1. 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.
  2. +
  3. Digest authentication uses an MD5 checksum of the username, + password, and domain ("CUPS"), 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 "man in the middle" 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.
  4. +
  5. Local certificate authentication passes 128-bit "certificates" that + identify an authenticated user. Certificates are created on-the-fly + from random data and stored in files under /etc/cups/certs +. 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.)
  6. +
+

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.

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Page Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/ssr.pdf b/doc/ssr.pdf new file mode 100644 index 0000000000000000000000000000000000000000..34d12a768f76aa90620b16bcc069f8e41b4977a6 GIT binary patch literal 32595 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 literal 0 Hc-jL100001 diff --git a/doc/ssr.shtml b/doc/ssr.shtml new file mode 100644 index 0000000000..8dc9cf5902 --- /dev/null +++ b/doc/ssr.shtml @@ -0,0 +1,167 @@ + + + + + + CUPS Software Security Report + + + +

Scope

+ +

Identification

+ +

This software security report provides an analysis of possible security +concerns for the Common UNIX Printing System ("CUPS") Version 1.1.

+ + + +

Document Overview

+ +

This software security report is organized into the following sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Local Access Risks
  • +
  • 4 - Remote Access Risks
  • +
  • A - Glossary
  • +
+ + + +

Local Access Risks

+ +

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. + +

Security Breaches

+ +

There is one known security vulnerability with local access: + +

    + +
  1. 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. + +

    We recommend that any password-protected accounts used for + remote printing have limited access priviledges so that the + possible damages can be minimized. + +

    The device URI is "sanitized" (the username and password are + removed) when sent to an IPP client so that a remote user + cannot exploit this vulnerability. + +

+ +

Remote Access Risks

+ +

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. + +

Denial of Service Attacks

+ +

Like all Internet services, the CUPS server is vulnerable to denial of +service attacks, including: + +

    + +
  1. Establishing multiple connections to the server until the server + will accept no more. + +

    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. + +

  2. Repeatedly opening and closing connections to the server as fast + as possible. + +

    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. + +

  3. Flooding the network with broadcast packets on port 631. + +

    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. + +

  4. Sending partial IPP requests; specifically, sending part of an + attribute value and then stopping transmission. + +

    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. + +

  5. Sending large/long print jobs to printers, preventing other users + from printing. + +

    There are limited facilities for protecting against large print + jobs (the MaxRequestSize 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. + +

+ +

Security Breaches

+ +

The current CUPS server supports Basic, Digest, and local certificate +authentication: + +

    + +
  1. 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. + +
  2. Digest authentication uses an MD5 checksum of the username, + password, and domain ("CUPS"), 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 "man in the middle" 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. + +
  3. Local certificate authentication passes 128-bit + "certificates" that identify an authenticated user. + Certificates are created on-the-fly from random data and stored + in files under /etc/cups/certs. 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.) + +
+ +

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. + + + + + diff --git a/doc/stp.html b/doc/stp.html new file mode 100644 index 0000000000..cc612d8aea --- /dev/null +++ b/doc/stp.html @@ -0,0 +1,267 @@ + + + +CUPS Software Test Plan + + + + + + + +


+

CUPS Software Test Plan


+CUPS-STP-1.1
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Test Procedure +
+
4 IPP Compliance Tests + +5 Command Tests + +A Glossary + +
+

1 Scope

+

1.1 Identification

+

This software test plan provides detailed tests that are used to + evaluate the stability and compliance of the Common UNIX Printing + System ("CUPS") Version 1.1.

+

1.2 System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+

1.3 Document Overview

+

This software test plan is organized into the following sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Test Procedure
  • +
  • 4 - IPP Compliance Tests
  • +
  • 5 - Command Tests
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+

The following CUPS documentation is referenced by this document:

+
    +
  • CUPS-CMP-1.1: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.1: CUPS System Interface Design Description
  • +
  • CUPS-IPP-1.1: CUPS Implementation of IPP
  • +
  • CUPS-SAM-1.1.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.1: CUPS Software Design Description
  • +
  • CUPS-SPM-1.1.x: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.1: CUPS Software Security Report
  • +
  • CUPS-STP-1.1: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.1.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.1: CUPS Software Version Description
  • +
+

2.2 Other Documents

+

The following non-CUPS documents are referenced by this document:

+ +

3 Test Procedure

+

The test software and data files are located in the test + subdirectory of the source distribution. A script is provided to + compile the ipptest program and run all of the tests that + follow, producing a success/fail report.

+

The test target of the top-level makefile can be used to + run this script:

+
    +
    +make test
    +
    +
+

or you can run the test script directly:

+
    +
    +cd test
    +./run-stp-tests
    +
    +
+

A Software Test Report is stored in HTML and PDF files that are + generated using the HTMLDOC + software.

+

4 IPP Compliance Tests

+

This section describes the tests used to validate the IPP standards + compliance of the CUPS server.

+

4.1 Request Tests

+

These tests verify that the CUPS scheduler only accepts valid IPP + requests that start with the attributes-charset and +attributes-natural-language attributes and also contain a +printer-uri or job-uri attribute.

+

It also verifies that the CUPS scheduler always responds with +attributes-charset and attributes-natural-language + attributes, using default values if they are not provided by the + client.

+

4.2 CUPS Printer Operation Tests

+

These tests verify that the CUPS printer operations are supported and + function properly. Two printers called Test1 and +Test2 are created, one as a PostScript printer and one as a + raster printer.

+

4.3 Job Operation Tests

+

These test verify that the CUPS scheduler accepts print jobs for all + supported file formats and that the cancel-job, +hold-job, and resume-job operations work.

+

5 Command Tests

+

This section describes the tests used to validate the Berkeley and + System V commands included with CUPS.

+

5.1 lpadmin

+

This test verifies that printers can be added, modified, and + defaulted using the lpadmin command.

+

5.2 lpc

+

This test verifies that the lpc command can show the + current status of all print queues.

+

5.3 lpq

+

This test verifies that the lpq command lists any jobs + in the queue.

+

5.4 lpstat

+

This test verifies that the lpstat command works with + all reports using the "-t" option.

+

5.5 lp

+

This test verifies that the lp command works with both + the default destination and a specific destination.

+

5.6 lpr

+

This test verifies that the lpr command works with both + the default destination and a specific destination.

+

5.7 lprm

+

This test verifies that the lprm command can properly + cancel a job.

+

5.8 cancel

+

This test verifies that the cancel command can properly + cancel a job or all jobs.

+

5.9 lpinfo

+

This test verifies that the lpinfo command returns a + list of available printer drivers and devices.

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Page Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/stp.pdf b/doc/stp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a8b8d0634d78b47e5cdab6609a634c0f6e07ca78 GIT binary patch literal 36056 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 literal 0 Hc-jL100001 diff --git a/doc/stp.shtml b/doc/stp.shtml new file mode 100644 index 0000000000..ebd4a85fca --- /dev/null +++ b/doc/stp.shtml @@ -0,0 +1,144 @@ + + + + + + + CUPS Software Test Plan + + + +

Scope

+ +

Identification

+ +

This software test plan provides detailed tests that are used +to evaluate the stability and compliance of the Common UNIX +Printing System ("CUPS") Version 1.1. + + + +

Document Overview

+ +

This software test plan is organized into the following sections: + +

    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Test Procedure
  • +
  • 4 - IPP Compliance Tests
  • +
  • 5 - Command Tests
  • +
  • A - Glossary
  • +
+ + + +

Test Procedure

+ +

The test software and data files are located in the test +subdirectory of the source distribution. A script is provided to compile +the ipptest program and run all of the tests that follow, +producing a success/fail report. + +

The test target of the top-level makefile can be used to +run this script: + +

    +make test
    +
+ +

or you can run the test script directly: + +

    +cd test
    +./run-stp-tests
    +
+ +

A Software Test Report is stored in HTML and PDF files that +are generated using the +HTMLDOC software. + +

IPP Compliance Tests

+ +

This section describes the tests used to validate the IPP +standards compliance of the CUPS server. + +

Request Tests

+ +

These tests verify that the CUPS scheduler only accepts valid +IPP requests that start with the attributes-charset +and attributes-natural-language attributes and also +contain a printer-uri or job-uri attribute. + +

It also verifies that the CUPS scheduler always responds with +attributes-charset and +attributes-natural-language attributes, using +default values if they are not provided by the client. + +

CUPS Printer Operation Tests

+ +

These tests verify that the CUPS printer operations are supported +and function properly. Two printers called Test1 and +Test2 are created, one as a PostScript printer and one +as a raster printer. + +

Job Operation Tests

+ +

These test verify that the CUPS scheduler accepts print jobs for +all supported file formats and that the cancel-job, +hold-job, and resume-job operations work. + +

Command Tests

+ +

This section describes the tests used to validate the +Berkeley and System V commands included with CUPS. + +

lpadmin

+ +

This test verifies that printers can be added, modified, and +defaulted using the lpadmin command. + +

lpc

+ +

This test verifies that the lpc command can show +the current status of all print queues. + +

lpq

+ +

This test verifies that the lpq command lists +any jobs in the queue. + +

lpstat

+ +

This test verifies that the lpstat command works +with all reports using the "-t" option. + +

lp

+ +

This test verifies that the lp command works +with both the default destination and a specific destination. + +

lpr

+ +

This test verifies that the lpr command works +with both the default destination and a specific destination. + +

lprm

+ +

This test verifies that the lprm command can +properly cancel a job. + +

cancel

+ +

This test verifies that the cancel command can +properly cancel a job or all jobs. + +

lpinfo

+ +

This test verifies that the lpinfo command +returns a list of available printer drivers and devices. + + + + + diff --git a/doc/sum.html b/doc/sum.html new file mode 100644 index 0000000000..6c7b5e01f9 --- /dev/null +++ b/doc/sum.html @@ -0,0 +1,1754 @@ + + + +CUPS Software Users Manual + + + + + + + +


+

CUPS Software Users Manual


+CUPS-SUM-1.1.17
+Easy Software Products
+Copyright 1997-2002, All Rights Reserved
+
+
+

Table of Contents

+
+
Preface + +1 - Printing System Overview + +2 - Using the Printing System + +3 - Standard Printer Options + +4 - Saving Printer Options and Defaults + +A - Software License Agreement + +
+

Preface

+

This software users manual describes how to use the Common UNIX + Printing SystemTM ("CUPSTM") Version 1.1.17.

+

System Overview

+

CUPS provides a portable printing layer for UNIX®-based operating + systems. It has been developed by Easy + Software Products to promote a standard printing solution for all + UNIX vendors and users. CUPS provides the System V and Berkeley + command-line interfaces.

+

CUPS uses the Internet Printing Protocol ("IPP") as the basis for + managing print jobs and queues. The Line Printer Daemon ("LPD") Server + Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are + also supported with reduced functionality. CUPS adds network printer + browsing and PostScript Printer Description ("PPD") based printing + options to support real-world printing under UNIX.

+

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.

+ + +

Document Overview

+

This software users manual is organized into the following sections:

+ +

Notation Conventions

+

Various font and syntax conventions are used in this guide. Examples + and their meanings and uses are explained below: +

+ + + + + + + + + + + + +
Example   Description
 
lpstat +
lpstat(1)
   The names of commands; + the first mention of a command or function in a chapter is followed by + a manual page section number.
 
/var +
/usr/share/cups/data/testprint.ps
    +File and directory names.
 
Request ID is Printer-123 +   Screen output.
 
lp -d printer filename ENTER +   Literal user input; special keys like ENTER are + in ALL CAPS.
 
12.3   Numbers in the text are + written using the period (.) to indicate the decimal point.
+
+ + +

+

Abbreviations

+ The following abbreviations are used throughout this manual: +
    +
    +
    kb
    +
    Kilobytes, or 1024 bytes +
     
    +
    Mb
    +
    Megabytes, or 1048576 bytes +
     
    +
    Gb
    +
    Gigabytes, or 1073741824 bytes +
     
    +
    +
+

Other References

+
    +
    +
    CUPS Software Administrators Manual
    +
    An administration guide for the CUPS software. +
     
    +
    CUPS Software Programmers Manual
    +
    A programmer guide for interfacing with and/or extending the CUPS + software. +
     
    +
    +
+

1 - Printing System Overview

+

This chapter provides an overview of how the Common UNIX Printing + System works.

+

The Printing Problem

+

For years the printing problem has plagued UNIX. Unlike + Microsoft® Windows® 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.

+

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.

+

CUPS is designed to eliminate the printing problem. 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.

+

The Technology

+

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.

+

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.

+

IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP") + 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.

+

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.

+

Jobs

+

Each file or set of files that is submitted for printing is called a + job. 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.

+

Classes

+

CUPS supports collections of printers known as classes. Jobs + sent to a class are forwarded to the first available printer in the + class.

+

Filters

+

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.

+

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 ("RIP") filters that convert + PostScript or image files into bitmaps that can be sent to a raster + printer.

+

Backends

+

Backends perform the most important task of all - they send the + filtered print data to the printer.

+

CUPS provides backends for printing over parallel, serial, and USB + ports, and over the network via the IPP, JetDirect (AppSocket), and + Line Printer Daemon ("LPD") protocols. Additional backends are + available in network service packages such as the SMB backend included + with the popular SAMBA software.

+

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.

+

Printer Drivers

+

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.

+

Networking

+

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 "name@server".

+

CUPS also provides implicit classes, 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!

+

2 - Using the Printing System +

+

This chapter shows you how to submit, query, and cancel print jobs to + different printers.

+

Submitting Files for Printing

+

CUPS provides both the System V (lp(1)) and Berkeley ( +lpr(1)) printing commands. Type the following command to print a + file to the default (or only) printer on the system:

+
    +
    +lp filename ENTER
    +
    +
+

or:

+
    +
    +lpr filename ENTER
    +
    +
+

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!

+

Choosing a Printer

+

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.

+

Use the lpstat(1) command to see a list of available + printers:

+
    +
    +lpstat -p -d ENTER
    +
    +
+

The -p option specifies that you want to see a list of + printers, and the -d option reports the current default + printer or class.

+

Use the -d option with the lp command to + print to a specific printer:

+
    +
    +lp -d printer filename ENTER
    +
    +
+

or the -P option with the lpr command:

+
    +
    +lpr -P printer filename ENTER
    +
    +
+

Setting Printer Options

+

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.

+

The lp and lpr commands allow you to pass + printer options using the -o option:

+
    +
    +lp -o landscape -o scaling=75 -o media=A4 filename.jpg
    +lpr -o landscape -o scaling=75 -o media=A4 filename.jpg
    +
    +
+

The available printer options vary depending on the printer. The + standard options are described in Chapter + 3, "Standard Printing Options".

+

Printing Multiple Copies

+

Both the lp and lpr commands have options + for printing more than one copy of a file:

+
    +
    +lp -n num-copies filename ENTER
    +lpr -#num-copies filename ENTER
    +
    +
+

Copies are normally not collated for you. Use the -o + Collate=True option to get collated copies :

+
    +
    +lp -n num-copies -o Collate=True filename ENTER
    +lpr -#num-copies -o Collate=True filename ENTER
    +
    +
+ + +

Checking the Printer Status from the Command-Line

+

The lpstat command can be used to check for jobs that + you have submitted for printing:

+
    +
    +lpstat ENTER
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +
    +
+

The jobs are listed in the order they will be printed. Use the +-p option to see which files and printers are active:

+
    +
    +lpstat -p ENTER
    +printer DeskJet now printing DeskJet-1.
    +
    +
+ + +

Use the -o and -p options together to show + the jobs and the printers:

+
    +
    +lpstat -o -p ENTER
    +Printer-1 johndoe 4427776
    +Printer-2 johndoe 15786
    +Printer-3 johndoe 372842
    +printer DeskJet now printing DeskJet-1.
    +
    +
+

Checking the Printer Status from the Web

+

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:

+ +

From there you can view the status of classes, jobs, and printers + with the click of a button!

+

Canceling a Print Job

+

The cancel(1) and lprm(1) commands cancel a + print job:

+
    +
    +cancel job-id ENTER
    +lprm job-id ENTER
    +
    +
+

The job-id is the number that was reported to you by the + lp or lpstat commands.

+

3 - Standard Printer + Options

+

This chapter describes the standard printer options that are + available when printing with the lp and lpr + commands.

+

General Options

+

The following options apply when printing all types of files. + +

+

Selecting the Media Size, Type, and Source

+

The -o media=xyz option sets the media size, type, + and/or source:

+
    +
    +lp -o media=Letter filename ENTER
    +lp -o media=Letter,MultiPurpose filename ENTER
    +lpr -o media=Letter,Transparency filename ENTER
    +lpr -o media=Letter,MultiPurpose,Transparency filename ENTER
    +
    +
+ + +

The available media sizes, types, and sources depend on the printer, + but most support the following options (case is not significant):

+
    +
  • Letter - US Letter (8.5x11 inches, or 216x279mm)
  • +
  • Legal - US Legal (8.5x14 inches, or 216x356mm)
  • +
  • A4 - ISO A4 (8.27x11.69 inches, or 210x297mm)
  • +
  • COM10 - US #10 Envelope (9.5x4.125 inches, or + 241x105mm)
  • +
  • DL - ISO DL Envelope (8.66x4.33 inches, or 220x110mm)
  • +
  • Transparency - Transparency media type or source
  • +
  • Upper - Upper paper tray
  • +
  • Lower - Lower paper tray
  • +
  • MultiPurpose - Multi-purpose paper tray
  • +
  • LargeCapacity - Large capacity paper tray
  • +
+

The actual options supported are defined in the printer's PPD file in + the PageSize, InputSlot, and MediaType + options.

+

Setting the Orientation

+

The -o landscape option will rotate the page 90 degrees + to print in landscape orientation:

+
    +
    +lp -o landscape filename ENTER
    +lpr -o landscape filename ENTER
    +
    +
+

Printing On Both Sides of the Paper

+

The -o sides=two-sided-short-edge and -o + sides=two-sided-long-edge options will enable duplexing on the + printer, if the printer supports it. The -o + sides=two-sided-short-edge option is suitable for landscape + pages, while the -o sides=two-sided-long-edge option is + suitable for portrait pages:

+
    +
    +lp -o sides=two-sided-short-edge filename ENTER
    +lp -o sides=two-sided-long-edge filename ENTER
    +lpr -o sides=two-sided-long-edge filename ENTER
    +
    +
+

The default is to print single-sided:

+
    +
    +lp -o sides=one-sided filename ENTER
    +lpr -o sides=one-sided filename ENTER
    +
    +
+

Banner Options

+

The following options apply when printing all types of files.

+

Selecting the Banner Page(s)

+

The -o jobsheets=start,end option sets the banner + page(s) to use for a job:

+
    +
    +lp -o job-sheets=none filename ENTER
    +lp -o job-sheets=standard filename ENTER
    +lpr -o job-sheets=classified,classified filename ENTER
    +
    +
+

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.

+

The available banner pages depend on the local system configuration; + CUPS includes the following banner files:

+
    +
  • none - Do not produce a banner page.
  • +
  • classified - A banner page with a "classified" label at + the top and bottom.
  • +
  • confidential - A banner page with a "confidential" + label at the top and bottom.
  • +
  • secret - A banner page with a "secret" label at the top + and bottom.
  • +
  • standard - A banner page with no label at the top and + bottom.
  • +
  • topsecret - A banner page with a "top secret" label at + the top and bottom.
  • +
  • unclassified - A banner page with an "unclassified" + label at the top and bottom.
  • +
+

Document Options

+

The following options apply when printing all types of files.

+

Selecting a Range of Pages

+

The -o page-ranges=pages option selects a range of pages + for printing:

+
    +
    +lp -o page-ranges=1 filename ENTER
    +lp -o page-ranges=1-4 filename ENTER
    +lp -o page-ranges=1-4,7,9-12 filename ENTER
    +lpr -o page-ranges=1-4,7,9-12 filename ENTER
    +
    +
+

As shown above, the pages 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 page-ranges option.

+

The default is to print all pages.

+

Selecting Even or Odd Pages

+

Use the -o page-set=set option to select the even or odd + pages:

+
    +
    +lp -o page-set=odd filename ENTER
    +lp -o page-set=even filename ENTER
    +lpr -o page-set=even filename ENTER
    +
    +
+

The default is to print all pages.

+

Setting the Output Order

+

The the -o outputorder=order option to set the output + order of all pages:

+
    +
    +lp -o outputorder=normal filename ENTER
    +lp -o outputorder=reverse filename ENTER
    +lpr -o outputorder=reverse filename ENTER
    +
    +
+

N-Up Printing

+

The -o number-up=value option selects N-Up printing. + N-Up printing places multiple document pages on a single printed page. + CUPS supports 1, 2, 4, 6, 9, and 16-Up formats; the default format is + 1-Up:

+
    +
    +lp -o number-up=1 filename ENTER
    +lp -o number-up=2 filename ENTER
    +lp -o number-up=4 filename ENTER
    +lpr -o number-up=16 filename ENTER
    +
    +
+

The -o page-border=value option chooses the border to + draw around each page:

+
    +
  • -o page-border=double; draw two hairline borders around + each page
  • +
  • -o page-border=double-thick; draw two 1pt borders + around each page
  • +
  • -o page-border=none; do not draw a border (default)
  • +
  • -o page-border=single; draw one hairline border around + each page
  • +
  • -o page-border=single-thick; draw one 1pt border around + each page
  • +
+

The -o number-up-layout=value option chooses the layout + of the pages on each output page:

+
    +
  • -o number-up-layout=btlr; Bottom to top, left to right
  • +
  • -o number-up-layout=btrl; Bottom to top, right to left
  • +
  • -o number-up-layout=lrbt; Left to right, bottom to top
  • +
  • -o number-up-layout=lrtb; Left to right, top to bottom + (default)
  • +
  • -o number-up-layout=rlbt; Right to left, bottom to top
  • +
  • -o number-up-layout=rltb; Right to left, top to bottom
  • +
  • -o number-up-layout=tblr; Top to bottom, left to right
  • +
  • -o number-up-layout=tbrl; Top to bottom, right to left
  • +
+

Mirroring Prints

+

You can mirror a print using the -o mirror option:

+
    +
    +lp -o mirror filename ENTER
    +lpr -o mirror filename ENTER
    +
    +
+

This is useful for printing mirrored pages on transfer paper, for T + shirts, mugs, etc.

+

Setting the Brightness

+

You can control the overall brightness of the printed output using + the -o brightness=percent option:

+
    +
    +lp -o brightness=120 filename ENTER
    +lpr -o brightness=120 filename ENTER
    +
    +
+

Values greater than 100 will lighten the print, while values less + than 100 will darken it.

+

Setting the Gamma Correction

+

You can control the overall gamma correction of the printed output + using the -o gamma=value option:

+
    +
    +lp -o gamma=1700 filename ENTER
    +lpr -o gamma=1700 filename ENTER
    +
    +
+

Values greater than 1000 will lighten the print, while values less + than 1000 will darken it. The default gamma is 1000.

+

Text Options

+

The following options apply when printing text files.

+

Setting the Number of Characters Per Inch

+

The -o cpi=value option sets the number of characters + per inch:

+
    +
    +lp -o cpi=10 filename ENTER
    +lp -o cpi=12 filename ENTER
    +lpr -o cpi=17 filename ENTER
    +
    +
+

The default characters per inch is 10.

+

Setting the Number of Lines Per Inch

+

The -o lpi=value option sets the number of lines per + inch:

+
    +
    +lp -o lpi=6 filename ENTER
    +lpr -o lpi=8 filename ENTER
    +
    +
+

The default lines per inch is 6.

+

Setting the Number of Columns

+

The -o columns=value option sets the number of text + columns:

+
    +
    +lp -o columns=2 filename ENTER
    +lpr -o columns=3 filename ENTER
    +
    +
+

The default number of columns is 1.

+

Setting the Page Margins

+

Normally the page margins are set to the hard limits of the printer. + Use the -o page-left=value, -o page-right=value +, -o page-top=value, and -o page-bottom=value + options to adjust the page margins:

+
    +
    +lp -o page-left=value filename ENTER
    +lp -o page-right=value filename ENTER
    +lp -o page-top=value filename ENTER
    +lp -o page-bottom=value filename ENTER
    +lpr -o page-bottom=value filename ENTER
    +
    +
+

The value argument is the margin in points; each point + is 1/72 inch or 0.35mm.

+

Pretty Printing

+

The -o prettyprint 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:

+
    +
    +lp -o prettyprint filename ENTER
    +lpr -o prettyprint filename ENTER
    +
    +
+

Image Options

+

The following options apply when printing image files.

+

Positioning the Image

+

The -o position=name option specifies the position of + the image on the page:

+
    +
  • center - Center the image on the page (default)
  • +
  • top - Print the image centered at the top of the page
  • +
  • left - Print the image centered on the left of page
  • +
  • right - Print the image centered on the right of the + page
  • +
  • top-left - Print the image at the top left corner of + the page
  • +
  • top-right - Print the image at the top right corner of + the page
  • +
  • bottom - Print the image centered at the bottom of the + page
  • +
  • bottom-left - Print the image at the bottom left corner + of the page
  • +
  • bottom-right - Print the image at the bottom right + corner of the page
  • +
+

Scaling the Image

+

The -o scaling=percent, -o ppi=value, and +-o natural-scaling=percent options change the size of a printed + image:

+
    +
    +lp -o scaling=percent filename ENTER
    +lp -o ppi=value filename ENTER
    +lpr -o natural-scaling=percent filename ENTER
    +
    +
+

The scaling=percent value is a number from 1 to 800 + specifying the size in relation to the page (not 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.

+

The ppi=value 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.

+

The natural-scaling=percent 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.

+

Adjusting the Hue (Tint) of an Image

+

The -o hue=value option will adjust the hue of the + printed image, much like the tint control on your television:

+
    +
    +lp -o hue=value filename ENTER
    +lpr -o hue=value filename ENTER
    +
    +
+ + +

The value 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: +

+ + + + + + + + +
Originalhue=-45hue=45
RedPurpleYellow-orange
GreenYellow-greenBlue-green
YellowOrangeGreen-yellow
BlueSky-bluePurple
MagentaIndigoCrimson
CyanBlue-greenLight-navy-blue
+
+

+

The default hue adjustment is 0.

+

Adjusting the Saturation (Color) of an Image

+

The -o saturation=percent option adjusts the saturation + of the colors in an image, much like the color knob on your television:

+
    +
    +lp -o saturation=percent filename ENTER
    +lpr -o saturation=percent filename ENTER
    +
    +
+

The percent 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.

+

The default saturation is 100. + +

+

HP-GL/2 Options

+

The following options apply to HP-GL/2 files.

+

Printing in Black

+

The -o blackplot option specifies that all pens should + plot in black:

+
    +
    +lp -o blackplot filename ENTER
    +lpr -o blackplot filename ENTER
    +
    +
+

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.

+

Fitting the Plot on the Page

+

The -o fitplot option specifies that the plot should be + scaled to fit on the page:

+
    +
    +lp -o fitplot filename ENTER
    +lpr -o fitplot filename ENTER
    +
    +
+

The default is to use the absolute distances specified in the plot + file. +

+ + +
NOTE: +

This feature depends upon an accurate plot size (PS) + 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.

+
+
+

+

Setting the Default Pen Width

+

The -o penwidth=value option specifies the default pen + width for HP-GL/2 files:

+
    +
    +lp -o penwidth=value filename ENTER
    +lpr -o penwidth=value filename ENTER
    +
    +
+

The pen width value 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. +

+ + +
NOTE: +

This option is ignored when the pen widths are set in the plot file.

+
+
+

+

Raw or Unfiltered Output

+

The -o raw option allows you to send files directly to a + printer without filtering. This is sometimes required when printing + from applications that provide their own "printer drivers" for your + printer:

+
    +
    +lp -o raw filename ENTER
    +lpr -o raw filename ENTER
    +
    +
+

The -l option can also be used with the lpr + command to send files directly to a printer:

+
    +
    +lpr -l filename ENTER
    +
    +
+

4 - Saving Printer Options + and Defaults

+

This chapter describes how to save printer options for your printer + and set your own default printer.

+

Printer Options

+

Each printer supports a large number of options, which you learned + about in Chapter 3, "Standard Printer + Options". Rather than specifying these options each time you print + a file, CUPS allows you to save them as "default" options for the + printer.

+

The lpoptions(1) command saves the options for your + printers. Like the lp and lpr commands, it + accepts printer options using the -o argument:

+
    +
    +lpoptions -o prettyprint ENTER
    +lpoptions -o media=A4 -o sides=two-sided-long-edge ENTER
    +lpoptions -o media=Legal -o scaling=100 ENTER
    +
    +
+

Once saved, any lp or lpr command will use + them when you print.

+

Setting Options for a Specific Printer

+

The previous example shows how to set the options for the default + printer. The -p printer option specifies the options are + for another printer:

+
    +
    +lpoptions -p laserjet -o prettyprint ENTER
    +lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTER
    +lpoptions -p deskjet -o media=Legal -o scaling=100 ENTER
    +
    +
+

Removing Options

+

The previous two examples shows how to set options for the default + and a specific printer. Below, shows you how to remove the saved option + using the -r argument:

+
    +
    +lpoptions -r prettyprint ENTER
    +lpoptions -p laserjet -r prettyprint ENTER
    +
    +
+

Viewing the Current Defaults

+

The lpoptions command can also be used to show the + current options by not specifying any new options on the command-line:

+
    +
    +lpoptions ENTER
    +media=A4 sides=two-sided-long-edge
    +lpoptions -p deskjet ENTER
    +media=Legal scaling=100
    +
    +
+

Viewing Options for a Specific Printer

+

You can display the supported options using the lpoptions + command with the -l option, as follows:

+
    +
    +lpoptions -p laserjet -l ENTER
    +
    +
+

Setting the Default Printer

+

The administrator normally will set a system-wide default printer + that is normally used as the default printer by everyone. Use the +-d printer option to set your own default printer:

+
    +
    +lpoptions -d deskjet ENTER
    +
    +
+

The printer can be local (deskjet) or remote ( +deskjet@server).

+

Printer Instances

+

Besides setting options for each print queue, CUPS supports + printer instances which allow you to define several different sets + of options for each printer. You specify a printer instance using the + slash (/) character:

+
    +
    +lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTER
    +lpoptions -p laserjet/legal -o media=Legal ENTER
    +
    +
+

The lp and lpr commands also understand + this notation:

+
    +
    +lp -d laserjet/duplex filename ENTER
    +lpr -P laserjet/legal filename ENTER
    +
    +
+

Removing Instances

+

Use the -x printer/instance option to remove a printer + instance that you no longer need:

+
    +
    +lpoptions -x laserjet ENTER
    +lpoptions -x laserjet/duplex ENTER
    +lpoptions -x laserjet/legal ENTER
    +
    +
+

The -x option only removes the default options for that + printer and instance; the original print queue will remain until + deleted with the lpadmin(8) command by the administrator.

+

A - Software License Agreement

+

Common UNIX Printing System License + Agreement

+

Copyright 1997-2002 by Easy Software Products +
44141 AIRPORT VIEW DR STE 204 +
HOLLYWOOD, MARYLAND 20636-3111 USA +
+
Voice: +1.301.373.9600 +
Email: cups-info@cups.org +
WWW: http://www.cups.org

+

Introduction

+

The Common UNIX Printing SystemTM, ("CUPSTM"), + is provided under the GNU General Public License ("GPL") and GNU + Library General Public License ("LGPL"), Version 2, with exceptions for + Apple operating systems and the OpenSSL toolkit. A copy of the + exceptions and licenses follow this introduction.

+

The GNU LGPL applies to the CUPS API library, located in the "cups" + subdirectory of the CUPS source distribution and in the "cups" include + directory and library files in the binary distributions. The GNU GPL + applies to the remainder of the CUPS distribution, including the + "pdftops" filter which is based upon Xpdf and the CUPS imaging library.

+

For those not familiar with the GNU GPL, the license basically allows + you to:

+
    +
  • Use the CUPS software at no charge.
  • +
  • Distribute verbatim copies of the software in source or binary form.
  • +
  • Sell verbatim copies of the software for a media fee, or sell + support for the software.
  • +
  • Distribute or sell printer drivers and filters that use CUPS so long + as source code is made available under the GPL.
  • +
+

What this license does not 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. The only exceptions to this are the portions of + the CUPS software covered by the Apple operating system license + exceptions outlined later in this license agreement.

+

The GNU LGPL relaxes the "link-to" restriction, allowing you to + develop applications that use the CUPS API library under other licenses + and/or conditions as appropriate for your application.

+

License Exceptions

+

In addition, as the copyright holder of CUPS, Easy Software Products + grants the following special exceptions:

+
    +
  1. Apple Operating System Development License Exception; +
      +
    1. Software that is developed by any person or entity for an Apple + Operating System ("Apple OS-Developed Software"), including but not + limited to Apple and third party printer drivers, filters, and backends + for an Apple Operating System, that is linked to the CUPS imaging + library or based on any sample filters or backends provided with CUPS + shall not be considered to be a derivative work or collective work + based on the CUPS program and is exempt from the mandatory source code + release clauses of the GNU GPL. You may therefore distribute linked + combinations of the CUPS imaging library with Apple OS-Developed + Software without releasing the source code of the Apple OS-Developed + Software. You may also use sample filters and backends provided with + CUPS to develop Apple OS-Developed Software without releasing the + source code of the Apple OS-Developed Software.
    2. +
    3. An Apple Operating System means any operating system software + developed and/or marketed by Apple Computer, Inc., including but not + limited to all existing releases and versions of Apple's Darwin, Mac OS + X, and Mac OS X Server products and all follow-on releases and future + versions thereof.
    4. +
    5. This exception is only available for Apple OS-Developed Software and + does not apply to software that is distributed for use on other + operating systems.
    6. +
    7. All CUPS software that falls under this license exception have the + following text at the top of each source file:
      This file is + subject to the Apple OS-Developed Software exception.
    8. +
    +
  2. +
  3. OpenSSL Toolkit License Exception; +
      +
    1. Easy Software Products explicitly allows the compilation and + distribution of the CUPS software with the OpenSSL Toolkit.
    2. +
    +
  4. +
+

No developer is required to provide these exceptions in a derived + work.

+

Trademarks

+

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. Please contract Easy + Software Products for written permission to use them in derivative + products. 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.

+

Binary Distribution Rights

+

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.

+

The Common UNIX Printing System provides a "pdftops" filter that is + based on the Xpdf software. For binary distribution licensing of this + software, please contact:

Derek B. Noonburg +
Email: derekn@foolabs.com +
WWW: + http://www.foolabs.com/xpdf/

+

Support

+

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:

+ + + +

GNU GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow.

+

GNU GENERAL PUBLIC LICENSE +
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+
    +
  1. 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 "Program", below, + refers to any such program or work, and a "work based on the Program" + 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 "modification".) Each licensee is addressed as "you". +

    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.

    +
  2. 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. +

    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.

    +
  3. 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: +
      +
    1. You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change.
    2. +
    3. 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.
    4. +
    5. 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.)
    6. +
    +

    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.

    +

    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.

    +

    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.

    +
  4. 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: +
      +
    1. 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,
    2. +
    3. 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,
    4. +
    5. 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.)
    6. +
    +

    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.

    +

    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.

    +
  5. 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.
  6. +
  7. 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.
  8. +
  9. 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.
  10. +
  11. 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. +

    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.

    +

    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.

    +

    This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

    +
  12. 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.
  13. +
  14. 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. +

    Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", 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.

    +
  15. 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.
  16. + + + + + + +
+

NO WARRANTY

+
    +
  1. 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 "AS IS" 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.
  2. +
  3. 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.
  4. +
+

END OF TERMS AND CONDITIONS

+ + +

GNU LIBRARY GENERAL PUBLIC LICENSE

+

Version 2, June 1991

+
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+

Preamble

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

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.

+

The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, while the latter only + works together with the library.

+

Note that it is possible for a library to be covered by the ordinary + General Public License rather than by this special one.

+

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+

0. 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 "this License"). Each + licensee is addressed as "you".

+

A "library" 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.

+

The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" 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 "modification".)

+

"Source code" 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.

+

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.

+

1. 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.

+

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.

+

2. 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:

+
    +
  1. The modified work must itself be a software library. +

    +
  2. You must cause the files modified to carry prominent notices stating + that you changed the files and the date of any change. +

    +
  3. You must cause the whole of the work to be licensed at no charge to + all third parties under the terms of this License. +

    +
  4. 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. +

    (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.)

    +
  5. + + + +
+

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.

+

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.

+

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.

+

3. 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.

+

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.

+

This option is useful when you wish to copy part of the code of the + Library into a program that is not a library.

+

4. 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.

+

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.

+

5. 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 "work that uses the + Library". Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License.

+

However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. Section + 6 states terms for distribution of such executables.

+

When a "work that uses the Library" 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.

+

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.)

+

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.

+

6. As an exception to the Sections above, you may + also compile or link a "work that uses the Library" 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.

+

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:

+
    +
  1. 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 "work that uses the Library", 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.) +

    +
  2. 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. +

    +
  3. 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. +

    +
  4. Verify that the user has already received a copy of these materials + or that you have already sent this user a copy.
  5. + + + +
+

For an executable, the required form of the "work that uses the + Library" 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.

+

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.

+

7. 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:

+
    +
  1. 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. +

    +
  2. 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.
  3. + +
+

8. 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.

+

9. 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.

+

10. 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.

+

11. 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.

+

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.

+

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.

+

This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License.

+

12. 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.

+

13. 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.

+

Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and "any + later version", 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.

+

14. 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.

+

NO WARRANTY

+

15. 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 "AS IS" 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.

+

16. 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.

+

END OF TERMS AND CONDITIONS

+ + diff --git a/doc/sum.pdf b/doc/sum.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e67bc7a3dc574f14c11dca272b7597c8d7f7618d GIT binary patch literal 100081 zc-q8$c|6qL_kR)!l`L7agtC;G*X(1>zGNM1j4~MeI%5>2EYV`AM4}R*>`4)_MUpL1 zLuE@vA?^F-_nLXBcjNs=pYK0E@5g86-q)OapXc6l&b{ZJdwPB3E%gjG11d;v`NvPX z?{WjuaOpr-A9Zz@B_+_E=0>I{c!l`;xd*yQ11dNb1X5ZzFer@T?dcUF4dC(E%?LOg zA+1lMhDloodW7sGQOMFz%Mj`&X>C70X##_mDor3$$&^sCyNV)AmqI3mcn1dPkwVA{ zda8^b062gK5NHentqe!O;fgRD?+`z-g08Kl^*{aEf;~{B%}4<>lAj_>n-<~~NKu#% z`ajtGPkt0NHOT?);E=fyzlUxU7DR^W2e<{gdk1*J^t?Sh$P{vb8=2}PjYPnxK_oXa zjJ(UukK_*vrUizO-Cg})0W^PCkUekD0GNBApC5?=3nEk8$N?cRl0R6Yk^_6UJWOjcneY6zL)P4$HZ`O&B_w?Kb?63pK_04#%Dcn7+}sD31>7c87i z34{d(kYOP^17RUv6fzm+5lExJJiJ56Fsk=17?m7K4uFxFeFk`ggl>U;fdSxSe{ZPd zN2XF?R!(h3UccVFoZmm=VkvW&+y^GliMK%wZNV zOPCdm0JDbKz-(c5FngE-Y#YoG=1L*C`I1AJLvjU+5UaCKe+|#g+uO~X;zsj_(E{AT zS#b-bkUM&Rss4A|MKwokIV-l%kH>MW+?#AtxA;AJE z?jE29F%^md?nm|ygyiiP=;`f7@(TzIfq8`md4U~L$e!K|D6%`upXA11*PZOiP*jFy zLn;j_FO|mBYYL>qziT8nS_m2DPh*${3Dk}tuUY+PjDXpv8`&MiCozoRcPo%Re^Bl; zKNkLGSr1?+JB6X=V9|@@=K(>^KBWHEe&$4JLmH_K@uB^P+_fQDX#buaZ3<&9we?}T zzgW_T8tX%i_5WzB|GSkjL}Lum82>?I{F_EU#0zE)!C64$77)3`ALJIZ1ixGP)BHlb zgZ#o^7LfhfLQQRY>8EQ=aqcQn+D{qL#8=~?4gU0(e4H=w<00=G+A`gVf1OFfooF(|( z%H2EEoACge1RB(k1~sJp(UA7LMHuvB2y+s`em!>ny*nUTcL#$&(3Y%et|5#H;|T!M z0ap*^V_k492HXGML8KWw3*mQ9sQx2+7aeZNBdC{}tpX5n~*?YT(cuAv>0LT;5 zuR{Z1m);>%OEN__&_4)V*8@Oj527|BQGKODC?LBA-hPZ#-@p%aa`ea`>tvWIIlvR_ z3JFKUrI~-4n$!@`3-agQ^>BK~to$^Ne~Al8;>ei^GHgSq1j*dxtI_4tsa7MVhCOSp z+>18iG>-g9AQWcq*nPgaB8ac_YoT=N@hY4E7qI_wbTrqc zsM0F?`<0_6mtI$_vE6@P&-#r8P?>BK{Z@*-$zsfjGjYjdlHR?{?BXsyd1~rS_J^0Y zJZ4Mf<=wGa-l_s4csSX1na;9z3QPStj>pA?3dpWpIW`3BO+@EyJxov8R9JCtmsJ

3^*j;{TqSBwv8 zi?PpE!4=LcIma3U9bD2Jra#wsUAdlhkH|ADZCz~ReWm4?1}}G4#afET!BmA+FLn*P zL^fO%RO{bNNF@c-PgZ5L8%`N%2Xh=hPt>Wfzd35y*BR;m)g`T8Z)sqjC`W}>hu`3q^r{->no-9w! z9a$eGr8Rp1IWwGaYNw6b>nJfw#oAO8p)2fCXY2Ow!Fpld<%Q}{Id;_H^Hy{T`RzG> z{)rd%-DJvol)c$zA$fjz@aZ0(2`eS5=sUNfGOTUY>PiJ#RwPP1ZA!_%WO$6wd?Cep zi^V&8!q7{!#gi}3EecTM= z_St1H0hBv$KKyp-sF^nKwa)%%-nsz=28?7e4W zx!x#W@692Lu&<@ZGU_r;^9!8iIV|f_dru^DrkS3s*aojix%WCBJz`tTy*qzvM19Ko z{4VA3l%$#xOSW^vwK`v4;0cCVn4*v89dG%|d$$U(eD{NvW2M$%peWSRb!2#w_fb+}7E=C&SNnUB z3;Y|b?@URAs4HFFeJ{u0T=Z9XW!9>SP{pPTbp$P4e+`qLytF;F{I3YjBc{RagHxUb z5qtH6k(oz4546X%m_5J0!E}anEr*I5KTkQoGh+?yrB^_7q_ThOl4{3QST8NQh>}_= zGEB|IM|1F~h<($?y5Nn4#XH$=TdzEZ5ZEGK7kISjO;B^S^(CY9g3}SJt(!;VH1f;O z&OEeq%I~xZ@XT@DAw4nPO;@9b{@ksMHGMld=%RPV@UiuZ3w@Sg6FhhMRiby1jrIeh z`e|ClexLG5^_vks`FI--CC|4e;T6L^S51Uda`P2!LX|wvx32u)l&?858A*&C_%I-% zgiO7BIpB`%hu!(Zd=)Jw4->vd9K2^|*RGUyV8$h?T%a*IIcCJV-r%skpw##6Us5Ah z)A6YS@2au;Oz4*{+?RAYl#*Z2^9jTAZEYdm+VGrTcjar#Hp2p<*>$nE7qc^zd_ML# z+(_G!z9Q=+x6hknJKXa_%+8qAPG1e@pShu%e$E4f6_cJ*^-v|CQwrk&QON=sIL7nW7@W1KX z!z=$nt3A|Gys-0@_Jf=+6(S0E_vN(n#!Qd&e|8u4Zs)zZ_Aco)yF;8tUt{Ra+~;2 zL@BG-FE$)bzW1oS=lchjEM+zJz86O(9C_~zESD|KT_-mE;>Z`rkoK2Zfz8`(#)UgY z&wLA16ddzlbFtWZO-9rzy~tLDtSL~i!v5izHE@AZ-=3mFse)Bc%Z1NYwOCF>Q!dmE zN{+5IHmNz1v6Ean9{te&X{Xnx?Ry-<9?vK$4p>ON41}$>ol#LzI~&}t(t8iNwqfld zlihjN6@v7abV=nm7oFtYUR=IhMXwMk+;`&Mp224uN?QuWjC?j14i&kt>{hhWHrsBd z0X8`_Y06D=_M&V~7IgYjGWht+yUSMMr6~>hV~)Hjg#|rD$If4AP}gtO*kU&QQ|GuZ zK;SBE+<{mcEJaiLk^l7j%~6^8)D4N@iR(w4@I8?i%2gc3&ipcl$<+!}iP^(OV z^OlhA<=dw79m7*5?VOJE=4b3qIbZmESl(Rqk z52`ujt}+<3y|1iPopbbVXlnmG$&nq3UdA&Sy&UMfDc1&UdVB5ba^3d`mz>KBG+vqe zwC<&1AF74t@Q3^}Cl0o)>qBuITH3q0<>(-ORqmFAUAEL*~rv-zsAhwWYB5wMPsap+_Gj?q}$8`--x+mtLDk zjB&0~l26?Bd-T5Ldn~67vARcW*FJP=(ag#|Z}2GQu<;$G#+A>YHX&MsBuo+rCq z(cau%2NJrf&jjw;;%nPfPH(+uIc%2PzUv%egDIKK!1sJtOP`6-&jN}q_LgjHUv#{^ zRhlhvXMoBLjgoyQ1reJ{TpWD?J08jF#bWNooL3J0NHufV)x0^rIi;^i@KSiw!M)oG zevZ}+@ed6XN?NA+dtW&U=qoj+(}jnOCyfLPEWNg4Q_sB>D>eKB?PvF46jzH6d^}H#MbSsXtkJzT&->I#Udi>4T`_W>b zOCR3mDHKHSKlZRd=0(AgbtmrOZfS3_B?@2J^rFzTUNB_?XU>JkU#%>;0FgudS6o7D zN_NDX+>Jh_AWb$f9GfXPCzqF~mg!YyD|i$W|2;SED-t0`zI@9f>wY1(!YTcT@|%N} zh3WgbJ{*#nzEJwwW3a$NXWOa6uN_2Qtbo-DY1>pt?Tk^(|A5rD6|2PD8$PH%I-zwg z`6aoc|7ziT8`%dqDqG2MwdZYReaOt$0tid3i*`66PWt7hJSq*Q={(iYnRo6ic=VX{ z`F|Zk(0_9XVV*0P=M@5Yn)VB%STllbPB7yDck(W>J4}xp>g`4*80tu))#1!PB=Zl$ z{KGTVPLT z;BHq~=*6z;YbDQe9)Frq3Ve5Ag~F}QC5IzAu2VIpb(%Lf2Xcy-j_hk&`U9J0z2;TJ zr*A(x?pE*l-u<)t+r#P`13wFlLdGV(e26$heEcb1(l~lxW}9f*XMeY^o4PN4aIAW5 ziM^ub`zU<3@h$nG{$tc1%KY2IH1#__oZ32eS3)M^(pxo;%7>l89sioPOle!4T>nKm z2V;x);IKYz3l~0YpW&D4nPX8NcbHp2{V4yJXHsO0thk zD6feA{QCH?aejRXV!CIk8^7^`urZ(GUMADWl-DZj;en<0sd_f%!&NmW%Zhv1rUX{n z++$M~Txoibt>`f7wd0X7AJ^t`UXfypCsyp7%J+69P;Ukw61lYDNw`DKO<50-;%@mI z50OqR(W3j?kM2*@FFWf$^My9LoESAZyDw?umoJifWo$98n^Vo@e#Bo*gR^sHADDVj zWApV{WN6SM)i_b5uzMeeo5Ppmi2L8WUGG|{d8zt-Hs@yN)5evflwjSJ;o$+Tj);4v zD&s+ydJFKnCy><+QR-OnWWZhVNYRR%X~_dG8Xqf-mtVhzRjxJC_&h=nGT!}6PW-e8 zam>#;{%lz4-Rc^SvRf{SXW}=#EjX*3oOhXGO5MC)f7yU#bp}VmQMbeBV?{*n_~n&3 z!L;q_a>B(y6w;%>(GNMF93406E(<(X>$$0Sx@cW&(Hp+oxYV5H12G%vM!qw|{gU@~ zsf>wQ_=NRr${*ET(8G$t+a$D?iCts!NfIQGG?j-LHlcEh8_y{S2V}kH`lJ-9>ibS z5+oFSkW+sOxy-&}b>|83vWK^ATh@!Eu&LdzK5T@_ymxl6oqiKdyv5d0Otf`xj(tz6 zNGv+&S9R1P+;epDTyWbJm9e#@8)`=^@A70*S z!R|KmU1KoQJ13tK|KXkCp4Lbqy=hCLnrxb-WB@w#j!8&KMO0C4i`a3ZxNQHloBNq& z+^VRv(v9ic@kz=6H7a-eI?cgNJtvl(o}g`^tV%-7`}(?^09so}s%^)2k&NWfY1e-y^vUf_61hBE-_-rn09u5Ay;hJEp2seR#>E z4@Ijb*Mn}RiP#HWuCEW3TdDq?MEWyXC58A`tCSCJ+3u^HT^kFsP;s?^Zq>;LSW(v5 zYom0P`>)@k{V1OPVE=iuT2YxliWuz^XIDDdNvmC&`UGinVYl9E{5N z%2G2-d1e!RBxU#p$7%KpoMgh5>W0+7^_jL%jD_wc(m5IfGFe^{-9dL^mMhQPfkYh z>yL$$#?$P_X=9nBgP15aMPjio8C}^MD@p|}U_#Df~A60ggJmY?%rFTLGJ zAKax{BZFBkx+GfSCGUnyqBHQp842n-EvcnnukcTM3za6zinsTa9o=*6hOKw?jXEyF zavARZ&TKNOs0=+7Hi`ZTdVI2C+u-uZ1>qpQYY zoPa!+#D)-y%2dKA?4wDVUp^v3wLMJ2vJqyMY(8+aW#mcS2Cdzj(?o)W4v*2;2xzu- zA2OzMuho7=MP!b0E2b8a+DARB&HFxAz3AEV@M7T-yYb7ml+;=UrSQ^dVf~id^2Dcb z*V5ZotK7zXs(VOJiCy-`o5k&0l2$z#SACn)oL}93al<=o>Eoid(Zu-6=!T^#Z^qnz zw$u0G(_1MeI^$#d(vJoy-+OAS_Byq_Gk#on9|7wR)126QO1(~LVDFKk;U1c%{}q2< z_xtW_r=2vVt0cc+n%lPdR){TIA)En0?NvW=afqWZPFQzxt9`oCBbbJQYt;mQpLZr7W*Zb#cxk>q=UrthPE*h@|=y}KE+C01Nbt$$ko^QoSK<`KPWN$H)z z&7)#yA0e)wZ@4Y~u2OtNg5zP;8%G8+Nx}lF`ty&4KM(16!e%2vYYNinJ&4-&*2!OZ zwL~c?hp@5}hQhz!-*Ndav8mBEy_&MBzpTgQJh2nOZX-f>tCH06Dxdj4R6O8&$7|Oc zn@82Xe8h~YJ)tUQIib&8K1q!U!AD8sx6yqoyJ(tfX%nklN}XUE_g3wXn#%7F1D`GH zud>Rcl|`<|c{{AXI)3-2+Te!9V3m@@`L2Tce?5a=^m17BlVU#oHs&5|v$BUq#zr#%?o2Qku)km@ao_Y6X9?$L%|VG`qScX71|Pmg0WS)ZYIX_ui}jZsW4Avt-cD;U z^VJnTzz{&QfkA1zY`?MA;fnhB=BYgjr6gI|{$o;-AH!piey@(y;A(Flcr1od;`A=u zS=uXZ?rnqlJA{^-KjFwy)o|xPVK1o-~Hmfvjp*3bMQ*B)MQs>Vyu*k z;*4bywsb(Ux;{Q;Y7eedJI6|b?o$0$@~Zg+joAAw8|7Sk5Rp|nK6-t+LYSK4Ibrv!0ya{+-^t>>abs%pswrvrRc!QQrZ#R=bM zH|Q1=wgX$eb+@RDsY;#L>Tlzn{6?$lA-P&yo$D-##!7Lg&0|7pW3k zmG;n!Z^a2=m9#O$;i8k{lQ^P}ERB3xD(6vh>ATTt&cqb9q9W01^KlhB36+Xt83xOQ zRi-`~Oy08H@OJIAoz!b9Za-J)uJ!@>nb!@i-=38a zecPgh-k#Ae3%p#Sa`jWY?OtjGwIs^-oqqLO8bxS?`0GE=YOwuS`(33s&P=(D#njuI z6kOZX-_W7f*=ujQQ;{Y-9xl3lhxHDOTph{W+J2u{mR5lYN;of}jykSnI3eznS-(de zUE1+Twcu2CRMpQUd(>n{ZA~kwbw_8Sl5)RxL>8%P|G1uUL^g>!@>n?kl%ZYekOVQy z$uaHiGV$C%-bqANWgPfBdoa?L_d0*SGeX zeRCmx;)}R9FeR)dm<+@8(425$-4uC5tph}VvFiT8{d3C zFjRH^_J^n8?Yj@13SL`s34DI-$F9(hB%<}Rveb`~2g-4!B{W6i`sxP02(_-Ukorvt z>3L%cMJ>d%M*4`vyRoaIRh-+dcx#BYNm!*d(P*8*S0$3ShWDH>$^Mp%w|3_4rvq1o zrKFOl-mQP3kYSeF~lTG5h({;~#HZR`xxcIlop#>Wg0> z?1{dao5R!Rll)Z~@f_O+DZ5Gy1FN9EGsQ?t3UiyE^Vvk$1k=BF1nC-_4!Fcm8L0tO7hzU z?JAp3+8?%_a%lxBu{@<|Bx~`s zj=EEXFV851XBWV(GN!sRI?qhO>%Kp1n>w0!%(oDn%m~~E7hQv?jWS z9s6;j$|t^y{&%&G=$6EQbfutT4OhzFv)1M+J@Y~0WAJkC?VHT$c|pdnVpq1>nibRI zhytLD<&!!lwufS^Xt&T-Y1eJ9QT>A_FwJ-N2^O84O0FvG30xXP^N1AU;^W3#&ie{YGPJ&)U{ct`XF(Zt}jNx2n~JGft)9sl<;flkO^26W4Z*5Z_Vp zn>X2aRXEG1eQp?Qw{Iiwi1e>lu&*>PeaypIpET0?rmJE}{~NGe_3912IGG3h@f`=d zUh6BgQ{nyXA8V-JC2R5ymvnFqe&RF`HbU>MI>(diN3d7h3wuV$(+L(T;=%c4FZ;MV z(2WOYawQZPrdM2 zq7ZS&kNn^vUEK1gG=i(|z8X(H7hgJi(TkfL3NeX(9HCbXBO(vW%2HkOoS!b)csh86 z#<`1;)DWu`5eLdPHzxYo=!~qtvLuLGAoULWdLu3(J%4|_PKeM^UGd|0(w5&{`qU;t z@f_^M%cg=C*i=^9cKE zlG=KrYu|fiACc2}VYx;MEOpzjKj4(kBlG^)a;~fw+~HU57_OHvOj)(WQNwLb($Y&` zldCdP^$2z{Rg&^sjtGCYAf+Xrxz_04 zkU6?q>UErWY|s@W7|;H-z;eUb7qah{X(zZK2MU*-k`dP7lYQNJf13NbVsusFzVLMh zL^}5dk*_KWd>?h!FQ4eyS(3eRMQg7B?~f$T=f+K!UN5_>^))fBC}D5(sKBd8_u8!% zWwPPtwpa)xkvEEHQkEoB9d<=me9jX*>N*y?QDpS}8Y88epo2y@jsuwr5YnZxAgf)Y|3P9vi{(-{-FL&cZmGPi!^m zk1WiMpRQbye4dTwqvCOJxzj_D>ZCVf>;1oRgnwN&pzjk$*|f|(t^TMC2Bo|7Ew`tP zu6l1K_D;#JHM)W~?g-u5dYa68Nk%i^xu}3&l*lDH^VQGs0-KKX@TR7621#~)k57&J zT9*CHwCsU>m%MFPmZw=+`teOp<)5N5(bqjfNkU-(OMGv6+O5)lwWjR+^Un6`2OXm> z4`!;3D@-8SaRai*R*B8ck&#$q&(yE7ZcXg(-gGK_h<f6q79)9JdCu}cKX961? z?yjpUR~?8P4Zo}(B$K-LJe#sZx5(#xKACK8aVr|n7QEwixXv>bIlcUuXj$BZX%tNR z^0IZe6nmajB{`JoN;Fq!Q!0+}o>ZvP#=SR>!+kEyBkQajQW6fw>hjhEt=&@;HQdD) zC$;^iIUE?r)QbtN%fTVDAb^sXzr>D$6HxD1mk|I_TVhu2g7w%!x>@y5dMZ^wxk z32fac#eMrY=IBlXr|i9+yr(_=MP3c!9eHryzDir03MQ3vXl9DYom3dyxa2cHIqP!n{p;*UZ4&C7Ho0MSZb3boqdDKP zmj%uDt3D#_)Gp`VY5RSwRj;u%oGvS}vO{8ZWZDmowlk;4Zy>e`eLmd#(nZUY&@|EP z@;cwFbW;0fMpYu`PxYB*)m@eMh3>6xe?W}5&L+P1F23;l`F)*-y6I(A$?sRw%0$*` z331)8I>~-QuABDgdd7C~ZPkVQonG%yov|xFAN;CGo_}wc!8W%~P2Z-tHmV$8Q|rEL ze+pj@6m06?QcLTIbnY4M+V^ee^`F<&3{@r(roKlnzRC#}2>jMG7W|=<==}JCy2h(d z-_E|08uM@1rzkP=@OFAfYh)O#^1C5#+QFl~&!Rfa_=QDPB<%OFhrVtS8j5^ywLXaG z>fapubp7dvomPC};YOwP2MJyPV{ACz6~ptddwRsXS#uHRfS6+zL@`B3#_rFxn| z-?=v^m6vO8FFmLIRkpv{Pu z{B4{PDkkBN_%p7LXE>`pFQBNGrdPxqW4rZ~pIl3L-h{rOP);~dO?(&i2GMq(m~iFn zHi#p-6JwB^^qr3%h9$KBYZ(B$Mb~Ls~c(4B(dY$3kDowwhk)z}bnv$j4 zYi}SOG^^EDK6qDfB(X@i;SBlpg^Tr{pFX}|HjzV)7woV=_{agLk*^wU_& z{NgJaEi9^^_UJZN;v>xB+1uKYhWZAsnOobc)+)T#k}OHP{qHM-f0E>W-4d932l&DW zWVa9}EJ6h?jlrS7PXLZpK}loqSQWT4Oec`yPNq09GQ_}|9+?{Agn;9i7YYvB9Kmla z5(WP9PjVD?0T2L=W1wK+DmZBXhfzU;h)5OOU!WjSNEQ^_;wWgW3WkwPuYzYHV*VS2 znfo^1Sn!LZpitmkA>b$m3W$jM3lub-1qA_L90dueAfy3s6i6l_VjdL4{9{1?i=zOH zPXN>bEE5s_7bs{Hz=DEUOvTW602B+@2?GS2w)w<@Szsv0MTdgM;+SGVf)mC-MEwN{ z5{+R&K`oAgK{LdHgM(NM#QDUsfVm*hi=&_!^9CRo>dZid{{;#Phi5^-ERKT2F^m!g zFcE?IjFJ@vj$lDq-1N~1G{Y#77!`nti1`Z?B!YD;i<>?g)Gm}XfMzT+3`Eplpa6I{ z3(DfAj{=t#hEXCxO=cj@BYni5rjNm~mWm$q);kIbk3o z;xAAD42y~(7dL$r0uFv6;CKcKh&Z2EFf8jn%N~YY-1Jd!3^-Q^fUzH=0Q`JL$%29c zSjV!s=_Bz-Q2Iy|Y8Dam7bpk}>sS^yeI#?4MBowNj4=@Blm4GZi9xX#C311oM`Ey` z^bv5z0>D5-`~?acVAV1FV&;NG!I@%VY{y9SybcU%GZ9gLfr7xXq97JWfioN!P=&xx2I4$oLH=o!XgG@^qmYZD zAaFS5CyF5#_`D7b3knKgSu0VCn?3@|Sik@*!zd9r?7Y(d69vIY*ZBhlz4%x#Og{^Vr8AC5_`{3rvw0-8bjGNa_VnIP5S)`9% z-1Y%9WHoTm8)G2C{{jU-uy|wW#cdxzAsBOoVQ4aFZSzSV#p3g!S;w-t?E?sgJB9=p z+cEMAToPps=hnwz%yBaE9Cw7z|@9z`X7l3knj=vcI4g zw|zX*8v~COcqSnHFF+7Tmc`AV47p0u&P_ z0(3YcK&KZ1bi5!y2LJ-(p%Wk%ngIE@1jq>`KwcsNa^nb)pGAN?Ap+#85FlTI0B!aJ zXg4N6+a&?o&j`?lLx6S!0<>fkpf!~MEqVlKRU$yk1_82b0%Uju$TA3!>JlK`B0$n7 zKmsB-|C-8$);1*OpLiLTvE?ifFI&hF#4NP5G1dB?a2aNya2bnIpji(z7}TO5P_ztO zI8h5l%UD2=tcO_)dQlK4ScYbNE)Xn3EpW`lU={^o#>ya9aDiAE3kV9yvZ-OPiv~)e zP#KzGrwfG2Pzyw{Ft|lW0!PhmHV6=KUPqG!1cPN+Ix+agKz_yJ;Ea*XACE(^dVnk- zSooqKP&f{B&@c;y<5)nDtTMqa8pQY&jYBhHe)C7;SU><2%O-$b)Z(Eq83Msj;RV8E z=mjhui(GUhvr#feaAAQc84JjqKnWJLC;=f?tq!m`9i zvADmB!vTy#mpjL7*rcc%)n~3Wr`` zfy4oe86y-PV|ZlPg~DT)1+I8-i(XjFM#tcc1K$GCF%}Rcjz#deMfZ3pI0i8H#|468 zEFcKhRT#JE9uLLF04(G1vOsJM!{SJ=ddav&_jn{4HG57%GXdd$0RkXcN3!T1KO2C9 zV;2sg0TrN5P!q4#;jPUYf+1b!f)Vl7gXT|!f%*`>}2tHB@}(b zGbU|;=o@wc5d5sgJ3)ej+*ShQSP~%Dj{rGm1jv0NKn@N8azO}?lR$vBaRRi_5}>V+ z0Bu$TXgeW53qAo_k_phFNr09$0<`cDprwHT87~1cF9Ku$1V}{*kP;CfF%uv`5TL30 z?cd}7SYTkb1Y^ek6ud%0f>dF!ojZ4`kV(`q>P{86K>vSUx`tn9y+DJWAOOxY!&672 z8QusIj{mpbXiGDZ|9GVf^8didq8mH{hh*M@AsJ&5F_60;wUY;8{`ek52#MS{{vIN{@N=VC>)jHev|+&$l^Y zfAflA<#8dsM}fO3z+A9!;I5Bi?nj9K%heVDUsUszB8Q88McMsT~ zEG-z=WuE8I0G@fv##ksB?4kaPCET2MlEMFW&;FB{zsSNuG0x)5t5R@%ME>Wt4T1m3 z4C1#yXT!a-fnEskAHn{SI>j(CD#N{<)73vJx7FL7>I6W6;6DuSkCY`-Z-4I)s*?hs zs6b=9+H(gu<`A;KqBG2#ZU!Wj1qs(XpZU116L52KPX8wZuU1PLD|E@78F~4gd-)QXb8pt^s_qzu2 zj>iA4f!t$$@d38N{NjT-77XHd4Mf8rf7d`X4C;4{(GLB)2BKkpal$D7;sed>5%;^s z=n?74XB0EL>DbWV;OfMSu>LWynw3NtV1 zoNP4!#UibRvcUipZeG$kDO~`HMOq8xWdUgTyrgrIs{k}GFX@~NDFBU_mvl~=6M$xs z)0H}Fqvs`^lQjgOG4qnnN&NxPtkPO&9YEveC7qLm1EBHqlFrGb0Wk1+ zN#~@)02mf&EtJy&U=Z_?&PhxGFvxjH=VX@v7}UI^b5cYA40>MDIf)(shDBNn=y^$zb9u$gOFHNB7QnJdYoXgw0E?TKbj}?ofMt=^LN}EF4n8mGocl%q z2h2-4=hhIwA?78WbN2_}kn@txxxoW)EYe!&9uB~)9zHMWoNF8a&mygbE@J>Zi?px{k|O7wtbdWB=JhoHMT(wR zwf{wmnb#lq7b*6yoqarRUYG1&q;p(TeMl71HWhKX79`pv$ti4*?Tg?>G^FnaIO*9#o&jF^S9JB)i!VV!W6*^J zW@F)uzu&|7$9m^~yFSDJ{MS1u&CEN@o8f%5-;~Ff^M}^?_9q=tKYSybFo2WdllNxh z(0L+wuc5V#1C>Ts|FmhjYRn_io7rFZJVl%p8t&Z0=UFXlaT(v^5%EFCSAFIE_yY=d z-E75cj!1VY@#U8lN*}qeqg-892IB&U7bCx2qJZrM$Q@*(UC6SMS)dC2i&p9+Vf{{ctfHyJ|Wwz4!4IgA(1({g^$@tyk|( zE#tnvwJ+mU(8woTr+ZU&$B~Gg(-OmamxLRH=!S3q_3wfaaK!&4XXO7?&d&b`YmS7F ze<308VE%6jDL+Nnz?bOga=0P+Om2@+xJM}~N4cLaU1HS6Ve}s(Mg31BMgQMN`Y+`L zoBfRzGo}Tm9S{%*GJs*dK|uU*$FzVVGY+$Jr>Vb-%~jYam}{PtmjN5#y0Pl>}hXY$l*-bT%#=LYOKGZF=bQ4NKZ z8Xy0PK?yXC-Qum*tL>x5+cTET1Qb>lnJt@|e34&q>$>jh(;sfF*<#*kmX}hXru}wH zi7!vC{p%Dq%F?DS)05IhlJ}RL+-;4|NLd0tX|#LNXxiJTa^I0%bkC51C2k~HuLvP6 zY7%5J@o)vd^Ih7BP1BFYz9SJF*Ai&hzxZ3xZk;SsF+AO+jHit~RrUgH-ThlxL1rDk8{CiL1;moQ zR@O#okDh*VYq!YttRVQ3#7pazWwLRUZ9&;Y4RE)ytLevuuZ|)ejrP6Lc75!ub&!B= z&!&{fQ|*s@xi?C0Mk?djdQ1``PujR75VpKYC$BU)=2oj+u}mS2`-V4rIO;gR+xgM` z(Ly2)MQ`%b^U^Ah8fN5V%Vw!>;^S>fft`*#Y5x3;&fDDAYua@WT;`MJ5?UUQi!5$h zaqwj@&U-@`;euD)^?lCE+`Xet51Jh1cRPLQz0ipZ)9SJNg#;8<9VEhWD%7PEn(s12 zpzP?7dHGWIDe(|8iGvfPeiDBxz2dIGiI$^Ha&cSM2;eI?9((BM!Ub#1_ug53u9O6|-<~X11eCzh3Ey9G8y32r087j9= zB!BLWe5+?+4!LXJDaC&~<-&0jo@2O78NPp8Mb@=4essa3Kf z+9nA_eWr15udLh2uK7s$+CARo2k$;EwKqBh*p}_*v2!sOlHC^7b3i2cI(Nb$_YDTd z37YqgU#fNV(#npWl0C@L@42cA8||*;bxMhNFst~)trq$*<3rW?s%_i}jtYX|y-!^3 zoB4=|K0OZvn~Wk9Um^_@oU z>@j|X$AUIj?T+$O(~9Jk;VQYIh)Xw~Z`VjqH=_)mv`T{CQap|`Kc-`nutD@-HaJ*% ze1se6OJ1ch7n`_tLP3|r&3in_Tw(!S>_1y0B^;zx`F!1E!d!e!$S#)dl?FC(VAFcr zR~mPjG>^S>-%cWLx-6S!Wvy3v z_qsp><4D+#fH>nVqui!Tx$UJlARKM0mIkvoXPyt@D6cvnB-i-0e0fQlFC5_)e0~{& z#)aRqYH3(nMXaoDP3fkA(&I%K#P@O26}MLOttj1My0e&^o|7gTkgw4P9Dg_w-FvCg zRMo#LQQ785(!TSXm1HX|g(k>t7afp6$ClljD$js4!%D z3;zdmm!A(>hw4X;Zn)2@BWQbO_|uagg){6ca1{?d%zcdST%zi?bT_{ZU}uw~W{0Mz;TtvWU=n6IYuI8p~h1t8j z)Pcy<6lLe_TU(cB=T96QNm6#$HsH(8^`Y**Kbh1t;P~2E`G#sew(FDMMxWvL z-?ZZ1=oS|S4WINx4aWT7f3>G2v_PxDxqd`Hf)DQ7d*NgCT5ltf(dr#R6ZNXC?7^nWwAL91|3e`)q0=)%J9^l~FgPrB z_4lHNtnMhYX@O0GE&ZaOHM-n^O^@zWo7eN%!_Vd$9VvvP`X=^gd6aeNoq3yI_~u)A z?T5;jT%K%1l+nt#xJ7F(gnf)D^l2#TuAjX6qspPRud(Q5B)^lB zR#6eI-gx5SMCRp}Y1KQt^n7@M8j=%|jxue6qiN4el}siR7N_*!@!G!-Xe>BPV_vzDH$E%2czN~0 zfMN9ZRo_k-Ry_BkiGI`bs@YTHBwp%ur7-5J-V&uQhi>nKJz16udq7Bh`ic;c#4i&<>r|9XqVQ+<+~UU&mJ4km8Dt-fBVHN0|T^Vfjpu&Dms76VQ4 z*T^xRurQT%n zaJYp>j!sYP6ME0Vrd8K;py9OCk9W`aou?%8{)eNC`JWtR?Eha!84sW1C}aP^Q3mi> z;NOn2gE94KrBMBp{cD`&!3}GdKC((4yHuER=$!o4R9FZWt$R&4FU|D(t9NTR9Z5Dp z8sGFWF0|YCdHJL1U5~Vm*w7m<7A7<|Jb0U5ATH7-)&D9umr@ziO{Vwxf3MFENaA+1 zYd2S5OG~w`SaUkEqmZWp^rOnouQ-0FMBmEPiAzr0spz1WVN?`-rTOOK#>Pss>17=} zzAIxols@ww72w076?SZpHwZKH=jiCbtmBP7Cy8I0>lFpJ5>457oc~FAfqW()n?mRq+u2Q6`I z4?IDC@bZS_vCT44I>X6Z9v~5~XfxkTa9 zK6k!@B8u1Nv0GEz=&(r)wS~lSbHjBDheJ`c=e13}*(9$pLGB{H938PP746+f=`_KE zK)k1iOxU@@W^OU5NmerA0pFLNUl}8^%XvJ=*4QLrRZD3_*_Gm#t{oySDcYg&9|!d- z6qMOB?4_|LXQbr~0?fInL>xNtM>bG`e8;>Oc& zD5OJ|n#%<~zW@0An-qy+Jp}q(kJeNP>~b2qJwah>zP$754_JJ*e2fsd5^{Rpuj-tc8~c}0~IKMciU zsqGmGIuS>uge;SutZFxK60Ax85TBm_?8saGRa$~@?2xMD;V8>z?mwsYUW@0}MtaqJ z>o&aPPK$Lb4EE)tUffLjTDSO8;WXMtDQ-FeV6{`TgNLJ zDr)7pcd71*JGZ4YPk%AQ=5k(PLl_pg=E=nhl$(Vo6g_9Vdn2LPT=>TeECL&%p1qsr zuzp@`rox9ORa;d_h4)|U?ApG$Pc6KRZR7dtw8Q8bg8PpD$J|?nx7B3{)@G)dnVCUm zJC2!|nVFfH*)he;%*=Mo%osB>bIkMh)bw;sSH5|Y=j*AiU-}{GUg_$bb@yI-pQFN~ zz%#}Rpo6d#!&B<9i?~MivXGZMSn5~Cwa1qMdXLR?`ck$UaIOkJp1WrIt{2nl4)KJgGtl4JGFjvMI8iTpum2GeJIctbRzb?)+P zx&hm~dbhmAT1VYUtx_m0Pk|GdOT!95sXhGsp-;N)USb0ew_n)`D#i-nI8)zkb@j|CYBD)Z_3!gokHm$bUkkMGI zU!*4e=K{E<&2i8QT!(dYcL)edq$}Ub!7XMto{l>YG;wPLD73kb1Vw5E9=%%2bSj$c z-ZJ66@Jrgf6`fg6c9h>(osG*P>9zZF8_fusK~|DKZw0Xwx9o{i)O2lnU$CP_FD`16 z(+@4ztROJ;NhD@@t-n$Sxam4mTVm) zZcg|HI_uZ8cwFZDez{DjF-gx}0*RWvc>~5mb2>CjQM z*@0j6=Fc6AoI6c8^^FsNnasHOP@PYDl-blOcZ&~kO3`cUBWBck= z10mmbyq=(}B<#;>c7b`a3ZR2%%j@@>*o@`}FIv&(adP2VJI-4RBvKTXEcMOGAB>X9 zH`x%BaA4A;VYH3cN*`cJ&SDi>os`;aMuwvtL6d1@djE9F z#<*5L;?Ob{uRSchS*u-+`>&TgR78ESJJ<+2YdukU{1vRa*{fAa?sL7NVp6o%`@!U zC}gI0HW^0)cBc0rJ7h7D$7zn6IOS5=iKL|#zT7M&4Pn39hKiP|tw2^J6uMilG9IL2urOOZ=YfsW$wo^%4AslsVlfe6qfOkmn5<8>I2!fBfya5!uf z^?DV2xI*uG8XQ_QXRFgWIOP&#+V7D(uKYKC!Iqd(6!<)^J^tRdcO{GbAC3$jjI+o` z)p7QDtB!<`H1umV0b7CFAduWFB1XM=llqeO0|O;g&J{N?b^4^8AC)wN=JXkzue zHNzP@zE8~FM|4OohvLXR43-tWLll-Xv(rM5j2GTY@p|Kjz znK}E+#l7!$O56FoB51H+;h3Nw<1%_Qnjn$B-=(vN}9i|3Z>BW zeA*856WBaaiX6{#&)uW@Vzs%w;Cm&H-SrSCpTc+dMu+go&2fUM@71qiElBeB>ik<@ z?ZC*aRM0C3on$#+RpLlVoBn#(lFueZH#aoOPb@&U+;c;Xm2v>6?L}pb@HzhVN}2!p z$`Fawado7DpIyi-32bZ%+K~$ieE_l<(gi>DlYVn+SX2H)!Ejr9bfw8)M~Gc5Gvhnr z2w#lFVR2&Q@&7nlzew2zZ3Z|~E=HzS15=$oB!351DhKa(>?AH3`KFGjE}QB2Q2b9W{uB?#tV5}yYJ zX0SF#?JJd%=E^F=LX?YoCRP?B+ogT44!vhOD>8NNY3mi*$MdprHvW#!Dks0p56u$^ zodR?5GX~!HgAaMF1Wa)iUue>DWZPuZzUuj%#lHC1-b|na6*q%@y>qC@RDx=a?H<^W zPDBec`@1?t8vl;cR!!;XUhTy)_uiN`CZyy9QWHY41z%VIN{g?lvZli>)Ps_foIP%{ zhiz9c_j8@Z1%1-(W0O(dpqnm-%noEe9d4sLfDmxk*xSE^G01b0@ofi%5GESKRqG&g zTAPV!ZG-_kmrT5X_u8xs;ajDU=43$%L$m6}!}C1Ri2**$Tq_)8lL=b#+}U&*3`Rv9 z!30;h%t=iQS~K%v>6{f;Y&%qY?jlWbhSA}-8`Z@!P85eV`Tglnpi!r5b#JXnyAXoB zO1f^MQt(zTJ*fJrHJ@uPX!||l)-}2e(ifkmN1b~-nl4(;G+7@ClK21z36!lD&O}`E zvreMBD4e##lw?rhwgo)5wxA~dd>2YRyD^+UiNB}FK6)nXy5y7!ZX&#;^t|}g8pFx} zpSN^!E0q=WycxQDyuOhlg2?8to`^?S_ev4)H}PQnTvzo;l#8f-1vKv;1aGN&_||N* zBO=;)-ZspPG8_$HB-3xG+?L?bOdQxBJ$Y95bvox=&P3{aWMw%w?zb$0TU8G~U|;nx zoCxey9CAtcFDO~$U@z$Bv!!}Tfgrno0<#y(6AEtgc3+{DEyH*Vcv6%ts1kgGL@E0w zdUirx;*(0sB))5;H79vl_hNOwbi$X8QOxiQME+5wn2F`TFt%bN+fjyTZLtI z#(xZ}qT|;U0vVBlFWn!oBAc(f#SU2PlqwN#=;#SN5oS74f_vEB%FH z&$Z0}(5Kd1c5ve%hkB9HCBfX#X3#axPrdU48W9TdMY$ifKn$C6B+i3qN#G;niYrXY zz}rt!OULbbJnRdG?|J;B2$`+uH%QMDJ58Bs_4Y`Qw=Q8j8%x{ik0g6SU#oRHEZ^j}b`|M!vge;H4|Q-S}tg$cjWs4(kVFUJT_f)ZC`1k}&7 zfJda`s8I(MP+}foVPaASky>(uLV(eL9Tq1gQlJ-72cZ|EqtW~%KS&}!FbgrVKkjWf z7PvD{@e`7cg1d{Fi1KR!7RF78k5Cw6Mv-K`y^Y|nt0L0!*8)ncB-Q@K<^3bW%f$ZQ zK9zsR>2k0#{o|$2RGx|1VMFykq`4p=VWMKBt%+S%Rz2@?DbZ{4PQgf6LvqFCZp2f2 z?>gl2*JmM7E{j7VT{_J0yr_MfG80ksGHFPg>x;kfxHD&eJ{}WIlQmb}@l53%H*eLL ztI9EF%iOX5oHfI1-O(h!3Tiz?Qi%;3w)N2`3!1TJc8)Rk1R5x*yt7Yw#2YE7-P z_lFZf3Shz8j4MkF;*A@5EI(7;A71WwLR-y|o)bn5`{foM_@eLlBkGPmT?sDi-5Uow z?AOv?!?@iRl(-P5Todj-3Jh5rW)`Gc6*rwthf*C1tPz*X{Cr%M^Gd9uiK@^1$%0fr z1JgH(>nu_CuIjFbe_Ddpb6CjZRe6egEa?cr3m_#gTxDQe>$jTmA)N4rz4eB5s9Ds9l_2v^I0iv%N(Cau6778`%ZfPLWE+PC=^^&P% za;sqINJEr9M4H6H*aV$G0#KkgvzEZnIc`8d*G*y`+_JH`rnrYnxxds8wHDl!bNC5G>qTNU8!J6J9=TN126W-n;sdAe&zYhT4i)6WAU_57 zUQ$xo3w*Q2%_6>IWitHKU8GPwO<>RFn?4Iz1ka+~m@>Lu)(20)vr;Ig8Qp7u*mm8GVkH=JW}A?qY+*876AjZ4gdAJHkw6vncq z%sA_Q*>to(qM)d?E&y$CaDENOVzabtM|BSaIQlBiCncJjdagkS$4UOUGEZY4yXT(4 zneAki+O#a@TUPM-q@9SaiPIR4KaE_v5V3;v1uY>}&xnZpP%L#H>KXI^w#Z=^w5@`& zO=9O++FIG#^=I9*$=o0yuS%LhLy8Bib@p7yz?27b_`+qXy@-J@n54%m!~Dci&iJD1 zMWx*=;ZQjsr3k^zvac?igHw$^m}^!7SR57ipKuqwZYM z%jJU_aW@_}9t&(KM6bwr88y(?f_v4H^AoW7<%w3h#C4rn=*^LkNRl~>`ARi=X(gp^&i!43!a}roW!H}0$EP>MqzR3ghVFg_whAnda z(d016_tkuXUR~~m^c&_dX`*7>P}^YgX5rEBJVz*L>ahkf!5k0O@5TfBWF`+keXH)i z5*BM--`VFlPbX_;}Vcx-4o1+^`%vx zFdqfx1pBRCao*`(WLZ8o?pyT5fqf!l4KDD_G$MR@n||pv^0IPoFD;(RBgnZHhL