CHANGES IN CUPS V1.2.11
+ - "make distclean" didn't remove all generated files
+ (STR #2366)
+ - Fixed a bug in the advertisement of classes (STR
+ #2373)
+ - The IPP backend now stays running until the job is
+ actually printed by the remote server; previously
+ it would stop monitoring the job if it was held or
+ temporarily stopped (STR #2352)
+ - PDF files were not always printed using the correct
+ orientation (STR #2348)
+ - The scheduler could crash if you specified a bad file:
+ URI for a printer (STR #2351)
+ - The Renew-Subscription operation now returns the
+ notify-lease-duration value that was used (STR #2346)
+ - The IPP backend sent job options to IPP printers,
+ however some printers tried to override the options
+ embedded in the PS/PCL stream with those job options
+ (STR #2349)
+ - ppdLocalize() now also tries a country-specific
+ localization for when localizing to a generic locale
+ name.
+ - The cupstestppd program now allows for partial
+ localizations to reduce the size of universal PPD
+ files.
+ - Chinese PPD files were incorrectly tagged with the
+ "cn" locale (should have been "zh")
+ - The backends now manage the printer-state-reasons
+ attribute more accurately (STR #2345)
+ - Java, PHP, Perl, and Python scripts did not work
+ properly (STR #2342)
+ - The scheduler would take forever to start if the
+ maximum number of file descriptors was set to
+ "unlimited" (STR #2329)
+ - The page-ranges option was incorrectly applied to the
+ banner pages (STR #2336)
+ - Fixed some GCC compile warnings (STR #2340)
+ - The DBUS notification code was broken for older
+ versions of DBUS (STR #2327)
+ - The IPv6 code did not compile on HP-UX 11.23 (STR
+ #2331)
+ - PPD constraints did not work properly with custom
+ options.
+ - Regular PPD options with the name "CustomFoo" did
+ not work.
- The USB backend did not work on NetBSD (STR #2324)
- The printer-state-reasons attribute was incorrectly
cleared after a job completed (STR #2323)
-CHANGES.txt - 2007-04-04
+CHANGES.txt - 2007-05-03
------------------------
CHANGES IN CUPS V1.3
- - Documentation updates (STR #1775, STR #2130, STR #2131)
+ - Documentation updates (STR #1775, STR #2130, STR #2131,
+ STR #2263, STR #2356)
+ - Added new -R and -W options to the cupstestppd program
+ for greater control over the testing of PPDs.
+ - Added a new cupsGetServerPPD() function for getting
+ an available PPD from the server (STR #2334)
+ - Added a new cupsDoIORequest() function for reading
+ and writing files via IPP requests (STR #2334)
+ - Added a new CUPS_GET_PPD operation for getting an
+ available PPD file on the server (STR #2334)
+ - CUPS_GET_PPDS now reports multiple ppd-product values
+ if the corresponding PPD contains multiple products
+ (STR #2334)
+ - CUPS_GET_PPDS now reports the PSVersion attributes
+ from a PPD file in the ppd-psversion attribute
+ (STR #2334)
+ - Added a new printer attribute called "cups-version"
+ which reports the version of CUPS that is running
+ (STR #2240)
+ - backendRunLoop() now aborts immediately on SIGTERM
+ if no data has been written yet (STR #2103)
+ - Due to poor IPP support from the vendors, the SNMP
+ backend no longer tries IPP connections; instead,
+ it now uses a lookup file with fallback to port 9100
+ (socket://address) and 515 (lpd://address) printing
+ (STR #2035, STR #2354)
+ - The scheduler now recreates the CUPS log directory as
+ needed (STR #2353)
+ - cupsLangDefault() now maps new-style Apple locale names
+ to the traditional ll_CC form (STR #2357)
+ - Add new cupsArrayNew2() API to support hashed lookups
+ of array elements (STR #2358)
+ - ppdConflicts() optimizations (STR #2358)
- The cupstestppd program now tests for existing filters,
icons, profiles, and dialog extensions (STR #2326)
- The web interface no longer lists new printers on the
#
-# "$Id: Makefile 6332 2007-03-12 16:08:51Z mike $"
+# "$Id: Makefile 6500 2007-04-30 21:47:48Z mike $"
#
# Top-level Makefile for the Common UNIX Printing System (CUPS).
#
distclean: clean
$(RM) Makedefs config.h config.log config.status
$(RM) cups-config conf/cupsd.conf conf/pam.std
- $(RM) doc/help/standard.html doc/index.html
+ $(RM) doc/help/ref-cupsd-conf.html doc/help/standard.html
+ $(RM) doc/index.html
$(RM) init/cups.sh init/cups-lpd
+ $(RM) man/client.conf.man
$(RM) man/cups-deviced.man man/cups-driverd.man
$(RM) man/cups-lpd.man man/cupsaddsmb.man man/cupsd.man
$(RM) man/cupsd.conf.man man/lpoptions.man
done
+#
+# Generate a ctags file...
+#
+
+ctags:
+ ctags -R .
+
+
#
# Install object and target files...
#
#
-# End of "$Id: Makefile 6332 2007-03-12 16:08:51Z mike $".
+# End of "$Id: Makefile 6500 2007-04-30 21:47:48Z mike $".
#
/*
- * "$Id: ipp.c 6434 2007-04-02 22:07:10Z mike $"
+ * "$Id: ipp.c 6482 2007-04-30 17:05:59Z mike $"
*
* IPP backend for the Common UNIX Printing System (CUPS).
*
char *argv[]) /* I - Command-line arguments */
{
int i; /* Looping var */
+ int send_options; /* Send job options? */
int num_options; /* Number of printer options */
cups_option_t *options; /* Printer options */
char method[255], /* Method in URI */
filename = tmpfilename;
files = &filename;
num_files = 1;
+
+ send_options = 0;
}
else
{
num_files = argc - 6;
files = argv + 6;
+ send_options = strncasecmp(content_type, "application/vnd.cups-", 21) != 0;
+
#ifdef HAVE_LIBZ
if (compression)
compress_files(num_files, files);
content_type = "application/postscript";
copies = 1;
copies_remaining = 1;
+ send_options = 0;
}
}
#endif /* __APPLE__ */
num_options, &options);
}
- if (copies_sup && version > 0)
+ if (copies_sup && version > 0 && send_options)
{
/*
* Only send options if the destination printer supports the copies
* Stop polling if the job is finished or pending-held...
*/
- if (job_state->values[0].integer > IPP_JOB_PROCESSING ||
- job_state->values[0].integer == IPP_JOB_HELD)
+ if (job_state->values[0].integer > IPP_JOB_STOPPED)
{
if ((job_sheets = ippFindAttribute(response,
"job-media-sheets-completed",
if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
{
fprintf(stderr,
- _("ERROR: Unable to create temporary compressed print file: %s\n"),
+ _("ERROR: Unable to create temporary compressed print file: "
+ "%s\n"),
strerror(errno));
exit(CUPS_BACKEND_FAILED);
}
/*
- * End of "$Id: ipp.c 6434 2007-04-02 22:07:10Z mike $".
+ * End of "$Id: ipp.c 6482 2007-04-30 17:05:59Z mike $".
*/
/*
- * "$Id: runloop.c 6403 2007-03-27 16:00:56Z mike $"
+ * "$Id: runloop.c 6498 2007-04-30 21:40:33Z mike $"
*
* Common run loop API for the Common UNIX Printing System (CUPS).
*
* Now loop until we are out of data from print_fd...
*/
- for (print_bytes = 0, print_ptr = print_buffer, offline = 0, paperout = 0, total_bytes = 0;;)
+ for (print_bytes = 0, print_ptr = print_buffer, offline = -1,
+ paperout = -1, total_bytes = 0;;)
{
/*
* Use select() to determine whether we have data to copy around...
* Pause printing to clear any pending errors...
*/
- if (errno == ENXIO && !offline)
+ if (errno == ENXIO && offline != 1)
{
fputs("STATE: +offline-error\n", stderr);
fputs(_("INFO: Printer is currently off-line.\n"), stderr);
offline = 1;
}
+ else if (errno == EINTR && total_bytes == 0)
+ {
+ fputs("DEBUG: Received an interrupt before any bytes were "
+ "written, aborting!\n", stderr);
+ return (0);
+ }
sleep(1);
continue;
if (errno == ENOSPC)
{
- if (!paperout)
+ if (paperout != 1)
{
fputs("STATE: +media-empty-error\n", stderr);
fputs(_("ERROR: Out of paper!\n"), stderr);
}
else if (errno == ENXIO)
{
- if (!offline)
+ if (offline != 1)
{
fputs("STATE: +offline-error\n", stderr);
fputs(_("INFO: Printer is currently off-line.\n"), stderr);
/*
- * End of "$Id: runloop.c 6403 2007-03-27 16:00:56Z mike $".
+ * End of "$Id: runloop.c 6498 2007-04-30 21:40:33Z mike $".
*/
/*
- * "$Id: snmp.c 6403 2007-03-27 16:00:56Z mike $"
+ * "$Id: snmp.c 6495 2007-04-30 21:23:04Z mike $"
*
* SNMP discovery backend for the Common UNIX Printing System (CUPS).
*
* main() - Discover printers via SNMP.
* add_array() - Add a string to an array.
* add_cache() - Add a cached device...
+ * add_device_uri() - Add a device URI to the cache.
* alarm_handler() - Handle alarm signals...
* asn1_decode_snmp() - Decode a SNMP packet.
* asn1_debug() - Decode an ASN1-encoded message.
* packed integer value.
* compare_cache() - Compare two cache entries.
* debug_printf() - Display some debugging information.
- * do_request() - Do a non-blocking IPP request.
* fix_make_model() - Fix common problems in the make-and-model
* string.
* free_array() - Free an array of strings.
#include "backend-private.h"
#include <cups/array.h>
#include <cups/file.h>
+#include <regex.h>
/*
* This backend implements SNMP printer discovery. It uses a broadcast-
- * based approach to get SNMP response packets from potential printers
- * and then interrogates each responder by trying to connect on port
- * 631, 9100, and 515.
+ * based approach to get SNMP response packets from potential printers,
+ * tries a mDNS lookup (Mac OS X only at present), a URI lookup based on
+ * the device description string, and finally a probe of port 9100
+ * (AppSocket) and 515 (LPD).
*
* The current focus is on printers with internal network cards, although
* the code also works with many external print servers as well. Future
* Address @IF(name)
* Community name
* DebugLevel N
+ * DeviceURI "regex pattern" uri
* HostNameLookups on
* HostNameLookups off
+ * MaxRunTime N
*
* The default is to use:
*
* Community public
* DebugLevel 0
* HostNameLookups off
+ * MaxRunTime 10
*
* This backend is known to work with the following network printers and
* print servers:
* Types...
*/
+typedef struct device_uri_s /**** DeviceURI values ****/
+{
+ regex_t re; /* Regular expression to match */
+ cups_array_t *uris; /* URIs */
+} device_uri_t;
+
typedef struct snmp_cache_s /**** SNMP scan cache ****/
{
http_addr_t address; /* Address of device */
static void add_cache(http_addr_t *addr, const char *addrname,
const char *uri, const char *id,
const char *make_and_model);
+static device_uri_t *add_device_uri(char *value);
static void alarm_handler(int sig);
static int asn1_decode_snmp(unsigned char *buffer, size_t len,
snmp_packet_t *packet);
static int asn1_size_packed(int integer);
static int compare_cache(snmp_cache_t *a, snmp_cache_t *b);
static void debug_printf(const char *format, ...);
-static ipp_t *do_request(http_t *http, ipp_t *request,
- const char *resource);
static void fix_make_model(char *make_model,
const char *old_make_model,
int make_model_size);
static cups_array_t *Communities = NULL;
static cups_array_t *Devices = NULL;
static int DebugLevel = 0;
-static int DeviceTypeOID[] = { 1, 3, 6, 1, 2, 1, 25, 3,
- 2, 1, 2, 1, 0 };
static int DeviceDescOID[] = { 1, 3, 6, 1, 2, 1, 25, 3,
2, 1, 3, 1, 0 };
-static unsigned DeviceTypeRequest;
static unsigned DeviceDescRequest;
+static int DeviceTypeOID[] = { 1, 3, 6, 1, 2, 1, 25, 3,
+ 2, 1, 2, 1, 0 };
+static unsigned DeviceTypeRequest;
+static cups_array_t *DeviceURIs = NULL;
static int HostNameLookups = 0;
static int MaxRunTime = 10;
static struct timeval StartTime;
}
+/*
+ * 'add_device_uri()' - Add a device URI to the cache.
+ *
+ * The value string is modified (chopped up) as needed.
+ */
+
+static device_uri_t * /* O - Device URI */
+add_device_uri(char *value) /* I - Value from snmp.conf */
+{
+ device_uri_t *device_uri; /* Device URI */
+ char *start; /* Start of value */
+
+
+ /*
+ * Allocate memory as needed...
+ */
+
+ if (!DeviceURIs)
+ DeviceURIs = cupsArrayNew(NULL, NULL);
+
+ if (!DeviceURIs)
+ return (NULL);
+
+ if ((device_uri = calloc(1, sizeof(device_uri_t))) == NULL)
+ return (NULL);
+
+ if ((device_uri->uris = cupsArrayNew(NULL, NULL)) == NULL)
+ {
+ free(device_uri);
+ return (NULL);
+ }
+
+ /*
+ * Scan the value string for the regular expression and URI(s)...
+ */
+
+ value ++; /* Skip leading " */
+
+ for (start = value; *value && *value != '\"'; value ++)
+ if (*value == '\\' && value[1])
+ _cups_strcpy(value, value + 1);
+
+ if (!*value)
+ {
+ fputs("ERROR: Missing end quote for DeviceURI!\n", stderr);
+
+ cupsArrayDelete(device_uri->uris);
+ free(device_uri);
+
+ return (NULL);
+ }
+
+ *value++ = '\0';
+
+ if (regcomp(&(device_uri->re), start, REG_EXTENDED | REG_ICASE))
+ {
+ fputs("ERROR: Bad regular expression for DeviceURI!\n", stderr);
+
+ cupsArrayDelete(device_uri->uris);
+ free(device_uri);
+
+ return (NULL);
+ }
+
+ while (*value)
+ {
+ while (isspace(*value & 255))
+ value ++;
+
+ if (!*value)
+ break;
+
+ for (start = value; *value && !isspace(*value & 255); value ++);
+
+ if (*value)
+ *value++ = '\0';
+
+ cupsArrayAdd(device_uri->uris, strdup(start));
+ }
+
+ /*
+ * Add the device URI to the list and return it...
+ */
+
+ cupsArrayAdd(DeviceURIs, device_uri);
+
+ return (device_uri);
+}
+
+
/*
* 'alarm_handler()' - Handle alarm signals...
*/
}
-/*
- * 'do_request()' - Do a non-blocking IPP request.
- */
-
-static ipp_t * /* O - Response data or NULL */
-do_request(http_t *http, /* I - HTTP connection to server */
- ipp_t *request, /* I - IPP request */
- const char *resource) /* I - HTTP resource for POST */
-{
- ipp_t *response; /* IPP response data */
- http_status_t status; /* Status of HTTP request */
- ipp_state_t state; /* State of IPP processing */
-
-
- /*
- * Setup the HTTP variables needed...
- */
-
- httpClearFields(http);
- httpSetLength(http, ippLength(request));
- httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
-
- /*
- * Do the POST request...
- */
-
- debug_printf("DEBUG: %.3f POST %s...\n", run_time(), resource);
-
- if (httpPost(http, resource))
- {
- if (httpReconnect(http))
- {
- _cupsSetError(IPP_DEVICE_ERROR, "Unable to reconnect");
- return (NULL);
- }
- else if (httpPost(http, resource))
- {
- _cupsSetError(IPP_GONE, "Unable to POST");
- return (NULL);
- }
- }
-
- /*
- * Send the IPP data...
- */
-
- request->state = IPP_IDLE;
- status = HTTP_CONTINUE;
-
- while ((state = ippWrite(http, request)) != IPP_DATA)
- if (state == IPP_ERROR)
- {
- status = HTTP_ERROR;
- break;
- }
- else if (httpCheck(http))
- {
- if ((status = httpUpdate(http)) != HTTP_CONTINUE)
- break;
- }
-
- /*
- * Get the server's return status...
- */
-
- debug_printf("DEBUG: %.3f Getting response...\n", run_time());
-
- while (status == HTTP_CONTINUE)
- if (httpWait(http, 1000))
- status = httpUpdate(http);
- else
- {
- status = HTTP_ERROR;
- http->error = ETIMEDOUT;
- }
-
- if (status != HTTP_OK)
- {
- /*
- * Flush any error message...
- */
-
- httpFlush(http);
- response = NULL;
- }
- else
- {
- /*
- * Read the response...
- */
-
- response = ippNew();
-
- while ((state = ippRead(http, response)) != IPP_DATA)
- if (state == IPP_ERROR)
- {
- /*
- * Delete the response...
- */
-
- ippDelete(response);
- response = NULL;
-
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
- break;
- }
- }
-
- /*
- * Delete the original request and return the response...
- */
-
- ippDelete(request);
-
- if (response)
- {
- ipp_attribute_t *attr; /* status-message attribute */
-
-
- attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT);
-
- _cupsSetError(response->request.status.status_code,
- attr ? attr->values[0].string.text :
- ippErrorString(response->request.status.status_code));
- }
- else if (status != HTTP_OK)
- {
- switch (status)
- {
- case HTTP_NOT_FOUND :
- _cupsSetError(IPP_NOT_FOUND, httpStatus(status));
- break;
-
- case HTTP_UNAUTHORIZED :
- _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status));
- break;
-
- case HTTP_FORBIDDEN :
- _cupsSetError(IPP_FORBIDDEN, httpStatus(status));
- break;
-
- case HTTP_BAD_REQUEST :
- _cupsSetError(IPP_BAD_REQUEST, httpStatus(status));
- break;
-
- case HTTP_REQUEST_TOO_LARGE :
- _cupsSetError(IPP_REQUEST_VALUE, httpStatus(status));
- break;
-
- case HTTP_NOT_IMPLEMENTED :
- _cupsSetError(IPP_OPERATION_NOT_SUPPORTED, httpStatus(status));
- break;
-
- case HTTP_NOT_SUPPORTED :
- _cupsSetError(IPP_VERSION_NOT_SUPPORTED, httpStatus(status));
- break;
-
- default :
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status));
- break;
- }
- }
-
- return (response);
-}
-
-
/*
* 'fix_make_model()' - Fix common problems in the make-and-model string.
*/
static void
probe_device(snmp_cache_t *device) /* I - Device */
{
- int i, j; /* Looping vars */
- http_t *http; /* HTTP connection for IPP */
- char uri[1024]; /* Full device URI */
+ char uri[1024], /* Full device URI */
+ *uriptr, /* Pointer into URI */
+ *format; /* Format string for device */
+ device_uri_t *device_uri; /* Current DeviceURI match */
- /*
- * Try connecting via IPP first...
- */
-
debug_printf("DEBUG: %.3f Probing %s...\n", run_time(), device->addrname);
- if (device->make_and_model &&
- (!strncasecmp(device->make_and_model, "Epson", 5) ||
- !strncasecmp(device->make_and_model, "HP ", 3) ||
- !strncasecmp(device->make_and_model, "Hewlett", 7) ||
- !strncasecmp(device->make_and_model, "Kyocera", 7) ||
- !strncasecmp(device->make_and_model, "Lexmark", 7) ||
- !strncasecmp(device->make_and_model, "Tektronix", 9) ||
- !strncasecmp(device->make_and_model, "Xerox", 5)))
- {
- /*
- * Epson, HP, Kyocera, Lexmark, Tektronix, and Xerox printers often lock
- * up on IPP probes, so exclude them from the IPP connection test...
- */
+#ifdef __APPLE__
+ /*
+ * TODO: Try an mDNS query first, and then fallback on direct probes...
+ */
- http = NULL;
- }
- else
+ if (!try_connect(&(device->address), device->addrname, 5353))
{
- /*
- * Otherwise, try connecting for up to 1 second...
- */
-
- alarm(1);
- http = httpConnect(device->addrname, 631);
- alarm(0);
+ debug_printf("DEBUG: %s supports mDNS, not reporting!\n", device->addrname);
+ return;
}
+#endif /* __APPLE__ */
- if (http)
- {
- /*
- * IPP is supported...
- */
-
- ipp_t *request, /* IPP request */
- *response; /* IPP response */
- ipp_attribute_t *model, /* printer-make-and-model attribute */
- *info, /* printer-info attribute */
- *supported; /* printer-uri-supported attribute */
- char make_model[256],/* Make and model string to use */
- temp[256]; /* Temporary make/model string */
- int num_uris; /* Number of good URIs */
- static const char * const resources[] =
- { /* Common resource paths for IPP */
- "/ipp",
- /*"/ipp/port2",*/
- /*"/ipp/port3",*/
- /*"/EPSON_IPP_Printer",*/
- "/LPT1",
- "/LPT2",
- "/COM1",
- "/"
- };
-
-
- /*
- * Use non-blocking IO...
- */
-
- httpBlocking(http, 0);
-
- /*
- * Loop through a list of common resources that covers 99% of the
- * IPP-capable printers on the market today...
- */
+ /*
+ * Lookup the device in the match table...
+ */
- for (i = 0, num_uris = 0;
- i < (int)(sizeof(resources) / sizeof(resources[0]));
- i ++)
+ for (device_uri = (device_uri_t *)cupsArrayFirst(DeviceURIs);
+ device_uri;
+ device_uri = (device_uri_t *)cupsArrayNext(DeviceURIs))
+ if (!regexec(&(device_uri->re), device->make_and_model, 0, NULL, 0))
{
/*
- * Stop early if we are out of time...
- */
-
- if (MaxRunTime > 0 && run_time() >= MaxRunTime)
- break;
-
- /*
- * Don't look past /ipp if we have found a working URI...
+ * Found a match, add the URIs...
*/
- if (num_uris > 0 && strncmp(resources[i], "/ipp", 4))
- break;
-
- httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
- device->addrname, 631, resources[i]);
-
- request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
-
- response = do_request(http, request, resources[i]);
-
- debug_printf("DEBUG: %.3f %s %s (%s)\n", run_time(), uri,
- ippErrorString(cupsLastError()), cupsLastErrorString());
-
- if (response && response->request.status.status_code == IPP_OK)
+ for (format = (char *)cupsArrayFirst(device_uri->uris);
+ format;
+ format = (char *)cupsArrayNext(device_uri->uris))
{
- model = ippFindAttribute(response, "printer-make-and-model",
- IPP_TAG_TEXT);
- info = ippFindAttribute(response, "printer-info", IPP_TAG_TEXT);
- supported = ippFindAttribute(response, "printer-uri-supported",
- IPP_TAG_URI);
-
- if (!supported)
- {
- fprintf(stderr, "ERROR: Missing printer-uri-supported from %s!\n",
- device->addrname);
-
- httpClose(http);
- return;
- }
-
- debug_printf("DEBUG: printer-info=\"%s\"\n",
- info ? info->values[0].string.text : "(null)");
- debug_printf("DEBUG: printer-make-and-model=\"%s\"\n",
- model ? model->values[0].string.text : "(null)");
-
- /*
- * Don't advertise this port if the printer actually only supports
- * a more generic version...
- */
-
- if (!strncmp(resources[i], "/ipp/", 5))
- {
- for (j = 0; j < supported->num_values; j ++)
- if (strstr(supported->values[j].string.text, "/ipp/"))
- break;
-
- if (j >= supported->num_values)
+ for (uriptr = uri; *format && uriptr < (uri + sizeof(uri) - 1);)
+ if (*format == '%' && format[1] == 's')
{
- ippDelete(response);
- break;
- }
- }
-
- /*
- * Don't use the printer-info attribute if it does not contain the
- * IEEE-1284 device ID data...
- */
-
- if (info &&
- (!strchr(info->values[0].string.text, ':') ||
- !strchr(info->values[0].string.text, ';')))
- info = NULL;
-
- /*
- * Don't use the printer-make-and-model if it contains a generic
- * string like "Ricoh IPP Printer"...
- */
-
- if (model && strstr(model->values[0].string.text, "IPP Printer"))
- model = NULL;
-
- /*
- * If we don't have a printer-make-and-model string from the printer
- * but do have the 1284 device ID string, generate a make-and-model
- * string from the device ID info...
- */
-
- if (model)
- strlcpy(temp, model->values[0].string.text, sizeof(temp));
- else if (info)
- backendGetMakeModel(info->values[0].string.text, temp, sizeof(temp));
- else
- temp[0] = '\0';
-
- fix_make_model(make_model, temp, sizeof(make_model));
+ /*
+ * Insert hostname/address...
+ */
- /*
- * Update the current device or add a new printer to the cache...
- */
+ strlcpy(uriptr, device->addrname, sizeof(uri) - (uriptr - uri));
+ uriptr += strlen(uriptr);
+ format += 2;
+ }
+ else
+ *uriptr++ = *format++;
- if (num_uris == 0)
- update_cache(device, uri,
- info ? info->values[0].string.text : NULL,
- make_model[0] ? make_model : NULL);
- else
- add_cache(&(device->address), device->addrname, uri,
- info ? info->values[0].string.text : NULL,
- make_model[0] ? make_model : NULL);
+ *uriptr = '\0';
- num_uris ++;
+ update_cache(device, uri, NULL, NULL);
}
- ippDelete(response);
-
- if (num_uris > 0 && cupsLastError() != IPP_OK)
- break;
- }
-
- httpClose(http);
-
- if (num_uris > 0)
return;
- }
+ }
/*
- * OK, now try the standard ports...
+ * Then try the standard ports...
*/
if (!try_connect(&(device->address), device->addrname, 9100))
add_array(Communities, value);
else if (!strcasecmp(line, "DebugLevel"))
DebugLevel = atoi(value);
+ else if (!strcasecmp(line, "DeviceURI"))
+ {
+ if (*value != '\"')
+ fprintf(stderr,
+ "ERROR: Missing double quote for regular expression on "
+ "line %d of %s!\n", linenum, filename);
+ else
+ add_device_uri(value);
+ }
else if (!strcasecmp(line, "HostNameLookups"))
HostNameLookups = !strcasecmp(value, "on") ||
!strcasecmp(value, "yes") ||
/*
- * End of "$Id: snmp.c 6403 2007-03-27 16:00:56Z mike $".
+ * End of "$Id: snmp.c 6495 2007-04-30 21:23:04Z mike $".
*/
/*
- * "$Id: usb-darwin.c 6432 2007-04-02 21:50:28Z mike $"
+ * "$Id: usb-darwin.c 6491 2007-04-30 18:21:52Z mike $"
*
* Copyright © 2005-2007 Apple Inc. All rights reserved.
*
else
strcpy(modelstr + 1, "Printer");
- /*
- * Fix common HP 1284 bug...
- */
-
- if (!strcasecmp(makestr, "Hewlett-Packard"))
- strcpy(makestr, "HP");
-
- if (!strncasecmp(modelstr + 1, "hp ", 3))
- _cups_strcpy(modelstr + 1, modelstr + 4);
-
optionsstr[0] = '\0';
if (serial != NULL)
{
httpAssembleURI(HTTP_URI_CODING_ALL, uristr, sizeof(uristr), "usb", NULL, makestr, 0, modelstr);
strncat(uristr, optionsstr, sizeof(uristr));
+ /*
+ * Fix common HP 1284 bug...
+ */
+
+ if (!strcasecmp(makestr, "Hewlett-Packard"))
+ strcpy(makestr, "HP");
+
+ if (!strncasecmp(modelstr + 1, "hp ", 3))
+ _cups_strcpy(modelstr + 1, modelstr + 4);
+
printf("direct %s \"%s %s\" \"%s %s USB\" \"%s\"\n", uristr, makestr,
&modelstr[1], makestr, &modelstr[1], idstr);
copy_deviceinfo(idString, &make, &model, &serial);
if (CFStringCompare(make, userData->make, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
if (CFStringCompare(model, userData->model, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
- if (userData->serial != NULL) {
+ if (userData->serial != NULL && CFStringGetLength(userData->serial) > 0 ) {
if (serial != NULL && CFStringCompare(serial, userData->serial, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
IOObjectRetain(obj);
userData->printerObj = obj;
}
/*
- * End of "$Id: usb-darwin.c 6432 2007-04-02 21:50:28Z mike $".
+ * End of "$Id: usb-darwin.c 6491 2007-04-30 18:21:52Z mike $".
*/
/*
- * "$Id: usb-unix.c 6437 2007-04-03 17:38:10Z mike $"
+ * "$Id: usb-unix.c 6510 2007-05-04 13:08:05Z mike $"
*
* USB port backend for the Common UNIX Printing System (CUPS).
*
do
{
-#ifdef __NetBSD__
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
/*
- * NetBSD's ulpt driver currently does not support the
- * back-channel...
+ * *BSD's ulpt driver currently does not support the
+ * back-channel, incorrectly returns data ready on a select(),
+ * and locks up on read()...
*/
use_bc = 0;
strcasecmp(hostname, "Canon") &&
strcasecmp(hostname, "Konica Minolta") &&
strcasecmp(hostname, "Minolta");
-#endif /* __NetBSD__ */
+#endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */
if ((device_fd = open_device(uri, &use_bc)) == -1)
{
/*
- * End of "$Id: usb-unix.c 6437 2007-04-03 17:38:10Z mike $".
+ * End of "$Id: usb-unix.c 6510 2007-05-04 13:08:05Z mike $".
*/
dnl
-dnl "$Id: cups-compiler.m4 6264 2007-02-11 17:11:15Z mike $"
+dnl "$Id: cups-compiler.m4 6447 2007-04-10 18:02:00Z mike $"
dnl
dnl Compiler stuff for the Common UNIX Printing System (CUPS).
dnl
# HP-UX 11.00 (at least) needs this definition to get the
# u_short type used by the IP headers...
OPTIM="$OPTIM -D_INCLUDE_HPUX_SOURCE"
+
+ # HP-UX 11.23 (at least) needs this definition to get the
+ # IPv6 header to work...
+ OPTIM="$OPTIM -D_HPUX_SOURCE"
;;
OSF*)
esac
dnl
-dnl End of "$Id: cups-compiler.m4 6264 2007-02-11 17:11:15Z mike $".
+dnl End of "$Id: cups-compiler.m4 6447 2007-04-10 18:02:00Z mike $".
dnl
dnl
-dnl "$Id: configure.in 6291 2007-02-19 21:54:27Z mike $"
+dnl "$Id: configure.in 6488 2007-04-30 17:45:57Z mike $"
dnl
dnl Configuration script for the Common UNIX Printing System (CUPS).
dnl
AC_OUTPUT(Makedefs packaging/cups.list init/cups.sh init/cups-lpd cups-config
conf/cupsd.conf conf/pam.std doc/index.html
- doc/help/standard.html man/client.conf.man
- man/cups-deviced.man man/cups-driverd.man
+ doc/help/ref-cupsd-conf.html doc/help/standard.html
+ man/client.conf.man man/cups-deviced.man man/cups-driverd.man
man/cups-lpd.man man/cupsaddsmb.man man/cupsd.man
man/cupsd.conf.man man/lpoptions.man
templates/edit-config.tmpl templates/header.tmpl
chmod +x cups-config
dnl
-dnl End of "$Id: configure.in 6291 2007-02-19 21:54:27Z mike $".
+dnl End of "$Id: configure.in 6488 2007-04-30 17:45:57Z mike $".
dnl
/*
- * "$Id: array.c 6123 2006-11-21 15:36:04Z mike $"
+ * "$Id: array.c 6477 2007-04-25 19:55:45Z mike $"
*
* Sorted array routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products.
+ * Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
void **elements; /* Array elements */
cups_array_func_t compare; /* Element comparison function */
void *data; /* User data passed to compare */
+ cups_ahash_func_t hashfunc; /* Hash function */
+ int hashsize, /* Size of hash */
+ *hash; /* Hash array */
};
if (a->alloc_elements)
free(a->elements);
+ if (a->hashsize)
+ free(a->hash);
+
free(a);
}
void *e) /* I - Element */
{
int current, /* Current element */
- diff; /* Difference */
+ diff, /* Difference */
+ hash; /* Hash index */
/*
* Yes, look for a match...
*/
- current = cups_array_find(a, e, a->current, &diff);
+ if (a->hash)
+ {
+ hash = (*(a->hashfunc))(e, a->data);
+
+ if (hash < 0 || hash >= a->hashsize)
+ {
+ current = a->current;
+ hash = -1;
+ }
+ else
+ {
+ current = a->hash[hash];
+
+ if (current < 0 || current >= a->num_elements)
+ current = a->current;
+ }
+ }
+ else
+ {
+ current = a->current;
+ hash = -1;
+ }
+
+ current = cups_array_find(a, e, current, &diff);
if (!diff)
{
/*
a->current = current;
+ if (hash >= 0)
+ a->hash[hash] = current;
+
return (a->elements[current]);
}
else
cups_array_t * /* O - Array */
cupsArrayNew(cups_array_func_t f, /* I - Comparison function */
void *d) /* I - User data */
+{
+ return (cupsArrayNew2(f, d, 0, 0));
+}
+
+
+/*
+ * 'cupsArrayNew2()' - Create a new array with hash.
+ *
+ * @since CUPS 1.3@
+ */
+
+cups_array_t * /* O - Array */
+cupsArrayNew2(cups_array_func_t f, /* I - Comparison function */
+ void *d, /* I - User data */
+ cups_ahash_func_t h, /* I - Hash function*/
+ int hsize) /* I - Hash size */
{
cups_array_t *a; /* Array */
a->num_saved = 0;
a->unique = 1;
+ if (hsize > 0 && h)
+ {
+ a->hashfunc = h;
+ a->hashsize = hsize;
+ a->hash = malloc(hsize * sizeof(int));
+
+ if (!a->hash)
+ {
+ free(a);
+ return (NULL);
+ }
+
+ memset(a->hash, -1, hsize * sizeof(int));
+ }
+
return (a);
}
/*
- * End of "$Id: array.c 6123 2006-11-21 15:36:04Z mike $".
+ * End of "$Id: array.c 6477 2007-04-25 19:55:45Z mike $".
*/
/*
- * "$Id: array.h 6123 2006-11-21 15:36:04Z mike $"
+ * "$Id: array.h 6477 2007-04-25 19:55:45Z mike $"
*
* Sorted array definitions for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products.
+ * Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
/**** CUPS array type ****/
typedef int (*cups_array_func_t)(void *first, void *second, void *data);
/**** Array comparison function ****/
+typedef int (*cups_ahash_func_t)(void *element, void *data);
+ /**** Array hash function ****/
+
/*
* Functions...
extern int cupsArrayInsert(cups_array_t *a, void *e);
extern void *cupsArrayLast(cups_array_t *a);
extern cups_array_t *cupsArrayNew(cups_array_func_t f, void *d);
+extern cups_array_t *cupsArrayNew2(cups_array_func_t f, void *d,
+ cups_ahash_func_t h, int hsize);
extern void *cupsArrayNext(cups_array_t *a);
extern void *cupsArrayPrev(cups_array_t *a);
extern int cupsArrayRemove(cups_array_t *a, void *e);
#endif /* !_CUPS_ARRAY_H_ */
/*
- * End of "$Id: array.h 6123 2006-11-21 15:36:04Z mike $".
+ * End of "$Id: array.h 6477 2007-04-25 19:55:45Z mike $".
*/
/*
- * "$Id: auth.c 6397 2007-03-25 23:33:32Z mike $"
+ * "$Id: auth.c 6499 2007-04-30 21:44:43Z mike $"
*
* Authentication functions for the Common UNIX Printing System (CUPS).
*
* Delete any previous authorization reference...
*/
- if (cg->auth_ref)
+ if (http->auth_ref)
{
- AuthorizationFree(cg->auth_ref, kAuthorizationFlagDefaults);
- cg->auth_ref = NULL;
+ AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
+ http->auth_ref = NULL;
}
if (httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
auth_key, sizeof(auth_key)))
{
status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
- kAuthorizationFlagDefaults, &cg->auth_ref);
+ kAuthorizationFlagDefaults, &http->auth_ref);
if (status != errAuthorizationSuccess)
{
DEBUG_printf(("cups_local_auth: AuthorizationCreate() returned %d (%s)\n",
kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagExtendRights;
- status = AuthorizationCopyRights(cg->auth_ref, &auth_rights,
+ status = AuthorizationCopyRights(http->auth_ref, &auth_rights,
kAuthorizationEmptyEnvironment,
auth_flags, NULL);
if (status == errAuthorizationSuccess)
- status = AuthorizationMakeExternalForm(cg->auth_ref, &auth_extrn);
+ status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn);
if (status == errAuthorizationSuccess)
{
/*
- * End of "$Id: auth.c 6397 2007-03-25 23:33:32Z mike $".
+ * End of "$Id: auth.c 6499 2007-04-30 21:44:43Z mike $".
*/
/*
- * "$Id: cups.h 6187 2007-01-10 16:20:42Z mike $"
+ * "$Id: cups.h 6506 2007-05-03 18:12:35Z mike $"
*
* API definitions for the Common UNIX Printing System (CUPS).
*
extern cups_file_t *cupsTempFile2(char *filename, int len);
/**** New in CUPS 1.3 ****/
+extern ipp_t *cupsDoIORequest(http_t *http, ipp_t *request,
+ const char *resource, int infile,
+ int outfile);
+extern char *cupsGetServerPPD(http_t *http, const char *name);
extern int cupsRemoveDest(const char *name,
const char *instance,
int num_dests, cups_dest_t **dests);
#endif /* !_CUPS_CUPS_H_ */
/*
- * End of "$Id: cups.h 6187 2007-01-10 16:20:42Z mike $".
+ * End of "$Id: cups.h 6506 2007-05-03 18:12:35Z mike $".
*/
/*
- * "$Id: globals.c 6253 2007-02-10 18:48:40Z mike $"
+ * "$Id: globals.c 6499 2007-04-30 21:44:43Z mike $"
*
* Global variable access routines for the Common UNIX Printing System (CUPS).
*
cupsFreeOptions(cg->cupsd_num_settings, cg->cupsd_settings);
-#ifdef HAVE_AUTHORIZATION_H
- if (cg->auth_ref)
- AuthorizationFree(cg->auth_ref, kAuthorizationFlagDefaults);
-#endif /* HAVE_AUTHORIZATION_H */
-
free(value);
}
/*
- * End of "$Id: globals.c 6253 2007-02-10 18:48:40Z mike $".
+ * End of "$Id: globals.c 6499 2007-04-30 21:44:43Z mike $".
*/
/*
- * "$Id: globals.h 6253 2007-02-10 18:48:40Z mike $"
+ * "$Id: globals.h 6499 2007-04-30 21:44:43Z mike $"
*
* Global variable definitions for the Common UNIX Printing System (CUPS).
*
# include <pthread.h>
# endif /* HAVE_PTHREAD_H */
-# ifdef HAVE_AUTHORIZATION_H
-# include <Security/Authorization.h>
-# endif /* HAVE_AUTHORIZATION_H */
-
/*
* C++ magic...
/* Default printer */
char ppd_filename[HTTP_MAX_URI];
/* PPD filename */
-
-#ifdef HAVE_AUTHORIZATION_H
- /* auth.c */
- AuthorizationRef auth_ref; /* Authorization ref */
-#endif /* HAVE_AUTHORIZATION_H */
} _cups_globals_t;
#endif /* !_CUPS_GLOBALS_H_ */
/*
- * End of "$Id: globals.h 6253 2007-02-10 18:48:40Z mike $".
+ * End of "$Id: globals.h 6499 2007-04-30 21:44:43Z mike $".
*/
/*
- * "$Id: http-private.h 6187 2007-01-10 16:20:42Z mike $"
+ * "$Id: http-private.h 6499 2007-04-30 21:44:43Z mike $"
*
* Private HTTP definitions for the Common UNIX Printing System (CUPS).
*
# endif /* !HAVE_GSS_C_NT_HOSTBASED_SERVICE */
# endif /* HAVE_GSSAPI */
+# ifdef HAVE_AUTHORIZATION_H
+# include <Security/Authorization.h>
+# endif /* HAVE_AUTHORIZATION_H */
+
# if defined(__sgi) || (defined(__APPLE__) && !defined(_SOCKLEN_T))
/*
* IRIX and MacOS X 10.2.x do not define socklen_t, and in fact use an int instead of
gss_ctx_id_t gssctx; /* Authentication context @since CUPS 1.3@ */
gss_name_t gssname; /* Authentication server name @since CUPS 1.3@ */
# endif /* HAVE_GSSAPI */
+# ifdef HAVE_AUTHORIZATION_H
+ AuthorizationRef auth_ref; /* Authorization ref */
+# endif /* HAVE_AUTHORIZATION_H */
};
#endif /* !_CUPS_HTTP_PRIVATE_H_ */
/*
- * End of "$Id: http-private.h 6187 2007-01-10 16:20:42Z mike $".
+ * End of "$Id: http-private.h 6499 2007-04-30 21:44:43Z mike $".
*/
/*
- * "$Id: http.c 6285 2007-02-16 01:10:55Z mike $"
+ * "$Id: http.c 6499 2007-04-30 21:44:43Z mike $"
*
* HTTP routines for the Common UNIX Printing System (CUPS).
*
major_status = gss_release_name(&minor_status, &http->gssname);
#endif /* HAVE_GSSAPI */
+#ifdef HAVE_AUTHORIZATION_H
+ if (http->auth_ref)
+ AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
+#endif /* HAVE_AUTHORIZATION_H */
+
httpClearFields(http);
if (http->authstring && http->authstring != http->_authstring)
httpClearFields(http);
/*
- * The Kerberos authentication string can only be used once...
+ * The Kerberos and AuthRef authentication strings can only be used once...
*/
- if (http->authstring && !strncmp(http->authstring, "Negotiate", 9))
+ if (http->authstring &&
+ (!strncmp(http->authstring, "Negotiate", 9) ||
+ !strncmp(http->authstring, "AuthRef", 7)))
{
http->_authstring[0] = '\0';
/*
- * End of "$Id: http.c 6285 2007-02-16 01:10:55Z mike $".
+ * End of "$Id: http.c 6499 2007-04-30 21:44:43Z mike $".
*/
/*
- * "$Id: ipp-support.c 5903 2006-08-29 20:45:15Z mike $"
+ * "$Id: ipp-support.c 6503 2007-05-01 23:06:44Z mike $"
*
* Internet Printing Protocol support functions for the Common UNIX
* Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
"CUPS-Get-Devices",
"CUPS-Get-PPDs",
"CUPS-Move-Job",
- "CUPS-Authenticate-Job"
+ "CUPS-Authenticate-Job",
+ "CUPS-Get-PPD"
};
return (ipp_status_oks[error]);
else if (error == IPP_REDIRECTION_OTHER_SITE)
return ("redirection-other-site");
+ else if (error == CUPS_SEE_OTHER)
+ return ("cups-see-other");
else if (error >= IPP_BAD_REQUEST && error <= IPP_PRINT_SUPPORT_FILE_NOT_FOUND)
return (ipp_status_400s[error - IPP_BAD_REQUEST]);
else if (error >= IPP_INTERNAL_ERROR && error <= IPP_PRINTER_IS_DEACTIVATED)
if (!strcasecmp(name, "redirection-other-site"))
return (IPP_REDIRECTION_OTHER_SITE);
+ if (!strcasecmp(name, "cups-see-other"))
+ return (CUPS_SEE_OTHER);
+
for (i = 0; i < (sizeof(ipp_status_400s) / sizeof(ipp_status_400s[0])); i ++)
if (!strcasecmp(name, ipp_status_400s[i]))
return ((ipp_status_t)(i + 0x400));
return (ipp_std_ops[op]);
else if (op == IPP_PRIVATE)
return ("windows-ext");
- else if (op >= CUPS_GET_DEFAULT && op <= CUPS_AUTHENTICATE_JOB)
+ else if (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD)
return (ipp_cups_ops[op - CUPS_GET_DEFAULT]);
/*
/*
- * End of "$Id: ipp-support.c 5903 2006-08-29 20:45:15Z mike $".
+ * End of "$Id: ipp-support.c 6503 2007-05-01 23:06:44Z mike $".
*/
/*
- * "$Id: ipp.h 5873 2006-08-24 14:37:24Z mike $"
+ * "$Id: ipp.h 6503 2007-05-01 23:06:44Z mike $"
*
* Internet Printing Protocol definitions for the Common UNIX Printing
* System (CUPS).
CUPS_GET_DEVICES, /* Get a list of supported devices */
CUPS_GET_PPDS, /* Get a list of supported drivers */
CUPS_MOVE_JOB, /* Move a job to a different printer */
- CUPS_AUTHENTICATE_JOB /* Authenticate a job @since CUPS 1.2@ */
+ CUPS_AUTHENTICATE_JOB, /* Authenticate a job @since CUPS 1.2@ */
+ CUPS_GET_PPD /* Get a PPD file @since CUPS 1.3@ */
} ipp_op_t;
/* Old names for the operations */
IPP_OK_TOO_MANY_EVENTS, /* successful-ok-too-many-events */
IPP_OK_BUT_CANCEL_SUBSCRIPTION, /* successful-ok-but-cancel-subscription */
IPP_OK_EVENTS_COMPLETE, /* successful-ok-events-complete */
- IPP_REDIRECTION_OTHER_SITE = 0x300, /* */
+ IPP_REDIRECTION_OTHER_SITE = 0x200, /* */
+ CUPS_SEE_OTHER = 0x280, /* cups-see-other */
IPP_BAD_REQUEST = 0x0400, /* client-error-bad-request */
IPP_FORBIDDEN, /* client-error-forbidden */
IPP_NOT_AUTHENTICATED, /* client-error-not-authenticated */
#endif /* !_CUPS_IPP_H_ */
/*
- * End of "$Id: ipp.h 5873 2006-08-24 14:37:24Z mike $".
+ * End of "$Id: ipp.h 6503 2007-05-01 23:06:44Z mike $".
*/
/*
- * "$Id: language.c 6407 2007-03-27 17:45:12Z mike $"
+ * "$Id: language.c 6489 2007-04-30 17:55:15Z mike $"
*
* I18N/language support for the Common UNIX Printing System (CUPS).
*
*/
# ifdef HAVE_CF_LOCALE_ID
+
+typedef struct
+{
+ const char * const name; /* Language name */
+ const char * const locale; /* Locale name */
+} _apple_name_locale_t;
+
+static const _apple_name_locale_t apple_name_locale[] =
+{
+ { "en" , "en_US" },
+ { "no" , "nb" },
+ { "zh-Hans" , "zh_CN" },
+ { "zh-Hant" , "zh_TW" }
+};
+
/*
* 'appleLangDefault()' - Get the default locale string.
*/
static const char * /* O - Locale string */
appleLangDefault(void)
{
+ int i; /* Looping var */
CFPropertyListRef localizationList;
/* List of localization data */
CFStringRef languageName; /* Current name */
kCFStringEncodingASCII);
CFRelease(localeName);
- if (!strcmp(cg->language, "en"))
- strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language));
- else if (strchr(cg->language, '.') == NULL)
+ /*
+ * Map new language identifiers to locales...
+ */
+
+ for (i = 0;
+ i < sizeof(apple_name_locale) / sizeof(apple_name_locale[0]);
+ i++)
+ {
+ if (!strcmp(cg->language, apple_name_locale[i].name))
+ {
+ strlcpy(cg->language, apple_name_locale[i].locale,
+ sizeof(cg->language));
+ break;
+ }
+ }
+
+ /*
+ * Convert language subtag into region subtag...
+ */
+
+ if (cg->language[2] == '-')
+ cg->language[2] = '_';
+
+ if (strchr(cg->language, '.') == NULL)
strlcat(cg->language, ".UTF-8", sizeof(cg->language));
}
}
/*
- * End of "$Id: language.c 6407 2007-03-27 17:45:12Z mike $".
+ * End of "$Id: language.c 6489 2007-04-30 17:55:15Z mike $".
*/
/*
- * "$Id: localize.c 6388 2007-03-24 14:21:31Z mike $"
+ * "$Id: localize.c 6457 2007-04-17 18:40:55Z mike $"
*
* PPD custom option routines for the Common UNIX Printing System (CUPS).
*
strlcpy(ll_CC, lang->language, sizeof(ll_CC));
strlcpy(ll, lang->language, sizeof(ll));
+ if (strlen(ll_CC) == 2)
+ {
+ /*
+ * Map "ll" to primary/origin country locales to have the best
+ * chance of finding a match...
+ */
+
+ if (!strcmp(ll_CC, "cs"))
+ strcpy(ll_CC, "cs_CZ");
+ else if (!strcmp(ll_CC, "en"))
+ strcpy(ll_CC, "en_US");
+ else if (!strcmp(ll_CC, "ja"))
+ strcpy(ll_CC, "ja_JP");
+ else if (!strcmp(ll_CC, "sv"))
+ strcpy(ll_CC, "sv_SE");
+ else if (!strcmp(ll_CC, "zh"))
+ strcpy(ll_CC, "zh_CN"); /* Simplified Chinese */
+ else
+ {
+ ll_CC[2] = '_';
+ ll_CC[3] = toupper(ll_CC[0] & 255);
+ ll_CC[4] = toupper(ll_CC[1] & 255);
+ ll_CC[5] = '\0';
+ }
+ }
+
DEBUG_printf((" lang->language=\"%s\", ll=\"%s\", ll_CC=\"%s\"...\n",
lang->language, ll, ll_CC));
/*
- * End of "$Id: localize.c 6388 2007-03-24 14:21:31Z mike $".
+ * End of "$Id: localize.c 6457 2007-04-17 18:40:55Z mike $".
*/
/*
- * "$Id: mark.c 6187 2007-01-10 16:20:42Z mike $"
+ * "$Id: mark.c 6477 2007-04-25 19:55:45Z mike $"
*
* Option marking routines for the Common UNIX Printing System (CUPS).
*
* 'ppdConflicts()' - Check to see if there are any conflicts.
*/
-int /* O - Number of conflicts found */
-ppdConflicts(ppd_file_t *ppd) /* I - PPD to check */
+int /* O - Number of conflicts found */
+ppdConflicts(ppd_file_t *ppd) /* I - PPD to check */
{
- int i, j, /* Looping variables */
- conflicts; /* Number of conflicts */
- ppd_const_t *c; /* Current constraint */
- ppd_option_t *o1, *o2; /* Options */
- ppd_choice_t *c1, *c2; /* Choices */
+ int i, /* Looping variable */
+ conflicts; /* Number of conflicts */
+ ppd_const_t *c; /* Current constraint */
+ ppd_option_t *o1, *o2; /* Options */
+ ppd_choice_t *c1, *c2; /* Choices */
+ ppd_choice_t key; /* Search key */
if (!ppd)
* that conflict...
*/
- for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
+ for (i = ppd->num_consts, c = ppd->consts, o1 = o2 = NULL, c1 = c2 = NULL;
+ i > 0;
+ i --, c ++)
{
/*
* Grab pointers to the first option...
*/
- o1 = ppdFindOption(ppd, c->option1);
+ if (!o1 || strcmp(c->option1, o1->keyword))
+ {
+ o1 = ppdFindOption(ppd, c->option1);
+ c1 = NULL;
+ }
if (!o1)
continue;
- else if (c->choice1[0])
+ else if (c->choice1[0] && (!c1 || strcmp(c->choice1, c1->choice)))
{
/*
* This constraint maps to a specific choice.
*/
- c1 = ppdFindChoice(o1, c->choice1);
+ key.option = o1;
+
+ if ((c1 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+ !c1->marked)
+ c1 = NULL;
}
- else
+ else if (!c1)
{
/*
* This constraint applies to any choice for this option.
*/
- for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
- if (c1->marked)
- break;
+ key.option = o1;
- if (!j ||
- !strcasecmp(c1->choice, "None") ||
- !strcasecmp(c1->choice, "Off") ||
- !strcasecmp(c1->choice, "False"))
+ if ((c1 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+ (!strcasecmp(c1->choice, "None") || !strcasecmp(c1->choice, "Off") ||
+ !strcasecmp(c1->choice, "False")))
c1 = NULL;
}
* Grab pointers to the second option...
*/
- o2 = ppdFindOption(ppd, c->option2);
+ if (!o2 || strcmp(c->option2, o2->keyword))
+ {
+ o2 = ppdFindOption(ppd, c->option2);
+ c2 = NULL;
+ }
if (!o2)
continue;
- else if (c->choice2[0])
+ else if (c->choice2[0] && (!c2 || strcmp(c->choice2, c2->choice)))
{
/*
* This constraint maps to a specific choice.
*/
- c2 = ppdFindChoice(o2, c->choice2);
+ key.option = o2;
+
+ if ((c2 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+ !c2->marked)
+ c2 = NULL;
}
- else
+ else if (!c2)
{
/*
* This constraint applies to any choice for this option.
*/
- for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
- if (c2->marked)
- break;
+ key.option = o2;
- if (!j ||
- !strcasecmp(c2->choice, "None") ||
- !strcasecmp(c2->choice, "Off") ||
- !strcasecmp(c2->choice, "False"))
+ if ((c2 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
+ (!strcasecmp(c2->choice, "None") || !strcasecmp(c2->choice, "Off") ||
+ !strcasecmp(c2->choice, "False")))
c2 = NULL;
}
ppdFindChoice(ppd_option_t *o, /* I - Pointer to option */
const char *choice) /* I - Name of choice */
{
- int i; /* Looping var */
- ppd_choice_t *c; /* Current choice */
+ int i; /* Looping var */
+ ppd_choice_t *c; /* Current choice */
if (o == NULL || choice == NULL)
ppdFindMarkedChoice(ppd_file_t *ppd, /* I - PPD file */
const char *option) /* I - Keyword/option name */
{
- int i; /* Looping var */
- ppd_option_t *o; /* Pointer to option */
- ppd_choice_t *c; /* Pointer to choice */
+ ppd_choice_t key; /* Search key for choice */
- if ((o = ppdFindOption(ppd, option)) == NULL)
+ if ((key.option = ppdFindOption(ppd, option)) == NULL)
return (NULL);
- for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
- if (c->marked)
- return (c);
-
- return (NULL);
+ return ((ppd_choice_t *)cupsArrayFind(ppd->marked, &key));
}
* 'ppdIsMarked()' - Check to see if an option is marked...
*/
-int /* O - Non-zero if option is marked */
-ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */
- const char *option, /* I - Option/Keyword name */
- const char *choice) /* I - Choice name */
+int /* O - Non-zero if option is marked */
+ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */
+ const char *option, /* I - Option/Keyword name */
+ const char *choice) /* I - Choice name */
{
- ppd_option_t *o; /* Option pointer */
- ppd_choice_t *c; /* Choice pointer */
+ ppd_choice_t key, /* Search key */
+ *c; /* Choice pointer */
- if (ppd == NULL)
+ if (!ppd)
return (0);
- if ((o = ppdFindOption(ppd, option)) == NULL)
+ if ((key.option = ppdFindOption(ppd, option)) == NULL)
return (0);
- if ((c = ppdFindChoice(o, choice)) == NULL)
+ if ((c = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) == NULL)
return (0);
- return (c->marked);
+ return (!strcmp(c->choice, choice));
}
*/
void
-ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */
+ppdMarkDefaults(ppd_file_t *ppd) /* I - PPD file record */
{
- int i; /* Looping variables */
- ppd_group_t *g; /* Current group */
+ int i; /* Looping variables */
+ ppd_group_t *g; /* Current group */
+ ppd_choice_t *c; /* Current choice */
- if (ppd == NULL)
+ if (!ppd)
return;
+ /*
+ * Clean out the marked array...
+ */
+
+ for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked);
+ c;
+ c = (ppd_choice_t *)cupsArrayNext(ppd->marked))
+ cupsArrayRemove(ppd->marked, c);
+
+ /*
+ * Then repopulate it with the defaults...
+ */
+
for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
ppd_defaults(ppd, g);
}
{
int i, j; /* Looping vars */
ppd_option_t *o; /* Option pointer */
- ppd_choice_t *c; /* Choice pointer */
+ ppd_choice_t *c, /* Choice pointer */
+ *oldc, /* Old choice pointer */
+ key; /* Search key for choice */
struct lconv *loc; /* Locale data */
if (!strcasecmp(option, "AP_D_InputSlot"))
{
if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
- for (i = 0; i < o->num_choices; i ++)
- o->choices[i].marked = 0;
+ {
+ key.option = o;
+ if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+ {
+ oldc->marked = 0;
+ cupsArrayRemove(ppd->marked, oldc);
+ }
+ }
}
/*
* Option found; mark it and then handle unmarking any other options.
*/
- c->marked = 1;
-
if (o->ui != PPD_UI_PICKMANY)
{
/*
* Unmark all other choices...
*/
- for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
- if (strcasecmp(c->choice, choice))
+ if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, c)) != NULL)
+ {
+ oldc->marked = 0;
+ cupsArrayRemove(ppd->marked, oldc);
+ }
+
+ if (!strcasecmp(option, "PageSize") || !strcasecmp(option, "PageRegion"))
+ {
+ /*
+ * Mark current page size...
+ */
+
+ for (j = 0; j < ppd->num_sizes; j ++)
+ ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
+ choice);
+
+ /*
+ * Unmark the current PageSize or PageRegion setting, as
+ * appropriate...
+ */
+
+ if (!strcasecmp(option, "PageSize"))
{
- c->marked = 0;
+ if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
+ {
+ key.option = o;
+ if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+ {
+ oldc->marked = 0;
+ cupsArrayRemove(ppd->marked, oldc);
+ }
+ }
+ }
+ else
+ {
+ if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
+ {
+ key.option = o;
+ if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+ {
+ oldc->marked = 0;
+ cupsArrayRemove(ppd->marked, oldc);
+ }
+ }
+ }
+ }
+ else if (!strcasecmp(option, "InputSlot"))
+ {
+ /*
+ * Unmark ManualFeed True and possibly mark ManualFeed False
+ * option...
+ */
- if (!strcasecmp(option, "PageSize") ||
- !strcasecmp(option, "PageRegion"))
- {
- /*
- * Mark current page size...
- */
-
- for (j = 0; j < ppd->num_sizes; j ++)
- ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
- choice);
-
- /*
- * Unmark the current PageSize or PageRegion setting, as
- * appropriate...
- */
-
- if (!strcasecmp(option, "PageSize"))
- {
- if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
- for (j = 0; j < o->num_choices; j ++)
- o->choices[j].marked = 0;
- }
- else
- {
- if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
- for (j = 0; j < o->num_choices; j ++)
- o->choices[j].marked = 0;
- }
- }
- else if (!strcasecmp(option, "InputSlot"))
- {
- /*
- * Unmark ManualFeed True and possibly mark ManualFeed False
- * option...
- */
-
- if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
- for (j = 0; j < o->num_choices; j ++)
- o->choices[j].marked = !strcasecmp(o->choices[j].choice, "False");
- }
- else if (!strcasecmp(option, "ManualFeed") &&
- !strcasecmp(choice, "True"))
- {
- /*
- * Unmark InputSlot option...
- */
+ if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
+ {
+ key.option = o;
+ if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+ {
+ oldc->marked = 0;
+ cupsArrayRemove(ppd->marked, oldc);
+ }
+ }
+ }
+ else if (!strcasecmp(option, "ManualFeed") &&
+ !strcasecmp(choice, "True"))
+ {
+ /*
+ * Unmark InputSlot option...
+ */
- if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
- for (j = 0; j < o->num_choices; j ++)
- o->choices[j].marked = 0;
- }
+ if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
+ {
+ key.option = o;
+ if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
+ {
+ oldc->marked = 0;
+ cupsArrayRemove(ppd->marked, oldc);
+ }
}
+ }
}
+ c->marked = 1;
+
+ cupsArrayAdd(ppd->marked, c);
+
/*
* Return the number of conflicts...
*/
ppd_group_t *sg; /* Current sub-group */
- if (g == NULL)
- return;
-
for (i = g->num_options, o = g->options; i > 0; i --, o ++)
if (strcasecmp(o->keyword, "PageRegion") != 0)
ppdMarkOption(ppd, o->keyword, o->defchoice);
/*
- * End of "$Id: mark.c 6187 2007-01-10 16:20:42Z mike $".
+ * End of "$Id: mark.c 6477 2007-04-25 19:55:45Z mike $".
*/
/*
- * "$Id: ppd.c 6445 2007-04-04 23:43:26Z mike $"
+ * "$Id: ppd.c 6479 2007-04-27 11:44:10Z mike $"
*
* PPD file routines for the Common UNIX Printing System (CUPS).
*
* ppd_add_choice() - Add a choice to an option.
* ppd_add_size() - Add a page size.
* ppd_compare_attrs() - Compare two attributes.
+ * ppd_compare_choices() - Compare two choices...
+ * ppd_compare_consts() - Compare two constraints.
* ppd_compare_coptions() - Compare two custom options.
* ppd_compare_cparams() - Compare two custom parameters.
* ppd_compare_options() - Compare two options.
* ppd_get_cparam() - Get a custom parameter record.
* ppd_get_group() - Find or create the named group as needed.
* ppd_get_option() - Find or create the named option as needed.
+ * ppd_hash_option() - Generate a hash of the option name...
* ppd_read() - Read a line from a PPD file, skipping comment
* lines as necessary.
*/
#define PPD_TEXT 4 /* Line contained human-readable text */
#define PPD_STRING 8 /* Line contained a string or code */
+#define PPD_HASHSIZE 512 /* Size of hash */
+
/*
* Local functions...
static ppd_choice_t *ppd_add_choice(ppd_option_t *option, const char *name);
static ppd_size_t *ppd_add_size(ppd_file_t *ppd, const char *name);
static int ppd_compare_attrs(ppd_attr_t *a, ppd_attr_t *b);
+static int ppd_compare_choices(ppd_choice_t *a, ppd_choice_t *b);
+static int ppd_compare_consts(ppd_const_t *a, ppd_const_t *b);
static int ppd_compare_coptions(ppd_coption_t *a,
ppd_coption_t *b);
static int ppd_compare_cparams(ppd_cparam_t *a, ppd_cparam_t *b);
const char *text, _cups_globals_t *cg,
cups_encoding_t encoding);
static ppd_option_t *ppd_get_option(ppd_group_t *group, const char *name);
+static int ppd_hash_option(ppd_option_t *option);
static int ppd_read(cups_file_t *fp, char *keyword, char *option,
char *text, char **string, int ignoreblank,
_cups_globals_t *cg);
}
cupsArrayDelete(ppd->options);
+ cupsArrayDelete(ppd->marked);
/*
* Free any page sizes...
* each choice and custom option...
*/
- ppd->options = cupsArrayNew((cups_array_func_t)ppd_compare_options, NULL);
+ ppd->options = cupsArrayNew2((cups_array_func_t)ppd_compare_options, NULL,
+ (cups_ahash_func_t)ppd_hash_option,
+ PPD_HASHSIZE);
for (i = ppd->num_groups, group = ppd->groups;
i > 0;
}
}
+ /*
+ * Sort the constraints...
+ */
+
+ if (ppd->num_consts > 1)
+ qsort(ppd->consts, ppd->num_consts, sizeof(ppd_const_t),
+ (int (*)(const void *, const void *))ppd_compare_consts);
+
+ /*
+ * Create an array to track the marked choices...
+ */
+
+ ppd->marked = cupsArrayNew((cups_array_func_t)ppd_compare_choices, NULL);
+
/*
* Return the PPD file structure...
*/
}
+/*
+ * 'ppd_compare_choices()' - Compare two choices...
+ */
+
+static int /* O - Result of comparison */
+ppd_compare_choices(ppd_choice_t *a, /* I - First choice */
+ ppd_choice_t *b) /* I - Second choice */
+{
+ return (a->option - b->option);
+}
+
+
+/*
+ * 'ppd_compare_consts()' - Compare two constraints.
+ */
+
+static int /* O - Result of comparison */
+ppd_compare_consts(ppd_const_t *a, /* I - First constraint */
+ ppd_const_t *b) /* I - Second constraint */
+{
+ int ret; /* Result of comparison */
+
+
+ if ((ret = strcmp(a->option1, b->option1)) != 0)
+ return (ret);
+ else if ((ret = strcmp(a->choice1, b->choice1)) != 0)
+ return (ret);
+ else if ((ret = strcmp(a->option2, b->option2)) != 0)
+ return (ret);
+ else
+ return (strcmp(a->choice2, b->choice2));
+}
+
+
/*
* 'ppd_compare_coptions()' - Compare two custom options.
*/
}
+/*
+ * 'ppd_hash_option()' - Generate a hash of the option name...
+ */
+
+static int /* O - Hash index */
+ppd_hash_option(ppd_option_t *option) /* I - Option */
+{
+ int hash = 0; /* Hash index */
+ const char *k; /* Pointer into keyword */
+
+
+ for (hash = option->keyword[0], k = option->keyword + 1; *k;)
+ hash = 33 * hash + *k++;
+
+ return (hash & 511);
+}
+
+
/*
* 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
* necessary.
/*
- * End of "$Id: ppd.c 6445 2007-04-04 23:43:26Z mike $".
+ * End of "$Id: ppd.c 6479 2007-04-27 11:44:10Z mike $".
*/
/*
- * "$Id: ppd.h 5238 2006-03-07 04:41:42Z mike $"
+ * "$Id: ppd.h 6477 2007-04-25 19:55:45Z mike $"
*
* PostScript Printer Description definitions for the Common UNIX Printing
* System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
cups_array_t *sorted_attrs; /* Attribute lookup array @since CUPS 1.2@ @private@ */
cups_array_t *options; /* Option lookup array @since CUPS 1.2@ @private@ */
cups_array_t *coptions; /* Custom options array @since CUPS 1.2@ @private@ */
+
+ /**** New in CUPS 1.3 ****/
+ cups_array_t *marked; /* Marked choices @since CUPS 1.3@ @private@ */
} ppd_file_t;
#endif /* !_CUPS_PPD_H_ */
/*
- * End of "$Id: ppd.h 5238 2006-03-07 04:41:42Z mike $".
+ * End of "$Id: ppd.h 6477 2007-04-25 19:55:45Z mike $".
*/
/*
- * "$Id: request.c 6416 2007-03-30 18:30:33Z mike $"
+ * "$Id: request.c 6506 2007-05-03 18:12:35Z mike $"
*
* IPP utilities for the Common UNIX Printing System (CUPS).
*
#else
# include <unistd.h>
#endif /* WIN32 || __EMX__ */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif /* O_BINARY */
/*
ipp_t *request, /* I - IPP request */
const char *resource, /* I - HTTP resource for POST */
const char *filename) /* I - File to send or NULL for none */
+{
+ ipp_t *response; /* IPP response data */
+ int infile; /* Input file */
+
+
+ if (filename)
+ {
+ if ((infile = open(filename, O_RDONLY | O_BINARY)) < 0)
+ {
+ /*
+ * Can't get file information!
+ */
+
+ _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+ strerror(errno));
+
+ ippDelete(request);
+
+ return (NULL);
+ }
+ }
+ else
+ infile = -1;
+
+ response = cupsDoIORequest(http, request, resource, infile, -1);
+
+ if (infile >= 0)
+ close(infile);
+
+ return (response);
+}
+
+
+/*
+ * 'cupsDoIORequest()' - Do an IPP request with file descriptors.
+ *
+ * This function sends the IPP request to the specified server, retrying
+ * and authenticating as necessary. The request is freed with ippDelete()
+ * after receiving a valid IPP response.
+ *
+ * If "infile" is a valid file descriptor, cupsDoIORequest() copies
+ * all of the data from the file after the IPP request message.
+ *
+ * If "outfile" is a valid file descriptor, cupsDoIORequest() copies
+ * all of the data after the IPP response message to the file.
+ *
+ * @since CUPS 1.3@
+ */
+
+ipp_t * /* O - Response data */
+cupsDoIORequest(http_t *http, /* I - HTTP connection to server */
+ ipp_t *request, /* I - IPP request */
+ const char *resource, /* I - HTTP resource for POST */
+ int infile, /* I - File to read from or -1 for none */
+ int outfile) /* I - File to write to or -1 for none */
{
ipp_t *response; /* IPP response data */
size_t length; /* Content-Length value */
http_status_t status; /* Status of HTTP request */
int got_status; /* Did we get the status? */
ipp_state_t state; /* State of IPP processing */
- FILE *file; /* File to send */
struct stat fileinfo; /* File information */
int bytes; /* Number of bytes read/written */
char buffer[32768]; /* Output buffer */
http_status_t expect; /* Expect: header to use */
-#ifdef HAVE_AUTHORIZATION_H
- _cups_globals_t *cg = _cupsGlobals(); /* Global data */
-#endif /* HAVE_AUTHORIZATION_H */
DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
* See if we have a file to send...
*/
- if (filename != NULL)
+ if (infile >= 0)
{
- if (stat(filename, &fileinfo))
+ if (fstat(infile, &fileinfo))
{
/*
* Can't get file information!
*/
_cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
+ strerror(errno));
ippDelete(request);
return (NULL);
}
-
- if ((file = fopen(filename, "rb")) == NULL)
- {
- /*
- * Can't open file!
- */
-
- _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
-
- ippDelete(request);
-
- return (NULL);
- }
}
- else
- file = NULL;
#ifdef HAVE_SSL
/*
*/
length = ippLength(request);
- if (filename)
+ if (infile >= 0)
+ {
+#ifndef WIN32
+ if (!S_ISREG(fileinfo.st_mode))
+ length = 0; /* Chunk when piping */
+ else
+#endif /* !WIN32 */
length += fileinfo.st_size;
+ }
httpClearFields(http);
httpSetLength(http, length);
else if (httpCheck(http))
status = httpUpdate(http);
- if (status == HTTP_CONTINUE && state == IPP_DATA && filename)
+ if (status == HTTP_CONTINUE && state == IPP_DATA && infile >= 0)
{
DEBUG_puts("cupsDoFileRequest: file write...");
* Send the file...
*/
- rewind(file);
+#ifndef WIN32
+ if (S_ISREG(fileinfo.st_mode))
+#endif /* WIN32 */
+ lseek(infile, 0, SEEK_SET);
- while ((bytes = (int)fread(buffer, 1, sizeof(buffer), file)) > 0)
+ while ((bytes = (int)read(infile, buffer, sizeof(buffer))) > 0)
{
if (httpCheck(http))
{
break;
}
- }
- }
-
- /*
- * Close the file if needed...
- */
-
- if (filename != NULL)
- fclose(file);
+ else if (outfile >= 0)
+ {
+ /*
+ * Write trailing data to file...
+ */
- /*
- * Flush any remaining data...
- */
+ while ((bytes = (int)httpRead2(http, buffer, sizeof(buffer))) > 0)
+ if (write(outfile, buffer, bytes) < bytes)
+ break;
+ }
+ else
+ {
+ /*
+ * Flush any remaining data...
+ */
- httpFlush(http);
+ httpFlush(http);
+ }
+ }
+ }
/*
* Delete the original request and return the response...
}
}
-#ifdef HAVE_AUTHORIZATION_H
- /*
- * Delete any authorization reference created for this request...
- */
-
- if (cg->auth_ref)
- {
- AuthorizationFree(cg->auth_ref, kAuthorizationFlagDefaults);
- cg->auth_ref = NULL;
- }
-#endif /* HAVE_AUTHORIZATION_H */
-
return (response);
}
/*
- * End of "$Id: request.c 6416 2007-03-30 18:30:33Z mike $".
+ * End of "$Id: request.c 6506 2007-05-03 18:12:35Z mike $".
*/
/*
- * "$Id: util.c 6138 2006-12-06 18:52:39Z mike $"
+ * "$Id: util.c 6506 2007-05-03 18:12:35Z mike $"
*
* Printing utilities for the Common UNIX Printing System (CUPS).
*
* cupsGetPPD2() - Get the PPD file for a printer on the specified
* server.
* cupsGetPrinters() - Get a list of printers from the default server.
+ * cupsGetServerPPD() - Get an available PPD file from the server.
* cupsLastError() - Return the last IPP status code.
* cupsLastErrorString() - Return the last IPP status-message.
* cupsPrintFile() - Print a file to a printer or class on the default
}
+/*
+ * 'cupsGetServerPPD()' - Get an available PPD file from the server.
+ *
+ * This function returns the named PPD file from the server. The
+ * list of available PPDs is provided by the IPP CUPS_GET_PPDS
+ * operation.
+ *
+ * You must remove (unlink) the PPD file when you are finished with
+ * it. The PPD filename is stored in a static location that will be
+ * overwritten on the next call to cupsGetPPD(), cupsGetPPD2(), or
+ * cupsGetServerPPD().
+ *
+ * @since CUPS 1.3@
+ */
+
+char * /* O - Name of PPD file or NULL on error */
+cupsGetServerPPD(http_t *http, /* I - HTTP connection */
+ const char *name) /* I - Name of PPD file ("ppd-name") */
+{
+ int fd; /* PPD file descriptor */
+ ipp_t *request; /* IPP request */
+ _cups_globals_t *cg = _cupsGlobals();
+ /* Pointer to library globals */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !name)
+ {
+ if (!http)
+ _cupsSetError(IPP_INTERNAL_ERROR, "No HTTP connection!");
+ else
+ _cupsSetError(IPP_INTERNAL_ERROR, "No PPD name!");
+
+ return (NULL);
+ }
+
+ /*
+ * Get a temp file...
+ */
+
+ if ((fd = cupsTempFd(cg->ppd_filename, sizeof(cg->ppd_filename))) < 0)
+ {
+ /*
+ * Can't open file; close the server connection and return NULL...
+ */
+
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+
+ return (NULL);
+ }
+
+ /*
+ * Get the PPD file...
+ */
+
+ request = ippNewRequest(CUPS_GET_PPD);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name", NULL,
+ name);
+
+ ippDelete(cupsDoIORequest(http, request, "/", -1, fd));
+
+ close(fd);
+
+ if (cupsLastError() != IPP_OK)
+ {
+ unlink(cg->ppd_filename);
+ return (NULL);
+ }
+ else
+ return (cg->ppd_filename);
+}
+
+
/*
* 'cupsLastError()' - Return the last IPP status code.
*/
/*
- * End of "$Id: util.c 6138 2006-12-06 18:52:39Z mike $".
+ * End of "$Id: util.c 6506 2007-05-03 18:12:35Z mike $".
*/
<HTML>
<!-- SECTION: Getting Started -->
<HEAD>
- <TITLE>Printing and Options</TITLE>
+ <TITLE>Command-Line Printing and Options</TITLE>
</HEAD>
<BODY>
</PRE>
+<H2 CLASS="title"><A NAME="LPMOVE">Moving a Print Job</A></H2>
+
+<P>The <A HREF="man-lpmove.html">lpmove(8)</A> command moves a print
+job to a new printer or class:</P>
+
+<PRE CLASS="command">
+lpmove <I>job-id</I> <i>destination</i>
+</PRE>
+
+<P>The <I>job-id</I> is the number that was reported to you by
+the <B>lp</B> or <B>lpstat</B> commands. <i>Destination</i> is the
+name of a printer or class that you want to actually print the job.
+
+<BLOCKQUOTE><B>Note:</B>
+
+<P>The <B>lpmove</B> command is located in the system command
+directory (typically <VAR>/usr/sbin</VAR> or <VAR>/usr/local/sbin</VAR>),
+and so may not be in your command path. Specify the full path to the
+command if you get a "command not found" error, for example:
+
+<PRE CLASS="command">
+/usr/sbin/lpmove foo-123 bar
+</PRE>
+
+</BLOCKQUOTE>
+
+
<H2 CLASS="title"><A NAME="OPTIONS">Standard Printing Options</A></H2>
<P>The following options apply when printing all types of
information to the system log instead of a plain file.</P>
<P>The default access log file is
-<VAR>/var/log/cups/access_log</VAR>.</P>
+<VAR>@CUPS_LOGDIR@/access_log</VAR>.</P>
<H2 CLASS="title"><A NAME="Allow">Allow</A></H2>
<P>The <CODE>BrowseLocalProtocols</CODE> directive specifies the
protocols to use when advertising local shared printers on the
network. Multiple protocols can be specified by separating them
-with spaces. The default is <CODE>cups</CODE>, which is a
-broadcast-based protocol.</P>
+with spaces. The default is <CODE>@CUPS_BROWSE_REMOTE_PROTOCOLS@</CODE>.</P>
<H2 CLASS="title"><A NAME="BrowseOrder">BrowseOrder</A></H2>
protocols to use when showing and advertising shared printers on
the local network. Multiple protocols can be specified by
separating them with spaces. The default protocol is
-<CODE>cups</CODE>, which is a broadcast-based protocol.</P>
+<CODE>@CUPS_BROWSE_LOCAL_PROTOCOLS@</CODE> for
+<A HREF="#BrowseLocalProtocols"><CODE>BrowseLocalProtocols</CODE></A> and
+<CODE>@CUPS_BROWSE_REMOTE_PROTOCOLS@</CODE> for
+<A HREF="#BrowseRemoteProtocols"><CODE>BrowseRemoteProtocols</CODE></A>.</P>
<BLOCKQUOTE><B>Note:</B>
<P>The <CODE>BrowseRemoteProtocols</CODE> directive specifies the
protocols to use when finding remote shared printers on the
network. Multiple protocols can be specified by separating them
-with spaces. The default is <CODE>cups</CODE>, which is a
-broadcast-based protocol.</P>
+with spaces. The default is <CODE>@CUPS_BROWSE_REMOTE_PROTOCOLS@</CODE>.</P>
<H2 CLASS="title"><A NAME="BrowseShortNames">BrowseShortNames</A></H2>
same name, the printers will have long names ("printer@server1",
"printer@server2".)</P>
-<P>The default value for this option is <CODE>Yes</CODE>.</P>
+<P>The default value for this option is <CODE>@CUPS_BROWSE_SHORT_NAMES@</CODE>.</P>
<H2 CLASS="title"><A NAME="BrowseTimeout">BrowseTimeout</A></H2>
<P>The <CODE>Browsing</CODE> directive controls whether or not
network printer browsing is enabled. The default setting is
-<CODE>On</CODE>.</P>
+<CODE>@CUPS_BROWSING@</CODE>.</P>
<P>This directive does not enable sharing of local printers by
itself; you must also use the <A
<P>The <CODE>ConfigFilePerm</CODE> directive specifies the
permissions to use when writing configuration files. The default
-is 0640.</P>
+is @CUPS_CONFIG_FILE_PERM@.</P>
<H2 CLASS="title"><A NAME="DataDir">DataDir</A></H2>
<P>The <CODE>DefaultShared</CODE> directive specifies whether
printers are shared (published) by default. The default is
-<CODE>yes</CODE>.</P>
+<CODE>@CUPS_DEFAULT_SHARED@</CODE>.</P>
<H2 CLASS="title"><A NAME="Deny">Deny</A></H2>
of web content for the HTTP server in CUPS. If an absolute path
is not specified then it is assumed to be relative to the <A
HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
-default directory is <VAR>/usr/share/doc/cups</VAR>.</P>
+default directory is <VAR>@CUPS_DOCROOT@</VAR>.</P>
<P>Documents are first looked up in a sub-directory for the
primary language requested by the client (e.g.
-<VAR>/usr/share/doc/cups/fr/...</VAR>) and then directly under
+<VAR>@CUPS_DOCROOT@/fr/...</VAR>) and then directly under
the <CODE>DocumentRoot</CODE> directory (e.g.
-<VAR>/usr/share/doc/cups/...</VAR>), so it is possible to
+<VAR>@CUPS_DOCROOT@/...</VAR>), so it is possible to
localize the web content by providing subdirectories for each
language needed.</P>
log file. If the filename is not absolute then it is assumed to
be relative to the <A
HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
-default error log file is <VAR>/var/log/cups/error_log</VAR>.</P>
+default error log file is <VAR>@CUPS_LOGDIR@/error_log</VAR>.</P>
<P>The server name can be included in the filename by using
<CODE>%s</CODE> in the name.</P>
required.</P>
-<H2 CLASS="title"><A NAME="ImplicitClasses">ImplicitClasses</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-ImplicitClasses On
-ImplicitClasses Off
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>ImplicitClasses</CODE> directive controls whether
-implicit classes are created based upon the available network
-printers and classes. The default setting is <CODE>On</CODE> but
-is automatically turned <CODE>Off</CODE> if <A
-HREF="#Browsing"><CODE>Browsing</CODE></A> is turned
-<CODE>Off</CODE>.</P>
-
-
<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.10</SPAN><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H2>
<H3>Examples</H3>
must be enabled for this directive to have any effect.</P>
+<H2 CLASS="title"><A NAME="ImplicitClasses">ImplicitClasses</A></H2>
+
+<H3>Examples</H3>
+
+<PRE CLASS="command">
+ImplicitClasses On
+ImplicitClasses Off
+</PRE>
+
+<H3>Description</H3>
+
+<P>The <CODE>ImplicitClasses</CODE> directive controls whether
+implicit classes are created based upon the available network
+printers and classes. The default setting is
+<CODE>@CUPS_IMPLICIT_CLASSES@</CODE> but is automatically turned
+<CODE>Off</CODE> if <A HREF="#Browsing"><CODE>Browsing</CODE></A> is turned
+<CODE>Off</CODE>.</P>
+
+
<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.9</SPAN><A NAME="Include">Include</A></H2>
<H3>Examples</H3>
<P>The <CODE>LogFilePerm</CODE> directive specifies the
permissions to use when writing configuration files. The default
-is 0644.</P>
+is @CUPS_LOG_FILE_PERM@.</P>
<H2 CLASS="title"><A NAME="LogLevel">LogLevel</A></H2>
<P>The <CODE>MaxCopies</CODE> directive controls the maximum
number of copies that a user can print of a job. The default is
-100 copies.</P>
+@CUPS_MAX_COPIES@ copies.</P>
<BLOCKQUOTE><B>Note:</B>
log file. If the filename is not absolute then it is assumed to
be relative to the <A
HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
-default page log file is <VAR>/var/log/cups/page_log</VAR>.</P>
+default page log file is <VAR>@CUPS_LOGDIR@/page_log</VAR>.</P>
<P>The server name can be included in the filename by using
<CODE>%s</CODE> in the name.</P>
incoming IPP requests and HTML forms. If an absolute path is not
provided then it is assumed to be relative to the <A
HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
-default request directory is <VAR>/var/spool/cups</VAR>.</P>
+default request directory is <VAR>@CUPS_REQUESTS@</VAR>.</P>
<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.7</SPAN><A NAME="Require">Require</A></H2>
<P>The <CODE>SystemGroup</CODE> directive specifies the system
administration group for <CODE>System</CODE> authentication.
Multiple groups can be listed, separated with spaces. The default
-is system-dependent and generally consists of all of the
-following groups, if present: <CODE>lpadmin</CODE>,
-<CODE>root</CODE>, <CODE>sys</CODE>, and/or
-<CODE>system</CODE>.</P>
+group list is <CODE>@CUPS_SYSTEM_GROUPS@</CODE>.</P>
<H2 CLASS="title"><A NAME="TempDir">TempDir</A></H2>
<P>The <CODE>TempDir</CODE> directive specifies an absolute path
for the directory to use for temporary files. The default
-directory is <VAR>/var/spool/cups/tmp</VAR>.</P>
+directory is <VAR>@CUPS_REQUESTS@/tmp</VAR>.</P>
<P>Temporary directories must be world-writable and should have
the "sticky" permission bit enabled so that other users cannot
set to the first discovered printer, or to the implicit class for
the same printer available from multiple servers.</P>
-<P>The default is <CODE>yes</CODE>.</P>
+<P>The default is <CODE>@CUPS_USE_NETWORK_DEFAULT@</CODE>.</P>
<H2 CLASS="title"><A NAME="User">User</A></H2>
<P>The <CODE>User</CODE> directive specifies the UNIX user that
filter and CGI programs run as. The default user is
-<CODE>lp</CODE>.</P>
+<CODE>@CUPS_USER@</CODE>.</P>
<BLOCKQUOTE><B>Note:</B>
<P>The default setting is <VAR>0</VAR>.</P>
+<H2 CLASS="title"><A NAME="DeviceURI">DeviceURI</A></H2>
+
+<H3>Examples</H3>
+
+<PRE CLASS="command">
+DeviceURI "HP.*JetDirect.*" socket://%s:9100 socket://%s:9101 socket://%s:9102
+DeviceURI "HP.*" socket://%s
+DeviceURI "Acme.*Laser.*" lpd://%s/print
+DeviceURI "Xerox.*"
+</PRE>
+
+<H3>Description</H3>
+
+<P>The <CODE>DeviceURI</CODE> directive specifies a regular expression
+(enclosed in double quotes) that is matched against the SNMP device
+description OID returned by a printer. If the description matches the
+regular expression, each device URI that follows the regular expression
+is listed by the backend, with any occurrences of <CODE>%s</CODE>
+replaced by the device's hostname or IP address. If no URIs are listed,
+the device is ignored.</P>
+
+<P>The <CODE>DeviceURI</CODE> directives are processed serially in
+the order specified in the <VAR>snmp.conf</VAR> file until a match
+is found.</P>
+
+
<H2 CLASS="title"><A NAME="HostNameLookups">HostNameLookups</A></H2>
<H3>Examples</H3>
'fold',' trim', and 'bale' attribute values extension"
specifications.</p>
-<p>CUPS also provides 13 new operations and many new attributes
+<p>CUPS also provides 15 new operations and many new attributes
to support multiple IPP printers and printer classes on a single
host.</p>
<td>0x400E</td>
<td>Authenticate a job for printing.</td>
</tr>
+<tr>
+ <td><a href='#CUPS_GET_PPD'>CUPS-Get-PPD</a></td>
+ <td>1.3</td>
+ <td>0x400F</td>
+ <td>Get a PPD file.</td>
+</tr>
</tbody>
</table></div>
</dl
+<h3 class='title'><span class='info'>CUPS 1.3</span><a name='CUPS_GET_PPD'>CUPS-Get-PPD Operation</a></h3>
+
+<p>The CUPS-Get-PPD operation (0x400F) gets a PPD file from the
+server. The PPD file can be specified using a <tt>ppd-name</tt>
+returned by <a href='#CUPS_GET_PPDS'><tt>CUPS-Get-PPDs</tt></a>
+or using the <tt>printer-uri</tt> for a queue.</p>
+
+<p>If the PPD file is found, <tt>successful-ok</tt> is returned with
+the PPD file following the response data.</p>
+
+<p>If the PPD file cannot be served by the local server because
+the <tt>printer-uri</tt> attribute points to an external printer,
+a <tt>cups-see-other</tt> status is returned with the correct
+URI to use.</p>
+
+<p>If the PPD file does not exist, <tt>client-error-not-found</tt> is
+returned.</p>
+
+<h4>CUPS-Get-PPD Request</h4>
+
+<p>The following group of attributes is supplied as part of the
+CUPS-Get-PPD request:
+
+<p>Group 1: Operation Attributes
+
+<dl>
+
+ <dt>Natural Language and Character Set:
+
+ <dd>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <dt>"printer-uri" (uri)
+ <br><i>OR</i>
+ <br>"ppd-name" (name(255)):
+
+ <dd>The client MUST supply a printer URI or PPD name.
+
+</dl>
+
+<h4>CUPS-Get-PPD Response</h4>
+
+<p>The following group of attributes is sent as part of the
+CUPS-Get-PPD Response:
+
+<p>Group 1: Operation Attributes
+
+<dl>
+
+ <dt>Status Message:
+
+ <dd>The standard response status message.
+
+ <dt>Natural Language and Character Set:
+
+ <dd>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+ <dt>"printer-uri" (uri):
+
+ <dd>The printer that provides the actual PPD file when
+ the status code is cups-see-other (0x280)
+
+</dl>
+
+<p>If the status code is <tt>successful-ok</tt>, the PPD file follows
+the end of the IPP response.</p>
+
+
<h2 class='title'><a name='ATTRIBUTES'>Attributes</a></h2>
<p>CUPS provides many extension attributes to support multiple
<p>The job-hold-until attribute specifies a hold time. In addition to the
standard IPP/1.1 keyword names, CUPS supports name values of the form
"HH:MM" and "HH:MM:SS" that specify a hold time. The hold time is in
-Greenwich Mean Time (GMT) and <i>not</i> in the local time zone. If the
+Universal Coordinated Time (UTC) and <i>not</i> in the local time zone. If the
specified time is less than the current time, the job is held until the
next day.
relative to the model directory. The forward slash (/) is used to
delineate directories.
-<h4><a name="ppd-natural-language">ppd-natural-language (naturalLanguage)</a></h4>
+<h4><a name="ppd-natural-language">ppd-natural-language (1setOf naturalLanguage)</a></h4>
<p>The ppd-natural-language attribute specifies the language encoding
of the PPD file (the LanguageVersion attribute in the PPD file). If the
language is unknown or undefined then "en" (English) is assumed.
-<h4><a name="ppd-product">ppd-product (text(127))</a></h4>
+<h4><a name="ppd-product">ppd-product (1setOf text(127))</a></h4>
+
+<p>The ppd-product attribute specifies the Product attribute values in the PPD file.
+
+<h4><a name="ppd-psversion">ppd-psversion (1setOf text(127))</a><span class="info">CUPS 1.3</span></h4>
-<p>The ppd-product attribute specifies the Product attribute value in the PPD file.
+<p>The ppd-product attribute specifies the PSVersion attribute values in the PPD file.
<h3 class='title'><a name='PRINTER_ATTRIBUTES'>Printer Attributes</a></h3>
</head>
<body>
<!--
- "$Id: spec-ppd.html 6252 2007-02-10 15:34:18Z mike $"
+ "$Id: spec-ppd.html 6457 2007-04-17 18:40:55Z mike $"
CUPS PPD extensions specification for the Common UNIX Printing System (CUPS).
<p>This attribute describes which language localizations are
included in the PPD. The "locale list" string is a space-delimited
-list of locale names ("en", "en_US", "fr_FR", etc.)</p>
+list of locale names ("en", "en_US", "fr_CA", etc.)</p>
<p>Example:</p>
<pre class='command'>
<em>*% Specify Canadian, UK, and US English, and Candian and French French</em>
-*cupsLanguages: "en_CA en_UK en_US fr_CA fr_FR"
+*cupsLanguages: "en_CA en_UK en_US fr_CA fr_CA"
</pre>
<h3>cupsManualCopies</h3>
<li>Localizations are specified using a locale prefix of
the form "ll" or "ll_CC." where "ll" is the 2-letter ISO
language code and "CC" is the 2-letter ISO country
- code</li>
+ code<ul>
+ <li>A generic language translation ("ll") SHOULD be provided with country-specific differences ("ll_CC") provided only as needed</li>
+ <li>For historical reasons, the "zh" and "zh_CN" locales map to Simplified Chinese while the "zh_TW" locale maps to Traditional Chinese</li>
+ </ul></li>
<li>Locale-specific translation strings MUST be encoded
using UTF-8.</li>
<pre class='command'>
*LanguageVersion: English
*LanguageEncoding: ISOLatin1
-*cupsLanguages: "de_DE fr_FR"
+*cupsLanguages: "de fr_CA"
*ModelName: "Foobar Laser 9999"
<em>*% Localize ModelName for French and German</em>
-*fr_FR.Translation ModelName/La Foobar Laser 9999: ""
-*de_DE.Translation ModelName/Foobar LaserDrucken 9999: ""
+*fr_CA.Translation ModelName/La Foobar Laser 9999: ""
+*de.Translation ModelName/Foobar LaserDrucken 9999: ""
*cupsIPPReason com.vendor-error/A serious error occurred: "/help/com.vendor/error.html"
<em>*% Localize printer-state-reason for French and German</em>
-*fr_FR.cupsIPPReason com.vendor-error/Une erreur sèrieuse s'est produite: "/help/com.vendor/error.html"
-*de_DE.cupsIPPReason com.vendor-error/Eine ernste Störung trat: "/help/com.vendor/error.html"
+*fr_CA.cupsIPPReason com.vendor-error/Une erreur sèrieuse s'est produite: "/help/com.vendor/error.html"
+*de.cupsIPPReason com.vendor-error/Eine ernste Störung trat: "/help/com.vendor/error.html"
...
*OrderDependency: 10 AnySetup *InputSlot
*DefaultInputSlot: Auto
<em>*% Localize InputSlot for French and German</em>
-*fr_FR.Translation InputSlot/Papier source: ""
-*de_DE.Translation InputSlot/Papiereinzug: ""
+*fr_CA.Translation InputSlot/Papier source: ""
+*de.Translation InputSlot/Papiereinzug: ""
*InputSlot Auto/Default: "<</ManualFeed false>>setpagedevice"
<em>*% Localize InputSlot=Auto for French and German</em>
-*fr_FR.InputSlot Auto/Par Defaut: ""
-*de_DE.InputSlot Auto/Standard: ""
+*fr_CA.InputSlot Auto/Par Defaut: ""
+*de.InputSlot Auto/Standard: ""
*InputSlot Manual/Manual Feed: "<</ManualFeed true>>setpagedevice"
<em>*% Localize InputSlot=Manual for French and German</em>
-*fr_FR.InputSlot Manual/Manuel mecanisme de alimentation: ""
-*de_DE.InputSlot Manual/Manueller Einzug: ""
+*fr_CA.InputSlot Manual/Manuel mecanisme de alimentation: ""
+*de.InputSlot Manual/Manueller Einzug: ""
*CloseUI: *InputSlot
</pre>
.\"
-.\" "$Id: cupstestppd.man 5099 2006-02-13 02:46:10Z mike $"
+.\" "$Id: cupstestppd.man 6509 2007-05-03 22:58:41Z mike $"
.\"
.\" cupstestppd man page for the Common UNIX Printing System (CUPS).
.\"
.\" EMail: cups-info@cups.org
.\" WWW: http://www.cups.org
.\"
-.TH cupstestppd 1 "Common UNIX Printing System" "12 February 2006" "Easy Software Products"
+.TH cupstestppd 1 "Common UNIX Printing System" "3 May 2007" "Easy Software Products"
.SH NAME
cupstestppd \- test conformance of ppd files
.SH SYNOPSIS
.B cupstestppd
-[ -q ] [-r] [ -v[v] ] filename.ppd[.gz] [ ... filenameN.ppd[.gz] ]
+[ -R
+.I rootdir
+] [ -W
+.I category
+] [ -q ] [-r] [ -v[v] ] filename.ppd[.gz] [ ... filenameN.ppd[.gz] ]
.br
.B cupstestppd
-[ -q ] [-r] [ -v[v] ] -
+[ -R
+.I rootdir
+] [ -W
+.I category
+] [ -q ] [-r] [ -v[v] ] -
.SH DESCRIPTION
\fIcupstestppd\fR tests the conformance of PPD files to the
Adobe PostScript Printer Description file format specification
.SH OPTIONS
\fIcupstestppd\fR supports the following options:
.TP 5
+-R rootdir
+.br
+Specifies an alternate root directory for the filter, pre-filter,
+and other support file checks.
+.TP 5
+-W constraints
+.br
+Report all UIConstraint errors as warnings.
+.TP 5
+-W defaults
+.br
+Except for size-related options, report all default option errors as warnings.
+.TP 5
+-W filters
+.br
+Report all filter errors as warnings.
+.TP 5
+-W translations
+.br
+Report all translation errors as warnings.
+.TP 5
+-W all
+.br
+Report all of the previous errors as warnings.
+.TP 5
+-W none
+.br
+Report all of the previous errors as errors.
+.TP 5
-q
.br
Specifies that no information should be displayed.
.br
Adobe PostScript Printer Description File Format Specification, Version 4.3.
.SH COPYRIGHT
-Copyright 1997-2006 by Easy Software Products, All Rights Reserved.
+Copyright 1997-2007 by Easy Software Products, All Rights Reserved.
.\"
-.\" End of "$Id: cupstestppd.man 5099 2006-02-13 02:46:10Z mike $".
+.\" End of "$Id: cupstestppd.man 6509 2007-05-03 22:58:41Z mike $".
.\"
#
-# "$Id: cups.list.in 6431 2007-04-02 14:31:49Z mike $"
+# "$Id: cups.list.in 6480 2007-04-27 18:53:20Z mike $"
#
# ESP Package Manager (EPM) file list for the Common UNIX Printing
# System (CUPS).
f 0644 root sys $DATADIR/model ppd/*.ppd
d 0755 root sys $DATADIR/templates -
-c 0644 root sys $DATADIR/templates templates/*.tmpl
+f 0644 root sys $DATADIR/templates templates/*.tmpl
# Japanese template files
%subpackage de
%postinstall <<EOF
rm -f /System/Library/StartupItems/PrintingServices/PrintingServices
launchctl unload /System/Library/LaunchDaemons/org.cups.cupsd.plist || exit 0
+killall cupsd
+sleep 1
launchctl load /System/Library/LaunchDaemons/org.cups.cupsd.plist
EOF
%subpackage lpd
%subpackage
#
-# End of "$Id: cups.list.in 6431 2007-04-02 14:31:49Z mike $".
+# End of "$Id: cups.list.in 6480 2007-04-27 18:53:20Z mike $".
#
landscape = gFalse;
} else {
rotate = (360 - state->getRotate()) % 360;
+
+ fprintf(stderr, "DEBUG: Page rotate=%d, width=%d, height=%d, imgWidth=%d, imgHeight=%d\n",
+ state->getRotate(), width, height, imgWidth, imgHeight);
+
+ rotate = (360 - state->getRotate()) % 360;
if (rotate == 0 || rotate == 180) {
- if ((width > height && imgWidth < imgHeight) ||
- (height > width && imgHeight < imgWidth)) {
+ if (width > height && width > imgWidth) {
rotate += 90;
landscape = gTrue;
} else {
landscape = gFalse;
}
} else { // rotate == 90 || rotate == 270
- if ((width > height && imgWidth < imgHeight) ||
- (height > width && imgHeight < imgWidth)) {
+ if (height > width && height > imgWidth) {
rotate = 270 - rotate;
landscape = gTrue;
} else {
}
}
}
+
writePSFmt("%%%%PageOrientation: %s\n",
landscape ? "Landscape" : "Portrait");
writePS("pdfStartPage\n");
/*
- * "$Id: client.c 6383 2007-03-21 20:01:20Z mike $"
+ * "$Id: client.c 6504 2007-05-02 00:14:56Z mike $"
*
* Client routines for the Common UNIX Printing System (CUPS) scheduler.
*
#ifdef DEBUG
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdWriteClient(con=%p) %d response=%p, file=%d "
+ "cupsdWriteClient(con=%p) %d response=%p(%d), file=%d "
"pipe_pid=%d state=%d",
- con, con->http.fd, con->response, con->file, con->pipe_pid,
- con->http.state);
+ con, con->http.fd, con->response, con->response->state,
+ con->file, con->pipe_pid, con->http.state);
#endif /* DEBUG */
if (con->http.state != HTTP_GET_SEND &&
con->file_ready = 0;
}
- if (con->response)
+ if (con->response && con->response->state != IPP_DATA)
{
ipp_state = ippWrite(HTTP(con), con->response);
- bytes = ipp_state != IPP_ERROR && ipp_state != IPP_DATA;
+ bytes = ipp_state != IPP_ERROR &&
+ (con->file >= 0 || ipp_state != IPP_DATA);
}
else if ((bytes = read(con->file, buf, sizeof(buf) - 1)) > 0)
{
cupsdSetString(&con->command, CUPS_JAVA);
if (options)
- cupsdSetStringf(&con->options, "%s %s", filename, options);
+ cupsdSetStringf(&con->options, " %s %s", filename, options);
else
- cupsdSetString(&con->options, filename);
+ cupsdSetStringf(&con->options, " %s", filename);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"",
cupsdSetString(&con->command, CUPS_PERL);
if (options)
- cupsdSetStringf(&con->options, "%s %s", filename, options);
+ cupsdSetStringf(&con->options, " %s %s", filename, options);
else
- cupsdSetString(&con->options, filename);
+ cupsdSetStringf(&con->options, " %s", filename);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"",
cupsdSetString(&con->command, CUPS_PHP);
if (options)
- cupsdSetStringf(&con->options, "%s %s", filename, options);
+ cupsdSetStringf(&con->options, " %s %s", filename, options);
else
- cupsdSetString(&con->options, filename);
+ cupsdSetStringf(&con->options, " %s", filename);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"",
cupsdSetString(&con->command, CUPS_PYTHON);
if (options)
- cupsdSetStringf(&con->options, "%s %s", filename, options);
+ cupsdSetStringf(&con->options, " %s %s", filename, options);
else
- cupsdSetString(&con->options, filename);
+ cupsdSetStringf(&con->options, " %s", filename);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"",
int envc; /* Number of environment variables */
char argbuf[10240], /* Argument buffer */
*argv[100], /* Argument strings */
- *envp[MAX_ENV + 18]; /* Environment variables */
- char content_length[1024], /* CONTENT_LENGTH environment variable */
+ *envp[MAX_ENV + 20]; /* Environment variables */
+ char auth_type[256], /* AUTH_TYPE environment variable */
+ content_length[1024], /* CONTENT_LENGTH environment variable */
content_type[1024], /* CONTENT_TYPE environment variable */
http_cookie[32768], /* HTTP_COOKIE environment variable */
http_referer[1024], /* HTTP_REFERER environment variable */
remote_addr[1024], /* REMOTE_ADDR environment variable */
remote_host[1024], /* REMOTE_HOST environment variable */
remote_user[1024], /* REMOTE_USER environment variable */
+ script_filename[1024], /* SCRIPT_FILENAME environment variable */
script_name[1024], /* SCRIPT_NAME environment variable */
server_name[1024], /* SERVER_NAME environment variable */
server_port[1024]; /* SERVER_PORT environment variable */
{
commptr = argbuf;
path_info[0] = '\0';
+
+ if (*commptr == ' ')
+ commptr ++;
}
cupsdLogMessage(CUPSD_LOG_INFO, "commptr=\"%s\"", commptr);
* Setup the environment variables as needed...
*/
+ if (con->username[0])
+ {
+ snprintf(auth_type, sizeof(auth_type), "AUTH_TYPE=%s",
+ httpGetField(HTTP(con), HTTP_FIELD_AUTHORIZATION));
+
+ if ((uriptr = strchr(auth_type + 10, ' ')) != NULL)
+ *uriptr = '\0';
+ }
+ else
+ auth_type[0] = '\0';
+
if (con->language)
snprintf(lang, sizeof(lang), "LANG=%s.UTF-8", con->language->language);
else
if ((uriptr = strchr(script_name, '?')) != NULL)
*uriptr = '\0';
+ snprintf(script_filename, sizeof(script_filename), "SCRIPT_FILENAME=%s%s",
+ DocumentRoot, script_name + 12);
+
sprintf(server_port, "SERVER_PORT=%d", con->serverport);
snprintf(server_name, sizeof(server_name), "SERVER_NAME=%s",
envc = cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
+ if (auth_type[0])
+ envp[envc ++] = auth_type;
+
envp[envc ++] = lang;
envp[envc ++] = "REDIRECT_STATUS=1";
+ envp[envc ++] = "GATEWAY_INTERFACE=CGI/1.1";
envp[envc ++] = server_name;
envp[envc ++] = server_port;
envp[envc ++] = remote_addr;
envp[envc ++] = remote_host;
envp[envc ++] = script_name;
+ envp[envc ++] = script_filename;
if (path_info[0])
envp[envc ++] = path_info;
/*
- * End of "$Id: client.c 6383 2007-03-21 20:01:20Z mike $".
+ * End of "$Id: client.c 6504 2007-05-02 00:14:56Z mike $".
*/
/*
- * "$Id: client.h 6383 2007-03-21 20:01:20Z mike $"
+ * "$Id: client.h 6503 2007-05-01 23:06:44Z mike $"
*
* Client definitions for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
/*
- * End of "$Id: client.h 6383 2007-03-21 20:01:20Z mike $".
+ * End of "$Id: client.h 6503 2007-05-01 23:06:44Z mike $".
*/
/*
- * "$Id: conf.c 6436 2007-04-02 23:24:02Z mike $"
+ * "$Id: conf.c 6505 2007-05-03 17:44:22Z mike $"
*
* Configuration routines for the Common UNIX Printing System (CUPS).
*
*
* Contents:
*
- * cupsdReadConfiguration() - Read the cupsd.conf file.
- * check_permissions() - Fix the mode and ownership of a file or
+ * cupsdCheckPermissions() - Fix the mode and ownership of a file or
* directory.
+ * cupsdReadConfiguration() - Read the cupsd.conf file.
* get_address() - Get an address + port number from a line.
* get_addr_and_mask() - Get an IP address and netmask.
* parse_aaa() - Parse authentication, authorization, and
#include <stdarg.h>
#include <grp.h>
#include <sys/utsname.h>
+#include <syslog.h>
#include <cups/dir.h>
-#ifdef HAVE_VSYSLOG
-# include <syslog.h>
-#endif /* HAVE_VSYSLOG */
-
/*
* Possibly missing network definitions...
/*
* Local functions...
*/
-static int check_permissions(const char *filename,
- const char *suffix, int mode,
- int user, int group, int is_dir,
- int create_dir);
static http_addrlist_t *get_address(const char *value, int defport);
static int get_addr_and_mask(const char *value, unsigned *ip,
unsigned *mask);
static int read_policy(cups_file_t *fp, char *name, int linenum);
+/*
+ * 'cupsdCheckPermissions()' - Fix the mode and ownership of a file or directory.
+ */
+
+int /* O - 0 on success, -1 on error, 1 on warning */
+cupsdCheckPermissions(
+ const char *filename, /* I - File/directory name */
+ const char *suffix, /* I - Additional file/directory name */
+ int mode, /* I - Permissions */
+ int user, /* I - Owner */
+ int group, /* I - Group */
+ int is_dir, /* I - 1 = directory, 0 = file */
+ int create_dir) /* I - 1 = create directory, -1 = create w/o logging, 0 = not */
+{
+ int dir_created = 0; /* Did we create a directory? */
+ char pathname[1024]; /* File name with prefix */
+ struct stat fileinfo; /* Stat buffer */
+
+
+ /*
+ * Prepend the given root to the filename before testing it...
+ */
+
+ if (suffix)
+ {
+ snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix);
+ filename = pathname;
+ }
+
+ /*
+ * See if we can stat the file/directory...
+ */
+
+ if (stat(filename, &fileinfo))
+ {
+ if (errno == ENOENT && create_dir)
+ {
+ if (create_dir > 0)
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"",
+ filename);
+
+ if (mkdir(filename, mode))
+ {
+ if (create_dir > 0)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to create directory \"%s\" - %s", filename,
+ strerror(errno));
+ else
+ syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename,
+ strerror(errno));
+
+ return (-1);
+ }
+
+ dir_created = 1;
+ }
+ else
+ return (create_dir ? -1 : 1);
+ }
+
+ /*
+ * Make sure it's a regular file...
+ */
+
+ if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file!", filename);
+ return (-1);
+ }
+
+ if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode))
+ {
+ if (create_dir >= 0)
+ cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory!", filename);
+ else
+ syslog(LOG_ERR, "\"%s\" is not a directory!", filename);
+
+ return (-1);
+ }
+
+ /*
+ * Fix owner, group, and mode as needed...
+ */
+
+ if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group)
+ {
+ if (create_dir >= 0)
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"",
+ filename);
+
+ if (chown(filename, user, group) && !getuid())
+ {
+ if (create_dir >= 0)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to change ownership of \"%s\" - %s", filename,
+ strerror(errno));
+ else
+ syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename,
+ strerror(errno));
+
+ return (1);
+ }
+ }
+
+ if (dir_created || (fileinfo.st_mode & 07777) != mode)
+ {
+ if (create_dir >= 0)
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"",
+ filename);
+
+ if (chmod(filename, mode))
+ {
+ if (create_dir >= 0)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to change permissions of \"%s\" - %s", filename,
+ strerror(errno));
+ else
+ syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename,
+ strerror(errno));
+
+ return (1);
+ }
+ }
+
+ /*
+ * Everything is OK...
+ */
+
+ return (0);
+}
+
+
/*
* 'cupsdReadConfiguration()' - Read the cupsd.conf file.
*/
* writable by the user and group in the cupsd.conf file...
*/
- if (check_permissions(CacheDir, NULL, 0775, RunUser, Group, 1, 1) < 0 ||
- check_permissions(StateDir, NULL, 0755, RunUser, Group, 1, 1) < 0 ||
- check_permissions(StateDir, "certs", RunUser ? 0711 : 0511, User,
- SystemGroupIDs[0], 1, 1) < 0 ||
- check_permissions(ServerRoot, NULL, 0755, RunUser, Group, 1, 0) < 0 ||
- check_permissions(ServerRoot, "ppd", 0755, RunUser, Group, 1, 1) < 0 ||
- check_permissions(ServerRoot, "ssl", 0700, RunUser, Group, 1, 0) < 0 ||
- check_permissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser,
- Group, 0, 0) < 0 ||
- check_permissions(ServerRoot, "classes.conf", 0600, RunUser, Group,
- 0, 0) < 0 ||
- check_permissions(ServerRoot, "printers.conf", 0600, RunUser, Group,
- 0, 0) < 0 ||
- check_permissions(ServerRoot, "passwd.md5", 0600, User, Group, 0, 0) < 0)
+ if (cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser,
+ Group, 1, 1) < 0 ||
+ cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser,
+ Group, 1, 1) < 0 ||
+ cupsdCheckPermissions(StateDir, NULL, 0755, RunUser,
+ Group, 1, 1) < 0 ||
+ cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User,
+ SystemGroupIDs[0], 1, 1) < 0 ||
+ cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser,
+ Group, 1, 0) < 0 ||
+ cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser,
+ Group, 1, 1) < 0 ||
+ cupsdCheckPermissions(ServerRoot, "ssl", 0700, RunUser,
+ Group, 1, 0) < 0 ||
+ cupsdCheckPermissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser,
+ Group, 0, 0) < 0 ||
+ cupsdCheckPermissions(ServerRoot, "classes.conf", 0600, RunUser,
+ Group, 0, 0) < 0 ||
+ cupsdCheckPermissions(ServerRoot, "printers.conf", 0600, RunUser,
+ Group, 0, 0) < 0 ||
+ cupsdCheckPermissions(ServerRoot, "passwd.md5", 0600, User,
+ Group, 0, 0) < 0)
return (0);
/*
}
/*
- * Make sure the request and temporary directories have the right
- * permissions...
+ * Make sure the temporary directory has the right permissions...
*/
- if (check_permissions(RequestRoot, NULL, 0710, RunUser, Group, 1, 1) < 0)
- return (0);
-
if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)) ||
access(TempDir, 0))
{
* is under the spool directory or does not exist...
*/
- if (check_permissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0)
+ if (cupsdCheckPermissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0)
return (0);
}
}
-/*
- * 'check_permissions()' - Fix the mode and ownership of a file or directory.
- */
-
-static int /* O - 0 on success, -1 on error, 1 on warning */
-check_permissions(const char *filename, /* I - File/directory name */
- const char *suffix, /* I - Additional file/directory name */
- int mode, /* I - Permissions */
- int user, /* I - Owner */
- int group, /* I - Group */
- int is_dir, /* I - 1 = directory, 0 = file */
- int create_dir)/* I - 1 = create directory, 0 = not */
-{
- int dir_created = 0; /* Did we create a directory? */
- char pathname[1024]; /* File name with prefix */
- struct stat fileinfo; /* Stat buffer */
-
-
- /*
- * Prepend the given root to the filename before testing it...
- */
-
- if (suffix)
- {
- snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix);
- filename = pathname;
- }
-
- /*
- * See if we can stat the file/directory...
- */
-
- if (stat(filename, &fileinfo))
- {
- if (errno == ENOENT && create_dir)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"",
- filename);
-
- if (mkdir(filename, mode))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create directory \"%s\" - %s", filename,
- strerror(errno));
- return (-1);
- }
-
- dir_created = 1;
- }
- else
- return (create_dir ? -1 : 1);
- }
-
- /*
- * Make sure it's a regular file...
- */
-
- if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file!", filename);
- return (-1);
- }
-
- if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory!", filename);
- return (-1);
- }
-
- /*
- * Fix owner, group, and mode as needed...
- */
-
- if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"", filename);
-
- if (chown(filename, user, group) && !getuid())
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to change ownership of \"%s\" - %s", filename,
- strerror(errno));
- return (1);
- }
- }
-
- if (dir_created || (fileinfo.st_mode & 07777) != mode)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"",
- filename);
-
- if (chmod(filename, mode))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to change permissions of \"%s\" - %s", filename,
- strerror(errno));
- return (1);
- }
- }
-
- /*
- * Everything is OK...
- */
-
- return (0);
-}
-
-
/*
* 'get_address()' - Get an address + port number from a line.
*/
/*
- * End of "$Id: conf.c 6436 2007-04-02 23:24:02Z mike $".
+ * End of "$Id: conf.c 6505 2007-05-03 17:44:22Z mike $".
*/
/*
- * "$Id: conf.h 6436 2007-04-02 23:24:02Z mike $"
+ * "$Id: conf.h 6490 2007-04-30 18:09:30Z mike $"
*
* Configuration file definitions for the Common UNIX Printing System (CUPS)
* scheduler.
* Prototypes...
*/
+extern int cupsdCheckPermissions(const char *filename,
+ const char *suffix, int mode,
+ int user, int group, int is_dir,
+ int create_dir);
extern char *cupsdGetDateTime(time_t t);
-extern int cupsdReadConfiguration(void);
#ifdef HAVE_GSSAPI
extern int cupsdLogGSSMessage(int level, int major_status,
int minor_status,
;
extern int cupsdLogPage(cupsd_job_t *job, const char *page);
extern int cupsdLogRequest(cupsd_client_t *con, http_status_t code);
+extern int cupsdReadConfiguration(void);
/*
- * End of "$Id: conf.h 6436 2007-04-02 23:24:02Z mike $".
+ * End of "$Id: conf.h 6490 2007-04-30 18:09:30Z mike $".
*/
/*
- * "$Id: cups-driverd.c 6377 2007-03-21 07:17:11Z mike $"
+ * "$Id: cups-driverd.c 6508 2007-05-03 20:07:14Z mike $"
*
* PPD/driver support for the Common UNIX Printing System (CUPS).
*
* cat_ppd() - Copy a 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_drivers() - Load driver-generated PPD files.
extern cups_encoding_t _ppdGetEncoding(const char *name);
+/*
+ * Constants...
+ */
+
+#define PPD_SYNC 0x50504433 /* Sync word for ppds.dat (PPD3) */
+#define PPD_MAX_LANG 32 /* Maximum languages */
+#define PPD_MAX_PROD 8 /* Maximum products */
+#define PPD_MAX_VERS 8 /* Maximum versions */
+
+
/*
* PPD information structures...
*/
{
time_t mtime; /* Modification time */
size_t size; /* Size in bytes */
- char name[512 - sizeof(time_t) - sizeof(size_t)],
- /* PPD name */
- natural_language[6], /* LanguageVersion */
- product[122], /* Product */
+ char name[512], /* PPD name */
+ languages[PPD_MAX_LANG][6],
+ /* LanguageVersion/cupsLanguages */
+ products[PPD_MAX_PROD][128],
+ /* Product strings */
+ psversions[PPD_MAX_VERS][32],
+ /* PSVersion strings */
make[128], /* Manufacturer */
make_and_model[128], /* NickName/ModelName */
device_id[128]; /* IEEE 1284 Device ID */
-} ppd_rec_t;
+} ppd_rec_t;
typedef struct /**** In-memory record ****/
{
* Local functions...
*/
-static ppd_info_t *add_ppd(const char *name, const char *natural_language,
+static ppd_info_t *add_ppd(const char *name, const char *language,
const char *make, const char *make_and_model,
const char *device_id, const char *product,
- time_t mtime, size_t size);
-static int cat_ppd(const char *name);
+ const char *psversion, time_t mtime,
+ size_t size);
+static int cat_ppd(const char *name, int request_id);
static int compare_names(const ppd_info_t *p0,
const ppd_info_t *p1);
static int compare_ppds(const ppd_info_t *p0,
const ppd_info_t *p1);
+static void free_array(cups_array_t *a);
static int list_ppds(int request_id, int limit, const char *opt);
static int load_drivers(void);
-static int load_ppds(const char *d, const char *p);
+static int load_ppds(const char *d, const char *p, int descend);
/*
*/
if (argc == 3 && !strcmp(argv[1], "cat"))
- return (cat_ppd(argv[2]));
+ return (cat_ppd(argv[2], 0));
+ else if (argc == 4 && !strcmp(argv[1], "get"))
+ return (cat_ppd(argv[3], atoi(argv[2])));
else if (argc == 5 && !strcmp(argv[1], "list"))
return (list_ppds(atoi(argv[2]), atoi(argv[3]), argv[4]));
else
{
fputs("Usage: cups-driverd cat ppd-name\n", stderr);
+ fputs("Usage: cups-driverd get request_id ppd-name\n", stderr);
fputs("Usage: cups-driverd list request_id limit options\n", stderr);
return (1);
}
static ppd_info_t * /* O - PPD */
add_ppd(const char *name, /* I - PPD name */
- const char *natural_language, /* I - Language(s) */
+ const char *language, /* I - LanguageVersion */
const char *make, /* I - Manufacturer */
const char *make_and_model, /* I - NickName/ModelName */
const char *device_id, /* I - 1284DeviceID */
const char *product, /* I - Product */
+ const char *psversion, /* I - PSVersion */
time_t mtime, /* I - Modification time */
size_t size) /* I - File size */
{
if (ppd == NULL)
{
- fprintf(stderr, "ERROR: [cups-driverd] Ran out of memory for %d PPD files!\n",
+ fprintf(stderr,
+ "ERROR: [cups-driverd] Ran out of memory for %d PPD files!\n",
AllocPPDs);
return (NULL);
}
ppd->record.size = size;
strlcpy(ppd->record.name, name, sizeof(ppd->record.name));
- strlcpy(ppd->record.natural_language, natural_language,
- sizeof(ppd->record.natural_language));
- strlcpy(ppd->record.product, product, sizeof(ppd->record.product));
+ strlcpy(ppd->record.languages[0], language,
+ sizeof(ppd->record.languages[0]));
+ strlcpy(ppd->record.products[0], product, sizeof(ppd->record.products[0]));
+ strlcpy(ppd->record.psversions[0], psversion,
+ sizeof(ppd->record.psversions[0]));
strlcpy(ppd->record.make, make, sizeof(ppd->record.make));
strlcpy(ppd->record.make_and_model, make_and_model,
sizeof(ppd->record.make_and_model));
* Foomatic drivers...
*/
- if ((recommended = strstr(ppd->record.make_and_model, " (recommended)")) != NULL)
+ if ((recommended = strstr(ppd->record.make_and_model,
+ " (recommended)")) != NULL)
*recommended = '\0';
/*
*/
static int /* O - Exit code */
-cat_ppd(const char *name) /* I - PPD name */
+cat_ppd(const char *name, /* I - PPD name */
+ int request_id) /* I - Request ID for response? */
{
char scheme[256], /* Scheme from PPD name */
*sptr; /* Pointer into scheme */
char line[1024]; /* Line/filename */
+ char message[2048]; /* status-message */
/*
else
scheme[0] = '\0';
+ puts("Content-Type: application/ipp\n");
+
if (scheme[0])
{
/*
fprintf(stderr, "ERROR: [cups-driverd] Unable to access \"%s\" - %s\n",
line, strerror(errno));
+
+ if (request_id > 0)
+ {
+ snprintf(message, sizeof(message), "Unable to access \"%s\" - %s",
+ line, strerror(errno));
+
+ cupsdSendIPPHeader(IPP_NOT_FOUND, 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_TEXT, "status-message", message);
+ cupsdSendIPPTrailer();
+ }
+
return (1);
}
* Yes, let it cat the PPD file...
*/
+ if (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");
+ cupsdSendIPPTrailer();
+ }
+
if (execl(line, scheme, "cat", name, (char *)NULL))
{
/*
*/
fprintf(stderr, "ERROR: [cups-driverd] Bad PPD name \"%s\"!\n", name);
+
+ if (request_id)
+ {
+ snprintf(message, sizeof(message), "Bad PPD name \"%s\"!", name);
+
+ 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_TEXT, "status-message", message);
+ cupsdSendIPPTrailer();
+ }
+
return (1);
}
* Try opening the file...
*/
- if ((datadir = getenv("CUPS_DATADIR")) == NULL)
- datadir = CUPS_DATADIR;
+#ifdef __APPLE__
+ if (!strncmp(name, "System/Library/Printers/PPDs/Contents/Resources/", 48) ||
+ !strncmp(name, "Library/Printers/PPDs/Contents/Resources/", 41))
+ {
+ /*
+ * Map ppd-name to Mac OS X standard locations...
+ */
+
+ snprintf(line, sizeof(line), "/%s", name);
+ }
+ else
+
+#elif defined(__linux)
+ if (!strncmp(name, "lsb/usr/", 8))
+ {
+ /*
+ * Map ppd-name to LSB standard /usr/share/ppd location...
+ */
+
+ snprintf(line, sizeof(line), "/usr/share/ppd/%s", name + 8);
+ }
+ else if (!strncmp(name, "lsb/opt/", 8))
+ {
+ /*
+ * Map ppd-name to LSB standard /opt/share/ppd location...
+ */
+
+ snprintf(line, sizeof(line), "/opt/share/ppd/%s", name + 8);
+ }
+ else if (!strncmp(name, "lsb/local/", 10))
+ {
+ /*
+ * Map ppd-name to LSB standard /usr/local/share/ppd location...
+ */
+
+ snprintf(line, sizeof(line), "/usr/local/share/ppd/%s", name + 10);
+ }
+ else
+
+#endif /* __APPLE__ */
+ {
+ if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+ datadir = CUPS_DATADIR;
+
+ snprintf(line, sizeof(line), "%s/model/%s", datadir, name);
+ }
- snprintf(line, sizeof(line), "%s/model/%s", datadir, name);
if ((fp = cupsFileOpen(line, "r")) == NULL)
{
fprintf(stderr, "ERROR: [cups-driverd] Unable to open \"%s\" - %s\n",
line, strerror(errno));
+
+ if (request_id)
+ {
+ snprintf(message, sizeof(message), "Unable to open \"%s\" - %s",
+ line, strerror(errno));
+
+ cupsdSendIPPHeader(IPP_NOT_FOUND, 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_TEXT, "status-message", message);
+ cupsdSendIPPTrailer();
+ }
+
return (1);
}
+ if (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");
+ cupsdSendIPPTrailer();
+ }
+
/*
* Now copy the file to stdout...
*/
p1->record.make_and_model)) != 0)
return (diff);
else
- return (strcasecmp(p0->record.natural_language,
- p1->record.natural_language));
+ return (strcasecmp(p0->record.languages[0],
+ p1->record.languages[0]));
+}
+
+
+/*
+ * 'free_array()' - Free an array of strings.
+ */
+
+static void
+free_array(cups_array_t *a) /* I - Array to free */
+{
+ char *ptr; /* Pointer to string */
+
+
+ for (ptr = (char *)cupsArrayFirst(a);
+ ptr;
+ ptr = (char *)cupsArrayNext(a))
+ free(ptr);
+
+ cupsArrayDelete(a);
}
int limit, /* I - Limit */
const char *opt) /* I - Option argument */
{
- int i; /* Looping var */
+ int i, j; /* Looping vars */
int count; /* Number of PPDs to send */
ppd_info_t *ppd; /* Current PPD file */
cups_file_t *fp; /* ppds.dat file */
int num_options; /* Number of options */
cups_option_t *options; /* Options */
const char *requested, /* requested-attributes option */
- *make; /* ppd-make option */
- int send_natural_language, /* Send ppd-natural-language attribute? */
- send_make, /* Send ppd-make attribute? */
- send_make_and_model, /* Send ppd-make-and-model attribute? */
- send_name, /* Send ppd-name attribute? */
- send_device_id, /* Send ppd-device-id attribute? */
- send_product; /* Send ppd-product attribute? */
-
-
- fprintf(stderr, "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, opt=\"%s\"\n",
- request_id, limit, opt);
+ *device_id, /* ppd-device-id option */
+ *language, /* ppd-natural-language option */
+ *make, /* ppd-make option */
+ *make_and_model, /* ppd-make-and-model option */
+ *product, /* ppd-product option */
+ *psversion; /* ppd-psversion option */
+ int mam_len, /* Length of ppd-make-and-model */
+ device_id_len, /* Length of ppd-device-id */
+ send_natural_language, /* Send ppd-natural-language? */
+ send_make, /* Send ppd-make? */
+ send_make_and_model, /* Send ppd-make-and-model? */
+ send_name, /* Send ppd-name? */
+ send_device_id, /* Send ppd-device-id? */
+ send_product, /* Send ppd-product? */
+ send_psversion, /* Send ppd-psversion? */
+ sent_header; /* Sent the IPP header? */
+
+
+ fprintf(stderr,
+ "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, "
+ "opt=\"%s\"\n", request_id, limit, opt);
/*
* See if we a PPD database file...
cups_cachedir = CUPS_CACHEDIR;
snprintf(filename, sizeof(filename), "%s/ppds.dat", cups_cachedir);
- if (!stat(filename, &fileinfo) &&
- (fileinfo.st_size % sizeof(ppd_rec_t)) == 0 &&
- (NumPPDs = fileinfo.st_size / sizeof(ppd_rec_t)) > 0)
+ if ((fp = cupsFileOpen(filename, "r")) != NULL)
{
/*
- * We have a ppds.dat file, so read it!
+ * See if we have the right sync word...
*/
- AllocPPDs = NumPPDs;
+ unsigned ppdsync; /* Sync word */
- if ((PPDs = malloc(sizeof(ppd_info_t) * NumPPDs)) == NULL)
+ if (cupsFileRead(fp, (char *)&ppdsync, sizeof(ppdsync))
+ == sizeof(ppdsync) &&
+ ppdsync == PPD_SYNC &&
+ !stat(filename, &fileinfo) &&
+ ((fileinfo.st_size - sizeof(ppdsync)) % sizeof(ppd_rec_t)) == 0 &&
+ (NumPPDs = (fileinfo.st_size - sizeof(ppdsync)) /
+ sizeof(ppd_rec_t)) > 0)
{
- fprintf(stderr,
- "ERROR: [cups-driverd] Unable to allocate memory for %d "
- "PPD files!\n", NumPPDs);
- NumPPDs = 0;
- AllocPPDs = 0;
- }
- else if ((fp = cupsFileOpen(filename, "r")) != NULL)
- {
- for (i = NumPPDs, ppd = PPDs; i > 0; i --, ppd ++)
+ /*
+ * We have a ppds.dat file, so read it!
+ */
+
+ if ((PPDs = malloc(sizeof(ppd_info_t) * NumPPDs)) == NULL)
+ fprintf(stderr,
+ "ERROR: [cups-driverd] Unable to allocate memory for %d "
+ "PPD files!\n", NumPPDs);
+ else
{
- cupsFileRead(fp, (char *)&(ppd->record), sizeof(ppd_rec_t));
- ppd->found = 0;
- }
+ AllocPPDs = NumPPDs;
- cupsFileClose(fp);
+ for (i = NumPPDs, ppd = PPDs; i > 0; i --, ppd ++)
+ {
+ cupsFileRead(fp, (char *)&(ppd->record), sizeof(ppd_rec_t));
+ ppd->found = 0;
+ }
- fprintf(stderr, "INFO: [cups-driverd] Read \"%s\", %d PPDs...\n",
- filename, NumPPDs);
- }
- else
- {
- fprintf(stderr, "ERROR: [cups-driverd] Unable to read \"%s\" - %s\n", filename,
- strerror(errno));
- NumPPDs = 0;
+ fprintf(stderr, "INFO: [cups-driverd] Read \"%s\", %d PPDs...\n",
+ filename, NumPPDs);
+ }
}
- }
+ cupsFileClose(fp);
+ }
+
/*
* Load all PPDs in the specified directory and below...
*/
cups_datadir = CUPS_DATADIR;
snprintf(model, sizeof(model), "%s/model", cups_datadir);
- load_ppds(model, "");
+ load_ppds(model, "", 1);
+
+#ifdef __APPLE__
+ /*
+ * Load PPDs from standard Mac OS X locations...
+ */
+
+ load_ppds("/Library/Printers/PPDs/Contents/Resources",
+ "Library/Printers/PPDs/Contents/Resources", 0);
+ load_ppds("/Library/Printers/PPDs/Contents/Resources/en.lproj",
+ "Library/Printers/PPDs/Contents/Resources/en.lproj", 0);
+ load_ppds("/System/Library/Printers/PPDs/Contents/Resources",
+ "System/Library/Printers/PPDs/Contents/Resources", 0);
+ load_ppds("/System/Library/Printers/PPDs/Contents/Resources/en.lproj",
+ "System/Library/Printers/PPDs/Contents/Resources/en.lproj", 0);
+
+#elif defined(__linux)
+ /*
+ * Load PPDs from LSB-defined locations...
+ */
+
+ load_ppds("/usr/local/share/ppds", "lsb/local", 1);
+ load_ppds("/usr/share/ppds", "lsb/usr", 1);
+ load_ppds("/opt/share/ppds", "lsb/opt", 1);
+#endif /* __APPLE__ */
/*
* Cull PPD files that are no longer present...
{
if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
+ unsigned ppdsync = PPD_SYNC; /* Sync word */
+
+
+ cupsFileWrite(fp, (char *)&ppdsync, sizeof(ppdsync));
+
for (i = NumPPDs, ppd = PPDs; i > 0; i --, ppd ++)
cupsFileWrite(fp, (char *)&(ppd->record), sizeof(ppd_rec_t));
* Add the raw driver...
*/
- add_ppd("raw", "en", "Raw", "Raw Queue", "", "", 0, 0);
+ add_ppd("raw", "en", "Raw", "Raw Queue", "", "", "", 0, 0);
/*
* Sort the PPDs by make and model...
* Send IPP attributes...
*/
- num_options = cupsParseOptions(opt, 0, &options);
- requested = cupsGetOption("requested-attributes", num_options, options);
- make = cupsGetOption("ppd-make", num_options, options);
+ num_options = cupsParseOptions(opt, 0, &options);
+ requested = cupsGetOption("requested-attributes", num_options, options);
+ device_id = cupsGetOption("ppd-device-id", num_options, options);
+ language = cupsGetOption("ppd-natural-language", num_options, options);
+ make = cupsGetOption("ppd-make", num_options, options);
+ make_and_model = cupsGetOption("ppd-make-and-model", num_options, options);
+ product = cupsGetOption("ppd-product", num_options, options);
+ psversion = cupsGetOption("ppd-psversion", num_options, options);
+
+ if (make_and_model)
+ mam_len = strlen(make_and_model);
+ else
+ mam_len = 0;
- fprintf(stderr, "DEBUG: [cups-driverd] requested=\"%s\"\n",
- requested ? requested : "(nil)");
+ if (device_id)
+ device_id_len = strlen(device_id);
+ else
+ device_id_len = 0;
+
+ if (requested)
+ fprintf(stderr, "DEBUG: [cups-driverd] requested-attributes=\"%s\"\n",
+ requested);
+ if (device_id)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-device-id=\"%s\"\n",
+ device_id);
+ if (language)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-natural-language=\"%s\"\n",
+ language);
+ if (make)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-make=\"%s\"\n",
+ make);
+ if (make_and_model)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-make-and-model=\"%s\"\n",
+ make_and_model);
+ if (product)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-product=\"%s\"\n",
+ product);
+ if (psversion)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-psversion=\"%s\"\n",
+ psversion);
if (!requested || strstr(requested, "all"))
{
send_natural_language = 1;
send_device_id = 1;
send_product = 1;
+ send_psversion = 1;
}
else
{
send_natural_language = strstr(requested, "ppd-natural-language") != NULL;
send_device_id = strstr(requested, "ppd-device-id") != NULL;
send_product = strstr(requested, "ppd-product") != NULL;
+ send_psversion = strstr(requested, "ppd-psversion") != NULL;
}
puts("Content-Type: application/ipp\n");
- 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");
+ sent_header = 0;
if (limit <= 0 || limit > NumPPDs)
count = NumPPDs;
count = limit;
for (i = NumPPDs, ppd = PPDs; count > 0 && i > 0; i --, ppd ++)
- if (!make || !strcasecmp(ppd->record.make, make))
+ {
+ /*
+ * Filter PPDs based on make, model, or device ID...
+ */
+
+ if (device_id && strncasecmp(ppd->record.device_id, device_id,
+ device_id_len))
+ continue; /* TODO: implement smart compare */
+
+ if (language)
{
- /*
- * Send this PPD...
- */
+ for (j = 0; j < PPD_MAX_LANG; j ++)
+ if (!ppd->record.languages[j][0] ||
+ !strcasecmp(ppd->record.languages[j], language))
+ break;
+
+ if (j >= PPD_MAX_LANG || !ppd->record.languages[j][0])
+ continue;
+ }
+
+ if (make && strcasecmp(ppd->record.make, make))
+ continue;
+
+ if (make_and_model && strncasecmp(ppd->record.make_and_model,
+ make_and_model, mam_len))
+ continue;
+
+ if (product)
+ {
+ for (j = 0; j < PPD_MAX_PROD; j ++)
+ if (!ppd->record.products[j][0] ||
+ !strcasecmp(ppd->record.products[j], product))
+ break;
- fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n",
- ppd->record.name, ppd->record.make_and_model);
+ if (j >= PPD_MAX_PROD || !ppd->record.products[j][0])
+ continue;
+ }
- count --;
+ if (psversion)
+ {
+ for (j = 0; j < PPD_MAX_VERS; j ++)
+ if (!ppd->record.psversions[j][0] ||
+ !strcasecmp(ppd->record.psversions[j], psversion))
+ break;
- cupsdSendIPPGroup(IPP_TAG_PRINTER);
+ if (j >= PPD_MAX_VERS || !ppd->record.psversions[j][0])
+ continue;
+ }
- if (send_name)
- cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name);
+ /*
+ * Send this PPD...
+ */
- if (send_natural_language)
- cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language",
- ppd->record.natural_language);
+ if (!sent_header)
+ {
+ sent_header = 1;
- if (send_make)
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make);
+ 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");
+ }
- if (send_make_and_model)
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model",
- ppd->record.make_and_model);
+ fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n",
+ ppd->record.name, ppd->record.make_and_model);
- if (send_device_id)
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id",
- ppd->record.device_id);
+ count --;
- if (send_product)
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product",
- ppd->record.product);
+ cupsdSendIPPGroup(IPP_TAG_PRINTER);
- /*
- * If we have only requested the ppd-make attribute, then skip
- * the remaining PPDs with this make...
- */
+ if (send_name)
+ cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name);
- if (requested && !strcmp(requested, "ppd-make"))
- {
- const char *this_make; /* This ppd-make */
+ if (send_natural_language)
+ {
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language",
+ ppd->record.languages[0]);
+ for (j = 1; j < PPD_MAX_LANG && ppd->record.languages[j][0]; j ++)
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "", ppd->record.languages[j]);
+ }
- for (this_make = ppd->record.make, i --, ppd ++; i > 0; i --, ppd ++)
- if (strcasecmp(this_make, ppd->record.make))
- break;
+ if (send_make)
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make);
- i ++;
- ppd --;
- }
+ if (send_make_and_model)
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model",
+ ppd->record.make_and_model);
+
+ if (send_device_id)
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id",
+ ppd->record.device_id);
+
+ if (send_product)
+ {
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product",
+ ppd->record.products[0]);
+
+ for (j = 1; j < PPD_MAX_PROD && ppd->record.products[j][0]; j ++)
+ cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.products[j]);
+ }
+
+ if (send_psversion)
+ {
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-psversion",
+ ppd->record.psversions[0]);
+
+ for (j = 1; j < PPD_MAX_VERS && ppd->record.psversions[j][0]; j ++)
+ cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.psversions[j]);
+ }
+
+ /*
+ * If we have only requested the ppd-make attribute, then skip
+ * the remaining PPDs with this make...
+ */
+
+ if (requested && !strcmp(requested, "ppd-make"))
+ {
+ const char *this_make; /* This ppd-make */
+
+
+ for (this_make = ppd->record.make, i --, ppd ++; i > 0; i --, ppd ++)
+ if (strcasecmp(this_make, ppd->record.make))
+ break;
+
+ i ++;
+ ppd --;
}
+ }
+
+ if (!sent_header)
+ {
+ cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
+ cupsdSendIPPGroup(IPP_TAG_OPERATION);
+ cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");
+ }
cupsdSendIPPTrailer();
static int /* O - 1 on success, 0 on failure */
load_ppds(const char *d, /* I - Actual directory */
- const char *p) /* I - Virtual path in name */
+ const char *p, /* I - Virtual path in name */
+ int descend) /* I - Descend into directories? */
{
int i; /* Looping var */
cups_file_t *fp; /* Pointer to file */
model_name[256], /* ModelName */
nick_name[256], /* NickName */
device_id[256], /* 1284DeviceID */
- product[256]; /* Product */
- cups_array_t *products; /* Array of product strings */
+ product[256], /* Product */
+ psversion[256]; /* PSVersion */
+ cups_array_t *products, /* Product array */
+ *psversions, /* PSVersion array */
+ *cups_languages; /* cupsLanguages array */
ppd_info_t *ppd, /* New PPD file */
key; /* Search key */
int new_ppd; /* Is this a new PPD? */
*language; /* Language code */
} languages[] =
{
- { "chinese", "cn" },
+ { "chinese", "zh" },
{ "danish", "da" },
{ "dutch", "nl" },
{ "english", "en" },
if ((dir = cupsDirOpen(d)) == NULL)
{
- fprintf(stderr, "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n",
+ fprintf(stderr,
+ "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n",
d, strerror(errno));
return (0);
}
* Do subdirectory...
*/
- if (!load_ppds(filename, name))
- {
- cupsDirClose(dir);
- return (1);
- }
+ if (descend)
+ if (!load_ppds(filename, name, 1))
+ {
+ cupsDirClose(dir);
+ return (1);
+ }
continue;
}
* Now read until we get the NickName field...
*/
- products = cupsArrayNew(NULL, NULL);
+ cups_languages = cupsArrayNew(NULL, NULL);
+ products = cupsArrayNew(NULL, NULL);
+ psversions = cupsArrayNew(NULL, NULL);
model_name[0] = '\0';
nick_name[0] = '\0';
sscanf(line, "%*[^\"]\"(%255[^)]", product);
cupsArrayAdd(products, strdup(product));
}
+ else if (!strncasecmp(line, "*PSVersion:", 11))
+ {
+ sscanf(line, "%*[^\"]\"%255[^\"]", psversion);
+ cupsArrayAdd(psversions, strdup(psversion));
+ }
+ else if (!strncasecmp(line, "*cupsLanguages:", 15))
+ {
+ char *start; /* Start of language */
+
+
+ for (start = line + 15; *start && isspace(*start & 255); start ++);
+
+ if (*start++ == '\"')
+ {
+ while (*start)
+ {
+ for (ptr = start + 1;
+ *ptr && *ptr != '\"' && !isspace(*ptr & 255);
+ ptr ++);
+
+ if (*ptr)
+ {
+ *ptr++ = '\0';
+
+ while (isspace(*ptr & 255))
+ *ptr++ = '\0';
+ }
+
+ cupsArrayAdd(cups_languages, strdup(start));
+ start = ptr;
+ }
+ }
+ }
else if (!strncmp(line, "*OpenUI", 7))
{
/*
* before the first OpenUI...
*/
- if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0)
+ if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0 &&
+ cupsArrayCount(psversions) > 0)
break;
}
}
while (isspace(make_model[0] & 255))
_cups_strcpy(make_model, make_model + 1);
- if (!make_model[0] || cupsArrayCount(products) == 0)
+ if (!make_model[0] || cupsArrayCount(products) == 0 ||
+ cupsArrayCount(psversions) == 0)
{
/*
* We don't have all the info needed, so skip this file...
if (cupsArrayCount(products) == 0)
fprintf(stderr, "WARNING: Missing Product in %s!\n", filename);
- for (ptr = (char *)cupsArrayFirst(products);
- ptr;
- ptr = (char *)cupsArrayNext(products))
- free(ptr);
+ if (cupsArrayCount(psversions) == 0)
+ fprintf(stderr, "WARNING: Missing PSVersion in %s!\n", filename);
- cupsArrayDelete(products);
+ free_array(products);
+ free_array(psversions);
+ free_array(cups_languages);
continue;
}
fprintf(stderr, "DEBUG: [cups-driverd] Adding ppd \"%s\"...\n", name);
- /* TODO: Support multiple Products... */
- if (!add_ppd(name, lang_version, manufacturer, make_model, device_id,
- (char *)cupsArrayFirst(products),
- dent->fileinfo.st_mtime, dent->fileinfo.st_size))
+ ppd = add_ppd(name, lang_version, manufacturer, make_model, device_id,
+ (char *)cupsArrayFirst(products),
+ (char *)cupsArrayFirst(psversions),
+ dent->fileinfo.st_mtime, dent->fileinfo.st_size);
+
+ if (!ppd)
{
cupsDirClose(dir);
return (0);
strlcpy(ppd->record.make, manufacturer, sizeof(ppd->record.make));
strlcpy(ppd->record.make_and_model, make_model,
sizeof(ppd->record.make_and_model));
- strlcpy(ppd->record.natural_language, lang_version,
- sizeof(ppd->record.natural_language));
- strlcpy(ppd->record.product, (char *)cupsArrayFirst(products),
- sizeof(ppd->record.product));
+ strlcpy(ppd->record.languages[0], lang_version,
+ sizeof(ppd->record.languages[0]));
+ strlcpy(ppd->record.products[0], (char *)cupsArrayFirst(products),
+ sizeof(ppd->record.products[0]));
+ strlcpy(ppd->record.psversions[0], (char *)cupsArrayFirst(psversions),
+ sizeof(ppd->record.psversions[0]));
strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id));
}
/*
- * Free products...
+ * Add remaining products, versions, and languages...
*/
- for (ptr = (char *)cupsArrayFirst(products);
- ptr;
- ptr = (char *)cupsArrayNext(products))
- free(ptr);
+ for (i = 1;
+ i < PPD_MAX_PROD && (ptr = (char *)cupsArrayNext(products)) != NULL;
+ i ++)
+ strlcpy(ppd->record.products[i], ptr,
+ sizeof(ppd->record.products[0]));
+
+ for (i = 1;
+ i < PPD_MAX_VERS && (ptr = (char *)cupsArrayNext(psversions)) != NULL;
+ i ++)
+ strlcpy(ppd->record.psversions[i], ptr,
+ sizeof(ppd->record.psversions[0]));
- cupsArrayDelete(products);
+ for (i = 1, ptr = (char *)cupsArrayFirst(cups_languages);
+ i < PPD_MAX_LANG && ptr;
+ i ++, ptr = (char *)cupsArrayNext(cups_languages))
+ strlcpy(ppd->record.languages[i], ptr,
+ sizeof(ppd->record.languages[0]));
+
+ /*
+ * Free products, versions, and languages...
+ */
+
+ free_array(cups_languages);
+ free_array(products);
+ free_array(psversions);
ChangedPPD = 1;
}
static int /* O - 1 on success, 0 on failure */
load_drivers(void)
{
- const char *server_bin; /* CUPS_SERVERBIN environment variable */
+ int i; /* Looping var */
+ char *start, /* Start of value */
+ *ptr; /* Pointer into string */
+ const char *server_bin; /* CUPS_SERVERBIN env variable */
char drivers[1024]; /* Location of driver programs */
FILE *fp; /* Pipe to driver program */
cups_dir_t *dir; /* Directory pointer */
char filename[1024], /* Name of driver */
line[2048], /* Line from driver */
name[512], /* ppd-name */
- natural_language[128], /* ppd-natural-language */
make[128], /* ppd-make */
- make_and_model[256], /* ppd-make-and-model */
- device_id[256], /* ppd-device-id */
- product[256]; /* ppd-product */
+ make_and_model[128], /* ppd-make-and-model */
+ device_id[128], /* ppd-device-id */
+ languages[128], /* ppd-natural-language */
+ product[128], /* ppd-product */
+ psversion[128]; /* ppd-psversion */
+ ppd_info_t *ppd; /* Newly added PPD */
/*
* Each line is of the form:
*
* "ppd-name" ppd-natural-language "ppd-make" "ppd-make-and-model" \
- * "ppd-device-id" "ppd-product"
+ * "ppd-device-id" "ppd-product" "ppd-psversion"
*/
device_id[0] = '\0';
product[0] = '\0';
+ psversion[0] = '\0';
if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\""
- "%*[ \t]\"%256[^\"]\"%*[ \t]\"%256[^\"]\""
- "%*[ \t]\"%256[^\"]\"",
- name, natural_language, make, make_and_model,
- device_id, product) < 4)
+ "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\""
+ "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"",
+ name, languages, make, make_and_model,
+ device_id, product, psversion) < 4)
{
/*
* Bad format; strip trailing newline and write an error message.
* Add the device to the array of available devices...
*/
- if (!add_ppd(name, natural_language, make, make_and_model, device_id,
- product, 0, 0))
+ if ((start = strchr(languages, ',')) != NULL)
+ *start++ = '\0';
+
+ ppd = add_ppd(name, languages, make, make_and_model, device_id,
+ product, psversion, 0, 0);
+
+ if (!ppd)
{
cupsDirClose(dir);
return (0);
}
+ if (start && *start)
+ {
+ for (i = 1; i < PPD_MAX_LANG && *start; i ++)
+ {
+ if ((ptr = strchr(start, ',')) != NULL)
+ *ptr++ = '\0';
+ else
+ ptr = start + strlen(start);
+
+ strlcpy(ppd->record.languages[i], start,
+ sizeof(ppd->record.languages[0]));
+
+ start = ptr;
+ }
+ }
+
fprintf(stderr, "DEBUG: [cups-driverd] Added dynamic PPD \"%s\"...\n",
name);
}
/*
- * End of "$Id: cups-driverd.c 6377 2007-03-21 07:17:11Z mike $".
+ * End of "$Id: cups-driverd.c 6508 2007-05-03 20:07:14Z mike $".
*/
/*
- * "$Id: dirsvc.c 6376 2007-03-21 06:39:10Z mike $"
+ * "$Id: dirsvc.c 6483 2007-04-30 17:16:16Z mike $"
*
* Directory services routines for the Common UNIX Printing System (CUPS).
*
{
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
iface->hostname, iface->port,
- (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s%s" :
+ (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" :
"/printers/%s",
p->name);
snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\" %s\n",
/*
- * End of "$Id: dirsvc.c 6376 2007-03-21 06:39:10Z mike $".
+ * End of "$Id: dirsvc.c 6483 2007-04-30 17:16:16Z mike $".
*/
/*
- * "$Id: ipp.c 6433 2007-04-02 21:50:50Z mike $"
+ * "$Id: ipp.c 6508 2007-05-03 20:07:14Z mike $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
* get_job_attrs() - Get job attributes.
* get_jobs() - Get a list of jobs for the specified printer.
* get_notifications() - Get events for a subscription.
+ * get_ppd() - Get a named PPD from the local system.
* get_ppds() - Get the list of PPD files on the local
* system.
* get_printer_attrs() - Get printer attributes.
* start_printer() - Start a printer.
* stop_printer() - Stop a printer.
* url_encode_attr() - URL-encode a string attribute.
+ * url_encode_string() - URL-encode a string.
* user_allowed() - See if a user is allowed to print to a queue.
* validate_job() - Validate printer options and destination.
* validate_name() - Make sure the printer name only contains
static void get_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
static void get_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
static void get_notifications(cupsd_client_t *con);
+static void get_ppd(cupsd_client_t *con, ipp_attribute_t *uri);
static void get_ppds(cupsd_client_t *con);
static void get_printers(cupsd_client_t *con, int type);
static void get_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
static void stop_printer(cupsd_client_t *con, ipp_attribute_t *uri);
static void url_encode_attr(ipp_attribute_t *attr, char *buffer,
int bufsize);
+static char *url_encode_string(const char *s, char *buffer, int bufsize);
static int user_allowed(cupsd_printer_t *p, const char *username);
static void validate_job(cupsd_client_t *con, ipp_attribute_t *uri);
static int validate_name(const char *name);
else if ((attr = ippFindAttribute(con->request, "job-uri",
IPP_TAG_URI)) != NULL)
uri = attr;
+ else if (con->request->request.op.operation_id == CUPS_GET_PPD)
+ uri = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME);
else
uri = NULL;
if (!uri)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing printer-uri or job-uri attribute!");
+ "Missing printer-uri, job-uri, or ppd-name "
+ "attribute!");
cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL,
- "%04X %s Missing printer-uri or job-uri attribute",
- IPP_BAD_REQUEST, con->http.hostname);
+ "%04X %s Missing printer-uri, job-uri, or ppd-name "
+ "attribute", IPP_BAD_REQUEST, con->http.hostname);
}
cupsdLogMessage(CUPSD_LOG_DEBUG, "Request attributes follow...");
get_devices(con);
break;
+ case CUPS_GET_PPD :
+ get_ppd(con, uri);
+ break;
+
case CUPS_GET_PPDS :
get_ppds(con);
break;
length = ippLength(con->response);
+ if (con->file >= 0 && !con->pipe_pid)
+ {
+ struct stat fileinfo; /* File information */
+
+
+ if (!fstat(con->file, &fileinfo))
+ length += fileinfo.st_size;
+ }
+
if (httpPrintf(HTTP(con), "Content-Length: " CUPS_LLFMT "\r\n\r\n",
CUPS_LLCAST length) < 0)
return (0);
con->http.data_encoding = HTTP_ENCODE_LENGTH;
con->http.data_remaining = length;
+
+ if (con->http.data_remaining <= INT_MAX)
+ con->http._data_remaining = con->http.data_remaining;
+ else
+ con->http._data_remaining = INT_MAX;
}
cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient,
}
+/*
+ * 'get_ppd()' - Get a named PPD from the local system.
+ */
+
+static void
+get_ppd(cupsd_client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI or PPD name */
+{
+ http_status_t status; /* Policy status */
+ cupsd_printer_t *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", con,
+ con->http.fd, uri, uri->name, uri->values[0].string.text);
+
+ if (!strcmp(uri->name, "ppd-name"))
+ {
+ /*
+ * Return a PPD file from cups-driverd...
+ */
+
+ char command[1024], /* cups-driverd command */
+ options[1024], /* Options to pass to command */
+ ppd_name[1024]; /* ppd-name */
+
+
+ /*
+ * Check policy...
+ */
+
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
+ /*
+ * Run cups-driverd command with the given options...
+ */
+
+ snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
+ url_encode_string(uri->values[0].string.text, ppd_name, sizeof(ppd_name));
+ snprintf(options, sizeof(options), "get+%d+%s",
+ con->request->request.op.request_id, ppd_name);
+
+ if (cupsdSendCommand(con, command, options, 0))
+ {
+ /*
+ * Command started successfully, don't send an IPP response here...
+ */
+
+ ippDelete(con->response);
+ con->response = NULL;
+ }
+ else
+ {
+ /*
+ * Command failed, return "internal error" so the user knows something
+ * went wrong...
+ */
+
+ send_ipp_status(con, IPP_INTERNAL_ERROR,
+ _("cups-driverd failed to execute."));
+ }
+ }
+ else if (!strcmp(uri->name, "printer-uri") &&
+ cupsdValidateDest(uri->values[0].string.text, &dtype, &dest))
+ {
+ int i; /* Looping var */
+ char filename[1024]; /* PPD filename */
+
+
+ /*
+ * Check policy...
+ */
+
+ if ((status = cupsdCheckPolicy(dest->op_policy_ptr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
+ /*
+ * See if we need the PPD for a class or remote printer...
+ */
+
+ if (dtype & CUPS_PRINTER_REMOTE)
+ {
+ send_ipp_status(con, CUPS_SEE_OTHER, NULL);
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, dest->uri);
+ return;
+ }
+ else if (dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ {
+ for (i = 0; i < dest->num_printers; i ++)
+ if (!(dest->printers[i]->type &
+ (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE)))
+ break;
+
+ if (i < dest->num_printers)
+ dest = dest->printers[i];
+ else
+ {
+ send_ipp_status(con, CUPS_SEE_OTHER, NULL);
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, dest->printers[0]->uri);
+ return;
+ }
+ }
+
+ /*
+ * Found the printer with the PPD file, now see if there is one...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
+ dest->name);
+
+ if ((con->file = open(filename, O_RDONLY)) < 0)
+ {
+ send_ipp_status(con, IPP_NOT_FOUND,
+ _("The PPD file \"%s\" could not be opened: %s"),
+ uri->values[i].string.text, strerror(errno));
+ return;
+ }
+
+ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
+
+ con->pipe_pid = 0;
+
+ send_ipp_status(con, IPP_OK, NULL);
+ }
+ else
+ send_ipp_status(con, IPP_NOT_FOUND,
+ _("The PPD file \"%s\" could not be found."),
+ uri->values[0].string.text);
+}
+
+
/*
* 'get_ppds()' - Get the list of PPD files on the local system.
*/
{
http_status_t status; /* Policy status */
ipp_attribute_t *limit, /* Limit attribute */
+ *device, /* ppd-device-id attribute */
+ *language, /* ppd-natural-language attribute */
*make, /* ppd-make attribute */
+ *model, /* ppd-make-and-model attribute */
+ *product, /* ppd-product attribute */
+ *psversion, /* ppd-psverion attribute */
*requested; /* requested-attributes attribute */
- char command[1024], /* cups-deviced command */
+ char command[1024], /* cups-driverd command */
options[1024], /* Options to pass to command */
- requested_str[256],
+ device_str[256],/* Escaped ppd-device-id string */
+ language_str[256],
+ /* Escaped ppd-natural-language string */
+ make_str[256], /* Escaped ppd-make string */
+ model_str[256], /* Escaped ppd-make-and-model string */
+ product_str[256],
+ /* Escaped ppd-product string */
+ psversion_str[256],
+ /* Escaped ppd-psversion string */
+ requested_str[256];
/* String for requested attributes */
- make_str[256]; /* Escaped ppd-make string */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->http.fd);
*/
limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER);
+ device = ippFindAttribute(con->request, "ppd-device-id", IPP_TAG_TEXT);
+ language = ippFindAttribute(con->request, "ppd-natural-language",
+ IPP_TAG_LANGUAGE);
make = ippFindAttribute(con->request, "ppd-make", IPP_TAG_TEXT);
+ model = ippFindAttribute(con->request, "ppd-make-and-model",
+ IPP_TAG_TEXT);
+ product = ippFindAttribute(con->request, "ppd-product", IPP_TAG_TEXT);
+ psversion = ippFindAttribute(con->request, "ppd-psversion", IPP_TAG_TEXT);
requested = ippFindAttribute(con->request, "requested-attributes",
IPP_TAG_KEYWORD);
else
strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));
+ if (device)
+ url_encode_attr(device, device_str, sizeof(device_str));
+ else
+ device_str[0] = '\0';
+
+ if (language)
+ url_encode_attr(language, language_str, sizeof(language_str));
+ else
+ language_str[0] = '\0';
+
if (make)
url_encode_attr(make, make_str, sizeof(make_str));
else
make_str[0] = '\0';
+ if (model)
+ url_encode_attr(model, model_str, sizeof(model_str));
+ else
+ model_str[0] = '\0';
+
+ if (product)
+ url_encode_attr(product, product_str, sizeof(product_str));
+ else
+ product_str[0] = '\0';
+
+ if (psversion)
+ url_encode_attr(psversion, psversion_str, sizeof(psversion_str));
+ else
+ psversion_str[0] = '\0';
+
snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
- snprintf(options, sizeof(options), "list+%d+%d+%s%s%s",
+ snprintf(options, sizeof(options), "list+%d+%d+%s%s%s%s%s%s%s%s%s%s%s%s%s",
con->request->request.op.request_id,
limit ? limit->values[0].integer : 0,
- requested_str, make ? "%20" : "", make_str);
+ requested_str,
+ device ? "%20" : "", device_str,
+ language ? "%20" : "", language_str,
+ make ? "%20" : "", make_str,
+ model ? "%20" : "", model_str,
+ product ? "%20" : "", product_str,
+ psversion ? "%20" : "", psversion_str);
if (cupsdSendCommand(con, command, options, 0))
{
cupsdSaveAllSubscriptions();
con->response->request.status.status_code = IPP_OK;
+
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-lease-duration", sub->lease);
}
{
int i; /* Looping var */
char *bufptr, /* Pointer into buffer */
- *bufend, /* End of buffer */
- *valptr; /* Pointer into value */
+ *bufend; /* End of buffer */
strlcpy(buffer, attr->name, bufsize);
*bufptr++ = '\'';
- for (valptr = attr->values[i].string.text;
- *valptr && bufptr < bufend;
- valptr ++)
- if (*valptr == ' ')
- {
- if (bufptr >= (bufend - 2))
- break;
-
- *bufptr++ = '%';
- *bufptr++ = '2';
- *bufptr++ = '0';
- }
- else if (*valptr == '\'' || *valptr == '\\')
- {
- *bufptr++ = '\\';
- *bufptr++ = *valptr;
- }
- else
- *bufptr++ = *valptr;
+ bufptr = url_encode_string(attr->values[i].string.text,
+ bufptr, bufend - bufptr + 1);
if (bufptr >= bufend)
break;
}
+/*
+ * 'url_encode_string()' - URL-encode a string.
+ */
+
+static char * /* O - End of string */
+url_encode_string(const char *s, /* I - String */
+ char *buffer, /* I - String buffer */
+ int bufsize) /* I - Size of buffer */
+{
+ char *bufptr, /* Pointer into buffer */
+ *bufend; /* End of buffer */
+ static const char *hex = "0123456789ABCDEF";
+ /* Hex digits */
+
+
+ bufptr = buffer;
+ bufend = buffer + bufsize - 1;
+
+ while (*s && bufptr < bufend)
+ {
+ if (*s == ' ' || *s == '%')
+ {
+ if (bufptr >= (bufend - 2))
+ break;
+
+ *bufptr++ = '%';
+ *bufptr++ = hex[(*s >> 4) & 15];
+ *bufptr++ = hex[*s & 15];
+
+ s ++;
+ }
+ else if (*s == '\'' || *s == '\\')
+ {
+ if (bufptr >= (bufend - 1))
+ break;
+
+ *bufptr++ = '\\';
+ *bufptr++ = *s++;
+ }
+ else
+ *bufptr++ = *s++;
+ }
+
+ *bufptr = '\0';
+
+ return (bufptr);
+}
+
+
/*
* 'user_allowed()' - See if a user is allowed to print to a queue.
*/
/*
- * End of "$Id: ipp.c 6433 2007-04-02 21:50:50Z mike $".
+ * End of "$Id: ipp.c 6508 2007-05-03 20:07:14Z mike $".
*/
/*
- * "$Id: job.c 6433 2007-04-02 21:50:50Z mike $"
+ * "$Id: job.c 6462 2007-04-23 19:25:13Z mike $"
*
* Job management routines for the Common UNIX Printing System (CUPS).
*
if ((!strcmp(attr->name, "page-label") ||
!strcmp(attr->name, "page-border") ||
!strncmp(attr->name, "number-up", 9) ||
+ !strcmp(attr->name, "page-ranges") ||
!strcmp(attr->name, "page-set") ||
!strcasecmp(attr->name, "AP_FIRSTPAGE_InputSlot") ||
!strcasecmp(attr->name, "AP_FIRSTPAGE_ManualFeed")) &&
cupsdClosePipe(job->status_pipes);
cupsdStatBufDelete(job->status_buffer);
+ job->status_buffer = NULL;
+
cupsArrayDelete(filters);
if (printer->remote && job->num_files > 1)
/*
- * End of "$Id: job.c 6433 2007-04-02 21:50:50Z mike $".
+ * End of "$Id: job.c 6462 2007-04-23 19:25:13Z mike $".
*/
/*
- * "$Id: log.c 6328 2007-03-12 14:45:42Z mike $"
+ * "$Id: log.c 6492 2007-04-30 19:31:36Z mike $"
*
* Log file routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
if ((*lf = cupsFileOpen(filename, "a")) == NULL)
{
- syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename,
- strerror(errno));
+ /*
+ * If the file is in CUPS_LOGDIR then try to create a missing directory...
+ */
- return (0);
+ if (!strncmp(filename, CUPS_LOGDIR, strlen(CUPS_LOGDIR)))
+ {
+ cupsdCheckPermissions(CUPS_LOGDIR, NULL, 0755, RunUser, Group, 1, -1);
+
+ *lf = cupsFileOpen(filename, "a");
+ }
+
+ if (*lf == NULL)
+ {
+ syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename,
+ strerror(errno));
+ return (0);
+ }
}
if (strncmp(filename, "/dev/", 5))
/*
- * End of "$Id: log.c 6328 2007-03-12 14:45:42Z mike $".
+ * End of "$Id: log.c 6492 2007-04-30 19:31:36Z mike $".
*/
/*
- * "$Id: main.c 6365 2007-03-19 20:56:57Z mike $"
+ * "$Id: main.c 6493 2007-04-30 19:33:31Z mike $"
*
* Scheduler main loop for the Common UNIX Printing System (CUPS).
*
* launchd_checkin() - Check-in with launchd and collect the
* listening fds.
* launchd_checkout() - Check-out with launchd.
- * launchd_create_dict() - Create a dictionary representing the launchd
- * config file org.cups.cupsd.plist.
- * launchd_sync_conf() - Re-write the launchd config file
- * org.cups.cupsd.plist based on cupsd.conf.
* parent_handler() - Catch USR1/CHLD signals...
* process_children() - Process all dead children...
* sigchld_handler() - Handle 'child' signals from old processes.
#ifdef HAVE_LAUNCHD
static void launchd_checkin(void);
static void launchd_checkout(void);
-static CFDictionaryRef launchd_create_dict(void);
-static int launchd_sync_conf(void);
#endif /* HAVE_LAUNCHD */
static void parent_handler(int sig);
static void process_children(void);
static int stop_scheduler = 0;
/* Should the scheduler stop? */
-#ifdef HAVE_LAUNCHD
-static CFURLRef launchd_conf_url = NULL;
- /* org.cups.cupsd.plist url */
-static CFDictionaryRef launchd_conf_dict = NULL;
- /* org.cups.cupsd.plist dict */
-#endif /* HAVE_LAUNCHD */
-
#if defined(__APPLE__) && defined(HAVE_DLFCN_H)
static const char *PSQLibPath = "/usr/lib/libPrintServiceQuota.dylib";
static const char *PSQLibFuncName = "PSQUpdateQuota";
getrlimit(RLIMIT_NOFILE, &limit);
- for (i = 0; i < limit.rlim_cur; i ++)
+ for (i = 0; i < limit.rlim_cur && i < 1024; i ++)
close(i);
#endif /* DEBUG */
}
if (Launchd)
{
/*
- * If we were started by launchd, make sure the cupsd plist file contains
- * the same listeners as cupsd.conf.
- */
-
- launchd_sync_conf();
-
- /*
- * Then get the file descriptors from launchd...
+ * If we were started by launchd get the listen sockets file descriptors...
*/
launchd_checkin();
#if HAVE_LAUNCHD
if (Launchd)
{
- launchd_sync_conf();
+ /*
+ * If we were started by launchd get the listen sockets file descriptors...
+ */
+
launchd_checkin();
}
#endif /* HAVE_LAUNCHD */
#ifdef HAVE_LAUNCHD
/*
- * Update the launchd config file as needed...
+ * Update the launchd KeepAlive file as needed...
*/
if (Launchd)
- {
launchd_checkout();
- launchd_sync_conf();
+#endif /* HAVE_LAUNCHD */
- if (launchd_conf_url)
- CFRelease(launchd_conf_url);
+#ifdef __APPLE__
+#ifdef HAVE_DLFCN_H
+ /*
+ * Unload Print Service quota enforcement library (X Server only)
+ */
- if (launchd_conf_dict)
- CFRelease(launchd_conf_dict);
+ PSQUpdateQuotaProc = NULL;
+ if (PSQLibRef)
+ {
+ dlclose(PSQLibRef);
+ PSQLibRef = NULL;
}
-#endif /* HAVE_LAUNCHD */
+#endif /* HAVE_DLFCN_H */
+#endif /* __APPLE__ */
#ifdef __sgi
/*
}
}
- /*
- * Collect the browse socket (if there is one)...
- */
-
- if ((ld_array = launch_data_dict_lookup(ld_sockets, "BrowseSockets")))
- {
- if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY)
- {
- if ((tmp = launch_data_array_get_index(ld_array, 0)))
- {
- if (launch_data_get_type(tmp) == LAUNCH_DATA_FD)
- {
- if (BrowseSocket != -1)
- close(BrowseSocket);
-
- BrowseSocket = launch_data_get_fd(tmp);
- }
- else
- cupsdLogMessage(CUPSD_LOG_WARN,
- "launchd_checkin: BrowseSocket not a fd!");
- }
- else
- cupsdLogMessage(CUPSD_LOG_WARN,
- "launchd_checkin: BrowseSockets is an empty array!");
- }
- else
- cupsdLogMessage(CUPSD_LOG_WARN,
- "launchd_checkin: BrowseSockets is not an array!");
- }
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: No BrowseSockets");
-
launch_data_free(ld_msg);
launch_data_free(ld_resp);
}
}
}
-
-/*
- * 'launchd_create_dict()' - Create a dictionary representing the launchd
- * config file org.cups.cupsd.plist.
- */
-
-static CFDictionaryRef /* O - CFDictionary */
-launchd_create_dict(void)
-{
- int portnum; /* Port number */
- bool runatload; /* Run at load? */
- CFMutableDictionaryRef cupsd_dict, /* org.cups.cupsd.plist dictionary */
- keepalive, /* KeepAlive dictionary */
- pathstate, /* PathState dictionary */
- sockets, /* Sockets dictionary */
- listener; /* Listener dictionary */
- CFMutableArrayRef array; /* Array */
- CFNumberRef socket_mode; /* Domain socket mode bits */
- CFStringRef socket_path; /* Domain socket path */
- CFTypeRef value; /* CF values */
- cupsd_listener_t *lis; /* Current listening socket */
- struct servent *service; /* Services data base entry */
- char temp[1024]; /* Temporary buffer for value */
-
-
- if ((cupsd_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) == NULL)
- return (NULL);
-
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_LABEL),
- CFSTR("org.cups.cupsd"));
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_ONDEMAND),
- kCFBooleanTrue);
-
- /*
- * Use run-at-load and/or KeepAlive if there are active jobs, polling or
- * shared printers to advertise...
- */
-
- if ((keepalive = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- if ((pathstate = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- CFDictionaryAddValue(pathstate, CFSTR(CUPS_KEEPALIVE), kCFBooleanTrue);
- CFDictionaryAddValue(keepalive, CFSTR(LAUNCH_JOBKEY_PATHSTATE),
- pathstate);
- }
-
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_KEEPALIVE),
- keepalive);
- }
-
- runatload = (cupsArrayCount(ActiveJobs) || NumPolled ||
- (Browsing && BrowseLocalProtocols &&
- NumBrowsers && cupsArrayCount(Printers))) ? true : false;
-
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_RUNATLOAD),
- runatload ? kCFBooleanTrue : kCFBooleanFalse);
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SERVICEIPC),
- kCFBooleanTrue);
-
- if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 2,
- &kCFTypeArrayCallBacks)) != NULL)
- {
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_PROGRAMARGUMENTS),
- array);
- CFArrayAppendValue(array, CFSTR("/usr/sbin/cupsd"));
- CFArrayAppendValue(array, CFSTR("-l"));
- CFRelease(array);
- }
-
- /*
- * Add a sockets dictionary...
- */
-
- if ((sockets = (CFMutableDictionaryRef)CFDictionaryCreateMutable(
- kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SOCKETS), sockets);
-
- /*
- * Add a Listeners array to the sockets dictionary...
- */
-
- if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks)) != NULL)
- {
- CFDictionaryAddValue(sockets, CFSTR("Listeners"), array);
-
- /*
- * For each listener add a dictionary to the listeners array...
- */
-
- for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
- lis;
- lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
- {
- if ((listener = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- CFArrayAppendValue(array, listener);
-
-# ifdef AF_LOCAL
- if (lis->address.addr.sa_family == AF_LOCAL)
- {
- if ((socket_path = CFStringCreateWithCString(kCFAllocatorDefault,
- lis->address.un.sun_path,
- kCFStringEncodingUTF8)))
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_PATHNAME),
- socket_path);
- CFRelease(socket_path);
- }
- portnum = 0140777; /* (S_IFSOCK|S_IRWXU|S_IRWXG|S_IRWXO) or *
- * 49663d decimal */
- if ((socket_mode = CFNumberCreate(kCFAllocatorDefault,
- kCFNumberIntType, &portnum)))
- {
- CFDictionaryAddValue(listener, CFSTR("SockPathMode"),
- socket_mode);
- CFRelease(socket_mode);
- }
- }
- else
-# endif /* AF_LOCAL */
- {
-# ifdef AF_INET6
- if (lis->address.addr.sa_family == AF_INET6)
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY),
- CFSTR("IPv6"));
- portnum = lis->address.ipv6.sin6_port;
- }
- else
-# endif /* AF_INET6 */
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY),
- CFSTR("IPv4"));
- portnum = lis->address.ipv4.sin_port;
- }
-
- if ((service = getservbyport(portnum, NULL)))
- value = CFStringCreateWithCString(kCFAllocatorDefault,
- service->s_name,
- kCFStringEncodingUTF8);
- else
- value = CFNumberCreate(kCFAllocatorDefault,
- kCFNumberIntType, &portnum);
-
- if (value)
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME),
- value);
- CFRelease(value);
- }
-
- httpAddrString(&lis->address, temp, sizeof(temp));
- if ((value = CFStringCreateWithCString(kCFAllocatorDefault, temp,
- kCFStringEncodingUTF8)))
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_NODENAME),
- value);
- CFRelease(value);
- }
- }
-
- CFRelease(listener);
- }
- }
-
- CFRelease(array);
- }
-
- /*
- * Add the BrowseSocket to the sockets dictionary...
- */
-
- if (Browsing && (BrowseRemoteProtocols & BROWSE_CUPS))
- {
- if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks)) != NULL)
- {
- CFDictionaryAddValue(sockets, CFSTR("BrowseSockets"), array);
-
- if ((listener = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- CFArrayAppendValue(array, listener);
-
- CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY),
- CFSTR("IPv4"));
- CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_TYPE),
- CFSTR("dgram"));
-
- if ((service = getservbyport(BrowsePort, NULL)))
- value = CFStringCreateWithCString(kCFAllocatorDefault,
- service->s_name,
- kCFStringEncodingUTF8);
- else
- value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
- &BrowsePort);
-
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME), value);
- CFRelease(value);
-
- CFRelease(listener);
- }
-
- CFRelease(array);
- }
- }
-
- CFRelease(sockets);
- }
-
- return (cupsd_dict);
-}
-
-
-/*
- * 'launchd_sync_conf()' - Rewrite the launchd config file
- * org.cups.cupsd.plist based on cupsd.conf.
- */
-
-static int /* O - 1 if the file was updated */
-launchd_sync_conf(void)
-{
- SInt32 errorCode; /* Error code */
- CFDataRef resourceData; /* XML property list */
- CFDictionaryRef cupsd_dict; /* New org.cups.cupsd.plist dict */
-
-
- /*
- * If needed reconstitute the existing org.cups.cupsd.plist...
- */
-
- if (!launchd_conf_url &&
- !(launchd_conf_url = CFURLCreateFromFileSystemRepresentation(
- kCFAllocatorDefault,
- (const unsigned char *)LaunchdConf,
- strlen(LaunchdConf), false)))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_sync_conf: "
- "Unable to create file URL for \"%s\"\n", LaunchdConf);
- return (0);
- }
-
- if (!launchd_conf_dict)
- {
- if (CFURLCreateDataAndPropertiesFromResource(NULL, launchd_conf_url,
- &resourceData, NULL, NULL, &errorCode))
- {
- launchd_conf_dict = CFPropertyListCreateFromXMLData(NULL, resourceData,
- kCFPropertyListImmutable, NULL);
- CFRelease(resourceData);
- }
-
- if (!launchd_conf_dict)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_sync_conf: "
- "Unable to create dictionary for \"%s\"\n", LaunchdConf);
- }
- }
-
- /*
- * Create a new org.cups.cupsd.plist dictionary...
- */
-
- if ((cupsd_dict = launchd_create_dict()) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_sync_conf: "
- "Unable to create file URL for \"%s\"\n", LaunchdConf);
- return (0);
- }
-
- /*
- * If the dictionaries are different write a new org.cups.cupsd.plist...
- */
-
- if (!CFEqual(cupsd_dict, launchd_conf_dict))
- {
- if ((resourceData = CFPropertyListCreateXMLData(kCFAllocatorDefault,
- cupsd_dict)))
- {
- if (CFURLWriteDataAndPropertiesToResource(launchd_conf_url, resourceData,
- NULL, &errorCode))
- {
- /*
- * The new cupsd dictionary becomes the on-disk launchd dictionary...
- */
-
- if (launchd_conf_dict)
- CFRelease(launchd_conf_dict);
-
- launchd_conf_dict = cupsd_dict;
- }
- else
- {
- cupsdLogMessage(CUPSD_LOG_WARN,
- "launchd_sync_conf: "
- "CFURLWriteDataAndPropertiesToResource(\"%s\") "
- "failed: %d\n",
- LaunchdConf, (int)errorCode);
-
- CFRelease(cupsd_dict);
- }
-
- CFRelease(resourceData);
- }
-
- /*
- * Let the caller know we updated the file...
- */
-
- return (1);
- }
-
- return (0);
-}
#endif /* HAVE_LAUNCHD */
/*
- * End of "$Id: main.c 6365 2007-03-19 20:56:57Z mike $".
+ * End of "$Id: main.c 6493 2007-04-30 19:33:31Z mike $".
*/
/*
- * "$Id: printers.c 6436 2007-04-02 23:24:02Z mike $"
+ * "$Id: printers.c 6501 2007-04-30 21:53:15Z mike $"
*
* Printer routines for the Common UNIX Printing System (CUPS).
*
* cupsdAddPrinter() - Add a printer to the system.
* cupsdAddPrinterHistory() - Add the current printer state to the history.
* cupsdAddPrinterUser() - Add a user to the ACL.
+ * cupsdCreateCommonData() - Create the common printer data.
* cupsdDeleteAllPrinters() - Delete all printers from the system.
* cupsdDeletePrinter() - Delete a printer from the system.
* cupsdFindPrinter() - Find a printer in the list.
*notifier; /* Current notifier */
static const int nups[] = /* number-up-supported values */
{ 1, 2, 4, 6, 9, 16 };
- static const ipp_orient_t orients[4] =/* orientation-requested-supported values */
+ static const int orients[4] =/* orientation-requested-supported values */
{
IPP_PORTRAIT,
IPP_LANDSCAPE,
"1.0",
"1.1"
};
- static const ipp_op_t ops[] = /* operations-supported values */
+ static const int ops[] = /* operations-supported values */
{
IPP_PRINT_JOB,
IPP_VALIDATE_JOB,
/* copies-supported */
ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies);
+ /* cups-version */
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_TEXT, "cups-version",
+ NULL, CUPS_SVERSION + 6);
+
/* generated-natural-language-supported */
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
"generated-natural-language-supported", NULL, DefaultLanguage);
/* operations-supported */
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"operations-supported",
- sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops);
+ sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, ops);
/* orientation-requested-supported */
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "orientation-requested-supported", 4, (int *)orients);
+ "orientation-requested-supported", 4, orients);
/* page-ranges-supported */
ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1);
ipp_attribute_t *attr; /* Attribute data */
ipp_value_t *val; /* Attribute value */
int num_finishings; /* Number of finishings */
- ipp_finish_t finishings[5]; /* finishings-supported values */
+ int finishings[5]; /* finishings-supported values */
cups_option_t *option; /* Current printer option */
static const char * const sides[3] = /* sides-supported values */
{
}
ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "finishings-supported", num_finishings, (int *)finishings);
+ "finishings-supported", num_finishings, finishings);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"finishings-default", IPP_FINISHINGS_NONE);
}
/*
- * End of "$Id: printers.c 6436 2007-04-02 23:24:02Z mike $".
+ * End of "$Id: printers.c 6501 2007-04-30 21:53:15Z mike $".
*/
/*
- * "$Id: cupstestppd.c 6444 2007-04-04 22:13:58Z mike $"
+ * "$Id: cupstestppd.c 6509 2007-05-03 22:58:41Z mike $"
*
* PPD test program for the Common UNIX Printing System (CUPS).
*
#include <sys/stat.h>
+/*
+ * Error warning overrides...
+ */
+
+enum
+{
+ WARN_NONE = 0,
+ WARN_CONSTRAINTS = 1,
+ WARN_DEFAULTS = 2,
+ WARN_FILTERS = 4,
+ WARN_TRANSLATIONS = 8,
+ WARN_ALL = 15
+};
+
+
/*
* Error codes...
*/
*/
void check_basics(const char *filename);
+int check_constraints(ppd_file_t *ppd, int errors, int verbose, int warn);
+int check_defaults(ppd_file_t *ppd, int errors, int verbose, int warn);
+int check_filters(ppd_file_t *ppd, const char *root, int errors,
+ int verbose, int warn);
+int check_translations(ppd_file_t *ppd, int errors, int verbose, int warn);
void show_conflicts(ppd_file_t *ppd);
void usage(void);
int valid_utf8(const char *s);
+
/*
* 'main()' - Main entry for test program.
*/
const char *ptr; /* Pointer into string */
int files; /* Number of files */
int verbose; /* Want verbose output? */
+ int warn; /* Which errors to just warn about */
int status; /* Exit status */
int errors; /* Number of conformance errors */
int ppdversion; /* PPD spec version in PPD file */
ppd_status_t error; /* Status of ppdOpen*() */
int line; /* Line number for error */
struct stat statbuf; /* File information */
- char super[16], /* Super-type for filter */
- type[256], /* Type for filter */
- program[256], /* Program/filter name */
- pathprog[1024], /* Complete path to program/filter */
+ char pathprog[1024], /* Complete path to program/filter */
*root; /* Root directory */
- int cost; /* Cost of filter */
int xdpi, /* X resolution */
ydpi; /* Y resolution */
ppd_file_t *ppd; /* PPD file record */
ppd_group_t *group2; /* UI group */
ppd_option_t *option2; /* Standard UI option */
ppd_choice_t *choice; /* Standard UI option choice */
- ppd_const_t *c; /* Current constraint */
static char *uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
static char *sections[] = { "ANY", "DOCUMENT", "EXIT",
"JCL", "PAGE", "PROLOG" };
files = 0;
status = ERROR_NONE;
root = "";
+ warn = WARN_NONE;
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-' && argv[i][1])
root = argv[i];
break;
+ case 'W' : /* Turn errors into warnings */
+ i ++;
+
+ if (i >= argc)
+ usage();
+
+ if (!strcmp(argv[i], "none"))
+ warn = WARN_NONE;
+ else if (!strcmp(argv[i], "constraints"))
+ warn |= WARN_CONSTRAINTS;
+ else if (!strcmp(argv[i], "defaults"))
+ warn |= WARN_DEFAULTS;
+ else if (!strcmp(argv[i], "filters"))
+ warn |= WARN_FILTERS;
+ else if (!strcmp(argv[i], "translations"))
+ warn |= WARN_TRANSLATIONS;
+ else if (!strcmp(argv[i], "all"))
+ warn = WARN_ALL;
+ else
+ usage();
+ break;
+
case 'q' : /* Quiet mode */
if (verbose > 0)
{
* Look for default keywords with no matching option...
*/
- for (j = 0; j < ppd->num_attrs; j ++)
- {
- attr = ppd->attrs[j];
-
- if (!strcmp(attr->name, "DefaultColorSpace") ||
- !strcmp(attr->name, "DefaultFont") ||
- !strcmp(attr->name, "DefaultImageableArea") ||
- !strcmp(attr->name, "DefaultOutputOrder") ||
- !strcmp(attr->name, "DefaultPaperDimension") ||
- !strcmp(attr->name, "DefaultResolution") ||
- !strcmp(attr->name, "DefaultTransfer"))
- continue;
-
- if (!strncmp(attr->name, "Default", 7))
- {
- if ((option = ppdFindOption(ppd, attr->name + 7)) != NULL &&
- strcmp(attr->value, "Unknown"))
- {
- /*
- * Check that the default option value matches a choice...
- */
-
- for (k = 0; k < option->num_choices; k ++)
- if (!strcmp(option->choices[k].choice, attr->value))
- break;
-
- if (k >= option->num_choices)
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** %s %s does not exist!\n"),
- attr->name, attr->value);
- }
-
- errors ++;
- }
- }
- }
- }
+ if (!(warn & WARN_DEFAULTS))
+ errors = check_defaults(ppd, errors, verbose, 0);
if ((attr = ppdFindAttr(ppd, "DefaultImageableArea", NULL)) == NULL)
{
_cupsLangPuts(stdout, _(" FAIL\n"));
_cupsLangPuts(stdout,
- _(" **FAIL** REQUIRED DefaultImageableArea\n"
+ _(" **FAIL** REQUIRED DefaultImageableArea\n"
" REF: Page 102, section 5.15.\n"));
- }
+ }
errors ++;
}
else if (ppdPageSize(ppd, attr->value) == NULL &&
- strcmp(attr->value, "Unknown"))
+ strcmp(attr->value, "Unknown"))
{
if (verbose >= 0)
{
_cupsLangPuts(stdout, _(" FAIL\n"));
_cupsLangPrintf(stdout,
- _(" **FAIL** BAD DefaultImageableArea %s!\n"
+ _(" **FAIL** BAD DefaultImageableArea %s!\n"
" REF: Page 102, section 5.15.\n"),
attr->value);
- }
+ }
errors ++;
}
_cupsLangPuts(stdout, _(" FAIL\n"));
_cupsLangPuts(stdout,
- _(" **FAIL** REQUIRED DefaultPaperDimension\n"
+ _(" **FAIL** REQUIRED DefaultPaperDimension\n"
" REF: Page 103, section 5.15.\n"));
- }
+ }
errors ++;
}
else if (ppdPageSize(ppd, attr->value) == NULL &&
- strcmp(attr->value, "Unknown"))
+ strcmp(attr->value, "Unknown"))
{
if (verbose >= 0)
{
_cupsLangPuts(stdout, _(" FAIL\n"));
_cupsLangPrintf(stdout,
- _(" **FAIL** BAD DefaultPaperDimension %s!\n"
+ _(" **FAIL** BAD DefaultPaperDimension %s!\n"
" REF: Page 103, section 5.15.\n"),
attr->value);
- }
+ }
errors ++;
}
if (option->defchoice[0])
{
- if (ppdFindChoice(option, option->defchoice) == NULL &&
- strcmp(option->defchoice, "Unknown"))
+ if (ppdFindChoice(option, option->defchoice) == NULL &&
+ strcmp(option->defchoice, "Unknown"))
{
if (verbose >= 0)
{
_cupsLangPuts(stdout, _(" FAIL\n"));
_cupsLangPrintf(stdout,
- _(" **FAIL** BAD Default%s %s\n"
+ _(" **FAIL** BAD Default%s %s\n"
" REF: Page 40, section 4.5.\n"),
option->keyword, option->defchoice);
- }
+ }
errors ++;
}
else if (verbose > 0)
_cupsLangPrintf(stdout,
- _(" PASS Default%s\n"),
+ _(" PASS Default%s\n"),
option->keyword);
}
else
_cupsLangPuts(stdout, _(" FAIL\n"));
_cupsLangPrintf(stdout,
- _(" **FAIL** REQUIRED Default%s\n"
- " REF: Page 40, section 4.5.\n"),
- option->keyword);
- }
+ _(" **FAIL** REQUIRED Default%s\n"
+ " REF: Page 40, section 4.5.\n"),
+ option->keyword);
+ }
errors ++;
}
errors ++;
}
+ else if (!strncasecmp(ppd->manufacturer, "OkiData", 7) ||
+ !strncasecmp(ppd->manufacturer, "Oki Data", 8))
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ _cupsLangPuts(stdout,
+ _(" **FAIL** BAD Manufacturer (should be "
+ "\"Oki\")\n"
+ " REF: Page 211, table D.1.\n"));
+ }
+
+ errors ++;
+ }
else if (verbose > 0)
_cupsLangPuts(stdout, _(" PASS Manufacturer\n"));
}
}
}
- if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) != NULL &&
- attr->value)
+ if ((attr = ppdFindAttr(ppd, "1284DeviceID", NULL)) &&
+ strcmp(attr->name, "1284DeviceID"))
{
- /*
- * This file contains localizations, check them...
- */
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
- char *languages, /* Copy of attribute value */
- *langstart, /* Start of current language */
- *langptr, /* Pointer into languages */
- keyword[PPD_MAX_NAME],
- /* Localization keyword */
- ckeyword[PPD_MAX_NAME];
- /* Custom option keyword */
- ppd_coption_t *coption; /* Custom option */
- ppd_cparam_t *cparam; /* Custom parameter */
- cups_array_t *langlist; /* List of languages so far */
- char ll[3]; /* Base language */
+ _cupsLangPrintf(stdout,
+ _(" **FAIL** %s must be 1284DeviceID!\n"
+ " REF: Page 72, section 5.5\n"),
+ attr->name);
+ }
+ errors ++;
+ }
- languages = strdup(attr->value);
- langlist = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+ if (!(warn & WARN_CONSTRAINTS))
+ errors = check_constraints(ppd, errors, verbose, 0);
- for (langptr = languages; *langptr;)
- {
- /*
- * Skip leading whitespace...
- */
+ if (!(warn & WARN_FILTERS))
+ errors = check_filters(ppd, root, errors, verbose, 0);
- while (isspace(*langptr & 255))
- langptr ++;
+ if (!(warn & WARN_TRANSLATIONS))
+ errors = check_translations(ppd, errors, verbose, 0);
- if (!*langptr)
- break;
+ if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) != NULL &&
+ attr->value)
+ {
+ /*
+ * This file contains localizations, check for conformance of the
+ * base translation...
+ */
- /*
- * Find the end of this language name...
- */
+ if ((attr = ppdFindAttr(ppd, "LanguageEncoding", NULL)) != NULL)
+ {
+ if (!attr->value || strcmp(attr->value, "ISOLatin1"))
+ {
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
- for (langstart = langptr;
- *langptr && !isspace(*langptr & 255);
- langptr ++);
+ if (verbose >= 0)
+ _cupsLangPrintf(stderr,
+ _(" **FAIL** Bad LanguageEncoding %s - "
+ "must be ISOLatin1!\n"),
+ attr->value ? attr->value : "(null)");
- if (*langptr)
- *langptr++ = '\0';
+ errors ++;
+ }
- j = strlen(langstart);
- if (j != 2 && j != 5)
+ if (!ppd->lang_version || strcmp(ppd->lang_version, "English"))
{
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad language \"%s\"!\n"),
- langstart);
- }
+ if (verbose >= 0)
+ _cupsLangPrintf(stderr,
+ _(" **FAIL** Bad LanguageVersion %s - "
+ "must be English!\n"),
+ ppd->lang_version ? ppd->lang_version : "(null)");
- errors ++;
- continue;
+ errors ++;
}
-
- cupsArrayAdd(langlist, langstart);
-
- /*
+
+ /*
* Loop through all options and choices...
*/
- for (option = ppdFirstOption(ppd);
+ for (option = ppdFirstOption(ppd);
option;
option = ppdNextOption(ppd))
{
- snprintf(keyword, sizeof(keyword), "%s.Translation", langstart);
- if ((attr = ppdFindAttr(ppd, keyword, option->keyword)) == NULL)
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
+ /*
+ * Check for special characters outside A0 to BF, F7, or F8
+ * that are used for languages other than English.
+ */
- _cupsLangPrintf(stdout,
- _(" **FAIL** Missing \"%s\" translation "
- "string for option %s!\n"),
- langstart, option->keyword);
- }
+ for (ptr = option->text; *ptr; ptr ++)
+ if ((*ptr & 0x80) && (*ptr & 0xe0) != 0xa0 &&
+ (*ptr & 0xff) != 0xf7 && (*ptr & 0xff) != 0xf8)
+ break;
- errors ++;
- }
- else if (!valid_utf8(attr->text))
+ if (*ptr)
{
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad UTF-8 \"%s\" translation "
- "string for option %s!\n"),
- langstart, option->keyword);
- }
-
- errors ++;
- }
-
- for (ptr = option->text; *ptr; ptr ++)
- if (*ptr & 128)
- break;
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
- if (*ptr)
- {
if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
_cupsLangPrintf(stdout,
- _(" **FAIL** Default translation "
+ _(" **FAIL** Default translation "
"string for option %s contains 8-bit "
"characters!\n"),
option->keyword);
- }
errors ++;
}
- snprintf(keyword, sizeof(keyword), "%s.%s", langstart,
- option->keyword);
- for (j = 0; j < option->num_choices; j ++)
+ for (j = 0; j < option->num_choices; j ++)
{
- if (!strcasecmp(option->choices[j].choice, "Custom") &&
- (coption = ppdFindCustomOption(ppd,
- option->keyword)) != NULL)
- {
- snprintf(ckeyword, sizeof(ckeyword), "%s.Custom%s",
- langstart, option->keyword);
-
- if ((attr = ppdFindAttr(ppd, ckeyword, "True")) != NULL &&
- !valid_utf8(attr->text))
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad UTF-8 \"%s\" "
- "translation string for option %s, "
- "choice %s!\n"),
- langstart, ckeyword + 1 + strlen(langstart),
- "True");
- }
-
- errors ++;
- }
+ /*
+ * Check for special characters outside A0 to BF, F7, or F8
+ * that are used for languages other than English.
+ */
- if (strcasecmp(option->keyword, "PageSize"))
- {
- for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
- cparam;
- cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
- {
- snprintf(ckeyword, sizeof(ckeyword), "%s.ParamCustom%s",
- langstart, option->keyword);
- if ((attr = ppdFindAttr(ppd, ckeyword, cparam->name)) == NULL)
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Missing \"%s\" "
- "translation string for option %s, "
- "choice %s!\n"),
- langstart,
- ckeyword + 1 + strlen(langstart),
- cparam->name);
- }
-
- errors ++;
- }
- else if (!valid_utf8(attr->text))
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad UTF-8 \"%s\" "
- "translation string for option %s, "
- "choice %s!\n"),
- langstart,
- ckeyword + 1 + strlen(langstart),
- cparam->name);
- }
-
- errors ++;
- }
- }
- }
- }
- else if ((attr = ppdFindAttr(ppd, keyword, option->choices[j].choice)) == NULL)
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Missing \"%s\" "
- "translation string for option %s, "
- "choice %s!\n"),
- langstart, option->keyword,
- option->choices[j].choice);
- }
+ for (ptr = option->choices[j].text; *ptr; ptr ++)
+ if ((*ptr & 0x80) && (*ptr & 0xe0) != 0xa0 &&
+ (*ptr & 0xff) != 0xf7 && (*ptr & 0xff) != 0xf8)
+ break;
- errors ++;
- }
- else if (!valid_utf8(attr->text))
+ if (*ptr)
{
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad UTF-8 \"%s\" "
- "translation string for option %s, "
- "choice %s!\n"),
- langstart, option->keyword,
- option->choices[j].choice);
- }
-
- errors ++;
- }
-
- for (ptr = option->choices[j].text; *ptr; ptr ++)
- if (*ptr & 128)
- break;
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
- if (*ptr)
- {
if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
_cupsLangPrintf(stdout,
- _(" **FAIL** Default translation "
+ _(" **FAIL** Default translation "
"string for option %s choice %s contains "
"8-bit characters!\n"),
option->keyword,
option->choices[j].choice);
- }
errors ++;
}
- }
+ }
}
- }
-
- /*
- * Verify that we have the base language for each localized one...
- */
+ }
+ }
- for (langptr = (char *)cupsArrayFirst(langlist);
- langptr;
- langptr = (char *)cupsArrayNext(langlist))
- if (langptr[2])
- {
- /*
- * Lookup the base language...
- */
+ /*
+ * Final pass/fail notification...
+ */
- cupsArraySave(langlist);
+ if (errors)
+ status = ERROR_CONFORMANCE;
+ else if (!verbose)
+ _cupsLangPuts(stdout, _(" PASS\n"));
- strlcpy(ll, langptr, sizeof(ll));
+ if (verbose >= 0)
+ {
+ check_basics(argv[i]);
- if (!cupsArrayFind(langlist, ll))
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
+ if (warn & WARN_CONSTRAINTS)
+ errors = check_constraints(ppd, errors, verbose, 1);
- _cupsLangPrintf(stdout,
- _(" **FAIL** No base translation \"%s\" "
- "is included in file!\n"), ll);
- }
+ if (warn & WARN_DEFAULTS)
+ errors = check_defaults(ppd, errors, verbose, 1);
- errors ++;
- }
+ if (warn & WARN_FILTERS)
+ errors = check_filters(ppd, root, errors, verbose, 1);
- cupsArrayRestore(langlist);
- }
+ if (warn & WARN_TRANSLATIONS)
+ errors = check_translations(ppd, errors, verbose, 1);
/*
- * Free memory used for the languages...
+ * Look for default keywords with no corresponding option...
*/
- cupsArrayDelete(langlist);
- free(languages);
- }
-
- for (attr = ppdFindAttr(ppd, "cupsFilter", NULL);
- attr;
- attr = ppdFindNextAttr(ppd, "cupsFilter", NULL))
- {
- if (!attr->value ||
- sscanf(attr->value, "%15[^/]/%255s%d%255s", super, type, &cost,
- program) != 4)
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
+ for (j = 0; j < ppd->num_attrs; j ++)
+ {
+ attr = ppd->attrs[j];
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad cupsFilter value \"%s\"!\n"),
- attr->value ? attr->value : "");
- }
+ if (!strcmp(attr->name, "DefaultColorSpace") ||
+ !strcmp(attr->name, "DefaultColorSep") ||
+ !strcmp(attr->name, "DefaultFont") ||
+ !strcmp(attr->name, "DefaultImageableArea") ||
+ !strcmp(attr->name, "DefaultOutputOrder") ||
+ !strcmp(attr->name, "DefaultPaperDimension") ||
+ !strcmp(attr->name, "DefaultScreenProc") ||
+ !strcmp(attr->name, "DefaultTransfer"))
+ continue;
- errors ++;
+ if (!strncmp(attr->name, "Default", 7) &&
+ !ppdFindOption(ppd, attr->name + 7))
+ _cupsLangPrintf(stdout,
+ _(" WARN %s has no corresponding "
+ "options!\n"),
+ attr->name);
}
- else
- {
- if (program[0] == '/')
- snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
- else
- {
- if ((ptr = getenv("CUPS_SERVERBIN")) == NULL)
- ptr = CUPS_SERVERBIN;
- if (*ptr == '/' || !*root)
- snprintf(pathprog, sizeof(pathprog), "%s%s/filter/%s", root, ptr,
- program);
- else
- snprintf(pathprog, sizeof(pathprog), "%s/%s/filter/%s", root, ptr,
- program);
- }
-
- if (stat(pathprog, &statbuf))
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout, _(" **FAIL** Missing cupsFilter "
- "file \"%s\"\n"), program);
- }
-
- errors ++;
- }
- }
- }
-
- for (attr = ppdFindAttr(ppd, "cupsPreFilter", NULL);
- attr;
- attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL))
- {
- if (!attr->value ||
- sscanf(attr->value, "%15[^/]/%255s%d%255s", super, type, &cost,
- program) != 4)
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad cupsPreFilter value \"%s\"!\n"),
- attr->value ? attr->value : "");
- }
-
- errors ++;
- }
- else
- {
- if (program[0] == '/')
- snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
- else
- {
- if ((ptr = getenv("CUPS_SERVERBIN")) == NULL)
- ptr = CUPS_SERVERBIN;
-
- if (*ptr == '/' || !*root)
- snprintf(pathprog, sizeof(pathprog), "%s%s/filter/%s", root, ptr,
- program);
- else
- snprintf(pathprog, sizeof(pathprog), "%s/%s/filter/%s", root, ptr,
- program);
- }
-
- if (stat(pathprog, &statbuf))
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout, _(" **FAIL** Missing cupsPreFilter "
- "file \"%s\"\n"), program);
- }
-
- errors ++;
- }
- }
- }
-
- if ((attr = ppdFindAttr(ppd, "1284DeviceID", NULL)) &&
- strcmp(attr->name, "1284DeviceID"))
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** %s must be 1284DeviceID!\n"
- " REF: Page 72, section 5.5\n"),
- attr->name);
- }
-
- errors ++;
- }
-
- /*
- * Check for bad UIConstraints...
- */
-
- for (j = ppd->num_consts, c = ppd->consts; j > 0; j --, c ++)
- {
- option = ppdFindOption(ppd, c->option1);
- option2 = ppdFindOption(ppd, c->option2);
-
- if (!option || !option2)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- if (!option)
- _cupsLangPrintf(stdout,
- _(" **FAIL** Missing option %s in "
- "UIConstraint \"*%s %s *%s %s\"!\n"),
- c->option1,
- c->option1, c->choice1, c->option2, c->choice2);
-
- if (!option2)
- _cupsLangPrintf(stdout,
- _(" **FAIL** Missing option %s in "
- "UIConstraint \"*%s %s *%s %s\"!\n"),
- c->option2,
- c->option1, c->choice1, c->option2, c->choice2);
-
- continue;
- }
-
- if (c->choice1[0] && !ppdFindChoice(option, c->choice1))
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Missing choice *%s %s in "
- "UIConstraint \"*%s %s *%s %s\"!\n"),
- c->option1, c->choice1,
- c->option1, c->choice1, c->option2, c->choice2);
- }
-
- if (c->choice2[0] && !ppdFindChoice(option2, c->choice2))
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Missing choice *%s %s in "
- "UIConstraint \"*%s %s *%s %s\"!\n"),
- c->option2, c->choice2,
- c->option1, c->choice1, c->option2, c->choice2);
- }
- }
-
- /*
- * Final pass/fail notification...
- */
-
- if (errors)
- status = ERROR_CONFORMANCE;
- else if (!verbose)
- _cupsLangPuts(stdout, _(" PASS\n"));
-
- if (verbose >= 0)
- {
- check_basics(argv[i]);
-
- /*
- * Look for default keywords with no corresponding option...
- */
-
- for (j = 0; j < ppd->num_attrs; j ++)
- {
- attr = ppd->attrs[j];
-
- if (!strcmp(attr->name, "DefaultColorSpace") ||
- !strcmp(attr->name, "DefaultColorSep") ||
- !strcmp(attr->name, "DefaultFont") ||
- !strcmp(attr->name, "DefaultImageableArea") ||
- !strcmp(attr->name, "DefaultOutputOrder") ||
- !strcmp(attr->name, "DefaultPaperDimension") ||
- !strcmp(attr->name, "DefaultScreenProc") ||
- !strcmp(attr->name, "DefaultTransfer"))
- continue;
-
- if (!strncmp(attr->name, "Default", 7) &&
- !ppdFindOption(ppd, attr->name + 7))
- _cupsLangPrintf(stdout,
- _(" WARN %s has no corresponding "
- "options!\n"),
- attr->name);
- }
-
- /*
- * Check for old Duplex option names...
- */
+ /*
+ * Check for old Duplex option names...
+ */
if ((option = ppdFindOption(ppd, "EFDuplex")) == NULL)
option = ppdFindOption(ppd, "KD03Duplex");
}
+/*
+ * 'check_constraints()' - Check UIConstraints in the PPD file.
+ */
+
+int /* O - Errors found */
+check_constraints(ppd_file_t *ppd, /* I - PPD file */
+ int errors, /* I - Errors found */
+ int verbose, /* I - Verbosity level */
+ int warn) /* I - Warnings only? */
+{
+ int j; /* Looping var */
+ ppd_const_t *c; /* Current constraint */
+ ppd_option_t *option; /* Standard UI option */
+ ppd_option_t *option2; /* Standard UI option */
+ const char *prefix; /* WARN/FAIL prefix */
+
+
+ prefix = warn ? " WARN " : "**FAIL**";
+
+ for (j = ppd->num_consts, c = ppd->consts; j > 0; j --, c ++)
+ {
+ option = ppdFindOption(ppd, c->option1);
+ option2 = ppdFindOption(ppd, c->option2);
+
+ if (!option || !option2)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (!option)
+ _cupsLangPrintf(stdout,
+ _(" %s Missing option %s in "
+ "UIConstraint \"*%s %s *%s %s\"!\n"),
+ prefix, c->option1,
+ c->option1, c->choice1, c->option2, c->choice2);
+
+ if (!option2)
+ _cupsLangPrintf(stdout,
+ _(" %s Missing option %s in "
+ "UIConstraint \"*%s %s *%s %s\"!\n"),
+ prefix, c->option2,
+ c->option1, c->choice1, c->option2, c->choice2);
+
+ if (!warn)
+ errors ++;
+
+ continue;
+ }
+
+ if (c->choice1[0] && !ppdFindChoice(option, c->choice1))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ _cupsLangPrintf(stdout,
+ _(" %s Missing choice *%s %s in "
+ "UIConstraint \"*%s %s *%s %s\"!\n"),
+ prefix, c->option1, c->choice1,
+ c->option1, c->choice1, c->option2, c->choice2);
+
+ if (!warn)
+ errors ++;
+ }
+
+ if (c->choice2[0] && !ppdFindChoice(option2, c->choice2))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ _cupsLangPrintf(stdout,
+ _(" %s Missing choice *%s %s in "
+ "UIConstraint \"*%s %s *%s %s\"!\n"),
+ prefix, c->option2, c->choice2,
+ c->option1, c->choice1, c->option2, c->choice2);
+
+ if (!warn)
+ errors ++;
+ }
+ }
+
+ return (errors);
+}
+
+
+/*
+ * 'check_defaults()' - Check default option keywords in the PPD file.
+ */
+
+int /* O - Errors found */
+check_defaults(ppd_file_t *ppd, /* I - PPD file */
+ int errors, /* I - Errors found */
+ int verbose, /* I - Verbosity level */
+ int warn) /* I - Warnings only? */
+{
+ int j, k; /* Looping vars */
+ ppd_attr_t *attr; /* PPD attribute */
+ ppd_option_t *option; /* Standard UI option */
+ const char *prefix; /* WARN/FAIL prefix */
+
+
+ prefix = warn ? " WARN " : "**FAIL**";
+
+ for (j = 0; j < ppd->num_attrs; j ++)
+ {
+ attr = ppd->attrs[j];
+
+ if (!strcmp(attr->name, "DefaultColorSpace") ||
+ !strcmp(attr->name, "DefaultFont") ||
+ !strcmp(attr->name, "DefaultImageableArea") ||
+ !strcmp(attr->name, "DefaultOutputOrder") ||
+ !strcmp(attr->name, "DefaultPaperDimension") ||
+ !strcmp(attr->name, "DefaultResolution") ||
+ !strcmp(attr->name, "DefaultTransfer"))
+ continue;
+
+ if (!strncmp(attr->name, "Default", 7))
+ {
+ if ((option = ppdFindOption(ppd, attr->name + 7)) != NULL &&
+ strcmp(attr->value, "Unknown"))
+ {
+ /*
+ * Check that the default option value matches a choice...
+ */
+
+ for (k = 0; k < option->num_choices; k ++)
+ if (!strcmp(option->choices[k].choice, attr->value))
+ break;
+
+ if (k >= option->num_choices)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s %s %s does not exist!\n"),
+ prefix, attr->name, attr->value);
+
+ if (!warn)
+ errors ++;
+ }
+ }
+ }
+ }
+
+ return (errors);
+}
+
+
+/*
+ * 'check_filters()' - Check filters in the PPD file.
+ */
+
+int /* O - Errors found */
+check_filters(ppd_file_t *ppd, /* I - PPD file */
+ const char *root, /* I - Root directory */
+ int errors, /* I - Errors found */
+ int verbose, /* I - Verbosity level */
+ int warn) /* I - Warnings only? */
+{
+ ppd_attr_t *attr; /* PPD attribute */
+ const char *ptr; /* Pointer into string */
+ struct stat statbuf; /* File information */
+ char super[16], /* Super-type for filter */
+ type[256], /* Type for filter */
+ program[256], /* Program/filter name */
+ pathprog[1024]; /* Complete path to program/filter */
+ int cost; /* Cost of filter */
+ const char *prefix; /* WARN/FAIL prefix */
+
+
+ prefix = warn ? " WARN " : "**FAIL**";
+
+ for (attr = ppdFindAttr(ppd, "cupsFilter", NULL);
+ attr;
+ attr = ppdFindNextAttr(ppd, "cupsFilter", NULL))
+ {
+ if (!attr->value ||
+ sscanf(attr->value, "%15[^/]/%255s%d%255s", super, type, &cost,
+ program) != 4)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Bad cupsFilter value \"%s\"!\n"),
+ prefix, attr->value ? attr->value : "");
+
+ if (!warn)
+ errors ++;
+ }
+ else
+ {
+ if (program[0] == '/')
+ snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
+ else
+ {
+ if ((ptr = getenv("CUPS_SERVERBIN")) == NULL)
+ ptr = CUPS_SERVERBIN;
+
+ if (*ptr == '/' || !*root)
+ snprintf(pathprog, sizeof(pathprog), "%s%s/filter/%s", root, ptr,
+ program);
+ else
+ snprintf(pathprog, sizeof(pathprog), "%s/%s/filter/%s", root, ptr,
+ program);
+ }
+
+ if (stat(pathprog, &statbuf))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout, _(" %s Missing cupsFilter "
+ "file \"%s\"\n"), prefix, program);
+
+ if (!warn)
+ errors ++;
+ }
+ }
+ }
+
+ for (attr = ppdFindAttr(ppd, "cupsPreFilter", NULL);
+ attr;
+ attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL))
+ {
+ if (!attr->value ||
+ sscanf(attr->value, "%15[^/]/%255s%d%255s", super, type, &cost,
+ program) != 4)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Bad cupsPreFilter value \"%s\"!\n"),
+ prefix, attr->value ? attr->value : "");
+
+ if (!warn)
+ errors ++;
+ }
+ else
+ {
+ if (program[0] == '/')
+ snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
+ else
+ {
+ if ((ptr = getenv("CUPS_SERVERBIN")) == NULL)
+ ptr = CUPS_SERVERBIN;
+
+ if (*ptr == '/' || !*root)
+ snprintf(pathprog, sizeof(pathprog), "%s%s/filter/%s", root, ptr,
+ program);
+ else
+ snprintf(pathprog, sizeof(pathprog), "%s/%s/filter/%s", root, ptr,
+ program);
+ }
+
+ if (stat(pathprog, &statbuf))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout, _(" %s Missing cupsPreFilter "
+ "file \"%s\"\n"), prefix, program);
+
+ if (!warn)
+ errors ++;
+ }
+ }
+ }
+
+ return (errors);
+}
+
+
+/*
+ * 'check_translations()' - Check translations in the PPD file.
+ */
+
+int /* O - Errors found */
+check_translations(ppd_file_t *ppd, /* I - PPD file */
+ int errors, /* I - Errors found */
+ int verbose, /* I - Verbosity level */
+ int warn) /* I - Warnings only? */
+{
+ int j; /* Looping var */
+ ppd_attr_t *attr; /* PPD attribute */
+ char *languages, /* Copy of attribute value */
+ *langstart, /* Start of current language */
+ *langptr, /* Pointer into languages */
+ keyword[PPD_MAX_NAME], /* Localization keyword (full) */
+ llkeyword[PPD_MAX_NAME],/* Localization keyword (base) */
+ ckeyword[PPD_MAX_NAME], /* Custom option keyword (full) */
+ cllkeyword[PPD_MAX_NAME];
+ /* Custom option keyword (base) */
+ ppd_option_t *option; /* Standard UI option */
+ ppd_coption_t *coption; /* Custom option */
+ ppd_cparam_t *cparam; /* Custom parameter */
+ cups_array_t *langlist; /* List of languages so far */
+ char ll[3]; /* Base language */
+ const char *prefix; /* WARN/FAIL prefix */
+
+
+ prefix = warn ? " WARN " : "**FAIL**";
+
+ if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) != NULL &&
+ attr->value)
+ {
+ /*
+ * This file contains localizations, check them...
+ */
+
+ languages = strdup(attr->value);
+ langlist = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+
+ for (langptr = languages; *langptr;)
+ {
+ /*
+ * Skip leading whitespace...
+ */
+
+ while (isspace(*langptr & 255))
+ langptr ++;
+
+ if (!*langptr)
+ break;
+
+ /*
+ * Find the end of this language name...
+ */
+
+ for (langstart = langptr;
+ *langptr && !isspace(*langptr & 255);
+ langptr ++);
+
+ if (*langptr)
+ *langptr++ = '\0';
+
+ j = strlen(langstart);
+ if (j != 2 && j != 5)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Bad language \"%s\"!\n"),
+ prefix, langstart);
+
+ if (!warn)
+ errors ++;
+
+ continue;
+ }
+
+ cupsArrayAdd(langlist, langstart);
+
+ strlcpy(ll, langstart, sizeof(ll));
+
+ /*
+ * Loop through all options and choices...
+ */
+
+ for (option = ppdFirstOption(ppd);
+ option;
+ option = ppdNextOption(ppd))
+ {
+ snprintf(keyword, sizeof(keyword), "%s.Translation", langstart);
+ snprintf(llkeyword, sizeof(llkeyword), "%s.Translation", ll);
+
+ if ((attr = ppdFindAttr(ppd, keyword, option->keyword)) == NULL &&
+ (attr = ppdFindAttr(ppd, llkeyword, option->keyword)) == NULL)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Missing \"%s\" translation "
+ "string for option %s!\n"),
+ prefix, langstart, option->keyword);
+
+ if (!warn)
+ errors ++;
+ }
+ else if (!valid_utf8(attr->text))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Bad UTF-8 \"%s\" translation "
+ "string for option %s!\n"),
+ prefix, langstart, option->keyword);
+
+ if (!warn)
+ errors ++;
+ }
+
+ snprintf(keyword, sizeof(keyword), "%s.%s", langstart,
+ option->keyword);
+ snprintf(llkeyword, sizeof(llkeyword), "%s.%s", ll,
+ option->keyword);
+
+ for (j = 0; j < option->num_choices; j ++)
+ {
+ if (!strcasecmp(option->choices[j].choice, "Custom") &&
+ (coption = ppdFindCustomOption(ppd,
+ option->keyword)) != NULL)
+ {
+ snprintf(ckeyword, sizeof(ckeyword), "%s.Custom%s",
+ langstart, option->keyword);
+
+ if ((attr = ppdFindAttr(ppd, ckeyword, "True")) != NULL &&
+ !valid_utf8(attr->text))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Bad UTF-8 \"%s\" "
+ "translation string for option %s, "
+ "choice %s!\n"),
+ prefix, langstart,
+ ckeyword + 1 + strlen(langstart),
+ "True");
+
+ if (!warn)
+ errors ++;
+ }
+
+ if (strcasecmp(option->keyword, "PageSize"))
+ {
+ for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
+ cparam;
+ cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
+ {
+ snprintf(ckeyword, sizeof(ckeyword), "%s.ParamCustom%s",
+ langstart, option->keyword);
+ snprintf(cllkeyword, sizeof(cllkeyword), "%s.ParamCustom%s",
+ ll, option->keyword);
+
+ if ((attr = ppdFindAttr(ppd, ckeyword,
+ cparam->name)) == NULL &&
+ (attr = ppdFindAttr(ppd, cllkeyword,
+ cparam->name)) == NULL)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Missing \"%s\" "
+ "translation string for option %s, "
+ "choice %s!\n"),
+ prefix, langstart,
+ ckeyword + 1 + strlen(langstart),
+ cparam->name);
+
+ if (!warn)
+ errors ++;
+ }
+ else if (!valid_utf8(attr->text))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Bad UTF-8 \"%s\" "
+ "translation string for option %s, "
+ "choice %s!\n"),
+ prefix, langstart,
+ ckeyword + 1 + strlen(langstart),
+ cparam->name);
+
+ if (!warn)
+ errors ++;
+ }
+ }
+ }
+ }
+ else if ((attr = ppdFindAttr(ppd, keyword,
+ option->choices[j].choice)) == NULL &&
+ (attr = ppdFindAttr(ppd, llkeyword,
+ option->choices[j].choice)) == NULL)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Missing \"%s\" "
+ "translation string for option %s, "
+ "choice %s!\n"),
+ prefix, langstart, option->keyword,
+ option->choices[j].choice);
+
+ if (!warn)
+ errors ++;
+ }
+ else if (!valid_utf8(attr->text))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s Bad UTF-8 \"%s\" "
+ "translation string for option %s, "
+ "choice %s!\n"),
+ prefix, langstart, option->keyword,
+ option->choices[j].choice);
+
+ if (!warn)
+ errors ++;
+ }
+ }
+ }
+ }
+
+ /*
+ * Verify that we have the base language for each localized one...
+ */
+
+ for (langptr = (char *)cupsArrayFirst(langlist);
+ langptr;
+ langptr = (char *)cupsArrayNext(langlist))
+ if (langptr[2])
+ {
+ /*
+ * Lookup the base language...
+ */
+
+ cupsArraySave(langlist);
+
+ strlcpy(ll, langptr, sizeof(ll));
+
+ if (!cupsArrayFind(langlist, ll) && strcmp(ll, "zh"))
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" %s No base translation \"%s\" "
+ "is included in file!\n"), prefix, ll);
+
+ if (!warn)
+ errors ++;
+ }
+
+ cupsArrayRestore(langlist);
+ }
+
+ /*
+ * Free memory used for the languages...
+ */
+
+ cupsArrayDelete(langlist);
+ free(languages);
+ }
+
+ return (errors);
+}
+
+
/*
* 'show_conflicts()' - Show option conflicts in a PPD file.
*/
usage(void)
{
_cupsLangPuts(stdout,
- _("Usage: cupstestppd [-R root-directory] [-q] [-r] [-v[v]] "
- "filename1.ppd[.gz] [... filenameN.ppd[.gz]]\n"
- " program | cupstestppd [-R root-directory] [-q] [-r] "
- "[-v[v]] -\n"));
+ _("Usage: cupstestppd [options] filename1.ppd[.gz] "
+ "[... filenameN.ppd[.gz]]\n"
+ " program | cupstestppd [options] -\n"
+ "\n"
+ "Options:\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"));
exit(ERROR_USAGE);
}
/*
- * End of "$Id: cupstestppd.c 6444 2007-04-04 22:13:58Z mike $".
+ * End of "$Id: cupstestppd.c 6509 2007-05-03 22:58:41Z mike $".
*/
</TD>
<TD VALIGN="TOP"><B>Description:</B> {printer_info}<BR>
<B>Location:</B> {printer_location}<BR>
-<B>Make and Model:</B> {printer_make_and_model}<BR>
+<B>Pritner Driver:</B> {printer_make_and_model}<BR>
<B>Printer State:</B> {printer_state=3?idle:{printer_state=4?processing:stopped}},
{printer_is_accepting_jobs=0?rejecting jobs:accepting jobs}, {printer_is_shared=0?not:} published.
{?device_uri=?:<BR><B>Device URI:</B> {device_uri}}
--- /dev/null
+# Get printer PPD file using CUPS-Get-PPD
+{
+ # The name of the test...
+ NAME "Get printer PPD file using CUPS-Get-PPD"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-Get-PPD
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+
+ # What statuses are OK?
+ STATUS successful-ok
+}
--- /dev/null
+# Get PPD file using CUPS-get-ppd
+{
+ # The name of the test...
+ NAME "Get PPD file using CUPS-get-ppd"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-get-ppd
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR name ppd-name $ENV[ppd-name]
+
+ # What statuses are OK?
+ STATUS successful-ok
+}
--- /dev/null
+# Get PPD files using CUPS-Get-PPDs and language
+{
+ # The name of the test...
+ NAME "Get PPD files using CUPS-Get-PPDs and language"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-Get-PPDs
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR language ppd-natural-language $ENV[language]
+
+ # What statuses are OK?
+ STATUS successful-ok
+}
--- /dev/null
+# Get PPD files using CUPS-Get-PPDs and model
+{
+ # The name of the test...
+ NAME "Get PPD files using CUPS-Get-PPDs and model"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-Get-PPDs
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR text ppd-make-and-model $ENV[model]
+
+ # What statuses are OK?
+ STATUS successful-ok
+}
--- /dev/null
+# Get PPD files using CUPS-Get-PPDs and make
+{
+ # The name of the test...
+ NAME "Get PPD files using CUPS-Get-PPDs and make"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-Get-PPDs
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR text ppd-make $ENV[make]
+
+ # What statuses are OK?
+ STATUS successful-ok
+}
--- /dev/null
+# Get PPD files using CUPS-Get-PPDs and Product
+{
+ # The name of the test...
+ NAME "Get PPD files using CUPS-Get-PPDs and Product"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-Get-PPDs
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR text ppd-product $ENV[product]
+
+ # What statuses are OK?
+ STATUS successful-ok
+}
--- /dev/null
+# Get PPD files using CUPS-Get-PPDs and PSVersion
+{
+ # The name of the test...
+ NAME "Get PPD files using CUPS-Get-PPDs and PSVersion"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-Get-PPDs
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR text ppd-psversion $ENV[psversion]
+
+ # What statuses are OK?
+ STATUS successful-ok
+}
/*
- * "$Id: ipptest.c 5876 2006-08-24 15:05:04Z mike $"
+ * "$Id: ipptest.c 6503 2007-05-01 23:06:44Z mike $"
*
* IPP test command for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products.
+ * Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
{
if (!strcmp(argv[i], "-v"))
Verbosity ++;
+ else if (!strcmp(argv[i], "-d"))
+ {
+ i ++;
+
+ if (i >= argc)
+ usage(NULL);
+ else
+ putenv(argv[i]);
+ }
else if (!strcmp(argv[i], "-i"))
{
i++;
strlcpy(tokenptr, cupsUser(), sizeof(token) - (tokenptr - token));
tempptr += 5;
}
+ else if (!strncasecmp(tempptr + 1, "ENV[", 4))
+ {
+ char *end; /* End of $ENV[name] */
+
+
+ if ((end = strchr(tempptr + 5, ']')) != NULL)
+ {
+ *end++ = '\0';
+ strlcpy(tokenptr,
+ getenv(tempptr + 5) ? getenv(tempptr + 5) : tempptr + 5,
+ sizeof(token) - (tokenptr - token));
+ tempptr = end;
+ }
+ else
+ {
+ *tokenptr++ = *tempptr++;
+ *tokenptr = '\0';
+ }
+ }
else
{
- *tokenptr++ = *tempptr ++;
+ *tokenptr++ = *tempptr++;
*tokenptr = '\0';
}
if (filename[0])
response = cupsDoFileRequest(http, request, resource, filename);
else
- response = cupsDoRequest(http, request, resource);
+ response = cupsDoIORequest(http, request, resource, -1,
+ Verbosity ? 1 : -1);
if (response == NULL)
{
puts(" BAD STATUS");
printf(" status-code = %04x (%s)\n",
- cupsLastError(), cupsLastErrorString());
+ cupsLastError(), ippErrorString(cupsLastError()));
for (i = 0; i < num_expects; i ++)
if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
/*
- * End of "$Id: ipptest.c 5876 2006-08-24 15:05:04Z mike $".
+ * End of "$Id: ipptest.c 6503 2007-05-01 23:06:44Z mike $".
*/