From 58dc193312e27d25c0394e4fcb7a6eed7301b1ec Mon Sep 17 00:00:00 2001 From: msweet Date: Wed, 8 Oct 2008 22:50:16 +0000 Subject: [PATCH] Merge changes from CUPS 1.4svn-r8033. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@1003 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES.txt | 7 +- Makedefs.in | 3 +- Makefile | 3 +- backend/Makefile | 2 +- backend/dnssd.c | 25 +- backend/snmp-supplies.c | 16 + backend/usb-darwin.c | 21 +- cgi-bin/Makefile | 8 +- cgi-bin/admin.c | 874 ++++++------ cgi-bin/cgi.h | 6 +- cgi-bin/classes.c | 137 +- cgi-bin/html.c | 48 +- cgi-bin/ipp-var.c | 160 ++- cgi-bin/libcupscgi.exp | 3 + cgi-bin/printers.c | 232 ++-- cgi-bin/var.c | 2 +- conf/mime.convs.in | 2 +- config-scripts/cups-common.m4 | 2 +- cups/adminutil.c | 3 +- cups/file.c | 61 + cups/file.h | 4 +- cups/libcups.exp | 1 + cups/testhttp.c | 4 + cups/testi18n.c | 16 +- cups/transcode.c | 4 +- cups/util.c | 11 +- data/iso-8859-10 | 251 ---- data/iso-8859-13 | 251 ---- data/iso-8859-14 | 251 ---- data/iso-8859-15 | 251 ---- doc/Makefile | 7 +- doc/cups.css | 29 +- doc/help/overview.html | 129 +- doc/help/ref-printers-conf.html | 71 +- doc/help/spec-ipp.html | 2 +- doc/help/spec-ppd.html | 18 + doc/help/whatsnew.html | 161 +-- doc/images/web-add-this-printer.gif | Bin 23429 -> 0 bytes doc/images/web-password.gif | Bin 20956 -> 0 bytes doc/images/web-printer-driver.gif | Bin 20917 -> 0 bytes doc/images/web-printer-status.gif | Bin 24271 -> 0 bytes doc/images/web-set-printer-options.gif | Bin 19998 -> 0 bytes doc/images/web-test-page.gif | Bin 19005 -> 0 bytes filter/bannertops.c | 11 +- locale/cups_pt_PT.po | 1464 -------------------- man/lpinfo.man | 42 +- scheduler/classes.c | 109 +- scheduler/client.c | 5 +- scheduler/conf.c | 2 + scheduler/cups-driverd.cxx | 383 ++++- scheduler/cupsd.h | 3 +- scheduler/dirsvc.c | 38 +- scheduler/ipp.c | 14 +- scheduler/printers.c | 286 ++-- scheduler/printers.h | 2 + systemv/lpinfo.c | 195 ++- templates/Makefile | 2 +- templates/choose-device.tmpl | 5 +- templates/class-added.tmpl | 2 + templates/class-confirm.tmpl | 2 + templates/class-deleted.tmpl | 2 + templates/class-modified.tmpl | 2 + templates/class.tmpl | 4 +- templates/error-op.tmpl | 2 + templates/error.tmpl | 2 + templates/help-header.tmpl | 2 +- templates/job-cancel.tmpl | 6 + templates/job-hold.tmpl | 6 + templates/job-move.tmpl | 6 +- templates/job-moved.tmpl | 6 + templates/job-release.tmpl | 6 + templates/job-restart.tmpl | 6 + templates/jobs.tmpl | 4 +- templates/maintenance.tmpl | 6 - templates/norestart.tmpl | 10 +- templates/option-boolean.tmpl | 2 +- templates/option-header.tmpl | 6 +- templates/option-pickmany.tmpl | 2 +- templates/option-pickone.tmpl | 2 +- templates/option-trailer.tmpl | 8 +- templates/printer-accept.tmpl | 2 + templates/printer-added.tmpl | 2 + templates/printer-configured.tmpl | 6 +- templates/printer-confirm.tmpl | 2 + templates/printer-default.tmpl | 2 + templates/printer-deleted.tmpl | 2 + templates/printer-modified.tmpl | 2 + templates/printer-purge.tmpl | 2 + templates/printer-reject.tmpl | 2 + templates/printer-start.tmpl | 4 +- templates/printer-stop.tmpl | 4 +- templates/printer.tmpl | 7 +- templates/restart.tmpl | 9 +- templates/set-printer-options-header.tmpl | 8 +- templates/set-printer-options-trailer.tmpl | 2 + templates/test-page.tmpl | 6 + tools/checkpo | 22 - 97 files changed, 2097 insertions(+), 3718 deletions(-) delete mode 100644 data/iso-8859-10 delete mode 100644 data/iso-8859-13 delete mode 100644 data/iso-8859-14 delete mode 100644 data/iso-8859-15 delete mode 100644 doc/images/web-add-this-printer.gif delete mode 100644 doc/images/web-password.gif delete mode 100644 doc/images/web-printer-driver.gif delete mode 100644 doc/images/web-printer-status.gif delete mode 100644 doc/images/web-set-printer-options.gif delete mode 100644 doc/images/web-test-page.gif delete mode 100644 locale/cups_pt_PT.po delete mode 100755 tools/checkpo diff --git a/CHANGES.txt b/CHANGES.txt index 9fd042a64..67afdc144 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,9 +1,14 @@ -CHANGES.txt - 2008-10-01 +CHANGES.txt - 2008-10-08 ------------------------ CHANGES IN CUPS V1.4b1 - Documentation updates (STR #2567) + - CUPS-Get-Driver now provides much better driver matching based + on the IEEE-1284 device ID and make/model strings (STR #2707) + - Now support the cupsSNMPSupplies keyword to control whether + the network backends query the SNMP Printer MIB for supply + levels. - Now support and use a new banner file format for better text support and easier customization (STR #2490) - The scheduler now sets the PRINTER_INFO and PRINTER_LOCATION diff --git a/Makedefs.in b/Makedefs.in index 33270a4c3..c756e0283 100644 --- a/Makedefs.in +++ b/Makedefs.in @@ -137,7 +137,8 @@ FONTS = @FONTS@ IMGLIBS = @IMGLIBS@ IMGFILTERS = @IMGFILTERS@ LAUNCHDLIBS = @LAUNCHDLIBS@ -LDFLAGS = -L../cups -L../filter @LDARCHFLAGS@ \ +LDFLAGS = -L../cgi-bin -L../cups -L../filter -L../ppdc \ + -L../scheduler @LDARCHFLAGS@ \ @LDFLAGS@ @RELROFLAGS@ @PIEFLAGS@ $(OPTIM) LEGACY_BACKENDS = @LEGACY_BACKENDS@ LIBCUPSORDER = @LIBCUPSORDER@ diff --git a/Makefile b/Makefile index d74d82f09..cd19f8358 100644 --- a/Makefile +++ b/Makefile @@ -117,12 +117,13 @@ distclean: clean $(RM) man/cups-lpd.man man/cupsaddsmb.man man/cupsd.man $(RM) man/cupsd.conf.man man/drv.man man/lpoptions.man $(RM) packaging/cups.list + $(RM) packaging/cups-desc.plist packaging/cups-info.plist $(RM) templates/header.tmpl $(RM) desktop/cups.desktop $(RM) init/cups.xml -$(RM) doc/*/index.html -$(RM) templates/*/header.tmpl - -$(RM) -r autom4te*.cache + -$(RM) -r autom4te*.cache clang cups/charmaps cups/locale driver/test # diff --git a/backend/Makefile b/backend/Makefile index 29901826e..462273339 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -264,7 +264,7 @@ socket: socket.o ../cups/$(LIBCUPS) libbackend.a usb: usb.o ../cups/$(LIBCUPS) libbackend.a echo Linking $@... - $(CC) $(ARCHFLAGS) $(LDFLAGS) -o usb usb.o libbackend.a $(LIBUSB) \ + $(CC) $(LDFLAGS) -o usb usb.o libbackend.a $(LIBUSB) \ $(BACKLIBS) $(LIBS) usb.o: usb.c usb-darwin.c usb-libusb.c usb-unix.c diff --git a/backend/dnssd.c b/backend/dnssd.c index 674bacf80..ec32bba48 100644 --- a/backend/dnssd.c +++ b/backend/dnssd.c @@ -242,6 +242,7 @@ main(int argc, /* I - Number of command-line args */ * Announce any devices we've found... */ + DNSServiceErrorType status; /* DNS query status */ cups_device_t *best; /* Best matching device */ char device_uri[1024]; /* Device URI */ int count; /* Number of queries */ @@ -266,13 +267,19 @@ main(int argc, /* I - Number of command-line args */ fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName); - if (DNSServiceQueryRecord(&(device->ref), - kDNSServiceFlagsShareConnection, - 0, device->fullName, kDNSServiceType_TXT, - kDNSServiceClass_IN, query_callback, - devices) != kDNSServiceErr_NoError) + status = DNSServiceQueryRecord(&(device->ref), + kDNSServiceFlagsShareConnection, + 0, device->fullName, + kDNSServiceType_TXT, + kDNSServiceClass_IN, query_callback, + devices); + if (status != kDNSServiceErr_NoError) + { fputs("ERROR: Unable to query for TXT records!\n", stderr); - else + fprintf(stderr, "DEBUG: DNSServiceQueryRecord returned %d\n", + status); + } + else count ++; } } @@ -501,7 +508,8 @@ get_device(cups_array_t *devices, /* I - Device array */ { cups_device_t key, /* Search key */ *device; /* Device */ - char fullName[1024]; /* Full name for query */ + char fullName[kDNSServiceMaxDomainName]; + /* Full name for query */ /* @@ -551,8 +559,7 @@ get_device(cups_array_t *devices, /* I - Device array */ * Set the "full name" of this service, which is used for queries... */ - snprintf(fullName, sizeof(fullName), "%s.%s%s", serviceName, regtype, - replyDomain); + DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain); device->fullName = strdup(fullName); return (device); diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c index dea84fcf1..b63ed85c3 100644 --- a/backend/snmp-supplies.c +++ b/backend/snmp-supplies.c @@ -323,6 +323,8 @@ backend_init_supplies( *ptr, /* Pointer into value string */ *name_ptr; /* Pointer into name string */ cups_snmp_t packet; /* SNMP response packet */ + ppd_file_t *ppd; /* PPD file for this queue */ + ppd_attr_t *ppdattr; /* cupsSNMPSupplies attribute */ static const char * const types[] = /* Supply types */ { "other", @@ -371,6 +373,20 @@ backend_init_supplies( memset(supplies, 0, sizeof(supplies)); + /* + * See if we should be getting supply levels via SNMP... + */ + + if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL && + (ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL && + ppdattr->value && strcasecmp(ppdattr->value, "true")) + { + ppdClose(ppd); + return; + } + + ppdClose(ppd); + /* * Get the device description... */ diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index ea2f92b1d..3f12405f8 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -648,14 +648,12 @@ print_device(const char *uri, /* I - Device URI */ status = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0); /* - * Ignore timeout errors... + * Ignore timeout errors, but retain the number of bytes written to + * avoid sending duplicate data ()... */ if (status == kIOUSBTransactionTimeout) - { status = 0; - bytes = 0; - } if (status || bytes < 0) { @@ -1287,11 +1285,9 @@ static kern_return_t load_classdriver(CFStringRef driverPath, } } -#ifdef DEBUG char bundlestr[1024]; CFStringGetCString(bundle, bundlestr, sizeof(bundlestr), kCFStringEncodingUTF8); fprintf(stderr, "DEBUG: load_classdriver(%s) (kr:0x%08x)\n", bundlestr, (int)kr); -#endif /* DEBUG */ return kr; } @@ -1771,6 +1767,9 @@ static void run_legacy_backend(int argc, struct sigaction action; /* POSIX signal action */ sigset_t newmask, /* New signal mask */ oldmask; /* Old signal mask */ + char usbpath[1024]; /* Path to USB backend */ + const char *cups_serverbin;/* Path to CUPS binaries */ + memset(&action, 0, sizeof(action)); sigaddset(&action.sa_mask, SIGTERM); @@ -1822,15 +1821,19 @@ static void run_legacy_backend(int argc, * Set up the arguments and call posix_spawn... */ + if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL) + cups_serverbin = CUPS_SERVERBIN; + snprintf(usbpath, sizeof(usbpath), "%s/backend/usb", cups_serverbin); + for (i = 0; i < argc && i < (sizeof(my_argv) / sizeof(my_argv[0])) - 1; i ++) my_argv[i] = argv[i]; my_argv[i] = NULL; - if (posix_spawn(&child_pid, "/usr/libexec/cups/backend/usb", NULL, &attrs, - my_argv, environ)) + if (posix_spawn(&child_pid, usbpath, NULL, &attrs, my_argv, environ)) { - perror("DEBUG: Unable to exec /usr/libexec/cups/backend/usb"); + fprintf(stderr, "DEBUG: Unable to exec %s: %s\n", usbpath, + strerror(errno)); _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n")); exit(CUPS_BACKEND_STOP); } diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile index 04055777b..0e35492b0 100644 --- a/cgi-bin/Makefile +++ b/cgi-bin/Makefile @@ -328,7 +328,7 @@ libcupscgi.a: $(LIBOBJS) admin.cgi: admin.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI) echo Linking $@... - $(CC) $(LDFLAGS) -o $@ admin.o -L. -lcupscgi $(LIBS) + $(CC) $(LDFLAGS) -o $@ admin.o -lcupscgi $(LIBS) # @@ -337,7 +337,7 @@ admin.cgi: admin.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI) classes.cgi: classes.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI) echo Linking $@... - $(CC) $(LDFLAGS) -o $@ classes.o -L. -lcupscgi $(LIBS) + $(CC) $(LDFLAGS) -o $@ classes.o -lcupscgi $(LIBS) # @@ -346,7 +346,7 @@ classes.cgi: classes.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI) help.cgi: help.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI) echo Linking $@... - $(CC) $(LDFLAGS) -o $@ help.o -L. -lcupscgi $(LIBS) + $(CC) $(LDFLAGS) -o $@ help.o -lcupscgi $(LIBS) # @@ -355,7 +355,7 @@ help.cgi: help.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI) jobs.cgi: jobs.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI) echo Linking $@... - $(CC) $(LDFLAGS) -o $@ jobs.o -L. -lcupscgi $(LIBS) + $(CC) $(LDFLAGS) -o $@ jobs.o -lcupscgi $(LIBS) # diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index 70a57dc5e..a02020370 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -1,5 +1,5 @@ /* - * "$Id: admin.c 7888 2008-08-29 21:16:56Z mike $" + * "$Id: admin.c 8029 2008-10-08 21:07:45Z mike $" * * Administration CGI for the Common UNIX Printing System (CUPS). * @@ -15,6 +15,7 @@ * Contents: * * main() - Main entry for CGI. + * choose_device_cb() - Add a device to the device selection page. * do_add_rss_subscription() - Add a RSS subscription. * do_am_class() - Add or modify a class. * do_am_printer() - Add or modify a printer. @@ -25,13 +26,12 @@ * do_export() - Export printers to Samba. * do_list_printers() - List available printers. * do_menu() - Show the main menu. - * do_printer_op() - Do a printer operation. * do_set_allowed_users() - Set the allowed/denied users for a queue. + * do_set_default() - Set the server default printer/class. * do_set_options() - Configure the default options for a queue. * do_set_sharing() - Set printer-is-shared value. * get_option_value() - Return the value of an option. * get_points() - Get a value in points. - * match_string() - Return the number of matching characters. */ /* @@ -48,29 +48,41 @@ #include +/* + * Local globals... + */ + +static int current_device; /* Current device for add/modify */ +static time_t last_device_time; /* Last update time for device list */ + + /* * Local functions... */ +static void choose_device_cb(const char *device_class, + const char *device_id, const char *device_info, + const char *device_make_and_model, + const char *device_uri, + const char *device_location, + const char *title); static void do_add_rss_subscription(http_t *http); static void do_am_class(http_t *http, int modify); static void do_am_printer(http_t *http, int modify); static void do_cancel_subscription(http_t *http); -static void do_set_options(http_t *http, int is_class); static void do_config_server(http_t *http); static void do_delete_class(http_t *http); static void do_delete_printer(http_t *http); static void do_export(http_t *http); static void do_list_printers(http_t *http); static void do_menu(http_t *http); -static void do_printer_op(http_t *http, - ipp_op_t op, const char *title); static void do_set_allowed_users(http_t *http); +static void do_set_default(http_t *http); +static void do_set_options(http_t *http, int is_class); static void do_set_sharing(http_t *http); static char *get_option_value(ppd_file_t *ppd, const char *name, char *buffer, size_t bufsize); static double get_points(double number, const char *uval); -static int match_string(const char *a, const char *b); /* @@ -133,24 +145,10 @@ main(int argc, /* I - Number of command-line arguments */ fprintf(stderr, "DEBUG: op=\"%s\"...\n", op); - if (!strcmp(op, "start-printer")) - do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Printer"))); - else if (!strcmp(op, "stop-printer")) - do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Printer"))); - else if (!strcmp(op, "start-class")) - do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Class"))); - else if (!strcmp(op, "stop-class")) - do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Class"))); - else if (!strcmp(op, "accept-jobs")) - do_printer_op(http, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs"))); - else if (!strcmp(op, "reject-jobs")) - do_printer_op(http, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs"))); - else if (!strcmp(op, "purge-jobs")) - do_printer_op(http, IPP_PURGE_JOBS, cgiText(_("Purge Jobs"))); - else if (!strcmp(op, "set-allowed-users")) + if (!strcmp(op, "set-allowed-users")) do_set_allowed_users(http); else if (!strcmp(op, "set-as-default")) - do_printer_op(http, CUPS_SET_DEFAULT, cgiText(_("Set As Default"))); + do_set_default(http); else if (!strcmp(op, "set-sharing")) do_set_sharing(http); else if (!strcmp(op, "find-new-printers") || @@ -236,6 +234,49 @@ main(int argc, /* I - Number of command-line arguments */ } +/* + * 'choose_device_cb()' - Add a device to the device selection page. + */ + +static void +choose_device_cb( + const char *device_class, /* I - Class */ + const char *device_id, /* I - 1284 device ID */ + const char *device_info, /* I - Description */ + const char *device_make_and_model, /* I - Make and model */ + const char *device_uri, /* I - Device URI */ + const char *device_location, /* I - Location */ + const char *title) /* I - Page title */ +{ + /* + * Add the device to the array... + */ + + cgiSetArray("device_class", current_device, device_class); + cgiSetArray("device_id", current_device, device_id); + cgiSetArray("device_info", current_device, device_info); + cgiSetArray("device_make_and_model", current_device, device_make_and_model); + cgiSetArray("device_uri", current_device, device_uri); + cgiSetArray("device_location", current_device, device_location); + + current_device ++; + + if (time(NULL) > last_device_time) + { + /* + * Update the page... + */ + + cgiStartHTML(title); + cgiCopyTemplateLang("choose-device.tmpl"); + cgiEndHTML(); + fflush(stdout); + + time(&last_device_time); + } +} + + /* * 'do_add_rss_subscription()' - Add a RSS subscription. */ @@ -852,54 +893,55 @@ do_am_printer(http_t *http, /* I - HTTP connection */ if (!var) { /* - * Build a CUPS_GET_DEVICES request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri + * Look for devices so the user can pick something... */ - fputs("DEBUG: Getting list of devices...\n", stderr); + if ((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'; - request = ippNewRequest(CUPS_GET_DEVICES); + cgiSetVariable("CURRENT_DEVICE_URI", attr->values[0].string.text); + cgiSetVariable("CURRENT_DEVICE_SCHEME", uri); + } - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", - NULL, "ipp://localhost/printers/"); + /* + * Prime the page with the current device listed... + */ + + cgiStartMultipart(); + cgiStartHTML(title); + cgiCopyTemplateLang("choose-device.tmpl"); + cgiEndHTML(); + fflush(stdout); /* - * Do the request and get back a response... + * Scan for devices for up to 30 seconds, updating the page as we find + * them... */ - if ((response = cupsDoRequest(http, request, "/")) != NULL) - { - fputs("DEBUG: Got device list!\n", stderr); + fputs("DEBUG: Getting list of devices...\n", stderr); - cgiSetIPPVars(response, NULL, NULL, NULL, 0); - ippDelete(response); - } + time(&last_device_time); + current_device = 0; + if (cupsGetDevices(http, 30, NULL, (cups_device_cb_t)choose_device_cb, + (void *)title) == IPP_OK) + fputs("DEBUG: Got device list!\n", stderr); else fprintf(stderr, "ERROR: CUPS-Get-Devices request failed with status %x: %s\n", cupsLastError(), cupsLastErrorString()); /* - * Let the user choose... + * Show the final selection page... */ - if ((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", attr->values[0].string.text); - cgiSetVariable("CURRENT_DEVICE_SCHEME", uri); - } - + cgiSetVariable("CUPS_GET_DEVICES_DONE", "1"); cgiStartHTML(title); cgiCopyTemplateLang("choose-device.tmpl"); cgiEndHTML(); + cgiEndMultipart(); } else if (strchr(var, '/') == NULL) { @@ -1072,8 +1114,14 @@ do_am_printer(http_t *http, /* I - HTTP connection */ if ((var = cgiGetVariable("CURRENT_MAKE")) == NULL) var = cgiGetVariable("PPD_MAKE"); if (var) + { ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make", NULL, var); + + if ((var = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, + "ppd-make-and-model", NULL, var); + } else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "ppd-make"); @@ -1123,47 +1171,9 @@ do_am_printer(http_t *http, /* I - HTTP connection */ * Let the user choose a model... */ - const char *make_model; /* Current make/model string */ - - - if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL) - { - /* - * Scan for "close" matches... - */ - - int match, /* Current match */ - best_match, /* Best match so far */ - count; /* Number of drivers */ - const char *best, /* Best matching string */ - *current; /* Current string */ - - - count = cgiGetSize("PPD_MAKE_AND_MODEL"); - - for (i = 0, best_match = 0, best = NULL; i < count; i ++) - { - current = cgiGetArray("PPD_MAKE_AND_MODEL", i); - match = match_string(make_model, current); - - if (match > best_match) - { - best_match = match; - best = current; - } - } - - if (best_match > strlen(var)) - { - /* - * Found a match longer than the make... - */ - - cgiSetVariable("CURRENT_MAKE_AND_MODEL", best); - } - } - cgiStartHTML(title); + cgiSetVariable("CURRENT_MAKE_AND_MODEL", + cgiGetArray("PPD_MAKE_AND_MODEL", 0)); cgiCopyTemplateLang("choose-model.tmpl"); cgiEndHTML(); } @@ -1432,6 +1442,22 @@ do_config_server(http_t *http) /* I - HTTP connection */ /* BrowseLocalProtocols */ remote_protocols[255]; /* BrowseRemoteProtocols */ + const char *current_browse_web_if, + /* BrowseWebIF value */ + *current_preserve_job_history, + /* PreserveJobHistory value */ + *current_preserve_job_files, + /* PreserveJobFiles value */ + *current_max_clients, + /* MaxClients value */ + *current_max_jobs, + /* MaxJobs value */ + *current_max_log_size, + /* MaxLogSize value */ + *current_local_protocols, + /* BrowseLocalProtocols */ + *current_remote_protocols; + /* BrowseRemoteProtocols */ #ifdef HAVE_GSSAPI char default_auth_type[255]; /* DefaultAuthType value */ @@ -1569,6 +1595,42 @@ do_config_server(http_t *http) /* I - HTTP connection */ fprintf(stderr, "DEBUG: DefaultAuthType %s\n", default_auth_type); #endif /* HAVE_GSSAPI */ + if ((current_browse_web_if = cupsGetOption("BrowseWebIF", num_settings, + settings)) == NULL) + current_browse_web_if = "No"; + + if ((current_preserve_job_history = cupsGetOption("PreserveJobHistory", + num_settings, + settings)) == NULL) + current_preserve_job_history = "Yes"; + + if ((current_preserve_job_files = cupsGetOption("PreserveJobFiles", + num_settings, + settings)) == NULL) + current_preserve_job_files = "No"; + + if ((current_max_clients = cupsGetOption("MaxClients", num_settings, + settings)) == NULL) + current_max_clients = "100"; + + if ((current_max_jobs = cupsGetOption("MaxJobs", num_settings, + settings)) == NULL) + current_max_jobs = "500"; + + if ((current_max_log_size = cupsGetOption("MaxLogSize", num_settings, + settings)) == NULL) + current_max_log_size = "1m"; + + if ((current_local_protocols = cupsGetOption("BrowseLocalProtocols", + num_settings, + settings)) == NULL) + current_local_protocols = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; + + if ((current_remote_protocols = cupsGetOption("BrowseRemoteProtocols", + num_settings, + settings)) == NULL) + current_remote_protocols = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS; + /* * See if the settings have changed... */ @@ -1592,25 +1654,14 @@ do_config_server(http_t *http) /* I - HTTP connection */ num_settings, settings)); if (advanced && !changed) - changed = cupsGetOption("BrowseLocalProtocols", num_settings, settings) || - strcasecmp(local_protocols, - CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS) || - cupsGetOption("BrowseRemoteProtocols", num_settings, - settings) || - strcasecmp(remote_protocols, - CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS) || - cupsGetOption("BrowseWebIF", num_settings, settings) || - strcasecmp(browse_web_if, "No") || - cupsGetOption("PreserveJobHistory", num_settings, settings) || - strcasecmp(preserve_job_history, "Yes") || - cupsGetOption("PreserveJobFiles", num_settings, settings) || - strcasecmp(preserve_job_files, "No") || - cupsGetOption("MaxClients", num_settings, settings) || - strcasecmp(max_clients, "100") || - cupsGetOption("MaxJobs", num_settings, settings) || - strcasecmp(max_jobs, "500") || - cupsGetOption("MaxLogSize", num_settings, settings) || - strcasecmp(max_log_size, "1m"); + changed = strcasecmp(local_protocols, current_local_protocols) || + strcasecmp(remote_protocols, current_remote_protocols) || + strcasecmp(browse_web_if, current_browse_web_if) || + strcasecmp(preserve_job_history, current_preserve_job_history) || + strcasecmp(preserve_job_files, current_preserve_job_files) || + strcasecmp(max_clients, current_max_clients) || + strcasecmp(max_jobs, current_max_jobs) || + strcasecmp(max_log_size, current_max_log_size); if (changed) { @@ -1644,37 +1695,29 @@ do_config_server(http_t *http) /* I - HTTP connection */ * Add advanced settings... */ - if (cupsGetOption("BrowseLocalProtocols", num_settings, settings) || - strcasecmp(local_protocols, CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS)) + if (strcasecmp(local_protocols, current_local_protocols)) num_settings = cupsAddOption("BrowseLocalProtocols", local_protocols, num_settings, &settings); - if (cupsGetOption("BrowseRemoteProtocols", num_settings, settings) || - strcasecmp(remote_protocols, CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS)) + if (strcasecmp(remote_protocols, current_remote_protocols)) num_settings = cupsAddOption("BrowseRemoteProtocols", remote_protocols, num_settings, &settings); - if (cupsGetOption("BrowseWebIF", num_settings, settings) || - strcasecmp(browse_web_if, "No")) + if (strcasecmp(browse_web_if, current_browse_web_if)) num_settings = cupsAddOption("BrowseWebIF", browse_web_if, num_settings, &settings); - if (cupsGetOption("PreserveJobHistory", num_settings, settings) || - strcasecmp(preserve_job_history, "Yes")) + if (strcasecmp(preserve_job_history, current_preserve_job_history)) num_settings = cupsAddOption("PreserveJobHistory", preserve_job_history, num_settings, &settings); - if (cupsGetOption("PreserveJobFiles", num_settings, settings) || - strcasecmp(preserve_job_files, "No")) + if (strcasecmp(preserve_job_files, current_preserve_job_files)) num_settings = cupsAddOption("PreserveJobFiles", preserve_job_files, num_settings, &settings); - if (cupsGetOption("MaxClients", num_settings, settings) || - strcasecmp(max_clients, "100")) + if (strcasecmp(max_clients, current_max_clients)) num_settings = cupsAddOption("MaxClients", max_clients, num_settings, &settings); - if (cupsGetOption("MaxJobs", num_settings, settings) || - strcasecmp(max_jobs, "500")) + if (strcasecmp(max_jobs, current_max_jobs)) num_settings = cupsAddOption("MaxJobs", max_jobs, num_settings, &settings); - if (cupsGetOption("MaxLogSize", num_settings, settings) || - strcasecmp(max_log_size, "1m")) + if (strcasecmp(max_log_size, current_max_log_size)) num_settings = cupsAddOption("MaxLogSize", max_log_size, num_settings, &settings); } @@ -1695,7 +1738,10 @@ do_config_server(http_t *http) /* I - HTTP connection */ } else { - cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect"); + if (advanced) + cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&URL=/admin/?ADVANCEDSETTINGS=YES"); + else + cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect"); cgiStartHTML(cgiText(_("Change Settings"))); cgiCopyTemplateLang("restart.tmpl"); } @@ -2681,101 +2727,6 @@ do_menu(http_t *http) /* I - HTTP connection */ } -/* - * 'do_printer_op()' - Do a printer operation. - */ - -static void -do_printer_op(http_t *http, /* I - HTTP connection */ - ipp_op_t op, /* I - Operation to perform */ - const char *title) /* I - Title of page */ -{ - ipp_t *request; /* IPP request */ - char uri[HTTP_MAX_URI]; /* Printer URI */ - const char *printer, /* Printer name (purge-jobs) */ - *is_class; /* Is a class? */ - - - is_class = cgiGetVariable("IS_CLASS"); - printer = cgiGetVariable("PRINTER_NAME"); - - if (!printer) - { - cgiSetVariable("ERROR", cgiText(_("Missing form variable!"))); - cgiStartHTML(title); - cgiCopyTemplateLang("error.tmpl"); - cgiEndHTML(); - return; - } - - /* - * Build a printer request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - */ - - request = ippNewRequest(op); - - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - "localhost", 0, is_class ? "/classes/%s" : "/printers/%s", - printer); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", - NULL, uri); - - /* - * Do the request and get back a response... - */ - - ippDelete(cupsDoRequest(http, request, "/admin/")); - - if (cupsLastError() == IPP_NOT_AUTHORIZED) - { - puts("Status: 401\n"); - exit(0); - } - else if (cupsLastError() > IPP_OK_CONFLICT) - { - cgiStartHTML(title); - cgiShowIPPError(_("Unable to change printer:")); - } - else - { - /* - * Redirect successful updates back to the printer page... - */ - - char url[1024], /* Printer/class URL */ - refresh[1024]; /* Refresh URL */ - - - cgiRewriteURL(uri, url, sizeof(url), NULL); - cgiFormEncode(uri, url, sizeof(uri)); - snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri); - cgiSetVariable("refresh_page", refresh); - - cgiStartHTML(title); - - if (op == IPP_PAUSE_PRINTER) - cgiCopyTemplateLang("printer-stop.tmpl"); - else if (op == IPP_RESUME_PRINTER) - cgiCopyTemplateLang("printer-start.tmpl"); - else if (op == CUPS_ACCEPT_JOBS) - cgiCopyTemplateLang("printer-accept.tmpl"); - else if (op == CUPS_REJECT_JOBS) - cgiCopyTemplateLang("printer-reject.tmpl"); - else if (op == IPP_PURGE_JOBS) - cgiCopyTemplateLang("printer-purge.tmpl"); - else if (op == CUPS_SET_DEFAULT) - cgiCopyTemplateLang("printer-default.tmpl"); - } - - cgiEndHTML(); -} - - /* * 'do_set_allowed_users()' - Set the allowed/denied users for a queue. */ @@ -3042,6 +2993,89 @@ do_set_allowed_users(http_t *http) /* I - HTTP connection */ } +/* + * 'do_set_default()' - Set the server default printer/class. + */ + +static void +do_set_default(http_t *http) /* I - HTTP connection */ +{ + const char *title; /* Page title */ + ipp_t *request; /* IPP request */ + char uri[HTTP_MAX_URI]; /* Printer URI */ + const char *printer, /* Printer name (purge-jobs) */ + *is_class; /* Is a class? */ + + + is_class = cgiGetVariable("IS_CLASS"); + printer = cgiGetVariable("PRINTER_NAME"); + title = cgiText(_("Set As Server Default")); + + if (!printer) + { + cgiSetVariable("ERROR", cgiText(_("Missing form variable!"))); + cgiStartHTML(title); + cgiCopyTemplateLang("error.tmpl"); + cgiEndHTML(); + return; + } + + /* + * Build a printer request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNewRequest(CUPS_SET_DEFAULT); + + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, + "localhost", 0, is_class ? "/classes/%s" : "/printers/%s", + printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + ippDelete(cupsDoRequest(http, request, "/admin/")); + + if (cupsLastError() == IPP_NOT_AUTHORIZED) + { + puts("Status: 401\n"); + exit(0); + } + else if (cupsLastError() > IPP_OK_CONFLICT) + { + cgiStartHTML(title); + cgiShowIPPError(_("Unable to set server default:")); + } + else + { + /* + * Redirect successful updates back to the printer page... + */ + + char url[1024], /* Printer/class URL */ + refresh[1024]; /* Refresh URL */ + + + cgiRewriteURL(uri, url, sizeof(url), NULL); + cgiFormEncode(uri, url, sizeof(uri)); + snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri); + cgiSetVariable("refresh_page", refresh); + + cgiStartHTML(title); + cgiCopyTemplateLang("printer-default.tmpl"); + } + + cgiEndHTML(); +} + + /* * 'do_set_options()' - Configure the default options for a queue. */ @@ -3106,57 +3140,7 @@ do_set_options(http_t *http, /* I - HTTP connection */ if (cgiGetVariable("AUTOCONFIGURE")) { - int job_id; /* Command file job */ - char refresh[1024]; /* Refresh URL */ - http_status_t status; /* Document status */ - static const char *autoconfigure =/* Command file */ - "#CUPS-COMMAND\n" - "AutoConfigure\n"; - - - if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer, "Auto-Configure", - 0, NULL)) < 1) - { - cgiSetVariable("ERROR", cgiText(_("Unable to send auto-configure command " - "to printer driver!"))); - cgiStartHTML(title); - cgiCopyTemplateLang("error.tmpl"); - cgiEndHTML(); - return; - } - - status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, - "AutoConfigure.command", CUPS_FORMAT_COMMAND, 1); - if (status == HTTP_CONTINUE) - status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, autoconfigure, - strlen(autoconfigure)); - if (status == HTTP_CONTINUE) - cupsFinishDocument(CUPS_HTTP_DEFAULT, printer); - - if (cupsLastError() >= IPP_REDIRECTION_OTHER_SITE) - { - cgiSetVariable("ERROR", cupsLastErrorString()); - cgiStartHTML(title); - cgiCopyTemplateLang("error.tmpl"); - cgiEndHTML(); - - cupsCancelJob(printer, job_id); - return; - } - - /* - * Redirect successful updates back to the printer page... - */ - - cgiFormEncode(uri, printer, sizeof(uri)); - snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=/%s/%s", - is_class ? "classes" : "printers", uri); - cgiSetVariable("refresh_page", refresh); - - cgiStartHTML(title); - - cgiCopyTemplateLang("printer-configured.tmpl"); - cgiEndHTML(); + cgiPrintCommand(http, printer, "AutoConfigure", "Set Default Options"); return; } @@ -3217,6 +3201,10 @@ do_set_options(http_t *http, /* I - HTTP connection */ fputs("DEBUG: Showing options...\n", stderr); + /* + * Show auto-configure button if supported... + */ + if (ppd) { if (ppd->num_filters == 0 || @@ -3234,6 +3222,62 @@ do_set_options(http_t *http, /* I - HTTP connection */ } } + /* + * Get the printer attributes... + */ + + request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); + + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, + "localhost", 0, "/printers/%s", printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + response = cupsDoRequest(http, request, "/"); + + /* + * List the groups used as "tabs"... + */ + + i = 0; + + if (ppd) + { + for (group = ppd->groups; + i < ppd->num_groups; + i ++, group ++) + { + cgiSetArray("GROUP_ID", i, group->name); + + if (!strcmp(group->name, "InstallableOptions")) + cgiSetArray("GROUP", i, cgiText(_("Options Installed"))); + else + cgiSetArray("GROUP", i, group->text); + } + } + + if (ippFindAttribute(response, "job-sheets-supported", IPP_TAG_ZERO)) + { + cgiSetArray("GROUP_ID", i, "CUPS_BANNERS"); + cgiSetArray("GROUP", i ++, cgiText(_("Banners"))); + } + + if (ippFindAttribute(response, "printer-error-policy-supported", + IPP_TAG_ZERO) || + ippFindAttribute(response, "printer-op-policy-supported", + IPP_TAG_ZERO)) + { + cgiSetArray("GROUP_ID", i, "CUPS_POLICIES"); + cgiSetArray("GROUP", i ++, cgiText(_("Policies"))); + } + + if ((attr = ippFindAttribute(response, "port-monitor-supported", + IPP_TAG_NAME)) != NULL && attr->num_values > 1) + { + cgiSetArray("GROUP_ID", i, "CUPS_PORT_MONITOR"); + cgiSetArray("GROUP", i, cgiText(_("Port Monitor"))); + } + cgiStartHTML(cgiText(_("Set Printer Options"))); cgiCopyTemplateLang("set-printer-options-header.tmpl"); @@ -3263,6 +3307,8 @@ do_set_options(http_t *http, /* I - HTTP connection */ i > 0; i --, group ++) { + cgiSetVariable("GROUP_ID", group->name); + if (!strcmp(group->name, "InstallableOptions")) cgiSetVariable("GROUP", cgiText(_("Options Installed"))); else @@ -3428,38 +3474,66 @@ do_set_options(http_t *http, /* I - HTTP connection */ } } - /* - * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the - * following attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - */ + if ((attr = ippFindAttribute(response, "job-sheets-supported", + IPP_TAG_ZERO)) != NULL) + { + /* + * Add the job sheets options... + */ - request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); + cgiSetVariable("GROUP_ID", "CUPS_BANNERS"); + cgiSetVariable("GROUP", cgiText(_("Banners"))); + cgiCopyTemplateLang("option-header.tmpl"); - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - "localhost", 0, "/printers/%s", printer); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", - NULL, uri); + 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); + } - /* - * Do the request and get back a response... - */ + attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO); - if ((response = cupsDoRequest(http, request, "/")) != NULL) + cgiSetVariable("KEYWORD", "job_sheets_start"); + cgiSetVariable("KEYTEXT", cgiText(_("Starting Banner"))); + cgiSetVariable("DEFCHOICE", attr != NULL ? + attr->values[0].string.text : ""); + + cgiCopyTemplateLang("option-pickone.tmpl"); + + cgiSetVariable("KEYWORD", "job_sheets_end"); + cgiSetVariable("KEYTEXT", cgiText(_("Ending Banner"))); + cgiSetVariable("DEFCHOICE", attr != NULL && attr->num_values > 1 ? + attr->values[1].string.text : ""); + + cgiCopyTemplateLang("option-pickone.tmpl"); + + cgiCopyTemplateLang("option-trailer.tmpl"); + } + + if (ippFindAttribute(response, "printer-error-policy-supported", + IPP_TAG_ZERO) || + ippFindAttribute(response, "printer-op-policy-supported", + IPP_TAG_ZERO)) { - if ((attr = ippFindAttribute(response, "job-sheets-supported", - IPP_TAG_ZERO)) != NULL) - { - /* - * Add the job sheets options... - */ + /* + * Add the error and operation policy options... + */ - cgiSetVariable("GROUP", cgiText(_("Banners"))); - cgiCopyTemplateLang("option-header.tmpl"); + cgiSetVariable("GROUP_ID", "CUPS_POLICIES"); + cgiSetVariable("GROUP", cgiText(_("Policies"))); + cgiCopyTemplateLang("option-header.tmpl"); + + /* + * Error policy... + */ + attr = ippFindAttribute(response, "printer-error-policy-supported", + IPP_TAG_ZERO); + + if (attr) + { cgiSetSize("CHOICES", attr->num_values); cgiSetSize("TEXT", attr->num_values); for (k = 0; k < attr->num_values; k ++) @@ -3468,136 +3542,80 @@ do_set_options(http_t *http, /* I - HTTP connection */ cgiSetArray("TEXT", k, attr->values[k].string.text); } - attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO); - - cgiSetVariable("KEYWORD", "job_sheets_start"); - cgiSetVariable("KEYTEXT", cgiText(_("Starting Banner"))); - cgiSetVariable("DEFCHOICE", attr != NULL ? - attr->values[0].string.text : ""); + attr = ippFindAttribute(response, "printer-error-policy", + IPP_TAG_ZERO); - cgiCopyTemplateLang("option-pickone.tmpl"); - - cgiSetVariable("KEYWORD", "job_sheets_end"); - cgiSetVariable("KEYTEXT", cgiText(_("Ending Banner"))); - cgiSetVariable("DEFCHOICE", attr != NULL && attr->num_values > 1 ? - attr->values[1].string.text : ""); - - cgiCopyTemplateLang("option-pickone.tmpl"); - - cgiCopyTemplateLang("option-trailer.tmpl"); + cgiSetVariable("KEYWORD", "printer_error_policy"); + cgiSetVariable("KEYTEXT", cgiText(_("Error Policy"))); + cgiSetVariable("DEFCHOICE", attr == NULL ? + "" : attr->values[0].string.text); } - if (ippFindAttribute(response, "printer-error-policy-supported", - IPP_TAG_ZERO) || - ippFindAttribute(response, "printer-op-policy-supported", - IPP_TAG_ZERO)) - { - /* - * Add the error and operation policy options... - */ - - cgiSetVariable("GROUP", cgiText(_("Policies"))); - cgiCopyTemplateLang("option-header.tmpl"); + cgiCopyTemplateLang("option-pickone.tmpl"); - /* - * Error policy... - */ + /* + * Operation policy... + */ - attr = ippFindAttribute(response, "printer-error-policy-supported", - IPP_TAG_ZERO); + attr = ippFindAttribute(response, "printer-op-policy-supported", + IPP_TAG_ZERO); - if (attr) + if (attr) + { + cgiSetSize("CHOICES", attr->num_values); + cgiSetSize("TEXT", attr->num_values); + for (k = 0; k < attr->num_values; k ++) { - 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); - } + cgiSetArray("CHOICES", k, attr->values[k].string.text); + cgiSetArray("TEXT", k, attr->values[k].string.text); + } - attr = ippFindAttribute(response, "printer-error-policy", - IPP_TAG_ZERO); + attr = ippFindAttribute(response, "printer-op-policy", IPP_TAG_ZERO); - cgiSetVariable("KEYWORD", "printer_error_policy"); - cgiSetVariable("KEYTEXT", cgiText(_("Error Policy"))); - cgiSetVariable("DEFCHOICE", attr == NULL ? - "" : attr->values[0].string.text); - } + cgiSetVariable("KEYWORD", "printer_op_policy"); + cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy"))); + cgiSetVariable("DEFCHOICE", attr == NULL ? + "" : attr->values[0].string.text); cgiCopyTemplateLang("option-pickone.tmpl"); - - /* - * Operation policy... - */ - - attr = ippFindAttribute(response, "printer-op-policy-supported", - IPP_TAG_ZERO); - - if (attr) - { - 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, "printer-op-policy", IPP_TAG_ZERO); - - cgiSetVariable("KEYWORD", "printer_op_policy"); - cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy"))); - cgiSetVariable("DEFCHOICE", attr == NULL ? - "" : attr->values[0].string.text); - - cgiCopyTemplateLang("option-pickone.tmpl"); - } - - cgiCopyTemplateLang("option-trailer.tmpl"); } - ippDelete(response); + cgiCopyTemplateLang("option-trailer.tmpl"); } /* * Binary protocol support... */ - if (ppd && ppd->protocols && strstr(ppd->protocols, "BCP")) + if ((attr = ippFindAttribute(response, "port-monitor-supported", + IPP_TAG_NAME)) != NULL && attr->num_values > 1) { - ppdattr = ppdFindAttr(ppd, "cupsProtocol", NULL); + cgiSetVariable("GROUP_ID", "CUPS_PORT_MONITOR"); + cgiSetVariable("GROUP", cgiText(_("Port Monitor"))); - cgiSetVariable("GROUP", cgiText(_("PS Binary Protocol"))); - cgiCopyTemplateLang("option-header.tmpl"); + cgiSetSize("CHOICES", attr->num_values); + cgiSetSize("TEXT", attr->num_values); - cgiSetSize("CHOICES", 2); - cgiSetSize("TEXT", 2); - cgiSetArray("CHOICES", 0, "None"); - cgiSetArray("TEXT", 0, cgiText(_("None"))); - - if (strstr(ppd->protocols, "TBCP")) - { - cgiSetArray("CHOICES", 1, "TBCP"); - cgiSetArray("TEXT", 1, "TBCP"); - } - else + for (i = 0; i < attr->num_values; i ++) { - cgiSetArray("CHOICES", 1, "BCP"); - cgiSetArray("TEXT", 1, "BCP"); + cgiSetArray("CHOICES", i, attr->values[i].string.text); + cgiSetArray("TEXT", i, attr->values[i].string.text); } - cgiSetVariable("KEYWORD", "protocol"); - cgiSetVariable("KEYTEXT", cgiText(_("PS Binary Protocol"))); - cgiSetVariable("DEFCHOICE", ppdattr ? ppdattr->value : "None"); + attr = ippFindAttribute(response, "port-monitor", IPP_TAG_NAME); + cgiSetVariable("KEYWORD", "port_monitor"); + cgiSetVariable("KEYTEXT", cgiText(_("Port Monitor"))); + cgiSetVariable("DEFCHOICE", attr ? attr->values[0].string.text : "none"); + cgiCopyTemplateLang("option-header.tmpl"); cgiCopyTemplateLang("option-pickone.tmpl"); - cgiCopyTemplateLang("option-trailer.tmpl"); } cgiCopyTemplateLang("set-printer-options-trailer.tmpl"); cgiEndHTML(); + + ippDelete(response); } else { @@ -3634,7 +3652,7 @@ do_set_options(http_t *http, /* I - HTTP connection */ while (cupsFileGets(in, line, sizeof(line))) { - if (!strncmp(line, "*cupsProtocol:", 14) && cgiGetVariable("protocol")) + if (!strncmp(line, "*cupsProtocol:", 14)) continue; else if (strncmp(line, "*Default", 8)) cupsFilePrintf(out, "%s\n", line); @@ -3666,13 +3684,6 @@ do_set_options(http_t *http, /* I - HTTP connection */ } } - /* - * TODO: We need to set the port-monitor attribute! - */ - - if ((var = cgiGetVariable("protocol")) != NULL) - cupsFilePrintf(out, "*cupsProtocol: %s\n", var); - cupsFileClose(in); cupsFileClose(out); } @@ -3717,6 +3728,10 @@ do_set_options(http_t *http, /* I - HTTP connection */ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-op-policy", NULL, var); + if ((var = cgiGetVariable("port_monitor")) != NULL) + ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, + "port-monitor", NULL, var); + /* * Do the request and get back a response... */ @@ -4148,54 +4163,5 @@ get_points(double number, /* I - Original number */ /* - * 'match_string()' - Return the number of matching characters. - */ - -static int /* O - Number of matching characters */ -match_string(const char *a, /* I - First string */ - const char *b) /* I - Second string */ -{ - int count; /* Number of matching characters */ - - - /* - * Loop through both strings until we hit the end of either or we find - * a non-matching character. For the purposes of comparison, we ignore - * whitespace and do a case-insensitive comparison so that we have a - * better chance of finding a match... - */ - - for (count = 0; *a && *b; a++, b++, count ++) - { - /* - * Skip leading whitespace characters... - */ - - while (isspace(*a & 255)) - a ++; - - while (isspace(*b & 255)) - b ++; - - /* - * Break out if we run out of characters... - */ - - if (!*a || !*b) - break; - - /* - * Do a case-insensitive comparison of the next two chars... - */ - - if (tolower(*a & 255) != tolower(*b & 255)) - break; - } - - return (count); -} - - -/* - * End of "$Id: admin.c 7888 2008-08-29 21:16:56Z mike $". + * End of "$Id: admin.c 8029 2008-10-08 21:07:45Z mike $". */ diff --git a/cgi-bin/cgi.h b/cgi-bin/cgi.h index 9f462dd20..66de5110a 100644 --- a/cgi-bin/cgi.h +++ b/cgi-bin/cgi.h @@ -3,7 +3,7 @@ * * CGI support library definitions. * - * 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 @@ -59,6 +59,7 @@ extern void cgiCopyTemplateFile(FILE *out, const char *tmpl); extern void cgiCopyTemplateLang(const char *tmpl); extern int cgiDoSearch(void *search, const char *text); extern void cgiEndHTML(void); +extern void cgiEndMultipart(void); extern char *cgiFormEncode(char *dst, const char *src, size_t dstsize); extern void cgiFreeSearch(void *search); extern const char *cgiGetArray(const char *name, int element); @@ -72,6 +73,8 @@ extern const char *cgiGetVariable(const char *name); extern int cgiInitialize(void); extern int cgiIsPOST(void); extern void cgiMoveJobs(http_t *http, const char *dest, int job_id); +extern void cgiPrintCommand(http_t *http, const char *dest, + const char *command, const char *title); extern void cgiPrintTestPage(http_t *http, const char *dest); extern char *cgiRewriteURL(const char *uri, char *url, int urlsize, const char *newresource); @@ -91,6 +94,7 @@ extern void cgiSetVariable(const char *name, const char *value); extern void cgiShowIPPError(const char *message); extern void cgiShowJobs(http_t *http, const char *dest); extern void cgiStartHTML(const char *title); +extern void cgiStartMultipart(void); extern const char *cgiText(const char *message); #endif /* !_CUPS_CGI_H_ */ diff --git a/cgi-bin/classes.c b/cgi-bin/classes.c index 28aa7a925..fa4b49edc 100644 --- a/cgi-bin/classes.c +++ b/cgi-bin/classes.c @@ -14,9 +14,6 @@ * * Contents: * - * main() - Main entry for CGI. - * show_all_classes() - Show all classes... - * show_class() - Show a single class. */ /* @@ -30,8 +27,10 @@ * Local functions... */ -void show_all_classes(http_t *http, const char *username); -void show_class(http_t *http, const char *printer); +static void do_class_op(http_t *http, const char *printer, ipp_op_t op, + const char *title); +static void show_all_classes(http_t *http, const char *username); +static void show_class(http_t *http, const char *printer); /* @@ -80,6 +79,9 @@ main(int argc, /* I - Number of command-line arguments */ if (!*pclass) pclass = NULL; + + if (pclass) + cgiSetVariable("PRINTER_NAME", pclass); } /* @@ -138,21 +140,40 @@ main(int argc, /* I - Number of command-line arguments */ else show_class(http, pclass); } - else if (!strcasecmp(op, "print-test-page") && pclass) - cgiPrintTestPage(http, pclass); - else if (!strcasecmp(op, "move-jobs") && pclass) - cgiMoveJobs(http, pclass, 0); + else if (pclass) + { + if (!strcmp(op, "start-class")) + do_class_op(http, pclass, IPP_RESUME_PRINTER, cgiText(_("Resume Class"))); + else if (!strcmp(op, "stop-class")) + do_class_op(http, pclass, IPP_PAUSE_PRINTER, cgiText(_("Pause Class"))); + else if (!strcmp(op, "accept-jobs")) + do_class_op(http, pclass, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs"))); + else if (!strcmp(op, "reject-jobs")) + do_class_op(http, pclass, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs"))); + else if (!strcmp(op, "purge-jobs")) + do_class_op(http, pclass, IPP_PURGE_JOBS, cgiText(_("Purge Jobs"))); + else if (!strcasecmp(op, "print-test-page")) + cgiPrintTestPage(http, pclass); + else if (!strcasecmp(op, "move-jobs")) + cgiMoveJobs(http, pclass, 0); + else + { + /* + * Unknown/bad operation... + */ + + cgiStartHTML(pclass); + cgiCopyTemplateLang("error-op.tmpl"); + cgiEndHTML(); + } + } else { /* * Unknown/bad operation... */ - if (pclass) - cgiStartHTML(pclass); - else - cgiStartHTML(cgiText(_("Classes"))); - + cgiStartHTML(cgiText(_("Classes"))); cgiCopyTemplateLang("error-op.tmpl"); cgiEndHTML(); } @@ -171,11 +192,94 @@ main(int argc, /* I - Number of command-line arguments */ } +/* + * 'do_class_op()' - Do a class operation. + */ + +static void +do_class_op(http_t *http, /* I - HTTP connection */ + const char *printer, /* I - Printer name */ + ipp_op_t op, /* I - Operation to perform */ + const char *title) /* I - Title of page */ +{ + ipp_t *request; /* IPP request */ + char uri[HTTP_MAX_URI], /* Printer URI */ + resource[HTTP_MAX_URI]; /* Path for request */ + + + /* + * Build a printer request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNewRequest(op); + + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, + "localhost", 0, "/classes/%s", printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Do the request and get back a response... + */ + + snprintf(resource, sizeof(resource), "/classes/%s", printer); + ippDelete(cupsDoRequest(http, request, resource)); + + if (cupsLastError() == IPP_NOT_AUTHORIZED) + { + puts("Status: 401\n"); + exit(0); + } + else if (cupsLastError() > IPP_OK_CONFLICT) + { + cgiStartHTML(title); + cgiShowIPPError(_("Unable to do maintenance command:")); + } + else + { + /* + * Redirect successful updates back to the printer page... + */ + + char url[1024], /* Printer/class URL */ + refresh[1024]; /* Refresh URL */ + + + cgiRewriteURL(uri, url, sizeof(url), NULL); + cgiFormEncode(uri, url, sizeof(uri)); + snprintf(refresh, sizeof(refresh), "5;URL=%s", uri); + cgiSetVariable("refresh_page", refresh); + + cgiStartHTML(title); + + cgiSetVariable("IS_CLASS", "YES"); + + if (op == IPP_PAUSE_PRINTER) + cgiCopyTemplateLang("printer-stop.tmpl"); + else if (op == IPP_RESUME_PRINTER) + cgiCopyTemplateLang("printer-start.tmpl"); + else if (op == CUPS_ACCEPT_JOBS) + cgiCopyTemplateLang("printer-accept.tmpl"); + else if (op == CUPS_REJECT_JOBS) + cgiCopyTemplateLang("printer-reject.tmpl"); + else if (op == IPP_PURGE_JOBS) + cgiCopyTemplateLang("printer-purge.tmpl"); + } + + cgiEndHTML(); +} + + /* * 'show_all_classes()' - Show all classes... */ -void +static void show_all_classes(http_t *http, /* I - Connection to server */ const char *user) /* I - Username */ { @@ -335,7 +439,7 @@ show_all_classes(http_t *http, /* I - Connection to server */ * 'show_class()' - Show a single class. */ -void +static void show_class(http_t *http, /* I - Connection to server */ const char *pclass) /* I - Name of class */ { @@ -407,7 +511,6 @@ show_class(http_t *http, /* I - Connection to server */ * Show the class status... */ - cgiSetVariable("_SINGLE_DEST", "1"); cgiCopyTemplateLang("class.tmpl"); /* diff --git a/cgi-bin/html.c b/cgi-bin/html.c index 4382e152a..e99245868 100644 --- a/cgi-bin/html.c +++ b/cgi-bin/html.c @@ -3,7 +3,7 @@ * * HTML support functions 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 @@ -14,10 +14,12 @@ * * Contents: * - * cgiEndHTML() - End a HTML page. - * cgiFormEncode() - Encode a string as a form variable... - * cgiStartHTML() - Start a HTML page. - * cgi_null_passwd() - Return a NULL password for authentication. + * cgiEndHTML() - End a HTML page. + * cgiEndMultipart() - End the delivery of a multipart web page. + * cgiFormEncode() - Encode a string as a form variable... + * cgiStartHTML() - Start a HTML page. + * cgiStartMultipart() - Start a multipart delivery of a web page... + * cgi_null_passwd() - Return a NULL password for authentication. */ /* @@ -27,6 +29,14 @@ #include "cgi-private.h" +/* + * Local globals... + */ + +static const char *cgi_multipart = NULL; + /* Multipart separator, if any */ + + /* * Local functions... */ @@ -49,6 +59,18 @@ cgiEndHTML(void) } +/* + * 'cgiEndMultipart()' - End the delivery of a multipart web page. + */ + +void +cgiEndMultipart(void) +{ + if (cgi_multipart) + printf("\n%s--\n", cgi_multipart); +} + + /* * 'cgiFormEncode()' - Encode a string as a form variable... */ @@ -144,6 +166,9 @@ cgiStartHTML(const char *title) /* I - Title of page */ * Tell the client to expect UTF-8 encoded HTML... */ + if (cgi_multipart) + puts(cgi_multipart); + puts("Content-Type: text/html;charset=utf-8\n"); /* @@ -157,6 +182,19 @@ cgiStartHTML(const char *title) /* I - Title of page */ } +/* + * 'cgiStartMultipart()' - Start a multipart delivery of a web page... + */ + +void +cgiStartMultipart(void) +{ + puts("MIME-Version: 1.0"); + puts("Content-Type: multipart/x-mixed-replace; boundary=\"CUPS-MULTIPART\"\n"); + cgi_multipart = "--CUPS-MULTIPART"; +} + + /* * 'cgi_null_passwd()' - Return a NULL password for authentication. */ diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c index 95305030e..7b24fe53d 100644 --- a/cgi-bin/ipp-var.c +++ b/cgi-bin/ipp-var.c @@ -14,10 +14,11 @@ * * Contents: * - * cgiGetAttributes() - Get the list of attributes that are needed - * by the template file. + * cgiGetAttributes() - Get the list of attributes that are needed by the + * template file. * cgiGetIPPObjects() - Get the objects in an IPP response. * cgiMoveJobs() - Move one or more jobs. + * cgiPrintCommand() - Print a CUPS command job. * cgiPrintTestPage() - Print a test page. * cgiRewriteURL() - Rewrite a printer URI into a web browser URL... * cgiSetIPPObjectVars() - Set CGI variables from an IPP object. @@ -113,7 +114,7 @@ cgiGetAttributes(ipp_t *request, /* I - IPP request */ */ for (nameptr = name; (ch = getc(in)) != EOF;) - if (strchr("}]<>=! \t\n", ch)) + if (strchr("}]<>=!~ \t\n", ch)) break; else if (nameptr > name && ch == '?') break; @@ -509,6 +510,155 @@ cgiMoveJobs(http_t *http, /* I - Connection to server */ } +/* + * 'cgiPrintCommand()' - Print a CUPS command job. + */ + +void +cgiPrintCommand(http_t *http, /* I - Connection to server */ + const char *dest, /* I - Destination printer */ + const char *command, /* I - Command to send */ + const char *title) /* I - Page/job title */ +{ + int job_id; /* Command file job */ + char uri[HTTP_MAX_URI], /* Job URI */ + resource[1024], /* Printer resource path */ + refresh[1024], /* Refresh URL */ + command_file[1024]; /* Command "file" */ + http_status_t status; /* Document status */ + cups_option_t hold_option; /* job-hold-until option */ + const char *user; /* User name */ + ipp_t *request, /* Get-Job-Attributes request */ + *response; /* Get-Job-Attributes response */ + ipp_attribute_t *attr; /* Current job attribute */ + static const char const *job_attrs[] =/* Job attributes we want */ + { + "job-state", + "job-printer-state-message" + }; + + + /* + * Create the CUPS command file... + */ + + snprintf(command_file, sizeof(command_file), "#CUPS-COMMAND\n%s\n", command); + + /* + * Show status... + */ + + cgiStartMultipart(); + cgiStartHTML(title); + cgiCopyTemplateLang("command.tmpl"); + cgiEndHTML(); + fflush(stdout); + + /* + * Send the command file job... + */ + + hold_option.name = "job-hold-until"; + hold_option.value = "no-hold"; + + if ((user = getenv("REMOTE_USER")) != NULL) + cupsSetUser(user); + else + cupsSetUser("anonymous"); + + if ((job_id = cupsCreateJob(http, dest, title, + 1, &hold_option)) < 1) + { + cgiSetVariable("MESSAGE", cgiText(_("Unable to send command to printer driver!"))); + cgiSetVariable("ERROR", cupsLastErrorString()); + cgiStartHTML(title); + cgiCopyTemplateLang("error.tmpl"); + cgiEndHTML(); + cgiEndMultipart(); + return; + } + + status = cupsStartDocument(http, dest, job_id, NULL, CUPS_FORMAT_COMMAND, 1); + if (status == HTTP_CONTINUE) + status = cupsWriteRequestData(http, command_file, + strlen(command_file)); + if (status == HTTP_CONTINUE) + cupsFinishDocument(http, dest); + + if (cupsLastError() >= IPP_REDIRECTION_OTHER_SITE) + { + cgiSetVariable("MESSAGE", cgiText(_("Unable to send command to printer driver!"))); + cgiSetVariable("ERROR", cupsLastErrorString()); + cgiStartHTML(title); + cgiCopyTemplateLang("error.tmpl"); + cgiEndHTML(); + cgiEndMultipart(); + + cupsCancelJob(dest, job_id); + return; + } + + /* + * Wait for the job to complete... + */ + + for (;;) + { + /* + * Get the current job state... + */ + + snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", job_id); + request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", + NULL, uri); + if (user) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requesting-user-name", NULL, user); + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "requested-attributes", 2, NULL, job_attrs); + + if ((response = cupsDoRequest(http, request, "/")) != NULL) + cgiSetIPPVars(response, NULL, NULL, NULL, 0); + + attr = ippFindAttribute(response, "job-state", IPP_TAG_ENUM); + if (!attr || attr->values[0].integer >= IPP_JOB_STOPPED) + { + ippDelete(response); + break; + } + + /* + * Job not complete, so update the status... + */ + + ippDelete(response); + + cgiStartHTML(title); + cgiCopyTemplateLang("command.tmpl"); + cgiEndHTML(); + fflush(stdout); + + sleep(5); + } + + /* + * Send the final page that reloads the printer's page... + */ + + snprintf(resource, sizeof(resource), "/printers/%s", dest); + + cgiFormEncode(uri, resource, sizeof(uri)); + snprintf(refresh, sizeof(refresh), "5;URL=%s", uri); + cgiSetVariable("refresh_page", refresh); + + cgiStartHTML(title); + cgiCopyTemplateLang("command.tmpl"); + cgiEndHTML(); + cgiEndMultipart(); +} + + /* * 'cgiPrintTestPage()' - Print a test page. */ @@ -561,7 +711,6 @@ cgiPrintTestPage(http_t *http, /* I - Connection to server */ * attributes-natural-language * printer-uri * requesting-user-name - * document-format */ request = ippNewRequest(IPP_PRINT_JOB); @@ -576,9 +725,6 @@ cgiPrintTestPage(http_t *http, /* I - Connection to server */ 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... */ diff --git a/cgi-bin/libcupscgi.exp b/cgi-bin/libcupscgi.exp index 42373d7ff..efe0ac7e3 100644 --- a/cgi-bin/libcupscgi.exp +++ b/cgi-bin/libcupscgi.exp @@ -4,6 +4,7 @@ _cgiCopyTemplateFile _cgiCopyTemplateLang _cgiDoSearch _cgiEndHTML +_cgiEndMultipart _cgiFormEncode _cgiFreeSearch _cgiGetArray @@ -16,6 +17,7 @@ _cgiGetVariable _cgiInitialize _cgiIsPOST _cgiMoveJobs +_cgiPrintCommand _cgiPrintTestPage _cgiRewriteURL _cgiSetArray @@ -27,6 +29,7 @@ _cgiSetVariable _cgiShowIPPError _cgiShowJobs _cgiStartHTML +_cgiStartMultipart _cgiText _helpDeleteIndex _helpFindNode diff --git a/cgi-bin/printers.c b/cgi-bin/printers.c index 131174263..d3e0224fd 100644 --- a/cgi-bin/printers.c +++ b/cgi-bin/printers.c @@ -14,10 +14,6 @@ * * Contents: * - * main() - Main entry for CGI. - * print_command() - Send a print command to the printer. - * show_all_printers() - Show all printers... - * show_printer() - Show a single printer. */ /* @@ -32,9 +28,10 @@ * Local functions... */ -void print_command(http_t *http, const char *printer, const char *command); -void show_all_printers(http_t *http, const char *username); -void show_printer(http_t *http, const char *printer); +static void do_printer_op(http_t *http, const char *printer, ipp_op_t op, + const char *title); +static void show_all_printers(http_t *http, const char *username); +static void show_printer(http_t *http, const char *printer); /* @@ -83,6 +80,9 @@ main(int argc, /* I - Number of command-line arguments */ if (!*printer) printer = NULL; + + if (printer) + cgiSetVariable("PRINTER_NAME", printer); } /* @@ -141,25 +141,48 @@ main(int argc, /* I - Number of command-line arguments */ else show_printer(http, printer); } - else if (!strcasecmp(op, "print-self-test-page") && printer) - print_command(http, printer, "PrintSelfTestPage"); - else if (!strcasecmp(op, "clean-print-heads") && printer) - print_command(http, printer, "Clean all"); - else if (!strcasecmp(op, "print-test-page") && printer) - cgiPrintTestPage(http, printer); - else if (!strcasecmp(op, "move-jobs") && printer) - cgiMoveJobs(http, printer, 0); + else if (printer) + { + if (!strcmp(op, "start-printer")) + do_printer_op(http, printer, IPP_RESUME_PRINTER, + cgiText(_("Resume Printer"))); + else if (!strcmp(op, "stop-printer")) + do_printer_op(http, printer, IPP_PAUSE_PRINTER, + cgiText(_("Pause Printer"))); + else if (!strcmp(op, "accept-jobs")) + do_printer_op(http, printer, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs"))); + else if (!strcmp(op, "reject-jobs")) + do_printer_op(http, printer, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs"))); + else if (!strcmp(op, "purge-jobs")) + do_printer_op(http, printer, IPP_PURGE_JOBS, cgiText(_("Purge Jobs"))); + else if (!strcasecmp(op, "print-self-test-page")) + cgiPrintCommand(http, printer, "PrintSelfTestPage", + cgiText(_("Print Self-Test Page"))); + else if (!strcasecmp(op, "clean-print-heads")) + cgiPrintCommand(http, printer, "Clean all", + cgiText(_("Clean Print Heads"))); + else if (!strcasecmp(op, "print-test-page")) + cgiPrintTestPage(http, printer); + else if (!strcasecmp(op, "move-jobs")) + cgiMoveJobs(http, printer, 0); + else + { + /* + * Unknown/bad operation... + */ + + cgiStartHTML(printer); + cgiCopyTemplateLang("error-op.tmpl"); + cgiEndHTML(); + } + } else { /* * Unknown/bad operation... */ - if (printer) - cgiStartHTML(printer); - else - cgiStartHTML(cgiText(_("Printers"))); - + cgiStartHTML(cgiText(_("Printers"))); cgiCopyTemplateLang("error-op.tmpl"); cgiEndHTML(); } @@ -179,122 +202,80 @@ main(int argc, /* I - Number of command-line arguments */ /* - * 'print_command()' - Send a print command to the printer. + * 'do_printer_op()' - Do a printer operation. */ -void -print_command(http_t *http, /* I - Connection to server */ - const char *printer, /* I - Printer */ - const char *command) /* I - Command to send */ +static void +do_printer_op(http_t *http, /* I - HTTP connection */ + const char *printer, /* I - Printer name */ + ipp_op_t op, /* I - Operation to perform */ + const char *title) /* I - Title of page */ { - cups_file_t *fp; /* File pointer */ - char filename[1024]; /* Temporary file */ - ipp_t *request, /* IPP request */ - *response; /* IPP response */ + ipp_t *request; /* IPP request */ char uri[HTTP_MAX_URI], /* Printer URI */ - resource[1024], /* POST resource path */ - refresh[1024]; /* Refresh URL */ - const char *user; /* Username */ - - - /* - * See who is logged in... - */ - - if ((user = getenv("REMOTE_USER")) == NULL) - user = "guest"; - - /* - * Create the CUPS command file to print... - */ - - if ((fp = cupsTempFile2(filename, sizeof(filename))) == NULL) - { - cgiStartHTML(cgiText(_("Printer Maintenance"))); - cgiSetVariable("MESSAGE", _("Unable to create temporary file:")); - cgiSetVariable("ERROR", strerror(errno)); - cgiCopyTemplateLang("error.tmpl"); - cgiEndHTML(); - return; - } - - cupsFilePuts(fp, "#CUPS-COMMAND\n"); - cupsFilePrintf(fp, "%s\n", command); - cupsFileClose(fp); - - /* - * Point to the printer... - */ - - snprintf(resource, sizeof(resource), "/printers/%s", printer); + resource[HTTP_MAX_URI]; /* Path for request */ - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - "localhost", ippPort(), "/printers/%s", printer); /* - * Build an IPP_PRINT_JOB request, which requires the following + * Build a printer request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri - * requesting-user-name - * document-format */ - request = ippNewRequest(IPP_PRINT_JOB); + request = ippNewRequest(op); + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, + "localhost", 0, "/printers/%s", printer); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requesting-user-name", NULL, user); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", - NULL, "Printer Maintenance"); - - 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, resource, - filename)) != NULL) - { - cgiSetIPPVars(response, NULL, NULL, NULL, 0); + snprintf(resource, sizeof(resource), "/printers/%s", printer); + ippDelete(cupsDoRequest(http, request, resource)); - ippDelete(response); + if (cupsLastError() == IPP_NOT_AUTHORIZED) + { + puts("Status: 401\n"); + exit(0); } - - unlink(filename); - - if (cupsLastError() <= IPP_OK_CONFLICT) + else if (cupsLastError() > IPP_OK_CONFLICT) + { + cgiStartHTML(title); + cgiShowIPPError(_("Unable to do maintenance command:")); + } + else { /* - * Automatically reload the printer status page... + * Redirect successful updates back to the printer page... */ - cgiFormEncode(uri, resource, sizeof(uri)); - snprintf(refresh, sizeof(refresh), "2;URL=%s", uri); - cgiSetVariable("refresh_page", refresh); - } - else if (cupsLastError() == IPP_NOT_AUTHORIZED) - { - puts("Status: 401\n"); - exit(0); - } + char url[1024], /* Printer/class URL */ + refresh[1024]; /* Refresh URL */ - cgiStartHTML(cgiText(_("Printer Maintenance"))); - if (cupsLastError() > IPP_OK_CONFLICT) - cgiShowIPPError(_("Unable to send maintenance job:")); - else - { - cgiSetVariable("PRINTER_NAME", printer); + cgiRewriteURL(uri, url, sizeof(url), NULL); + cgiFormEncode(uri, url, sizeof(uri)); + snprintf(refresh, sizeof(refresh), "5;URL=q%s", uri); + cgiSetVariable("refresh_page", refresh); - cgiCopyTemplateLang("maintenance.tmpl"); + cgiStartHTML(title); + + if (op == IPP_PAUSE_PRINTER) + cgiCopyTemplateLang("printer-stop.tmpl"); + else if (op == IPP_RESUME_PRINTER) + cgiCopyTemplateLang("printer-start.tmpl"); + else if (op == CUPS_ACCEPT_JOBS) + cgiCopyTemplateLang("printer-accept.tmpl"); + else if (op == CUPS_REJECT_JOBS) + cgiCopyTemplateLang("printer-reject.tmpl"); + else if (op == IPP_PURGE_JOBS) + cgiCopyTemplateLang("printer-purge.tmpl"); } cgiEndHTML(); @@ -305,7 +286,7 @@ print_command(http_t *http, /* I - Connection to server */ * 'show_all_printers()' - Show all printers... */ -void +static void show_all_printers(http_t *http, /* I - Connection to server */ const char *user) /* I - Username */ { @@ -408,42 +389,14 @@ show_all_printers(http_t *http, /* I - Connection to server */ for (i = 0, printer = (ipp_attribute_t *)cupsArrayIndex(printers, first); i < CUPS_PAGE_MAX && printer; i ++, printer = (ipp_attribute_t *)cupsArrayNext(printers)) - { cgiSetIPPObjectVars(printer, NULL, i); - - cgiSetArray("cupscommand", i, "0"); - - for (attr = printer; attr; attr = attr->next) - if (attr->group_tag != IPP_TAG_PRINTER || !attr->name) - break; - else if (!strcmp(attr->name, "printer-type")) - { - if (attr->values[0].integer & CUPS_PRINTER_COMMANDS) - cgiSetArray("cupscommand", i, "1"); - break; - } - } } else { for (i = 0, printer = (ipp_attribute_t *)cupsArrayIndex(printers, count - first - 1); i < CUPS_PAGE_MAX && printer; i ++, printer = (ipp_attribute_t *)cupsArrayPrev(printers)) - { cgiSetIPPObjectVars(printer, NULL, i); - - cgiSetArray("cupscommand", i, "0"); - - for (attr = printer; attr; attr = attr->next) - if (attr->group_tag == IPP_TAG_ZERO || !attr->name) - break; - else if (!strcmp(attr->name, "printer-type")) - { - if (attr->values[0].integer & CUPS_PRINTER_COMMANDS) - cgiSetArray("cupscommand", i, "1"); - break; - } - } } /* @@ -504,7 +457,7 @@ show_all_printers(http_t *http, /* I - Connection to server */ * 'show_printer()' - Show a single printer. */ -void +static void show_printer(http_t *http, /* I - Connection to server */ const char *printer) /* I - Name of printer */ { @@ -549,14 +502,6 @@ show_printer(http_t *http, /* I - Connection to server */ cgiSetIPPVars(response, NULL, NULL, NULL, 0); - if ((attr = ippFindAttribute(response, "printer-type", - IPP_TAG_ENUM)) != NULL) - { - cgiSetVariable("cupscommand", - (attr->values[0].integer & CUPS_PRINTER_COMMANDS) ? - "1" : "0"); - } - if (printer && (attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL && attr->values[0].integer == IPP_PRINTER_PROCESSING) @@ -587,7 +532,6 @@ show_printer(http_t *http, /* I - Connection to server */ * Show the printer status... */ - cgiSetVariable("_SINGLE_DEST", "1"); cgiCopyTemplateLang("printer.tmpl"); /* diff --git a/cgi-bin/var.c b/cgi-bin/var.c index 7ceb3ecaa..164144a27 100644 --- a/cgi-bin/var.c +++ b/cgi-bin/var.c @@ -925,7 +925,7 @@ cgi_initialize_string(const char *data) /* I - Form data string */ if (s > value) s --; - while (s >= value && *s == ' ') + while (s >= value && isspace(*s & 255)) *s-- = '\0'; /* diff --git a/conf/mime.convs.in b/conf/mime.convs.in index 36c7b9c7e..9416b2de7 100644 --- a/conf/mime.convs.in +++ b/conf/mime.convs.in @@ -62,7 +62,7 @@ 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 -application/vnd.cups-banner application/vnd.cups-postscript 33 bannertops +application/vnd.cups-banner application/postscript 33 bannertops ######################################################################## # diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index b112418ec..f04fcc5a6 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -286,7 +286,7 @@ LEGACY_BACKENDS="parallel scsi" case $uname in Darwin*) - FONTS="" +# FONTS="" LEGACY_BACKENDS="" BACKLIBS="$BACKLIBS -framework IOKit" CUPSDLIBS="$CUPSDLIBS -sectorder __TEXT __text cupsd.order -e start -framework IOKit -framework SystemConfiguration -weak_framework ApplicationServices" diff --git a/cups/adminutil.c b/cups/adminutil.c index dc62951ad..4d4eba8f1 100644 --- a/cups/adminutil.c +++ b/cups/adminutil.c @@ -1794,8 +1794,7 @@ _cupsAdminSetServerSettings( else if ((((in_admin_location || in_conf_location || in_root_location) && remote_admin >= 0) || (in_root_location && share_printers >= 0)) && - (((!strcasecmp(line, "Allow") || !strcasecmp(line, "Deny")) && - !strcasecmp(value, "@LOCAL")) || + (!strcasecmp(line, "Allow") || !strcasecmp(line, "Deny") || !strcasecmp(line, "Order"))) continue; else if (in_cancel_job == 2) diff --git a/cups/file.c b/cups/file.c index 815e1d3c5..bbaac6fe0 100644 --- a/cups/file.c +++ b/cups/file.c @@ -1253,6 +1253,67 @@ cupsFilePutChar(cups_file_t *fp, /* I - CUPS file */ } +/* + * 'cupsFilePutConf()' - Write a configuration line. + * + * This function handles any comment escaping of the value. + * + * @since CUPS 1.4@ + */ + +ssize_t /* O - Number of bytes written or -1 on error */ +cupsFilePutConf(cups_file_t *fp, /* I - CUPS file */ + const char *directive, /* I - Directive */ + const char *value) /* I - Value */ +{ + ssize_t bytes, /* Number of bytes written */ + temp; /* Temporary byte count */ + const char *ptr; /* Pointer into value */ + + + if (!fp || !directive || !*directive) + return (-1); + + if ((bytes = cupsFilePuts(fp, directive)) < 0) + return (-1); + + if (cupsFilePutChar(fp, ' ') < 0) + return (-1); + bytes ++; + + if (value && *value) + { + if ((ptr = strchr(value, '#')) != NULL) + { + /* + * Need to quote the first # in the info string... + */ + + if ((temp = cupsFileWrite(fp, value, ptr - value)) < 0) + return (-1); + bytes += temp; + + if (cupsFilePutChar(fp, '\\') < 0) + return (-1); + bytes ++; + + if ((temp = cupsFilePuts(fp, ptr)) < 0) + return (-1); + bytes += temp; + } + else if ((temp = cupsFilePuts(fp, value)) < 0) + return (-1); + else + bytes += temp; + } + + if (cupsFilePutChar(fp, '\n') < 0) + return (-1); + else + return (bytes + 1); +} + + /* * 'cupsFilePuts()' - Write a string. * diff --git a/cups/file.h b/cups/file.h index 53356d68a..c8a2b4667 100644 --- a/cups/file.h +++ b/cups/file.h @@ -8,7 +8,7 @@ * our own file functions allows us to provide transparent support of * gzip'd print files, PPD files, etc. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -87,6 +87,8 @@ __attribute__ ((__format__ (__printf__, 2, 3))) #endif /* __GNUC__ */ _CUPS_API_1_2; extern int cupsFilePutChar(cups_file_t *fp, int c) _CUPS_API_1_2; +extern ssize_t cupsFilePutConf(cups_file_t *fp, const char *directive, + const char *value) _CUPS_API_1_4; extern int cupsFilePuts(cups_file_t *fp, const char *s) _CUPS_API_1_2; extern ssize_t cupsFileRead(cups_file_t *fp, char *buf, size_t bytes) _CUPS_API_1_2; extern off_t cupsFileRewind(cups_file_t *fp) _CUPS_API_1_2; diff --git a/cups/libcups.exp b/cups/libcups.exp index 4908e8bbc..92d2f9c91 100644 --- a/cups/libcups.exp +++ b/cups/libcups.exp @@ -120,6 +120,7 @@ _cupsFileOpenFd _cupsFilePeekChar _cupsFilePrintf _cupsFilePutChar +_cupsFilePutConf _cupsFilePuts _cupsFileRead _cupsFileRewind diff --git a/cups/testhttp.c b/cups/testhttp.c index 9bb4dbedb..a197d5a87 100644 --- a/cups/testhttp.c +++ b/cups/testhttp.c @@ -323,6 +323,10 @@ main(int argc, /* I - Number of command-line arguments */ httpAddrFreeList(addrlist); } + else if (isdigit(hostname[0] & 255)) + { + puts("FAIL (ignored because hostname is numeric)"); + } else { failures ++; diff --git a/cups/testi18n.c b/cups/testi18n.c index b18b64668..0ea419d3a 100644 --- a/cups/testi18n.c +++ b/cups/testi18n.c @@ -3,7 +3,7 @@ * * Internationalization test for 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 @@ -537,11 +537,21 @@ static void print_utf8(const char *msg, /* I - Message String */ const cups_utf8_t *src) /* I - UTF-8 Source String */ { + const char *prefix; /* Prefix string */ + + if (msg) printf("%s:", msg); - for (; *src; src ++) - printf(" %02x", *src); + for (prefix = " "; *src; src ++) + { + printf("%s%02x", prefix, *src); + + if ((src[0] & 0x80) && (src[1] & 0x80)) + prefix = ""; + else + prefix = " "; + } putchar('\n'); } diff --git a/cups/transcode.c b/cups/transcode.c index 417db314e..de9526916 100644 --- a/cups/transcode.c +++ b/cups/transcode.c @@ -953,7 +953,7 @@ conv_utf8_to_sbcs( * Convert internal UCS-4 to SBCS legacy charset (and delete BOM)... */ - for (workptr = work + 1, start = dest; *workptr && maxout > 1; maxout --) + for (workptr = work, start = dest; *workptr && maxout > 0; maxout --) { unichar = *workptr++; if (!unichar) @@ -1041,7 +1041,7 @@ conv_utf8_to_vbcs( * Convert internal UCS-4 to VBCS legacy charset (and delete BOM)... */ - for (start = dest, workptr = work + 1; *workptr && maxout > 1; maxout --) + for (start = dest, workptr = work; *workptr && maxout > 0; maxout --) { unichar = *workptr++; diff --git a/cups/util.c b/cups/util.c index fe2a55bb0..d03542cb9 100644 --- a/cups/util.c +++ b/cups/util.c @@ -1577,7 +1577,8 @@ _cupsConnect(void) /* - * 'cups_get_printer_uri()' - Get the printer-uri-supported attribute for the first printer in a class. + * 'cups_get_printer_uri()' - Get the printer-uri-supported attribute for the + * first printer in a class. */ static int /* O - 1 on success, 0 on failure */ @@ -1605,9 +1606,9 @@ cups_get_printer_uri( /* Hostname associated with connection */ static const char * const requested_attrs[] = { /* Requested attributes */ + "member-uris", "printer-uri-supported", - "printer-type", - "member-uris" + "printer-type" }; @@ -1742,7 +1743,9 @@ cups_get_printer_uri( else if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) { - httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, + httpSeparateURI(HTTP_URI_CODING_ALL, + _httpResolveURI(attr->values[0].string.text, uri, + sizeof(uri), 0), scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); ippDelete(response); diff --git a/data/iso-8859-10 b/data/iso-8859-10 deleted file mode 100644 index 31f55552e..000000000 --- a/data/iso-8859-10 +++ /dev/null @@ -1,251 +0,0 @@ -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-Italic Courier-BoldItalic - -# -# 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 deleted file mode 100644 index dcfacca9d..000000000 --- a/data/iso-8859-13 +++ /dev/null @@ -1,251 +0,0 @@ -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-Italic Courier-BoldItalic - -# -# 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 deleted file mode 100644 index ca0097a47..000000000 --- a/data/iso-8859-14 +++ /dev/null @@ -1,251 +0,0 @@ -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-Italic Courier-BoldItalic - -# -# 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 deleted file mode 100644 index 334160f4f..000000000 --- a/data/iso-8859-15 +++ /dev/null @@ -1,251 +0,0 @@ -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-Italic Courier-BoldItalic - -# -# 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/doc/Makefile b/doc/Makefile index bb4fc91e0..92a397f93 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -36,12 +36,7 @@ WEBIMAGES = \ images/sel.gif \ images/smiley.jpg \ images/unsel.gif \ - images/web-add-this-printer.gif \ - images/web-password.gif \ - images/web-printer-driver.gif \ - images/web-printer-status.gif \ - images/web-set-printer-options.gif \ - images/web-test-page.gif + images/wait.gif HELPFILES = \ help/accounting.html \ help/api-array.html \ diff --git a/doc/cups.css b/doc/cups.css index 5ceddf2af..44f8f7c65 100644 --- a/doc/cups.css +++ b/doc/cups.css @@ -260,19 +260,34 @@ TABLE.list { } TABLE.list TH { - border-bottom: solid 1pt #999999; + background: white; + border-bottom: solid thin #cccccc; + color: #444444; padding-top: 10pt; padding-left: 5pt; text-align: left; + vertical-align: bottom; white-space: nowrap; } +TABLE.list TH A { + color: #4444cc; +} + TABLE.list TD { border-bottom: solid thin #eeeeee; padding-top: 5pt; padding-left: 5pt; } +TABLE.list TR:nth-child(even) { + background: #f8f8f8; +} + +TABLE.list TR:nth-child(odd) { + background: #f4f4f4; +} + DIV.sidebar { float: right; min-width: 25%; @@ -368,6 +383,18 @@ DIV.summary TABLE THEAD TH { background: #f0f0f0; } +DIV.tabs { + height: 480px; + overflow: hidden; +} + +DIV.tab { + float: left; + height: 100%; + overflow-y: auto; + width: 100%; +} + /* API documentation styles... */ div.body h1 { margin: 0; diff --git a/doc/help/overview.html b/doc/help/overview.html index 38f57eb3d..c83785e23 100644 --- a/doc/help/overview.html +++ b/doc/help/overview.html @@ -5,104 +5,63 @@ -

The Common UNIX Printing SystemTM, or CUPS, is the -software you use to print from applications like the web browser -you are using to read this page. It converts the page -descriptions produced by your application (put a paragraph -here, draw a line there, and so forth) into something your -printer can understand and then sends the information to the -printer for printing.

+

The Common UNIX Printing SystemTM, or CUPS, is the software you +use to print from applications like the web browser you are using to read this +page. It converts the page descriptions produced by your application +(put a paragraph here, draw a line there, and so forth) into something your +printer can understand and then sends the information to the printer for +printing.

-

Now, since every printer manufacturer does things differently, -printing can be very complicated. CUPS does its best to hide this -from you and your application so that you can concentrate on -printing and less on how to print. Generally, the only -time you need to know anything about your printer is when you use -it for the first time, and even then CUPS can often figure things +

Now, since every printer manufacturer does things differently, printing can +be very complicated. CUPS does its best to hide this from you and your +application so that you can concentrate on printing and less on how to +print. Generally, the only time you need to know anything about your printer is +when you use it for the first time, and even then CUPS can often figure things out on its own.

How Does It Work?

-

The first time you print to a printer, CUPS creates a -queue to keep track of the current status of the printer -(everything OK, out of paper, etc.) and any pages you have -printed. Most of the time the queue points to a printer connected -directly to your computer via a USB or parallel port, however it -can also point to a printer on your network, a printer on the -Internet, or multiple printers depending on the configuration. -Regardless of where the queue points, it will look like -any other printer to you and your applications.

+

The first time you print to a printer, CUPS creates a queue to keep +track of the current status of the printer (everything OK, out of paper, etc.) +and any pages you have printed. Most of the time the queue points to a printer +connected directly to your computer via a USB or parallel port, however it can +also point to a printer on your network, a printer on the Internet, or multiple +printers depending on the configuration. Regardless of where the queue +points, it will look like any other printer to you and your applications.

-

Every time you print something, CUPS creates a job -which contains the queue you are sending the print to, the name -of the document you are printing, and the page descriptions. Job -are numbered (queue-1, queue-2, and so forth) so you can monitor -the job as it is printed or cancel it if you see a mistake. When -CUPS gets a job for printing, it determines the best programs -(filters, printer drivers, port -monitors, and backends) to convert the pages into a -printable format and then runs them to actually print the -job.

+

Every time you print something, CUPS creates a job which contains +the queue you are sending the print to, the name of the document you are +printing, and the page descriptions. Job are numbered (queue-1, queue-2, and so +forth) so you can monitor the job as it is printed or cancel it if you see a +mistake. When CUPS gets a job for printing, it determines the best programs +(filters, printer drivers, port monitors, and +backends) to convert the pages into a printable format and then runs +them to actually print the job.

-

When the print job is completely printed, CUPS removes the job -from the queue and moves on to any other jobs you have submitted. -You can also be notified when the job is finished, or if there -are any errors during printing, in several different ways.

+

When the print job is completely printed, CUPS removes the job from the queue +and moves on to any other jobs you have submitted. You can also be notified when +the job is finished, or if there are any errors during printing, in several +different ways.

Where Do I Begin?

-

Click on the Administration tab at the -top of this page. If you have a printer connected to a USB or -parallel port, you will see it listed as a new printer - click on -the Add This Printer button, verify the printer driver -CUPS has chosen for you, and click on the Add Printer -button. If you do not see your printer listed, or if you have a -network printer, click on the Add Printer button and -follow the prompts.

+

Click on the Administration tab at the top of this page. +Click on the Add Printer button and follow the prompts.

-
If you are asked for a username and password, enter -your login username and password or the "root" username and -password. On MacOS X, the login username (or "short name") is -typically your first name in lowercase.
+
When you are asked for a username and password, enter your login +username and password or the "root" username and password. On MacOS X, the login +username (or "short name") is typically your first and last name in +lowercase.
-

After the printer is added, CUPS will ask you to set the -default printer options (paper size, output mode, etc.) for the -printer. Make any changes as needed and then click on the -Set Printer Options button to save them.

+

After the printer is added, CUPS will ask you to set the default printer +options (paper size, output mode, etc.) for the printer. Make any changes as +needed and then click on the Set Default Options button to save +them. Some printers also support auto-configuration - click on the Query +Printer for Default Options button to update the options automaticaly.

-

Finally, click on the Print Test Page button to -print a simple test page and verify that everything is working -properly.

- -

Once you have added the printer, you can print to it from any -application.

- - - - - - - - - - - - - - -
CUPS Administration Web Page
-Figure 1: The CUPS Administration Web Page
CUPS Driver Selection Web Page
-Figure 2: The CUPS Driver Selection Web Page
CUPS Password Dialog
-Figure 3: The CUPS Password Dialog
CUPS Set Printer Options Web Page
-Figure 4: The CUPS Set Printer Options Web Page
CUPS Printer Status Page
-Figure 5: The CUPS Printer Status Page
CUPS Printer Test Page
-Figure 6: The CUPS Printer Test Page
+

Once you have added the printer, you can print to it from any application. +You can also choose Print Test Page from the maintenance menu to print +a simple test page and verify that everything is working properly.

diff --git a/doc/help/ref-printers-conf.html b/doc/help/ref-printers-conf.html index 33397e8b0..e3fb07840 100644 --- a/doc/help/ref-printers-conf.html +++ b/doc/help/ref-printers-conf.html @@ -37,12 +37,12 @@ active.

The Accepting directive defines the initial state of the printer-is-accepting-jobs attribute. This state -is also set by the accept(8) and -reject(8) commands:

+is also set by the cupsaccept(8) and +cupsreject(8) commands:

-/usr/sbin/accept printername
-/usr/sbin/reject printername
+/usr/sbin/cupsaccept printername
+/usr/sbin/cupsreject printername
 

This directive must appear inside a DefaultPrinter section.

+

CUPS 1.4Filter

+ +

Examples

+ +
+<Printer name>
+  ...
+  Filter mime/type 100 program
+</Printer>
+
+ +

Description

+ +

The Filter directive lists a single filter program as defined +in the printer's PPD file.

+ +

This directive must appear inside a +Printer or +DefaultPrinter section.

+ +

Info

Examples

@@ -482,6 +503,27 @@ HREF="#DefaultPrinter">DefaultPrinter section.

+

CUPS 1.4PreFilter

+ +

Examples

+ +
+<Printer name>
+  ...
+  PreFilter mime/type 100 program
+</Printer>
+
+ +

Description

+ +

The PreFilter directive lists a single pre-filter program as +defined in the printer's PPD file.

+ +

This directive must appear inside a +Printer or +DefaultPrinter section.

+ +

Printer

Examples

@@ -503,6 +545,27 @@ command: +

CUPS 1.4Product

+ +

Examples

+ +
+<Printer name>
+  ...
+  Product Acme PaperWriter
+</Printer>
+
+ +

Description

+ +

The Product directive defines the main product string from the +printer's PPD file and is used when advertising the queue via DNS-SD.

+ +

This directive must appear inside a +Printer or +DefaultPrinter section.

+ +

QuotaPeriod

Examples

diff --git a/doc/help/spec-ipp.html b/doc/help/spec-ipp.html index da4d217f3..8fcfa7f0d 100644 --- a/doc/help/spec-ipp.html +++ b/doc/help/spec-ipp.html @@ -2130,7 +2130,7 @@ release.

-

columns (integer(1:4))

+

columns (integer(1:4)) Deprecated

The columns attribute specifies the number of columns to generate when printing text files. The default value is 1. diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html index 7a981dfc3..86ebea316 100644 --- a/doc/help/spec-ppd.html +++ b/doc/help/spec-ppd.html @@ -1527,6 +1527,21 @@ before the filter that accepts the given MIME type.

*cupsPreFilter: "image/png 0 mypngprefilter" +

CUPS 1.4cupsSNMPSupplies

+ +

*cupsSNMPSupplies: boolean

+ +

This attribute tells the standard network backends whether they should query +the standard SNMP Printer MIB OIDs for supply levels. The default value is +True. + +

Example:

+ +
+*% Do not use SNMP queries to report supply levels
+*cupsSNMPSupplies: False
+
+

cupsVersion

*cupsVersion: major.minor

@@ -1831,6 +1846,9 @@ the device.

  • Added cupsPJLDisplay attribute.
  • +
  • Added cupsSNMPSupplies + attribute.
  • +
  • Added cupsUIResolver and cupsUIConstraints attributes.
  • diff --git a/doc/help/whatsnew.html b/doc/help/whatsnew.html index 7a6ed2745..8d9b1c0b5 100644 --- a/doc/help/whatsnew.html +++ b/doc/help/whatsnew.html @@ -5,205 +5,188 @@ -

    CUPS 1.4 adds over ?? changes and new features to CUPS 1.3.x. This page provides a high-level outline of these changes. If you have never used CUPS before, read the "Overview of CUPS" document instead.

    +

    CUPS 1.4 adds over 64 changes and new features to CUPS 1.3.x. This page provides a high-level outline of these changes. If you have never used CUPS before, read the "Overview of CUPS" document instead.

    Commands

      -
    1. lppasswd; the lppasswd program is no longer installed setuid by default.
    2. +
    3. accept and reject; the accept and reject commands have been officially renamed to cupsaccess and cupsreject. The old names are still supported via symlinks.
    4. + +
    5. cupsfilter; the cupsfilter program now supports filtering of already-queued print job files and can also run printer-specific filters specified in the PPD file.
    6. -
    7. cupsfilter; the cupsfilter program now supports filtering of already-queued print job files.
    8. +
    9. cupstestdsc; the cupstestdsc utility has been improved to better detect problems with PostScript print files.
    10. -
    11. ;
    12. +
    13. cupstestppd; the cupstestppd utility has been improved to test new PPD keywords and better detect impossible contraints.
    14. -
    15. ;
    16. +
    17. lpadmin; the lpadmin command now supports options to hold and release new jobs on a printer or all printers.
    18. -
    19. ;
    20. +
    21. lpoptions; the lpoptions command now describes custom options and their parameters.
    22. + +
    23. lppasswd; the lppasswd program is no longer installed setuid by default.
    24. + +
    25. lpstat; the lpstat command now supports a -H option to show the current default server and no longer slows down when a printer is specified.

    Web Interface

    -
      +
        -
      1. Look-n-feel; the web interface has been given a new look with a new CUPS logo.
      2. +
      3. Look-n-feel; the web interface has been given a new look.
      4. -
      5. Security; the web interface has been updated to require authentication for printing of test pages and RSS subscription operations.
      6. - -
      7. Printer sharing; the "share printer" and "unshare printer" buttons are now only shown when printer sharing is enabled in the scheduler.
      8. +
      9. PHP support; the "php-cgi" program is used, when available, to process PHP pages in the CUPS web interface.
      10. Printer configuration; improvements have been made to the add and modify printer pages.
      11. -
      12. ;
      13. +
      14. Printer options; the Set Default Options page now provides a "query" button that queries the default and installed options from the printer.
      15. -
      16. ;
      17. +
      18. Printer sharing; the "share printer" and "unshare printer" buttons are now only shown when printer sharing is enabled in the scheduler.
      19. -
      20. ;
      21. +
      22. Security; the web interface has been updated to support authentication for printing of test pages and RSS subscription operations.
      23. -
      24. ;
      25. +
      26. Server settings; the Administration page now provides access to common "advanced" server settings.

      Networking

      -
        +
        1. Bonjour (DNS-SD) printing support; a new mdns backend provides Bonjour-based printer discovery and the ipp, lpd, and socket backends now support Bonjour address resolution.
        2. Bonjour (DNS-SD) perforance tuning; the scheduler now only uses a single file descriptor for printer sharing. It previously used one per printer.
        3. -
        4. Bonjour (DNS-SD) web interface registry; when remote access is enabled, the scheduler registers the web interface for easier access
        5. +
        6. Bonjour (DNS-SD) web interface registry; when remote access is enabled, the scheduler can register the web interface for easier access.
        7. -
        8. SNMP-based monitoring; the ipp, lpd, and socket backends now report supply levels and printer status using SNMP queries.
        9. - -
        10. SNMP port monitor MIB; the ipp, lpd, snmp, and socket now support the PWG port monitor MIB
        11. +
        12. LPD client support; the cups-lpd mini-daemon now provides the document-name for print jobs and supports specification of a CUPS server.
        13. -
        14. ;
        15. +
        16. PWG Port Monitor MIB; the snmp backend now supports the PWG Port Monitor MIB to better choose the device URI to use.
        17. -
        18. ;
        19. +
        20. SNMP-based monitoring; the ipp, lpd, and socket backends now report supply levels and printer status using SNMP queries.

        IPP Support

        -
          +
            -
          1. CUPS-Get-Document operation; the scheduler now supports a "get document" operation to download files from a print job.
          2. - -
          3. ;
          4. - -
          5. ;
          6. +
          7. CUPS-Add-Modify-Printer operation; the scheduler now supports setting the printer-state-reasons attribute using this operation.
          8. -
          9. ;
          10. +
          11. CUPS-Get-Document operation; the scheduler now supports a "get document" operation to download files from a print job.
          12. -
          13. ;
          14. +
          15. Device location; the scheduler and backend discovery interface now support a device-location attribute.
          16. -
          17. ;
          18. +
          19. Hold-New-Jobs and Release-Held-New-Jobs operations; the scheduler now supports the Hold-New-Jobs and Release-Held-New-Jobs operations.

          Scheduler

          -
            +
              + +
            1. Access control; the scheduler now supports multiple addresses in Allow and Deny lines. It also now returns a HTTP 403 (forbidden) status when a user authenticates successfully but is not allowed to perform an operation.
            2. -
            3. Performance tuning; the scheduler now coalesces configuration and state file changes to reduce the amount of disk activity.
            4. +
            5. Access logging; the scheduler now supports an AccessLogLevel directive to control what is logged in the access_log file.
            6. Configuration files; the default cupsd.conf file now provides an "authenticated" policy for easy authenticated sharing of printers.
            7. -
            8. Seatbelt support; the scheduler now runs child processes using restrictive policies on Mac OS X for improved security and job isolation.
            9. +
            10. Default LogLevel; the default LogLevel is now "warn" instead of "info".
            11. -
            12. PAM support; the scheduler now sets more PAM attributes to better support third-party authentication schemes.
            13. +
            14. Default paper size; the scheduler now supports a DefaultPaperSize directive to override the default paper size defined by the locale or libpaper configuration.
            15. -
            16. Test option; the scheduler now supports a test mode via the "-t" option.
            17. +
            18. Encryption support; the scheduler now supports a SSLOptions directive to optionally support Windows clients in "FIPS" mode. It also now loads both the server and CA certificates (if present) from the ServerCertificate file.
            19. -
            20. Page logging; the scheduler now supports a PageLogFormat directive to control the format of the page_log file.
            21. +
            22. Error logging; the scheduler now logs unsuccessful operations as errors in the error_log file.
            23. -
            24. ;
            25. +
            26. Error policies; the scheduler now supports a retry-current-job error policy that retries the current job immediately.
            27. -
            28. ;
            29. +
            30. Fatal error handling; the scheduler now supports a FatalErrors directive to control which startup errors should be considered fatal.
            31. -
            32. ;
            33. +
            34. Filter command-line; the scheduer now passes the job-originating-host-name attribute as a CUPS option to filters and backends.
            35. -
            36. ;
            37. +
            38. Filter environment; the scheduler now includes CUPS_JOBTYPE, PRINTER_INFO, and PRINTER_LOCATION variables in the environment passed to filters and backends.
            39. -
            40. ;
            41. +
            42. Job progress; the scheduler now supports a job-media-progress attribute to track the printing progress of each page.
            43. -
            +
          1. MIME database; MIME types now support a priority attribute to override the default (alphabetical) rules of precedence.
          2. +
          3. Page logging; the scheduler now supports a PageLogFormat directive to control the format of the page_log file.
          4. -

            Printer Drivers

            +
          5. PAM support; the scheduler now sets more PAM attributes to better support third-party authentication schemes.
          6. -
              +
            1. PDF job ticket support; the scheduler now supports cupsJobTicket comments at the beginning of PDF print jobs.
            2. -
            3. Dynamic PPD support; drivers can now set PPD keywords - dynamically using PPD: messages.
            4. +
            5. Performance tuning; the scheduler now coalesces configuration and state file changes to reduce the amount of disk activity and caches printer attributes to further reduce startup time.
            6. -
            7. Generic PostScript command filter; a new CUPS command file filter for PostScript printers provides auto-configuration, self-test page, and status and supply level reporting functions.
            8. +
            9. Printcap support; the scheduler no longer clears the printcap file when shutting down, and can now create XML "plist" printcap files as well.
            10. -
            11. PJL support; the cupsPJLDisplay PPD attribute controls the PJL commands used to display the current user and job on the printer.
            12. +
            13. RSS subscriptions; the scheduler now starts the notifier for RSS subscriptions after creation so the feed is available immediately.
            14. -
            15. Driver development kit; the CUPS DDK is now a standard part of CUPS
            16. +
            17. Sandbox support; the scheduler now runs child processes using restrictive policies on Mac OS X for improved security and job isolation.
            18. -
            19. PPD compiler improvements; the PPD compiler now supports Mac OS X .strings files for localization and ...
            20. +
            21. Test option; the scheduler now supports a test mode via the "-t" option.
            22. -
            23. Generic PostScript and PCL drivers; new generic PostScript and PCL drivers provide improved support for laser printers.
            24. +
            -
          7. ;
          8. -
          9. ;
          10. +

            Printer Drivers

            -
          11. ;
          12. +
              -
            1. ;
            2. +
            3. Device discovery; the cups-deviced helper now runs backends in parallel for faster discovery and streams the results of discovery as the backends provide them.
            4. -
            5. ;
            6. +
            7. Driver development kit; the CUPS DDK is now a standard part of CUPS.
            8. -
            9. ;
            10. +
            11. Driver information file support; the cups-driverd helper program now directly supports PPD compiler driver information files.
            12. -
            13. ;
            14. +
            15. Dynamic PPD support; drivers can now set PPD keywords dynamically using PPD: messages.
            16. -
            17. ;
            18. +
            19. Generic PostScript command filter; a new CUPS command file filter for PostScript printers provides auto-configuration, self-test page, and status and supply level reporting functions.
            20. -
            21. ;
            22. +
            23. New printer drivers; new generic PostScript and PCL drivers provide improved support for laser printers, the CUPS DDK drivers offer support for many HP DesignJet printers, and new label drivers offer support for Seiko and Tharo label printers.
            24. -
            25. ;
            26. +
            27. PJL support; the cupsPJLDisplay PPD attribute controls the PJL commands used to display the current user and job on the printer.
            28. -
            29. ;
            30. +
            31. PPD compiler improvements; the PPD compiler now supports Mac OS X .strings files, OID query strings, conditional directives, long file names, and a test mode. It also fixes many other bugs from the CUPS DDK 1.2.3 release.
            32. -
            33. ;
            34. +
            35. USB printer support; the usb backend now uses libusb when available to allow it to better work with third-party scanning and printing solutions.

            Print Filters

            -
              +
                -
              1. Image filters; the standard image filters now support image files larger than 2GB.
              2. +
              3. Banner filter; the bundled banner ("job-sheets") pages are now generated using a new banner filter provides easier customization and better support for UTF-8 text.
              4. -
              5. Device discovery; the cups-deviced helper now runs backends in parallel for faster discovery and streams the results of discovery as the backends provide them.
              6. +
              7. Image filters; the standard image filters now support image files larger than 2GB.
              8. PDF filter; the pdftops filter has been replaced with a wrapper program that runs the Xpdf, poppler, or Ghostscript PDF to PostScript utilities.
              9. -
              10. ;
              11. - -
              12. ;
              13. - -
              14. ;
              15. - -
              16. ;
              17. -

              CUPS API

              -
                +
                  -
                1. Streaming API; a new streaming request API provides asynchronous job creation and request submission.
                2. +
                3. Backend API; a new cupsBackendReport function is provided to report a device from a backend and handles any needed quoting of the make-and-model, info, device-id, and location strings.
                4. Device discovery; the new cupsGetDevices function streams discovered devices to an application-provided callback function.
                5. -
                6. PPD support; two new functions are provided, cupsGetPPD3 and ppdLocalizeMarkerName, to update the local copy of a printers's PPD file and get a localized marker (supply) name, respectively.
                7. - -
                8. ;
                9. - -
                10. ;
                11. +
                12. IPP API; the IPP read and write functions no longer use a large stack-based buffer when reading and writing IPP attributes.
                13. -
                14. ;
                15. +
                16. PPD support; several new functions are provided: cupsGetPPD3, cupsResolveConflicts, ppdInstallableConflict, ppdLocalizeAttr, ppdLocalizeMarkerName and ppdPageSizeLimits.
                17. -
                18. ;
                19. +
                20. Side-Channel API; new cupsSideChannelSNMPGet and cupsSideChannelSNMPWalk functions allow printer drivers to do SNMP queries via the standard network backends.
                21. -
                22. ;
                23. - -
                24. ;
                25. - -
                26. ;
                27. +
                28. Streaming API; a new streaming request API provides asynchronous job creation and request submission.
                diff --git a/doc/images/web-add-this-printer.gif b/doc/images/web-add-this-printer.gif deleted file mode 100644 index e4bd2f2ca8797879c83195df1fe04d8dd624423f..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 23429 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 diff --git a/doc/images/web-password.gif b/doc/images/web-password.gif deleted file mode 100644 index d59c3764c21dd093c58d40a16cef6ecb9acdd886..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 20956 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 D9|Y(< diff --git a/doc/images/web-printer-status.gif b/doc/images/web-printer-status.gif deleted file mode 100644 index 9202291ed06209101d0b1aa322de38ea3da98a27..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 24271 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 diff --git a/doc/images/web-set-printer-options.gif b/doc/images/web-set-printer-options.gif deleted file mode 100644 index e1b9bcf08dec74e5298fb4e0de6eb175b213d829..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 19998 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 NE#WdQ$1)%Q06Tzo_D28! diff --git a/doc/images/web-test-page.gif b/doc/images/web-test-page.gif deleted file mode 100644 index 8d33e6114954bd1d8c2f4f248af998b82bd15d8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 19005 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 z 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 z z^PAxuXF1QA&ULo)o$;J!J-c}cZ0Lg~gkfQqjELD6nlSXC5uIp7FPhPfcJ!km9cf8V zn$nfF^rbNkXshow & SHOW_JOB_ID) { - snprintf(text, sizeof(text), "%s-%d", getenv("PRINTER_NAME"), job_id); + snprintf(text, sizeof(text), "%s-%d", getenv("PRINTER"), job_id); printf("%.1f %.1f moveto", x, y); y -= line_height; psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT, diff --git a/locale/cups_pt_PT.po b/locale/cups_pt_PT.po deleted file mode 100644 index 00ad3bac7..000000000 --- a/locale/cups_pt_PT.po +++ /dev/null @@ -1,1464 +0,0 @@ -msgid "\t\t(all)\n" -msgstr "\t\t(tudo)\n" -msgid "\t\t(none)\n" -msgstr "\t\t(sem)\n" -msgid "\t%d entries\n" -msgstr "\t%d entradas\n" -msgid "\tAfter fault: continue\n" -msgstr "\tApós falha: continuar\n" -msgid "\tAlerts:" -msgstr "\tAlertas:" -msgid "\tBanner required\n" -msgstr "\tFaixa publicitária requerida\n" -msgid "\tCharset sets:\n" -msgstr "\tConjuntos charset:\n" -msgid "\tConnection: direct\n" -msgstr "\tLigação: directa\n" -msgid "\tConnection: remote\n" -msgstr "\tLigação: remota\n" -msgid "\tDefault page size:\n" -msgstr "\tTamanho de página predefinido:\n" -msgid "\tDefault pitch:\n" -msgstr "\tPitch predefinido:\n" -msgid "\tDefault port settings:\n" -msgstr "\tPredefinições de porta:\n" -msgid "\tDescription: %s\n" -msgstr "\tDescrição: %s\n" -msgid "\tForm mounted:\n\tContent types: any\n\tPrinter types: unknown\n" -msgstr "\tFormato montado:\n\tTipos de conteúdo: qualquer\n\tTipos de impressora: desconhecido\n" -msgid "\tForms allowed:\n" -msgstr "\tFormatos permitidos:\n" -msgid "\tInterface: %s.ppd\n" -msgstr "\tInterface: %s.ppd\n" -msgid "\tInterface: %s/interfaces/%s\n" -msgstr "\tInterface: %s/interfaces/%s\n" -msgid "\tInterface: %s/ppd/%s.ppd\n" -msgstr "\tInterface: %s/ppd/%s.ppd\n" -msgid "\tLocation: %s\n" -msgstr "\tLocalização: %s\n" -msgid "\tOn fault: no alert\n" -msgstr "\tEm falha: sem alerta\n" -msgid "\tUsers allowed:\n" -msgstr "\tUtilizadores permitidos:\n" -msgid "\tUsers denied:\n" -msgstr "\tUtilizadores negados:\n" -msgid "\tdaemon present\n" -msgstr "\tdaemon presente\n" -msgid "\tno entries\n" -msgstr "\tsem entradas\n" -msgid "\tprinter is on device '%s' speed -1\n" -msgstr "\timpressora está no periférico '%s' velocidade -1\n" -msgid "\tprinting is disabled\n" -msgstr "\timpressão desactivada\n" -msgid "\tprinting is enabled\n" -msgstr "\timpressão activada\n" -msgid "\tqueued for %s\n" -msgstr "\tem fila para %s\n" -msgid "\tqueuing is disabled\n" -msgstr "\tcolocação em fila desactivada\n" -msgid "\tqueuing is enabled\n" -msgstr "\tcolocação em fila activada\n" -msgid "\treason unknown\n" -msgstr "\tmotivo desconhecido\n" -msgid "\n DETAILED CONFORMANCE TEST RESULTS\n" -msgstr "\n RESULTADOS DETALHADOS DO TESTE DE CONFORMIDADE\n" -msgid " REF: Page 15, section 3.1.\n" -msgstr " REF: Página 15, secção 3.1.\n" -msgid " REF: Page 15, section 3.2.\n" -msgstr " REF: Página 15, secção 3.2.\n" -msgid " REF: Page 19, section 3.3.\n" -msgstr " REF: Página 19, secção 3.3.\n" -msgid " REF: Page 20, section 3.4.\n" -msgstr " REF: Página 20, secção 3.4.\n" -msgid " REF: Page 27, section 3.5.\n" -msgstr " REF: Página 27, secção 3.5.\n" -msgid " REF: Page 42, section 5.2.\n" -msgstr " REF: Página 42, secção 5.2.\n" -msgid " REF: Pages 16-17, section 3.2.\n" -msgstr " REF: Páginas 16-17, secção 3.2.\n" -msgid " REF: Pages 42-45, section 5.2.\n" -msgstr " REF: Páginas 42-45, secção 5.2.\n" -msgid " REF: Pages 45-46, section 5.2.\n" -msgstr " REF: Páginas 45-46, secção 5.2.\n" -msgid " REF: Pages 48-49, section 5.2.\n" -msgstr " REF: Páginas 48-49, secção 5.2.\n" -msgid " REF: Pages 52-54, section 5.2.\n" -msgstr " REF: Páginas 52-54, secção 5.2.\n" -msgid " %-39.39s %.0f bytes\n" -msgstr " %-39.39s %.0f bytes\n" -msgid " PASS Default%s\n" -msgstr " PASS Predefinição%s\n" -msgid " PASS DefaultImageableArea\n" -msgstr " PASS DefaultImageableArea\n" -msgid " PASS DefaultPaperDimension\n" -msgstr " PASS DefaultPaperDimension\n" -msgid " PASS FileVersion\n" -msgstr " PASS FileVersion\n" -msgid " PASS FormatVersion\n" -msgstr " PASS FormatVersion\n" -msgid " PASS LanguageEncoding\n" -msgstr " PASS LanguageEncoding\n" -msgid " PASS LanguageVersion\n" -msgstr " PASS LanguageVersion\n" -msgid " PASS Manufacturer\n" -msgstr " PASS Fabricante\n" -msgid " PASS ModelName\n" -msgstr " PASS ModelName\n" -msgid " PASS NickName\n" -msgstr " PASS NickName\n" -msgid " PASS PCFileName\n" -msgstr " PASS PCFileName\n" -msgid " PASS PSVersion\n" -msgstr " PASS PSVersion\n" -msgid " PASS PageRegion\n" -msgstr " PASS PageRegion\n" -msgid " PASS PageSize\n" -msgstr " PASS PageSize\n" -msgid " PASS Product\n" -msgstr " PASS Produto\n" -msgid " PASS ShortNickName\n" -msgstr " PASS ShortNickName\n" -msgid " WARN \"%s %s\" conflicts with \"%s %s\"\n (constraint=\"%s %s %s %s\")\n" -msgstr " WARN \"%s %s\" em conflito com \"%s %s\"\n (restrição=\"%s %s %s %s\")\n" -msgid " WARN %s has no corresponding options!\n" -msgstr " WARN %s não tem opções correspondentes!\n" -msgid " WARN %s shares a common prefix with %s\n REF: Page 15, section 3.2.\n" -msgstr " WARN %s partilha um prefixo comum com %s\n REF: Página 15, secção 3.2.\n" -msgid " WARN Default choices conflicting!\n" -msgstr " WARN Escolhas predefinidas em conflito!\n" -msgid " WARN Duplex option keyword %s should be named Duplex or JCLDuplex!\n REF: Page 122, section 5.17\n" -msgstr " WARN Palavra-chave de opção de frente e verso %s deve ter o nome Duplex ou JCLDuplex!\n REF: Página 122, secção 5.17\n" -msgid " WARN File contains a mix of CR, LF, and CR LF line endings!\n" -msgstr " WARN Ficheiro contém um misto de fins de linha CR, LF e CR LF!\n" -msgid " WARN LanguageEncoding required by PPD 4.3 spec.\n REF: Pages 56-57, section 5.3.\n" -msgstr " WARN LanguageEncoding requerido por espec. de PPD 4.3\n REF: Páginas 56-57, secção 5.3.\n" -msgid " WARN Line %d only contains whitespace!\n" -msgstr " WARN Linha %d só contém espaço em branco!\n" -msgid " WARN Manufacturer required by PPD 4.3 spec.\n REF: Pages 58-59, section 5.3.\n" -msgstr " WARN Fabricante requerido por espec. de PPD 4.3\n REF: Páginas 58-59, secção 5.3.\n" -msgid " WARN Missing APDialogExtension file \"%s\"\n" -msgstr " WARN Ficheiro APDialogExtension inexistente \"%s\"\n" -msgid " WARN Missing APPrinterIconPath file \"%s\"\n" -msgstr " WARN Ficheiro APPrinterIconPath inexistente \"%s\"\n" -msgid " WARN Missing cupsICCProfile file \"%s\"\n" -msgstr " WARN Ficheiro cupsICCProfile inexistente \"%s\"\n" -msgid " WARN Non-Windows PPD files should use lines ending with only LF, not CR LF!\n" -msgstr " WARN Ficheiros PPD não Windows devem utilizar fins de linha com LF, e não CR LF!\n" -msgid " WARN Obsolete PPD version %.1f!\n REF: Page 42, section 5.2.\n" -msgstr " WARN Versão de PPD obsoleta %.1f!\n REF: Página 42, secção 5.2" -msgid " WARN PCFileName longer than 8.3 in violation of PPD spec.\n REF: Pages 61-62, section 5.3.\n" -msgstr " WARN PCFileName superior a 8.3 viola espec. de PPD\n REF: Páginas 61-62, secção 5.3.\n" -msgid " WARN Protocols contains PJL but JCL attributes are not set.\n REF: Pages 78-79, section 5.7.\n" -msgstr " WARN Protocolos contêm PJL, mas atributos JCL não estão especificados.\n REF: Páginas 78-79, secção 5.7.\n" -msgid " WARN Protocols contains both PJL and BCP; expected TBCP.\n REF: Pages 78-79, section 5.7.\n" -msgstr " WARN Protocolos contêm PJL e BCP; TBCP esperados.\n REF: Páginas 78-79, secção 5.7.\n" -msgid " WARN ShortNickName required by PPD 4.3 spec.\n REF: Pages 64-65, section 5.3.\n" -msgstr " WARN ShortNickName requerido por espec. de PPD 4.3\n REF: Páginas 64-65, secção 5.3.\n" -msgid " %s %s %s does not exist!\n" -msgstr " %s %s %s não existe!\n" -msgid " %s Bad UTF-8 \"%s\" translation string for option %s!\n" -msgstr " %s Cadeia de tradução UTF-8 \"%s\" inválida para opção %s!\n" -msgid " %s Bad UTF-8 \"%s\" translation string for option %s, choice %s!\n" -msgstr " %s Cadeia de tradução UTF-8 \"%s\" inválida para opção %s, escolha %s!\n" -msgid " %s Bad cupsFilter value \"%s\"!\n" -msgstr " %s Valor cupsFilter inválido \"%s\"!\n" -msgid " %s Bad cupsPreFilter value \"%s\"!\n" -msgstr " %s Valor cupsPreFilter inválido \"%s\"!\n" -msgid " %s Bad language \"%s\"!\n" -msgstr " %s Idioma inválido \"%s\"!\n" -msgid " %s Missing \"%s\" translation string for option %s!\n" -msgstr " %s Cadeia de tradução inexistente \"%s\" para opção %s!\n" -msgid " %s Missing \"%s\" translation string for option %s, choice %s!\n" -msgstr " %s Cadeia de tradução inexistente \"%s\" para opção %s, escolha %s!\n" -msgid " %s Missing choice *%s %s in UIConstraint \"*%s %s *%s %s\"!\n" -msgstr " %s Escolha inexistente *%s %s em UIConstraint \"*%s %s *%s %s\"!\n" -msgid " %s Missing cupsFilter file \"%s\"\n" -msgstr " %s Ficheiro cupsFilter inexistente \"%s\"!\n" -msgid " %s Missing cupsPreFilter file \"%s\"\n" -msgstr " %s Ficheiro cupsPreFilter inexistente \"%s\"!\n" -msgid " %s Missing option %s in UIConstraint \"*%s %s *%s %s\"!\n" -msgstr " %s Opção inexistente %s em UIConstraint \"*%s %s *%s %s\"!\n" -msgid " %s No base translation \"%s\" is included in file!\n" -msgstr " %s Sem tradução base \"%s\" incluída no ficheiro!\n" -msgid " **FAIL** %s must be 1284DeviceID!\n REF: Page 72, section 5.5\n" -msgstr " **FAIL** %s deve ser 1284DeviceID!\n REF: Página 72, secção 5.5\n" -msgid " **FAIL** BAD Default%s %s\n REF: Page 40, section 4.5.\n" -msgstr " **FAIL** Predefinição%s %s inválida\n REF: Página 40, secção 4.5\n" -msgid " **FAIL** BAD DefaultImageableArea %s!\n REF: Page 102, section 5.15.\n" -msgstr " **FAIL** DefaultImageableArea %s inválida!\n REF: Página 102, secção 5.15\n" -msgid " **FAIL** BAD DefaultPaperDimension %s!\n REF: Page 103, section 5.15.\n" -msgstr " **FAIL** DefaultPaperDimension %s inválida!\n REF: Página 103, secção 5.15\n" -msgid " **FAIL** BAD JobPatchFile attribute in file\n REF: Page 24, section 3.4.\n" -msgstr " **FAIL** Atributo JobPatchFile inválido no ficheiro!\n REF: Página 24, secção 3.4\n" -msgid " **FAIL** BAD Manufacturer (should be \"HP\")\n REF: Page 211, table D.1.\n" -msgstr " **FAIL** Fabricante inválido (deve ser \"HP\")\n REF: Página 211, tabela D.1.\n" -msgid " **FAIL** BAD Manufacturer (should be \"Oki\")\n REF: Page 211, table D.1.\n" -msgstr " **FAIL** Fabricante inválido (deve ser \"Oki\")\n REF: Página 211, tabela D.1.\n" -msgid " **FAIL** BAD ModelName - \"%c\" not allowed in string.\n REF: Pages 59-60, section 5.3.\n" -msgstr " **FAIL** ModelName inválido - \"%c\" não permitido na cadeia.\n REF: Páginas 59-60, secção 5.3\n" -msgid " **FAIL** BAD PSVersion - not \"(string) int\".\n REF: Pages 62-64, section 5.3.\n" -msgstr " **FAIL** PSVersion inválida - não \"(cadeia) int\".\n REF: Páginas 62-64, secção 5.3\n" -msgid " **FAIL** BAD Product - not \"(string)\".\n REF: Page 62, section 5.3.\n" -msgstr " **FAIL** Produto inválido - não \"(cadeia)\".\n REF: Página 62, secção 5.3\n" -msgid " **FAIL** BAD ShortNickName - longer than 31 chars.\n REF: Pages 64-65, section 5.3.\n" -msgstr " **FAIL** ShortNickName inválido - superior a 31 car.\n REF: Páginas 64-65, secção 5.3\n" -msgid " **FAIL** Bad %s choice %s!\n REF: Page 122, section 5.17\n" -msgstr " **FAIL** Escolha %s inválida %s!\n REF: Página 122, secção 5.17\n" -msgid " **FAIL** Bad %s choice %s!\n REF: Page 84, section 5.9\n" -msgstr " **FAIL** Escolha %s inválida %s!\n REF: Página 84, secção 5.9\n" -msgid " **FAIL** Bad LanguageEncoding %s - must be ISOLatin1!\n" -msgstr " **FAIL** LanguageEncoding %s inválida - deve ser ISOLatin1!\n" -msgid " **FAIL** Bad LanguageVersion %s - must be English!\n" -msgstr " **FAIL** LanguageVersion %s inválida - deve ser Inglês!\n" -msgid " **FAIL** Default option code cannot be interpreted: %s\n" -msgstr " **FAIL** Impossível interpretar código de opção predefinida: %s\n" -msgid " **FAIL** Default translation string for option %s choice %s contains 8-bit characters!\n" -msgstr " **FAIL** Cadeia de tradução predefinida para opção %s escolha %s contém caracteres de 8 bits!\n" -msgid " **FAIL** Default translation string for option %s contains 8-bit characters!\n" -msgstr " **FAIL** Cadeia de tradução predefinida para opção %s contém caracteres de 8 bits!\n" -msgid " **FAIL** REQUIRED %s does not define choice None!\n REF: Page 122, section 5.17\n" -msgstr " **FAIL** %s requerido não define escolha Sem!\n REF: Página 122, secção 5.17\n" -msgid " **FAIL** REQUIRED Default%s\n REF: Page 40, section 4.5.\n" -msgstr " **FAIL** Predefinição%s requerida\n REF: Página 40, secção 4.5\n" -msgid " **FAIL** REQUIRED DefaultImageableArea\n REF: Page 102, section 5.15.\n" -msgstr " **FAIL** DefaultImageableArea requerida\n REF: Página 102, secção 5.15\n" -msgid " **FAIL** REQUIRED DefaultPaperDimension\n REF: Page 103, section 5.15.\n" -msgstr " **FAIL** DefaultPaperDimension requerida\n REF: Página 103, secção 5.15\n" -msgid " **FAIL** REQUIRED FileVersion\n REF: Page 56, section 5.3.\n" -msgstr " **FAIL** FileVersion requerida\n REF: Página 56, secção 5.3\n" -msgid " **FAIL** REQUIRED FormatVersion\n REF: Page 56, section 5.3.\n" -msgstr " **FAIL** FormatVersion requerida\n REF: Página 56, secção 5.3\n" -msgid " **FAIL** REQUIRED ImageableArea for PageSize %s\n REF: Page 41, section 5.\n REF: Page 102, section 5.15.\n" -msgstr " **FAIL** ImageableArea requerida para PageSize %s\n REF: Página 41, secção 5.\n REF: Página 102, secção 5.15.\n" -msgid " **FAIL** REQUIRED LanguageEncoding\n REF: Pages 56-57, section 5.3.\n" -msgstr " **FAIL** LanguageEncoding requerida\n REF: Páginas 56-57, secção 5.3\n" -msgid " **FAIL** REQUIRED LanguageVersion\n REF: Pages 57-58, section 5.3.\n" -msgstr " **FAIL** LanguageVersion requerida\n REF: Páginas 57-58, secção 5.3\n" -msgid " **FAIL** REQUIRED Manufacturer\n REF: Pages 58-59, section 5.3.\n" -msgstr " **FAIL** Fabricante requerido\n REF: Páginas 58-59, secção 5.3\n" -msgid " **FAIL** REQUIRED ModelName\n REF: Pages 59-60, section 5.3.\n" -msgstr " **FAIL** ModelName requerido\n REF: Páginas 59-60, secção 5.3\n" -msgid " **FAIL** REQUIRED NickName\n REF: Page 60, section 5.3.\n" -msgstr " **FAIL** NickName requerido\n REF: Página 60, secção 5.3\n" -msgid " **FAIL** REQUIRED PCFileName\n REF: Pages 61-62, section 5.3.\n" -msgstr " **FAIL** PCFileName requerido\n REF: Páginas 61-62, secção 5.3\n" -msgid " **FAIL** REQUIRED PSVersion\n REF: Pages 62-64, section 5.3.\n" -msgstr " **FAIL** PSVersion requerida\n REF: Páginas 62-64, secção 5.3\n" -msgid " **FAIL** REQUIRED PageRegion\n REF: Page 100, section 5.14.\n" -msgstr " **FAIL** PageRegion requerida\n REF: Página 100, secção 5.14\n" -msgid " **FAIL** REQUIRED PageSize\n REF: Page 41, section 5.\n REF: Page 99, section 5.14.\n" -msgstr " **FAIL** PageSize requerido\n REF: Página 41, secção 5.\n REF: Página 99, secção 5.14.\n" -msgid " **FAIL** REQUIRED PageSize\n REF: Pages 99-100, section 5.14.\n" -msgstr " **FAIL** PageSize requerido\n REF: Páginas 99-100, secção 5.14\n" -msgid " **FAIL** REQUIRED PaperDimension for PageSize %s\n REF: Page 41, section 5.\n REF: Page 103, section 5.15.\n" -msgstr " **FAIL** PaperDimension requerida para PageSize %s\n REF: Página 41, secção 5.\n REF: Página 103, secção 5.15.\n" -msgid " **FAIL** REQUIRED Product\n REF: Page 62, section 5.3.\n" -msgstr " **FAIL** Produto requerido\n REF: Página 62, secção 5.3\n" -msgid " **FAIL** REQUIRED ShortNickName\n REF: Page 64-65, section 5.3.\n" -msgstr " **FAIL** ShortNickName requerido\n REF: Páginas 64-65, secção 5.3\n" -msgid " %d ERRORS FOUND\n" -msgstr " %d ERROS ENCONTRADOS\n" -msgid " Bad %%%%BoundingBox: on line %d!\n REF: Page 39, %%%%BoundingBox:\n" -msgstr " %%%%BoundingBox: inválida na linha %d!\n REF: Página 39, %%%%BoundingBox:\n" -msgid " Bad %%%%Page: on line %d!\n REF: Page 53, %%%%Page:\n" -msgstr " %%%%Page: inválida na linha %d!\n REF: Página 53, %%%%Page:\n" -msgid " Bad %%%%Pages: on line %d!\n REF: Page 43, %%%%Pages:\n" -msgstr " %%%%Pages: inválidas na linha %d!\n REF: Página 43, %%%%Pages:\n" -msgid " Line %d is longer than 255 characters (%d)!\n REF: Page 25, Line Length\n" -msgstr " Linha %d tem mais de 255 caracteres (%d)!\n REF: Página 25, Comprimento da Linha\n" -msgid " Missing %!PS-Adobe-3.0 on first line!\n REF: Page 17, 3.1 Conforming Documents\n" -msgstr " %!PS-Adobe-3.0 inexistente na primeira linha!\n REF: Página 17, 3.1 Documentos de Conformidade\n" -msgid " Missing %%EndComments comment!\n REF: Page 41, %%EndComments\n" -msgstr " Comentário %%EndComments inexistente!\n REF: Página 41, %%EndComments\n" -msgid " Missing or bad %%BoundingBox: comment!\n REF: Page 39, %%BoundingBox:\n" -msgstr " Comentário %%BoundingBox: inexistente ou inválido!\n REF: Página 39, %%BoundingBox:\n" -msgid " Missing or bad %%Page: comments!\n REF: Page 53, %%Page:\n" -msgstr " Comentários %%Page: inexistentes ou inválidos!\n REF: Página 53, %%Page:\n" -msgid " Missing or bad %%Pages: comment!\n REF: Page 43, %%Pages:\n" -msgstr " Comentário %%Pages: inexistente ou inválido!\n REF: Página 43, %%Pages:\n" -msgid " NO ERRORS FOUND\n" -msgstr " SEM ERROS\n" -msgid " Saw %d lines that exceeded 255 characters!\n" -msgstr " Detectadas %d linhas que excedem 255 caracteres!\n" -msgid " Too many %%BeginDocument comments!\n" -msgstr " Demasiados comentários %%BeginDocument!\n" -msgid " Too many %%EndDocument comments!\n" -msgstr " Demasiados comentários %%EndDocument!\n" -msgid " Warning: file contains binary data!\n" -msgstr " Aviso: ficheiro contém dados binários!\n" -msgid " Warning: no %%EndComments comment in file!\n" -msgstr " Aviso: sem comentário %%EndComments no ficheiro!\n" -msgid " Warning: obsolete DSC version %.1f in file!\n" -msgstr " Aviso: versão obsoleta de DSC %.1f no ficheiro!\n" -msgid " FAIL\n" -msgstr " FAIL\n" -msgid " FAIL\n **FAIL** Unable to open PPD file - %s\n" -msgstr " FAIL\n **FAIL** Impossível abrir ficheiro PPD - %s\n" -msgid " FAIL\n **FAIL** Unable to open PPD file - %s on line %d.\n" -msgstr " FAIL\n **FAIL** Impossível abrir ficheiro PPD - %s na linha %d.\n" -msgid " PASS\n" -msgstr " PASS\n" -msgid "%-6s %-10.10s %-4d %-10d %-27.27s %.0f bytes\n" -msgstr "%-6s %-10.10s %-4d %-10d %-27.27s %.0f bytes\n" -msgid "%-7s %-7.7s %-7d %-31.31s %.0f bytes\n" -msgstr "%-7s %-7.7s %-7d %-31.31s %.0f bytes\n" -msgid "%s accepting requests since %s\n" -msgstr "%s aceita pedidos desde %s\n" -msgid "%s cannot be changed." -msgstr "Impossível alterar %s." -msgid "%s is not implemented by the CUPS version of lpc.\n" -msgstr "%s não é implementado pela versão CUPS de lpc.\n" -msgid "%s is not ready\n" -msgstr "%s não está preparada\n" -msgid "%s is ready\n" -msgstr "%s está preparada\n" -msgid "%s is ready and printing\n" -msgstr "%s está preparada e a imprimir\n" -msgid "%s not accepting requests since %s -\n\t%s\n" -msgstr "%s não aceita pedidos desde %s-\n\t%s\n" -msgid "%s not supported!" -msgstr "%s não suportado!" -msgid "%s/%s accepting requests since %s\n" -msgstr "%s/%s aceita pedidos desde %s\n" -msgid "%s/%s not accepting requests since %s -\n\t%s\n" -msgstr "%s/%s não aceita pedidos desde %s-\n\t%s\n" -msgid "%s: %-33.33s [job %d localhost]\n" -msgstr "%s: %-33.33s [trabalho %d localhost]\n" -msgid "%s: %s failed: %s\n" -msgstr "%s: %s falhou: %s\n" -msgid "%s: Don't know what to do!\n" -msgstr "%s: Não sei que fazer!\n" -msgid "%s: Error - %s environment variable names non-existent destination \"%s\"!\n" -msgstr "%s: Erro - nomes de variáveis de ambiente %s inexistentes no destino \"%s\"!\n" -msgid "%s: Error - bad job ID!\n" -msgstr "%s: Erro - ID de trabalho inválido!\n" -msgid "%s: Error - cannot print files and alter jobs simultaneously!\n" -msgstr "%s: Erro - impossível imprimir ficheiros e alterar trabalhos em simultâneo!\n" -msgid "%s: Error - cannot print from stdin if files or a job ID are provided!\n" -msgstr "%s: Erro - impossível imprimir a partir de stdin se fornecidos ficheiros ou ID do trabalho!\n" -msgid "%s: Error - expected character set after '-S' option!\n" -msgstr "%s: Erro - conjunto de caracteres esperado após opção '-S'!\n" -msgid "%s: Error - expected content type after '-T' option!\n" -msgstr "%s: Erro - tipo de conteúdo esperado após opção '-T'!\n" -msgid "%s: Error - expected copies after '-n' option!\n" -msgstr "%s: Erro - cópias esperadas após opção '-n'!\n" -msgid "%s: Error - expected copy count after '-#' option!\n" -msgstr "%s: Erro - contagem de cópias esperadas após opção '-#'!\n" -msgid "%s: Error - expected destination after '-P' option!\n" -msgstr "%s: Erro - destino esperado após opção '-P'!\n" -msgid "%s: Error - expected destination after '-b' option!\n" -msgstr "%s: Erro - destino esperado após opção '-b'!\n" -msgid "%s: Error - expected destination after '-d' option!\n" -msgstr "%s: Erro - destino esperado após opção '-d'!\n" -msgid "%s: Error - expected form after '-f' option!\n" -msgstr "%s: Erro - formato esperado após opção '-f'!\n" -msgid "%s: Error - expected hold name after '-H' option!\n" -msgstr "%s: Erro - nome para reter esperado após opção '-H'!\n" -msgid "%s: Error - expected hostname after '-H' option!\n" -msgstr "%s: Erro - nome de host esperado após opção '-H'!\n" -msgid "%s: Error - expected hostname after '-h' option!\n" -msgstr "%s: Erro - nome de host esperado após opção '-h'!\n" -msgid "%s: Error - expected mode list after '-y' option!\n" -msgstr "%s: Erro - lista de modo esperada após opção '-y'!\n" -msgid "%s: Error - expected name after '-%c' option!\n" -msgstr "%s: Erro - nome esperado após opção '-%c'!\n" -msgid "%s: Error - expected option string after '-o' option!\n" -msgstr "%s: Erro - cadeia de opção esperada após opção '-o'!\n" -msgid "%s: Error - expected page list after '-P' option!\n" -msgstr "%s: Erro - lista de página esperada após opção '-P'!\n" -msgid "%s: Error - expected priority after '-%c' option!\n" -msgstr "%s: Erro - prioridade esperada após opção '-%c'!\n" -msgid "%s: Error - expected reason text after '-r' option!\n" -msgstr "%s: Erro - texto de motivo esperado após opção '-r'!\n" -msgid "%s: Error - expected title after '-t' option!\n" -msgstr "%s: Erro - título esperado após opção '-t'!\n" -msgid "%s: Error - expected username after '-U' option!\n" -msgstr "%s: Erro - nome de utilizador esperado após opção '-U'!\n" -msgid "%s: Error - expected username after '-u' option!\n" -msgstr "%s: Erro - nome de utilizador esperado após opção '-u'!\n" -msgid "%s: Error - expected value after '-%c' option!\n" -msgstr "%s: Erro - valor esperado após opção '-%c'!\n" -msgid "%s: Error - need \"completed\", \"not-completed\", or \"all\" after '-W' option!\n" -msgstr "%s: Erro - necessário \"concluído\", \"não concluído\" ou \"tudo\" após opção '-W'!\n" -msgid "%s: Error - no default destination available.\n" -msgstr "%s: Erro - sem destino predefinido disponível.\n" -msgid "%s: Error - priority must be between 1 and 100.\n" -msgstr "%s: Erro - prioridade deve ser entre 1 e 100.\n" -msgid "%s: Error - scheduler not responding!\n" -msgstr "%s: Erro - programador não responde!\n" -msgid "%s: Error - stdin is empty, so no job has been sent.\n" -msgstr "%s: Erro - stdin está vazio, por isso nenhum trabalho foi enviado.\n" -msgid "%s: Error - too many files - \"%s\"\n" -msgstr "%s: Erro - demasiados ficheiros - \"%s\"\n" -msgid "%s: Error - unable to access \"%s\" - %s\n" -msgstr "%s: Erro - impossível aceder a \"%s\" - %s\n" -msgid "%s: Error - unable to create temporary file \"%s\" - %s\n" -msgstr "%s: Erro - impossível criar ficheiro temporário \"%s\" - %s\n" -msgid "%s: Error - unable to write to temporary file \"%s\" - %s\n" -msgstr "%s: Erro - impossível escrever no ficheiro temporário \"%s\" - %s\n" -msgid "%s: Error - unknown destination \"%s\"!\n" -msgstr "%s: Erro - destino desconhecido \"%s\"!\n" -msgid "%s: Error - unknown destination \"%s/%s\"!\n" -msgstr "%s: Erro - destino desconhecido \"%s/%s\"!\n" -msgid "%s: Error - unknown option '%c'!\n" -msgstr "%s: Erro - opção desconhecida '%c'!\n" -msgid "%s: Expected job ID after '-i' option!\n" -msgstr "%s: ID de trabalho esperado após opção '-i'!\n" -msgid "%s: Invalid destination name in list \"%s\"!\n" -msgstr "%s: Nome de destino inválido na lista \"%s\"!\n" -msgid "%s: Need job ID ('-i jobid') before '-H restart'!\n" -msgstr "%s: Necessário ID do trabalho ('-i jobid') antes de '-H reiniciar'!\n" -msgid "%s: Operation failed: %s\n" -msgstr "%s: Operação falhou: %s\n" -msgid "%s: Sorry, no encryption support compiled in!\n" -msgstr "%s: Sem suporte de encriptação compilado!\n" -msgid "%s: Unable to connect to server\n" -msgstr "%s: Impossível ligar ao servidor\n" -msgid "%s: Unable to connect to server: %s\n" -msgstr "%s: Impossível ligar ao servidor: %s\n" -msgid "%s: Unable to contact server!\n" -msgstr "%s: Impossível contactar servidor!\n" -msgid "%s: Unknown destination \"%s\"!\n" -msgstr "%s: Destino desconhecido \"%s\"!\n" -msgid "%s: Unknown option '%c'!\n" -msgstr "%s: Opção desconhecida '%c'!\n" -msgid "%s: Warning - '%c' format modifier not supported - output may not be correct!\n" -msgstr "%s: Aviso - modificador de formato '%c' não suportado - saída pode ser incorrecta!\n" -msgid "%s: Warning - character set option ignored!\n" -msgstr "%s: Aviso - opção de conjunto de caracteres ignorada!\n" -msgid "%s: Warning - content type option ignored!\n" -msgstr "%s: Aviso - opção de tipo de conteúdo ignorada!\n" -msgid "%s: Warning - form option ignored!\n" -msgstr "%s: Aviso - opção de formato ignorada!\n" -msgid "%s: Warning - mode option ignored!\n" -msgstr "%s: Aviso - opção de modo ignorada!\n" -msgid "%s: error - %s environment variable names non-existent destination \"%s\"!\n" -msgstr "%s: Erro - nomes de variáveis de ambiente %s inexistentes no destino \"%s\"!\n" -msgid "%s: error - expected option=value after '-o' option!\n" -msgstr "%s: Erro - opção=valor esperada após opção '-o'!\n" -msgid "%s: error - no default destination available.\n" -msgstr "%s: Erro - sem destino predefinido disponível.\n" -msgid "?Invalid help command unknown\n" -msgstr "?Comando de ajuda inválido desconhecido\n" -msgid "A Samba password is required to export printer drivers!" -msgstr "Palavra-passe Samba requerida para exportar recursos de impressora!" -msgid "A Samba username is required to export printer drivers!" -msgstr "Nome de utilizador Samba requerido para exportar recursos de impressora!" -msgid "A class named \"%s\" already exists!" -msgstr "Uma classe com o nome \"%s\" já existe!" -msgid "A printer named \"%s\" already exists!" -msgstr "Uma impressora com o nome \"%s\" já existe!" -msgid "Accept Jobs" -msgstr "Aceitar trabalhos" -msgid "Add Class" -msgstr "Adicionar classe" -msgid "Add Printer" -msgstr "Adicionar impressora" -msgid "Add RSS Subscription" -msgstr "Adicionar subscrição RSS" -msgid "Administration" -msgstr "Administração" -msgid "Attempt to set %s printer-state to bad value %d!" -msgstr "Tentativa de especificar %s printer-state para valor inválido %d!" -msgid "Attribute groups are out of order (%x < %x)!" -msgstr "Grupos de atributos desordenados (%x < %x)!" -msgid "Bad OpenGroup" -msgstr "OpenGroup inválido" -msgid "Bad OpenUI/JCLOpenUI" -msgstr "OpenUI/JCLOpenUI inválidos" -msgid "Bad OrderDependency" -msgstr "OrderDependency inválida" -msgid "Bad UIConstraints" -msgstr "UIConstraints inválidas" -msgid "Bad copies value %d." -msgstr "Valor de cópias inválido %d." -msgid "Bad custom parameter" -msgstr "Parâmetro personalizado inválido" -msgid "Bad device-uri \"%s\"!" -msgstr "Device-uri \"%s\" inválido!" -msgid "Bad document-format \"%s\"!" -msgstr "Document-format \"%s\" inválido!" -msgid "Bad job-priority value!" -msgstr "Valor job-priority inválido!" -msgid "Bad job-state value!" -msgstr "Valor job-state inválido!" -msgid "Bad job-uri attribute \"%s\"!" -msgstr "Atributo job-uri \"%s\" inválido!" -msgid "Bad notify-pull-method \"%s\"!" -msgstr "Notify-pull-method \"%s\" inválido!" -msgid "Bad notify-recipient-uri URI \"%s\"!" -msgstr "Notify-recipient-uri URI \"%s\" inválido!" -msgid "Bad number-up value %d." -msgstr "Valor number-up inválido %d." -msgid "Bad option + choice on line %d!" -msgstr "Opção + escolha inválidas na linha %d!" -msgid "Bad page-ranges values %d-%d." -msgstr "Valores page-ranges inválidos %d-%d." -msgid "Bad port-monitor \"%s\"!" -msgstr "Port-monitor \"%s\" inválido!" -msgid "Bad printer-state value %d!" -msgstr "Valor printer-state inválido %d!" -msgid "Bad request version number %d.%d!" -msgstr "Número de versão pedido inválido %d.%d!" -msgid "Bad subscription ID!" -msgstr "ID de subscrição inválido!" -msgid "Banners" -msgstr "Faixas publicitárias" -msgid "Cancel RSS Subscription" -msgstr "Cancelar subscrição RSS" -msgid "Change Settings" -msgstr "Alterar especificações" -msgid "Character set \"%s\" not supported!" -msgstr "Conjunto de caracteres \"%s\" não suportado!" -msgid "Classes" -msgstr "Classes" -msgid "Commands may be abbreviated. Commands are:\n\nexit help quit status ?\n" -msgstr "É possível abreviar comandos. Comandos são:\n\nsair ajuda sair estado ?\n" -msgid "Could not scan type \"%s\"!" -msgstr "Impossível procurar tipo \"%s\"!" -msgid "Cover open." -msgstr "Tampa aberta." -msgid "Custom" -msgstr "Personalizar" -msgid "Delete Class" -msgstr "Apagar classe" -msgid "Delete Printer" -msgstr "Apagar impressora" -msgid "Destination \"%s\" is not accepting jobs." -msgstr "Destino \"%s\" não está a aceitar trabalhos." -msgid "Developer almost empty." -msgstr "Programador quase vazio." -msgid "Developer empty!" -msgstr "Programador vazio!" -msgid "Device: uri = %s\n class = %s\n info = %s\n make-and-model = %s\n device-id = %s\n" -msgstr "Periférico: uri = %s\n class = %s\n info = %s\n make-and-model = %s\n device-id = %s\n" -msgid "Door open." -msgstr "Porta aberta." -msgid "EMERG: Unable to allocate memory for page info: %s\n" -msgstr "EMERG: Impossível alocar memória para info de página: %s\n" -msgid "EMERG: Unable to allocate memory for pages array: %s\n" -msgstr "EMERG: Impossível alocar memória para matriz de páginas: %s\n" -msgid "ERROR: %ld: (canceled:%ld)\n" -msgstr "ERROR: %ld: (cancelado:%ld)\n" -msgid "ERROR: Bad %%BoundingBox: comment seen!\n" -msgstr "ERROR: Detectado comentário %%BoundingBox: inválido!\n" -msgid "ERROR: Bad %%IncludeFeature: comment!\n" -msgstr "ERROR: Detectado comentário %%IncludeFeature: inválido!\n" -msgid "ERROR: Bad %%Page: comment in file!\n" -msgstr "ERROR: Comentário %%Page: inválido no ficheiro!\n" -msgid "ERROR: Bad %%PageBoundingBox: comment in file!\n" -msgstr "ERROR: Comentário %%PageBoundingBox: inválido no ficheiro!\n" -msgid "ERROR: Bad SCSI device file \"%s\"!\n" -msgstr "ERROR: Ficheiro de periférico SCSI inválido \"%s\"!\n" -msgid "ERROR: Bad charset file %s\n" -msgstr "ERROR: Ficheiro charset inválido %s\n" -msgid "ERROR: Bad charset type %s\n" -msgstr "ERROR: Tipo charset inválido %s\n" -msgid "ERROR: Bad font description line: %s\n" -msgstr "ERROR: Linha de descrição de tipo de letra inválida: %s\n" -msgid "ERROR: Bad page setup!\n" -msgstr "ERROR: Configuração de página inválida!\n" -msgid "ERROR: Bad text direction %s\n" -msgstr "ERROR: Orientação de texto inválida %s\n" -msgid "ERROR: Bad text width %s\n" -msgstr "ERROR: Largura de texto inválida %s\n" -msgid "ERROR: Destination printer does not exist!\n" -msgstr "ERROR: Impressora de destino não existe!\n" -msgid "ERROR: Duplicate %%BoundingBox: comment seen!\n" -msgstr "ERROR: Detectado comentário %%BoundingBox: em duplicado!\n" -msgid "ERROR: Duplicate %%Pages: comment seen!\n" -msgstr "ERROR: Detectado comentário %%Pages: em duplicado!\n" -msgid "ERROR: Empty print file!\n" -msgstr "ERROR: Ficheiro de impressão vazio!\n" -msgid "ERROR: Invalid HP-GL/2 command seen, unable to print file!\n" -msgstr "ERROR: Detectado comando HP-GL/2 inválido; impossível imprimir ficheiro!\n" -msgid "ERROR: Missing %%EndProlog!\n" -msgstr "ERROR: %%EndProlog inexistente!\n" -msgid "ERROR: Missing %%EndSetup!\n" -msgstr "ERROR: %%EndSetup inexistente!\n" -msgid "ERROR: Missing device URI on command-line and no DEVICE_URI environment variable!\n" -msgstr "ERROR: URI de periférico inexistente em command-line e sem variável de ambiente DEVICE_URI!\n" -msgid "ERROR: No %%BoundingBox: comment in header!\n" -msgstr "ERROR: Sem comentário %%BoundingBox: no cabeçalho!\n" -msgid "ERROR: No %%Pages: comment in header!\n" -msgstr "ERROR: Sem comentário %%Pages: no cabeçalho!\n" -msgid "ERROR: No device URI found in argv[0] or in DEVICE_URI environment variable!\n" -msgstr "ERROR: Sem URI de periférico em argv[0] ou na variável de ambiente DEVICE_URI!\n" -msgid "ERROR: No pages found!\n" -msgstr "ERROR: Sem páginas!\n" -msgid "ERROR: Out of paper!\n" -msgstr "ERROR: Sem papel!\n" -msgid "ERROR: PRINTER environment variable not defined!\n" -msgstr "ERROR: Variável de ambiente PRINTER não definida!\n" -msgid "ERROR: Print file was not accepted (%s)!\n" -msgstr "ERROR: Ficheiro de impressão não foi aceite (%s)!\n" -msgid "ERROR: Printer not responding!\n" -msgstr "ERROR: Impressora não responde!\n" -msgid "ERROR: Remote host did not accept control file (%d)\n" -msgstr "ERROR: Host remoto não aceitou ficheiro de controlo (%d)\n" -msgid "ERROR: Remote host did not accept data file (%d)\n" -msgstr "ERROR: Host remoto não aceitou ficheiro de dados (%d)\n" -msgid "ERROR: Unable to add file %d to job: %s\n" -msgstr "ERROR: Impossível adicionar ficheiro %d ao trabalho: %s\n" -msgid "ERROR: Unable to cancel job %d: %s\n" -msgstr "ERROR: Impossível cancelar trabalho %d: %s\n" -msgid "ERROR: Unable to create temporary compressed print file: %s\n" -msgstr "ERROR: Impossível criar ficheiro de impressão comprimido temporário: %s\n" -msgid "ERROR: Unable to create temporary file - %s.\n" -msgstr "ERROR: Impossível criar ficheiro temporário - %s.\n" -msgid "ERROR: Unable to create temporary file: %s\n" -msgstr "ERROR: Impossível criar ficheiro temporário: %s.\n" -msgid "ERROR: Unable to exec pictwpstops: %s\n" -msgstr "ERROR: Impossível executar pictwpstops: %s\n" -msgid "ERROR: Unable to fork pictwpstops: %s\n" -msgstr "ERROR: Impossível separar pictwpstops: %s\n" -msgid "ERROR: Unable to get PPD file for printer \"%s\" - %s.\n" -msgstr "ERROR: Impossível obter ficheiro PPD para impressora \"%s\" - %s.\n" -msgid "ERROR: Unable to get job %d attributes (%s)!\n" -msgstr "ERROR: Impossível obter atributos do trabalho %d (%s)!\n" -msgid "ERROR: Unable to get printer status (%s)!\n" -msgstr "ERROR: Impossível obter estado da impressora (%s)!\n" -msgid "ERROR: Unable to locate printer '%s'!\n" -msgstr "ERROR: Impossível localizar impressora '%s'!\n" -msgid "ERROR: Unable to open \"%s\" - %s\n" -msgstr "ERROR: Impossível abrir \"%s\" - %s\n" -msgid "ERROR: Unable to open %s: %s\n" -msgstr "ERROR: Impossível abrir %s: %s\n" -msgid "ERROR: Unable to open device file \"%s\": %s\n" -msgstr "ERROR: Impossível abrir ficheiro de periférico \"%s\": %s\n" -msgid "ERROR: Unable to open file \"%s\" - %s\n" -msgstr "ERROR: Impossível abrir ficheiro \"%s\" - %s\n" -msgid "ERROR: Unable to open file \"%s\": %s\n" -msgstr "ERROR: Impossível abrir ficheiro \"%s\": %s\n" -msgid "ERROR: Unable to open image file for printing!\n" -msgstr "ERROR: Impossível abrir ficheiro de imagem para impressão!\n" -msgid "ERROR: Unable to open print file \"%s\": %s\n" -msgstr "ERROR: Impossível abrir ficheiro de impressão \"%s\": %s\n" -msgid "ERROR: Unable to open print file %s - %s\n" -msgstr "ERROR: Impossível abrir ficheiro de impressão %s - %s\n" -msgid "ERROR: Unable to open print file %s: %s\n" -msgstr "ERROR: Impossível abrir ficheiro de impressão %s: %s\n" -msgid "ERROR: Unable to open temporary compressed print file: %s\n" -msgstr "ERROR: Impossível abrir ficheiro de impressão comprimido temporário: %s\n" -msgid "ERROR: Unable to seek to offset %ld in file - %s\n" -msgstr "ERROR: Impossível atingir offset %ld no ficheiro - %s\n" -msgid "ERROR: Unable to seek to offset %lld in file - %s\n" -msgstr "ERROR: Impossível atingir offset %lld no ficheiro - %s\n" -msgid "ERROR: Unable to send print data (%d)\n" -msgstr "ERROR: Impossível enviar dados de impressão (%d)\n" -msgid "ERROR: Unable to wait for pictwpstops: %s\n" -msgstr "ERROR: Impossível aguardar por pictwpstops: %s\n" -msgid "ERROR: Unable to write %d bytes to \"%s\": %s\n" -msgstr "ERROR: Impossível escrever %d bytes em \"%s\": %s\n" -msgid "ERROR: Unable to write print data: %s\n" -msgstr "ERROR: Impossível escrever dados de impressão: %s\n" -msgid "ERROR: Unable to write raster data to driver!\n" -msgstr "ERROR: Impossível escrever dados de retícula no recurso!\n" -msgid "ERROR: Unable to write uncompressed document data: %s\n" -msgstr "ERROR: Impossível escrever dados de documento não comprimidos: %s\n" -msgid "ERROR: Unknown encryption option value \"%s\"!\n" -msgstr "ERROR: Valor de opção de encriptação desconhecido \"%s\"!\n" -msgid "ERROR: Unknown file order \"%s\"\n" -msgstr "ERROR: Ordem de ficheiro desconhecida \"%s\"\n" -msgid "ERROR: Unknown format character \"%c\"\n" -msgstr "ERROR: Caracteres de formato desconhecido \"%c\"\n" -msgid "ERROR: Unknown option \"%s\" with value \"%s\"!\n" -msgstr "ERROR: Opção desconhecida \"%s\" com valor \"%s\"!\n" -msgid "ERROR: Unknown print mode \"%s\"\n" -msgstr "ERROR: Modo de impressão desconhecido \"%s\"\n" -msgid "ERROR: Unknown version option value \"%s\"!\n" -msgstr "ERROR: Valor de opção de versão desconhecido \"%s\"!\n" -msgid "ERROR: Unsupported brightness value %s, using brightness=100!\n" -msgstr "ERROR: Valor de brilho não suportado %s ao utilizar brilho=100!\n" -msgid "ERROR: Unsupported gamma value %s, using gamma=1000!\n" -msgstr "ERROR: Valor gama não suportado %s ao utilizar gama=1000!\n" -msgid "ERROR: Unsupported number-up value %d, using number-up=1!\n" -msgstr "ERROR: Valor number-up não suportado %d ao utilizar number-up=1!\n" -msgid "ERROR: Unsupported number-up-layout value %s, using number-up-layout=lrtb!\n" -msgstr "ERROR: Valor number-up-layout não suportado %s ao utilizar number-up-layout=lrtb!\n" -msgid "ERROR: Unsupported page-border value %s, using page-border=none!\n" -msgstr "ERROR: Valor page-border não suportado %s ao utilizar page-border=none!\n" -msgid "ERROR: doc_printf overflow (%d bytes) detected, aborting!\n" -msgstr "ERROR: Detectado excesso doc_printf (%d bytes); a interromper!\n" -msgid "ERROR: pictwpstops exited on signal %d!\n" -msgstr "ERROR: pictwpstops saiu ao sinal %d!\n" -msgid "ERROR: pictwpstops exited with status %d!\n" -msgstr "ERROR: pictwpstops saiu com o estado %d!\n" -msgid "ERROR: recoverable: Unable to connect to printer; will retry in 30 seconds...\n" -msgstr "ERROR: recuperável: Impossível ligar à impressora; nova tentativa dentro de 30 segundos...\n" -msgid "ERROR: select() returned %d\n" -msgstr "ERROR: selecção() devolveu %d\n" -msgid "Edit Configuration File" -msgstr "Editar ficheiro de configuração" -msgid "Empty PPD file!" -msgstr "Ficheiro PPD vazio!" -msgid "Ending Banner" -msgstr "Terminar faixa publicitária" -msgid "Enter old password:" -msgstr "Introduza palavra-passe antiga:" -msgid "Enter password again:" -msgstr "Introduza palavra-passe novamente:" -msgid "Enter password:" -msgstr "Introduza palavra-passe:" -msgid "Enter your username and password or the root username and password to access this page. If you are using Kerberos authentication, make sure you have a valid Kerberos ticket." -msgstr "Introduza o seu nome de utilizador e palavra-passe ou o nome de utilizador e palavra-passe da raiz para aceder a esta página. Se utilizar a autenticação Kerberos, certifique-se que tem um ticket de Kerberos válido." -msgid "Error Policy" -msgstr "Política de Erros" -msgid "Error: need hostname after '-h' option!\n" -msgstr "Erro: necessário nome de host após opção '-h'!\n" -msgid "Export Printers to Samba" -msgstr "Exportar Impressoras para Samba" -msgid "FAIL\n" -msgstr "FAIL\n" -msgid "FATAL: Could not load %s\n" -msgstr "FATAL: Impossível carregar %s\n" -msgid "File device URIs have been disabled! To enable, see the FileDevice directive in \"%s/cupsd.conf\"." -msgstr "URIs do periférico do ficheiro foram desactivados! Para activar, consulte a directiva FileDevice em \"%s/cupsd.conf\"." -msgid "Fuser temperature high!" -msgstr "Temperatura do fusor elevada!" -msgid "Fuser temperature low!" -msgstr "Temperatura do fusor baixa!" -msgid "General" -msgstr "Geral" -msgid "Got a printer-uri attribute but no job-id!" -msgstr "Obtive um atributo printer-uri, mas não job-id!" -msgid "Help" -msgstr "Ajuda" -msgid "INFO: Attempting to connect to host %s for printer %s\n" -msgstr "INFO: Tentativa de ligar ao host %s para impressora %s\n" -msgid "INFO: Attempting to connect to host %s on port %d\n" -msgstr "INFO: Tentativa de ligar ao host %s na porta %d\n" -msgid "INFO: Canceling print job...\n" -msgstr "INFO: A cancelar trabalho de impressão...\n" -msgid "INFO: Connected to %s...\n" -msgstr "INFO: Ligado a %s...\n" -msgid "INFO: Connecting to %s on port %d...\n" -msgstr "INFO: A ligar a %s na porta %d...\n" -msgid "INFO: Control file sent successfully\n" -msgstr "INFO: Ficheiro de controlo enviado com êxito\n" -msgid "INFO: Data file sent successfully\n" -msgstr "INFO: Ficheiro de dados enviado com êxito\n" -msgid "INFO: Formatting page %d...\n" -msgstr "INFO: A formatar página %d...\n" -msgid "INFO: Loading image file...\n" -msgstr "INFO: A carregar ficheiro de imagem...\n" -msgid "INFO: Print file sent, waiting for printer to finish...\n" -msgstr "INFO: Ficheiro de impressão enviado; a aguardar conclusão da impressora...\n" -msgid "INFO: Printer busy (status:0x%08x)\n" -msgstr "INFO: Impressora ocupada (estado:0x%08x)\n" -msgid "INFO: Printer busy; will retry in 10 seconds...\n" -msgstr "INFO: Impressora ocupada; nova tentativa dentro de 10 segundos...\n" -msgid "INFO: Printer busy; will retry in 30 seconds...\n" -msgstr "INFO: Impressora ocupada; nova tentativa dentro de 30 segundos...\n" -msgid "INFO: Printer busy; will retry in 5 seconds...\n" -msgstr "INFO: Impressora ocupada; nova tentativa dentro de 5 segundos...\n" -msgid "INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n" -msgstr "INFO: Impressora não suporta IPP/1.1; a tentar IPP/1.0...\n" -msgid "INFO: Printer is busy; will retry in 5 seconds...\n" -msgstr "INFO: Impressora está ocupada; nova tentativa dentro de 5 segundos...\n" -msgid "INFO: Printer is currently off-line.\n" -msgstr "INFO: Impressora está actualmente sem ligação.\n" -msgid "INFO: Printer is now on-line.\n" -msgstr "INFO: Impressora tem agora ligação.\n" -msgid "INFO: Printer not connected; will retry in 30 seconds...\n" -msgstr "INFO: Impressora sem ligação; nova tentativa dentro de 30 segundos...\n" -msgid "INFO: Printing page %d, %d%% complete...\n" -msgstr "INFO: A imprimir página %d, %d%% concluído...\n" -msgid "INFO: Printing page %d...\n" -msgstr "INFO: A imprimir página %d...\n" -msgid "INFO: Ready to print.\n" -msgstr "INFO: Preparada para imprimir.\n" -msgid "INFO: Sending control file (%lu bytes)\n" -msgstr "INFO: A enviar ficheiro de controlo (%lu bytes)\n" -msgid "INFO: Sending control file (%u bytes)\n" -msgstr "INFO: A enviar ficheiro de controlo (%u bytes)\n" -msgid "INFO: Sending data\n" -msgstr "INFO: A enviar dados\n" -msgid "INFO: Sending data file (%ld bytes)\n" -msgstr "INFO: A enviar ficheiro de dados (%ld bytes)\n" -msgid "INFO: Sending data file (%lld bytes)\n" -msgstr "INFO: A enviar ficheiro de dados (%lld bytes)\n" -msgid "INFO: Sent print file, %ld bytes...\n" -msgstr "INFO: Ficheiro de impressão enviado, %ld bytes...\n" -msgid "INFO: Sent print file, %lld bytes...\n" -msgstr "INFO: Ficheiro de impressão enviado, %lld bytes...\n" -msgid "INFO: Spooling LPR job, %.0f%% complete...\n" -msgstr "INFO: A processar trabalho LPR, %.0f%% concluído...\n" -msgid "INFO: Unable to contact printer, queuing on next printer in class...\n" -msgstr "INFO: Impossível contactar impressora; a colocar em fila na próxima impressora na classe...\n" -msgid "INFO: Waiting for job to complete...\n" -msgstr "INFO: A aguardar conclusão do trabalho...\n" -msgid "Illegal control character" -msgstr "Carácter de controlo ilegal" -msgid "Illegal main keyword string" -msgstr "Cadeia de palavra-chave principal ilegal" -msgid "Illegal option keyword string" -msgstr "Cadeia de palavra-chave de opção ilegal" -msgid "Illegal translation string" -msgstr "Cadeia de tradução ilegal" -msgid "Illegal whitespace character" -msgstr "Carácter de espaço em branco ilegal" -msgid "Ink/toner almost empty." -msgstr "Tinta/toner quase vazio." -msgid "Ink/toner empty!" -msgstr "Tinta/toner vazio!" -msgid "Ink/toner waste bin almost full." -msgstr "Receptáculo de tinta/toner quase cheio." -msgid "Ink/toner waste bin full!" -msgstr "Receptáculo de tinta/toner cheio!" -msgid "Interlock open." -msgstr "Bloqueio aberto." -msgid "Internal error" -msgstr "Erro interno" -msgid "JCL" -msgstr "JCL" -msgid "Job #%d cannot be restarted - no files!" -msgstr "Impossível reiniciar trabalho #%d - sem ficheiros!" -msgid "Job #%d does not exist!" -msgstr "Trabalho #%d não existe!" -msgid "Job #%d is already aborted - can't cancel." -msgstr "Trabalho #%d já interrompido - impossível cancelar." -msgid "Job #%d is already canceled - can't cancel." -msgstr "Trabalho #%d já cancelado - impossível cancelar." -msgid "Job #%d is already completed - can't cancel." -msgstr "Trabalho #%d já concluído - impossível cancelar." -msgid "Job #%d is finished and cannot be altered!" -msgstr "Trabalho #%d concluído; não é possível alterar!" -msgid "Job #%d is not complete!" -msgstr "Trabalho #%d não concluído!" -msgid "Job #%d is not held for authentication!" -msgstr "Trabalho #%d não retido para autenticação!" -msgid "Job #%d is not held!" -msgstr "Trabalho #%d não retido!" -msgid "Job #%s does not exist!" -msgstr "Trabalho #%s não existe!" -msgid "Job %d not found!" -msgstr "Trabalho %d não encontrado!" -msgid "Job Completed" -msgstr "Trabalho concluído" -msgid "Job Created" -msgstr "Trabalho criado" -msgid "Job Options Changed" -msgstr "Opções de trabalho alteradas" -msgid "Job Stopped" -msgstr "Trabalho parado" -msgid "Job is completed and cannot be changed." -msgstr "Trabalho concluído; não é possível alterar." -msgid "Job operation failed:" -msgstr "Operação de trabalho falhou:" -msgid "Job state cannot be changed." -msgstr "Impossível alterar estado do trabalho." -msgid "Job subscriptions cannot be renewed!" -msgstr "Impossível renovar subscrições do trabalho!" -msgid "Jobs" -msgstr "Trabalhos" -msgid "Language \"%s\" not supported!" -msgstr "Idioma \"%s\" não suportado!" -msgid "Line longer than the maximum allowed (255 characters)" -msgstr "Linha excede máximo permitido (255 caracteres)" -msgid "List Available Printers" -msgstr "Apresentar impressoras disponíveis" -msgid "Media Size" -msgstr "Tamanho do suporte" -msgid "Media Source" -msgstr "Origem do suporte" -msgid "Media Type" -msgstr "Tipo de suporte" -msgid "Media jam!" -msgstr "Suporte encravado!" -msgid "Media tray almost empty." -msgstr "Tabuleiro de suporte quase vazio." -msgid "Media tray empty!" -msgstr "Tabuleiro de suporte vazio!" -msgid "Media tray missing!" -msgstr "Tabuleiro de suporte inexistente!" -msgid "Media tray needs to be filled." -msgstr "É necessário encher o tabuleiro de suporte." -msgid "Memory allocation error" -msgstr "Erro de alocação de memória" -msgid "Missing PPD-Adobe-4.x header" -msgstr "Cabeçalho PPD-Adobe-4.x inexistente" -msgid "Missing asterisk in column 1" -msgstr "Asterisco inexistente na coluna 1" -msgid "Missing double quote on line %d!" -msgstr "Aspas inexistentes na linha %d!" -msgid "Missing form variable!" -msgstr "Variável de formato inexistente!" -msgid "Missing notify-subscription-ids attribute!" -msgstr "Atributo notify-subscription-ids inexistente!" -msgid "Missing requesting-user-name attribute!" -msgstr "Atributo requesting-user-name inexistente!" -msgid "Missing required attributes!" -msgstr "Atributos necessários inexistentes!" -msgid "Missing value on line %d!" -msgstr "Valor inexistente na linha %d!" -msgid "Missing value string" -msgstr "Cadeia de valor inexistente" -msgid "Model: name = %s\n natural_language = %s\n make-and-model = %s\n device-id = %s\n" -msgstr "Modelo: name = %s\n natural_language = %s\n make-and-model = %s\n device-id = %s\n" -msgid "Modify Class" -msgstr "Modificar classe" -msgid "Modify Printer" -msgstr "Modificar impressora" -msgid "Move All Jobs" -msgstr "Mover todos os trabalhos" -msgid "Move Job" -msgstr "Mover trabalho" -msgid "NOTICE: Print file accepted - job ID %d.\n" -msgstr "NOTICE: Ficheiro de impressão aceite - ID do trabalho %d.\n" -msgid "NOTICE: Print file accepted - job ID unknown.\n" -msgstr "NOTICE: Ficheiro de impressão aceite - ID do trabalho desconhecido.\n" -msgid "NULL PPD file pointer" -msgstr "Ponteiro do ficheiro PPD NULL" -msgid "No" -msgstr "Não" -msgid "No Windows printer drivers are installed!" -msgstr "Sem controladores de impressora Windows instalados!" -msgid "No active jobs on %s!" -msgstr "Sem trabalhos activos em %s!" -msgid "No attributes in request!" -msgstr "Sem atributos no pedido!" -msgid "No authentication information provided!" -msgstr "Sem informações de autenticação fornecidas!" -msgid "No default printer" -msgstr "Sem impressora predefinida" -msgid "No destinations added." -msgstr "Sem destinos adicionados." -msgid "No file!?!" -msgstr "Sem ficheiro!?!" -msgid "No subscription attributes in request!" -msgstr "Sem atributos de subscrição no pedido!" -msgid "No subscriptions found." -msgstr "Sem subscrições." -msgid "None" -msgstr "Sem" -msgid "Not allowed to print." -msgstr "Sem permissão para imprimir." -msgid "OK" -msgstr "OK" -msgid "OPC almost at end-of-life." -msgstr "OPC quase em fim de vida." -msgid "OPC at end-of-life!" -msgstr "OPC em fim de vida!" -msgid "OpenGroup without a CloseGroup first" -msgstr "OpenGroup sem um CloseGroup primeiro" -msgid "OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first" -msgstr "OpenUI/JCLOpenUI sem um CloseUI/JCLCloseUI primeiro" -msgid "Operation Policy" -msgstr "Política de Operação" -msgid "Options Installed" -msgstr "Opções instaladas" -msgid "Out of toner!" -msgstr "Sem toner!" -msgid "Output Mode" -msgstr "Modo de saída" -msgid "Output bin almost full." -msgstr "Receptáculo de saída quase cheio." -msgid "Output bin full!" -msgstr "Receptáculo de saída cheio!" -msgid "Output for printer %s is sent to %s\n" -msgstr "Saída de impressora %s enviada para %s\n" -msgid "Output for printer %s is sent to remote printer %s on %s\n" -msgstr "Saída de impressora %s enviada para impressora remota %s em %s\n" -msgid "Output for printer %s/%s is sent to %s\n" -msgstr "Saída de impressora %s/%s enviada para %s\n" -msgid "Output for printer %s/%s is sent to remote printer %s on %s\n" -msgstr "Saída de impressora %s/%s enviada para impressora remota %s em %s\n" -msgid "Output tray missing!" -msgstr "Tabuleiro de saída inexistente!" -msgid "PASS\n" -msgstr "PASS\n" -msgid "PS Binary Protocol" -msgstr "Protocolo Binário PS" -msgid "Password for %s on %s? " -msgstr "Palavra-passe para %s em %s? " -msgid "Password for %s required to access %s via SAMBA: " -msgstr "Palavra-passe para %s requerida para aceder a %s via SAMBA: " -msgid "Policies" -msgstr "Políticas" -msgid "Print Job:" -msgstr "Imprimir trabalho:" -msgid "Print Test Page" -msgstr "Imprimir página de teste" -msgid "Printer Added" -msgstr "Impressora adicionada" -msgid "Printer Deleted" -msgstr "Impressora apagada" -msgid "Printer Maintenance" -msgstr "Manutenção da impressora" -msgid "Printer Modified" -msgstr "Impressora modificada" -msgid "Printer Stopped" -msgstr "Impressora parada" -msgid "Printer off-line." -msgstr "Impressora sem ligação." -msgid "Printer:" -msgstr "Impressora:" -msgid "Printers" -msgstr "Impressoras" -msgid "Purge Jobs" -msgstr "Limpar trabalhos" -msgid "Quota limit reached." -msgstr "Quota atingida." -msgid "Rank Owner Job File(s) Total Size\n" -msgstr "Classificação Proprietário Trabalho Ficheiro(s) Tamanho total\n" -msgid "Rank Owner Pri Job Files Total Size\n" -msgstr "Classificação Proprietário Pri Trabalho Ficheiros Tamanho total\n" -msgid "Reject Jobs" -msgstr "Rejeitar trabalhos" -msgid "Resolution" -msgstr "Resolução" -msgid "Running command: %s %s -N -A %s -c '%s'\n" -msgstr "Comando em execução: %s %s -N -A %s -c '%s'\n" -msgid "Server Restarted" -msgstr "Servidor reiniciado" -msgid "Server Security Auditing" -msgstr "Auditoria de segurança do servidor" -msgid "Server Started" -msgstr "Servidor iniciado" -msgid "Server Stopped" -msgstr "Servidor parado" -msgid "Set Allowed Users" -msgstr "Especificar utilizadores permitidos" -msgid "Set As Default" -msgstr "Predefinir" -msgid "Set Class Options" -msgstr "Especificar opções de classe" -msgid "Set Printer Options" -msgstr "Especificar opções de impressora" -msgid "Set Publishing" -msgstr "Especificar publicação" -msgid "Start Class" -msgstr "Iniciar classe" -msgid "Start Printer" -msgstr "Iniciar impressora" -msgid "Starting Banner" -msgstr "Iniciar faixa publicitária" -msgid "Stop Class" -msgstr "Parar classe" -msgid "Stop Printer" -msgstr "Parar impressora" -msgid "The PPD file \"%s\" could not be found." -msgstr "Impossível localizar o ficheiro PPD \"%s\"." -msgid "The PPD file \"%s\" could not be opened: %s" -msgstr "Impossível abrir o ficheiro PPD \"%s\": %s" -msgid "The class name may only contain up to 127 printable characters and may not contain spaces, slashes (/), or the pound sign (#)." -msgstr "O nome de classe pode ter o máximo de 127 caracteres imprimíveis e não pode ter espaços, barras (/) ou cardinal (#)." -msgid "The notify-lease-duration attribute cannot be used with job subscriptions." -msgstr "Não é possível utilizar o atributo notify-lease-duration com subscrições de trabalho." -msgid "The notify-user-data value is too large (%d > 63 octets)!" -msgstr "O valor notify-user-data é demasiado grande (%d > 63 octetos)!" -msgid "The printer name may only contain up to 127 printable characters and may not contain spaces, slashes (/), or the pound sign (#)." -msgstr "O nome de impressora pode ter o máximo de 127 caracteres imprimíveis e não pode ter espaços, barras (/) ou cardinal (#)." -msgid "The printer or class is not shared!" -msgstr "Impressora ou classe não partilhadas!" -msgid "The printer or class was not found." -msgstr "Impressora ou classe não localizadas." -msgid "The printer-uri \"%s\" contains invalid characters." -msgstr "O atributo printer-uri \"%s\" contém caracteres inválidos." -msgid "The printer-uri attribute is required!" -msgstr "Necessário atributo printer-uri!" -msgid "The printer-uri must be of the form \"ipp://HOSTNAME/classes/CLASSNAME\"." -msgstr "O atributo printer-uri deve ser do formato \"ipp://HOSTNAME/classes/CLASSNAME\"." -msgid "The printer-uri must be of the form \"ipp://HOSTNAME/printers/PRINTERNAME\"." -msgstr "O atributo printer-uri deve ser do formato \"ipp://HOSTNAME/printers/PRINTERNAME\"." -msgid "The subscription name may not contain spaces, slashes (/), question marks (?), or the pound sign (#)." -msgstr "O nome de subscrição não pode ter espaços, barras (/), pontos de interrogação (?) ou cardinal (#)." -msgid "Toner low." -msgstr "Pouco toner." -msgid "Too many active jobs." -msgstr "Demasiados trabalhos activos." -msgid "Unable to access cupsd.conf file:" -msgstr "Impossível aceder ao ficheiro cupsd.conf:" -msgid "Unable to add RSS subscription:" -msgstr "Impossível adicionar subscrição RSS:" -msgid "Unable to add class:" -msgstr "Impossível adicionar classe:" -msgid "Unable to add job for destination \"%s\"!" -msgstr "Impossível adicionar trabalho ao destino \"%s\"!" -msgid "Unable to add printer:" -msgstr "Impossível adicionar impressora:" -msgid "Unable to allocate memory for file types!" -msgstr "Impossível alocar memória para tipos de ficheiros!" -msgid "Unable to cancel RSS subscription:" -msgstr "Impossível cancelar subscrição RSS:" -msgid "Unable to change printer-is-shared attribute:" -msgstr "Impossível alterar atributo printer-is-shared:" -msgid "Unable to change printer:" -msgstr "Impossível alterar impressora:" -msgid "Unable to change server settings:" -msgstr "Impossível alterar especificações do servidor:" -msgid "Unable to copy CUPS printer driver files (%d)!" -msgstr "Impossível copiar ficheiros de recurso de impressora CUPS (%d)!" -msgid "Unable to copy PPD file - %s!" -msgstr "Impossível copiar ficheiro PPD - %s!" -msgid "Unable to copy PPD file!" -msgstr "Impossível copiar ficheiro PPD!" -msgid "Unable to copy Windows 2000 printer driver files (%d)!" -msgstr "Impossível copiar ficheiros de controladores de impressora Windows 2000 (%d)!" -msgid "Unable to copy Windows 9x printer driver files (%d)!" -msgstr "Impossível copiar ficheiros de controladores de impressora Windows 9x (%d)!" -msgid "Unable to copy interface script - %s!" -msgstr "Impossível copiar script de interface - %s!" -msgid "Unable to create temporary file:" -msgstr "Impossível criar ficheiro temporário:" -msgid "Unable to delete class:" -msgstr "Impossível apagar classe:" -msgid "Unable to delete printer:" -msgstr "Impossível apagar impressora:" -msgid "Unable to edit cupsd.conf files larger than 1MB!" -msgstr "Impossível editar ficheiros cupsd.conf com mais de 1MB!" -msgid "Unable to find destination for job!" -msgstr "Impossível localizar destino para trabalho!" -msgid "Unable to get class list:" -msgstr "Impossível obter lista de classes:" -msgid "Unable to get class status:" -msgstr "Impossível obter estado da classe:" -msgid "Unable to get list of printer drivers:" -msgstr "Impossível obter lista de recursos da impressora:" -msgid "Unable to get printer attributes:" -msgstr "Impossível obter atributos da impressora:" -msgid "Unable to get printer list:" -msgstr "Impossível obter lista de impressoras:" -msgid "Unable to get printer status:" -msgstr "Impossível obter estado da impressora:" -msgid "Unable to install Windows 2000 printer driver files (%d)!" -msgstr "Impossível instalar ficheiros de controladores de impressora Windows 2000 (%d)!" -msgid "Unable to install Windows 9x printer driver files (%d)!" -msgstr "Impossível instalar ficheiros de controladores de impressora Windows 9x (%d)!" -msgid "Unable to modify class:" -msgstr "Impossível modificar classe:" -msgid "Unable to modify printer:" -msgstr "Impossível modificar impressora:" -msgid "Unable to move job" -msgstr "Impossível mover trabalho" -msgid "Unable to move jobs" -msgstr "Impossível mover trabalhos" -msgid "Unable to open PPD file" -msgstr "Impossível abrir ficheiro PPD" -msgid "Unable to open PPD file:" -msgstr "Impossível abrir ficheiro PPD:" -msgid "Unable to open cupsd.conf file:" -msgstr "Impossível abrir ficheiro cupsd.conf:" -msgid "Unable to print test page:" -msgstr "Impossível imprimir página de teste:" -msgid "Unable to run \"%s\": %s\n" -msgstr "Impossível executar \"%s\": %s\n" -msgid "Unable to send maintenance job:" -msgstr "Impossível enviar trabalho de manutenção:" -msgid "Unable to set Windows printer driver (%d)!" -msgstr "Impossível definir controlador de impressora Windows (%d)!" -msgid "Unable to set options:" -msgstr "Impossível especificar opções:" -msgid "Unable to upload cupsd.conf file:" -msgstr "Impossível carregar ficheiro cupsd.conf:" -msgid "Unknown" -msgstr "Desconhecida" -msgid "Unknown printer error (%s)!" -msgstr "Erro de impressora desconhecido (%s)!" -msgid "Unknown printer-error-policy \"%s\"." -msgstr "Printer-error-policy desconhecida \"%s\"." -msgid "Unknown printer-op-policy \"%s\"." -msgstr "Printer-op-policy desconhecida \"%s\"." -msgid "Unsupported compression \"%s\"!" -msgstr "Compressão não suportada \"%s\"!" -msgid "Unsupported compression attribute %s!" -msgstr "Atributo de compressão não suportado %s!" -msgid "Unsupported format \"%s\"!" -msgstr "Formato não suportado \"%s\"!" -msgid "Unsupported format '%s'!" -msgstr "Formato não suportado '%s'!" -msgid "Unsupported format '%s/%s'!" -msgstr "Formato não suportado %s/%s'!" -msgid "Usage:\n\n lpadmin [-h server] -d destination\n lpadmin [-h server] -x destination\n lpadmin [-h server] -p printer [-c add-class] [-i interface] [-m model]\n [-r remove-class] [-v device] [-D description]\n [-P ppd-file] [-o name=value]\n [-u allow:user,user] [-u deny:user,user]\n\n" -msgstr "Utilização:\n\n lpadmin [-h server] -d destination\n lpadmin [-h server] -x destination\n lpadmin [-h server] -p printer [-c add-class] [-i interface] [-m model]\n [-r remove-class] [-v device] [-D description]\n [-P ppd-file] [-o name=value]\n [-u allow:user,user] [-u deny:user,user]\n\n" -msgid "Usage: %s job-id user title copies options [file]\n" -msgstr "Utilização: opções de cópias de título de utilizador %s job-id [ficheiro]\n" -msgid "Usage: %s job-id user title copies options file\n" -msgstr "Utilização: ficheiro de opções de cópias de título de utilizador %s job-id\n" -msgid "Usage: cupsaddsmb [options] printer1 ... printerN\n cupsaddsmb [options] -a\n\nOptions:\n -E Encrypt the connection to the server\n -H samba-server Use the named SAMBA server\n -U samba-user Authenticate using the named SAMBA user\n -a Export all printers\n -h cups-server Use the named CUPS server\n -v Be verbose (show commands)\n" -msgstr "Utilização: cupsaddsmb [options] printer1 ... printerN\n cupsaddsmb [options] -a\n\nOpções:\n -E Encriptar a ligação ao servidor\n -H samba-server Utilizar o servidor SAMBA\n -U samba-user Autenticar utilizando utilizador SAMBA\n -a Exportar todas as impressoras\n -h cups-server Utilizar o servidor CUPS\n -v Verboso (mostrar comandos)\n" -msgid "Usage: cupsctl [options] [param=value ... paramN=valueN]\n\nOptions:\n\n -E Enable encryption\n -U username Specify username\n -h server[:port] Specify server address\n\n --[no-]debug-logging Turn debug logging on/off\n --[no-]remote-admin Turn remote administration on/off\n --[no-]remote-any Allow/prevent access from the Internet\n --[no-]remote-printers Show/hide remote printers\n --[no-]share-printers Turn printer sharing on/off\n --[no-]user-cancel-any Allow/prevent users to cancel any job\n" -msgstr "Utilização: cupsctl [options] [param=value ... paramN=valueN]\n\nOpções:\n\n -E Activar encriptação\n -U username Especificar nome de utilizador\n -h server[:port] Especificar endereço de servidor\n\n --[no-]debug-logging Activar/desactivar registo da depuração\n --[no-]remote-admin Activar/desactivar administração remota\n --[no-]remote-any Permitir/impedir acesso a partir da Internet\n --[no-]remote-printers Mostrar/ocultar impressoras remotas\n --[no-]share-printers Activar/desactivar partilha de impressora\n --[no-]user-cancel-any Permitir/impedir utilizadores de cancelar trabalhos\n" -msgid "Usage: cupsd [-c config-file] [-f] [-F] [-h] [-l]\n\n-c config-file Load alternate configuration file\n-f Run in the foreground\n-F Run in the foreground but detach\n-h Show this usage message\n-l Run cupsd from launchd(8)\n" -msgstr "Utilização: cupsd [-c config-file] [-f] [-F] [-h] [-l]\n\n-c config-file Carregar ficheiro de configuração alternativa\n-f Executar em primeiro plano\n-F Executar em primeiro plano, mas separar\n-h Mostrar esta mensagem de utilização\n-l Executar cupsd a partir de launchd(8)\n" -msgid "Usage: cupsfilter -m mime/type [ options ] filename(s)\n\nOptions:\n\n -c cupsd.conf Set cupsd.conf file to use\n -n copies Set number of copies\n -o name=value Set option(s)\n -p filename.ppd Set PPD file\n -t title Set title\n" -msgstr "Utilização: cupsfilter -m mime/type [ options ] filename(s)\n\nOpções:\n\n -c cupsd.conf Especificar ficheiro cupsd.conf a utilizar\n -n copies Especificar número de cópias\n -o name=value Especificar opção(ões)\n -p filename.ppd Especificar ficheiro PPD\n -t title Especificar título\n" -msgid "Usage: cupstestdsc [options] filename.ps [... filename.ps]\n cupstestdsc [options] -\n\nOptions:\n\n -h Show program usage\n\n Note: this program only validates the DSC comments, not the PostScript itself.\n" -msgstr "Utilização: cupstestdsc [options] filename.ps [... filename.ps]\n cupstestdsc [options] -\n\nOpções:\n\n -h Mostrar utilização de programa\n\n Nota: este programa só valida comentários DSC, não o próprio PostScript.\n" -msgid "Usage: cupstestppd [options] filename1.ppd[.gz] [... filenameN.ppd[.gz]]\n program | cupstestppd [options] -\n\nOptions:\n\n -R root-directory Set alternate root\n -W {all,none,constraints,defaults,filters,translations}\n Issue warnings instead of errors\n -q Run silently\n -r Use 'relaxed' open mode\n -v Be slightly verbose\n -vv Be very verbose\n" -msgstr "Utilização: cupstestppd [options] filename1.ppd[.gz] [... filenameN.ppd[.gz]]\n programa | cupstestppd [options] -\n\nOpções:\n\n -R root-directory Especificar raiz alternativa\n -W {tudo, sem, restrições, predefinições, filtros, traduções}\n Emitir avisos em vez de erros\n -q Executar silenciosamente\n -r Utilizar modo aberto 'descontraído'\n -v Ligeiramente verboso\n -vv Muito verboso\n" -msgid "Usage: lpmove job/src dest\n" -msgstr "Utilização: lpmove job/src dest\n" -msgid "Usage: lpoptions [-h server] [-E] -d printer\n lpoptions [-h server] [-E] [-p printer] -l\n lpoptions [-h server] [-E] -p printer -o option[=value] ...\n lpoptions [-h server] [-E] -x printer\n" -msgstr "Utilização: lpoptions [-h server] [-E] -d printer\n lpoptions [-h server] [-E] [-p printer] -l\n lpoptions [-h server] [-E] -p printer -o option[=value] ...\n lpoptions [-h server] [-E] -x printer\n" -msgid "Usage: lppasswd [-g groupname]\n" -msgstr "Utilização: lppasswd [-g groupname]\n" -msgid "Usage: lppasswd [-g groupname] [username]\n lppasswd [-g groupname] -a [username]\n lppasswd [-g groupname] -x [username]\n" -msgstr "Utilização: lppasswd [-g groupname] [username]\n lppasswd [-g groupname] -a [username]\n lppasswd [-g groupname] -x [username]\n" -msgid "Usage: lpq [-P dest] [-U username] [-h hostname[:port]] [-l] [+interval]\n" -msgstr "Utilização: lpq [-P dest] [-U username] [-h hostname[:port]] [-l] [+interval]\n" -msgid "Usage: snmp [host-or-ip-address]\n" -msgstr "Utilização: snmp [host-or-ip-address]\n" -msgid "WARNING: Boolean expected for waiteof option \"%s\"\n" -msgstr "WARNING: Booleano esperado para opção waiteof \"%s\"\n" -msgid "WARNING: Couldn't create read channel\n" -msgstr "WARNING: Impossível criar canal de leitura\n" -msgid "WARNING: Couldn't create side channel\n" -msgstr "WARNING: Impossível criar canal lateral\n" -msgid "WARNING: Failed to read side-channel request!\n" -msgstr "WARNING: Falha ao ler pedido de side-channel!\n" -msgid "WARNING: Option \"%s\" cannot be included via IncludeFeature!\n" -msgstr "WARNING: Impossível incluir opção \"%s\" via IncludeFeature!\n" -msgid "WARNING: Remote host did not respond with command status byte after %d seconds!\n" -msgstr "WARNING: Host remoto não respondeu com byte de estado de comando após %d segundos!\n" -msgid "WARNING: Remote host did not respond with control status byte after %d seconds!\n" -msgstr "WARNING: Host remoto não respondeu com byte de estado de controlo após %d segundos!\n" -msgid "WARNING: Remote host did not respond with data status byte after %d seconds!\n" -msgstr "WARNING: Host remoto não respondeu com byte de estado de dados após %d segundos!\n" -msgid "WARNING: SCSI command timed out (%d); retrying...\n" -msgstr "WARNING: Comando SCSI sem resposta (%d); a tentar de novo...\n" -msgid "WARNING: This document does not conform to the Adobe Document Structuring Conventions and may not print correctly!\n" -msgstr "WARNING: Este documento não está de acordo com ADSC e pode não ser impresso correctamente!\n" -msgid "WARNING: Unknown choice \"%s\" for option \"%s\"!\n" -msgstr "WARNING: Escolha desconhecida \"%s\" para opção \"%s\"!\n" -msgid "WARNING: Unknown option \"%s\"!\n" -msgstr "WARNING: Opção desconhecida \"%s\"!\n" -msgid "WARNING: Unsupported baud rate %s!\n" -msgstr "WARNING: Taxa baud não suportada %s!\n" -msgid "WARNING: recoverable: Network host '%s' is busy; will retry in %d seconds...\n" -msgstr "WARNING: recuperável: host de rede '%s' ocupado; nova tentativa dentro de %d segundos...\n" -msgid "Warning, no Windows 2000 printer drivers are installed!" -msgstr "Aviso, sem controladores de impressora Windows 2000 instalados!" -msgid "Yes" -msgstr "Sim" -msgid "You must access this page using the URL https://%s:%d%s." -msgstr "Deve aceder a esta página utilizando o URL https://%s:%d%s." -msgid "aborted" -msgstr "interrompido" -msgid "canceled" -msgstr "cancelado" -msgid "completed" -msgstr "concluído" -msgid "cups-deviced failed to execute." -msgstr "cups-deviced falhou a execução." -msgid "cups-driverd failed to execute." -msgstr "cups-driverd falhou a execução." -msgid "cupsaddsmb: No PPD file for printer \"%s\" - %s\n" -msgstr "cupsaddsmb: Sem ficheiro PPD para impressora \"%s\" - %s\n" -msgid "cupsctl: Unknown option \"%s\"!\n" -msgstr "cupsctl: Opção desconhecida \"%s\"!\n" -msgid "cupsctl: Unknown option \"-%c\"!\n" -msgstr "cupsctl: Opção desconhecida \"-%c\"!\n" -msgid "cupsd: Expected config filename after \"-c\" option!\n" -msgstr "cupsd: Nome de ficheiro config esperado após opção \"-c\"!\n" -msgid "cupsd: Unknown argument \"%s\" - aborting!\n" -msgstr "cupsd: Argumento desconhecido \"%s\" - a interromper!\n" -msgid "cupsd: Unknown option \"%c\" - aborting!\n" -msgstr "cupsd: Opção desconhecida \"%c\" - a interromper!\n" -msgid "cupsd: launchd(8) support not compiled in, running in normal mode.\n" -msgstr "cupsd: suporte launchd(8) não compilado; execução em modo normal.\n" -msgid "cupsfilter: No filter to convert from %s/%s to %s/%s!\n" -msgstr "cupsfilter: Sem filtro para converter de %s/%s para %s/%s!\n" -msgid "cupsfilter: Only one filename can be specified!\n" -msgstr "cupsfilter: Só pode ser especificado um nome de ficheiro!\n" -msgid "cupsfilter: Unable to determine MIME type of \"%s\"!\n" -msgstr "cupsfilter: Impossível determinar tipo MIME de \"%s\"!\n" -msgid "cupsfilter: Unable to read MIME database from \"%s\"!\n" -msgstr "cupsfilter: Impossível ler base de dados MIME a partir de \"%s\"!\n" -msgid "cupsfilter: Unknown destination MIME type %s/%s!\n" -msgstr "cupsfilter: Destino desconhecido de tipo MIME %s/%s!\n" -msgid "cupstestppd: The -q option is incompatible with the -v option.\n" -msgstr "cupstestppd: Opção -q incompatível com opção -v.\n" -msgid "cupstestppd: The -v option is incompatible with the -q option.\n" -msgstr "cupstestppd: Opção -v incompatível com opção -q.\n" -msgid "device for %s/%s: %s\n" -msgstr "periférico para %s/%s: %s\n" -msgid "device for %s: %s\n" -msgstr "periférico para %s: %s\n" -msgid "held" -msgstr "reter" -msgid "help\t\tget help on commands\n" -msgstr "help\t\tobter ajuda sobre comandos\n" -msgid "idle" -msgstr "inactivo" -msgid "job-printer-uri attribute missing!" -msgstr "atributo job-printer-uri inexistente!" -msgid "lpadmin: Class name can only contain printable characters!\n" -msgstr "lpadmin: Nome de classe só pode ter caracteres imprimíveis!\n" -msgid "lpadmin: Expected PPD after '-P' option!\n" -msgstr "lpadmin: PPD esperado após opção '-P'!\n" -msgid "lpadmin: Expected allow/deny:userlist after '-u' option!\n" -msgstr "lpadmin: Permitir/negar:lista de utilizadores esperado após opção '-u'!\n" -msgid "lpadmin: Expected class after '-r' option!\n" -msgstr "lpadmin: Classe esperada após opção '-r'!\n" -msgid "lpadmin: Expected class name after '-c' option!\n" -msgstr "lpadmin: Nome de classe esperado após opção '-c'!\n" -msgid "lpadmin: Expected description after '-D' option!\n" -msgstr "lpadmin: Descrição esperada após opção '-D'!\n" -msgid "lpadmin: Expected device URI after '-v' option!\n" -msgstr "lpadmin: URI de periférico esperado após opção '-v'!\n" -msgid "lpadmin: Expected file type(s) after '-I' option!\n" -msgstr "lpadmin: Tipo(s) de ficheiro esperados após opção '-I'!\n" -msgid "lpadmin: Expected hostname after '-h' option!\n" -msgstr "lpadmin: Nome de host esperado após opção '-h'!\n" -msgid "lpadmin: Expected interface after '-i' option!\n" -msgstr "lpadmin: Interface esperada após opção '-i'!\n" -msgid "lpadmin: Expected location after '-L' option!\n" -msgstr "lpadmin: Localização esperada após opção '-L'!\n" -msgid "lpadmin: Expected model after '-m' option!\n" -msgstr "lpadmin: Modelo esperado após opção '-m'!\n" -msgid "lpadmin: Expected name=value after '-o' option!\n" -msgstr "lpadmin: Nome=valor esperado após opção '-o'!\n" -msgid "lpadmin: Expected printer after '-p' option!\n" -msgstr "lpadmin: Impressora esperada após opção '-p'!\n" -msgid "lpadmin: Expected printer name after '-d' option!\n" -msgstr "lpadmin: Nome de impressora esperado após opção '-d'!\n" -msgid "lpadmin: Expected printer or class after '-x' option!\n" -msgstr "lpadmin: Impressora ou classe esperadas após opção '-x'!\n" -msgid "lpadmin: No member names were seen!\n" -msgstr "lpadmin: Sem nomes de membro detectados!\n" -msgid "lpadmin: Printer %s is already a member of class %s.\n" -msgstr "lpadmin: Impressora %s já é membro da classe %s.\n" -msgid "lpadmin: Printer %s is not a member of class %s.\n" -msgstr "lpadmin: Impressora %s não é membro da classe %s.\n" -msgid "lpadmin: Printer name can only contain printable characters!\n" -msgstr "lpadmin: Nome de impressora só pode ter caracteres imprimíveis!\n" -msgid "lpadmin: Unable to add a printer to the class:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível adicionar impressora à classe:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to connect to server: %s\n" -msgstr "lpadmin: Impossível ligar ao servidor: %s\n" -msgid "lpadmin: Unable to create temporary file - %s\n" -msgstr "lpadmin: Impossível criar ficheiro temporário - %s\n" -msgid "lpadmin: Unable to create temporary file: %s\n" -msgstr "lpadmin: Impossível criar ficheiro temporário: %s\n" -msgid "lpadmin: Unable to open PPD file \"%s\" - %s\n" -msgstr "lpadmin: Impossível abrir ficheiro PPD \"%s\" - %s\n" -msgid "lpadmin: Unable to open file \"%s\": %s\n" -msgstr "lpadmin: Impossível abrir ficheiro \"%s\": %s\n" -msgid "lpadmin: Unable to remove a printer from the class:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível remover impressora da classe:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to set the PPD file:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível especificar ficheiro PPD:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to set the device URI:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível especificar URI de periférico:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to set the interface script or PPD file:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível especificar script de interface ou ficheiro PPD:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to set the interface script:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível especificar script de interface:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to set the printer description:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível especificar descrição de impressora:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to set the printer location:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível especificar localização de impressora:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unable to set the printer options:\n You must specify a printer name first!\n" -msgstr "lpadmin: Impossível especificar opções de impressora:\n Especifique primeiro um nome de impressora!\n" -msgid "lpadmin: Unknown allow/deny option \"%s\"!\n" -msgstr "lpadmin: Opção permitir/negar desconhecida \"%s\"!\n" -msgid "lpadmin: Unknown argument '%s'!\n" -msgstr "lpadmin: Argumento desconhecido '%s'!\n" -msgid "lpadmin: Unknown option '%c'!\n" -msgstr "lpadmin: Opção desconhecida '%c'!\n" -msgid "lpadmin: Warning - content type list ignored!\n" -msgstr "lpadmin: Aviso - lista de tipo de conteúdo ignorada!\n" -msgid "lpc> " -msgstr "lpc> " -msgid "lpinfo: Unable to connect to server: %s\n" -msgstr "lpinfo: Impossível ligar ao servidor: %s\n" -msgid "lpinfo: Unknown argument '%s'!\n" -msgstr "lpinfo: Argumento desconhecido '%s'!\n" -msgid "lpinfo: Unknown option '%c'!\n" -msgstr "lpinfo: Opção desconhecida '%c'!\n" -msgid "lpmove: Unable to connect to server: %s\n" -msgstr "lpmove: Impossível ligar ao servidor: %s\n" -msgid "lpmove: Unknown argument '%s'!\n" -msgstr "lpmove: Argumento desconhecido '%s'!\n" -msgid "lpmove: Unknown option '%c'!\n" -msgstr "lpmove: Opção desconhecida '%c'!\n" -msgid "lpoptions: No printers!?!\n" -msgstr "lpoptions: Sem impressoras!?!\n" -msgid "lpoptions: Unable to add printer or instance: %s\n" -msgstr "lpoptions: Impossível adicionar impressora ou instância: %s\n" -msgid "lpoptions: Unable to get PPD file for %s: %s\n" -msgstr "lpoptions: Impossível obter ficheiro PPD para %s: %s\n" -msgid "lpoptions: Unable to open PPD file for %s!\n" -msgstr "lpoptions: Impossível abrir ficheiro PPD para %s!\n" -msgid "lpoptions: Unknown printer or class!\n" -msgstr "lpoptions: Impressora ou classe desconhecidas!\n" -msgid "lppasswd: Only root can add or delete passwords!\n" -msgstr "lppasswd: Só raiz pode adicionar ou apagar palavras-passe!\n" -msgid "lppasswd: Password file busy!\n" -msgstr "lppasswd: Ficheiro de palavra-passe ocupado!\n" -msgid "lppasswd: Password file not updated!\n" -msgstr "lppasswd: Ficheiro de palavra-passe não actualizado!\n" -msgid "lppasswd: Sorry, password doesn't match!\n" -msgstr "lppasswd: Palavra-passe não corresponde!\n" -msgid "lppasswd: Sorry, password rejected.\nYour password must be at least 6 characters long, cannot contain\nyour username, and must contain at least one letter and number.\n" -msgstr "lppasswd: Palavra-passe rejeitada.\nA palavra-passe deve ter o mínimo de 6 caracteres, sem conter\no nome de utilizador, e deve ter pelo menos uma letra e um número.\n" -msgid "lppasswd: Sorry, passwords don't match!\n" -msgstr "lppasswd: Palavras-passe não correspondem!\n" -msgid "lppasswd: Unable to copy password string: %s\n" -msgstr "lppasswd: Impossível copiar cadeia de palavra-passe: %s\n" -msgid "lppasswd: Unable to open password file: %s\n" -msgstr "lppasswd: Impossível abrir ficheiro de palavra-passe: %s\n" -msgid "lppasswd: Unable to write to password file: %s\n" -msgstr "lppasswd: Impossível escrever no ficheiro de palavra-passe: %s\n" -msgid "lppasswd: failed to backup old password file: %s\n" -msgstr "lppasswd: falha ao efectuar cópia de segurança de ficheiro de palavra-passe antigo: %s\n" -msgid "lppasswd: failed to rename password file: %s\n" -msgstr "lppasswd: falha ao alterar nome de ficheiro de palavra-passe: %s\n" -msgid "lppasswd: user \"%s\" and group \"%s\" do not exist.\n" -msgstr "lppasswd: utilizador \"%s\" e grupo \"%s\" não existem.\n" -msgid "lprm: Unable to contact server!\n" -msgstr "lprm: Impossível contactar servidor!\n" -msgid "lpstat: error - %s environment variable names non-existent destination \"%s\"!\n" -msgstr "lpstat: erro - nomes de variáveis de ambiente %s inexistentes no destino \"%s\"!\n" -msgid "members of class %s:\n" -msgstr "membros da classe %s:\n" -msgid "no entries\n" -msgstr "sem entradas\n" -msgid "no system default destination\n" -msgstr "sem destino predefinido de sistema\n" -msgid "notify-events not specified!" -msgstr "notify-events não especificados!" -msgid "notify-recipient-uri URI \"%s\" uses unknown scheme!" -msgstr "notify-recipient-uri URI \"%s\" utiliza esquema desconhecido!" -msgid "notify-subscription-id %d no good!" -msgstr "notify-subscription-id %d incorrecto!" -msgid "open of %s failed: %s" -msgstr "abertura de %s falhou: %s" -msgid "pending" -msgstr "pendente" -msgid "printer %s disabled since %s -\n" -msgstr "impressora %s desactivada desde %s -\n" -msgid "printer %s is idle. enabled since %s\n" -msgstr "impressora %s inactiva. activada desde %s\n" -msgid "printer %s now printing %s-%d. enabled since %s\n" -msgstr "impressora %s agora a imprimir %s-%d. activada desde %s\n" -msgid "printer %s/%s disabled since %s -\n" -msgstr "impressora %s/%s desactivada desde %s -\n" -msgid "printer %s/%s is idle. enabled since %s\n" -msgstr "impressora %s/%s inactiva. activada desde %s\n" -msgid "printer %s/%s now printing %s-%d. enabled since %s\n" -msgstr "impressora %s/%s agora a imprimir %s-%d. activada desde %s\n" -msgid "processing" -msgstr "a processar" -msgid "request id is %s-%d (%d file(s))\n" -msgstr "id de pedido é %s-%d (%d ficheiro(s))\n" -msgid "scheduler is not running\n" -msgstr "programador não está em execução\n" -msgid "scheduler is running\n" -msgstr "programador em execução\n" -msgid "stat of %s failed: %s" -msgstr "estatística de %s falhou: %s" -msgid "status\t\tshow status of daemon and queue\n" -msgstr "status\t\tmostra estado de daemon e fila\n" -msgid "stopped" -msgstr "parado" -msgid "system default destination: %s\n" -msgstr "destino predefinido de sistema: %s\n" -msgid "system default destination: %s/%s\n" -msgstr "destino predefinido de sistema: %s/%s\n" -msgid "unknown" -msgstr "desconhecido" -msgid "untitled" -msgstr "sem nome" diff --git a/man/lpinfo.man b/man/lpinfo.man index fff2ddd48..a16df1b7f 100644 --- a/man/lpinfo.man +++ b/man/lpinfo.man @@ -3,7 +3,7 @@ .\" .\" lpinfo 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 lpinfo 8 "Common UNIX Printing System" "12 February 2006" "Apple Inc." +.TH lpinfo 8 "Common UNIX Printing System" "8 October 2008" "Apple Inc." .SH NAME lpinfo \- show available devices or drivers .SH SYNOPSIS @@ -21,14 +21,24 @@ lpinfo \- show available devices or drivers .I username ] [ -h .I server[:port] -] [ -l ] -m +] [ -l ] [ --device-id +.I device-id-string +] [ --language +.I locale +] [ --make-and-model +.I name +] [ --product +.I name +] -m .br .B lpinfo [ -E ] [ -U .I username ] [ -h .I server[:port] -] [ -l ] -v +] [ -l ] [ --timeout +.I seconds +] -v .SH DESCRIPTION \fIlpinfo\fR lists the available devices or drivers known to the CUPS server. The first form (\fI-m\fR) lists the available @@ -52,6 +62,28 @@ Selects an alternate server. -l .br Shows a "long" listing of devices or drivers. +.TP 5 +--device-id device-id-string +.br +Specifies the IEEE-1284 device ID to match when listing drivers with the +\fI-m\fR option. +.TP 5 +--language locale +.br +Specifies the language to match when listing drivers with the \fI-m\fR option. +.TP 5 +--make-and-model name +.br +Specifies the make and model to match when listing drivers with the \fI-m\fR +option. +.TP 5 +--product name +.br +Specifies the product to match when listing drivers with the \fI-m\fR option. +.TP 5 +--timeout seconds +.br +Specifies the timeout when listing devices with the \fI-v\fR option. .SH COMPATIBILITY The \fIlpinfo\fR command is unique to CUPS. .SH SEE ALSO @@ -59,7 +91,7 @@ The \fIlpinfo\fR command is unique to CUPS. .br http://localhost:631/help .SH COPYRIGHT -Copyright 2007 by Apple Inc. +Copyright 2007-2008 by Apple Inc. .\" .\" End of "$Id: lpinfo.man 7600 2008-05-20 21:06:23Z mike $". .\" diff --git a/scheduler/classes.c b/scheduler/classes.c index 07190018a..b126a08d9 100644 --- a/scheduler/classes.c +++ b/scheduler/classes.c @@ -674,14 +674,14 @@ void cupsdSaveAllClasses(void) { cups_file_t *fp; /* classes.conf file */ - char temp[1024]; /* Temporary string */ - char backup[1024]; /* classes.conf.O file */ + char temp[1024], /* Temporary string */ + backup[1024], /* printers.conf.O file */ + value[2048]; /* Value string */ cupsd_printer_t *pclass; /* Current printer class */ int i; /* Looping var */ time_t curtime; /* Current time */ struct tm *curdate; /* Current date */ cups_option_t *option; /* Current option */ - const char *ptr; /* Pointer into info/location */ /* @@ -757,53 +757,38 @@ cupsdSaveAllClasses(void) if (pclass->num_auth_info_required > 0) { - cupsFilePrintf(fp, "AuthInfoRequired %s", pclass->auth_info_required[0]); - for (i = 1; i < pclass->num_auth_info_required; i ++) - cupsFilePrintf(fp, ",%s", pclass->auth_info_required[i]); - cupsFilePutChar(fp, '\n'); - } - - if (pclass->info) - { - if ((ptr = strchr(pclass->info, '#')) != NULL) + switch (pclass->num_auth_info_required) { - /* - * Need to quote the first # in the info string... - */ - - cupsFilePuts(fp, "Info "); - cupsFileWrite(fp, pclass->info, ptr - pclass->info); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - cupsFilePutChar(fp, '\n'); + case 1 : + strlcpy(value, pclass->auth_info_required[0], sizeof(value)); + break; + + case 2 : + snprintf(value, sizeof(value), "%s,%s", + pclass->auth_info_required[0], + pclass->auth_info_required[1]); + break; + + case 3 : + default : + snprintf(value, sizeof(value), "%s,%s,%s", + pclass->auth_info_required[0], + pclass->auth_info_required[1], + pclass->auth_info_required[2]); + break; } - else - cupsFilePrintf(fp, "Info %s\n", pclass->info); + + cupsFilePutConf(fp, "AuthInfoRequired", value); } - if (pclass->location) - { - if ((ptr = strchr(pclass->info, '#')) != NULL) - { - /* - * Need to quote the first # in the location string... - */ + if (pclass->info) + cupsFilePutConf(fp, "Info", pclass->info); - cupsFilePuts(fp, "Location "); - cupsFileWrite(fp, pclass->location, ptr - pclass->location); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - cupsFilePutChar(fp, '\n'); - } - else - cupsFilePrintf(fp, "Location %s\n", pclass->location); - } + if (pclass->location) + cupsFilePutConf(fp, "Location", pclass->location); if (pclass->state == IPP_PRINTER_STOPPED) - { cupsFilePuts(fp, "State Stopped\n"); - cupsFilePrintf(fp, "StateMessage %s\n", pclass->state_message); - } else cupsFilePuts(fp, "State Idle\n"); @@ -819,46 +804,30 @@ cupsdSaveAllClasses(void) else cupsFilePuts(fp, "Shared No\n"); - cupsFilePrintf(fp, "JobSheets %s %s\n", pclass->job_sheets[0], - pclass->job_sheets[1]); - - for (i = 0; i < pclass->num_users; i ++) - { - if ((ptr = strchr(pclass->users[i], '#')) != NULL) - { - /* - * Need to quote the first # in the user string... - */ - - cupsFilePrintf(fp, "%sUser ", pclass->deny_users ? "Deny" : "Allow"); - cupsFileWrite(fp, pclass->users[i], ptr - pclass->users[i]); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - cupsFilePutChar(fp, '\n'); - } - else - cupsFilePrintf(fp, "%sUser %s\n", - pclass->deny_users ? "Deny" : "Allow", - pclass->users[i]); - } + snprintf(value, sizeof(value), "%s %s", pclass->job_sheets[0], + pclass->job_sheets[1]); + cupsFilePutConf(fp, "JobSheets", value); cupsFilePrintf(fp, "QuotaPeriod %d\n", pclass->quota_period); cupsFilePrintf(fp, "PageLimit %d\n", pclass->page_limit); cupsFilePrintf(fp, "KLimit %d\n", pclass->k_limit); for (i = 0; i < pclass->num_users; i ++) - cupsFilePrintf(fp, "%sUser %s\n", pclass->deny_users ? "Deny" : "Allow", - pclass->users[i]); + cupsFilePutConf(fp, pclass->deny_users ? "DenyUser" : "AllowUser", + pclass->users[i]); - if (pclass->op_policy) - cupsFilePrintf(fp, "OpPolicy %s\n", pclass->op_policy); + if (pclass->op_policy) + cupsFilePutConf(fp, "OpPolicy", pclass->op_policy); if (pclass->error_policy) - cupsFilePrintf(fp, "ErrorPolicy %s\n", pclass->error_policy); + cupsFilePutConf(fp, "ErrorPolicy", pclass->error_policy); for (i = pclass->num_options, option = pclass->options; i > 0; i --, option ++) - cupsFilePrintf(fp, "Option %s %s\n", option->name, option->value); + { + snprintf(value, sizeof(value), "%s %s", option->name, option->value); + cupsFilePutConf(fp, "Option", value); + } cupsFilePuts(fp, "\n"); } diff --git a/scheduler/client.c b/scheduler/client.c index f2dd9007d..4f776b48c 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -3093,10 +3093,9 @@ encrypt_client(cupsd_client_t *con) /* I - Client to encrypt */ SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */ if (SSLOptions & CUPSD_SSL_NOEMPTY) - SSL_CTX_set_options(context, SSL_OP_DONTS_INSERT_EMPTY_FRAGMENTS); + SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM); - SSL_CTX_use_certificate_chain_file(context, ServerCertificate, - SSL_FILETYPE_PEM); + SSL_CTX_use_certificate_chain_file(context, ServerCertificate); bio = BIO_new(_httpBIOMethods()); BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)HTTP(con)); diff --git a/scheduler/conf.c b/scheduler/conf.c index 0161762fe..1f44e61af 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -3247,6 +3247,7 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ "Missing value for SetEnv directive on line %d.", linenum); } +#ifdef HAVE_SSL else if (!strcasecmp(line, "SSLOptions")) { /* @@ -3262,6 +3263,7 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ "Unknown value \"%s\" for SSLOptions directive on " "line %d.", value, linenum); } +#endif /* HAVE_SSL */ else { /* diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx index 7742abc93..3ee297410 100644 --- a/scheduler/cups-driverd.cxx +++ b/scheduler/cups-driverd.cxx @@ -18,18 +18,23 @@ * * Contents: * - * main() - Scan for drivers and return an IPP response. - * add_ppd() - Add a PPD file. - * cat_drv() - Generate a PPD from a driver info file. - * cat_ppd() - Copy a PPD file to stdout. - * copy_static() - Copy a static PPD file to stdout. - * compare_names() - Compare PPD filenames for sorting. - * compare_ppds() - Compare PPD file make and model names for sorting. - * free_array() - Free an array of strings. - * list_ppds() - List PPD files. - * load_ppds() - Load PPD files recursively. - * load_drv() - Load the PPDs from a driver information file. - * load_drivers() - Load driver-generated PPD files. + * main() - Scan for drivers and return an IPP response. + * add_ppd() - Add a PPD file. + * cat_drv() - Generate a PPD from a driver info file. + * cat_ppd() - Copy a PPD file to stdout. + * copy_static() - Copy a static PPD file to stdout. + * compare_matches() - Compare PPD match scores for sorting. + * compare_names() - Compare PPD filenames for sorting. + * compare_ppds() - Compare PPD file make and model names for sorting. + * free_array() - Free an array of strings. + * list_ppds() - List PPD files. + * load_ppds() - Load PPD files recursively. + * load_drv() - Load the PPDs from a driver information file. + * load_drivers() - Load driver-generated PPD files. + * regex_device_id() - Compile a regular expression based on the 1284 device + * ID. + * regex_string() - Construct a regular expression to compare a simple + * string. */ /* @@ -41,6 +46,7 @@ #include #include #include +#include /* @@ -95,6 +101,7 @@ typedef struct /**** PPD record ****/ typedef struct /**** In-memory record ****/ { int found; /* 1 if PPD is found */ + int matches; /* Match count */ ppd_rec_t record; /* PPDs.dat record */ } ppd_info_t; @@ -121,6 +128,8 @@ static ppd_info_t *add_ppd(const char *filename, const char *name, static int cat_drv(const char *name, int request_id); static int cat_ppd(const char *name, int request_id); static int cat_static(const char *name, int request_id); +static int compare_matches(const ppd_info_t *p0, + const ppd_info_t *p1); static int compare_names(const ppd_info_t *p0, const ppd_info_t *p1); static int compare_ppds(const ppd_info_t *p0, @@ -131,6 +140,8 @@ static int load_drivers(void); static int load_drv(const char *filename, const char *name, cups_file_t *fp, time_t mtime, off_t size); static int load_ppds(const char *d, const char *p, int descend); +static regex_t *regex_device_id(const char *device_id); +static regex_t *regex_string(const char *s); /* @@ -325,7 +336,7 @@ cat_drv(const char *name, /* I - PPD name */ ppdcCatalog *catalog; // Message catalog in .drv file - fprintf(stderr, "DEBUG: %d locales defined in \"%s\"...\n", + fprintf(stderr, "DEBUG: [cups-driverd] %d locales defined in \"%s\"...\n", src->po_files->count, filename); locales = new ppdcArray(); @@ -333,7 +344,7 @@ cat_drv(const char *name, /* I - PPD name */ catalog; catalog = (ppdcCatalog *)src->po_files->next()) { - fprintf(stderr, "DEBUG: Adding locale \"%s\"...\n", + fprintf(stderr, "DEBUG: [cups-driverd] Adding locale \"%s\"...\n", catalog->locale->value); locales->add(catalog->locale); } @@ -635,6 +646,22 @@ cat_static(const char *name, /* I - PPD name */ } +/* + * 'compare_matches()' - Compare PPD match scores for sorting. + */ + +static int +compare_matches(const ppd_info_t *p0, /* I - First PPD */ + const ppd_info_t *p1) /* I - Second PPD */ +{ + if (p1->matches != p0->matches) + return (p1->matches - p0->matches); + else + return (cupsdCompareNames(p1->record.make_and_model, + p0->record.make_and_model)); +} + + /* * 'compare_names()' - Compare PPD filenames for sorting. */ @@ -729,8 +756,8 @@ list_ppds(int request_id, /* I - Request ID */ *type_str; /* ppd-type option */ int model_number, /* ppd-model-number value */ type, /* ppd-type value */ - mam_len, /* Length of ppd-make-and-model */ - device_id_len, /* Length of ppd-device-id */ + make_and_model_len, /* Length of ppd-make-and-model */ + product_len, /* Length of ppd-product */ send_device_id, /* Send ppd-device-id? */ send_make, /* Send ppd-make? */ send_make_and_model, /* Send ppd-make-and-model? */ @@ -741,6 +768,10 @@ list_ppds(int request_id, /* I - Request ID */ send_psversion, /* Send ppd-psversion? */ send_type, /* Send ppd-type? */ sent_header; /* Sent the IPP header? */ + regex_t *device_id_re, /* Regular expression for matching device ID */ + *make_and_model_re; /* Regular expression for matching make and model */ + regmatch_t re_matches[6]; /* Regular expression matches */ + cups_array_t *matches; /* Matching PPDs */ fprintf(stderr, @@ -926,14 +957,14 @@ list_ppds(int request_id, /* I - Request ID */ type_str = cupsGetOption("ppd-type", num_options, options); if (make_and_model) - mam_len = strlen(make_and_model); + make_and_model_len = strlen(make_and_model); else - mam_len = 0; + make_and_model_len = 0; - if (device_id) - device_id_len = strlen(device_id); + if (product) + product_len = strlen(product); else - device_id_len = 0; + product_len = 0; if (model_number_str) model_number = atoi(model_number_str); @@ -1021,66 +1052,135 @@ list_ppds(int request_id, /* I - Request ID */ else count = limit; - for (ppd = (ppd_info_t *)cupsArrayFirst(PPDsByMakeModel); - count > 0 && ppd; - ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel)) + if (device_id || language || make || make_and_model || model_number_str || + product) { - /* - * Filter PPDs based on make, model, or device ID... - */ + matches = cupsArrayNew((cups_array_func_t)compare_matches, NULL); - if (ppd->record.type < PPD_TYPE_POSTSCRIPT || - ppd->record.type >= PPD_TYPE_DRV) - continue; + if (device_id) + device_id_re = regex_device_id(device_id); + else + device_id_re = NULL; - if (device_id && strncasecmp(ppd->record.device_id, device_id, - device_id_len)) - continue; /* TODO: implement smart compare */ + if (make_and_model) + make_and_model_re = regex_string(make_and_model); + else + make_and_model_re = NULL; - if (language) + for (ppd = (ppd_info_t *)cupsArrayFirst(PPDsByMakeModel); + ppd; + ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel)) { - for (i = 0; i < PPD_MAX_LANG; i ++) - if (!ppd->record.languages[i][0] || - !strcasecmp(ppd->record.languages[i], language)) - break; + /* + * Filter PPDs based on make, model, product, language, model number, + * and/or device ID using the "matches" score value. An exact match + * for product, make-and-model, or device-id adds 3 to the score. + * Partial matches for make-and-model yield 1 or 2 points, and matches + * for the make and language add a single point. Results are then sorted + * by score, highest score first. + */ - if (i >= PPD_MAX_LANG || !ppd->record.languages[i][0]) + if (ppd->record.type < PPD_TYPE_POSTSCRIPT || + ppd->record.type >= PPD_TYPE_DRV) continue; - } - if (make && strcasecmp(ppd->record.make, make)) - continue; + ppd->matches = 0; - if (make_and_model && strncasecmp(ppd->record.make_and_model, - make_and_model, mam_len)) - continue; + if (device_id_re && + !regexec(device_id_re, ppd->record.device_id, + (int)(sizeof(re_matches) / sizeof(re_matches[0])), + re_matches, 0)) + { + /* + * Add the number of matching values from the device ID - it will be + * at least 2 (manufacturer and model), and as much as 3 (command set). + */ - if (model_number_str && ppd->record.model_number != model_number) - continue; + for (i = 1; i < (int)(sizeof(re_matches) / sizeof(re_matches[0])); i ++) + if (re_matches[i].rm_so >= 0) + ppd->matches ++; + } - if (product) - { - for (i = 0; i < PPD_MAX_PROD; i ++) - if (!ppd->record.products[i][0] || - !strcasecmp(ppd->record.products[i], product)) - break; + if (language) + { + for (i = 0; i < PPD_MAX_LANG; i ++) + if (!ppd->record.languages[i][0] || + !strcasecmp(ppd->record.languages[i], language)) + { + ppd->matches ++; + break; + } + } - if (i >= PPD_MAX_PROD || !ppd->record.products[i][0]) - continue; - } + if (make && !strcasecmp(ppd->record.make, make)) + ppd->matches ++; - if (psversion) - { - for (i = 0; i < PPD_MAX_VERS; i ++) - if (!ppd->record.psversions[i][0] || - !strcasecmp(ppd->record.psversions[i], psversion)) - break; + if (make_and_model_re && + !regexec(make_and_model_re, ppd->record.make_and_model, + (int)(sizeof(re_matches) / sizeof(re_matches[0])), + re_matches, 0)) + { + // See how much of the make-and-model string we matched... + if (re_matches[0].rm_so == 0) + { + if (re_matches[0].rm_eo == make_and_model_len) + ppd->matches += 3; // Exact match + else + ppd->matches += 2; // Prefix match + } + else + ppd->matches ++; // Infix match + } - if (i >= PPD_MAX_VERS || !ppd->record.psversions[i][0]) - continue; + if (model_number_str && ppd->record.model_number == model_number) + ppd->matches ++; + + if (product) + { + for (i = 0; i < PPD_MAX_PROD; i ++) + if (!ppd->record.products[i][0] || + !strcasecmp(ppd->record.products[i], product)) + { + ppd->matches += 3; + break; + } + } + + if (psversion) + { + for (i = 0; i < PPD_MAX_VERS; i ++) + if (!ppd->record.psversions[i][0] || + !strcasecmp(ppd->record.psversions[i], psversion)) + { + ppd->matches ++; + break; + } + } + + if (type_str && ppd->record.type == type) + ppd->matches ++; + + if (ppd->matches) + { + fprintf(stderr, "DEBUG: [cups-driverd] %s matches with score %d!\n", + ppd->record.name, ppd->matches); + cupsArrayAdd(matches, ppd); + } } + } + else + matches = PPDsByMakeModel; - if (type_str && ppd->record.type != type) + for (ppd = (ppd_info_t *)cupsArrayFirst(matches); + count > 0 && ppd; + ppd = (ppd_info_t *)cupsArrayNext(matches)) + { + /* + * Skip invalid PPDs... + */ + + if (ppd->record.type < PPD_TYPE_POSTSCRIPT || + ppd->record.type >= PPD_TYPE_DRV) continue; /* @@ -1094,7 +1194,8 @@ list_ppds(int request_id, /* I - Request ID */ cupsdSendIPPHeader(IPP_OK, request_id); cupsdSendIPPGroup(IPP_TAG_OPERATION); cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); - cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); } fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n", @@ -1164,13 +1265,13 @@ list_ppds(int request_id, /* I - Request ID */ for (this_make = ppd->record.make, - ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel); + ppd = (ppd_info_t *)cupsArrayNext(matches); ppd; - ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel)) + ppd = (ppd_info_t *)cupsArrayNext(matches)) if (strcasecmp(this_make, ppd->record.make)) break; - cupsArrayPrev(PPDsByMakeModel); + cupsArrayPrev(matches); } } @@ -1382,7 +1483,13 @@ load_ppds(const char *d, /* I - Actual directory */ else if (!strncmp(line, "*NickName:", 10)) sscanf(line, "%*[^\"]\"%255[^\"]", nick_name); else if (!strncasecmp(line, "*1284DeviceID:", 14)) + { sscanf(line, "%*[^\"]\"%255[^\"]", device_id); + + // Make sure device ID ends with a semicolon... + if (device_id[0] && device_id[strlen(device_id) - 1] != ';') + strlcat(device_id, ";", sizeof(device_id)); + } else if (!strncmp(line, "*Product:", 9)) { if (sscanf(line, "%*[^\"]\"(%255[^)]", product) == 1) @@ -1980,6 +2087,144 @@ load_drivers(void) } +/* + * 'regex_device_id()' - Compile a regular expression based on the 1284 device + * ID. + */ + +static regex_t * /* O - Regular expression */ +regex_device_id(const char *device_id) /* I - IEEE-1284 device ID */ +{ + char res[2048], /* Regular expression string */ + *ptr; /* Pointer into string */ + regex_t *re; /* Regular expression */ + int cmd; /* Command set string? */ + + + fprintf(stderr, "DEBUG: [cups-driverd] regex_device_id(\"%s\")\n", device_id); + + /* + * Scan the device ID string and insert class, command set, manufacturer, and + * model attributes to match. We assume that the device ID in the PPD and the + * device ID reported by the device itself use the same attribute names and + * order of attributes. + */ + + ptr = res; + + while (*device_id && ptr < (res + sizeof(res) - 6)) + { + cmd = !strncasecmp(device_id, "COMMAND SET:", 12) || + !strncasecmp(device_id, "CMD:", 4); + + if (cmd || !strncasecmp(device_id, "MANUFACTURER:", 13) || + !strncasecmp(device_id, "MFG:", 4) || + !strncasecmp(device_id, "MFR:", 4) || + !strncasecmp(device_id, "MODEL:", 6) || + !strncasecmp(device_id, "MDL:", 4)) + { + if (ptr > res) + { + *ptr++ = '.'; + *ptr++ = '*'; + } + + *ptr++ = '('; + + while (*device_id && *device_id != ';' && ptr < (res + sizeof(res) - 4)) + { + if (strchr("[]{}().*\\|", *device_id)) + *ptr++ = '\\'; + *ptr++ = *device_id++; + } + + if (*device_id == ';' || !*device_id) + *ptr++ = ';'; + *ptr++ = ')'; + if (cmd) + *ptr++ = '?'; + } + else if ((device_id = strchr(device_id, ';')) == NULL) + break; + else + device_id ++; + } + + *ptr = '\0'; + + fprintf(stderr, "DEBUG: [cups-driverd] regex_device_id: \"%s\"\n", res); + + /* + * Compile the regular expression and return... + */ + + if (res[0] && (re = (regex_t *)calloc(1, sizeof(regex_t))) != NULL) + { + if (!regcomp(re, res, REG_EXTENDED | REG_ICASE)) + { + fputs("DEBUG: [cups-driverd] regex_device_id: OK\n", stderr); + return (re); + } + + free(re); + } + + return (NULL); +} + + +/* + * 'regex_string()' - Construct a regular expression to compare a simple string. + */ + +static regex_t * /* O - Regular expression */ +regex_string(const char *s) /* I - String to compare */ +{ + char res[2048], /* Regular expression string */ + *ptr; /* Pointer into string */ + regex_t *re; /* Regular expression */ + + + fprintf(stderr, "DEBUG: [cups-driverd] regex_string(\"%s\")\n", s); + + /* + * Convert the string to a regular expression, escaping special characters + * as needed. + */ + + ptr = res; + + while (*s && ptr < (res + sizeof(res) - 2)) + { + if (strchr("[]{}().*\\", *s)) + *ptr++ = '\\'; + + *ptr++ = *s++; + } + + *ptr = '\0'; + + fprintf(stderr, "DEBUG: [cups-driverd] regex_string: \"%s\"\n", res); + + /* + * Create a case-insensitive regular expression... + */ + + if (res[0] && (re = (regex_t *)calloc(1, sizeof(regex_t))) != NULL) + { + if (!regcomp(re, res, REG_ICASE)) + { + fputs("DEBUG: [cups-driverd] regex_string: OK\n", stderr); + return (re); + } + + free(re); + } + + return (NULL); +} + + /* * End of "$Id$". */ diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h index 88f914607..6bab44e0f 100644 --- a/scheduler/cupsd.h +++ b/scheduler/cupsd.h @@ -3,7 +3,7 @@ * * Main header file for the Common UNIX Printing System (CUPS) scheduler. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -235,6 +235,7 @@ extern void cupsdStopSelect(void); extern int cupsdRemoveFile(const char *filename); + /* * End of "$Id: cupsd.h 7928 2008-09-10 22:14:22Z mike $". */ diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index 0d841741a..d51f54630 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -696,7 +696,8 @@ cupsdSaveRemoteCache(void) { int i; /* Looping var */ cups_file_t *fp; /* printers.conf file */ - char temp[1024]; /* Temporary string */ + char temp[1024], /* Temporary string */ + value[2048]; /* Value string */ cupsd_printer_t *printer; /* Current printer class */ time_t curtime; /* Current time */ struct tm *curdate; /* Current date */ @@ -765,48 +766,49 @@ cupsdSaveRemoteCache(void) else cupsFilePrintf(fp, "Printer %s>\n", printer->name); - cupsFilePrintf(fp, "Type %d\n", printer->type); - cupsFilePrintf(fp, "BrowseTime %d\n", (int)printer->browse_expire); if (printer->info) - cupsFilePrintf(fp, "Info %s\n", printer->info); - - if (printer->make_model) - cupsFilePrintf(fp, "MakeModel %s\n", printer->make_model); + cupsFilePutConf(fp, "Info", printer->info); if (printer->location) - cupsFilePrintf(fp, "Location %s\n", printer->location); + cupsFilePutConf(fp, "Location", printer->location); + + if (printer->make_model) + cupsFilePutConf(fp, "MakeModel", printer->make_model); - cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri); + cupsFilePutConf(fp, "DeviceURI", printer->device_uri); if (printer->state == IPP_PRINTER_STOPPED) - { cupsFilePuts(fp, "State Stopped\n"); - cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message); - } else cupsFilePuts(fp, "State Idle\n"); for (i = 0; i < printer->num_reasons; i ++) - cupsFilePrintf(fp, "Reason %s\n", printer->reasons[i]); + cupsFilePutConf(fp, "Reason", printer->reasons[i]); + + cupsFilePrintf(fp, "Type %d\n", printer->type); if (printer->accepting) cupsFilePuts(fp, "Accepting Yes\n"); else cupsFilePuts(fp, "Accepting No\n"); - cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0], - printer->job_sheets[1]); + snprintf(value, sizeof(value), "%s %s", printer->job_sheets[0], + printer->job_sheets[1]); + cupsFilePutConf(fp, "JobSheets", value); for (i = 0; i < printer->num_users; i ++) - cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow", - printer->users[i]); + cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser", + printer->users[i]); for (i = printer->num_options, option = printer->options; i > 0; i --, option ++) - cupsFilePrintf(fp, "Option %s %s\n", option->name, option->value); + { + snprintf(value, sizeof(value), "%s %s", option->name, option->value); + cupsFilePutConf(fp, "Option", value); + } if (printer->type & CUPS_PRINTER_CLASS) cupsFilePuts(fp, "\n"); diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 23b2c09c4..2b44fba60 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -5449,6 +5449,17 @@ copy_printer_attrs( ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-shared", printer->shared); + if ((!ra || cupsArrayFind(ra, "printer-more-info")) && + !(printer->type & CUPS_PRINTER_DISCOVERED)) + { + httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), + "http", NULL, con->servername, con->serverport, + (printer->type & CUPS_PRINTER_CLASS) ? + "/classes/%s" : "/printers/%s", printer->name); + ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, + "printer-more-info", NULL, printer_uri); + } + if (!ra || cupsArrayFind(ra, "printer-op-policy")) ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-op-policy", NULL, printer->op_policy); @@ -5514,8 +5525,7 @@ copy_printer_attrs( "printer-up-time", curtime); if ((!ra || cupsArrayFind(ra, "printer-uri-supported")) && - !ippFindAttribute(printer->attrs, "printer-uri-supported", - IPP_TAG_URI)) + !(printer->type & CUPS_PRINTER_DISCOVERED)) { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp", NULL, con->servername, con->serverport, diff --git a/scheduler/printers.c b/scheduler/printers.c index 4217832d0..7b5b7b1bf 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -1005,6 +1005,11 @@ cupsdLoadAllPrinters(void) if (value) cupsdSetString(&p->info, value); } + else if (!strcasecmp(line, "MakeModel")) + { + if (value) + cupsdSetString(&p->make_model, value); + } else if (!strcasecmp(line, "Location")) { if (value) @@ -1111,6 +1116,52 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } + else if (!strcasecmp(line, "Type")) + { + if (value) + p->type = atoi(value); + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Syntax error on line %d of printers.conf.", linenum); + } + else if (!strcasecmp(line, "Product")) + { + if (value) + { +#ifdef HAVE_DNSSD + p->product = _cupsStrAlloc(value); +#endif /* HAVE_DNSSD */ + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Syntax error on line %d of printers.conf.", linenum); + } + else if (!strcasecmp(line, "Filter")) + { + if (value) + { + if (!p->filters) + p->filters = cupsArrayNew(NULL, NULL); + + cupsArrayAdd(p->filters, _cupsStrAlloc(value)); + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Syntax error on line %d of printers.conf.", linenum); + } + else if (!strcasecmp(line, "PreFilter")) + { + if (value) + { + if (!p->pre_filters) + p->pre_filters = cupsArrayNew(NULL, NULL); + + cupsArrayAdd(p->pre_filters, _cupsStrAlloc(value)); + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Syntax error on line %d of printers.conf.", linenum); + } else if (!strcasecmp(line, "Shared")) { /* @@ -1349,13 +1400,14 @@ cupsdSaveAllPrinters(void) { int i; /* Looping var */ cups_file_t *fp; /* printers.conf file */ - char temp[1024]; /* Temporary string */ - char backup[1024]; /* printers.conf.O file */ + char temp[1024], /* Temporary string */ + backup[1024], /* printers.conf.O file */ + value[2048], /* Value string */ + *ptr; /* Pointer into value */ cupsd_printer_t *printer; /* Current printer class */ time_t curtime; /* Current time */ struct tm *curdate; /* Current date */ cups_option_t *option; /* Current option */ - const char *ptr; /* Pointer into info/location */ ipp_attribute_t *marker; /* Current marker attribute */ @@ -1432,56 +1484,50 @@ cupsdSaveAllPrinters(void) if (printer->num_auth_info_required > 0) { - cupsFilePrintf(fp, "AuthInfoRequired %s", printer->auth_info_required[0]); - for (i = 1; i < printer->num_auth_info_required; i ++) - cupsFilePrintf(fp, ",%s", printer->auth_info_required[i]); - cupsFilePutChar(fp, '\n'); - } - - if (printer->info) - { - if ((ptr = strchr(printer->info, '#')) != NULL) + switch (printer->num_auth_info_required) { - /* - * Need to quote the first # in the info string... - */ - - cupsFilePuts(fp, "Info "); - cupsFileWrite(fp, printer->info, ptr - printer->info); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - cupsFilePutChar(fp, '\n'); + case 1 : + strlcpy(value, printer->auth_info_required[0], sizeof(value)); + break; + + case 2 : + snprintf(value, sizeof(value), "%s,%s", + printer->auth_info_required[0], + printer->auth_info_required[1]); + break; + + case 3 : + default : + snprintf(value, sizeof(value), "%s,%s,%s", + printer->auth_info_required[0], + printer->auth_info_required[1], + printer->auth_info_required[2]); + break; } - else - cupsFilePrintf(fp, "Info %s\n", printer->info); + + cupsFilePutConf(fp, "AuthInfoRequired", value); } + if (printer->info) + cupsFilePutConf(fp, "Info", printer->info); + if (printer->location) - { - if ((ptr = strchr(printer->info, '#')) != NULL) - { - /* - * Need to quote the first # in the location string... - */ + cupsFilePutConf(fp, "Location", printer->location); - cupsFilePuts(fp, "Location "); - cupsFileWrite(fp, printer->location, ptr - printer->location); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - cupsFilePutChar(fp, '\n'); - } - else - cupsFilePrintf(fp, "Location %s\n", printer->location); - } - cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri); + if (printer->make_model) + cupsFilePutConf(fp, "MakeModel", printer->make_model); + + cupsFilePutConf(fp, "DeviceURI", printer->device_uri); if (printer->port_monitor) - cupsFilePrintf(fp, "PortMonitor %s\n", printer->port_monitor); + cupsFilePutConf(fp, "PortMonitor", printer->port_monitor); if (printer->state == IPP_PRINTER_STOPPED) { cupsFilePuts(fp, "State Stopped\n"); - cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message); + + if (printer->state_message) + cupsFilePutConf(fp, "StateMessage", printer->state_message); } else cupsFilePuts(fp, "State Idle\n"); @@ -1489,7 +1535,24 @@ cupsdSaveAllPrinters(void) cupsFilePrintf(fp, "StateTime %d\n", (int)printer->state_time); for (i = 0; i < printer->num_reasons; i ++) - cupsFilePrintf(fp, "Reason %s\n", printer->reasons[i]); + cupsFilePutConf(fp, "Reason", printer->reasons[i]); + + cupsFilePrintf(fp, "Type %d", printer->type); + +#ifdef HAVE_DNSSD + if (printer->product) + cupsFilePutConf(fp, "Product", printer->product); +#endif /* HAVE_DNSSD */ + + for (ptr = (char *)cupsArrayFirst(printer->filters); + ptr; + ptr = (char *)cupsArrayNext(printer->filters)) + cupsFilePutConf(fp, "Filter", ptr); + + for (ptr = (char *)cupsArrayFirst(printer->pre_filters); + ptr; + ptr = (char *)cupsArrayNext(printer->pre_filters)) + cupsFilePutConf(fp, "PreFilter", ptr); if (printer->accepting) cupsFilePuts(fp, "Accepting Yes\n"); @@ -1501,80 +1564,50 @@ cupsdSaveAllPrinters(void) else cupsFilePuts(fp, "Shared No\n"); - cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0], - printer->job_sheets[1]); + snprintf(value, sizeof(value), "%s %s", printer->job_sheets[0], + printer->job_sheets[1]); + cupsFilePutConf(fp, "JobSheets", value); cupsFilePrintf(fp, "QuotaPeriod %d\n", printer->quota_period); cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit); cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit); for (i = 0; i < printer->num_users; i ++) - { - if ((ptr = strchr(printer->users[i], '#')) != NULL) - { - /* - * Need to quote the first # in the user string... - */ - - cupsFilePrintf(fp, "%sUser ", printer->deny_users ? "Deny" : "Allow"); - cupsFileWrite(fp, printer->users[i], ptr - printer->users[i]); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - cupsFilePutChar(fp, '\n'); - } - else - cupsFilePrintf(fp, "%sUser %s\n", - printer->deny_users ? "Deny" : "Allow", - printer->users[i]); - } + cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser", + printer->users[i]); if (printer->op_policy) - cupsFilePrintf(fp, "OpPolicy %s\n", printer->op_policy); + cupsFilePutConf(fp, "OpPolicy", printer->op_policy); if (printer->error_policy) - cupsFilePrintf(fp, "ErrorPolicy %s\n", printer->error_policy); + cupsFilePutConf(fp, "ErrorPolicy", printer->error_policy); for (i = printer->num_options, option = printer->options; i > 0; i --, option ++) { - if ((ptr = strchr(option->value, '#')) != NULL) - { - /* - * Need to quote the first # in the option string... - */ - - cupsFilePrintf(fp, "Option %s ", option->name); - cupsFileWrite(fp, option->value, ptr - option->value); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - cupsFilePutChar(fp, '\n'); - } - else - cupsFilePrintf(fp, "Option %s %s\n", option->name, option->value); + snprintf(value, sizeof(value), "%s %s", option->name, option->value); + cupsFilePutConf(fp, "Option", value); } if ((marker = ippFindAttribute(printer->attrs, "marker-colors", IPP_TAG_NAME)) != NULL) { - cupsFilePrintf(fp, "Attribute %s ", marker->name); + snprintf(value, sizeof(value), "%s ", marker->name); - for (i = 0, ptr = NULL; i < marker->num_values; i ++) + for (i = 0, ptr = value + strlen(value); + i < marker->num_values && ptr < (value + sizeof(value) - 1); + i ++) { if (i) - cupsFilePutChar(fp, ','); + *ptr++ = ','; - if (!ptr && (ptr = strchr(marker->values[i].string.text, '#')) != NULL) - { - cupsFileWrite(fp, marker->values[i].string.text, - ptr - marker->values[i].string.text); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - } - else - cupsFilePuts(fp, marker->values[i].string.text); + strlcpy(ptr, marker->values[i].string.text, + value + sizeof(value) - ptr); + ptr += strlen(ptr); } - cupsFilePuts(fp, "\n"); + *ptr = '\0'; + cupsFilePutConf(fp, "Attribute", value); } if ((marker = ippFindAttribute(printer->attrs, "marker-levels", @@ -1590,67 +1623,52 @@ cupsdSaveAllPrinters(void) if ((marker = ippFindAttribute(printer->attrs, "marker-message", IPP_TAG_TEXT)) != NULL) { - cupsFilePrintf(fp, "Attribute %s ", marker->name); + snprintf(value, sizeof(value), "%s %s", marker->name, + marker->values[0].string.text); - if ((ptr = strchr(marker->values[0].string.text, '#')) != NULL) - { - cupsFileWrite(fp, marker->values[0].string.text, - ptr - marker->values[0].string.text); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - } - else - cupsFilePuts(fp, marker->values[0].string.text); - - cupsFilePuts(fp, "\n"); + cupsFilePutConf(fp, "Attribute", value); } if ((marker = ippFindAttribute(printer->attrs, "marker-names", IPP_TAG_NAME)) != NULL) { - cupsFilePrintf(fp, "Attribute %s ", marker->name); + snprintf(value, sizeof(value), "%s ", marker->name); - for (i = 0, ptr = NULL; i < marker->num_values; i ++) + for (i = 0, ptr = value + strlen(value); + i < marker->num_values && ptr < (value + sizeof(value) - 1); + i ++) { if (i) - cupsFilePutChar(fp, ','); + *ptr++ = ','; - if (!ptr && (ptr = strchr(marker->values[i].string.text, '#')) != NULL) - { - cupsFileWrite(fp, marker->values[i].string.text, - ptr - marker->values[i].string.text); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - } - else - cupsFilePuts(fp, marker->values[i].string.text); + strlcpy(ptr, marker->values[i].string.text, + value + sizeof(value) - ptr); + ptr += strlen(ptr); } - cupsFilePuts(fp, "\n"); + *ptr = '\0'; + cupsFilePutConf(fp, "Attribute", value); } if ((marker = ippFindAttribute(printer->attrs, "marker-types", IPP_TAG_KEYWORD)) != NULL) { - cupsFilePrintf(fp, "Attribute %s ", marker->name); + snprintf(value, sizeof(value), "%s ", marker->name); - for (i = 0, ptr = NULL; i < marker->num_values; i ++) + for (i = 0, ptr = value + strlen(value); + i < marker->num_values && ptr < (value + sizeof(value) - 1); + i ++) { if (i) - cupsFilePutChar(fp, ','); + *ptr++ = ','; - if (!ptr && (ptr = strchr(marker->values[i].string.text, '#')) != NULL) - { - cupsFileWrite(fp, marker->values[i].string.text, - ptr - marker->values[i].string.text); - cupsFilePutChar(fp, '\\'); - cupsFilePuts(fp, ptr); - } - else - cupsFilePuts(fp, marker->values[i].string.text); + strlcpy(ptr, marker->values[i].string.text, + value + sizeof(value) - ptr); + ptr += strlen(ptr); } - cupsFilePuts(fp, "\n"); + *ptr = '\0'; + cupsFilePutConf(fp, "Attribute", value); } cupsFilePuts(fp, "\n"); @@ -2176,8 +2194,6 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ NULL, p->location ? p->location : ""); ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL, p->info ? p->info : ""); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", - NULL, p->uri); if (p->num_users) { @@ -2230,6 +2246,9 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", NULL, p->uri); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", + NULL, p->uri); + if (p->make_model) ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, p->make_model); @@ -2750,7 +2769,10 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ } else if (!strncmp(p->device_uri, "ipp://", 6) && (strstr(p->device_uri, "/printers/") != NULL || - strstr(p->device_uri, "/classes/") != NULL)) + strstr(p->device_uri, "/classes/") != NULL || + (strstr(p->device_uri, "._ipp.") != NULL && + !strcmp(p->device_uri + strlen(p->device_uri) - 5, + "/cups")))) { /* * Tell the client this is really a hard-wired remote printer. diff --git a/scheduler/printers.h b/scheduler/printers.h index 21353025a..abc1b4d0a 100644 --- a/scheduler/printers.h +++ b/scheduler/printers.h @@ -88,6 +88,8 @@ typedef struct cupsd_printer_s char *alert, /* PSX printer-alert value */ *alert_description; /* PSX printer-alert-description value */ time_t marker_time; /* Last time marker attributes were updated */ + cups_array_t *filters, /* Filters for queue */ + *pre_filters; /* Pre-filters for queue */ #ifdef __APPLE__ char *recoverable; /* com.apple.print.recoverable-message */ diff --git a/systemv/lpinfo.c b/systemv/lpinfo.c index babe6a2ad..72e8fbab8 100644 --- a/systemv/lpinfo.c +++ b/systemv/lpinfo.c @@ -42,8 +42,10 @@ static void device_cb(const char *device_clas, const char *device_id, const char *device_make_and_model, const char *device_uri, const char *device_location, void *user_data); -static int show_devices(http_t *, int); -static int show_models(http_t *, int); +static int show_devices(http_t *http, int long_status, int timeout); +static int show_models(http_t *http, int long_status, + const char *device_id, const char *language, + const char *make_model, const char *product); /* @@ -57,12 +59,22 @@ main(int argc, /* I - Number of command-line arguments */ int i; /* Looping var */ http_t *http; /* Connection to server */ int long_status; /* Long listing? */ + const char *device_id, /* 1284 device ID */ + *language, /* Language */ + *make_model, /* Make and model */ + *product; /* Product */ + int timeout; /* Device timeout */ _cupsSetLocale(argv); http = NULL; long_status = 0; + device_id = NULL; + language = NULL; + make_model = NULL; + product = NULL; + timeout = CUPS_TIMEOUT_DEFAULT; for (i = 1; i < argc; i ++) if (argv[i][0] == '-') @@ -81,6 +93,30 @@ main(int argc, /* I - Number of command-line arguments */ #endif /* HAVE_SSL */ break; + case 'h' : /* Connect to host */ + if (http) + { + httpClose(http); + http = NULL; + } + + if (argv[i][2] != '\0') + cupsSetServer(argv[i] + 2); + else + { + i ++; + + if (i >= argc) + { + _cupsLangPuts(stderr, + _("Error: need hostname after \'-h\' option!\n")); + return (1); + } + + cupsSetServer(argv[i]); + } + break; + case 'l' : /* Show long listing */ long_status = 1; break; @@ -100,7 +136,8 @@ main(int argc, /* I - Number of command-line arguments */ } } - if (show_models(http, long_status)) + if (show_models(http, long_status, device_id, language, make_model, + product)) return (1); break; @@ -119,31 +156,101 @@ main(int argc, /* I - Number of command-line arguments */ } } - if (show_devices(http, long_status)) + if (show_devices(http, long_status, timeout)) return (1); break; - case 'h' : /* Connect to host */ - if (http) + case '-' : /* --something */ + if (!strcmp(argv[i], "--device-id")) { - httpClose(http); - http = NULL; - } + i ++; - if (argv[i][2] != '\0') - cupsSetServer(argv[i] + 2); - else + if (i < argc) + device_id = argv[i]; + else + { + _cupsLangPuts(stderr, + _("lpinfo: Expected 1284 device ID string " + "after --device-id!\n")); + return (1); + } + } + else if (!strncmp(argv[i], "--device-id=", 12) && argv[i][12]) + { + device_id = argv[i] + 12; + } + else if (!strcmp(argv[i], "--language")) { i ++; - - if (i >= argc) + if (i < argc) + language = argv[i]; + else { - _cupsLangPuts(stderr, - _("Error: need hostname after \'-h\' option!\n")); + _cupsLangPuts(stderr, + _("lpinfo: Expected language after " + "--language!\n")); return (1); - } - - cupsSetServer(argv[i]); + } + } + else if (!strncmp(argv[i], "--language=", 11) && argv[i][11]) + { + language = argv[i] + 11; + } + else if (!strcmp(argv[i], "--make-and-model")) + { + i ++; + if (i < argc) + make_model= argv[i]; + else + { + _cupsLangPuts(stderr, + _("lpinfo: Expected make and model after " + "--make-and-model!\n")); + return (1); + } + } + else if (!strncmp(argv[i], "--make-and-model=", 17) && argv[i][17]) + { + make_model = argv[i] + 17; + } + else if (!strcmp(argv[i], "--product")) + { + i ++; + if (i < argc) + product = argv[i]; + else + { + _cupsLangPuts(stderr, + _("lpinfo: Expected product string after " + "--product!\n")); + return (1); + } + } + else if (!strncmp(argv[i], "--product=", 10) && argv[i][10]) + { + product = argv[i] + 10; + } + else if (!strcmp(argv[i], "--timeout")) + { + i ++; + if (i < argc) + timeout = atoi(argv[i]); + else + { + _cupsLangPuts(stderr, + _("lpinfo: Expected timeout after --timeout!\n")); + return (1); + } + } + else if (!strncmp(argv[i], "--timeout=", 10) && argv[i][10]) + { + timeout = atoi(argv[i] + 10); + } + else + { + _cupsLangPrintf(stderr, _("lpinfo: Unknown option \'%s\'!\n"), + argv[i]); + return (1); } break; @@ -209,9 +316,10 @@ device_cb( static int /* O - 0 on success, 1 on failure */ show_devices(http_t *http, /* I - HTTP connection to server */ - int long_status) /* I - Long status report? */ + int long_status, /* I - Long status report? */ + int timeout) /* I - Timeout */ { - if (cupsGetDevices(http, CUPS_TIMEOUT_DEFAULT, CUPS_EXCLUDE_NONE, device_cb, + if (cupsGetDevices(http, timeout, CUPS_EXCLUDE_NONE, device_cb, &long_status) != IPP_OK) { _cupsLangPrintf(stderr, "lpinfo: %s\n", cupsLastErrorString()); @@ -227,15 +335,19 @@ show_devices(http_t *http, /* I - HTTP connection to server */ */ static int /* O - 0 on success, 1 on failure */ -show_models(http_t *http, /* I - HTTP connection to server */ - int long_status) /* I - Long status report? */ +show_models(http_t *http, /* I - HTTP connection to server */ + int long_status, /* I - Long status report? */ + const char *device_id, /* I - 1284 device ID */ + const char *language, /* I - Language */ + const char *make_model, /* I - Make and model */ + const char *product) /* I - Product */ { ipp_t *request, /* IPP Request */ *response; /* IPP Response */ ipp_attribute_t *attr; /* Current attribute */ const char *ppd_device_id, /* Pointer to ppd-device-id */ *ppd_language, /* Pointer to ppd-natural-language */ - *ppd_make, /* Pointer to ppd-make-and-model */ + *ppd_make_model, /* Pointer to ppd-make-and-model */ *ppd_name; /* Pointer to ppd-name */ @@ -243,15 +355,24 @@ show_models(http_t *http, /* I - HTTP connection to server */ return (1); /* - * Build a CUPS_GET_PPDS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language + * Build a CUPS_GET_PPDS request... */ request = ippNewRequest(CUPS_GET_PPDS); + if (device_id) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-device-id", + NULL, device_id); + if (language) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "ppd-language", + NULL, language); + if (make_model) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make-and-model", + NULL, make_model); + if (product) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-product", + NULL, product); + /* * Do the request and get back a response... */ @@ -285,10 +406,10 @@ show_models(http_t *http, /* I - HTTP connection to server */ * Pull the needed attributes from this PPD... */ - ppd_device_id = "NONE"; - ppd_language = NULL; - ppd_make = NULL; - ppd_name = NULL; + ppd_device_id = "NONE"; + ppd_language = NULL; + ppd_make_model = NULL; + ppd_name = NULL; while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { @@ -300,7 +421,7 @@ show_models(http_t *http, /* I - HTTP connection to server */ ppd_language = attr->values[0].string.text; else if (!strcmp(attr->name, "ppd-make-and-model") && attr->value_tag == IPP_TAG_TEXT) - ppd_make = attr->values[0].string.text; + ppd_make_model = attr->values[0].string.text; else if (!strcmp(attr->name, "ppd-name") && attr->value_tag == IPP_TAG_NAME) ppd_name = attr->values[0].string.text; @@ -312,7 +433,7 @@ show_models(http_t *http, /* I - HTTP connection to server */ * See if we have everything needed... */ - if (ppd_language == NULL || ppd_make == NULL || ppd_name == NULL) + if (ppd_language == NULL || ppd_make_model == NULL || ppd_name == NULL) { if (attr == NULL) break; @@ -331,10 +452,10 @@ show_models(http_t *http, /* I - HTTP connection to server */ " natural_language = %s\n" " make-and-model = %s\n" " device-id = %s\n"), - ppd_name, ppd_language, ppd_make, ppd_device_id); + ppd_name, ppd_language, ppd_make_model, ppd_device_id); } else - _cupsLangPrintf(stdout, "%s %s\n", ppd_name, ppd_make); + _cupsLangPrintf(stdout, "%s %s\n", ppd_name, ppd_make_model); if (attr == NULL) break; diff --git a/templates/Makefile b/templates/Makefile index 4250ccc92..6ea624aba 100644 --- a/templates/Makefile +++ b/templates/Makefile @@ -37,6 +37,7 @@ FILES = \ class-modified.tmpl \ classes.tmpl \ classes-header.tmpl \ + command.tmpl \ edit-config.tmpl \ error.tmpl \ error-op.tmpl \ @@ -53,7 +54,6 @@ FILES = \ jobs.tmpl \ jobs-header.tmpl \ list-available-printers.tmpl \ - maintenance.tmpl \ modify-class.tmpl \ modify-printer.tmpl \ norestart.tmpl \ diff --git a/templates/choose-device.tmpl b/templates/choose-device.tmpl index 17e0ac011..b7d92723f 100644 --- a/templates/choose-device.tmpl +++ b/templates/choose-device.tmpl @@ -2,6 +2,9 @@

                {op=modify-printer?Modify {printer_name}:Add Printer}

                +{CUPS_GET_DEVICES_DONE?:

                Looking for printers...

                } +
                {printer_name?:} @@ -11,7 +14,7 @@ Current Connection: {current_device_uri} -:} +} Local Printers: diff --git a/templates/class-added.tmpl b/templates/class-added.tmpl index 64de61a18..c062a16d5 100644 --- a/templates/class-added.tmpl +++ b/templates/class-added.tmpl @@ -1,5 +1,7 @@
                +

                Add Class

                +

                Class {printer_name} has been added successfully. diff --git a/templates/class-confirm.tmpl b/templates/class-confirm.tmpl index d5641498c..c14d35482 100644 --- a/templates/class-confirm.tmpl +++ b/templates/class-confirm.tmpl @@ -1,5 +1,7 @@

                +

                Delete Class {printer_name}

                +

                Warning: Are you sure you want to delete class {printer_name}?

                diff --git a/templates/class-deleted.tmpl b/templates/class-deleted.tmpl index f2bb4d610..a4ad46a0a 100644 --- a/templates/class-deleted.tmpl +++ b/templates/class-deleted.tmpl @@ -1,5 +1,7 @@
                +

                Delete Class {printer_name}

                +

                Class {printer_name} has been deleted successfully.

                \ No newline at end of file diff --git a/templates/class-modified.tmpl b/templates/class-modified.tmpl index ddbbbc019..fe42c907b 100644 --- a/templates/class-modified.tmpl +++ b/templates/class-modified.tmpl @@ -1,5 +1,7 @@
                +

                Modify Class {printer_name}

                +

                Class {printer_name} has been modified successfully. diff --git a/templates/class.tmpl b/templates/class.tmpl index a344d4b66..535af64a6 100644 --- a/templates/class.tmpl +++ b/templates/class.tmpl @@ -8,7 +8,7 @@ +

                diff --git a/templates/job-cancel.tmpl b/templates/job-cancel.tmpl index 2bc5a13d5..3e8fd4dad 100644 --- a/templates/job-cancel.tmpl +++ b/templates/job-cancel.tmpl @@ -1 +1,7 @@ +
                + +

                Cancel Job {job_id}

                +

                Job {job_id} has been canceled. + +

                diff --git a/templates/job-hold.tmpl b/templates/job-hold.tmpl index 3e391543b..58ce97fc9 100644 --- a/templates/job-hold.tmpl +++ b/templates/job-hold.tmpl @@ -1 +1,7 @@ +
                + +

                Hold Job {job_id}

                +

                Job {job_id} has been held from printing. + +

                diff --git a/templates/job-move.tmpl b/templates/job-move.tmpl index a7a06ab4f..96b309006 100644 --- a/templates/job-move.tmpl +++ b/templates/job-move.tmpl @@ -1,3 +1,5 @@ +
                + {job_id?:} @@ -15,8 +17,10 @@ - + + +
                diff --git a/templates/job-moved.tmpl b/templates/job-moved.tmpl index df7ea1d34..ebad6767e 100644 --- a/templates/job-moved.tmpl +++ b/templates/job-moved.tmpl @@ -1,2 +1,8 @@ +
                + +

                {job_id?Move Job {job_id}:Move All Jobs}

                +

                {job_id?Job {job_id}:All jobs} moved to {job_printer_name}.

                + +
                diff --git a/templates/job-release.tmpl b/templates/job-release.tmpl index d04622353..8eb9a9667 100644 --- a/templates/job-release.tmpl +++ b/templates/job-release.tmpl @@ -1 +1,7 @@ +
                + +

                Release Job {job_id}

                +

                Job {job_id} has been released for printing. + +

                diff --git a/templates/job-restart.tmpl b/templates/job-restart.tmpl index d575c47a7..b91ced926 100644 --- a/templates/job-restart.tmpl +++ b/templates/job-restart.tmpl @@ -1 +1,7 @@ +
                + +

                Reprint Job {job_id}

                +

                Job {job_id} has been restarted. + +

                diff --git a/templates/jobs.tmpl b/templates/jobs.tmpl index f68eea01e..9e77556bf 100644 --- a/templates/jobs.tmpl +++ b/templates/jobs.tmpl @@ -16,9 +16,9 @@ {job_state=7?canceled at
                {time_at_completed}:{job_state=8?aborted:completed at
                {time_at_completed}}}}}}} {job_printer_state_message?
                "{job_printer_state_message}":} -{job_preserved>0? +{job_preserved>0?{job_state>5?
                -
                :} +:}:} {job_state=4?
                :} diff --git a/templates/maintenance.tmpl b/templates/maintenance.tmpl index 379c001cb..e69de29bb 100644 --- a/templates/maintenance.tmpl +++ b/templates/maintenance.tmpl @@ -1,6 +0,0 @@ -
                - -

                Maintenance commands sent; job ID is -{printer_name}-{job_id}.

                - -
                diff --git a/templates/norestart.tmpl b/templates/norestart.tmpl index 402e0f997..6b3120337 100644 --- a/templates/norestart.tmpl +++ b/templates/norestart.tmpl @@ -1,2 +1,8 @@ -

                The server was not restarted because no changes were made to -the configuration...

                +
                + +

                Change Settings

                + +

                The server was not restarted because no changes were made to +the configuration...

                + +
                diff --git a/templates/option-boolean.tmpl b/templates/option-boolean.tmpl index 72c85189a..2d0dd551a 100644 --- a/templates/option-boolean.tmpl +++ b/templates/option-boolean.tmpl @@ -1,5 +1,5 @@ -{keytext}: +{keytext}: {[choices]{text}} diff --git a/templates/option-header.tmpl b/templates/option-header.tmpl index cafc9f9fe..464726a50 100644 --- a/templates/option-header.tmpl +++ b/templates/option-header.tmpl @@ -1,3 +1,5 @@ -

                {printer_name}: {group}

                +
                - +

                {group}

                + +
                diff --git a/templates/option-pickmany.tmpl b/templates/option-pickmany.tmpl index d2534af75..067075aec 100644 --- a/templates/option-pickmany.tmpl +++ b/templates/option-pickmany.tmpl @@ -1,5 +1,5 @@ - + diff --git a/templates/option-pickone.tmpl b/templates/option-pickone.tmpl index a2ce9d8c8..05b83ee8a 100644 --- a/templates/option-pickone.tmpl +++ b/templates/option-pickone.tmpl @@ -1,5 +1,5 @@ - + - - -
                {keytext}:{keytext}:
                {keytext}:{keytext}: diff --git a/templates/option-trailer.tmpl b/templates/option-trailer.tmpl index 83635f4c9..17c928109 100644 --- a/templates/option-trailer.tmpl +++ b/templates/option-trailer.tmpl @@ -1,5 +1,5 @@ -
                + +

                + +
                \ No newline at end of file diff --git a/templates/printer-accept.tmpl b/templates/printer-accept.tmpl index 7aa91f3dd..3e987ce64 100644 --- a/templates/printer-accept.tmpl +++ b/templates/printer-accept.tmpl @@ -1,5 +1,7 @@
                +

                Accept Jobs On {is_class?Class:Printer} {printer_name}

                +

                {is_class?Class:Printer} {printer_name} is now accepting jobs.

                diff --git a/templates/printer-added.tmpl b/templates/printer-added.tmpl index 2b819954f..9a6e798e9 100644 --- a/templates/printer-added.tmpl +++ b/templates/printer-added.tmpl @@ -1,5 +1,7 @@
                +

                Add Printer

                +

                Printer {printer_name} has been added successfully. diff --git a/templates/printer-configured.tmpl b/templates/printer-configured.tmpl index b80db4569..6f8104e23 100644 --- a/templates/printer-configured.tmpl +++ b/templates/printer-configured.tmpl @@ -1,6 +1,8 @@

                -

                {OP=set-class-options?Class :Printer }{printer_name} has -been configured successfully. +

                Set Default Options for {printer_name}

                + +

                {OP=set-class-options?Class :Printer }{printer_name} +default options have been set successfully.

                diff --git a/templates/printer-confirm.tmpl b/templates/printer-confirm.tmpl index 4cac6c366..db16d691b 100644 --- a/templates/printer-confirm.tmpl +++ b/templates/printer-confirm.tmpl @@ -1,5 +1,7 @@
                +

                Delete Printer {printer_name}

                +

                Warning: Are you sure you want to delete printer {printer_name}?

                diff --git a/templates/printer-default.tmpl b/templates/printer-default.tmpl index b18e45047..72a7b5ea8 100644 --- a/templates/printer-default.tmpl +++ b/templates/printer-default.tmpl @@ -1,5 +1,7 @@
                +

                Set {is_class?Class:Printer} {printer_name} As Default

                +

                {is_class?Class:Printer} {printer_name} has been made the default printer on the server.

                diff --git a/templates/printer-deleted.tmpl b/templates/printer-deleted.tmpl index 0928955e2..d8a31ae61 100644 --- a/templates/printer-deleted.tmpl +++ b/templates/printer-deleted.tmpl @@ -1,5 +1,7 @@
                +

                Delete Printer {printer_name}

                +

                Printer {printer_name} has been deleted successfully.

                diff --git a/templates/printer-modified.tmpl b/templates/printer-modified.tmpl index f6fb6e2a1..b61e8e34a 100644 --- a/templates/printer-modified.tmpl +++ b/templates/printer-modified.tmpl @@ -1,5 +1,7 @@
                +

                Modify Printer {printer_name}

                +

                Printer {printer_name} has been modified successfully. diff --git a/templates/printer-purge.tmpl b/templates/printer-purge.tmpl index 4cba910e2..8cf7c1461 100644 --- a/templates/printer-purge.tmpl +++ b/templates/printer-purge.tmpl @@ -1,5 +1,7 @@

                +

                Purge Jobs On {is_class?Class:Printer} {printer_name}

                +

                {is_class?Class:Printer} {printer_name} has been purged of all jobs.

                diff --git a/templates/printer-reject.tmpl b/templates/printer-reject.tmpl index 4a52c24c6..5f1c79195 100644 --- a/templates/printer-reject.tmpl +++ b/templates/printer-reject.tmpl @@ -1,5 +1,7 @@
                +

                Reject Jobs On {is_class?Class:Printer} {printer_name}

                +

                {is_class?Class:Printer} {printer_name} is no longer accepting jobs.

                diff --git a/templates/printer-start.tmpl b/templates/printer-start.tmpl index d89d89c05..3eaed13d1 100644 --- a/templates/printer-start.tmpl +++ b/templates/printer-start.tmpl @@ -1,7 +1,9 @@
                +

                Resume {is_class?Class:Printer} {printer_name}

                +

                {is_class?Class:Printer} {printer_name} -has been started.

                +has been resumed.

                \ No newline at end of file diff --git a/templates/printer-stop.tmpl b/templates/printer-stop.tmpl index 75ad8ac16..b74e87135 100644 --- a/templates/printer-stop.tmpl +++ b/templates/printer-stop.tmpl @@ -1,7 +1,9 @@
                +

                Pause {is_class?Class:Printer} {printer_name}

                +

                {is_class?Class:Printer} {printer_name} -has been stopped.

                +has been paused.

                \ No newline at end of file diff --git a/templates/printer.tmpl b/templates/printer.tmpl index f069b8513..b7a38278e 100644 --- a/templates/printer.tmpl +++ b/templates/printer.tmpl @@ -1,4 +1,5 @@
                +

                {printer_name} ({printer_state=3?Idle:{printer_state=4?Processing:Paused}}, {printer_is_accepting_jobs=0?Rejecting Jobs:Accepting Jobs}, @@ -8,8 +9,8 @@ + -{HAVE_AUTOCONFIGURE?:} +{HAVE_AUTOCONFIGURE?:} +

                {[group_id] +{group}     }

                + +
                diff --git a/templates/set-printer-options-trailer.tmpl b/templates/set-printer-options-trailer.tmpl index f52d8947f..11adc7012 100644 --- a/templates/set-printer-options-trailer.tmpl +++ b/templates/set-printer-options-trailer.tmpl @@ -1,3 +1,5 @@ +
                +