From c5571a1d68de6e20e127c9745aa7a4dbf4e4474d Mon Sep 17 00:00:00 2001 From: msweet Date: Thu, 4 Sep 2008 17:09:47 +0000 Subject: [PATCH] Import CUPS 1.4svn-r7908. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@943 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES-1.3.txt | 4 + CHANGES.txt | 12 +- Makedefs.in | 4 +- Makefile | 13 +- backend/Makefile | 26 +- backend/{mdns.c => dnssd.c} | 16 +- backend/ipp.c | 25 +- backend/runloop.c | 10 +- backend/snmp-supplies.c | 44 +-- backend/usb-darwin.c | 4 +- cgi-bin/admin.c | 12 + conf/cupsd.conf.in | 5 + config-scripts/cups-common.m4 | 16 +- config-scripts/cups-dnssd.m4 | 6 +- cups/ppd.c | 3 +- cups/testppd.c | 26 +- doc/help/spec-ppd.html | 18 ++ filter/pstops.c | 6 +- man/lp.man | 14 +- man/lpoptions.man.in | 10 +- man/lpr.man | 22 +- notifier/Makefile | 30 +- notifier/dbus.c | 550 ++++++++++++++++++++++++++++++++++ packaging/cups.list.in | 5 +- scheduler/conf.c | 51 +++- scheduler/conf.h | 2 + scheduler/cups-lpd.c | 25 +- scheduler/dirsvc.c | 58 ++++ scheduler/ipp.c | 125 ++------ scheduler/job.c | 12 +- templates/add-printer.tmpl | 5 + templates/choose-make.tmpl | 5 + templates/choose-model.tmpl | 6 +- templates/modify-printer.tmpl | 5 + 34 files changed, 960 insertions(+), 215 deletions(-) rename backend/{mdns.c => dnssd.c} (98%) create mode 100644 notifier/dbus.c diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index 94039b61d..c03e5fba2 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -4,6 +4,10 @@ CHANGES-1.3.txt CHANGES IN CUPS V1.3.9 - Documentation updates (STR #2904) + - The PPD parser was too strict about missing keyword + values in "relaxed" mode. + - The PostScript filter incorrectly mirrored landscape + documents. - The scheduler did not correctly update the auth-info-required value(s) if the AuthType was Default. - The scheduler required Kerberos authentication for diff --git a/CHANGES.txt b/CHANGES.txt index 040b1a965..789220f8f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,18 @@ -CHANGES.txt - 2008-08-28 +CHANGES.txt - 2008-09-03 ------------------------ CHANGES IN CUPS V1.4b1 + - The scheduler now supports a DefaultPaperSize directive + (STR #2848) + - The scheduler now passes the job-originating-host-name + value to filters in the options argument (STR #2558) + - CUPS now supports job tickets in PDF files (STR #2903) + - Added a DBUS notifier (STR #2529) + - The LPD mini-daemon now passes the document name when queuing + print jobs (STR #2482) + - The IPP backend did not relay com.apple.print.recoverable-message + values. - The scheduler now supports a job-media-progress attribute to track the progress of individual pages. - The sample HP driver now supports A5 (STR #2798) diff --git a/Makedefs.in b/Makedefs.in index f213a3f38..3ee4e2512 100644 --- a/Makedefs.in +++ b/Makedefs.in @@ -127,6 +127,9 @@ COMMONLIBS = @LIBS@ CUPSDLIBS = @CUPSDLIBS@ CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ CXXLIBS = @CXXLIBS@ +DBUS_NOTIFIER = @DBUS_NOTIFIER@ +DBUS_NOTIFIERLIBS = @DBUS_NOTIFIERLIBS@ +DNSSD_BACKEND = @DNSSD_BACKEND@ DSOFLAGS = -L../cups @DSOFLAGS@ DSOLIBS = @DSOLIBS@ $(COMMONLIBS) DNSSDLIBS = @DNSSDLIBS@ @@ -142,7 +145,6 @@ LIBCUPSIMAGEORDER = @LIBCUPSIMAGEORDER@ LINKCUPS = @LINKCUPS@ $(SSLLIBS) LINKCUPSIMAGE = @LINKCUPSIMAGE@ LIBS = $(LINKCUPS) $(COMMONLIBS) -MDNS = @MDNS@ OPTIM = @OPTIM@ OPTIONS = PAMLIBS = @PAMLIBS@ diff --git a/Makefile b/Makefile index 7be3bac59..8cdcb4d28 100644 --- a/Makefile +++ b/Makefile @@ -110,6 +110,8 @@ distclean: clean $(RM) man/cupsd.conf.man man/lpoptions.man $(RM) packaging/cups.list $(RM) templates/header.tmpl + $(RM) desktop/cups.desktop + $(RM) init/cups.xml -$(RM) doc/*/index.html -$(RM) templates/*/header.tmpl -$(RM) -r autom4te*.cache @@ -132,14 +134,9 @@ depend: .PHONY: clang clang: - if test ! -d clang; then \ - mkdir clang; \ - else \ - rm -rf clang/*; \ - fi - $(MAKE) $(MFLAGS) CC="scan-build -o ../clang $(CC)" \ - CXX="scan-build -o ../clang $(CXX)" clean all - test `ls -1 clang | wc -l` = 0 + $(RM) -r clang + scan-build -k -o `pwd`/clang $(MAKE) $(MFLAGS) \ + CC=ccc-analyzer CXX=ccc-analyzer clean all # diff --git a/backend/Makefile b/backend/Makefile index 9c8a96c73..79868f83b 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -17,12 +17,12 @@ include ../Makedefs -RBACKENDS = ipp lpd $(MDNS) +RBACKENDS = ipp lpd $(DNSSD_BACKEND) UBACKENDS = $(PAP) $(LEGACY_BACKENDS) serial snmp socket usb TARGETS = test1284 testbackend testsupplies \ libbackend.a $(RBACKENDS) $(UBACKENDS) LIBOBJS = ieee1284.o network.o runloop.o snmp-supplies.o -OBJS = ipp.o lpd.o mdns.o pap.o parallel.o scsi.o serial.o snmp.o \ +OBJS = ipp.o lpd.o dnssd.o pap.o parallel.o scsi.o serial.o snmp.o \ socket.o test1284.o testbackend.o testsupplies.o usb.o @@ -52,7 +52,7 @@ unittests: # clean: - $(RM) $(OBJS) $(TARGETS) $(LIBOBJS) http + $(RM) $(OBJS) $(TARGETS) $(LIBOBJS) http mdns # @@ -167,6 +167,17 @@ libbackend.a: $(LIBOBJS) $(RANLIB) $@ +# +# dnssd +# + +dnssd: dnssd.o ../cups/$(LIBCUPS) libbackend.a + echo Linking $@... + $(CC) $(LDFLAGS) -o dnssd dnssd.o libbackend.a $(LIBS) + $(RM) mdns + $(LN) dnssd mdns + + # # ipp # @@ -187,15 +198,6 @@ lpd: lpd.o ../cups/$(LIBCUPS) libbackend.a $(CC) $(LDFLAGS) -o lpd lpd.o libbackend.a $(LIBS) -# -# mdns -# - -mdns: mdns.o ../cups/$(LIBCUPS) libbackend.a - echo Linking $@... - $(CC) $(LDFLAGS) -o mdns mdns.o libbackend.a $(LIBS) - - # # pap # diff --git a/backend/mdns.c b/backend/dnssd.c similarity index 98% rename from backend/mdns.c rename to backend/dnssd.c index 419b12dc3..674bacf80 100644 --- a/backend/mdns.c +++ b/backend/dnssd.c @@ -105,6 +105,7 @@ int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { + const char *name; /* Backend name */ DNSServiceRef main_ref, /* Main service reference */ fax_ipp_ref, /* IPP fax service reference */ ipp_ref, /* IPP service reference */ @@ -133,10 +134,23 @@ main(int argc, /* I - Number of command-line args */ exec_backend(argv); else if (argc != 1) { - fputs("Usage: mdns job user title copies options [filename(s)]\n", stderr); + fprintf(stderr, "Usage: %s job user title copies options [filename(s)]\n", + argv[0]); return (1); } + /* + * Only do discovery when run as "dnssd"... + */ + + if ((name = strrchr(argv[0], '/')) != NULL) + name ++; + else + name = argv[0]; + + if (strcmp(name, "dnssd")) + return (0); + /* * Create an array to track devices... */ diff --git a/backend/ipp.c b/backend/ipp.c index 5113ac727..636e738fd 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -138,6 +138,7 @@ main(int argc, /* I - Number of command-line args */ int version; /* IPP version */ static const char * const pattrs[] = { /* Printer attributes we want */ + "com.apple.print.recoverable-message", "copies-supported", "document-format-supported", "marker-colors", @@ -1366,6 +1367,7 @@ check_printer_state( *response; /* IPP response */ static const char * const attrs[] = /* Attributes we want */ { + "com.apple.print.recoverable-message", "marker-colors", "marker-levels", "marker-message", @@ -1601,7 +1603,8 @@ report_printer_state(ipp_t *ipp, /* I - IPP response */ { int i; /* Looping var */ int count; /* Count of reasons shown... */ - ipp_attribute_t *psm, /* printer-state-message */ + ipp_attribute_t *caprm, /* com.apple.print.recoverable-message */ + *psm, /* printer-state-message */ *reasons, /* printer-state-reasons */ *marker; /* marker-* attributes */ const char *reason; /* Current reason */ @@ -1610,6 +1613,7 @@ report_printer_state(ipp_t *ipp, /* I - IPP response */ const char *prefix; /* Prefix for STATE: line */ char state[1024]; /* State string */ cups_lang_t *language; /* Current localization */ + int saw_caprw; /* Saw com.apple.print.recoverable-warning state */ if ((psm = ippFindAttribute(ipp, "printer-state-message", @@ -1620,9 +1624,10 @@ report_printer_state(ipp_t *ipp, /* I - IPP response */ IPP_TAG_KEYWORD)) == NULL) return (0); - state[0] = '\0'; - prefix = "STATE: "; - language = cupsLangDefault(); + saw_caprw = 0; + state[0] = '\0'; + prefix = "STATE: "; + language = cupsLangDefault(); for (i = 0, count = 0; i < reasons->num_values; i ++) { @@ -1688,6 +1693,8 @@ report_printer_state(ipp_t *ipp, /* I - IPP response */ message = _("Developer almost empty."); else if (!strncmp(reason, "developer-empty", 15)) message = _("Developer empty!"); + else if (!strcmp(reason, "com.apple.print.recoverable-warning")) + saw_caprw = 1; else if (strstr(reason, "error") != NULL) { message = unknown; @@ -1710,6 +1717,16 @@ report_printer_state(ipp_t *ipp, /* I - IPP response */ fprintf(stderr, "%s\n", state); + /* + * Relay com.apple.print.recoverable-message... + */ + + if ((caprm = ippFindAttribute(ipp, "com.apple.print.recoverable-message", + IPP_TAG_TEXT)) != NULL) + fprintf(stderr, "WARNING: %s: %s\n", + saw_caprw ? "recoverable" : "recovered", + caprm->values[0].string.text); + /* * Relay the current marker-* attribute values... */ diff --git a/backend/runloop.c b/backend/runloop.c index 03aa956fe..14dfc494c 100644 --- a/backend/runloop.c +++ b/backend/runloop.c @@ -239,7 +239,7 @@ backendRunLoop( if (errno == ENXIO && offline != 1) { - fputs("STATE: +offline-error\n", stderr); + fputs("STATE: +offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is currently offline.\n")); offline = 1; } @@ -338,7 +338,7 @@ backendRunLoop( { if (paperout != 1) { - fputs("STATE: +media-empty-error\n", stderr); + fputs("STATE: +media-empty-warning\n", stderr); _cupsLangPuts(stderr, _("ERROR: Out of paper!\n")); paperout = 1; } @@ -347,7 +347,7 @@ backendRunLoop( { if (offline != 1) { - fputs("STATE: +offline-error\n", stderr); + fputs("STATE: +offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is currently off-line.\n")); offline = 1; } @@ -363,13 +363,13 @@ backendRunLoop( { if (paperout) { - fputs("STATE: -media-empty-error\n", stderr); + fputs("STATE: -media-empty-warning\n", stderr); paperout = 0; } if (offline) { - fputs("STATE: -offline-error\n", stderr); + fputs("STATE: -offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is now online.\n")); offline = 0; } diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c index 1267d2502..dea84fcf1 100644 --- a/backend/snmp-supplies.c +++ b/backend/snmp-supplies.c @@ -194,24 +194,24 @@ backendSNMPSupplies( (packet.object_value.string[1] & 255); if (i & CUPS_TC_lowPaper) - fputs("STATE: +media-low-warning\n", stderr); + fputs("STATE: +media-low-report\n", stderr); else - fputs("STATE: -media-low-warning\n", stderr); + fputs("STATE: -media-low-report\n", stderr); if (i & (CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty)) - fputs("STATE: +media-empty-error\n", stderr); + fputs("STATE: +media-empty-warning\n", stderr); else - fputs("STATE: -media-empty-error\n", stderr); + fputs("STATE: -media-empty-warning\n", stderr); if (i & CUPS_TC_lowToner) - fputs("STATE: +toner-low-warning\n", stderr); + fputs("STATE: +toner-low-report\n", stderr); else - fputs("STATE: -toner-low-warning\n", stderr); + fputs("STATE: -toner-low-report\n", stderr); if (i & CUPS_TC_noToner) - fputs("STATE: +toner-empty-error\n", stderr); + fputs("STATE: +toner-empty-warning\n", stderr); else - fputs("STATE: -toner-empty-error\n", stderr); + fputs("STATE: -toner-empty-warning\n", stderr); if (i & CUPS_TC_doorOpen) fputs("STATE: +door-open-report\n", stderr); @@ -219,9 +219,9 @@ backendSNMPSupplies( fputs("STATE: -door-open-report\n", stderr); if (i & CUPS_TC_jammed) - fputs("STATE: +media-jam-error\n", stderr); + fputs("STATE: +media-jam-warning\n", stderr); else - fputs("STATE: -media-jam-error\n", stderr); + fputs("STATE: -media-jam-warning\n", stderr); if (i & CUPS_TC_offline) fputs("STATE: +offline-report\n", stderr); @@ -229,34 +229,34 @@ backendSNMPSupplies( fputs("STATE: -offline-report\n", stderr); if (i & (CUPS_TC_serviceRequested | CUPS_TC_overduePreventMaint)) - fputs("STATE: +service-needed-error\n", stderr); + fputs("STATE: +service-needed-warning\n", stderr); else - fputs("STATE: -service-needed-error\n", stderr); + fputs("STATE: -service-needed-warning\n", stderr); if (i & CUPS_TC_inputTrayMissing) - fputs("STATE: +input-tray-missing-error\n", stderr); + fputs("STATE: +input-tray-missing-warning\n", stderr); else - fputs("STATE: -input-tray-missing-error\n", stderr); + fputs("STATE: -input-tray-missing-warning\n", stderr); if (i & CUPS_TC_outputTrayMissing) - fputs("STATE: +output-tray-missing-error\n", stderr); + fputs("STATE: +output-tray-missing-warning\n", stderr); else - fputs("STATE: -output-tray-missing-error\n", stderr); + fputs("STATE: -output-tray-missing-warning\n", stderr); if (i & CUPS_TC_markerSupplyMissing) - fputs("STATE: +marker-supply-missing-error\n", stderr); + fputs("STATE: +marker-supply-missing-warning\n", stderr); else - fputs("STATE: -marker-supply-missing-error\n", stderr); + fputs("STATE: -marker-supply-missing-warning\n", stderr); if (i & CUPS_TC_outputNearFull) - fputs("STATE: +output-area-almost-full-warning\n", stderr); + fputs("STATE: +output-area-almost-full-report\n", stderr); else - fputs("STATE: -output-area-almost-full-warning\n", stderr); + fputs("STATE: -output-area-almost-full-report\n", stderr); if (i & CUPS_TC_outputFull) - fputs("STATE: +output-area-full-error\n", stderr); + fputs("STATE: +output-area-full-warning\n", stderr); else - fputs("STATE: -output-area-full-error\n", stderr); + fputs("STATE: -output-area-full-warning\n", stderr); /* * Get the current printer state... diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index 655273d6c..a780d68be 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -1139,7 +1139,7 @@ static Boolean find_device_cb(void *refcon, if (!keepLooking && g.status_timer != NULL) { - fputs("STATE: -offline-error\n", stderr); + fputs("STATE: -offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is now online.\n")); CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), g.status_timer, kCFRunLoopDefaultMode); CFRelease(g.status_timer); @@ -1157,7 +1157,7 @@ static Boolean find_device_cb(void *refcon, static void status_timer_cb(CFRunLoopTimerRef timer, void *info) { - fputs("STATE: +offline-error\n", stderr); + fputs("STATE: +offline-report\n", stderr); _cupsLangPuts(stderr, _("INFO: Printer is offline.\n")); if (getenv("CLASS") != NULL) diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index bddc2d038..c7175f3df 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -965,6 +965,13 @@ do_am_printer(http_t *http, /* I - HTTP connection */ * Get the name, location, and description for a new printer... */ +#ifdef __APPLE__ + if (!strncmp(var, "usb:", 4)) + cgiSetVariable("printer_is_shared", "1"); + else +#endif /* __APPLE__ */ + cgiSetVariable("printer_is_shared", "0"); + cgiCopyTemplateLang("add-printer.tmpl"); } @@ -1175,6 +1182,7 @@ do_am_printer(http_t *http, /* I - HTTP connection */ * ppd-name * device-uri * printer-is-accepting-jobs + * printer-is-shared * printer-state */ @@ -1225,6 +1233,10 @@ do_am_printer(http_t *http, /* I - HTTP connection */ ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1); + var = cgiGetVariable("printer_is_shared"); + ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-shared", + var && (!strcmp(var, "1") || !strcmp(var, "on"))); + ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE); diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in index 649b552ee..9eff1e0e7 100644 --- a/conf/cupsd.conf.in +++ b/conf/cupsd.conf.in @@ -81,6 +81,11 @@ DefaultAuthType Basic # Set the authenticated printer/job policies... # Job-related operations must be done by the owner or an administrator... + + AuthType Default + Order deny,allow + + AuthType Default Require user @OWNER @SYSTEM diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index a9eae2709..3baf2dad9 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -247,6 +247,9 @@ AC_ARG_ENABLE(dbus, [ --enable-dbus enable DBUS support, default=auto AC_ARG_WITH(dbusdir, [ --with-dbusdir set DBUS configuration directory ], DBUSDIR="$withval") +DBUS_NOTIFIER="" +DBUS_NOTIFIERLIBS="" + if test "x$enable_dbus" != xno; then AC_PATH_PROG(PKGCONFIG, pkg-config) if test "x$PKGCONFIG" != x; then @@ -257,9 +260,14 @@ if test "x$enable_dbus" != xno; then CFLAGS="$CFLAGS `$PKGCONFIG --cflags dbus-1` -DDBUS_API_SUBJECT_TO_CHANGE" CUPSDLIBS="$CUPSDLIBS `$PKGCONFIG --libs dbus-1`" AC_CHECK_LIB(dbus-1, - dbus_message_iter_init_append, - AC_DEFINE(HAVE_DBUS_MESSAGE_ITER_INIT_APPEND),, - `$PKGCONFIG --libs dbus-1`) + dbus_message_iter_init_append, + AC_DEFINE(HAVE_DBUS_MESSAGE_ITER_INIT_APPEND),, + `$PKGCONFIG --libs dbus-1`) + if $PKGCONFIG --exists glib-2.0 && $PKGCONFIG --exists dbus-glib-1; then + DBUS_NOTIFIER="dbus" + DBUS_NOTIFIERLIBS="`$PKGCONFIG --libs glib-2.0` `$PKGCONFIG --libs dbus-glib-1` `$PKGCONFIG --libs dbus-1`" + CFLAGS="$CFLAGS `$PKGCONFIG --cflags glib-2.0`" + fi else AC_MSG_RESULT(no) fi @@ -267,6 +275,8 @@ if test "x$enable_dbus" != xno; then fi AC_SUBST(DBUSDIR) +AC_SUBST(DBUS_NOTIFIER) +AC_SUBST(DBUS_NOTIFIERLIBS) dnl Extra platform-specific libraries... CUPS_DEFAULT_PRINTADMIN_AUTH="@SYSTEM" diff --git a/config-scripts/cups-dnssd.m4 b/config-scripts/cups-dnssd.m4 index 79997d71f..46b7f39a6 100644 --- a/config-scripts/cups-dnssd.m4 +++ b/config-scripts/cups-dnssd.m4 @@ -25,7 +25,7 @@ AC_ARG_WITH(dnssd-includes, [ --with-dnssd-includes set directory for DNS Ser CPPFLAGS="-I$withval $CPPFLAGS",) DNSSDLIBS="" -MDNS="" +DNSSD_BACKEND="" if test x$enable_dnssd != xno; then AC_CHECK_HEADER(dns_sd.h, [ @@ -36,7 +36,7 @@ if test x$enable_dnssd != xno; then AC_DEFINE(HAVE_DNSSD) AC_DEFINE(HAVE_COREFOUNDATION) AC_DEFINE(HAVE_SYSTEMCONFIGURATION) - MDNS="mdns" + DNSSD_BACKEND="dnssd" ;; *) # All others... @@ -49,7 +49,7 @@ if test x$enable_dnssd != xno; then fi AC_SUBST(DNSSDLIBS) -AC_SUBST(MDNS) +AC_SUBST(DNSSD_BACKEND) dnl dnl End of "$Id: cups-dnssd.m4 7585 2008-05-16 23:13:47Z mike $". diff --git a/cups/ppd.c b/cups/ppd.c index 110f230ef..2488ff311 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -642,7 +642,8 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ "string=%d chars...", mask, keyword, name, text, string ? (int)strlen(string) : 0)); - if (strncmp(keyword, "Default", 7) && !string) + if (strncmp(keyword, "Default", 7) && !string && + cg->ppd_conform != PPD_CONFORM_RELAXED) { /* * Need a string value! diff --git a/cups/testppd.c b/cups/testppd.c index 5318c4d24..d9cbb9e2b 100644 --- a/cups/testppd.c +++ b/cups/testppd.c @@ -341,6 +341,9 @@ main(int argc, /* I - Number of command-line arguments */ } putenv("LANG=fr"); + putenv("LC_ALL=fr"); + putenv("LC_CTYPE=fr"); + putenv("LC_MESSAGES=fr"); fputs("ppdLocalizeIPPReason(fr text): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && @@ -353,6 +356,9 @@ main(int argc, /* I - Number of command-line arguments */ } putenv("LANG=zh_TW"); + putenv("LC_ALL=zh_TW"); + putenv("LC_CTYPE=zh_TW"); + putenv("LC_MESSAGES=zh_TW"); fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && @@ -369,6 +375,9 @@ main(int argc, /* I - Number of command-line arguments */ */ putenv("LANG=en"); + putenv("LC_ALL=en"); + putenv("LC_CTYPE=en"); + putenv("LC_MESSAGES=en"); fputs("ppdLocalizeMarkerName(bogus): ", stdout); @@ -393,6 +402,9 @@ main(int argc, /* I - Number of command-line arguments */ } putenv("LANG=fr"); + putenv("LC_ALL=fr"); + putenv("LC_CTYPE=fr"); + putenv("LC_MESSAGES=fr"); fputs("ppdLocalizeMarkerName(fr cyan): ", stdout); if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && @@ -406,6 +418,9 @@ main(int argc, /* I - Number of command-line arguments */ } putenv("LANG=zh_TW"); + putenv("LC_ALL=zh_TW"); + putenv("LC_CTYPE=zh_TW"); + putenv("LC_MESSAGES=zh_TW"); fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout); if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && @@ -663,13 +678,22 @@ main(int argc, /* I - Number of command-line arguments */ ppd_coption_t *coption; /* Custom option */ ppd_cparam_t *cparam; /* Custom parameter */ ppd_const_t *c; /* UIConstraints */ - char lang[255]; /* LANG environment variable */ + char lang[255], /* LANG environment variable */ + lc_all[255], /* LC_ALL environment variable */ + lc_ctype[255], /* LC_CTYPE environment variable */ + lc_messages[255];/* LC_MESSAGES environment variable */ if (argc > 2) { snprintf(lang, sizeof(lang), "LANG=%s", argv[2]); putenv(lang); + snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]); + putenv(lc_all); + snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]); + putenv(lc_ctype); + snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]); + putenv(lc_messages); } ppdLocalize(ppd); diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html index 33254bd14..cd80907e4 100644 --- a/doc/help/spec-ppd.html +++ b/doc/help/spec-ppd.html @@ -1668,6 +1668,20 @@ looking up IPP reason codes for this printer driver. The *APHelpBook: "file:///Library/Printers/vendor/Help.bundle" +

Mac OS X 10.6APICADriver

+ +

*APICADriver: boolean

+ +

This attribute specifies whether the device has a matching Image Capture +Architecture (ICA) driver for scanning. The default is False.

+ +

Examples:

+ +
+*APICADriver: True
+*APScanAppBundleID: "com.apple.ImageCaptureApp"
+
+

Mac OS X 10.3APPrinterIconPath

*APPrinterIconPath: "/Library/Printers/vendor/filename"

@@ -1791,6 +1805,7 @@ the device.

Examples:

+*APICADriver: True
 *APScanAppBundleID: "com.apple.ImageCaptureApp"
 
@@ -1801,6 +1816,9 @@ the device.

    +
  • Added APICADriver + attribute.
  • +
  • Added cupsCommands attribute.
  • diff --git a/filter/pstops.c b/filter/pstops.c index c6c1129a4..653378672 100644 --- a/filter/pstops.c +++ b/filter/pstops.c @@ -2844,9 +2844,6 @@ start_nup(pstops_doc_t *doc, /* I - Document information */ if (doc->number_up > 1) doc_puts(doc, "userdict/ESPsave save put\n"); - if (doc->mirror) - doc_printf(doc, "%.1f 0.0 translate -1 1 scale\n", PageWidth); - pos = (number - 1) % doc->number_up; pagew = PageRight - PageLeft; pagel = PageTop - PageBottom; @@ -2895,6 +2892,9 @@ start_nup(pstops_doc_t *doc, /* I - Document information */ else if (doc->number_up > 1 || doc->fitplot) doc_printf(doc, "%.1f %.1f translate\n", PageLeft, PageBottom); + if (doc->mirror) + doc_printf(doc, "%.1f 0.0 translate -1 1 scale\n", PageWidth); + switch (doc->number_up) { default : diff --git a/man/lp.man b/man/lp.man index f2e4ef9af..0a879b0ca 100644 --- a/man/lp.man +++ b/man/lp.man @@ -3,7 +3,7 @@ .\" .\" lp man page for the Common UNIX Printing System (CUPS). .\" -.\" Copyright 2007 by Apple Inc. +.\" Copyright 2007-2008 by Apple Inc. .\" Copyright 1997-2006 by Easy Software Products. .\" .\" These coded instructions, statements, and computer programs are the @@ -12,7 +12,7 @@ .\" which should have been included with this file. If this file is .\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH lp 1 "Common UNIX Printing System" "23 March 2006" "Apple Inc." +.TH lp 1 "Common UNIX Printing System" "29 August 2008" "Apple Inc." .SH NAME lp - print files .SH SYNOPSIS @@ -62,6 +62,11 @@ lp - print files .SH DESCRIPTION \fIlp\fR submits files for printing or alters a pending job. Use a filename of "-" to force printing from the standard input. +.SH THE DEFAULT DESTINATION +CUPS provides many ways to set the default destination. The "LPDEST" and +"PRINTER" environment variables are consulted first. If neither are set, +the current default set using the \fIlpoptions(1)\fR command is used, +followed by the default set using the \fIlpadmin(8)\fR command. .SH OPTIONS The following options are recognized by \fIlp\fR: .TP 5 @@ -233,11 +238,12 @@ Solaris lp command, matching the IPP job priority values (1-100, 100 is highest priority) instead of the Solaris values (0-39, 0 is highest priority). .SH SEE ALSO -\fIcancel(1)\fR, \fIlpmove(8)\fR, \fIlpoptions(1)\fR, \fIlpstat(1)\fR, +\fIcancel(1)\fR, \fIlpadmin(8)\fR, \fIlpmove(8)\fR, \fIlpoptions(1)\fR, +\fIlpstat(1)\fR, .br http://localhost:631/help .SH COPYRIGHT -Copyright 2007 by Apple Inc. +Copyright 2007-2008 by Apple Inc. .\" .\" End of "$Id: lp.man 7600 2008-05-20 21:06:23Z mike $". .\" diff --git a/man/lpoptions.man.in b/man/lpoptions.man.in index c446142b8..dd51590fb 100644 --- a/man/lpoptions.man.in +++ b/man/lpoptions.man.in @@ -3,7 +3,7 @@ .\" .\" lpoptions man page for the Common UNIX Printing System (CUPS). .\" -.\" Copyright 2007 by Apple Inc. +.\" Copyright 2007-2008 by Apple Inc. .\" Copyright 1997-2006 by Easy Software Products. .\" .\" These coded instructions, statements, and computer programs are the @@ -12,7 +12,7 @@ .\" which should have been included with this file. If this file is .\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH lpoptions 1 "Common UNIX Printing System" "20 March 2006" "Apple Inc." +.TH lpoptions 1 "Common UNIX Printing System" "29 August 2008" "Apple Inc." .SH NAME lpoptions \- display or set printer options and defaults .SH SYNOPSIS @@ -74,7 +74,7 @@ Uses an alternate username. .TP 5 -d destination[/instance] .br -Sets the default printer to \fIdestination\fR. If \fIinstance\fR +Sets the user default printer to \fIdestination\fR. If \fIinstance\fR is supplied then that particular instance is used. This option overrides the system default printer for the current user. .TP 5 @@ -125,11 +125,11 @@ users. @CUPS_SERVERROOT@/lpoptions - system-wide defaults and instances created by the root user. .SH SEE ALSO -\fIcancel(1)\fR, \fIlp(1)\fR, \fIlpr(1)\fR, +\fIcancel(1)\fR, \fIlp(1)\fR, \fIlpadmin(8)\fR, \fIlpr(1)\fR, .br http://localhost:631/help .SH COPYRIGHT -Copyright 2007 by Apple Inc. +Copyright 2007-2008 by Apple Inc. .\" .\" End of "$Id: lpoptions.man.in 7600 2008-05-20 21:06:23Z mike $". .\" diff --git a/man/lpr.man b/man/lpr.man index d678e61f2..82d787969 100644 --- a/man/lpr.man +++ b/man/lpr.man @@ -3,7 +3,7 @@ .\" .\" lpr man page for the Common UNIX Printing System (CUPS). .\" -.\" Copyright 2007 by Apple Inc. +.\" Copyright 2007-2008 by Apple Inc. .\" Copyright 1997-2006 by Easy Software Products. .\" .\" These coded instructions, statements, and computer programs are the @@ -12,7 +12,7 @@ .\" which should have been included with this file. If this file is .\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH lpr 1 "Common UNIX Printing System" "12 February 2006" "Apple Inc." +.TH lpr 1 "Common UNIX Printing System" "29 August 2008" "Apple Inc." .SH NAME lpr \- print files .SH SYNOPSIS @@ -34,10 +34,14 @@ lpr \- print files ] .SH DESCRIPTION \fIlpr\fR submits files for printing. Files named on the command -line are sent to the named printer (or the system default -destination if no destination is specified). If no files are -listed on the command-line, \fIlpr\fR reads the print file from -the standard input. +line are sent to the named printer (or the default destination if no +destination is specified). If no files are listed on the command-line, +\fIlpr\fR reads the print file from the standard input. +.SH THE DEFAULT DESTINATION +CUPS provides many ways to set the default destination. The "LPDEST" and +"PRINTER" environment variables are consulted first. If neither are set, +the current default set using the \fIlpoptions(1)\fR command is used, +followed by the default set using the \fIlpadmin(8)\fR command. .SH OPTIONS The following options are recognized by \fIlpr\fR: .TP 5 @@ -107,12 +111,12 @@ printing them. The "c", "d", "f", "g", "i", "n", "t", "v", and "w" options are not supported by CUPS and produce a warning message if used. .SH SEE ALSO -\fIcancel(1)\fR, \fIlp(1)\fR, \fIlpq(1)\fR, \fIlprm(1)\fR, -\fIlpstat(1)\fR, +\fIcancel(1)\fR, \fIlp(1)\fR, \fIlpadmin(8)\fR, \fIlpoptions(1)\fR, +\fIlpq(1)\fR, \fIlprm(1)\fR, \fIlpstat(1)\fR, .br http://localhost:631/help .SH COPYRIGHT -Copyright 2007 by Apple Inc. +Copyright 2007-2008 by Apple Inc. .\" .\" End of "$Id: lpr.man 7600 2008-05-20 21:06:23Z mike $". .\" diff --git a/notifier/Makefile b/notifier/Makefile index 42c86ea86..2c80380a6 100644 --- a/notifier/Makefile +++ b/notifier/Makefile @@ -16,8 +16,9 @@ include ../Makedefs -TARGETS = mailto rss testnotify -OBJS = mailto.o rss.o testnotify.o +NOTIFIERS = $(DBUS_NOTIFIER) mailto rss +TARGETS = $(NOTIFIERS) testnotify +OBJS = dbus.o mailto.o rss.o testnotify.o # @@ -46,7 +47,7 @@ unittests: # clean: - $(RM) $(OBJS) $(TARGETS) + $(RM) $(OBJS) $(TARGETS) dbus.h # @@ -65,7 +66,7 @@ install-data: -chgrp $(CUPS_GROUP) $(CACHEDIR)/rss if test "x$(SYMROOT)" != "x"; then \ $(INSTALL_DIR) $(SYMROOT); \ - cp mailto rss $(SYMROOT); \ + cp $(NOTIFIERS) $(SYMROOT); \ fi @@ -74,9 +75,11 @@ install-data: # install-exec: + echo Installing notifiers in $(SERVERBIN)/notifier... $(INSTALL_DIR) -m 755 $(SERVERBIN)/notifier - $(INSTALL_BIN) mailto $(SERVERBIN)/notifier - $(INSTALL_BIN) rss $(SERVERBIN)/notifier + for file in $(NOTIFIERS); do \ + $(INSTALL_BIN) $$file $(SERVERBIN)/notifier; \ + done # @@ -98,7 +101,7 @@ install-libs: # uninstall: - for file in $(TARGETS); do \ + for file in $(NOTIFIERS); do \ $(RM) $(SERVERBIN)/notifier/$$file; \ done -$(RMDIR) $(SERVERBIN)/notifier @@ -114,6 +117,19 @@ depend: makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1 +# +# dbus +# + +dbus: dbus.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o dbus dbus.o $(DBUS_NOTIFIERLIBS) $(LIBS) + +dbus.o: dbus.h +dbus.h: dbus-notifier.xml + dbus-binding-tool --mode=glib-server $< >$@ + + # # mailto # diff --git a/notifier/dbus.c b/notifier/dbus.c new file mode 100644 index 000000000..1f1c43a21 --- /dev/null +++ b/notifier/dbus.c @@ -0,0 +1,550 @@ +/* + * "$Id$" + * + * D-Bus notifier for the Common UNIX Printing System (CUPS). + * + * Copyright 2008 by Apple Inc. + * Copyright (C) 2007 Red Hat, Inc. + * Copyright (C) 2007 Tim Waugh + * Copyright 1997-2005 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * Contents: + * + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND +# define dbus_message_append_iter_init dbus_message_iter_init_append +# define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, v) +# define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, v) +# define dbus_message_iter_append_boolean(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, v) +#endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */ + + +/* + * D-Bus object: org.cups.cupsd.Notifier + * D-Bus object path: /org/cups/cupsd/Notifier + * + * D-Bus interface name: org.cups.cupsd.Notifier + * + * Signals: + * + * ServerRestarted(STRING text) + * Server has restarted. + * + * ServerStarted(STRING text) + * Server has started. + * + * ServerStopped(STRING text) + * Server has stopped. + * + * ServerAudit(STRING text) + * Security-related event. + * + * PrinterRestarted(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer has restarted. + * + * PrinterShutdown(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer has shutdown. + * + * PrinterStopped(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer has stopped. + * + * PrinterStateChanged(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer state has changed. + * + * PrinterFinishingsChanged(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer's finishings-supported attribute has changed. + * + * PrinterMediaChanged(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer's media-supported attribute has changed. + * + * PrinterAdded(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer has been added. + * + * PrinterDeleted(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer has been deleted. + * + * PrinterModified(STRING text, + * STRING printer-uri, + * STRING printer-name, + * UINT32 printer-state, + * STRING printer-state-reasons, + * BOOLEAN printer-is-accepting-jobs) + * Printer has been modified. + * + * text describes the event. + * printer-state-reasons is a comma-separated list. + * If printer-uri is "" in a Job* signal, the other printer-* parameters + * must be ignored. + * If the job name is not know, job-name will be "". + */ + +/* + * Constants... + */ + +enum +{ + PARAMS_NONE, + PARAMS_PRINTER, + PARAMS_JOB +}; + + +/* + * Local functions... + */ + +static int acquire_lock(int *fd); + + +/* + * 'main()' - Read events and send DBUS notifications. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line args */ + char *argv[]) /* I - Command-line arguments */ +{ + ipp_t *msg; /* Event message from scheduler */ + ipp_state_t state; /* IPP event state */ + struct sigaction action; /* POSIX sigaction data */ + DBusConnection *con = NULL; /* Connection to DBUS server */ + DBusError error; /* Error, if any */ + DBusMessage *message; /* Message to send */ + DBusMessageIter iter; /* Iterator for message data */ + int lock_fd = -1; /* Lock file descriptor */ + char lock_filename[1024]; + /* Lock filename */ + + + /* + * Don't buffer stderr... + */ + + setbuf(stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + + /* + * Validate command-line options... + */ + + if (argc != 3) + { + fputs("Usage: dbus dbus:/// notify-user-data\n", stderr); + return (1); + } + + if (strcmp(argv[1], "dbus:")) + { + fprintf(stderr, "ERROR: Bad URI \"%s\"!\n", argv[1]); + return (1); + } + + /* + * Loop forever until we run out of events... + */ + + for (;;) + { + ipp_attribute_t *attr; /* Current attribute */ + const char *event; /* Event name */ + const char *signame = NULL;/* DBUS signal name */ + char *printer_reasons = NULL; + /* Printer reasons string */ + const char *nul = ""; /* Empty string value */ + int no = 0; /* Boolean "no" value */ + int params = PARAMS_NONE; + /* What parameters to include? */ + + + /* + * Get the next event... + */ + + msg = ippNew(); + while ((state = ippReadFile(0, msg)) != IPP_DATA) + { + if (state <= IPP_IDLE) + break; + } + + fprintf(stderr, "DEBUG: state=%d\n", state); + + if (state == IPP_ERROR) + fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr); + + if (state <= IPP_IDLE) + { + /* + * Out of messages, free memory and then exit... + */ + + ippDelete(msg); + break; + } + + /* + * Verify connection to DBUS server... + */ + + if (con && !dbus_connection_get_is_connected(con)) + { + dbus_connection_unref(con); + con = NULL; + } + + if (!con) + { + dbus_error_init(&error); + + con = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (!con) + dbus_error_free(&error); + else + fputs("DEBUG: Connected to D-BUS\n", stderr); + } + + if (!con) + continue; + + if (lock_fd == -1 && + acquire_lock(&lock_fd, lock_filename, sizeof(lock_filename))) + continue; + + attr = ippFindAttribute(msg, "notify-subscribed-event", + IPP_TAG_KEYWORD); + if (!attr) + continue; + + event = attr->values[0].string.text; + if (!strncmp(event, "server-", 7)) + { + const char *word2 = event + 7; /* Second word */ + + if (!strcmp(word2, "restarted")) + signame = "ServerRestarted"; + else if (!strcmp(word2, "started")) + signame = "ServerStarted"; + else if (!strcmp(word2, "stopped")) + signame = "ServerStopped"; + else if (!strcmp(word2, "audit")) + signame = "ServerAudit"; + else + continue; + } + else if (!strncmp(event, "printer-", 8)) + { + const char *word2 = event + 8; /* Second word */ + + params = PARAMS_PRINTER; + if (!strcmp(word2, "restarted")) + signame = "PrinterRestarted"; + else if (!strcmp(word2, "shutdown")) + signame = "PrinterShutdown"; + else if (!strcmp(word2, "stopped")) + signame = "PrinterStopped"; + else if (!strcmp(word2, "state-changed")) + signame = "PrinterStateChanged"; + else if (!strcmp(word2, "finishings-changed")) + signame = "PrinterFinishingsChanged"; + else if (!strcmp(word2, "media-changed")) + signame = "PrinterMediaChanged"; + else if (!strcmp(word2, "added")) + signame = "PrinterAdded"; + else if (!strcmp(word2, "deleted")) + signame = "PrinterDeleted"; + else if (!strcmp(word2, "modified")) + signame = "PrinterModified"; + else + continue; + } + else if (!strncmp(event, "job-", 4)) + { + const char *word2 = event + 4; /* Second word */ + + params = PARAMS_JOB; + if (!strcmp(word2, "state")) + signame = "JobState"; + else if (!strcmp(word2, "created")) + signame = "JobCreated"; + else if (!strcmp(word2, "completed")) + signame = "JobCompleted"; + else if (!strcmp(word2, "stopped")) + signame = "JobStopped"; + else if (!strcmp(word2, "config-changed")) + signame = "JobConfigChanged"; + else if (!strcmp(word2, "progress")) + signame = "JobProgress"; + else + continue; + } + else + continue; + + /* + * Create and send the new message... + */ + + fprintf(stderr, "DEBUG: %s\n", signame); + message = dbus_message_new_signal("/org/cups/cupsd/Notifier", + "org.cups.cupsd.Notifier", + signame); + + dbus_message_append_iter_init(message, &iter); + attr = ippFindAttribute(msg, "notify-text", IPP_TAG_TEXT); + if (!attr) + goto bail; + dbus_message_iter_append_string(&iter, &(attr->values[0].string.text)); + + if (params >= PARAMS_PRINTER) + { + char *p; /* Pointer into printer_reasons */ + size_t reasons_length; /* Required size of printer_reasons */ + int i; /* Looping var */ + int have_printer_params = 1;/* Do we have printer URI? */ + + /* STRING printer-uri or "" */ + attr = ippFindAttribute(msg, "notify-printer-uri", IPP_TAG_URI); + if (attr) + dbus_message_iter_append_string(&iter, &(attr->values[0].string.text)); + else + { + have_printer_params = 0; + dbus_message_iter_append_string(&iter, &nul); + } + + /* STRING printer-name */ + if (have_printer_params) + { + attr = ippFindAttribute(msg, "printer-name", IPP_TAG_NAME); + if (attr) + dbus_message_iter_append_string(&iter, + &(attr->values[0].string.text)); + else + goto bail; + } + else + dbus_message_iter_append_string(&iter, &nul); + + /* UINT32 printer-state */ + if (have_printer_params) + { + attr = ippFindAttribute(msg, "printer-state", IPP_TAG_ENUM); + if (attr) + dbus_message_iter_append_uint32(&iter, &(attr->values[0].integer)); + else + goto bail; + } + else + dbus_message_iter_append_uint32(&iter, &no); + + /* STRING printer-state-reasons */ + if (have_printer_params) + { + attr = ippFindAttribute(msg, "printer-state-reasons", + IPP_TAG_KEYWORD); + if (attr) + { + for (reasons_length = 0, i = 0; i < attr->num_values; i++) + /* All need commas except the last, which needs a nul byte. */ + reasons_length += 1 + strlen(attr->values[i].string.text); + printer_reasons = malloc(reasons_length); + if (!printer_reasons) + goto bail; + p = printer_reasons; + for (i = 0; i < attr->num_values; i++) + { + strcpy(p, attr->values[i].string.text); + p += strlen(p); + if (i) + *p++ = ','; + } + dbus_message_iter_append_string(&iter, &printer_reasons); + } + else + goto bail; + } + else + dbus_message_iter_append_string(&iter, &nul); + + /* BOOL printer-is-accepting-jobs */ + if (have_printer_params) + { + attr = ippFindAttribute(msg, "printer-is-accepting-jobs", + IPP_TAG_BOOLEAN); + if (attr) + dbus_message_iter_append_boolean(&iter, &(attr->values[0].boolean)); + else + goto bail; + } + else + dbus_message_iter_append_boolean(&iter, &no); + } + + if (params >= PARAMS_JOB) + { + /* UINT32 job-id */ + attr = ippFindAttribute(msg, "notify-job-id", IPP_TAG_INTEGER); + if (!attr) + goto bail; + dbus_message_iter_append_uint32(&iter, &(attr->values[0].integer)); + + /* UINT32 job-state */ + attr = ippFindAttribute(msg, "job-state", IPP_TAG_ENUM); + if (!attr) + goto bail; + dbus_message_iter_append_uint32(&iter, &(attr->values[0].integer)); + + /* STRING job-state-reasons */ + attr = ippFindAttribute(msg, "job-state-reasons", IPP_TAG_KEYWORD); + if (!attr) + goto bail; + dbus_message_iter_append_string(&iter, &(attr->values[0].string.text)); + + /* STRING job-name or "" */ + attr = ippFindAttribute(msg, "job-name", IPP_TAG_NAME); + if (attr) + dbus_message_iter_append_string(&iter, &(attr->values[0].string.text)); + else + dbus_message_iter_append_string(&iter, &nul); + + /* UINT32 job-impressions-completed */ + attr = ippFindAttribute(msg, "job-impressions-completed", + IPP_TAG_INTEGER); + if (!attr) + goto bail; + dbus_message_iter_append_uint32(&iter, &(attr->values[0].integer)); + } + + dbus_connection_send(con, message, NULL); + dbus_connection_flush(con); + + /* + * Cleanup... + */ + + bail: + + if (printer_reasons) + free(printer_reasons); + + dbus_message_unref(message); + ippDelete(msg); + } + + /* + * Remove lock file... + */ + + if (lock_fd >= 0) + { + close(lock_fd); + unlink(lock_filename); + } + + return (0); +} + + +/* + * 'acquire_lock()' - Acquire a lock so we only have a single notifier running. + */ + +static int /* O - 0 on success, -1 on failure */ +acquire_lock(int *fd, /* O - Lock file descriptor */ + char *lockfile, /* I - Lock filename buffer */ + size_t locksize) /* I - Size of filename buffer */ +{ + const char *tmpdir; /* Temporary directory */ + + + /* + * Figure out where to put the lock file... + */ + + if ((tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = "/tmp"; + + snprintf(lockfile, locksize, "%s/cups-dbus-notifier-lockfile", tmpdir); + + /* + * Create the lock file and fail if it already exists... + */ + + if ((*fd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0) + return (-1); + else + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/packaging/cups.list.in b/packaging/cups.list.in index 648dcf6ca..da364d11d 100644 --- a/packaging/cups.list.in +++ b/packaging/cups.list.in @@ -271,8 +271,9 @@ d 0755 root sys $SERVERBIN/backend - f 0700 root sys $SERVERBIN/backend/ipp backend/ipp l 0700 root sys $SERVERBIN/backend/http ipp f 0700 root sys $SERVERBIN/backend/lpd backend/lpd -%if MDNS -f 0700 root sys $SERVERBIN/backend/mdns backend/mdns +%if DNSSD_BACKEND +f 0700 root sys $SERVERBIN/backend/dnssd backend/dnssd +l 0700 root sys $SERVERBIN/backend/mdns dnssd %endif %system !darwin f 0755 root sys $SERVERBIN/backend/parallel backend/parallel diff --git a/scheduler/conf.c b/scheduler/conf.c index b3fcbc379..51eecb22b 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -103,6 +103,7 @@ static const cupsd_var_t variables[] = { "DefaultCharset", &DefaultCharset, CUPSD_VARTYPE_STRING }, { "DefaultLanguage", &DefaultLanguage, CUPSD_VARTYPE_STRING }, { "DefaultLeaseDuration", &DefaultLeaseDuration, CUPSD_VARTYPE_INTEGER }, + { "DefaultPaperSize", &DefaultPaperSize, CUPSD_VARTYPE_STRING }, { "DefaultPolicy", &DefaultPolicy, CUPSD_VARTYPE_STRING }, { "DefaultShared", &DefaultShared, CUPSD_VARTYPE_BOOLEAN }, { "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_INTEGER }, @@ -462,6 +463,8 @@ cupsdReadConfiguration(void) cupsdSetString(&DefaultCharset, _cupsEncodingName(language->encoding)); + cupsdClearString(&DefaultPaperSize); + cupsdSetString(&RIPCache, "8m"); cupsdSetString(&TempDir, NULL); @@ -880,6 +883,48 @@ cupsdReadConfiguration(void) cupsdInitEnv(); + /* + * Update default paper size setting as needed... + */ + + if (!DefaultPaperSize) + { +#ifdef HAVE_LIBPAPER + char *paper_result; /* Paper size name from libpaper */ + + if ((paper_result = systempapername()) != NULL) + cupsdSetString(&DefaultPaperSize, paper_result); + else +#endif /* HAVE_LIBPAPER */ + if (!DefaultLanguage || + !strcasecmp(DefaultLanguage, "C") || + !strcasecmp(DefaultLanguage, "POSIX") || + !strcasecmp(DefaultLanguage, "en") || + !strncasecmp(DefaultLanguage, "en.", 3) || + !strncasecmp(DefaultLanguage, "en_US", 5) || + !strncasecmp(DefaultLanguage, "en_CA", 5) || + !strncasecmp(DefaultLanguage, "fr_CA", 5)) + { + /* + * These are the only locales that will default to "letter" size... + */ + + cupsdSetString(&DefaultPaperSize, "Letter"); + } + else + cupsdSetString(&DefaultPaperSize, "A4"); + } + + /* + * Update classification setting as needed... + */ + + if (Classification && !strcasecmp(Classification, "none")) + cupsdClearString(&Classification); + + if (Classification) + cupsdLogMessage(CUPSD_LOG_INFO, "Security set to \"%s\"", Classification); + /* * Check the MaxClients setting, and then allocate memory for it... */ @@ -904,12 +949,6 @@ cupsdReadConfiguration(void) if (MaxActiveJobs > (MaxFDs / 3)) MaxActiveJobs = MaxFDs / 3; - if (Classification && !strcasecmp(Classification, "none")) - cupsdClearString(&Classification); - - if (Classification) - cupsdLogMessage(CUPSD_LOG_INFO, "Security set to \"%s\"", Classification); - /* * Update the MaxClientsPerHost value, as needed... */ diff --git a/scheduler/conf.h b/scheduler/conf.h index e3040d438..1b3765bd4 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -98,6 +98,8 @@ VAR char *AccessLog VALUE(NULL), /* Default charset */ *DefaultLocale VALUE(NULL), /* Default locale */ + *DefaultPaperSize VALUE(NULL), + /* Default paper size */ *ErrorPolicy VALUE(NULL), /* Default printer-error-policy */ *RIPCache VALUE(NULL), diff --git a/scheduler/cups-lpd.c b/scheduler/cups-lpd.c index 450c93f02..d79c69202 100644 --- a/scheduler/cups-lpd.c +++ b/scheduler/cups-lpd.c @@ -81,8 +81,8 @@ */ static int create_job(http_t *http, const char *dest, const char *title, - const char *user, int num_options, - cups_option_t *options); + const char *docname, const char *user, + int num_options, cups_option_t *options); static int get_printer(http_t *http, const char *name, char *dest, int destsize, cups_option_t **options, int *accepting, int *shared, ipp_pstate_t *state); @@ -338,6 +338,7 @@ static int /* O - Job ID or -1 on error */ create_job(http_t *http, /* I - HTTP connection */ const char *dest, /* I - Destination name */ const char *title, /* I - job-name */ + const char *docname, /* I - Name of job file */ const char *user, /* I - requesting-user-name */ int num_options, /* I - Number of options for job */ cups_option_t *options) /* I - Options for job */ @@ -364,10 +365,14 @@ create_job(http_t *http, /* I - HTTP connection */ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); - if (title) + if (title[0]) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); + if (docname[0]) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", + NULL, docname); + cupsEncodeOptions(request, num_options, options); /* @@ -1143,9 +1148,10 @@ recv_print_job( * Grab the job information... */ - title[0] = '\0'; - user[0] = '\0'; - doccount = 0; + title[0] = '\0'; + user[0] = '\0'; + docname[0] = '\0'; + doccount = 0; while (smart_gets(line, sizeof(line), fp) != NULL) { @@ -1159,6 +1165,10 @@ recv_print_job( strlcpy(title, line + 1, sizeof(title)); break; + case 'N' : /* Document name */ + strlcpy(docname, line + 1, sizeof(docname)); + break; + case 'P' : /* User identification */ strlcpy(user, line + 1, sizeof(user)); break; @@ -1222,7 +1232,8 @@ recv_print_job( * Create the job... */ - if ((id = create_job(http, dest, title, user, num_options, options)) < 0) + if ((id = create_job(http, dest, title, docname, user, num_options, + options)) < 0) status = 1; else { diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index 27efd0d00..e7e2b6e1f 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -14,6 +14,64 @@ * * Contents: * + * cupsdDeregisterPrinter() - Stop sending broadcast information for a local + * printer and remove any pending references to + * remote printers. + * cupsdLoadRemoteCache() - Load the remote printer cache. + * cupsdRegisterPrinter() - Start sending broadcast information for a + * printer or update the broadcast contents. + * cupsdRestartPolling() - Restart polling servers as needed. + * cupsdSaveRemoteCache() - Save the remote printer cache. + * cupsdSendBrowseList() - Send new browsing information as necessary. + * ldap_rebind_proc() - Callback function for LDAP rebind + * ldap_connect() - Start new LDAP connection + * ldap_reconnect() - Reconnect to LDAP Server + * ldap_disconnect() - Disconnect from LDAP Server + * cupsdStartBrowsing() - Start sending and receiving broadcast + * information. + * cupsdStartPolling() - Start polling servers as needed. + * cupsdStopBrowsing() - Stop sending and receiving broadcast + * information. + * cupsdStopPolling() - Stop polling servers as needed. + * cupsdUpdateDNSSDName() - Update the computer name we use for + * browsing... + * cupsdUpdateLDAPBrowse() - Scan for new printers via LDAP... + * cupsdUpdateSLPBrowse() - Get browsing information via SLP. + * dequote() - Remote quotes from a string. + * dnssdBuildTxtRecord() - Build a TXT record from printer info. + * dnssdComparePrinters() - Compare the registered names of two printers. + * dnssdDeregisterPrinter() - Stop sending broadcast information for a + * printer. + * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT + * record format. + * dnssdRegisterCallback() - DNSServiceRegister callback. + * dnssdRegisterPrinter() - Start sending broadcast information for a + * printer or update the broadcast contents. + * dnssdUpdate() - Handle DNS-SD queries. + * get_hostconfig() - Get an /etc/hostconfig service setting. + * is_local_queue() - Determine whether the URI points at a local + * queue. + * process_browse_data() - Process new browse data. + * process_implicit_classes() - Create/update implicit classes as needed. + * send_cups_browse() - Send new browsing information using the CUPS + * protocol. + * ldap_search_rec() - LDAP Search with reconnect + * ldap_freeres() - Free LDAPMessage + * ldap_getval_char() - Get first LDAP value and convert to string + * send_ldap_ou() - Send LDAP ou registrations. + * send_ldap_browse() - Send LDAP printer registrations. + * ldap_dereg_printer() - Delete printer from directory + * send_slp_browse() - Register the specified printer with SLP. + * slp_attr_callback() - SLP attribute callback + * slp_dereg_printer() - SLPDereg() the specified printer + * slp_get_attr() - Get an attribute from an SLP registration. + * slp_reg_callback() - Empty SLPRegReport. + * slp_url_callback() - SLP service url callback + * update_cups_browse() - Update the browse lists using the CUPS + * protocol. + * update_lpd() - Update the LPD configuration as needed. + * update_polling() - Read status messages from the poll daemons. + * update_smb() - Update the SMB configuration as needed. */ /* diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 1bc53445c..11fa79bd5 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -77,7 +77,7 @@ * move_job() - Move a job to a new destination. * ppd_parse_line() - Parse a PPD default line. * print_job() - Print a file to a printer or class. - * read_ps_job_ticket() - Reads a job ticket embedded in a PS file. + * read_job_ticket() - Read a job ticket embedded in a print file. * reject_jobs() - Reject print jobs to a printer. * release_job() - Release a held print job. * renew_subscription() - Renew an existing subscription... @@ -201,7 +201,7 @@ static void move_job(cupsd_client_t *con, ipp_attribute_t *uri); static int ppd_parse_line(const char *line, char *option, int olen, char *choice, int clen); static void print_job(cupsd_client_t *con, ipp_attribute_t *uri); -static void read_ps_job_ticket(cupsd_client_t *con); +static void read_job_ticket(cupsd_client_t *con); static void reject_jobs(cupsd_client_t *con, ipp_attribute_t *uri); static void release_job(cupsd_client_t *con, ipp_attribute_t *uri); static void renew_subscription(cupsd_client_t *con, int sub_id); @@ -679,7 +679,9 @@ cupsdProcessIPPRequest( */ cupsdLogMessage(con->response->request.status.status_code - >= IPP_BAD_REQUEST ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, + >= IPP_BAD_REQUEST && + con->response->request.status.status_code + != IPP_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, "Returning IPP %s for %s (%s) from %s", ippErrorString(con->response->request.status.status_code), ippOpString(con->request->request.op.operation_id), @@ -4975,12 +4977,6 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ cups_option_t *defaults; /* Default options */ char cups_protocol[PPD_MAX_LINE]; /* cupsProtocol attribute */ - int have_letter, /* Have Letter size */ - have_a4; /* Have A4 size */ -#ifdef HAVE_LIBPAPER - char *paper_result; /* Paper size name from libpaper */ - char system_paper[64]; /* Paper size name buffer */ -#endif /* HAVE_LIBPAPER */ cupsdLogMessage(CUPSD_LOG_DEBUG2, @@ -5105,9 +5101,6 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ return (-1); } - have_letter = ppdPageSize(ppd, "Letter") != NULL; - have_a4 = ppdPageSize(ppd, "A4") != NULL; - /* * Open the destination (if possible) and set the default options... */ @@ -5152,81 +5145,20 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ cupsFileClose(dst); } -#ifdef HAVE_LIBPAPER - else if ((paper_result = systempapername()) != NULL) - { - /* - * Set the default media sizes from the systemwide default... - */ - - strlcpy(system_paper, paper_result, sizeof(system_paper)); - system_paper[0] = toupper(system_paper[0] & 255); - - if ((!strcmp(system_paper, "Letter") && have_letter) || - (!strcmp(system_paper, "A4") && have_a4)) - { - num_defaults = cupsAddOption("PageSize", system_paper, - num_defaults, &defaults); - num_defaults = cupsAddOption("PageRegion", system_paper, - num_defaults, &defaults); - num_defaults = cupsAddOption("PaperDimension", system_paper, - num_defaults, &defaults); - num_defaults = cupsAddOption("ImageableArea", system_paper, - num_defaults, &defaults); - } - } -#endif /* HAVE_LIBPAPER */ - else + else if (ppdPageSize(ppd, DefaultPaperSize)) { /* * Add the default media sizes... - * - * Note: These values are generally not valid for large-format devices - * like plotters, however it is probably safe to say that those - * users will configure the media size after initially adding - * the device anyways... */ - if (!DefaultLanguage || - !strcasecmp(DefaultLanguage, "C") || - !strcasecmp(DefaultLanguage, "POSIX") || - !strcasecmp(DefaultLanguage, "en") || - !strncasecmp(DefaultLanguage, "en.", 3) || - !strncasecmp(DefaultLanguage, "en_US", 5) || - !strncasecmp(DefaultLanguage, "en_CA", 5) || - !strncasecmp(DefaultLanguage, "fr_CA", 5)) - { - /* - * These are the only locales that will default to "letter" size... - */ - - if (have_letter) - { - num_defaults = cupsAddOption("PageSize", "Letter", num_defaults, - &defaults); - num_defaults = cupsAddOption("PageRegion", "Letter", num_defaults, - &defaults); - num_defaults = cupsAddOption("PaperDimension", "Letter", num_defaults, - &defaults); - num_defaults = cupsAddOption("ImageableArea", "Letter", num_defaults, - &defaults); - } - } - else if (have_a4) - { - /* - * The rest default to "a4" size... - */ - - num_defaults = cupsAddOption("PageSize", "A4", num_defaults, - &defaults); - num_defaults = cupsAddOption("PageRegion", "A4", num_defaults, - &defaults); - num_defaults = cupsAddOption("PaperDimension", "A4", num_defaults, - &defaults); - num_defaults = cupsAddOption("ImageableArea", "A4", num_defaults, - &defaults); - } + num_defaults = cupsAddOption("PageSize", DefaultPaperSize, + num_defaults, &defaults); + num_defaults = cupsAddOption("PageRegion", DefaultPaperSize, + num_defaults, &defaults); + num_defaults = cupsAddOption("PaperDimension", DefaultPaperSize, + num_defaults, &defaults); + num_defaults = cupsAddOption("ImageableArea", DefaultPaperSize, + num_defaults, &defaults); } ppdClose(ppd); @@ -8475,8 +8407,9 @@ print_job(cupsd_client_t *con, /* I - Client connection */ */ if (!strcasecmp(filetype->super, "application") && - !strcasecmp(filetype->type, "postscript")) - read_ps_job_ticket(con); + (!strcasecmp(filetype->type, "postscript") || + !strcasecmp(filetype->type, "pdf"))) + read_job_ticket(con); /* * Create the job object... @@ -8537,16 +8470,16 @@ print_job(cupsd_client_t *con, /* I - Client connection */ /* - * 'read_ps_job_ticket()' - Reads a job ticket embedded in a PS file. + * 'read_job_ticket()' - Read a job ticket embedded in a print file. * - * This function only gets called when printing a single PostScript + * This function only gets called when printing a single PDF or PostScript * file using the Print-Job operation. It doesn't work for Create-Job + * Send-File, since the job attributes need to be set at job creation - * time for banners to work. The embedded PS job ticket stuff is here - * only to allow the Windows printer driver for CUPS to pass in JCL + * time for banners to work. The embedded job ticket stuff is here + * primarily to allow the Windows printer driver for CUPS to pass in JCL * options and IPP attributes which otherwise would be lost. * - * The format of a PS job ticket is simple: + * The format of a job ticket is simple: * * %cupsJobTicket: attr1=value1 attr2=value2 ... attrN=valueN * @@ -8556,8 +8489,8 @@ print_job(cupsd_client_t *con, /* I - Client connection */ * %cupsJobTicket: attrN=valueN * * Job ticket lines must appear immediately after the first line that - * specifies PostScript format (%!PS-Adobe-3.0), and CUPS will stop - * looking for job ticket info when it finds a line that does not begin + * specifies PostScript (%!PS-Adobe-3.0) or PDF (%PDF) format, and CUPS + * stops looking for job ticket info when it finds a line that does not begin * with "%cupsJobTicket:". * * The maximum length of a job ticket line, including the prefix, is @@ -8570,7 +8503,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */ */ static void -read_ps_job_ticket(cupsd_client_t *con) /* I - Client connection */ +read_job_ticket(cupsd_client_t *con) /* I - Client connection */ { cups_file_t *fp; /* File to read from */ char line[256]; /* Line data */ @@ -8589,8 +8522,7 @@ read_ps_job_ticket(cupsd_client_t *con) /* I - Client connection */ if ((fp = cupsFileOpen(con->filename, "rb")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, - "read_ps_job_ticket: Unable to open PostScript print file " - "- %s", + "Unable to open print file for job ticket - %s", strerror(errno)); return; } @@ -8602,14 +8534,13 @@ read_ps_job_ticket(cupsd_client_t *con) /* I - Client connection */ if (cupsFileGets(fp, line, sizeof(line)) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, - "read_ps_job_ticket: Unable to read from PostScript print " - "file - %s", + "Unable to read from print file for job ticket - %s", strerror(errno)); cupsFileClose(fp); return; } - if (strncmp(line, "%!PS-Adobe-", 11)) + if (strncmp(line, "%!PS-Adobe-", 11) && strncmp(line, "%PDF-", 5)) { /* * Not a DSC-compliant file, so no job ticket info will be available... diff --git a/scheduler/job.c b/scheduler/job.c index 26a9b6c00..1fa6352aa 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -2894,19 +2894,11 @@ start_job(cupsd_job_t *job, /* I - Job ID */ if (!strncmp(attr->name, "time-", 5)) continue; - if (!strncmp(attr->name, "job-", 4) && strcmp(attr->name, "job-uuid") && - strcmp(attr->name, "job-impressions") && - strcmp(attr->name, "job-originating-host-name") && - !(printer->type & CUPS_PRINTER_REMOTE)) - continue; - if (!strncmp(attr->name, "job-", 4) && strcmp(attr->name, "job-uuid") && - strcmp(attr->name, "job-billing") && strcmp(attr->name, "job-impressions") && - strcmp(attr->name, "job-sheets") && - strcmp(attr->name, "job-hold-until") && - strcmp(attr->name, "job-priority")) + strcmp(attr->name, "job-originating-host-name") && + !(printer->type & CUPS_PRINTER_REMOTE)) continue; if ((!strcmp(attr->name, "job-impressions") || diff --git a/templates/add-printer.tmpl b/templates/add-printer.tmpl index 1b798b590..804e18921 100644 --- a/templates/add-printer.tmpl +++ b/templates/add-printer.tmpl @@ -24,6 +24,11 @@ (Human-readable location such as "Lab 1") +Sharing: + +Share This Printer + + diff --git a/templates/choose-make.tmpl b/templates/choose-make.tmpl index e50688c7f..2d5a1fac4 100644 --- a/templates/choose-make.tmpl +++ b/templates/choose-make.tmpl @@ -23,6 +23,11 @@ {printer_location} +Sharing: + +{?printer_is_shared=?Do Not:{?printer_is_shared=0?Do Not:}} Share This Printer + + Make: - @@ -23,6 +22,11 @@ + + + + diff --git a/templates/modify-printer.tmpl b/templates/modify-printer.tmpl index 238bc3da4..c670ca7a0 100644 --- a/templates/modify-printer.tmpl +++ b/templates/modify-printer.tmpl @@ -21,6 +21,11 @@ (Human-readable location such as "Lab 1") + + + + -- 2.39.2
    Connection:{printer_location}
    Sharing: +{?printer_is_shared=?Do Not:{?printer_is_shared=0?Do Not:}} Share This Printer
    Make: {PPD_MAKE}
    Sharing: +Share This Printer