summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES-1.4.txt9
-rw-r--r--CHANGES.txt3
-rw-r--r--backend/backend-private.h4
-rw-r--r--backend/ipp.c94
-rw-r--r--backend/lpd.c2
-rw-r--r--backend/network.c10
-rw-r--r--backend/pseudo30
-rw-r--r--backend/runloop.c3
-rw-r--r--backend/snmp-supplies.c6
-rw-r--r--backend/socket.c16
-rw-r--r--backend/usb-libusb.c4
-rw-r--r--cgi-bin/admin.c2
-rw-r--r--cups/Makefile3
-rw-r--r--cups/auth.c310
-rw-r--r--cups/cups-private.h10
-rw-r--r--cups/dest.c435
-rw-r--r--cups/file.c10
-rw-r--r--cups/globals.c3
-rw-r--r--cups/libcups2.def1
-rw-r--r--cups/libcups_s.exp1
-rw-r--r--cups/mark.c80
-rw-r--r--cups/ppd-cache.c2348
-rw-r--r--cups/ppd-private.h74
-rw-r--r--cups/ppd.c6
-rw-r--r--cups/ppd.h5
-rw-r--r--cups/pwg-file.c638
-rw-r--r--cups/pwg-media.c4
-rw-r--r--cups/pwg-ppd.c1489
-rw-r--r--cups/request.c39
-rw-r--r--cups/sidechannel.c6
-rw-r--r--cups/sidechannel.h17
-rw-r--r--cups/testppd.c17
-rw-r--r--cups/testpwg.c86
-rw-r--r--filter/commandtops.c26
-rw-r--r--filter/raster.c104
-rw-r--r--filter/testraster.c142
-rw-r--r--notifier/dbus.c2
-rw-r--r--ppdc/sample.drv5
-rw-r--r--scheduler/auth.c14
-rw-r--r--scheduler/conf.c2
-rw-r--r--scheduler/conf.h2
-rw-r--r--scheduler/cups-driverd.cxx27
-rw-r--r--scheduler/dirsvc.c2
-rw-r--r--scheduler/ipp.c46
-rw-r--r--scheduler/job.c72
-rw-r--r--scheduler/main.c1
-rw-r--r--scheduler/printers.c566
-rw-r--r--scheduler/printers.h12
-rwxr-xr-xtest/run-stp-tests.sh15
49 files changed, 3451 insertions, 3352 deletions
diff --git a/CHANGES-1.4.txt b/CHANGES-1.4.txt
index 3259a2970..612a85a01 100644
--- a/CHANGES-1.4.txt
+++ b/CHANGES-1.4.txt
@@ -9,6 +9,15 @@ CHANGES IN CUPS V1.4.7
STR #3755, STR #3769, STR #3783)
- Configure script fixes (STR #3659, STR #3691)
- Compilation fixes (STR #3718, STR #3771, STR #3774)
+ - Fixed an issue when reading compressed CUPS raster streams (STR #3812)
+ - Fixed an issue with PostScript printer auto-configuration (STR #3443)
+ - Fixed some compatibility issues with the libusb-based USB backend
+ (STR #3799)
+ - The network backends no longer try to collect SNMP supply and status
+ information for raw queues (STR #3809)
+ - The DBUS notifier did not report job state changes (STR #3805)
+ - The scheduler did not always report that the "normal" print-quality
+ value was supported (STR #3803)
- The gziptoany filter did not report the correct error if it was unable
to write the uncompressed document to the next filter or backend in
the chain (STR #3797)
diff --git a/CHANGES.txt b/CHANGES.txt
index 662d77602..a5c3bdd4b 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,8 +1,9 @@
-CHANGES.txt - 2011-02-21
+CHANGES.txt - 2011-03-07
------------------------
CHANGES IN CUPS V1.5b1
+ - Dropped support for the printer-state-history attribute (STR #3654)
- Added support for a new cupsIPPSupplies keyword in PPD files to allow
drivers to disable IPP supply level reporting.
- Added support for a new cupsFilter2 keyword in PPD files to allow for
diff --git a/backend/backend-private.h b/backend/backend-private.h
index 47f9b32ce..592b1e340 100644
--- a/backend/backend-private.h
+++ b/backend/backend-private.h
@@ -3,7 +3,7 @@
*
* Backend support definitions for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -309,7 +309,7 @@ extern int backendSNMPSupplies(int snmp_fd, http_addr_t *addr,
int *page_count,
int *printer_state);
extern int backendWaitLoop(int snmp_fd, http_addr_t *addr,
- _cups_sccb_t side_cb);
+ int use_bc, _cups_sccb_t side_cb);
# ifdef __cplusplus
diff --git a/backend/ipp.c b/backend/ipp.c
index fb172cd2d..1f5bb8e18 100644
--- a/backend/ipp.c
+++ b/backend/ipp.c
@@ -115,7 +115,7 @@ static ipp_t *new_request(ipp_op_t op, int version, const char *uri,
const char *user, const char *title,
int num_options, cups_option_t *options,
const char *compression, int copies,
- const char *format, _pwg_t *pwg,
+ const char *format, _ppd_cache_t *pc,
ipp_attribute_t *media_col_sup);
static const char *password_cb(const char *);
static void report_attr(ipp_attribute_t *attr);
@@ -167,7 +167,8 @@ main(int argc, /* I - Number of command-line args */
*supported; /* get-printer-attributes response */
time_t start_time; /* Time of first connect */
int contimeout; /* Connection timeout */
- int delay; /* Delay for retries... */
+ int delay, /* Delay for retries */
+ prev_delay; /* Previous delay */
const char *compression; /* Compression mode */
int waitjob, /* Wait for job complete? */
waitprinter; /* Wait for printer ready? */
@@ -197,7 +198,7 @@ main(int argc, /* I - Number of command-line args */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
int version; /* IPP version */
ppd_file_t *ppd; /* PPD file */
- _pwg_t *pwg; /* PWG<->PPD mapping data */
+ _ppd_cache_t *pc; /* PPD cache and mapping data */
/*
@@ -548,14 +549,14 @@ main(int argc, /* I - Number of command-line args */
*/
if (num_files == 0)
- if (!backendWaitLoop(snmp_fd, &(addrlist->addr), backendNetworkSideCB))
+ if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
return (CUPS_BACKEND_OK);
/*
* Try connecting to the remote server...
*/
- delay = 5;
+ delay = _cupsNextDelay(0, &prev_delay);
do
{
@@ -634,8 +635,7 @@ main(int argc, /* I - Number of command-line args */
sleep(delay);
- if (delay < 30)
- delay += 5;
+ delay = _cupsNextDelay(delay, &prev_delay);
}
else
{
@@ -759,8 +759,7 @@ main(int argc, /* I - Number of command-line args */
sleep(delay);
- if (delay < 30)
- delay += 5;
+ delay = _cupsNextDelay(delay, &prev_delay);
}
else if ((ipp_status == IPP_BAD_REQUEST ||
ipp_status == IPP_VERSION_NOT_SUPPORTED) && version > 10)
@@ -946,7 +945,7 @@ main(int argc, /* I - Number of command-line args */
{
copies_remaining = 1;
- if (argc < 7)
+ if (argc < 7 && !send_options)
copies = 1;
}
else
@@ -957,7 +956,7 @@ main(int argc, /* I - Number of command-line args */
*/
options = NULL;
- pwg = NULL;
+ pc = NULL;
if (send_options)
{
@@ -970,7 +969,7 @@ main(int argc, /* I - Number of command-line args */
*/
ppd = ppdOpenFile(getenv("PPD"));
- pwg = _pwgCreateWithPPD(ppd);
+ pc = _ppdCacheCreateWithPPD(ppd);
ppdClose(ppd);
}
@@ -1026,7 +1025,7 @@ main(int argc, /* I - Number of command-line args */
{
request = new_request(IPP_VALIDATE_JOB, version, uri, argv[2], argv[3],
num_options, options, compression,
- copies_sup ? copies : 1, document_format, pwg,
+ copies_sup ? copies : 1, document_format, pc,
media_col_sup);
ippDelete(cupsDoRequest(http, request, resource));
@@ -1102,7 +1101,7 @@ main(int argc, /* I - Number of command-line args */
request = new_request(num_files > 1 ? IPP_CREATE_JOB : IPP_PRINT_JOB,
version, uri, argv[2], argv[3], num_options, options,
compression, copies_sup ? copies : 1, document_format,
- pwg, media_col_sup);
+ pc, media_col_sup);
/*
* Do the request...
@@ -1299,7 +1298,7 @@ main(int argc, /* I - Number of command-line args */
_cupsLangPrintFilter(stderr, "INFO", _("Waiting for job to complete."));
- for (delay = 1; !job_canceled;)
+ for (delay = _cupsNextDelay(0, &prev_delay); !job_canceled;)
{
/*
* Check for side-channel requests...
@@ -1333,6 +1332,7 @@ main(int argc, /* I - Number of command-line args */
* Do the request...
*/
+ httpReconnect(http);
response = cupsDoRequest(http, request, resource);
ipp_status = cupsLastError();
@@ -1400,23 +1400,13 @@ main(int argc, /* I - Number of command-line args */
ippDelete(response);
-#if 0
/*
- * Check the printer state and report it if necessary...
- */
-
- check_printer_state(http, uri, resource, argv[2], version, job_id);
-#endif /* 0 */
-
- /*
- * Wait 1-10 seconds before polling again...
+ * Wait before polling again...
*/
sleep(delay);
- delay ++;
- if (delay > 10)
- delay = 1;
+ delay = _cupsNextDelay(delay, &prev_delay);
}
}
@@ -1458,7 +1448,7 @@ main(int argc, /* I - Number of command-line args */
cleanup:
cupsFreeOptions(num_options, options);
- _pwgDestroy(pwg);
+ _ppdCacheDestroy(pc);
httpClose(http);
@@ -1480,7 +1470,9 @@ main(int argc, /* I - Number of command-line args */
* Return the queue status...
*/
- fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
+ if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
+ ipp_status <= IPP_OK_CONFLICT)
+ fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN)
return (CUPS_BACKEND_AUTH_REQUIRED);
@@ -1679,8 +1671,7 @@ monitor_printer(
*response; /* IPP response */
ipp_attribute_t *attr; /* Attribute in response */
int delay, /* Current delay */
- prev_delay, /* Previous delay */
- temp_delay; /* Temporary delay value */
+ prev_delay; /* Previous delay */
/*
@@ -1695,8 +1686,7 @@ monitor_printer(
* Loop until the job is canceled, aborted, or completed.
*/
- delay = 1;
- prev_delay = 0;
+ delay = _cupsNextDelay(0, &prev_delay);
while (monitor->job_state < IPP_JOB_CANCELED && !job_canceled)
{
@@ -1762,15 +1752,12 @@ monitor_printer(
}
/*
- * Sleep for N seconds, and then update the next sleep time using a
- * Fibonacci series (1 1 2 3 5 8)...
+ * Sleep for N seconds...
*/
sleep(delay);
- temp_delay = delay;
- delay = (delay + prev_delay) % 12;
- prev_delay = delay < temp_delay ? 0 : temp_delay;
+ delay = _cupsNextDelay(delay, &prev_delay);
}
/*
@@ -1799,7 +1786,7 @@ new_request(
const char *compression, /* I - compression value or NULL */
int copies, /* I - copies value or 0 */
const char *format, /* I - documet-format value or NULL */
- _pwg_t *pwg, /* I - PWG<->PPD mapping data */
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
ipp_attribute_t *media_col_sup) /* I - media-col-supported values */
{
int i; /* Looping var */
@@ -1869,7 +1856,7 @@ new_request(
if (num_options > 0)
{
- if (pwg)
+ if (pc)
{
/*
* Send standard IPP attributes...
@@ -1878,7 +1865,7 @@ new_request(
if ((keyword = cupsGetOption("PageSize", num_options, options)) == NULL)
keyword = cupsGetOption("media", num_options, options);
- if ((size = _pwgGetSize(pwg, keyword)) != NULL)
+ if ((size = _ppdCacheGetSize(pc, keyword)) != NULL)
{
/*
* Add a media-col value...
@@ -1893,11 +1880,12 @@ new_request(
media_col = ippNew();
ippAddCollection(media_col, IPP_TAG_ZERO, "media-size", media_size);
- media_source = _pwgGetSource(pwg, cupsGetOption("InputSlot",
- num_options,
- options));
- media_type = _pwgGetType(pwg, cupsGetOption("MediaType",
- num_options, options));
+ media_source = _ppdCacheGetSource(pc, cupsGetOption("InputSlot",
+ num_options,
+ options));
+ media_type = _ppdCacheGetType(pc, cupsGetOption("MediaType",
+ num_options,
+ options));
for (i = 0; i < media_col_sup->num_values; i ++)
{
@@ -1932,8 +1920,8 @@ new_request(
if ((keyword = cupsGetOption("output-bin", num_options,
options)) == NULL)
- keyword = _pwgGetBin(pwg, cupsGetOption("OutputBin", num_options,
- options));
+ keyword = _ppdCacheGetBin(pc, cupsGetOption("OutputBin", num_options,
+ options));
if (keyword)
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-bin",
@@ -1975,17 +1963,17 @@ new_request(
if ((keyword = cupsGetOption("sides", num_options, options)) != NULL)
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
NULL, keyword);
- else if (pwg->sides_option &&
- (keyword = cupsGetOption(pwg->sides_option, num_options,
+ else if (pc->sides_option &&
+ (keyword = cupsGetOption(pc->sides_option, num_options,
options)) != NULL)
{
- if (!strcasecmp(keyword, pwg->sides_1sided))
+ if (!strcasecmp(keyword, pc->sides_1sided))
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
NULL, "one-sided");
- else if (!strcasecmp(keyword, pwg->sides_2sided_long))
+ else if (!strcasecmp(keyword, pc->sides_2sided_long))
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
NULL, "two-sided-long-edge");
- if (!strcasecmp(keyword, pwg->sides_2sided_short))
+ if (!strcasecmp(keyword, pc->sides_2sided_short))
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
NULL, "two-sided-short-edge");
}
diff --git a/backend/lpd.c b/backend/lpd.c
index 702c0fb9d..af690adb0 100644
--- a/backend/lpd.c
+++ b/backend/lpd.c
@@ -431,7 +431,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
*/
if (argc == 6)
- if (!backendWaitLoop(snmp_fd, &(addrlist->addr), backendNetworkSideCB))
+ if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
return (CUPS_BACKEND_OK);
/*
diff --git a/backend/network.c b/backend/network.c
index 0a4908a77..fb42f791f 100644
--- a/backend/network.c
+++ b/backend/network.c
@@ -1,9 +1,9 @@
/*
* "$Id$"
*
- * Common network APIs for the Common UNIX Printing System (CUPS).
+ * Common backend network APIs for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 2006-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -279,6 +279,12 @@ backendNetworkSideCB(
break;
}
+ case CUPS_SC_CMD_GET_CONNECTED :
+ status = CUPS_SC_STATUS_OK;
+ data[0] = device_fd != -1;
+ datalen = 1;
+ break;
+
default :
status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
datalen = 0;
diff --git a/backend/pseudo b/backend/pseudo
new file mode 100644
index 000000000..3a82a522a
--- /dev/null
+++ b/backend/pseudo
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Psuedo-backend for CUPS testing purposes.
+#
+# Copyright 2011 by Apple Inc.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Apple Inc. and are protected by Federal copyright
+# law. Distribution and use rights are outlined in the file "LICENSE.txt"
+# which should have been included with this file. If this file is
+# file is missing or damaged, see the license at "http://www.cups.org/".
+#
+# This file is subject to the Apple OS-Developed Software exception.
+#
+
+if test $# = 0; then
+ echo 'direct pseudo:///deskjet "HP DeskJet" "HP DeskJet (pseudo)" "MFG:HP;MDL:DeskJet;CMD:PCL;" "Nowhere"'
+ echo 'direct pseudo:///laserjet "HP LaserJet" "HP LaserJet (pseudo)" "MFG:HP;MDL:LaserJet;CMD:PCL;" "Nowhere"'
+ exit 0
+fi
+
+cat $6 >/dev/null
+sleep 5
+exit 0
+
+#
+# End of "$Id$".
+#
diff --git a/backend/runloop.c b/backend/runloop.c
index fbc5a467f..43b839996 100644
--- a/backend/runloop.c
+++ b/backend/runloop.c
@@ -431,6 +431,7 @@ int /* O - 1 if data is ready, 0 if not */
backendWaitLoop(
int snmp_fd, /* I - SNMP socket or -1 if none */
http_addr_t *addr, /* I - Address of device */
+ int use_bc, /* I - Use back-channel? */
_cups_sccb_t side_cb) /* I - Side-channel callback */
{
fd_set input; /* Input set for reading */
@@ -494,7 +495,7 @@ backendWaitLoop(
* loop since it may have read from print_fd...
*/
- if ((*side_cb)(0, -1, snmp_fd, addr, 0))
+ if ((*side_cb)(0, -1, snmp_fd, addr, use_bc))
side_cb = NULL;
continue;
}
diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c
index 990e54982..d6d8ae1b9 100644
--- a/backend/snmp-supplies.c
+++ b/backend/snmp-supplies.c
@@ -474,9 +474,9 @@ backend_init_supplies(
* See if we should be getting supply levels via SNMP...
*/
- if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL &&
- (ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
- ppdattr->value && strcasecmp(ppdattr->value, "true"))
+ if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL ||
+ ((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
+ ppdattr->value && strcasecmp(ppdattr->value, "true")))
{
ppdClose(ppd);
return;
diff --git a/backend/socket.c b/backend/socket.c
index 7d9196b98..414955948 100644
--- a/backend/socket.c
+++ b/backend/socket.c
@@ -286,8 +286,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0)
{
- have_supplies = !backendSNMPSupplies(snmp_fd, &(addr->addr), &start_count,
- NULL);
+ have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr),
+ &start_count, NULL);
}
else
have_supplies = start_count = 0;
@@ -297,7 +297,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
*/
if (print_fd == 0)
- if (!backendWaitLoop(snmp_fd, &(addrlist->addr), backendNetworkSideCB))
+ if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 1, backendNetworkSideCB))
return (CUPS_BACKEND_OK);
/*
@@ -393,7 +393,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
#ifdef AF_INET6
if (addr->addr.addr.sa_family == AF_INET6)
- fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n",
+ fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n",
httpAddrString(&addr->addr, addrname, sizeof(addrname)),
ntohs(addr->addr.ipv6.sin6_port));
else
@@ -419,8 +419,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
lseek(print_fd, 0, SEEK_SET);
}
- tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addr->addr), 1, 0,
- backendNetworkSideCB);
+ tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1,
+ 0, backendNetworkSideCB);
if (print_fd != 0 && tbytes >= 0)
_cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
@@ -454,8 +454,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Collect the final page count as needed...
*/
- if (have_supplies &&
- !backendSNMPSupplies(snmp_fd, &(addr->addr), &page_count, NULL) &&
+ if (have_supplies &&
+ !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &page_count, NULL) &&
page_count > start_count)
fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c
index 2c2d73e56..08af5997a 100644
--- a/backend/usb-libusb.c
+++ b/backend/usb-libusb.c
@@ -411,7 +411,7 @@ get_device_id(usb_printer_t *printer, /* I - Printer */
if (usb_control_msg(printer->handle,
USB_TYPE_CLASS | USB_ENDPOINT_IN | USB_RECIP_INTERFACE,
- 0, printer->conf, printer->iface,
+ 0, printer->conf, (printer->iface << 8) | printer->altset,
buffer, bufsize, 5000) < 0)
{
*buffer = '\0';
@@ -675,6 +675,7 @@ open_device(usb_printer_t *printer, /* I - Printer */
goto error;
}
+#if 0 /* STR #3801: Claiming interface 0 causes problems with some printers */
if (number != 0)
while (usb_claim_interface(printer->handle, 0) < 0)
{
@@ -685,6 +686,7 @@ open_device(usb_printer_t *printer, /* I - Printer */
goto error;
}
+#endif /* 0 */
/*
* Set alternate setting...
diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c
index c38352a6b..05fa23b38 100644
--- a/cgi-bin/admin.c
+++ b/cgi-bin/admin.c
@@ -1026,7 +1026,7 @@ do_am_printer(http_t *http, /* I - HTTP connection */
fputs("DEBUG: Getting list of devices...\n", stderr);
current_device = 0;
- if (cupsGetDevices(http, 30, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE,
+ if (cupsGetDevices(http, 5, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE,
(cups_device_cb_t)choose_device_cb,
(void *)title) == IPP_OK)
{
diff --git a/cups/Makefile b/cups/Makefile
index 5ce000916..adc5581fe 100644
--- a/cups/Makefile
+++ b/cups/Makefile
@@ -56,9 +56,8 @@ LIBOBJS = \
options.o \
page.o \
ppd.o \
- pwg-file.o \
+ ppd-cache.o \
pwg-media.o \
- pwg-ppd.o \
request.o \
sidechannel.o \
snmp.o \
diff --git a/cups/auth.c b/cups/auth.c
index 4d7facf4e..f9054d222 100644
--- a/cups/auth.c
+++ b/cups/auth.c
@@ -3,7 +3,7 @@
*
* Authentication functions for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* This file contains Kerberos support code, copyright 2006 by
@@ -122,10 +122,10 @@ cupsDoAuthentication(
{
DEBUG_printf(("2cupsDoAuthentication: authstring=\"%s\"",
http->authstring));
-
+
if (http->status == HTTP_UNAUTHORIZED)
http->digest_tries ++;
-
+
return (0);
}
else if (localauth == -1)
@@ -140,7 +140,8 @@ cupsDoAuthentication(
*/
if ((http->digest_tries > 1 || !http->userpass[0]) &&
- strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
+ (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) ||
+ !strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6)))
{
/*
* Nope - get a new password from the user...
@@ -185,171 +186,22 @@ cupsDoAuthentication(
* Got a password; encode it for the server...
*/
+#ifdef HAVE_GSSAPI
if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
{
-#ifdef HAVE_GSSAPI
/*
* Kerberos authentication...
*/
- OM_uint32 minor_status, /* Minor status code */
- major_status; /* Major status code */
- gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER,
- /* Output token */
- input_token = GSS_C_EMPTY_BUFFER;
- /* Input token */
- char *gss_service_name;
- /* GSS service name */
-# ifdef USE_SPNEGO
- const char *authorization;
- /* Pointer into Authorization string */
-# endif /* USE_SPNEGO */
-
-
-# ifdef __APPLE__
- /*
- * If the weak-linked GSSAPI/Kerberos library is not present, don't try
- * to use it...
- */
-
- if (gss_init_sec_context == NULL)
- {
- DEBUG_puts("1cupsDoAuthentication: Weak-linked GSSAPI/Kerberos framework "
- "is not present");
- http->status = HTTP_AUTHORIZATION_CANCELED;
-
- return (-1);
- }
-# endif /* __APPLE__ */
-
- if (http->gssname == GSS_C_NO_NAME)
- {
- if ((gss_service_name = getenv("CUPS_GSSSERVICENAME")) == NULL)
- gss_service_name = CUPS_DEFAULT_GSSSERVICENAME;
- else
- DEBUG_puts("2cupsDoAuthentication: GSS service name set via "
- "environment variable");
-
- http->gssname = cups_get_gssname(http, gss_service_name);
- }
-
-# ifdef USE_SPNEGO /* We don't implement SPNEGO just yet... */
- /*
- * Find the start of the Kerberos input token...
- */
-
- authorization = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
-
- authorization += 9;
- while (*authorization && _cups_isspace(*authorization))
- authorization ++;
-
- if (*authorization)
- {
- /*
- * Decode the authorization string to get the input token...
- */
-
- int len = strlen(authorization);
-
- input_token.value = malloc(len);
- input_token.value = httpDecode64_2(input_token.value, &len,
- authorization);
- input_token.length = len;
-
-# ifdef DEBUG
- {
- char *ptr = (char *)input_token.value;
- int left = len;
-
- fputs("input_token=", stdout);
- while (left > 0)
- {
- if (*ptr < ' ')
- printf("\\%03o", *ptr & 255);
- else
- putchar(*ptr);
- ptr ++;
- left --;
- }
- putchar('\n');
- }
-# endif /* DEBUG */
- }
-# endif /* USE_SPNEGO */
-
- if (http->gssctx != GSS_C_NO_CONTEXT)
- {
- gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
- http->gssctx = GSS_C_NO_CONTEXT;
- }
-
- major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
- &http->gssctx,
- http->gssname, http->gssmech,
-#ifdef GSS_C_DELEG_POLICY_FLAG
- GSS_C_DELEG_POLICY_FLAG |
-#endif /* GSS_C_DELEG_POLICY_FLAG */
- GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
- GSS_C_INDEFINITE,
- GSS_C_NO_CHANNEL_BINDINGS,
- &input_token, &http->gssmech,
- &output_token, NULL, NULL);
-
- if (input_token.value)
- free(input_token.value);
-
- if (GSS_ERROR(major_status))
+ if (_cupsSetNegotiateAuthString(http))
{
- cups_gss_printf(major_status, minor_status,
- "cupsDoAuthentication: Unable to initialize security "
- "context");
http->status = HTTP_AUTHORIZATION_CANCELED;
-
return (-1);
}
-
- if (major_status == GSS_S_CONTINUE_NEEDED)
- cups_gss_printf(major_status, minor_status,
- "cupsDoAuthentication: Continuation needed!");
-
- if (output_token.length > 0 && output_token.length <= 65536)
- {
- /*
- * Allocate the authorization string since Windows KDCs can have
- * arbitrarily large credentials...
- */
-
- int authsize = 10 + /* "Negotiate " */
- output_token.length * 4 / 3 + 1 + /* Base64 */
- 1; /* nul */
-
- httpSetAuthString(http, NULL, NULL);
-
- if ((http->authstring = malloc(authsize)) == NULL)
- {
- http->authstring = http->_authstring;
- authsize = sizeof(http->_authstring);
- }
-
- strcpy(http->authstring, "Negotiate ");
- httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value,
- output_token.length);
-
- gss_release_buffer(&minor_status, &output_token);
- }
- else
- {
- DEBUG_printf(("1cupsDoAuthentication: Kerberos credentials too large - "
- "%d bytes!", (int)output_token.length));
- http->status = HTTP_AUTHORIZATION_CANCELED;
- gss_release_buffer(&minor_status, &output_token);
-
- return (-1);
- }
-#endif /* HAVE_GSSAPI */
}
- else if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6))
+ else
+#endif /* HAVE_GSSAPI */
+ if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5))
{
/*
* Basic authentication...
@@ -362,7 +214,7 @@ cupsDoAuthentication(
(int)strlen(http->userpass));
httpSetAuthString(http, "Basic", encode);
}
- else
+ else if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6))
{
/*
* Digest authentication...
@@ -382,6 +234,13 @@ cupsDoAuthentication(
"response=\"%s\"", cupsUser(), realm, nonce, resource, encode);
httpSetAuthString(http, "Digest", digest);
}
+ else
+ {
+ DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"",
+ http->fields[HTTP_FIELD_WWW_AUTHENTICATE]));
+ http->status = HTTP_AUTHORIZATION_CANCELED;
+ return (-1);
+ }
DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring));
@@ -391,6 +250,114 @@ cupsDoAuthentication(
#ifdef HAVE_GSSAPI
/*
+ * '_cupsSetNegotiateAuthString()' - Set the Kerberos authentication string.
+ */
+
+int /* O - 0 on success, -1 on error */
+_cupsSetNegotiateAuthString(
+ http_t *http) /* I - Connection to server */
+{
+ OM_uint32 minor_status, /* Minor status code */
+ major_status; /* Major status code */
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+ /* Output token */
+ char *gss_service_name; /* GSS service name */
+
+
+# ifdef __APPLE__
+ /*
+ * If the weak-linked GSSAPI/Kerberos library is not present, don't try
+ * to use it...
+ */
+
+ if (gss_init_sec_context == NULL)
+ {
+ DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos "
+ "framework is not present");
+ return (-1);
+ }
+# endif /* __APPLE__ */
+
+ if (http->gssname == GSS_C_NO_NAME)
+ {
+ if ((gss_service_name = getenv("CUPS_GSSSERVICENAME")) == NULL)
+ gss_service_name = CUPS_DEFAULT_GSSSERVICENAME;
+ else
+ DEBUG_puts("2_cupsSetNegotiateAuthString: GSS service name set via "
+ "environment variable");
+
+ http->gssname = cups_get_gssname(http, gss_service_name);
+ }
+
+ if (http->gssctx != GSS_C_NO_CONTEXT)
+ {
+ gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
+ http->gssctx = GSS_C_NO_CONTEXT;
+ }
+
+ major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
+ &http->gssctx,
+ http->gssname, http->gssmech,
+#ifdef GSS_C_DELEG_POLICY_FLAG
+ GSS_C_DELEG_POLICY_FLAG |
+#endif /* GSS_C_DELEG_POLICY_FLAG */
+ GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
+ GSS_C_INDEFINITE,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ GSS_C_NO_BUFFER, &http->gssmech,
+ &output_token, NULL, NULL);
+
+ if (GSS_ERROR(major_status))
+ {
+ cups_gss_printf(major_status, minor_status,
+ "_cupsSetNegotiateAuthString: Unable to initialize "
+ "security context");
+ return (-1);
+ }
+
+ if (major_status == GSS_S_CONTINUE_NEEDED)
+ cups_gss_printf(major_status, minor_status,
+ "_cupsSetNegotiateAuthString: Continuation needed!");
+
+ if (output_token.length > 0 && output_token.length <= 65536)
+ {
+ /*
+ * Allocate the authorization string since Windows KDCs can have
+ * arbitrarily large credentials...
+ */
+
+ int authsize = 10 + /* "Negotiate " */
+ output_token.length * 4 / 3 + 1 + /* Base64 */
+ 1; /* nul */
+
+ httpSetAuthString(http, NULL, NULL);
+
+ if ((http->authstring = malloc(authsize)) == NULL)
+ {
+ http->authstring = http->_authstring;
+ authsize = sizeof(http->_authstring);
+ }
+
+ strcpy(http->authstring, "Negotiate ");
+ httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value,
+ output_token.length);
+
+ gss_release_buffer(&minor_status, &output_token);
+ }
+ else
+ {
+ DEBUG_printf(("1_cupsSetNegotiateAuthString: Kerberos credentials too "
+ "large - %d bytes!", (int)output_token.length));
+ gss_release_buffer(&minor_status, &output_token);
+
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/*
* 'cups_get_gssname()' - Get CUPS service credentials for authentication.
*/
@@ -540,7 +507,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
/*
* Delete any previous authorization reference...
*/
-
+
if (http->auth_ref)
{
AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
@@ -548,10 +515,10 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
}
if (!getenv("GATEWAY_INTERFACE") &&
- httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
+ httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
auth_key, sizeof(auth_key)))
{
- status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
+ status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
kAuthorizationFlagDefaults, &http->auth_ref);
if (status != errAuthorizationSuccess)
{
@@ -568,13 +535,13 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
auth_rights.count = 1;
auth_rights.items = &auth_right;
- auth_flags = kAuthorizationFlagDefaults |
+ auth_flags = kAuthorizationFlagDefaults |
kAuthorizationFlagPreAuthorize |
- kAuthorizationFlagInteractionAllowed |
+ kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagExtendRights;
- status = AuthorizationCopyRights(http->auth_ref, &auth_rights,
- kAuthorizationEmptyEnvironment,
+ status = AuthorizationCopyRights(http->auth_ref, &auth_rights,
+ kAuthorizationEmptyEnvironment,
auth_flags, NULL);
if (status == errAuthorizationSuccess)
status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn);
@@ -585,7 +552,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
* Set the authorization string and return...
*/
- httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn,
+ httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn,
sizeof(auth_extrn));
httpSetAuthString(http, "AuthRef", buffer);
@@ -613,11 +580,14 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
* information...
*/
-# ifdef HAVE_GSSAPI
- if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) &&
-# else
if (
+# ifdef HAVE_GSSAPI
+ strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) &&
# endif /* HAVE_GSSAPI */
+# ifdef HAVE_AUTHORIZATION_H
+ !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
+ auth_key, sizeof(auth_key)) &&
+# endif /* HAVE_AUTHORIZATION_H */
http->hostaddr->addr.sa_family == AF_LOCAL &&
!getenv("GATEWAY_INTERFACE")) /* Not via CGI programs... */
{
diff --git a/cups/cups-private.h b/cups/cups-private.h
index d6a8bbba9..6e1677f88 100644
--- a/cups/cups-private.h
+++ b/cups/cups-private.h
@@ -1,5 +1,5 @@
/*
- * "$Id$"
+ * "$Id: cups-private.h 9596 2011-03-11 18:26:36Z mike $"
*
* Private definitions for CUPS.
*
@@ -161,8 +161,10 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/
# ifdef __APPLE__
extern CFStringRef _cupsAppleCopyDefaultPaperID(void);
+extern CFStringRef _cupsAppleCopyDefaultPrinter(void);
extern int _cupsAppleGetUseLastPrinter(void);
extern void _cupsAppleSetDefaultPaperID(CFStringRef name);
+extern void _cupsAppleSetDefaultPrinter(CFStringRef name);
extern void _cupsAppleSetUseLastPrinter(int uselast);
# endif /* __APPLE__ */
@@ -175,10 +177,14 @@ extern const char *_cupsGetPassword(const char *prompt);
extern void _cupsGlobalLock(void);
extern _cups_globals_t *_cupsGlobals(void);
extern void _cupsGlobalUnlock(void);
+extern int _cupsNextDelay(int current, int *previous);
extern void _cupsSetDefaults(void);
extern void _cupsSetError(ipp_status_t status, const char *message,
int localize);
extern void _cupsSetHTTPError(http_status_t status);
+# ifdef HAVE_GSSAPI
+extern int _cupsSetNegotiateAuthString(http_t *http);
+# endif /* HAVE_GSSAPI */
extern char *_cupsUserDefault(char *name, size_t namesize);
@@ -192,5 +198,5 @@ extern char *_cupsUserDefault(char *name, size_t namesize);
#endif /* !_CUPS_CUPS_PRIVATE_H_ */
/*
- * End of "$Id$".
+ * End of "$Id: cups-private.h 9596 2011-03-11 18:26:36Z mike $".
*/
diff --git a/cups/dest.c b/cups/dest.c
index 1406c3420..bd738bf00 100644
--- a/cups/dest.c
+++ b/cups/dest.c
@@ -1,5 +1,5 @@
/*
- * "$Id: dest.c 7946 2008-09-16 23:27:54Z mike $"
+ * "$Id: dest.c 9568 2011-02-25 06:13:56Z mike $"
*
* User-defined destination (and option) support for CUPS.
*
@@ -19,8 +19,10 @@
* cupsAddDest() - Add a destination to the list of
* destinations.
* _cupsAppleCopyDefaultPaperID() - Get the default paper ID.
+ * _cupsAppleCopyDefaultPrinter() - Get the default printer at this location.
* _cupsAppleGetUseLastPrinter() - Get whether to use the last used printer.
* _cupsAppleSetDefaultPaperID() - Set the default paper id.
+ * _cupsAppleSetDefaultPrinter() - Set the default printer for this location.
* _cupsAppleSetUseLastPrinter() - Set whether to use the last used printer.
* cupsFreeDests() - Free the memory used by the list of
* destinations.
@@ -46,7 +48,6 @@
* location.
* appleGetPaperSize() - Get the default paper size.
* appleGetPrinter() - Get a printer from the history array.
- * appleSetDefault() - Set the default printer for this location.
* cups_add_dest() - Add a destination to the array.
* cups_compare_dests() - Compare two destinations.
* cups_find_dest() - Find a destination using a binary search.
@@ -70,13 +71,12 @@
#ifdef __APPLE__
# include <SystemConfiguration/SystemConfiguration.h>
-# define kDefaultPaperIDKey CFSTR("DefaultPaperID")
-# define kLocationHistoryArrayKey CFSTR("kLocationHistoryArrayKeyTMP")
-# define kLocationNetworkKey CFSTR("kLocationNetworkKey")
-# define kLocationPrinterIDKey CFSTR("kLocationPrinterIDKey")
-# define kPMPrintingPreferences CFSTR("com.apple.print.PrintingPrefs")
-# define kCUPSPrintingPreferences CFSTR("org.cups.PrintingPrefs")
-# define kUseLastPrinterAsCurrentPrinterKey CFSTR("UseLastPrinterAsCurrentPrinter")
+# define kCUPSPrintingPrefs CFSTR("org.cups.PrintingPrefs")
+# define kDefaultPaperIDKey CFSTR("DefaultPaperID")
+# define kLastUsedPrintersKey CFSTR("LastUsedPrinters")
+# define kLocationNetworkKey CFSTR("Network")
+# define kLocationPrinterIDKey CFSTR("PrinterID")
+# define kUseLastPrinter CFSTR("UseLastPrinter")
#endif /* __APPLE__ */
@@ -90,7 +90,6 @@ static CFStringRef appleCopyNetwork(void);
static char *appleGetPaperSize(char *name, int namesize);
static CFStringRef appleGetPrinter(CFArrayRef locations, CFStringRef network,
CFIndex *locindex);
-static void appleSetDefault(const char *name);
#endif /* __APPLE__ */
static cups_dest_t *cups_add_dest(const char *name, const char *instance,
int *num_dests, cups_dest_t **dests);
@@ -187,17 +186,79 @@ cupsAddDest(const char *name, /* I - Destination name */
CFStringRef /* O - Default paper ID */
_cupsAppleCopyDefaultPaperID(void)
{
- CFStringRef paper; /* Default paper ID */
+ return (CFPreferencesCopyAppValue(kDefaultPaperIDKey,
+ kCUPSPrintingPrefs));
+}
+
+
+/*
+ * '_cupsAppleCopyDefaultPrinter()' - Get the default printer at this location.
+ */
+
+CFStringRef /* O - Default printer name */
+_cupsAppleCopyDefaultPrinter(void)
+{
+ CFStringRef network; /* Network location */
+ CFArrayRef locations; /* Location array */
+ CFStringRef locprinter; /* Current printer */
- paper = CFPreferencesCopyAppValue(kDefaultPaperIDKey,
- kCUPSPrintingPreferences);
+ /*
+ * Use location-based defaults only if "use last printer" is selected in the
+ * system preferences...
+ */
- if (!paper)
- paper = CFPreferencesCopyAppValue(kDefaultPaperIDKey,
- kPMPrintingPreferences);
+ if (!_cupsAppleGetUseLastPrinter())
+ {
+ DEBUG_puts("1_cupsAppleCopyDefaultPrinter: Not using last printer as "
+ "default.");
+ return (NULL);
+ }
- return (paper);
+ /*
+ * Get the current location...
+ */
+
+ if ((network = appleCopyNetwork()) == NULL)
+ {
+ DEBUG_puts("1_cupsAppleCopyDefaultPrinter: Unable to get current "
+ "network.");
+ return (NULL);
+ }
+
+//# ifdef DEBUG
+// CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8);
+// DEBUG_printf(("2_cupsUserDefault: network=\"%s\"", name));
+//# endif /* DEBUG */
+
+ /*
+ * Lookup the network in the preferences...
+ */
+
+ if ((locations = appleCopyLocations()) == NULL)
+ {
+ /*
+ * Missing or bad location array, so no location-based default...
+ */
+
+ DEBUG_puts("1_cupsAppleCopyDefaultPrinter: Missing or bad last used "
+ "printer array.");
+
+ CFRelease(network);
+
+ return (NULL);
+ }
+
+ DEBUG_printf(("1_cupsAppleCopyDefaultPrinter: Got locations, %d entries.",
+ (int)CFArrayGetCount(locations)));
+
+ if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL)
+ CFRetain(locprinter);
+
+ CFRelease(network);
+ CFRelease(locations);
+
+ return (locprinter);
}
@@ -215,14 +276,10 @@ _cupsAppleGetUseLastPrinter(void)
if (getenv("CUPS_DISABLE_APPLE_DEFAULT"))
return (0);
- uselast = CFPreferencesGetAppBooleanValue(kUseLastPrinterAsCurrentPrinterKey,
- kCUPSPrintingPreferences,
+ uselast = CFPreferencesGetAppBooleanValue(kUseLastPrinter,
+ kCUPSPrintingPrefs,
&uselast_set);
if (!uselast_set)
- uselast = CFPreferencesGetAppBooleanValue(kUseLastPrinterAsCurrentPrinterKey,
- kPMPrintingPreferences,
- &uselast_set);
- if (!uselast_set)
return (1);
else
return (uselast);
@@ -237,7 +294,110 @@ void
_cupsAppleSetDefaultPaperID(
CFStringRef name) /* I - New paper ID */
{
- CFPreferencesSetAppValue(kDefaultPaperIDKey, name, kCUPSPrintingPreferences);
+ CFPreferencesSetAppValue(kDefaultPaperIDKey, name, kCUPSPrintingPrefs);
+ CFPreferencesAppSynchronize(kCUPSPrintingPrefs);
+ notify_post("com.apple.printerPrefsChange");
+}
+
+
+/*
+ * '_cupsAppleSetDefaultPrinter()' - Set the default printer for this location.
+ */
+
+void
+_cupsAppleSetDefaultPrinter(
+ CFStringRef name) /* I - Default printer/class name */
+{
+ CFStringRef network; /* Current network */
+ CFArrayRef locations; /* Old locations array */
+ CFIndex locindex; /* Index in locations array */
+ CFStringRef locprinter; /* Current printer */
+ CFMutableArrayRef newlocations; /* New locations array */
+ CFMutableDictionaryRef newlocation; /* New location */
+
+
+ /*
+ * Get the current location...
+ */
+
+ if ((network = appleCopyNetwork()) == NULL)
+ {
+ DEBUG_puts("1_cupsAppleSetDefaultPrinter: Unable to get current network...");
+ return;
+ }
+
+ /*
+ * Lookup the network in the preferences...
+ */
+
+ if ((locations = appleCopyLocations()) != NULL)
+ locprinter = appleGetPrinter(locations, network, &locindex);
+ else
+ {
+ locprinter = NULL;
+ locindex = -1;
+ }
+
+ if (!locprinter || CFStringCompare(locprinter, name, 0) != kCFCompareEqualTo)
+ {
+ /*
+ * Need to change the locations array...
+ */
+
+ if (locations)
+ {
+ newlocations = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0,
+ locations);
+
+ if (locprinter)
+ CFArrayRemoveValueAtIndex(newlocations, locindex);
+ }
+ else
+ newlocations = CFArrayCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeArrayCallBacks);
+
+ newlocation = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if (newlocation && newlocations)
+ {
+ /*
+ * Put the new location at the front of the array...
+ */
+
+ CFDictionaryAddValue(newlocation, kLocationNetworkKey, network);
+ CFDictionaryAddValue(newlocation, kLocationPrinterIDKey, name);
+ CFArrayInsertValueAtIndex(newlocations, 0, newlocation);
+
+ /*
+ * Limit the number of locations to 10...
+ */
+
+ while (CFArrayGetCount(newlocations) > 10)
+ CFArrayRemoveValueAtIndex(newlocations, 10);
+
+ /*
+ * Push the changes out...
+ */
+
+ CFPreferencesSetAppValue(kLastUsedPrintersKey, newlocations,
+ kCUPSPrintingPrefs);
+ CFPreferencesAppSynchronize(kCUPSPrintingPrefs);
+ notify_post("com.apple.printerPrefsChange");
+ }
+
+ if (newlocations)
+ CFRelease(newlocations);
+
+ if (newlocation)
+ CFRelease(newlocation);
+ }
+
+ if (locations)
+ CFRelease(locations);
+
+ CFRelease(network);
}
@@ -249,9 +409,11 @@ void
_cupsAppleSetUseLastPrinter(
int uselast) /* O - 1 to use last printer, 0 otherwise */
{
- CFPreferencesSetAppValue(kUseLastPrinterAsCurrentPrinterKey,
+ CFPreferencesSetAppValue(kUseLastPrinter,
uselast ? kCFBooleanTrue : kCFBooleanFalse,
- kCUPSPrintingPreferences);
+ kCUPSPrintingPrefs);
+ CFPreferencesAppSynchronize(kCUPSPrintingPrefs);
+ notify_post("com.apple.printerPrefsChange");
}
#endif /* __APPLE__ */
@@ -1254,7 +1416,18 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
*/
if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
- appleSetDefault(dest->name);
+ {
+ CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault,
+ dest->name,
+ kCFStringEncodingUTF8);
+ /* Default printer name */
+
+ if (name)
+ {
+ _cupsAppleSetDefaultPrinter(name);
+ CFRelease(name);
+ }
+ }
#endif /* __APPLE__ */
#ifdef HAVE_NOTIFY_POST
@@ -1281,9 +1454,7 @@ _cupsUserDefault(char *name, /* I - Name buffer */
{
const char *env; /* LPDEST or PRINTER env variable */
#ifdef __APPLE__
- CFStringRef network; /* Network location */
- CFArrayRef locations; /* Location array */
- CFStringRef locprinter; /* Current printer */
+ CFStringRef locprinter; /* Last printer as this location */
#endif /* __APPLE__ */
@@ -1303,59 +1474,15 @@ _cupsUserDefault(char *name, /* I - Name buffer */
* system preferences...
*/
- if (!_cupsAppleGetUseLastPrinter())
+ if ((locprinter = _cupsAppleCopyDefaultPrinter()) != NULL)
{
- DEBUG_puts("1_cupsUserDefault: Not using last printer as default...");
- name[0] = '\0';
- return (NULL);
- }
-
- /*
- * Get the current location...
- */
-
- if ((network = appleCopyNetwork()) == NULL)
- {
- DEBUG_puts("1_cupsUserDefault: Unable to get current network...");
- name[0] = '\0';
- return (NULL);
- }
-
-# ifdef DEBUG
- CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8);
- DEBUG_printf(("2_cupsUserDefault: network=\"%s\"", name));
-# endif /* DEBUG */
-
- /*
- * Lookup the network in the preferences...
- */
-
- if ((locations = appleCopyLocations()) == NULL)
- {
- /*
- * Missing or bad location array, so no location-based default...
- */
-
- DEBUG_puts("1_cupsUserDefault: Missing or bad location history array...");
-
- CFRelease(network);
-
- name[0] = '\0';
- return (NULL);
- }
-
- DEBUG_printf(("2_cupsUserDefault: Got location, %d entries...",
- (int)CFArrayGetCount(locations)));
-
- if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL)
CFStringGetCString(locprinter, name, namesize, kCFStringEncodingUTF8);
+ CFRelease(locprinter);
+ }
else
name[0] = '\0';
- CFRelease(network);
- CFRelease(locations);
-
- DEBUG_printf(("1_cupsUserDefault: Returning \"%s\"...", name));
+ DEBUG_printf(("1_cupsUserDefault: Returning \"%s\".", name));
return (*name ? name : NULL);
@@ -1385,8 +1512,8 @@ appleCopyLocations(void)
* Look up the location array in the preferences...
*/
- if ((locations = CFPreferencesCopyAppValue(kLocationHistoryArrayKey,
- kPMPrintingPreferences)) == NULL)
+ if ((locations = CFPreferencesCopyAppValue(kLastUsedPrintersKey,
+ kCUPSPrintingPrefs)) == NULL)
return (NULL);
if (CFGetTypeID(locations) != CFArrayGetTypeID())
@@ -1412,16 +1539,21 @@ appleCopyNetwork(void)
CFStringRef network = NULL; /* Current network ID */
- if ((dynamicStore = SCDynamicStoreCreate(NULL, CFSTR("Printing"), NULL,
+ if ((dynamicStore = SCDynamicStoreCreate(NULL, CFSTR("libcups"), NULL,
NULL)) != NULL)
{
+ /*
+ * First use the IPv6 router address, if available, since that will generally
+ * be a globally-unique link-local address.
+ */
+
if ((key = SCDynamicStoreKeyCreateNetworkGlobalEntity(
- NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4)) != NULL)
+ NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6)) != NULL)
{
if ((ip_dict = SCDynamicStoreCopyValue(dynamicStore, key)) != NULL)
{
if ((network = CFDictionaryGetValue(ip_dict,
- kSCPropNetIPv4Router)) != NULL)
+ kSCPropNetIPv6Router)) != NULL)
CFRetain(network);
CFRelease(ip_dict);
@@ -1430,6 +1562,29 @@ appleCopyNetwork(void)
CFRelease(key);
}
+ /*
+ * If that doesn't work, try the IPv4 router address. This isn't as unique
+ * and will likely be a 10.x.y.z or 192.168.y.z address...
+ */
+
+ if (!network)
+ {
+ if ((key = SCDynamicStoreKeyCreateNetworkGlobalEntity(
+ NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4)) != NULL)
+ {
+ if ((ip_dict = SCDynamicStoreCopyValue(dynamicStore, key)) != NULL)
+ {
+ if ((network = CFDictionaryGetValue(ip_dict,
+ kSCPropNetIPv4Router)) != NULL)
+ CFRetain(network);
+
+ CFRelease(ip_dict);
+ }
+
+ CFRelease(key);
+ }
+ }
+
CFRelease(dynamicStore);
}
@@ -1502,118 +1657,6 @@ appleGetPrinter(CFArrayRef locations, /* I - Location array */
return (NULL);
}
-
-
-/*
- * 'appleSetDefault()' - Set the default printer for this location.
- */
-
-static void
-appleSetDefault(const char *name) /* I - Default printer/class name */
-{
- CFStringRef network; /* Current network */
- CFArrayRef locations; /* Old locations array */
- CFIndex locindex; /* Index in locations array */
- CFStringRef locprinter; /* Current printer */
- CFMutableArrayRef newlocations; /* New locations array */
- CFMutableDictionaryRef newlocation; /* New location */
- CFStringRef newprinter; /* New printer */
-
-
- /*
- * Get the current location...
- */
-
- if ((network = appleCopyNetwork()) == NULL)
- {
- DEBUG_puts("1appleSetDefault: Unable to get current network...");
- return;
- }
-
- if ((newprinter = CFStringCreateWithCString(kCFAllocatorDefault, name,
- kCFStringEncodingUTF8)) == NULL)
- {
- CFRelease(network);
- return;
- }
-
- /*
- * Lookup the network in the preferences...
- */
-
- if ((locations = appleCopyLocations()) != NULL)
- locprinter = appleGetPrinter(locations, network, &locindex);
- else
- {
- locprinter = NULL;
- locindex = -1;
- }
-
- if (!locprinter ||
- CFStringCompare(locprinter, newprinter, 0) != kCFCompareEqualTo)
- {
- /*
- * Need to change the locations array...
- */
-
- if (locations)
- {
- newlocations = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0,
- locations);
-
- if (locprinter)
- CFArrayRemoveValueAtIndex(newlocations, locindex);
- }
- else
- newlocations = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks);
-
- newlocation = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
-
- if (newlocation && newlocations)
- {
- /*
- * Put the new location at the front of the array...
- */
-
- CFDictionaryAddValue(newlocation, kLocationNetworkKey, network);
- CFDictionaryAddValue(newlocation, kLocationPrinterIDKey, newprinter);
- CFArrayInsertValueAtIndex(newlocations, 0, newlocation);
-
- /*
- * Limit the number of locations to 10...
- */
-
- while (CFArrayGetCount(newlocations) > 10)
- CFArrayRemoveValueAtIndex(newlocations, 10);
-
- /*
- * Push the changes out...
- */
-
- CFPreferencesSetAppValue(kLocationHistoryArrayKey, newlocations,
- kPMPrintingPreferences);
- CFPreferencesAppSynchronize(kPMPrintingPreferences);
- notify_post("com.apple.printerPrefsChange");
- }
-
- if (newlocations)
- CFRelease(newlocations);
-
- if (newlocation)
- CFRelease(newlocation);
- }
-
- if (locations)
- CFRelease(locations);
-
- CFRelease(network);
- CFRelease(newprinter);
-}
-
-
#endif /* __APPLE__ */
@@ -2122,5 +2165,5 @@ cups_make_string(
/*
- * End of "$Id: dest.c 7946 2008-09-16 23:27:54Z mike $".
+ * End of "$Id: dest.c 9568 2011-02-25 06:13:56Z mike $".
*/
diff --git a/cups/file.c b/cups/file.c
index b788b7239..21e6fabb8 100644
--- a/cups/file.c
+++ b/cups/file.c
@@ -386,7 +386,7 @@ cupsFileFlush(cups_file_t *fp) /* I - CUPS file */
fp->ptr = fp->buf;
}
-
+
return (0);
}
@@ -406,7 +406,7 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */
if (!fp || (fp->mode != 'r' && fp->mode != 's'))
{
- DEBUG_puts("3cupsFileGetChar: Bad arguments!");
+ DEBUG_puts("5cupsFileGetChar: Bad arguments!");
return (-1);
}
@@ -417,7 +417,7 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */
if (fp->ptr >= fp->end)
if (cups_fill(fp) < 0)
{
- DEBUG_puts("3cupsFileGetChar: Unable to fill buffer!");
+ DEBUG_puts("5cupsFileGetChar: Unable to fill buffer!");
return (-1);
}
@@ -425,11 +425,11 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */
* Return the next character in the buffer...
*/
- DEBUG_printf(("3cupsFileGetChar: Returning %d...", *(fp->ptr) & 255));
+ DEBUG_printf(("5cupsFileGetChar: Returning %d...", *(fp->ptr) & 255));
fp->pos ++;
- DEBUG_printf(("4cupsFileGetChar: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos));
+ DEBUG_printf(("6cupsFileGetChar: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos));
return (*(fp->ptr)++ & 255);
}
diff --git a/cups/globals.c b/cups/globals.c
index 00f74c316..93985e0e9 100644
--- a/cups/globals.c
+++ b/cups/globals.c
@@ -314,8 +314,9 @@ cups_globals_free(_cups_globals_t *cg) /* I - Pointer to global data */
free(buffer);
}
- cupsArrayDelete(cg->pwg_size_lut);
cupsArrayDelete(cg->leg_size_lut);
+ cupsArrayDelete(cg->ppd_size_lut);
+ cupsArrayDelete(cg->pwg_size_lut);
httpClose(cg->http);
diff --git a/cups/libcups2.def b/cups/libcups2.def
index 35c382576..6e9581823 100644
--- a/cups/libcups2.def
+++ b/cups/libcups2.def
@@ -15,6 +15,7 @@ _cupsMD5Init
_cupsMessageFree
_cupsMessageLoad
_cupsMessageLookup
+_cupsNextDelay
_cupsSetError
_cupsSetLocale
_cupsStrAlloc
diff --git a/cups/libcups_s.exp b/cups/libcups_s.exp
index b86fbe759..80b347a75 100644
--- a/cups/libcups_s.exp
+++ b/cups/libcups_s.exp
@@ -13,6 +13,7 @@ _cupsMD5Init
_cupsMessageFree
_cupsMessageLoad
_cupsMessageLookup
+_cupsNextDelay
_cupsSetError
_cupsSetLocale
_cupsSNMPClose
diff --git a/cups/mark.c b/cups/mark.c
index 4dbd7555c..763b5310d 100644
--- a/cups/mark.c
+++ b/cups/mark.c
@@ -3,7 +3,7 @@
*
* Option marking routines for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -62,8 +62,9 @@ static void ppd_mark_option(ppd_file_t *ppd, const char *option,
* 'cupsMarkOptions()' - Mark command-line options in a PPD file.
*
* This function maps the IPP "finishings", "media", "mirror",
- * "multiple-document-handling", "output-bin", "printer-resolution", and
- * "sides" attributes to their corresponding PPD options and choices.
+ * "multiple-document-handling", "output-bin", "print-color-mode",
+ * "print-quality", "printer-resolution", and "sides" attributes to their
+ * corresponding PPD options and choices.
*/
int /* O - 1 if conflicts exist, 0 otherwise */
@@ -78,14 +79,14 @@ cupsMarkOptions(
const char *val, /* Pointer into value */
*media, /* media option */
*output_bin, /* output-bin option */
- *output_mode, /* output-mode option */
*page_size, /* PageSize option */
*ppd_keyword, /* PPD keyword */
+ *print_color_mode, /* print-color-mode option */
*print_quality, /* print-quality option */
*sides; /* sides option */
cups_option_t *optptr; /* Current option */
ppd_attr_t *attr; /* PPD attribute */
- _pwg_t *pwg; /* PWG mapping data */
+ _ppd_cache_t *cache; /* PPD cache and mapping data */
/*
@@ -104,22 +105,25 @@ cupsMarkOptions(
media = cupsGetOption("media", num_options, options);
output_bin = cupsGetOption("output-bin", num_options, options);
- output_mode = cupsGetOption("output-mode", num_options, options);
page_size = cupsGetOption("PageSize", num_options, options);
print_quality = cupsGetOption("print-quality", num_options, options);
sides = cupsGetOption("sides", num_options, options);
- if ((media || output_bin || output_mode || print_quality || sides) &&
- !ppd->pwg)
+ if ((print_color_mode = cupsGetOption("print-color-mode", num_options,
+ options)) == NULL)
+ print_color_mode = cupsGetOption("output-mode", num_options, options);
+
+ if ((media || output_bin || print_color_mode || print_quality || sides) &&
+ !ppd->cache)
{
/*
- * Load PWG mapping data as needed...
+ * Load PPD cache and mapping data as needed...
*/
- ppd->pwg = _pwgCreateWithPPD(ppd);
+ ppd->cache = _ppdCacheCreateWithPPD(ppd);
}
- pwg = (_pwg_t *)ppd->pwg;
+ cache = ppd->cache;
if (media)
{
@@ -154,40 +158,40 @@ cupsMarkOptions(
{
if (!strncasecmp(s, "Custom.", 7) || ppdPageSize(ppd, s))
ppd_mark_option(ppd, "PageSize", s);
- else if ((ppd_keyword = _pwgGetPageSize(pwg, NULL, s, NULL)) != NULL)
+ else if ((ppd_keyword = _ppdCacheGetPageSize(cache, NULL, s, NULL)) != NULL)
ppd_mark_option(ppd, "PageSize", ppd_keyword);
}
- if (pwg && pwg->source_option &&
- !cupsGetOption(pwg->source_option, num_options, options) &&
- (ppd_keyword = _pwgGetInputSlot(pwg, NULL, s)) != NULL)
- ppd_mark_option(ppd, pwg->source_option, ppd_keyword);
+ if (cache && cache->source_option &&
+ !cupsGetOption(cache->source_option, num_options, options) &&
+ (ppd_keyword = _ppdCacheGetInputSlot(cache, NULL, s)) != NULL)
+ ppd_mark_option(ppd, cache->source_option, ppd_keyword);
if (!cupsGetOption("MediaType", num_options, options) &&
- (ppd_keyword = _pwgGetMediaType(pwg, NULL, s)) != NULL)
+ (ppd_keyword = _ppdCacheGetMediaType(cache, NULL, s)) != NULL)
ppd_mark_option(ppd, "MediaType", ppd_keyword);
}
}
- if (pwg)
+ if (cache)
{
if (!cupsGetOption("com.apple.print.DocumentTicket.PMSpoolFormat",
num_options, options) &&
!cupsGetOption("APPrinterPreset", num_options, options) &&
- (output_mode || print_quality))
+ (print_color_mode || print_quality))
{
/*
* Map output-mode and print-quality to a preset...
*/
- _pwg_output_mode_t pwg_om; /* output-mode index */
+ _pwg_print_color_mode_t pwg_pcm;/* print-color-mode index */
_pwg_print_quality_t pwg_pq; /* print-quality index */
cups_option_t *preset;/* Current preset option */
- if (output_mode && !strcmp(output_mode, "monochrome"))
- pwg_om = _PWG_OUTPUT_MODE_MONOCHROME;
+ if (print_color_mode && !strcmp(print_color_mode, "monochrome"))
+ pwg_pcm = _PWG_PRINT_COLOR_MODE_MONOCHROME;
else
- pwg_om = _PWG_OUTPUT_MODE_COLOR;
+ pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
if (print_quality)
{
@@ -200,33 +204,33 @@ cupsMarkOptions(
else
pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
- if (pwg->num_presets[pwg_om][pwg_pq] == 0)
+ if (cache->num_presets[pwg_pcm][pwg_pq] == 0)
{
/*
* Try to find a preset that works so that we maximize the chances of us
* getting a good print using IPP attributes.
*/
- if (pwg->num_presets[pwg_om][_PWG_PRINT_QUALITY_NORMAL] > 0)
+ if (cache->num_presets[pwg_pcm][_PWG_PRINT_QUALITY_NORMAL] > 0)
pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
- else if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][pwg_pq] > 0)
- pwg_om = _PWG_OUTPUT_MODE_COLOR;
+ else if (cache->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_pq] > 0)
+ pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
else
{
- pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
- pwg_om = _PWG_OUTPUT_MODE_COLOR;
+ pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
+ pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
}
}
- if (pwg->num_presets[pwg_om][pwg_pq] > 0)
+ if (cache->num_presets[pwg_pcm][pwg_pq] > 0)
{
/*
* Copy the preset options as long as the corresponding names are not
* already defined in the IPP request...
*/
- for (i = pwg->num_presets[pwg_om][pwg_pq],
- preset = pwg->presets[pwg_om][pwg_pq];
+ for (i = cache->num_presets[pwg_pcm][pwg_pq],
+ preset = cache->presets[pwg_pcm][pwg_pq];
i > 0;
i --, preset ++)
{
@@ -237,7 +241,7 @@ cupsMarkOptions(
}
if (output_bin && !cupsGetOption("OutputBin", num_options, options) &&
- (ppd_keyword = _pwgGetOutputBin(pwg, output_bin)) != NULL)
+ (ppd_keyword = _ppdCacheGetOutputBin(cache, output_bin)) != NULL)
{
/*
* Map output-bin to OutputBin...
@@ -246,19 +250,19 @@ cupsMarkOptions(
ppd_mark_option(ppd, "OutputBin", ppd_keyword);
}
- if (sides && pwg->sides_option &&
- !cupsGetOption(pwg->sides_option, num_options, options))
+ if (sides && cache->sides_option &&
+ !cupsGetOption(cache->sides_option, num_options, options))
{
/*
* Map sides to duplex option...
*/
if (!strcmp(sides, "one-sided"))
- ppd_mark_option(ppd, pwg->sides_option, pwg->sides_1sided);
+ ppd_mark_option(ppd, cache->sides_option, cache->sides_1sided);
else if (!strcmp(sides, "two-sided-long-edge"))
- ppd_mark_option(ppd, pwg->sides_option, pwg->sides_2sided_long);
+ ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_long);
else if (!strcmp(sides, "two-sided-short-edge"))
- ppd_mark_option(ppd, pwg->sides_option, pwg->sides_2sided_short);
+ ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_short);
}
}
diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c
new file mode 100644
index 000000000..e0b5d65bc
--- /dev/null
+++ b/cups/ppd-cache.c
@@ -0,0 +1,2348 @@
+/*
+ * "$Id$"
+ *
+ * PPD cache implementation for CUPS.
+ *
+ * Copyright 2010-2011 by Apple Inc.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * _ppdCacheCreateWithFile() - Create PPD cache and mapping data from a
+ * written file.
+ * _ppdCacheCreateWithPPD() - Create PWG mapping data from a PPD file.
+ * _ppdCacheDestroy() - Free all memory used for PWG mapping data.
+ * _ppdCacheGetBin() - Get the PWG output-bin keyword associated with
+ * a PPD OutputBin.
+ * _ppdCacheGetInputSlot() - Get the PPD InputSlot associated with the job
+ * attributes or a keyword string.
+ * _ppdCacheGetMediaType() - Get the PPD MediaType associated with the job
+ * attributes or a keyword string.
+ * _ppdCacheGetOutputBin() - Get the PPD OutputBin associated with the
+ * keyword string.
+ * _ppdCacheGetPageSize() - Get the PPD PageSize associated with the job
+ * attributes or a keyword string.
+ * _ppdCacheGetSize() - Get the PWG size associated with a PPD
+ * PageSize.
+ * _ppdCacheGetSource() - Get the PWG media-source associated with a PPD
+ * InputSlot.
+ * _ppdCacheGetType() - Get the PWG media-type associated with a PPD
+ * MediaType.
+ * _ppdCacheWriteFile() - Write PWG mapping data to a file.
+ * _pwgInputSlotForSource() - Get the InputSlot name for the given PWG
+ * media-source.
+ * _pwgMediaTypeForType() - Get the MediaType name for the given PWG
+ * media-type.
+ * _pwgPageSizeForMedia() - Get the PageSize name for the given media.
+ * pwg_ppdize_name() - Convert an IPP keyword to a PPD keyword.
+ * pwg_unppdize_name() - Convert a PPD keyword to a lowercase IPP
+ * keyword.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups-private.h"
+#include <math.h>
+
+
+/*
+ * Macro to test for two almost-equal PWG measurements.
+ */
+
+#define _PWG_EQUIVALENT(x, y) (abs((x)-(y)) < 2)
+
+
+/*
+ * Local functions...
+ */
+
+static void pwg_ppdize_name(const char *ipp, char *name, size_t namesize);
+static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize);
+
+
+/*
+ * '_ppdCacheCreateWithFile()' - Create PPD cache and mapping data from a
+ * written file.
+ *
+ * Use the @link _ppdCacheWriteFile@ function to write PWG mapping data to a
+ * file.
+ */
+
+_ppd_cache_t * /* O - PPD cache and mapping data */
+_ppdCacheCreateWithFile(
+ const char *filename, /* I - File to read */
+ ipp_t **attrs) /* IO - IPP attributes, if any */
+{
+ cups_file_t *fp; /* File */
+ _ppd_cache_t *pc; /* PWG mapping data */
+ _pwg_size_t *size; /* Current size */
+ _pwg_map_t *map; /* Current map */
+ int linenum, /* Current line number */
+ num_bins, /* Number of bins in file */
+ num_sizes, /* Number of sizes in file */
+ num_sources, /* Number of sources in file */
+ num_types; /* Number of types in file */
+ char line[2048], /* Current line */
+ *value, /* Pointer to value in line */
+ *valueptr, /* Pointer into value */
+ pwg_keyword[128], /* PWG keyword */
+ ppd_keyword[PPD_MAX_NAME];
+ /* PPD keyword */
+ _pwg_print_color_mode_t print_color_mode;
+ /* Print color mode for preset */
+ _pwg_print_quality_t print_quality; /* Print quality for preset */
+
+
+ DEBUG_printf(("_ppdCacheCreateWithFile(filename=\"%s\")", filename));
+
+ /*
+ * Range check input...
+ */
+
+ if (attrs)
+ *attrs = NULL;
+
+ if (!filename)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+ return (NULL);
+ }
+
+ /*
+ * Open the file...
+ */
+
+ if ((fp = cupsFileOpen(filename, "r")) == NULL)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ return (NULL);
+ }
+
+ /*
+ * Read the first line and make sure it has "#CUPS-PPD-CACHE-version" in it...
+ */
+
+ if (!cupsFileGets(fp, line, sizeof(line)))
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ DEBUG_puts("_ppdCacheCreateWithFile: Unable to read first line.");
+ cupsFileClose(fp);
+ return (NULL);
+ }
+
+ if (strncmp(line, "#CUPS-PPD-CACHE-", 16) ||
+ atoi(line + 16) != _PPD_CACHE_VERSION)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ DEBUG_printf(("_ppdCacheCreateWithFile: Wrong first line \"%s\".", line));
+ cupsFileClose(fp);
+ return (NULL);
+ }
+
+ /*
+ * Allocate the mapping data structure...
+ */
+
+ if ((pc = calloc(1, sizeof(_ppd_cache_t))) == NULL)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ DEBUG_puts("_ppdCacheCreateWithFile: Unable to allocate _ppd_cache_t.");
+ goto create_error;
+ }
+
+ /*
+ * Read the file...
+ */
+
+ linenum = 0;
+ num_bins = 0;
+ num_sizes = 0;
+ num_sources = 0;
+ num_types = 0;
+
+ while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: line=\"%s\", value=\"%s\", "
+ "linenum=%d", line, value, linenum));
+
+ if (!value)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Missing value on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+ else if (!strcasecmp(line, "Filter"))
+ {
+ if (!pc->filters)
+ pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
+
+ cupsArrayAdd(pc->filters, value);
+ }
+ else if (!strcasecmp(line, "PreFilter"))
+ {
+ if (!pc->prefilters)
+ pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
+
+ cupsArrayAdd(pc->prefilters, value);
+ }
+ else if (!strcasecmp(line, "Product"))
+ {
+ pc->product = _cupsStrAlloc(value);
+ }
+ else if (!strcasecmp(line, "IPP"))
+ {
+ off_t pos = cupsFileTell(fp), /* Position in file */
+ length = strtol(value, NULL, 10);
+ /* Length of IPP attributes */
+
+ if (attrs && *attrs)
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: IPP listed multiple times.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+ else if (length <= 0)
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP length.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if (attrs)
+ {
+ /*
+ * Read IPP attributes into the provided variable...
+ */
+
+ *attrs = ippNew();
+
+ if (ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL,
+ *attrs) != IPP_DATA)
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+ }
+ else
+ {
+ /*
+ * Skip the IPP data entirely...
+ */
+
+ cupsFileSeek(fp, pos + length);
+ }
+
+ if (cupsFileTell(fp) != (pos + length))
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+ }
+ else if (!strcasecmp(line, "NumBins"))
+ {
+ if (num_bins > 0)
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: NumBins listed multiple times.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((num_bins = atoi(value)) <= 0 || num_bins > 65536)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumBins value %d on line "
+ "%d.", num_sizes, linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((pc->bins = calloc(num_bins, sizeof(_pwg_map_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d bins.",
+ num_sizes));
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ goto create_error;
+ }
+ }
+ else if (!strcasecmp(line, "Bin"))
+ {
+ if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad Bin on line %d.", linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if (pc->num_bins >= num_bins)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Too many Bin's on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ map = pc->bins + pc->num_bins;
+ map->pwg = _cupsStrAlloc(pwg_keyword);
+ map->ppd = _cupsStrAlloc(ppd_keyword);
+
+ pc->num_bins ++;
+ }
+ else if (!strcasecmp(line, "NumSizes"))
+ {
+ if (num_sizes > 0)
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: NumSizes listed multiple times.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((num_sizes = atoi(value)) <= 0 || num_sizes > 65536)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSizes value %d on line "
+ "%d.", num_sizes, linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((pc->sizes = calloc(num_sizes, sizeof(_pwg_size_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sizes.",
+ num_sizes));
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ goto create_error;
+ }
+ }
+ else if (!strcasecmp(line, "Size"))
+ {
+ if (pc->num_sizes >= num_sizes)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Too many Size's on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ size = pc->sizes + pc->num_sizes;
+
+ if (sscanf(value, "%127s%40s%d%d%d%d%d%d", pwg_keyword, ppd_keyword,
+ &(size->width), &(size->length), &(size->left),
+ &(size->bottom), &(size->right), &(size->top)) != 8)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad Size on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ size->map.pwg = _cupsStrAlloc(pwg_keyword);
+ size->map.ppd = _cupsStrAlloc(ppd_keyword);
+
+ pc->num_sizes ++;
+ }
+ else if (!strcasecmp(line, "CustomSize"))
+ {
+ if (pc->custom_max_width > 0)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Too many CustomSize's on line "
+ "%d.", linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if (sscanf(value, "%d%d%d%d%d%d%d%d", &(pc->custom_max_width),
+ &(pc->custom_max_length), &(pc->custom_min_width),
+ &(pc->custom_min_length), &(pc->custom_size.left),
+ &(pc->custom_size.bottom), &(pc->custom_size.right),
+ &(pc->custom_size.top)) != 8)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad CustomSize on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
+ pc->custom_max_width, pc->custom_max_length);
+ pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
+
+ _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
+ pc->custom_min_width, pc->custom_min_length);
+ pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
+ }
+ else if (!strcasecmp(line, "SourceOption"))
+ {
+ pc->source_option = _cupsStrAlloc(value);
+ }
+ else if (!strcasecmp(line, "NumSources"))
+ {
+ if (num_sources > 0)
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: NumSources listed multiple "
+ "times.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((num_sources = atoi(value)) <= 0 || num_sources > 65536)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSources value %d on "
+ "line %d.", num_sources, linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((pc->sources = calloc(num_sources, sizeof(_pwg_map_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sources.",
+ num_sources));
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ goto create_error;
+ }
+ }
+ else if (!strcasecmp(line, "Source"))
+ {
+ if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad Source on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if (pc->num_sources >= num_sources)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Too many Source's on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ map = pc->sources + pc->num_sources;
+ map->pwg = _cupsStrAlloc(pwg_keyword);
+ map->ppd = _cupsStrAlloc(ppd_keyword);
+
+ pc->num_sources ++;
+ }
+ else if (!strcasecmp(line, "NumTypes"))
+ {
+ if (num_types > 0)
+ {
+ DEBUG_puts("_ppdCacheCreateWithFile: NumTypes listed multiple times.");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((num_types = atoi(value)) <= 0 || num_types > 65536)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumTypes value %d on "
+ "line %d.", num_types, linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if ((pc->types = calloc(num_types, sizeof(_pwg_map_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d types.",
+ num_types));
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ goto create_error;
+ }
+ }
+ else if (!strcasecmp(line, "Type"))
+ {
+ if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad Type on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if (pc->num_types >= num_types)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Too many Type's on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ map = pc->types + pc->num_types;
+ map->pwg = _cupsStrAlloc(pwg_keyword);
+ map->ppd = _cupsStrAlloc(ppd_keyword);
+
+ pc->num_types ++;
+ }
+ else if (!strcasecmp(line, "Preset"))
+ {
+ /*
+ * Preset output-mode print-quality name=value ...
+ */
+
+ print_color_mode = (_pwg_print_color_mode_t)strtol(value, &valueptr, 10);
+ print_quality = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10);
+
+ if (print_color_mode < _PWG_PRINT_COLOR_MODE_MONOCHROME ||
+ print_color_mode >= _PWG_PRINT_COLOR_MODE_MAX ||
+ print_quality < _PWG_PRINT_QUALITY_DRAFT ||
+ print_quality >= _PWG_PRINT_QUALITY_MAX ||
+ valueptr == value || !*valueptr)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Bad Preset on line %d.",
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ pc->num_presets[print_color_mode][print_quality] =
+ cupsParseOptions(valueptr, 0,
+ pc->presets[print_color_mode] + print_quality);
+ }
+ else if (!strcasecmp(line, "SidesOption"))
+ pc->sides_option = _cupsStrAlloc(value);
+ else if (!strcasecmp(line, "Sides1Sided"))
+ pc->sides_1sided = _cupsStrAlloc(value);
+ else if (!strcasecmp(line, "Sides2SidedLong"))
+ pc->sides_2sided_long = _cupsStrAlloc(value);
+ else if (!strcasecmp(line, "Sides2SidedShort"))
+ pc->sides_2sided_short = _cupsStrAlloc(value);
+ else
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Unknown %s on line %d.", line,
+ linenum));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+ }
+
+ if (pc->num_sizes < num_sizes)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sizes (%d < %d).",
+ pc->num_sizes, num_sizes));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if (pc->num_sources < num_sources)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sources (%d < %d).",
+ pc->num_sources, num_sources));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ if (pc->num_types < num_types)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithFile: Not enough types (%d < %d).",
+ pc->num_types, num_types));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1);
+ goto create_error;
+ }
+
+ cupsFileClose(fp);
+
+ return (pc);
+
+ /*
+ * If we get here the file was bad - free any data and return...
+ */
+
+ create_error:
+
+ cupsFileClose(fp);
+ _ppdCacheDestroy(pc);
+
+ if (attrs)
+ ippDelete(*attrs);
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheCreateWithPPD()' - Create PWG mapping data from a PPD file.
+ */
+
+_ppd_cache_t * /* O - PPD cache and mapping data */
+_ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */
+{
+ int i, j, k; /* Looping vars */
+ _ppd_cache_t *pc; /* PWG mapping data */
+ ppd_option_t *input_slot, /* InputSlot option */
+ *media_type, /* MediaType option */
+ *output_bin, /* OutputBin option */
+ *color_model, /* ColorModel option */
+ *duplex; /* Duplex option */
+ ppd_choice_t *choice; /* Current InputSlot/MediaType */
+ _pwg_map_t *map; /* Current source/type map */
+ ppd_attr_t *ppd_attr; /* Current PPD preset attribute */
+ int num_options; /* Number of preset options and props */
+ cups_option_t *options; /* Preset options and properties */
+ ppd_size_t *ppd_size; /* Current PPD size */
+ _pwg_size_t *pwg_size; /* Current PWG size */
+ char pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3],
+ /* PWG keyword string */
+ ppd_name[PPD_MAX_NAME];
+ /* Normalized PPD name */
+ const char *pwg_name; /* Standard PWG media name */
+ _pwg_media_t *pwg_media; /* PWG media data */
+ _pwg_print_color_mode_t pwg_print_color_mode;
+ /* print-color-mode index */
+ _pwg_print_quality_t pwg_print_quality;
+ /* print-quality index */
+ int similar; /* Are the old and new size similar? */
+ _pwg_size_t *old_size; /* Current old size */
+ int old_imageable, /* Old imageable length in 2540ths */
+ old_borderless, /* Old borderless state */
+ old_known_pwg; /* Old PWG name is well-known */
+ int new_width, /* New width in 2540ths */
+ new_length, /* New length in 2540ths */
+ new_left, /* New left margin in 2540ths */
+ new_bottom, /* New bottom margin in 2540ths */
+ new_right, /* New right margin in 2540ths */
+ new_top, /* New top margin in 2540ths */
+ new_imageable, /* New imageable length in 2540ths */
+ new_borderless, /* New borderless state */
+ new_known_pwg; /* New PWG name is well-known */
+ _pwg_size_t *new_size; /* New size to add, if any */
+ const char *filter; /* Current filter */
+
+
+ DEBUG_printf(("_ppdCacheCreateWithPPD(ppd=%p)", ppd));
+
+ /*
+ * Range check input...
+ */
+
+ if (!ppd)
+ return (NULL);
+
+ /*
+ * Allocate memory...
+ */
+
+ if ((pc = calloc(1, sizeof(_ppd_cache_t))) == NULL)
+ {
+ DEBUG_puts("_ppdCacheCreateWithPPD: Unable to allocate _ppd_cache_t.");
+ goto create_error;
+ }
+
+ /*
+ * Copy and convert size data...
+ */
+
+ if (ppd->num_sizes == 0)
+ {
+ DEBUG_puts("_ppdCacheCreateWithPPD: No page sizes in PPD.");
+ goto create_error;
+ }
+
+ if ((pc->sizes = calloc(ppd->num_sizes, sizeof(_pwg_size_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
+ "_pwg_size_t's.", ppd->num_sizes));
+ goto create_error;
+ }
+
+ for (i = ppd->num_sizes, pwg_size = pc->sizes, ppd_size = ppd->sizes;
+ i > 0;
+ i --, ppd_size ++)
+ {
+ /*
+ * Don't copy over custom size...
+ */
+
+ if (!strcasecmp(ppd_size->name, "Custom"))
+ continue;
+
+ /*
+ * Convert the PPD size name to the corresponding PWG keyword name.
+ */
+
+ if ((pwg_media = _pwgMediaForPPD(ppd_size->name)) != NULL)
+ {
+ /*
+ * Standard name, do we have conflicts?
+ */
+
+ for (j = 0; j < pc->num_sizes; j ++)
+ if (!strcmp(pc->sizes[j].map.pwg, pwg_media->pwg))
+ {
+ pwg_media = NULL;
+ break;
+ }
+ }
+
+ if (pwg_media)
+ {
+ /*
+ * Standard name and no conflicts, use it!
+ */
+
+ pwg_name = pwg_media->pwg;
+ new_known_pwg = 1;
+ }
+ else
+ {
+ /*
+ * Not a standard name; convert it to a PWG vendor name of the form:
+ *
+ * pp_lowerppd_WIDTHxHEIGHTuu
+ */
+
+ pwg_name = pwg_keyword;
+ new_known_pwg = 0;
+
+ pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name));
+ _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name,
+ _PWG_FROMPTS(ppd_size->width),
+ _PWG_FROMPTS(ppd_size->length));
+ }
+
+ /*
+ * If we have a similar paper with non-zero margins then we only
+ * want to keep it if it has a larger imageable area length.
+ */
+
+ new_width = _PWG_FROMPTS(ppd_size->width);
+ new_length = _PWG_FROMPTS(ppd_size->length);
+ new_left = _PWG_FROMPTS(ppd_size->left);
+ new_bottom = _PWG_FROMPTS(ppd_size->bottom);
+ new_right = _PWG_FROMPTS(ppd_size->width - ppd_size->right);
+ new_top = _PWG_FROMPTS(ppd_size->length - ppd_size->top);
+ new_imageable = new_length - new_top - new_bottom;
+ new_borderless = new_bottom == 0 && new_top == 0 &&
+ new_left == 0 && new_right == 0;
+
+ for (k = pc->num_sizes, similar = 0, old_size = pc->sizes, new_size = NULL;
+ k > 0 && !similar;
+ k --, old_size ++)
+ {
+ old_imageable = old_size->length - old_size->top - old_size->bottom;
+ old_borderless = old_size->left == 0 && old_size->bottom == 0 &&
+ old_size->right == 0 && old_size->top == 0;
+ old_known_pwg = strncmp(old_size->map.pwg, "oe_", 3) &&
+ strncmp(old_size->map.pwg, "om_", 3);
+
+ similar = old_borderless == new_borderless &&
+ _PWG_EQUIVALENT(old_size->width, new_width) &&
+ _PWG_EQUIVALENT(old_size->length, new_length);
+
+ if (similar &&
+ (new_known_pwg || (!old_known_pwg && new_imageable > old_imageable)))
+ {
+ /*
+ * The new paper has a larger imageable area so it could replace
+ * the older paper. Regardless of the imageable area, we always
+ * prefer the size with a well-known PWG name.
+ */
+
+ new_size = old_size;
+ _cupsStrFree(old_size->map.ppd);
+ _cupsStrFree(old_size->map.pwg);
+ }
+ }
+
+ if (!similar)
+ {
+ /*
+ * The paper was unique enough to deserve its own entry so add it to the
+ * end.
+ */
+
+ new_size = pwg_size ++;
+ pc->num_sizes ++;
+ }
+
+ if (new_size)
+ {
+ /*
+ * Save this size...
+ */
+
+ new_size->map.ppd = _cupsStrAlloc(ppd_size->name);
+ new_size->map.pwg = _cupsStrAlloc(pwg_name);
+ new_size->width = new_width;
+ new_size->length = new_length;
+ new_size->left = new_left;
+ new_size->bottom = new_bottom;
+ new_size->right = new_right;
+ new_size->top = new_top;
+ }
+ }
+
+ if (ppd->variable_sizes)
+ {
+ /*
+ * Generate custom size data...
+ */
+
+ _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
+ _PWG_FROMPTS(ppd->custom_max[0]),
+ _PWG_FROMPTS(ppd->custom_max[1]));
+ pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
+ pc->custom_max_width = _PWG_FROMPTS(ppd->custom_max[0]);
+ pc->custom_max_length = _PWG_FROMPTS(ppd->custom_max[1]);
+
+ _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
+ _PWG_FROMPTS(ppd->custom_min[0]),
+ _PWG_FROMPTS(ppd->custom_min[1]));
+ pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
+ pc->custom_min_width = _PWG_FROMPTS(ppd->custom_min[0]);
+ pc->custom_min_length = _PWG_FROMPTS(ppd->custom_min[1]);
+
+ pc->custom_size.left = _PWG_FROMPTS(ppd->custom_margins[0]);
+ pc->custom_size.bottom = _PWG_FROMPTS(ppd->custom_margins[1]);
+ pc->custom_size.right = _PWG_FROMPTS(ppd->custom_margins[2]);
+ pc->custom_size.top = _PWG_FROMPTS(ppd->custom_margins[3]);
+ }
+
+ /*
+ * Copy and convert InputSlot data...
+ */
+
+ if ((input_slot = ppdFindOption(ppd, "InputSlot")) == NULL)
+ input_slot = ppdFindOption(ppd, "HPPaperSource");
+
+ if (input_slot)
+ {
+ pc->source_option = _cupsStrAlloc(input_slot->keyword);
+
+ if ((pc->sources = calloc(input_slot->num_choices,
+ sizeof(_pwg_map_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
+ "_pwg_map_t's for InputSlot.", input_slot->num_choices));
+ goto create_error;
+ }
+
+ pc->num_sources = input_slot->num_choices;
+
+ for (i = input_slot->num_choices, choice = input_slot->choices,
+ map = pc->sources;
+ i > 0;
+ i --, choice ++, map ++)
+ {
+ if (!strncasecmp(choice->choice, "Auto", 4) ||
+ !strcasecmp(choice->choice, "Default"))
+ pwg_name = "auto";
+ else if (!strcasecmp(choice->choice, "Cassette"))
+ pwg_name = "main";
+ else if (!strcasecmp(choice->choice, "PhotoTray"))
+ pwg_name = "photo";
+ else if (!strcasecmp(choice->choice, "CDTray"))
+ pwg_name = "disc";
+ else if (!strncasecmp(choice->choice, "Multipurpose", 12) ||
+ !strcasecmp(choice->choice, "MP") ||
+ !strcasecmp(choice->choice, "MPTray"))
+ pwg_name = "alternate";
+ else if (!strcasecmp(choice->choice, "LargeCapacity"))
+ pwg_name = "large-capacity";
+ else if (!strncasecmp(choice->choice, "Lower", 5))
+ pwg_name = "bottom";
+ else if (!strncasecmp(choice->choice, "Middle", 6))
+ pwg_name = "middle";
+ else if (!strncasecmp(choice->choice, "Upper", 5))
+ pwg_name = "top";
+ else if (!strncasecmp(choice->choice, "Side", 4))
+ pwg_name = "side";
+ else if (!strcasecmp(choice->choice, "Roll") ||
+ !strcasecmp(choice->choice, "Roll1"))
+ pwg_name = "main-roll";
+ else if (!strcasecmp(choice->choice, "Roll2"))
+ pwg_name = "alternate-roll";
+ else
+ {
+ /*
+ * Convert PPD name to lowercase...
+ */
+
+ pwg_name = pwg_keyword;
+ pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+ }
+
+ map->pwg = _cupsStrAlloc(pwg_name);
+ map->ppd = _cupsStrAlloc(choice->choice);
+ }
+ }
+
+ /*
+ * Copy and convert MediaType data...
+ */
+
+ if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL)
+ {
+ if ((pc->types = calloc(media_type->num_choices,
+ sizeof(_pwg_map_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
+ "_pwg_map_t's for MediaType.", media_type->num_choices));
+ goto create_error;
+ }
+
+ pc->num_types = media_type->num_choices;
+
+ for (i = media_type->num_choices, choice = media_type->choices,
+ map = pc->types;
+ i > 0;
+ i --, choice ++, map ++)
+ {
+ if (!strncasecmp(choice->choice, "Auto", 4) ||
+ !strcasecmp(choice->choice, "Any") ||
+ !strcasecmp(choice->choice, "Default"))
+ pwg_name = "auto";
+ else if (!strncasecmp(choice->choice, "Card", 4))
+ pwg_name = "cardstock";
+ else if (!strncasecmp(choice->choice, "Env", 3))
+ pwg_name = "envelope";
+ else if (!strncasecmp(choice->choice, "Gloss", 5))
+ pwg_name = "photographic-glossy";
+ else if (!strcasecmp(choice->choice, "HighGloss"))
+ pwg_name = "photographic-high-gloss";
+ else if (!strcasecmp(choice->choice, "Matte"))
+ pwg_name = "photographic-matte";
+ else if (!strncasecmp(choice->choice, "Plain", 5))
+ pwg_name = "stationery";
+ else if (!strncasecmp(choice->choice, "Coated", 6))
+ pwg_name = "stationery-coated";
+ else if (!strcasecmp(choice->choice, "Inkjet"))
+ pwg_name = "stationery-inkjet";
+ else if (!strcasecmp(choice->choice, "Letterhead"))
+ pwg_name = "stationery-letterhead";
+ else if (!strncasecmp(choice->choice, "Preprint", 8))
+ pwg_name = "stationery-preprinted";
+ else if (!strncasecmp(choice->choice, "Transparen", 10))
+ pwg_name = "transparency";
+ else
+ {
+ /*
+ * Convert PPD name to lowercase...
+ */
+
+ pwg_name = pwg_keyword;
+ pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+ }
+
+ map->pwg = _cupsStrAlloc(pwg_name);
+ map->ppd = _cupsStrAlloc(choice->choice);
+ }
+ }
+
+
+ /*
+ * Copy and convert OutputBin data...
+ */
+
+ if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL)
+ {
+ if ((pc->bins = calloc(output_bin->num_choices,
+ sizeof(_pwg_map_t))) == NULL)
+ {
+ DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
+ "_pwg_map_t's for OutputBin.", output_bin->num_choices));
+ goto create_error;
+ }
+
+ pc->num_bins = output_bin->num_choices;
+
+ for (i = output_bin->num_choices, choice = output_bin->choices,
+ map = pc->bins;
+ i > 0;
+ i --, choice ++, map ++)
+ {
+ pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+
+ map->pwg = _cupsStrAlloc(pwg_keyword);
+ map->ppd = _cupsStrAlloc(choice->choice);
+ }
+ }
+
+ if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL)
+ {
+ /*
+ * Copy and convert APPrinterPreset (output-mode + print-quality) data...
+ */
+
+ const char *quality, /* com.apple.print.preset.quality value */
+ *output_mode, /* com.apple.print.preset.output-mode value */
+ *color_model_val, /* ColorModel choice */
+ *graphicsType, /* com.apple.print.preset.graphicsType value */
+ *media_front_coating; /* com.apple.print.preset.media-front-coating value */
+
+ do
+ {
+ num_options = _ppdParseOptions(ppd_attr->value, 0, &options,
+ _PPD_PARSE_ALL);
+
+ if ((quality = cupsGetOption("com.apple.print.preset.quality",
+ num_options, options)) != NULL)
+ {
+ /*
+ * Get the print-quality for this preset...
+ */
+
+ if (!strcmp(quality, "low"))
+ pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
+ else if (!strcmp(quality, "high"))
+ pwg_print_quality = _PWG_PRINT_QUALITY_HIGH;
+ else
+ pwg_print_quality = _PWG_PRINT_QUALITY_NORMAL;
+
+ /*
+ * Ignore graphicsType "Photo" presets that are not high quality.
+ */
+
+ graphicsType = cupsGetOption("com.apple.print.preset.graphicsType",
+ num_options, options);
+
+ if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && graphicsType &&
+ !strcmp(graphicsType, "Photo"))
+ continue;
+
+ /*
+ * Ignore presets for normal and draft quality where the coating
+ * isn't "none" or "autodetect".
+ */
+
+ media_front_coating = cupsGetOption(
+ "com.apple.print.preset.media-front-coating",
+ num_options, options);
+
+ if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH &&
+ media_front_coating &&
+ strcmp(media_front_coating, "none") &&
+ strcmp(media_front_coating, "autodetect"))
+ continue;
+
+ /*
+ * Get the output mode for this preset...
+ */
+
+ output_mode = cupsGetOption("com.apple.print.preset.output-mode",
+ num_options, options);
+ color_model_val = cupsGetOption("ColorModel", num_options, options);
+
+ if (output_mode)
+ {
+ if (!strcmp(output_mode, "monochrome"))
+ pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME;
+ else
+ pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
+ }
+ else if (color_model_val)
+ {
+ if (!strcasecmp(color_model_val, "Gray"))
+ pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME;
+ else
+ pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
+ }
+ else
+ pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
+
+ /*
+ * Save the options for this combination as needed...
+ */
+
+ if (!pc->num_presets[pwg_print_color_mode][pwg_print_quality])
+ pc->num_presets[pwg_print_color_mode][pwg_print_quality] =
+ _ppdParseOptions(ppd_attr->value, 0,
+ pc->presets[pwg_print_color_mode] +
+ pwg_print_quality, _PPD_PARSE_OPTIONS);
+ }
+
+ cupsFreeOptions(num_options, options);
+ }
+ while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) != NULL);
+ }
+
+ if (!pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] &&
+ !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] &&
+ !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH])
+ {
+ /*
+ * Try adding some common color options to create grayscale presets. These
+ * are listed in order of popularity...
+ */
+
+ const char *color_option = NULL, /* Color control option */
+ *gray_choice = NULL; /* Choice to select grayscale */
+
+ if ((color_model = ppdFindOption(ppd, "ColorModel")) != NULL &&
+ ppdFindChoice(color_model, "Gray"))
+ {
+ color_option = "ColorModel";
+ gray_choice = "Gray";
+ }
+ else if ((color_model = ppdFindOption(ppd, "HPColorMode")) != NULL &&
+ ppdFindChoice(color_model, "grayscale"))
+ {
+ color_option = "HPColorMode";
+ gray_choice = "grayscale";
+ }
+ else if ((color_model = ppdFindOption(ppd, "BRMonoColor")) != NULL &&
+ ppdFindChoice(color_model, "Mono"))
+ {
+ color_option = "BRMonoColor";
+ gray_choice = "Mono";
+ }
+ else if ((color_model = ppdFindOption(ppd, "CNIJSGrayScale")) != NULL &&
+ ppdFindChoice(color_model, "1"))
+ {
+ color_option = "CNIJSGrayScale";
+ gray_choice = "1";
+ }
+ else if ((color_model = ppdFindOption(ppd, "HPColorAsGray")) != NULL &&
+ ppdFindChoice(color_model, "True"))
+ {
+ color_option = "HPColorAsGray";
+ gray_choice = "True";
+ }
+
+ if (color_option && gray_choice)
+ {
+ /*
+ * Copy and convert ColorModel (output-mode) data...
+ */
+
+ cups_option_t *coption, /* Color option */
+ *moption; /* Monochrome option */
+
+ for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
+ pwg_print_quality < _PWG_PRINT_QUALITY_MAX;
+ pwg_print_quality ++)
+ {
+ if (pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_print_quality])
+ {
+ /*
+ * Copy the color options...
+ */
+
+ num_options = pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [pwg_print_quality];
+ options = calloc(sizeof(cups_option_t), num_options);
+
+ if (options)
+ {
+ for (i = num_options, moption = options,
+ coption = pc->presets[_PWG_PRINT_COLOR_MODE_COLOR]
+ [pwg_print_quality];
+ i > 0;
+ i --, moption ++, coption ++)
+ {
+ moption->name = _cupsStrRetain(coption->name);
+ moption->value = _cupsStrRetain(coption->value);
+ }
+
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
+ num_options;
+ pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
+ options;
+ }
+ }
+ else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL)
+ continue;
+
+ /*
+ * Add the grayscale option to the preset...
+ */
+
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
+ cupsAddOption(color_option, gray_choice,
+ pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
+ [pwg_print_quality],
+ pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME] +
+ pwg_print_quality);
+ }
+ }
+ }
+
+ /*
+ * Copy and convert Duplex (sides) data...
+ */
+
+ if ((duplex = ppdFindOption(ppd, "Duplex")) == NULL)
+ if ((duplex = ppdFindOption(ppd, "JCLDuplex")) == NULL)
+ if ((duplex = ppdFindOption(ppd, "EFDuplex")) == NULL)
+ if ((duplex = ppdFindOption(ppd, "EFDuplexing")) == NULL)
+ duplex = ppdFindOption(ppd, "KD03Duplex");
+
+ if (duplex)
+ {
+ pc->sides_option = _cupsStrAlloc(duplex->keyword);
+
+ for (i = duplex->num_choices, choice = duplex->choices;
+ i > 0;
+ i --, choice ++)
+ {
+ if ((!strcasecmp(choice->choice, "None") ||
+ !strcasecmp(choice->choice, "False")) && !pc->sides_1sided)
+ pc->sides_1sided = _cupsStrAlloc(choice->choice);
+ else if ((!strcasecmp(choice->choice, "DuplexNoTumble") ||
+ !strcasecmp(choice->choice, "LongEdge") ||
+ !strcasecmp(choice->choice, "Top")) && !pc->sides_2sided_long)
+ pc->sides_2sided_long = _cupsStrAlloc(choice->choice);
+ else if ((!strcasecmp(choice->choice, "DuplexTumble") ||
+ !strcasecmp(choice->choice, "ShortEdge") ||
+ !strcasecmp(choice->choice, "Bottom")) &&
+ !pc->sides_2sided_short)
+ pc->sides_2sided_short = _cupsStrAlloc(choice->choice);
+ }
+ }
+
+ /*
+ * Copy filters and pre-filters...
+ */
+
+ pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
+
+ cupsArrayAdd(pc->filters,
+ "application/vnd.cups-raw application/octet-stream 0 -");
+
+ if ((ppd_attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) != NULL)
+ {
+ do
+ {
+ cupsArrayAdd(pc->filters, ppd_attr->value);
+ }
+ while ((ppd_attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);
+ }
+ else if (ppd->num_filters > 0)
+ {
+ for (i = 0; i < ppd->num_filters; i ++)
+ cupsArrayAdd(pc->filters, ppd->filters[i]);
+ }
+ else
+ cupsArrayAdd(pc->filters, "application/vnd.cups-postscript 0 -");
+
+ /*
+ * See if we have a command filter...
+ */
+
+ for (filter = (const char *)cupsArrayFirst(pc->filters);
+ filter;
+ filter = (const char *)cupsArrayNext(pc->filters))
+ if (!strncasecmp(filter, "application/vnd.cups-command", 28) &&
+ _cups_isspace(filter[28]))
+ break;
+
+ if (!filter &&
+ ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) == NULL ||
+ strcasecmp(ppd_attr->value, "none")))
+ {
+ /*
+ * No command filter and no cupsCommands keyword telling us not to use one.
+ * See if this is a PostScript printer, and if so add a PostScript command
+ * filter...
+ */
+
+ for (filter = (const char *)cupsArrayFirst(pc->filters);
+ filter;
+ filter = (const char *)cupsArrayNext(pc->filters))
+ if (!strncasecmp(filter, "application/vnd.cups-postscript", 31) &&
+ _cups_isspace(filter[31]))
+ break;
+
+ if (filter)
+ cupsArrayAdd(pc->filters,
+ "application/vnd.cups-command application/postscript 0 -");
+ }
+
+ if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
+ {
+ pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
+
+ do
+ {
+ cupsArrayAdd(pc->prefilters, ppd_attr->value);
+ }
+ while ((ppd_attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL)) != NULL);
+ }
+
+ /*
+ * Copy the product string, if any...
+ */
+
+ if (ppd->product)
+ pc->product = _cupsStrAlloc(ppd->product);
+
+ /*
+ * Return the cache data...
+ */
+
+ return (pc);
+
+ /*
+ * If we get here we need to destroy the PWG mapping data and return NULL...
+ */
+
+ create_error:
+
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Out of memory."), 1);
+ _ppdCacheDestroy(pc);
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheDestroy()' - Free all memory used for PWG mapping data.
+ */
+
+void
+_ppdCacheDestroy(_ppd_cache_t *pc) /* I - PPD cache and mapping data */
+{
+ int i; /* Looping var */
+ _pwg_map_t *map; /* Current map */
+ _pwg_size_t *size; /* Current size */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc)
+ return;
+
+ /*
+ * Free memory as needed...
+ */
+
+ if (pc->bins)
+ {
+ for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++)
+ {
+ _cupsStrFree(map->pwg);
+ _cupsStrFree(map->ppd);
+ }
+
+ free(pc->bins);
+ }
+
+ if (pc->sizes)
+ {
+ for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
+ {
+ _cupsStrFree(size->map.pwg);
+ _cupsStrFree(size->map.ppd);
+ }
+
+ free(pc->sizes);
+ }
+
+ if (pc->source_option)
+ _cupsStrFree(pc->source_option);
+
+ if (pc->sources)
+ {
+ for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++)
+ {
+ _cupsStrFree(map->pwg);
+ _cupsStrFree(map->ppd);
+ }
+
+ free(pc->sources);
+ }
+
+ if (pc->types)
+ {
+ for (i = pc->num_types, map = pc->types; i > 0; i --, map ++)
+ {
+ _cupsStrFree(map->pwg);
+ _cupsStrFree(map->ppd);
+ }
+
+ free(pc->types);
+ }
+
+ if (pc->custom_max_keyword)
+ _cupsStrFree(pc->custom_max_keyword);
+
+ if (pc->custom_min_keyword)
+ _cupsStrFree(pc->custom_min_keyword);
+
+ _cupsStrFree(pc->product);
+ cupsArrayDelete(pc->filters);
+ cupsArrayDelete(pc->prefilters);
+
+ free(pc);
+}
+
+
+/*
+ * '_ppdCacheGetBin()' - Get the PWG output-bin keyword associated with a PPD
+ * OutputBin.
+ */
+
+const char * /* O - output-bin or NULL */
+_ppdCacheGetBin(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ const char *output_bin) /* I - PPD OutputBin string */
+{
+ int i; /* Looping var */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc || !output_bin)
+ return (NULL);
+
+ /*
+ * Look up the OutputBin string...
+ */
+
+
+ for (i = 0; i < pc->num_bins; i ++)
+ if (!strcasecmp(output_bin, pc->bins[i].ppd))
+ return (pc->bins[i].pwg);
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheGetInputSlot()' - Get the PPD InputSlot associated with the job
+ * attributes or a keyword string.
+ */
+
+const char * /* O - PPD InputSlot or NULL */
+_ppdCacheGetInputSlot(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ ipp_t *job, /* I - Job attributes or NULL */
+ const char *keyword) /* I - Keyword string or NULL */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!pc || pc->num_sources == 0 || (!job && !keyword))
+ return (NULL);
+
+ if (job && !keyword)
+ {
+ /*
+ * Lookup the media-col attribute and any media-source found there...
+ */
+
+ ipp_attribute_t *media_col, /* media-col attribute */
+ *media_source; /* media-source attribute */
+ _pwg_size_t size; /* Dimensional size */
+ int margins_set; /* Were the margins set? */
+
+ media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
+ if (media_col &&
+ (media_source = ippFindAttribute(media_col->values[0].collection,
+ "media-source",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ /*
+ * Use the media-source value from media-col...
+ */
+
+ keyword = media_source->values[0].string.text;
+ }
+ else if (_pwgInitSize(&size, job, &margins_set))
+ {
+ /*
+ * For media <= 5x7, look for a photo tray...
+ */
+
+ if (size.width <= (5 * 2540) && size.length <= (7 * 2540))
+ keyword = "photo";
+ }
+ }
+
+ if (keyword)
+ {
+ int i; /* Looping var */
+
+ for (i = 0; i < pc->num_sources; i ++)
+ if (!strcasecmp(keyword, pc->sources[i].pwg))
+ return (pc->sources[i].ppd);
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheGetMediaType()' - Get the PPD MediaType associated with the job
+ * attributes or a keyword string.
+ */
+
+const char * /* O - PPD MediaType or NULL */
+_ppdCacheGetMediaType(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ ipp_t *job, /* I - Job attributes or NULL */
+ const char *keyword) /* I - Keyword string or NULL */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!pc || pc->num_types == 0 || (!job && !keyword))
+ return (NULL);
+
+ if (job && !keyword)
+ {
+ /*
+ * Lookup the media-col attribute and any media-source found there...
+ */
+
+ ipp_attribute_t *media_col, /* media-col attribute */
+ *media_type; /* media-type attribute */
+
+ media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
+ if (media_col)
+ {
+ if ((media_type = ippFindAttribute(media_col->values[0].collection,
+ "media-type",
+ IPP_TAG_KEYWORD)) == NULL)
+ media_type = ippFindAttribute(media_col->values[0].collection,
+ "media-type", IPP_TAG_NAME);
+
+ if (media_type)
+ keyword = media_type->values[0].string.text;
+ }
+ }
+
+ if (keyword)
+ {
+ int i; /* Looping var */
+
+ for (i = 0; i < pc->num_types; i ++)
+ if (!strcasecmp(keyword, pc->types[i].pwg))
+ return (pc->types[i].ppd);
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheGetOutputBin()' - Get the PPD OutputBin associated with the keyword
+ * string.
+ */
+
+const char * /* O - PPD OutputBin or NULL */
+_ppdCacheGetOutputBin(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ const char *output_bin) /* I - Keyword string */
+{
+ int i; /* Looping var */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc || !output_bin)
+ return (NULL);
+
+ /*
+ * Look up the OutputBin string...
+ */
+
+
+ for (i = 0; i < pc->num_bins; i ++)
+ if (!strcasecmp(output_bin, pc->bins[i].pwg))
+ return (pc->bins[i].ppd);
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheGetPageSize()' - Get the PPD PageSize associated with the job
+ * attributes or a keyword string.
+ */
+
+const char * /* O - PPD PageSize or NULL */
+_ppdCacheGetPageSize(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ ipp_t *job, /* I - Job attributes or NULL */
+ const char *keyword, /* I - Keyword string or NULL */
+ int *exact) /* O - 1 if exact match, 0 otherwise */
+{
+ int i; /* Looping var */
+ _pwg_size_t *size, /* Current size */
+ *closest, /* Closest size */
+ jobsize; /* Size data from job */
+ int margins_set, /* Were the margins set? */
+ dwidth, /* Difference in width */
+ dlength, /* Difference in length */
+ dleft, /* Difference in left margins */
+ dright, /* Difference in right margins */
+ dbottom, /* Difference in bottom margins */
+ dtop, /* Difference in top margins */
+ dmin, /* Minimum difference */
+ dclosest; /* Closest difference */
+ const char *ppd_name; /* PPD media name */
+
+
+ DEBUG_printf(("_ppdCacheGetPageSize(pc=%p, job=%p, keyword=\"%s\", exact=%p)",
+ pc, job, keyword, exact));
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc || (!job && !keyword))
+ return (NULL);
+
+ if (exact)
+ *exact = 0;
+
+ ppd_name = keyword;
+
+ if (job)
+ {
+ /*
+ * Try getting the PPD media name from the job attributes...
+ */
+
+ ipp_attribute_t *attr; /* Job attribute */
+
+ if ((attr = ippFindAttribute(job, "PageSize", IPP_TAG_ZERO)) == NULL)
+ if ((attr = ippFindAttribute(job, "PageRegion", IPP_TAG_ZERO)) == NULL)
+ attr = ippFindAttribute(job, "media", IPP_TAG_ZERO);
+
+#ifdef DEBUG
+ if (attr)
+ DEBUG_printf(("1_ppdCacheGetPageSize: Found attribute %s (%s)",
+ attr->name, ippTagString(attr->value_tag)));
+ else
+ DEBUG_puts("1_ppdCacheGetPageSize: Did not find media attribute.");
+#endif /* DEBUG */
+
+ if (attr && (attr->value_tag == IPP_TAG_NAME ||
+ attr->value_tag == IPP_TAG_KEYWORD))
+ ppd_name = attr->values[0].string.text;
+ }
+
+ DEBUG_printf(("1_ppdCacheGetPageSize: ppd_name=\"%s\"", ppd_name));
+
+ if (ppd_name)
+ {
+ /*
+ * Try looking up the named PPD size first...
+ */
+
+ for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
+ {
+ DEBUG_printf(("2_ppdCacheGetPageSize: size[%d]=[\"%s\" \"%s\"]",
+ (int)(size - pc->sizes), size->map.pwg, size->map.ppd));
+
+ if (!strcasecmp(ppd_name, size->map.ppd) ||
+ !strcasecmp(ppd_name, size->map.pwg))
+ {
+ if (exact)
+ *exact = 1;
+
+ DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", ppd_name));
+
+ return (size->map.ppd);
+ }
+ }
+ }
+
+ if (job && !keyword)
+ {
+ /*
+ * Get the size using media-col or media, with the preference being
+ * media-col.
+ */
+
+ if (!_pwgInitSize(&jobsize, job, &margins_set))
+ return (NULL);
+ }
+ else
+ {
+ /*
+ * Get the size using a media keyword...
+ */
+
+ _pwg_media_t *media; /* Media definition */
+
+
+ if ((media = _pwgMediaForPWG(keyword)) == NULL)
+ if ((media = _pwgMediaForLegacy(keyword)) == NULL)
+ if ((media = _pwgMediaForPPD(keyword)) == NULL)
+ return (NULL);
+
+ jobsize.width = media->width;
+ jobsize.length = media->length;
+ margins_set = 0;
+ }
+
+ /*
+ * Now that we have the dimensions and possibly the margins, look at the
+ * available sizes and find the match...
+ */
+
+ closest = NULL;
+ dclosest = 999999999;
+
+ if (!ppd_name || strncasecmp(ppd_name, "Custom.", 7) ||
+ strncasecmp(ppd_name, "custom_", 7))
+ {
+ for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
+ {
+ /*
+ * Adobe uses a size matching algorithm with an epsilon of 5 points, which
+ * is just about 176/2540ths...
+ */
+
+ dwidth = size->width - jobsize.width;
+ dlength = size->length - jobsize.length;
+
+ if (dwidth <= -176 || dwidth >= 176 || dlength <= -176 || dlength >= 176)
+ continue;
+
+ if (margins_set)
+ {
+ /*
+ * Use a tighter epsilon of 1 point (35/2540ths) for margins...
+ */
+
+ dleft = size->left - jobsize.left;
+ dright = size->right - jobsize.right;
+ dtop = size->top - jobsize.top;
+ dbottom = size->bottom - jobsize.bottom;
+
+ if (dleft <= -35 || dleft >= 35 || dright <= -35 || dright >= 35 ||
+ dtop <= -35 || dtop >= 35 || dbottom <= -35 || dbottom >= 35)
+ {
+ dleft = dleft < 0 ? -dleft : dleft;
+ dright = dright < 0 ? -dright : dright;
+ dbottom = dbottom < 0 ? -dbottom : dbottom;
+ dtop = dtop < 0 ? -dtop : dtop;
+ dmin = dleft + dright + dbottom + dtop;
+
+ if (dmin < dclosest)
+ {
+ dclosest = dmin;
+ closest = size;
+ }
+
+ continue;
+ }
+ }
+
+ if (exact)
+ *exact = 1;
+
+ DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", size->map.ppd));
+
+ return (size->map.ppd);
+ }
+ }
+
+ if (closest)
+ {
+ DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (closest)",
+ closest->map.ppd));
+
+ return (closest->map.ppd);
+ }
+
+ /*
+ * If we get here we need to check for custom page size support...
+ */
+
+ if (jobsize.width >= pc->custom_min_width &&
+ jobsize.width <= pc->custom_max_width &&
+ jobsize.length >= pc->custom_min_length &&
+ jobsize.length <= pc->custom_max_length)
+ {
+ /*
+ * In range, format as Custom.WWWWxLLLL (points).
+ */
+
+ snprintf(pc->custom_ppd_size, sizeof(pc->custom_ppd_size), "Custom.%dx%d",
+ (int)_PWG_TOPTS(jobsize.width), (int)_PWG_TOPTS(jobsize.length));
+
+ if (margins_set && exact)
+ {
+ dleft = pc->custom_size.left - jobsize.left;
+ dright = pc->custom_size.right - jobsize.right;
+ dtop = pc->custom_size.top - jobsize.top;
+ dbottom = pc->custom_size.bottom - jobsize.bottom;
+
+ if (dleft > -35 && dleft < 35 && dright > -35 && dright < 35 &&
+ dtop > -35 && dtop < 35 && dbottom > -35 && dbottom < 35)
+ *exact = 1;
+ }
+ else if (exact)
+ *exact = 1;
+
+ DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (custom)",
+ pc->custom_ppd_size));
+
+ return (pc->custom_ppd_size);
+ }
+
+ /*
+ * No custom page size support or the size is out of range - return NULL.
+ */
+
+ DEBUG_puts("1_ppdCacheGetPageSize: Returning NULL");
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheGetSize()' - Get the PWG size associated with a PPD PageSize.
+ */
+
+_pwg_size_t * /* O - PWG size or NULL */
+_ppdCacheGetSize(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ const char *page_size) /* I - PPD PageSize */
+{
+ int i;
+ _pwg_size_t *size; /* Current size */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc || !page_size)
+ return (NULL);
+
+ if (!strncasecmp(page_size, "Custom.", 7))
+ {
+ /*
+ * Custom size; size name can be one of the following:
+ *
+ * Custom.WIDTHxLENGTHin - Size in inches
+ * Custom.WIDTHxLENGTHft - Size in feet
+ * Custom.WIDTHxLENGTHcm - Size in centimeters
+ * Custom.WIDTHxLENGTHmm - Size in millimeters
+ * Custom.WIDTHxLENGTHm - Size in meters
+ * Custom.WIDTHxLENGTH[pt] - Size in points
+ */
+
+ double w, l; /* Width and length of page */
+ char *ptr; /* Pointer into PageSize */
+ struct lconv *loc; /* Locale data */
+
+ loc = localeconv();
+ w = (float)_cupsStrScand(page_size + 7, &ptr, loc);
+ if (!ptr || *ptr != 'x')
+ return (NULL);
+
+ l = (float)_cupsStrScand(ptr + 1, &ptr, loc);
+ if (!ptr)
+ return (NULL);
+
+ if (!strcasecmp(ptr, "in"))
+ {
+ w *= 2540.0;
+ l *= 2540.0;
+ }
+ else if (!strcasecmp(ptr, "ft"))
+ {
+ w *= 12.0 * 2540.0;
+ l *= 12.0 * 2540.0;
+ }
+ else if (!strcasecmp(ptr, "mm"))
+ {
+ w *= 100.0;
+ l *= 100.0;
+ }
+ else if (!strcasecmp(ptr, "cm"))
+ {
+ w *= 1000.0;
+ l *= 1000.0;
+ }
+ else if (!strcasecmp(ptr, "m"))
+ {
+ w *= 100000.0;
+ l *= 100000.0;
+ }
+ else
+ {
+ w *= 2540.0 / 72.0;
+ l *= 2540.0 / 72.0;
+ }
+
+ pc->custom_size.width = (int)w;
+ pc->custom_size.length = (int)l;
+
+ return (&(pc->custom_size));
+ }
+
+ /*
+ * Not a custom size - look it up...
+ */
+
+ for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
+ if (!strcasecmp(page_size, size->map.ppd))
+ return (size);
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheGetSource()' - Get the PWG media-source associated with a PPD
+ * InputSlot.
+ */
+
+const char * /* O - PWG media-source keyword */
+_ppdCacheGetSource(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ const char *input_slot) /* I - PPD InputSlot */
+{
+ int i; /* Looping var */
+ _pwg_map_t *source; /* Current source */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc || !input_slot)
+ return (NULL);
+
+ for (i = pc->num_sources, source = pc->sources; i > 0; i --, source ++)
+ if (!strcasecmp(input_slot, source->ppd))
+ return (source->pwg);
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheGetType()' - Get the PWG media-type associated with a PPD
+ * MediaType.
+ */
+
+const char * /* O - PWG media-type keyword */
+_ppdCacheGetType(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ const char *media_type) /* I - PPD MediaType */
+{
+ int i; /* Looping var */
+ _pwg_map_t *type; /* Current type */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc || !media_type)
+ return (NULL);
+
+ for (i = pc->num_types, type = pc->types; i > 0; i --, type ++)
+ if (!strcasecmp(media_type, type->ppd))
+ return (type->pwg);
+
+ return (NULL);
+}
+
+
+/*
+ * '_ppdCacheWriteFile()' - Write PWG mapping data to a file.
+ */
+
+int /* O - 1 on success, 0 on failure */
+_ppdCacheWriteFile(
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ const char *filename, /* I - File to write */
+ ipp_t *attrs) /* I - Attributes to write, if any */
+{
+ int i, j, k; /* Looping vars */
+ cups_file_t *fp; /* Output file */
+ _pwg_size_t *size; /* Current size */
+ _pwg_map_t *map; /* Current map */
+ cups_option_t *option; /* Current option */
+ const char *value; /* Filter/pre-filter value */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!pc || !filename)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+ return (0);
+ }
+
+ /*
+ * Open the file and write with compression...
+ */
+
+ if ((fp = cupsFileOpen(filename, "w9")) == NULL)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
+ return (0);
+ }
+
+ /*
+ * Standard header...
+ */
+
+ cupsFilePrintf(fp, "#CUPS-PPD-CACHE-%d\n", _PPD_CACHE_VERSION);
+
+ /*
+ * Output bins...
+ */
+
+ if (pc->num_bins > 0)
+ {
+ cupsFilePrintf(fp, "NumBins %d\n", pc->num_bins);
+ for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++)
+ cupsFilePrintf(fp, "Bin %s %s\n", map->pwg, map->ppd);
+ }
+
+ /*
+ * Media sizes...
+ */
+
+ cupsFilePrintf(fp, "NumSizes %d\n", pc->num_sizes);
+ for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
+ cupsFilePrintf(fp, "Size %s %s %d %d %d %d %d %d\n", size->map.pwg,
+ size->map.ppd, size->width, size->length, size->left,
+ size->bottom, size->right, size->top);
+ if (pc->custom_max_width > 0)
+ cupsFilePrintf(fp, "CustomSize %d %d %d %d %d %d %d %d\n",
+ pc->custom_max_width, pc->custom_max_length,
+ pc->custom_min_width, pc->custom_min_length,
+ pc->custom_size.left, pc->custom_size.bottom,
+ pc->custom_size.right, pc->custom_size.top);
+
+ /*
+ * Media sources...
+ */
+
+ if (pc->source_option)
+ cupsFilePrintf(fp, "SourceOption %s\n", pc->source_option);
+
+ if (pc->num_sources > 0)
+ {
+ cupsFilePrintf(fp, "NumSources %d\n", pc->num_sources);
+ for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++)
+ cupsFilePrintf(fp, "Source %s %s\n", map->pwg, map->ppd);
+ }
+
+ /*
+ * Media types...
+ */
+
+ if (pc->num_types > 0)
+ {
+ cupsFilePrintf(fp, "NumTypes %d\n", pc->num_types);
+ for (i = pc->num_types, map = pc->types; i > 0; i --, map ++)
+ cupsFilePrintf(fp, "Type %s %s\n", map->pwg, map->ppd);
+ }
+
+ /*
+ * Presets...
+ */
+
+ for (i = _PWG_PRINT_COLOR_MODE_MONOCHROME; i < _PWG_PRINT_COLOR_MODE_MAX; i ++)
+ for (j = _PWG_PRINT_QUALITY_DRAFT; j < _PWG_PRINT_QUALITY_MAX; j ++)
+ if (pc->num_presets[i][j])
+ {
+ cupsFilePrintf(fp, "Preset %d %d", i, j);
+ for (k = pc->num_presets[i][j], option = pc->presets[i][j];
+ k > 0;
+ k --, option ++)
+ cupsFilePrintf(fp, " %s=%s", option->name, option->value);
+ cupsFilePutChar(fp, '\n');
+ }
+
+ /*
+ * Duplex/sides...
+ */
+
+ if (pc->sides_option)
+ cupsFilePrintf(fp, "SidesOption %s\n", pc->sides_option);
+
+ if (pc->sides_1sided)
+ cupsFilePrintf(fp, "Sides1Sided %s\n", pc->sides_1sided);
+
+ if (pc->sides_2sided_long)
+ cupsFilePrintf(fp, "Sides2SidedLong %s\n", pc->sides_2sided_long);
+
+ if (pc->sides_2sided_short)
+ cupsFilePrintf(fp, "Sides2SidedShort %s\n", pc->sides_2sided_short);
+
+ /*
+ * Product, cupsFilter, cupsFilter2, and cupsPreFilter...
+ */
+
+ if (pc->product)
+ cupsFilePutConf(fp, "Product", pc->product);
+
+ for (value = (const char *)cupsArrayFirst(pc->filters);
+ value;
+ value = (const char *)cupsArrayNext(pc->filters))
+ cupsFilePutConf(fp, "Filter", value);
+
+ for (value = (const char *)cupsArrayFirst(pc->prefilters);
+ value;
+ value = (const char *)cupsArrayNext(pc->prefilters))
+ cupsFilePutConf(fp, "PreFilter", value);
+
+ /*
+ * IPP attributes, if any...
+ */
+
+ if (attrs)
+ {
+ cupsFilePrintf(fp, "IPP " CUPS_LLFMT "\n", CUPS_LLCAST ippLength(attrs));
+
+ attrs->state = IPP_IDLE;
+ ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL, attrs);
+ }
+
+ /*
+ * Close and return...
+ */
+
+ return (!cupsFileClose(fp));
+}
+
+
+/*
+ * '_pwgInputSlotForSource()' - Get the InputSlot name for the given PWG
+ * media-source.
+ */
+
+const char * /* O - InputSlot name */
+_pwgInputSlotForSource(
+ const char *media_source, /* I - PWG media-source */
+ char *name, /* I - Name buffer */
+ size_t namesize) /* I - Size of name buffer */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!media_source || !name || namesize < PPD_MAX_NAME)
+ return (NULL);
+
+ if (strcasecmp(media_source, "main"))
+ strlcpy(name, "Cassette", namesize);
+ else if (strcasecmp(media_source, "alternate"))
+ strlcpy(name, "Multipurpose", namesize);
+ else if (strcasecmp(media_source, "large-capacity"))
+ strlcpy(name, "LargeCapacity", namesize);
+ else if (strcasecmp(media_source, "bottom"))
+ strlcpy(name, "Lower", namesize);
+ else if (strcasecmp(media_source, "middle"))
+ strlcpy(name, "Middle", namesize);
+ else if (strcasecmp(media_source, "top"))
+ strlcpy(name, "Upper", namesize);
+ else if (strcasecmp(media_source, "rear"))
+ strlcpy(name, "Rear", namesize);
+ else if (strcasecmp(media_source, "side"))
+ strlcpy(name, "Side", namesize);
+ else if (strcasecmp(media_source, "envelope"))
+ strlcpy(name, "Envelope", namesize);
+ else if (strcasecmp(media_source, "main-roll"))
+ strlcpy(name, "Roll", namesize);
+ else if (strcasecmp(media_source, "alternate-roll"))
+ strlcpy(name, "Roll2", namesize);
+ else
+ pwg_ppdize_name(media_source, name, namesize);
+
+ return (name);
+}
+
+
+/*
+ * '_pwgMediaTypeForType()' - Get the MediaType name for the given PWG
+ * media-type.
+ */
+
+const char * /* O - MediaType name */
+_pwgMediaTypeForType(
+ const char *media_type, /* I - PWG media-type */
+ char *name, /* I - Name buffer */
+ size_t namesize) /* I - Size of name buffer */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!media_type || !name || namesize < PPD_MAX_NAME)
+ return (NULL);
+
+ if (strcasecmp(media_type, "auto"))
+ strlcpy(name, "Auto", namesize);
+ else if (strcasecmp(media_type, "cardstock"))
+ strlcpy(name, "Cardstock", namesize);
+ else if (strcasecmp(media_type, "envelope"))
+ strlcpy(name, "Envelope", namesize);
+ else if (strcasecmp(media_type, "photographic-glossy"))
+ strlcpy(name, "Glossy", namesize);
+ else if (strcasecmp(media_type, "photographic-high-gloss"))
+ strlcpy(name, "HighGloss", namesize);
+ else if (strcasecmp(media_type, "photographic-matte"))
+ strlcpy(name, "Matte", namesize);
+ else if (strcasecmp(media_type, "stationery"))
+ strlcpy(name, "Plain", namesize);
+ else if (strcasecmp(media_type, "stationery-coated"))
+ strlcpy(name, "Coated", namesize);
+ else if (strcasecmp(media_type, "stationery-inkjet"))
+ strlcpy(name, "Inkjet", namesize);
+ else if (strcasecmp(media_type, "stationery-letterhead"))
+ strlcpy(name, "Letterhead", namesize);
+ else if (strcasecmp(media_type, "stationery-preprinted"))
+ strlcpy(name, "Preprinted", namesize);
+ else if (strcasecmp(media_type, "transparency"))
+ strlcpy(name, "Transparency", namesize);
+ else
+ pwg_ppdize_name(media_type, name, namesize);
+
+ return (name);
+}
+
+
+/*
+ * '_pwgPageSizeForMedia()' - Get the PageSize name for the given media.
+ */
+
+const char * /* O - PageSize name */
+_pwgPageSizeForMedia(
+ _pwg_media_t *media, /* I - Media */
+ char *name, /* I - PageSize name buffer */
+ size_t namesize) /* I - Size of name buffer */
+{
+ const char *sizeptr, /* Pointer to size in PWG name */
+ *dimptr; /* Pointer to dimensions in PWG name */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!media || !name || namesize < PPD_MAX_NAME)
+ return (NULL);
+
+ /*
+ * Copy or generate a PageSize name...
+ */
+
+ if (media->ppd)
+ {
+ /*
+ * Use a standard Adobe name...
+ */
+
+ strlcpy(name, media->ppd, namesize);
+ }
+ else if (!media->pwg || !strncmp(media->pwg, "custom_", 7) ||
+ (sizeptr = strchr(media->pwg, '_')) == NULL ||
+ (dimptr = strchr(sizeptr + 1, '_')) == NULL ||
+ (size_t)(dimptr - sizeptr) > namesize)
+ {
+ /*
+ * Use a name of the form "wNNNhNNN"...
+ */
+
+ snprintf(name, namesize, "w%dh%d", (int)_PWG_TOPTS(media->width),
+ (int)_PWG_TOPTS(media->length));
+ }
+ else
+ {
+ /*
+ * Copy the size name from class_sizename_dimensions...
+ */
+
+ memcpy(name, sizeptr + 1, dimptr - sizeptr - 1);
+ name[dimptr - sizeptr - 1] = '\0';
+ }
+
+ return (name);
+}
+
+
+/*
+ * 'pwg_ppdize_name()' - Convert an IPP keyword to a PPD keyword.
+ */
+
+static void
+pwg_ppdize_name(const char *ipp, /* I - IPP keyword */
+ char *name, /* I - Name buffer */
+ size_t namesize) /* I - Size of name buffer */
+{
+ char *ptr, /* Pointer into name buffer */
+ *end; /* End of name buffer */
+
+
+ *name = toupper(*ipp++);
+
+ for (ptr = name + 1, end = name + namesize - 1; *ipp && ptr < end;)
+ {
+ if (*ipp == '-' && _cups_isalpha(ipp[1]))
+ {
+ ipp ++;
+ *ptr++ = toupper(*ipp++ & 255);
+ }
+ else
+ *ptr++ = *ipp++;
+ }
+
+ *ptr = '\0';
+}
+
+
+/*
+ * 'pwg_unppdize_name()' - Convert a PPD keyword to a lowercase IPP keyword.
+ */
+
+static void
+pwg_unppdize_name(const char *ppd, /* I - PPD keyword */
+ char *name, /* I - Name buffer */
+ size_t namesize) /* I - Size of name buffer */
+{
+ char *ptr, /* Pointer into name buffer */
+ *end; /* End of name buffer */
+
+
+ for (ptr = name, end = name + namesize - 1; *ppd && ptr < end; ppd ++)
+ {
+ if (_cups_isalnum(*ppd) || *ppd == '-')
+ *ptr++ = tolower(*ppd & 255);
+ else if (*ppd == '_' || *ppd == '.')
+ *ptr++ = '-';
+
+ if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) &&
+ _cups_isupper(ppd[1]) && ptr < end)
+ *ptr++ = '-';
+ }
+
+ *ptr = '\0';
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/ppd-private.h b/cups/ppd-private.h
index d44c1ca04..e907c46d7 100644
--- a/cups/ppd-private.h
+++ b/cups/ppd-private.h
@@ -3,7 +3,7 @@
*
* Private PPD definitions for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -46,6 +46,13 @@ extern "C" {
/*
+ * Constants...
+ */
+
+# define _PPD_CACHE_VERSION 1 /* Version number in cache file */
+
+
+/*
* Types and structures...
*/
@@ -71,12 +78,13 @@ typedef struct _ppd_cups_uiconsts_s /**** cupsUIConstraints ****/
_ppd_cups_uiconst_t *constraints; /* Constraints */
} _ppd_cups_uiconsts_t;
-typedef enum _pwg_output_mode_e /**** PWG output-mode indices ****/
+typedef enum _pwg_print_color_mode_e /**** PWG print-color-mode indices ****/
{
- _PWG_OUTPUT_MODE_MONOCHROME = 0, /* output-mode=monochrome */
- _PWG_OUTPUT_MODE_COLOR, /* output-mode=color */
- _PWG_OUTPUT_MODE_MAX
-} _pwg_output_mode_t;
+ _PWG_PRINT_COLOR_MODE_MONOCHROME = 0, /* print-color-mode=monochrome */
+ _PWG_PRINT_COLOR_MODE_COLOR, /* print-color-mode=color */
+ /* Other proposed values are not supported by CUPS yet. */
+ _PWG_PRINT_COLOR_MODE_MAX
+} _pwg_print_color_mode_t;
typedef enum _pwg_print_quality_e /**** PWG print-quality indices ****/
{
@@ -86,7 +94,7 @@ typedef enum _pwg_print_quality_e /**** PWG print-quality indices ****/
_PWG_PRINT_QUALITY_MAX
} _pwg_print_quality_t;
-typedef struct _pwg_s /**** PWG-PPD conversion data ****/
+struct _ppd_cache_s /**** PPD cache and PWG conversion data ****/
{
int num_bins; /* Number of output bins */
_pwg_map_t *bins; /* Output bins */
@@ -105,21 +113,46 @@ typedef struct _pwg_s /**** PWG-PPD conversion data ****/
_pwg_map_t *sources; /* Media sources */
int num_types; /* Number of media types */
_pwg_map_t *types; /* Media types */
- int num_presets[_PWG_OUTPUT_MODE_MAX][_PWG_PRINT_QUALITY_MAX];
- /* Number of output-mode/print-quality options */
- cups_option_t *presets[_PWG_OUTPUT_MODE_MAX][_PWG_PRINT_QUALITY_MAX];
- /* output-mode/print-quality options */
+ int num_presets[_PWG_PRINT_COLOR_MODE_MAX][_PWG_PRINT_QUALITY_MAX];
+ /* Number of print-color-mode/print-quality options */
+ cups_option_t *presets[_PWG_PRINT_COLOR_MODE_MAX][_PWG_PRINT_QUALITY_MAX];
+ /* print-color-mode/print-quality options */
char *sides_option, /* PPD option for sides */
*sides_1sided, /* Choice for one-sided */
*sides_2sided_long, /* Choice for two-sided-long-edge */
*sides_2sided_short; /* Choice for two-sided-short-edge */
-} _pwg_t;
+ char *product; /* Product value */
+ cups_array_t *filters, /* cupsFilter/cupsFilter2 values */
+ *prefilters; /* cupsPreFilter values */
+};
/*
* Prototypes...
*/
+extern _ppd_cache_t *_ppdCacheCreateWithFile(const char *filename,
+ ipp_t **attrs);
+extern _ppd_cache_t *_ppdCacheCreateWithPPD(ppd_file_t *ppd);
+extern void _ppdCacheDestroy(_ppd_cache_t *pc);
+extern const char *_ppdCacheGetBin(_ppd_cache_t *pc,
+ const char *output_bin);
+extern const char *_ppdCacheGetInputSlot(_ppd_cache_t *pc, ipp_t *job,
+ const char *keyword);
+extern const char *_ppdCacheGetMediaType(_ppd_cache_t *pc, ipp_t *job,
+ const char *keyword);
+extern const char *_ppdCacheGetOutputBin(_ppd_cache_t *pc,
+ const char *keyword);
+extern const char *_ppdCacheGetPageSize(_ppd_cache_t *pc, ipp_t *job,
+ const char *keyword, int *exact);
+extern _pwg_size_t *_ppdCacheGetSize(_ppd_cache_t *pc,
+ const char *page_size);
+extern const char *_ppdCacheGetSource(_ppd_cache_t *pc,
+ const char *input_slot);
+extern const char *_ppdCacheGetType(_ppd_cache_t *pc,
+ const char *media_type);
+extern int _ppdCacheWriteFile(_ppd_cache_t *pc,
+ const char *filename, ipp_t *attrs);
extern void _ppdFreeLanguages(cups_array_t *languages);
extern cups_encoding_t _ppdGetEncoding(const char *name);
extern cups_array_t *_ppdGetLanguages(ppd_file_t *ppd);
@@ -132,27 +165,12 @@ extern char *_ppdNormalizeMakeAndModel(const char *make_and_model,
extern int _ppdParseOptions(const char *s, int num_options,
cups_option_t **options,
_ppd_parse_t which);
-extern _pwg_t *_pwgCreateWithFile(const char *filename);
-extern _pwg_t *_pwgCreateWithPPD(ppd_file_t *ppd);
-extern void _pwgDestroy(_pwg_t *pwg);
-extern const char *_pwgGetBin(_pwg_t *pwg, const char *output_bin);
-extern const char *_pwgGetInputSlot(_pwg_t *pwg, ipp_t *job,
- const char *keyword);
-extern const char *_pwgGetMediaType(_pwg_t *pwg, ipp_t *job,
- const char *keyword);
-extern const char *_pwgGetOutputBin(_pwg_t *pwg, const char *keyword);
-extern const char *_pwgGetPageSize(_pwg_t *pwg, ipp_t *job,
- const char *keyword, int *exact);
-extern _pwg_size_t *_pwgGetSize(_pwg_t *pwg, const char *page_size);
-extern const char *_pwgGetSource(_pwg_t *pwg, const char *input_slot);
-extern const char *_pwgGetType(_pwg_t *pwg, const char *media_type);
extern const char *_pwgInputSlotForSource(const char *media_source,
char *name, size_t namesize);
extern const char *_pwgMediaTypeForType(const char *media_type,
- char *name, size_t namesize);
+ char *name, size_t namesize);
extern const char *_pwgPageSizeForMedia(_pwg_media_t *media,
char *name, size_t namesize);
-extern int _pwgWriteFile(_pwg_t *pwg, const char *filename);
/*
diff --git a/cups/ppd.c b/cups/ppd.c
index f1d236251..89ad18b6b 100644
--- a/cups/ppd.c
+++ b/cups/ppd.c
@@ -310,11 +310,11 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */
}
/*
- * Free any PWG mapping data...
+ * Free any PPD cache/mapping data...
*/
- if (ppd->pwg)
- _pwgDestroy((_pwg_t *)ppd->pwg);
+ if (ppd->cache)
+ _ppdCacheDestroy(ppd->cache);
/*
* Free the whole record...
diff --git a/cups/ppd.h b/cups/ppd.h
index 1b00ae455..7d12fade2 100644
--- a/cups/ppd.h
+++ b/cups/ppd.h
@@ -273,6 +273,9 @@ typedef struct ppd_coption_s /**** Custom Option @since CUPS 1.2/Mac OS X 10.5@
cups_array_t *params; /* Parameters */
} ppd_coption_t;
+typedef struct _ppd_cache_s _ppd_cache_t;
+ /**** PPD cache and mapping data @since CUPS 1.5@ @private@ ****/
+
typedef struct ppd_file_s /**** PPD File ****/
{
int language_level; /* Language level of device */
@@ -337,7 +340,7 @@ typedef struct ppd_file_s /**** PPD File ****/
cups_array_t *cups_uiconstraints; /* cupsUIConstraints @since CUPS 1.4/Mac OS X 10.6@ @private@ */
/**** New in CUPS 1.5 ****/
- void *pwg; /* PWG to/from PPD mappings @since CUPS 1.5@ @private@ */
+ _ppd_cache_t *cache; /* PPD cache and mapping data @since CUPS 1.5@ @private@ */
} ppd_file_t;
diff --git a/cups/pwg-file.c b/cups/pwg-file.c
deleted file mode 100644
index 52bac4d3e..000000000
--- a/cups/pwg-file.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * "$Id$"
- *
- * PWG load/save API implementation for CUPS.
- *
- * Copyright 2010 by Apple Inc.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file. If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- * _pwgCreateWithFile() - Create PWG mapping data from a written file.
- * _pwgDestroy() - Free all memory used for PWG mapping data.
- * _pwgWriteFile() - Write PWG mapping data to a file.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "cups-private.h"
-#include <math.h>
-
-
-/*
- * '_pwgCreateWithFile()' - Create PWG mapping data from a written file.
- *
- * Use the @link _pwgWriteFile@ function to write PWG mapping data to a file.
- */
-
-_pwg_t * /* O - PWG mapping data */
-_pwgCreateWithFile(const char *filename)/* I - File to read */
-{
- cups_file_t *fp; /* File */
- _pwg_t *pwg; /* PWG mapping data */
- _pwg_size_t *size; /* Current size */
- _pwg_map_t *map; /* Current map */
- int linenum, /* Current line number */
- num_bins, /* Number of bins in file */
- num_sizes, /* Number of sizes in file */
- num_sources, /* Number of sources in file */
- num_types; /* Number of types in file */
- char line[2048], /* Current line */
- *value, /* Pointer to value in line */
- *valueptr, /* Pointer into value */
- pwg_keyword[128], /* PWG keyword */
- ppd_keyword[PPD_MAX_NAME];
- /* PPD keyword */
- _pwg_output_mode_t output_mode; /* Output mode for preset */
- _pwg_print_quality_t print_quality; /* Print quality for preset */
-
-
- DEBUG_printf(("_pwgCreateWithFile(filename=\"%s\")", filename));
-
- /*
- * Range check input...
- */
-
- if (!filename)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
- return (NULL);
- }
-
- /*
- * Open the file...
- */
-
- if ((fp = cupsFileOpen(filename, "r")) == NULL)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
- return (NULL);
- }
-
- /*
- * Allocate the mapping data structure...
- */
-
- if ((pwg = calloc(1, sizeof(_pwg_t))) == NULL)
- {
- DEBUG_puts("_pwgCreateWithFile: Unable to allocate pwg_t.");
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
- goto create_error;
- }
-
- /*
- * Read the file...
- */
-
- linenum = 0;
- num_bins = 0;
- num_sizes = 0;
- num_sources = 0;
- num_types = 0;
-
- while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
- {
- DEBUG_printf(("_pwgCreateWithFile: line=\"%s\", value=\"%s\", linenum=%d",
- line, value, linenum));
-
- if (!value)
- {
- DEBUG_printf(("_pwgCreateWithFile: Missing value on line %d.", linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
- else if (!strcasecmp(line, "NumBins"))
- {
- if (num_bins > 0)
- {
- DEBUG_puts("_pwgCreateWithFile: NumBins listed multiple times.");
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((num_bins = atoi(value)) <= 0 || num_bins > 65536)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad NumBins value %d on line %d.",
- num_sizes, linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((pwg->bins = calloc(num_bins, sizeof(_pwg_map_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d bins.",
- num_sizes));
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
- goto create_error;
- }
- }
- else if (!strcasecmp(line, "Bin"))
- {
- if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad Bin on line %d.", linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if (pwg->num_bins >= num_bins)
- {
- DEBUG_printf(("_pwgCreateWithFile: Too many Bin's on line %d.",
- linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- map = pwg->bins + pwg->num_bins;
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(ppd_keyword);
-
- pwg->num_bins ++;
- }
- else if (!strcasecmp(line, "NumSizes"))
- {
- if (num_sizes > 0)
- {
- DEBUG_puts("_pwgCreateWithFile: NumSizes listed multiple times.");
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((num_sizes = atoi(value)) <= 0 || num_sizes > 65536)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad NumSizes value %d on line %d.",
- num_sizes, linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((pwg->sizes = calloc(num_sizes, sizeof(_pwg_size_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sizes.",
- num_sizes));
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
- goto create_error;
- }
- }
- else if (!strcasecmp(line, "Size"))
- {
- if (pwg->num_sizes >= num_sizes)
- {
- DEBUG_printf(("_pwgCreateWithFile: Too many Size's on line %d.",
- linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- size = pwg->sizes + pwg->num_sizes;
-
- if (sscanf(value, "%127s%40s%d%d%d%d%d%d", pwg_keyword, ppd_keyword,
- &(size->width), &(size->length), &(size->left),
- &(size->bottom), &(size->right), &(size->top)) != 8)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad Size on line %d.", linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- size->map.pwg = _cupsStrAlloc(pwg_keyword);
- size->map.ppd = _cupsStrAlloc(ppd_keyword);
-
- pwg->num_sizes ++;
- }
- else if (!strcasecmp(line, "CustomSize"))
- {
- if (pwg->custom_max_width > 0)
- {
- DEBUG_printf(("_pwgCreateWithFile: Too many CustomSize's on line %d.",
- linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if (sscanf(value, "%d%d%d%d%d%d%d%d", &(pwg->custom_max_width),
- &(pwg->custom_max_length), &(pwg->custom_min_width),
- &(pwg->custom_min_length), &(pwg->custom_size.left),
- &(pwg->custom_size.bottom), &(pwg->custom_size.right),
- &(pwg->custom_size.top)) != 8)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad CustomSize on line %d.", linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
- pwg->custom_max_width, pwg->custom_max_length);
- pwg->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
-
- _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
- pwg->custom_min_width, pwg->custom_min_length);
- pwg->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
- }
- else if (!strcasecmp(line, "SourceOption"))
- {
- pwg->source_option = _cupsStrAlloc(value);
- }
- else if (!strcasecmp(line, "NumSources"))
- {
- if (num_sources > 0)
- {
- DEBUG_puts("_pwgCreateWithFile: NumSources listed multiple times.");
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((num_sources = atoi(value)) <= 0 || num_sources > 65536)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad NumSources value %d on line %d.",
- num_sources, linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((pwg->sources = calloc(num_sources, sizeof(_pwg_map_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sources.",
- num_sources));
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
- goto create_error;
- }
- }
- else if (!strcasecmp(line, "Source"))
- {
- if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad Source on line %d.", linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if (pwg->num_sources >= num_sources)
- {
- DEBUG_printf(("_pwgCreateWithFile: Too many Source's on line %d.",
- linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- map = pwg->sources + pwg->num_sources;
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(ppd_keyword);
-
- pwg->num_sources ++;
- }
- else if (!strcasecmp(line, "NumTypes"))
- {
- if (num_types > 0)
- {
- DEBUG_puts("_pwgCreateWithFile: NumTypes listed multiple times.");
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((num_types = atoi(value)) <= 0 || num_types > 65536)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad NumTypes value %d on line %d.",
- num_types, linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if ((pwg->types = calloc(num_types, sizeof(_pwg_map_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d types.",
- num_types));
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
- goto create_error;
- }
- }
- else if (!strcasecmp(line, "Type"))
- {
- if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad Type on line %d.", linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if (pwg->num_types >= num_types)
- {
- DEBUG_printf(("_pwgCreateWithFile: Too many Type's on line %d.",
- linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- map = pwg->types + pwg->num_types;
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(ppd_keyword);
-
- pwg->num_types ++;
- }
- else if (!strcasecmp(line, "Preset"))
- {
- /*
- * Preset output-mode print-quality name=value ...
- */
-
- output_mode = (_pwg_output_mode_t)strtol(value, &valueptr, 10);
- print_quality = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10);
-
- if (output_mode < _PWG_OUTPUT_MODE_MONOCHROME ||
- output_mode >= _PWG_OUTPUT_MODE_MAX ||
- print_quality < _PWG_PRINT_QUALITY_DRAFT ||
- print_quality >= _PWG_PRINT_QUALITY_MAX ||
- valueptr == value || !*valueptr)
- {
- DEBUG_printf(("_pwgCreateWithFile: Bad Preset on line %d.", linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- pwg->num_presets[output_mode][print_quality] =
- cupsParseOptions(valueptr, 0,
- pwg->presets[output_mode] + print_quality);
- }
- else if (!strcasecmp(line, "SidesOption"))
- pwg->sides_option = _cupsStrAlloc(value);
- else if (!strcasecmp(line, "Sides1Sided"))
- pwg->sides_1sided = _cupsStrAlloc(value);
- else if (!strcasecmp(line, "Sides2SidedLong"))
- pwg->sides_2sided_long = _cupsStrAlloc(value);
- else if (!strcasecmp(line, "Sides2SidedShort"))
- pwg->sides_2sided_short = _cupsStrAlloc(value);
- else
- {
- DEBUG_printf(("_pwgCreateWithFile: Unknown %s on line %d.", line,
- linenum));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
- }
-
- if (pwg->num_sizes < num_sizes)
- {
- DEBUG_printf(("_pwgCreateWithFile: Not enough sizes (%d < %d).",
- pwg->num_sizes, num_sizes));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if (pwg->num_sources < num_sources)
- {
- DEBUG_printf(("_pwgCreateWithFile: Not enough sources (%d < %d).",
- pwg->num_sources, num_sources));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- if (pwg->num_types < num_types)
- {
- DEBUG_printf(("_pwgCreateWithFile: Not enough types (%d < %d).",
- pwg->num_types, num_types));
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
- goto create_error;
- }
-
- cupsFileClose(fp);
-
- return (pwg);
-
- /*
- * If we get here the file was bad - free any data and return...
- */
-
- create_error:
-
- cupsFileClose(fp);
- _pwgDestroy(pwg);
-
- return (NULL);
-}
-
-
-/*
- * '_pwgDestroy()' - Free all memory used for PWG mapping data.
- */
-
-void
-_pwgDestroy(_pwg_t *pwg) /* I - PWG mapping data */
-{
- int i; /* Looping var */
- _pwg_map_t *map; /* Current map */
- _pwg_size_t *size; /* Current size */
-
-
- /*
- * Range check input...
- */
-
- if (!pwg)
- return;
-
- /*
- * Free memory as needed...
- */
-
- if (pwg->bins)
- {
- for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++)
- {
- _cupsStrFree(map->pwg);
- _cupsStrFree(map->ppd);
- }
-
- free(pwg->bins);
- }
-
- if (pwg->sizes)
- {
- for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
- {
- _cupsStrFree(size->map.pwg);
- _cupsStrFree(size->map.ppd);
- }
-
- free(pwg->sizes);
- }
-
- if (pwg->source_option)
- _cupsStrFree(pwg->source_option);
-
- if (pwg->sources)
- {
- for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++)
- {
- _cupsStrFree(map->pwg);
- _cupsStrFree(map->ppd);
- }
-
- free(pwg->sources);
- }
-
- if (pwg->types)
- {
- for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++)
- {
- _cupsStrFree(map->pwg);
- _cupsStrFree(map->ppd);
- }
-
- free(pwg->types);
- }
-
- if (pwg->custom_max_keyword)
- _cupsStrFree(pwg->custom_max_keyword);
-
- if (pwg->custom_min_keyword)
- _cupsStrFree(pwg->custom_min_keyword);
-
- free(pwg);
-}
-
-
-/*
- * '_pwgWriteFile()' - Write PWG mapping data to a file.
- */
-
-int /* O - 1 on success, 0 on failure */
-_pwgWriteFile(_pwg_t *pwg, /* I - PWG mapping data */
- const char *filename) /* I - File to write */
-{
- int i, j, k; /* Looping vars */
- cups_file_t *fp; /* Output file */
- _pwg_size_t *size; /* Current size */
- _pwg_map_t *map; /* Current map */
- cups_option_t *option; /* Current option */
-
-
- /*
- * Range check input...
- */
-
- if (!pwg || !filename)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
- return (0);
- }
-
- /*
- * Open the file and write with compression...
- */
-
- if ((fp = cupsFileOpen(filename, "w9")) == NULL)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
- return (0);
- }
-
- /*
- * Standard header...
- */
-
- cupsFilePuts(fp, "#CUPS-PWGPPD\n");
-
- /*
- * Output bins...
- */
-
- if (pwg->num_bins > 0)
- {
- cupsFilePrintf(fp, "NumBins %d\n", pwg->num_bins);
- for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++)
- cupsFilePrintf(fp, "Bin %s %s\n", map->pwg, map->ppd);
- }
-
- /*
- * Media sizes...
- */
-
- cupsFilePrintf(fp, "NumSizes %d\n", pwg->num_sizes);
- for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
- cupsFilePrintf(fp, "Size %s %s %d %d %d %d %d %d\n", size->map.pwg,
- size->map.ppd, size->width, size->length, size->left,
- size->bottom, size->right, size->top);
- if (pwg->custom_max_width > 0)
- cupsFilePrintf(fp, "CustomSize %d %d %d %d %d %d %d %d\n",
- pwg->custom_max_width, pwg->custom_max_length,
- pwg->custom_min_width, pwg->custom_min_length,
- pwg->custom_size.left, pwg->custom_size.bottom,
- pwg->custom_size.right, pwg->custom_size.top);
-
- /*
- * Media sources...
- */
-
- if (pwg->source_option)
- cupsFilePrintf(fp, "SourceOption %s\n", pwg->source_option);
-
- if (pwg->num_sources > 0)
- {
- cupsFilePrintf(fp, "NumSources %d\n", pwg->num_sources);
- for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++)
- cupsFilePrintf(fp, "Source %s %s\n", map->pwg, map->ppd);
- }
-
- /*
- * Media types...
- */
-
- if (pwg->num_types > 0)
- {
- cupsFilePrintf(fp, "NumTypes %d\n", pwg->num_types);
- for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++)
- cupsFilePrintf(fp, "Type %s %s\n", map->pwg, map->ppd);
- }
-
- /*
- * Presets...
- */
-
- for (i = _PWG_OUTPUT_MODE_MONOCHROME; i < _PWG_OUTPUT_MODE_MAX; i ++)
- for (j = _PWG_PRINT_QUALITY_DRAFT; j < _PWG_PRINT_QUALITY_MAX; j ++)
- if (pwg->num_presets[i][j])
- {
- cupsFilePrintf(fp, "Preset %d %d", i, j);
- for (k = pwg->num_presets[i][j], option = pwg->presets[i][j];
- k > 0;
- k --, option ++)
- cupsFilePrintf(fp, " %s=%s", option->name, option->value);
- cupsFilePutChar(fp, '\n');
- }
-
- /*
- * Duplex/sides...
- */
-
- if (pwg->sides_option)
- cupsFilePrintf(fp, "SidesOption %s\n", pwg->sides_option);
-
- if (pwg->sides_1sided)
- cupsFilePrintf(fp, "Sides1Sided %s\n", pwg->sides_1sided);
-
- if (pwg->sides_2sided_long)
- cupsFilePrintf(fp, "Sides2SidedLong %s\n", pwg->sides_2sided_long);
-
- if (pwg->sides_2sided_short)
- cupsFilePrintf(fp, "Sides2SidedShort %s\n", pwg->sides_2sided_short);
-
- /*
- * Close and return...
- */
-
- return (!cupsFileClose(fp));
-}
-
-
-/*
- * End of "$Id$".
- */
diff --git a/cups/pwg-media.c b/cups/pwg-media.c
index 8e00ca031..306bf6d85 100644
--- a/cups/pwg-media.c
+++ b/cups/pwg-media.c
@@ -3,7 +3,7 @@
*
* PWG media name API implementation for CUPS.
*
- * Copyright 2009-2010 by Apple Inc.
+ * Copyright 2009-2011 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -116,7 +116,7 @@ static _pwg_media_t const cups_pwg_media[] =
_PWG_MEDIA_IN("na_f_44x68in", NULL, "AnsiF", 44, 68),
/* Chinese Standard Sheet Media Inch Sizes */
- _PWG_MEDIA_IN("roc_16k_7.75x10.75in", NULL, NULL, 7.75, 10.75),
+ _PWG_MEDIA_IN("roc_16k_7.75x10.75in", NULL, "roc16k", 7.75, 10.75),
_PWG_MEDIA_IN("roc_8k_10.75x15.5in", NULL, NULL, 10.75, 15.5),
/* ISO Standard Sheet Media Sizes */
diff --git a/cups/pwg-ppd.c b/cups/pwg-ppd.c
deleted file mode 100644
index 777ee07db..000000000
--- a/cups/pwg-ppd.c
+++ /dev/null
@@ -1,1489 +0,0 @@
-/*
- * "$Id$"
- *
- * PWG PPD mapping API implementation for CUPS.
- *
- * Copyright 2010 by Apple Inc.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file. If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- * _pwgCreateWithPPD() - Create PWG mapping data from a PPD file.
- * _pwgGetBin() - Get the PWG output-bin keyword associated with a
- * PPD OutputBin.
- * _pwgGetInputSlot() - Get the PPD InputSlot associated with the job
- * attributes or a keyword string.
- * _pwgGetMediaType() - Get the PPD MediaType associated with the job
- * attributes or a keyword string.
- * _pwgGetOutputBin() - Get the PPD OutputBin associated with the
- * keyword string.
- * _pwgGetPageSize() - Get the PPD PageSize associated with the job
- * attributes or a keyword string.
- * _pwgGetSize() - Get the PWG size associated with a PPD PageSize.
- * _pwgGetSource() - Get the PWG media-source associated with a PPD
- * InputSlot.
- * _pwgGetType() - Get the PWG media-type associated with a PPD
- * MediaType.
- * _pwgInputSlotForSource() - Get the InputSlot name for the given PWG source.
- * _pwgMediaTypeForType() - Get the MediaType name for the given PWG type.
- * _pwgPageSizeForMedia() - Get the PageSize name for the given media.
- * pwg_ppdize_name() - Convert an IPP keyword to a PPD keyword.
- * pwg_unppdize_name() - Convert a PPD keyword to a lowercase IPP
- * keyword.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "cups-private.h"
-#include <math.h>
-
-
-/*
- * Macro to test for two almost-equal PWG measurements.
- */
-
-#define _PWG_EQUIVALENT(x, y) (abs((x)-(y)) < 2)
-
-
-/*
- * Local functions...
- */
-
-static void pwg_ppdize_name(const char *ipp, char *name, size_t namesize);
-static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize);
-
-
-/*
- * '_pwgCreateWithPPD()' - Create PWG mapping data from a PPD file.
- */
-
-_pwg_t * /* O - PWG mapping data */
-_pwgCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */
-{
- int i, j, k; /* Looping vars */
- _pwg_t *pwg; /* PWG mapping data */
- ppd_option_t *input_slot, /* InputSlot option */
- *media_type, /* MediaType option */
- *output_bin, /* OutputBin option */
- *color_model, /* ColorModel option */
- *duplex; /* Duplex option */
- ppd_choice_t *choice; /* Current InputSlot/MediaType */
- _pwg_map_t *map; /* Current source/type map */
- ppd_attr_t *ppd_attr; /* Current PPD preset attribute */
- int num_options; /* Number of preset options and props */
- cups_option_t *options; /* Preset options and properties */
- ppd_size_t *ppd_size; /* Current PPD size */
- _pwg_size_t *pwg_size; /* Current PWG size */
- char pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3],
- /* PWG keyword string */
- ppd_name[PPD_MAX_NAME];
- /* Normalized PPD name */
- const char *pwg_name; /* Standard PWG media name */
- _pwg_media_t *pwg_media; /* PWG media data */
- _pwg_output_mode_t pwg_output_mode;/* output-mode index */
- _pwg_print_quality_t pwg_print_quality;
- /* print-quality index */
- int similar; /* Are the old and new size similar? */
- _pwg_size_t *old_size; /* Current old size */
- int old_imageable, /* Old imageable length in 2540ths */
- old_borderless, /* Old borderless state */
- old_known_pwg; /* Old PWG name is well-known */
- int new_width, /* New width in 2540ths */
- new_length, /* New length in 2540ths */
- new_left, /* New left margin in 2540ths */
- new_bottom, /* New bottom margin in 2540ths */
- new_right, /* New right margin in 2540ths */
- new_top, /* New top margin in 2540ths */
- new_imageable, /* New imageable length in 2540ths */
- new_borderless, /* New borderless state */
- new_known_pwg; /* New PWG name is well-known */
- _pwg_size_t *new_size; /* New size to add, if any */
-
-
- DEBUG_printf(("_pwgCreateWithPPD(ppd=%p)", ppd));
-
- /*
- * Range check input...
- */
-
- if (!ppd)
- return (NULL);
-
- /*
- * Allocate memory...
- */
-
- if ((pwg = calloc(1, sizeof(_pwg_t))) == NULL)
- {
- DEBUG_puts("_pwgCreateWithPPD: Unable to allocate _pwg_t.");
- goto create_error;
- }
-
- /*
- * Copy and convert size data...
- */
-
- if (ppd->num_sizes == 0)
- {
- DEBUG_puts("_pwgCreateWithPPD: No page sizes in PPD.");
- goto create_error;
- }
-
- if ((pwg->sizes = calloc(ppd->num_sizes, sizeof(_pwg_size_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_size_t's.",
- ppd->num_sizes));
- goto create_error;
- }
-
- for (i = ppd->num_sizes, pwg_size = pwg->sizes, ppd_size = ppd->sizes;
- i > 0;
- i --, ppd_size ++)
- {
- /*
- * Don't copy over custom size...
- */
-
- if (!strcasecmp(ppd_size->name, "Custom"))
- continue;
-
- /*
- * Convert the PPD size name to the corresponding PWG keyword name.
- */
-
- if ((pwg_media = _pwgMediaForPPD(ppd_size->name)) != NULL)
- {
- /*
- * Standard name, do we have conflicts?
- */
-
- for (j = 0; j < pwg->num_sizes; j ++)
- if (!strcmp(pwg->sizes[j].map.pwg, pwg_media->pwg))
- {
- pwg_media = NULL;
- break;
- }
- }
-
- if (pwg_media)
- {
- /*
- * Standard name and no conflicts, use it!
- */
-
- pwg_name = pwg_media->pwg;
- new_known_pwg = 1;
- }
- else
- {
- /*
- * Not a standard name; convert it to a PWG vendor name of the form:
- *
- * pp_lowerppd_WIDTHxHEIGHTuu
- */
-
- pwg_name = pwg_keyword;
- new_known_pwg = 0;
-
- pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name));
- _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name,
- _PWG_FROMPTS(ppd_size->width),
- _PWG_FROMPTS(ppd_size->length));
- }
-
- /*
- * If we have a similar paper with non-zero margins then we only
- * want to keep it if it has a larger imageable area length.
- */
-
- new_width = _PWG_FROMPTS(ppd_size->width);
- new_length = _PWG_FROMPTS(ppd_size->length);
- new_left = _PWG_FROMPTS(ppd_size->left);
- new_bottom = _PWG_FROMPTS(ppd_size->bottom);
- new_right = _PWG_FROMPTS(ppd_size->width - ppd_size->right);
- new_top = _PWG_FROMPTS(ppd_size->length - ppd_size->top);
- new_imageable = new_length - new_top - new_bottom;
- new_borderless = new_bottom == 0 && new_top == 0 &&
- new_left == 0 && new_right == 0;
-
- for (k = pwg->num_sizes, similar = 0, old_size = pwg->sizes, new_size = NULL;
- k > 0 && !similar;
- k --, old_size ++)
- {
- old_imageable = old_size->length - old_size->top - old_size->bottom;
- old_borderless = old_size->left == 0 && old_size->bottom == 0 &&
- old_size->right == 0 && old_size->top == 0;
- old_known_pwg = strncmp(old_size->map.pwg, "oe_", 3) &&
- strncmp(old_size->map.pwg, "om_", 3);
-
- similar = old_borderless == new_borderless &&
- _PWG_EQUIVALENT(old_size->width, new_width) &&
- _PWG_EQUIVALENT(old_size->length, new_length);
-
- if (similar &&
- (new_known_pwg || (!old_known_pwg && new_imageable > old_imageable)))
- {
- /*
- * The new paper has a larger imageable area so it could replace
- * the older paper. Regardless of the imageable area, we always
- * prefer the size with a well-known PWG name.
- */
-
- new_size = old_size;
- _cupsStrFree(old_size->map.ppd);
- _cupsStrFree(old_size->map.pwg);
- }
- }
-
- if (!similar)
- {
- /*
- * The paper was unique enough to deserve its own entry so add it to the
- * end.
- */
-
- new_size = pwg_size ++;
- pwg->num_sizes ++;
- }
-
- if (new_size)
- {
- /*
- * Save this size...
- */
-
- new_size->map.ppd = _cupsStrAlloc(ppd_size->name);
- new_size->map.pwg = _cupsStrAlloc(pwg_name);
- new_size->width = new_width;
- new_size->length = new_length;
- new_size->left = new_left;
- new_size->bottom = new_bottom;
- new_size->right = new_right;
- new_size->top = new_top;
- }
- }
-
- if (ppd->variable_sizes)
- {
- /*
- * Generate custom size data...
- */
-
- _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
- _PWG_FROMPTS(ppd->custom_max[0]),
- _PWG_FROMPTS(ppd->custom_max[1]));
- pwg->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
- pwg->custom_max_width = _PWG_FROMPTS(ppd->custom_max[0]);
- pwg->custom_max_length = _PWG_FROMPTS(ppd->custom_max[1]);
-
- _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
- _PWG_FROMPTS(ppd->custom_min[0]),
- _PWG_FROMPTS(ppd->custom_min[1]));
- pwg->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
- pwg->custom_min_width = _PWG_FROMPTS(ppd->custom_min[0]);
- pwg->custom_min_length = _PWG_FROMPTS(ppd->custom_min[1]);
-
- pwg->custom_size.left = _PWG_FROMPTS(ppd->custom_margins[0]);
- pwg->custom_size.bottom = _PWG_FROMPTS(ppd->custom_margins[1]);
- pwg->custom_size.right = _PWG_FROMPTS(ppd->custom_margins[2]);
- pwg->custom_size.top = _PWG_FROMPTS(ppd->custom_margins[3]);
- }
-
- /*
- * Copy and convert InputSlot data...
- */
-
- if ((input_slot = ppdFindOption(ppd, "InputSlot")) == NULL)
- input_slot = ppdFindOption(ppd, "HPPaperSource");
-
- if (input_slot)
- {
- pwg->source_option = _cupsStrAlloc(input_slot->keyword);
-
- if ((pwg->sources = calloc(input_slot->num_choices,
- sizeof(_pwg_map_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's "
- "for InputSlot.", input_slot->num_choices));
- goto create_error;
- }
-
- pwg->num_sources = input_slot->num_choices;
-
- for (i = input_slot->num_choices, choice = input_slot->choices,
- map = pwg->sources;
- i > 0;
- i --, choice ++, map ++)
- {
- if (!strncasecmp(choice->choice, "Auto", 4) ||
- !strcasecmp(choice->choice, "Default"))
- pwg_name = "auto";
- else if (!strcasecmp(choice->choice, "Cassette"))
- pwg_name = "main";
- else if (!strcasecmp(choice->choice, "PhotoTray"))
- pwg_name = "photo";
- else if (!strcasecmp(choice->choice, "CDTray"))
- pwg_name = "disc";
- else if (!strncasecmp(choice->choice, "Multipurpose", 12) ||
- !strcasecmp(choice->choice, "MP") ||
- !strcasecmp(choice->choice, "MPTray"))
- pwg_name = "alternate";
- else if (!strcasecmp(choice->choice, "LargeCapacity"))
- pwg_name = "large-capacity";
- else if (!strncasecmp(choice->choice, "Lower", 5))
- pwg_name = "bottom";
- else if (!strncasecmp(choice->choice, "Middle", 6))
- pwg_name = "middle";
- else if (!strncasecmp(choice->choice, "Upper", 5))
- pwg_name = "top";
- else if (!strncasecmp(choice->choice, "Side", 4))
- pwg_name = "side";
- else if (!strcasecmp(choice->choice, "Roll") ||
- !strcasecmp(choice->choice, "Roll1"))
- pwg_name = "main-roll";
- else if (!strcasecmp(choice->choice, "Roll2"))
- pwg_name = "alternate-roll";
- else
- {
- /*
- * Convert PPD name to lowercase...
- */
-
- pwg_name = pwg_keyword;
- pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
- }
-
- map->pwg = _cupsStrAlloc(pwg_name);
- map->ppd = _cupsStrAlloc(choice->choice);
- }
- }
-
- /*
- * Copy and convert MediaType data...
- */
-
- if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL)
- {
- if ((pwg->types = calloc(media_type->num_choices,
- sizeof(_pwg_map_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's "
- "for MediaType.", media_type->num_choices));
- goto create_error;
- }
-
- pwg->num_types = media_type->num_choices;
-
- for (i = media_type->num_choices, choice = media_type->choices,
- map = pwg->types;
- i > 0;
- i --, choice ++, map ++)
- {
- if (!strncasecmp(choice->choice, "Auto", 4) ||
- !strcasecmp(choice->choice, "Any") ||
- !strcasecmp(choice->choice, "Default"))
- pwg_name = "auto";
- else if (!strncasecmp(choice->choice, "Card", 4))
- pwg_name = "cardstock";
- else if (!strncasecmp(choice->choice, "Env", 3))
- pwg_name = "envelope";
- else if (!strncasecmp(choice->choice, "Gloss", 5))
- pwg_name = "photographic-glossy";
- else if (!strcasecmp(choice->choice, "HighGloss"))
- pwg_name = "photographic-high-gloss";
- else if (!strcasecmp(choice->choice, "Matte"))
- pwg_name = "photographic-matte";
- else if (!strncasecmp(choice->choice, "Plain", 5))
- pwg_name = "stationery";
- else if (!strncasecmp(choice->choice, "Coated", 6))
- pwg_name = "stationery-coated";
- else if (!strcasecmp(choice->choice, "Inkjet"))
- pwg_name = "stationery-inkjet";
- else if (!strcasecmp(choice->choice, "Letterhead"))
- pwg_name = "stationery-letterhead";
- else if (!strncasecmp(choice->choice, "Preprint", 8))
- pwg_name = "stationery-preprinted";
- else if (!strncasecmp(choice->choice, "Transparen", 10))
- pwg_name = "transparency";
- else
- {
- /*
- * Convert PPD name to lowercase...
- */
-
- pwg_name = pwg_keyword;
- pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
- }
-
- map->pwg = _cupsStrAlloc(pwg_name);
- map->ppd = _cupsStrAlloc(choice->choice);
- }
- }
-
-
- /*
- * Copy and convert OutputBin data...
- */
-
- if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL)
- {
- if ((pwg->bins = calloc(output_bin->num_choices,
- sizeof(_pwg_map_t))) == NULL)
- {
- DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's "
- "for OutputBin.", output_bin->num_choices));
- goto create_error;
- }
-
- pwg->num_bins = output_bin->num_choices;
-
- for (i = output_bin->num_choices, choice = output_bin->choices,
- map = pwg->bins;
- i > 0;
- i --, choice ++, map ++)
- {
- pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
-
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(choice->choice);
- }
- }
-
- if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL)
- {
- /*
- * Copy and convert APPrinterPreset (output-mode + print-quality) data...
- */
-
- const char *quality, /* com.apple.print.preset.quality value */
- *output_mode, /* com.apple.print.preset.output-mode value */
- *color_model_val, /* ColorModel choice */
- *graphics_type, /* com.apple.print.preset.graphicsType value */
- *paper_coating; /* com.apple.print.preset.media-front-coating value */
-
-
- do
- {
- num_options = _ppdParseOptions(ppd_attr->value, 0, &options,
- _PPD_PARSE_ALL);
-
- if ((quality = cupsGetOption("com.apple.print.preset.quality",
- num_options, options)) != NULL)
- {
- /*
- * Get the print-quality for this preset...
- */
-
- if (!strcmp(quality, "low"))
- pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
- else if (!strcmp(quality, "high"))
- pwg_print_quality = _PWG_PRINT_QUALITY_HIGH;
- else
- pwg_print_quality = _PWG_PRINT_QUALITY_NORMAL;
-
- /*
- * Ignore graphicsType "Photo" presets that are not high quality.
- */
-
- graphics_type = cupsGetOption("com.apple.print.preset.graphicsType",
- num_options, options);
-
- if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && graphics_type &&
- !strcmp(graphics_type, "Photo"))
- continue;
-
- /*
- * Ignore presets for normal and draft quality where the coating
- * isn't "none" or "autodetect".
- */
-
- paper_coating = cupsGetOption(
- "com.apple.print.preset.media-front-coating",
- num_options, options);
-
- if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && paper_coating &&
- strcmp(paper_coating, "none") &&
- strcmp(paper_coating, "autodetect"))
- continue;
-
- /*
- * Get the output mode for this preset...
- */
-
- output_mode = cupsGetOption("com.apple.print.preset.output-mode",
- num_options, options);
- color_model_val = cupsGetOption("ColorModel", num_options, options);
-
- if (output_mode)
- {
- if (!strcmp(output_mode, "monochrome"))
- pwg_output_mode = _PWG_OUTPUT_MODE_MONOCHROME;
- else
- pwg_output_mode = _PWG_OUTPUT_MODE_COLOR;
- }
- else if (color_model_val)
- {
- if (!strcasecmp(color_model_val, "Gray"))
- pwg_output_mode = _PWG_OUTPUT_MODE_MONOCHROME;
- else
- pwg_output_mode = _PWG_OUTPUT_MODE_COLOR;
- }
- else
- pwg_output_mode = _PWG_OUTPUT_MODE_COLOR;
-
- /*
- * Save the options for this combination as needed...
- */
-
- if (!pwg->num_presets[pwg_output_mode][pwg_print_quality])
- pwg->num_presets[pwg_output_mode][pwg_print_quality] =
- _ppdParseOptions(ppd_attr->value, 0,
- pwg->presets[pwg_output_mode] +
- pwg_print_quality, _PPD_PARSE_OPTIONS);
- }
-
- cupsFreeOptions(num_options, options);
- }
- while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) != NULL);
- }
-
- if (!pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] &&
- !pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] &&
- !pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH])
- {
- /*
- * Try adding some common color options to create grayscale presets. These
- * are listed in order of popularity...
- */
-
- const char *color_option = NULL, /* Color control option */
- *gray_choice = NULL; /* Choice to select grayscale */
-
- if ((color_model = ppdFindOption(ppd, "ColorModel")) != NULL &&
- ppdFindChoice(color_model, "Gray"))
- {
- color_option = "ColorModel";
- gray_choice = "Gray";
- }
- else if ((color_model = ppdFindOption(ppd, "HPColorMode")) != NULL &&
- ppdFindChoice(color_model, "grayscale"))
- {
- color_option = "HPColorMode";
- gray_choice = "grayscale";
- }
- else if ((color_model = ppdFindOption(ppd, "BRMonoColor")) != NULL &&
- ppdFindChoice(color_model, "Mono"))
- {
- color_option = "BRMonoColor";
- gray_choice = "Mono";
- }
- else if ((color_model = ppdFindOption(ppd, "CNIJSGrayScale")) != NULL &&
- ppdFindChoice(color_model, "1"))
- {
- color_option = "CNIJSGrayScale";
- gray_choice = "1";
- }
- else if ((color_model = ppdFindOption(ppd, "HPColorAsGray")) != NULL &&
- ppdFindChoice(color_model, "True"))
- {
- color_option = "HPColorAsGray";
- gray_choice = "True";
- }
-
- if (color_option && gray_choice)
- {
- /*
- * Copy and convert ColorModel (output-mode) data...
- */
-
- cups_option_t *coption, /* Color option */
- *moption; /* Monochrome option */
-
- for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
- pwg_print_quality < _PWG_PRINT_QUALITY_MAX;
- pwg_print_quality ++)
- {
- if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][pwg_print_quality])
- {
- /*
- * Copy the color options...
- */
-
- num_options = pwg->num_presets[_PWG_OUTPUT_MODE_COLOR]
- [pwg_print_quality];
- options = calloc(sizeof(cups_option_t), num_options);
-
- if (options)
- {
- for (i = num_options, moption = options,
- coption = pwg->presets[_PWG_OUTPUT_MODE_COLOR]
- [pwg_print_quality];
- i > 0;
- i --, moption ++, coption ++)
- {
- moption->name = _cupsStrRetain(coption->name);
- moption->value = _cupsStrRetain(coption->value);
- }
-
- pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] =
- num_options;
- pwg->presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] =
- options;
- }
- }
- else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL)
- continue;
-
- /*
- * Add the grayscale option to the preset...
- */
-
- pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] =
- cupsAddOption(color_option, gray_choice,
- pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME]
- [pwg_print_quality],
- pwg->presets[_PWG_OUTPUT_MODE_MONOCHROME] +
- pwg_print_quality);
- }
- }
- }
-
- /*
- * Copy and convert Duplex (sides) data...
- */
-
- if ((duplex = ppdFindOption(ppd, "Duplex")) == NULL)
- if ((duplex = ppdFindOption(ppd, "JCLDuplex")) == NULL)
- if ((duplex = ppdFindOption(ppd, "EFDuplex")) == NULL)
- if ((duplex = ppdFindOption(ppd, "EFDuplexing")) == NULL)
- duplex = ppdFindOption(ppd, "KD03Duplex");
-
- if (duplex)
- {
- pwg->sides_option = _cupsStrAlloc(duplex->keyword);
-
- for (i = duplex->num_choices, choice = duplex->choices;
- i > 0;
- i --, choice ++)
- {
- if ((!strcasecmp(choice->choice, "None") ||
- !strcasecmp(choice->choice, "False")) && !pwg->sides_1sided)
- pwg->sides_1sided = _cupsStrAlloc(choice->choice);
- else if ((!strcasecmp(choice->choice, "DuplexNoTumble") ||
- !strcasecmp(choice->choice, "LongEdge") ||
- !strcasecmp(choice->choice, "Top")) && !pwg->sides_2sided_long)
- pwg->sides_2sided_long = _cupsStrAlloc(choice->choice);
- else if ((!strcasecmp(choice->choice, "DuplexTumble") ||
- !strcasecmp(choice->choice, "ShortEdge") ||
- !strcasecmp(choice->choice, "Bottom")) &&
- !pwg->sides_2sided_short)
- pwg->sides_2sided_short = _cupsStrAlloc(choice->choice);
- }
- }
-
- return (pwg);
-
- /*
- * If we get here we need to destroy the PWG mapping data and return NULL...
- */
-
- create_error:
-
- _cupsSetError(IPP_INTERNAL_ERROR, _("Out of memory."), 1);
- _pwgDestroy(pwg);
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetBin()' - Get the PWG output-bin keyword associated with a PPD
- * OutputBin.
- */
-
-const char * /* O - output-bin or NULL */
-_pwgGetBin(_pwg_t *pwg, /* I - PWG mapping data */
- const char *output_bin) /* I - PPD OutputBin string */
-{
- int i; /* Looping var */
-
-
- /*
- * Range check input...
- */
-
- if (!pwg || !output_bin)
- return (NULL);
-
- /*
- * Look up the OutputBin string...
- */
-
-
- for (i = 0; i < pwg->num_bins; i ++)
- if (!strcasecmp(output_bin, pwg->bins[i].ppd))
- return (pwg->bins[i].pwg);
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetInputSlot()' - Get the PPD InputSlot associated with the job
- * attributes or a keyword string.
- */
-
-const char * /* O - PPD InputSlot or NULL */
-_pwgGetInputSlot(_pwg_t *pwg, /* I - PWG mapping data */
- ipp_t *job, /* I - Job attributes or NULL */
- const char *keyword) /* I - Keyword string or NULL */
-{
- /*
- * Range check input...
- */
-
- if (!pwg || pwg->num_sources == 0 || (!job && !keyword))
- return (NULL);
-
- if (job && !keyword)
- {
- /*
- * Lookup the media-col attribute and any media-source found there...
- */
-
- ipp_attribute_t *media_col, /* media-col attribute */
- *media_source; /* media-source attribute */
- _pwg_size_t size; /* Dimensional size */
- int margins_set; /* Were the margins set? */
-
- media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
- if (media_col &&
- (media_source = ippFindAttribute(media_col->values[0].collection,
- "media-source",
- IPP_TAG_KEYWORD)) != NULL)
- {
- /*
- * Use the media-source value from media-col...
- */
-
- keyword = media_source->values[0].string.text;
- }
- else if (_pwgInitSize(&size, job, &margins_set))
- {
- /*
- * For media <= 5x7, look for a photo tray...
- */
-
- if (size.width <= (5 * 2540) && size.length <= (7 * 2540))
- keyword = "photo";
- }
- }
-
- if (keyword)
- {
- int i; /* Looping var */
-
- for (i = 0; i < pwg->num_sources; i ++)
- if (!strcasecmp(keyword, pwg->sources[i].pwg))
- return (pwg->sources[i].ppd);
- }
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetMediaType()' - Get the PPD MediaType associated with the job
- * attributes or a keyword string.
- */
-
-const char * /* O - PPD MediaType or NULL */
-_pwgGetMediaType(_pwg_t *pwg, /* I - PWG mapping data */
- ipp_t *job, /* I - Job attributes or NULL */
- const char *keyword) /* I - Keyword string or NULL */
-{
- /*
- * Range check input...
- */
-
- if (!pwg || pwg->num_types == 0 || (!job && !keyword))
- return (NULL);
-
- if (job && !keyword)
- {
- /*
- * Lookup the media-col attribute and any media-source found there...
- */
-
- ipp_attribute_t *media_col, /* media-col attribute */
- *media_type; /* media-type attribute */
-
- media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
- if (media_col)
- {
- if ((media_type = ippFindAttribute(media_col->values[0].collection,
- "media-type",
- IPP_TAG_KEYWORD)) == NULL)
- media_type = ippFindAttribute(media_col->values[0].collection,
- "media-type", IPP_TAG_NAME);
-
- if (media_type)
- keyword = media_type->values[0].string.text;
- }
- }
-
- if (keyword)
- {
- int i; /* Looping var */
-
- for (i = 0; i < pwg->num_types; i ++)
- if (!strcasecmp(keyword, pwg->types[i].pwg))
- return (pwg->types[i].ppd);
- }
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetOutputBin()' - Get the PPD OutputBin associated with the keyword
- * string.
- */
-
-const char * /* O - PPD OutputBin or NULL */
-_pwgGetOutputBin(_pwg_t *pwg, /* I - PWG mapping data */
- const char *output_bin)/* I - Keyword string */
-{
- int i; /* Looping var */
-
-
- /*
- * Range check input...
- */
-
- if (!pwg || !output_bin)
- return (NULL);
-
- /*
- * Look up the OutputBin string...
- */
-
-
- for (i = 0; i < pwg->num_bins; i ++)
- if (!strcasecmp(output_bin, pwg->bins[i].pwg))
- return (pwg->bins[i].ppd);
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetPageSize()' - Get the PPD PageSize associated with the job
- * attributes or a keyword string.
- */
-
-const char * /* O - PPD PageSize or NULL */
-_pwgGetPageSize(_pwg_t *pwg, /* I - PWG mapping data */
- ipp_t *job, /* I - Job attributes or NULL */
- const char *keyword, /* I - Keyword string or NULL */
- int *exact) /* I - 1 if exact match, 0 otherwise */
-{
- int i; /* Looping var */
- _pwg_size_t *size, /* Current size */
- *closest, /* Closest size */
- jobsize; /* Size data from job */
- int margins_set, /* Were the margins set? */
- dwidth, /* Difference in width */
- dlength, /* Difference in length */
- dleft, /* Difference in left margins */
- dright, /* Difference in right margins */
- dbottom, /* Difference in bottom margins */
- dtop, /* Difference in top margins */
- dmin, /* Minimum difference */
- dclosest; /* Closest difference */
- const char *ppd_name; /* PPD media name */
-
-
- DEBUG_printf(("_pwgGetPageSize(pwg=%p, job=%p, keyword=\"%s\", exact=%p)",
- pwg, job, keyword, exact));
-
- /*
- * Range check input...
- */
-
- if (!pwg || (!job && !keyword))
- return (NULL);
-
- if (exact)
- *exact = 0;
-
- ppd_name = keyword;
-
- if (job)
- {
- /*
- * Try getting the PPD media name from the job attributes...
- */
-
- ipp_attribute_t *attr; /* Job attribute */
-
- if ((attr = ippFindAttribute(job, "PageSize", IPP_TAG_ZERO)) == NULL)
- if ((attr = ippFindAttribute(job, "PageRegion", IPP_TAG_ZERO)) == NULL)
- attr = ippFindAttribute(job, "media", IPP_TAG_ZERO);
-
-#ifdef DEBUG
- if (attr)
- DEBUG_printf(("1_pwgGetPageSize: Found attribute %s (%s)", attr->name,
- ippTagString(attr->value_tag)));
- else
- DEBUG_puts("1_pwgGetPageSize: Did not find media attribute.");
-#endif /* DEBUG */
-
- if (attr && (attr->value_tag == IPP_TAG_NAME ||
- attr->value_tag == IPP_TAG_KEYWORD))
- ppd_name = attr->values[0].string.text;
- }
-
- DEBUG_printf(("1_pwgGetPageSize: ppd_name=\"%s\"", ppd_name));
-
- if (ppd_name)
- {
- /*
- * Try looking up the named PPD size first...
- */
-
- for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
- {
- DEBUG_printf(("2_pwgGetPageSize: size[%d]=[\"%s\" \"%s\"]",
- (int)(size - pwg->sizes), size->map.pwg, size->map.ppd));
-
- if (!strcasecmp(ppd_name, size->map.ppd))
- {
- if (exact)
- *exact = 1;
-
- DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\"", ppd_name));
-
- return (ppd_name);
- }
- }
- }
-
- if (job && !keyword)
- {
- /*
- * Get the size using media-col or media, with the preference being
- * media-col.
- */
-
- if (!_pwgInitSize(&jobsize, job, &margins_set))
- return (NULL);
- }
- else
- {
- /*
- * Get the size using a media keyword...
- */
-
- _pwg_media_t *media; /* Media definition */
-
-
- if ((media = _pwgMediaForPWG(keyword)) == NULL)
- if ((media = _pwgMediaForLegacy(keyword)) == NULL)
- if ((media = _pwgMediaForPPD(keyword)) == NULL)
- return (NULL);
-
- jobsize.width = media->width;
- jobsize.length = media->length;
- margins_set = 0;
- }
-
- /*
- * Now that we have the dimensions and possibly the margins, look at the
- * available sizes and find the match...
- */
-
- closest = NULL;
- dclosest = 999999999;
-
- if (!ppd_name || strncasecmp(ppd_name, "Custom.", 7) ||
- strncasecmp(ppd_name, "custom_", 7))
- {
- for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
- {
- /*
- * Adobe uses a size matching algorithm with an epsilon of 5 points, which
- * is just about 176/2540ths...
- */
-
- dwidth = size->width - jobsize.width;
- dlength = size->length - jobsize.length;
-
- if (dwidth <= -176 || dwidth >= 176 || dlength <= -176 || dlength >= 176)
- continue;
-
- if (margins_set)
- {
- /*
- * Use a tighter epsilon of 1 point (35/2540ths) for margins...
- */
-
- dleft = size->left - jobsize.left;
- dright = size->right - jobsize.right;
- dtop = size->top - jobsize.top;
- dbottom = size->bottom - jobsize.bottom;
-
- if (dleft <= -35 || dleft >= 35 || dright <= -35 || dright >= 35 ||
- dtop <= -35 || dtop >= 35 || dbottom <= -35 || dbottom >= 35)
- {
- dleft = dleft < 0 ? -dleft : dleft;
- dright = dright < 0 ? -dright : dright;
- dbottom = dbottom < 0 ? -dbottom : dbottom;
- dtop = dtop < 0 ? -dtop : dtop;
- dmin = dleft + dright + dbottom + dtop;
-
- if (dmin < dclosest)
- {
- dclosest = dmin;
- closest = size;
- }
-
- continue;
- }
- }
-
- if (exact)
- *exact = 1;
-
- DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\"", size->map.ppd));
-
- return (size->map.ppd);
- }
- }
-
- if (closest)
- {
- DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\" (closest)",
- closest->map.ppd));
-
- return (closest->map.ppd);
- }
-
- /*
- * If we get here we need to check for custom page size support...
- */
-
- if (jobsize.width >= pwg->custom_min_width &&
- jobsize.width <= pwg->custom_max_width &&
- jobsize.length >= pwg->custom_min_length &&
- jobsize.length <= pwg->custom_max_length)
- {
- /*
- * In range, format as Custom.WWWWxLLLL (points).
- */
-
- snprintf(pwg->custom_ppd_size, sizeof(pwg->custom_ppd_size), "Custom.%dx%d",
- (int)_PWG_TOPTS(jobsize.width), (int)_PWG_TOPTS(jobsize.length));
-
- if (margins_set && exact)
- {
- dleft = pwg->custom_size.left - jobsize.left;
- dright = pwg->custom_size.right - jobsize.right;
- dtop = pwg->custom_size.top - jobsize.top;
- dbottom = pwg->custom_size.bottom - jobsize.bottom;
-
- if (dleft > -35 && dleft < 35 && dright > -35 && dright < 35 &&
- dtop > -35 && dtop < 35 && dbottom > -35 && dbottom < 35)
- *exact = 1;
- }
- else if (exact)
- *exact = 1;
-
- DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\" (custom)",
- pwg->custom_ppd_size));
-
- return (pwg->custom_ppd_size);
- }
-
- /*
- * No custom page size support or the size is out of range - return NULL.
- */
-
- DEBUG_puts("1_pwgGetPageSize: Returning NULL");
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetSize()' - Get the PWG size associated with a PPD PageSize.
- */
-
-_pwg_size_t * /* O - PWG size or NULL */
-_pwgGetSize(_pwg_t *pwg, /* I - PWG mapping data */
- const char *page_size) /* I - PPD PageSize */
-{
- int i;
- _pwg_size_t *size; /* Current size */
-
-
- /*
- * Range check input...
- */
-
- if (!pwg || !page_size)
- return (NULL);
-
- if (!strncasecmp(page_size, "Custom.", 7))
- {
- /*
- * Custom size; size name can be one of the following:
- *
- * Custom.WIDTHxLENGTHin - Size in inches
- * Custom.WIDTHxLENGTHft - Size in feet
- * Custom.WIDTHxLENGTHcm - Size in centimeters
- * Custom.WIDTHxLENGTHmm - Size in millimeters
- * Custom.WIDTHxLENGTHm - Size in meters
- * Custom.WIDTHxLENGTH[pt] - Size in points
- */
-
- double w, l; /* Width and length of page */
- char *ptr; /* Pointer into PageSize */
- struct lconv *loc; /* Locale data */
-
- loc = localeconv();
- w = (float)_cupsStrScand(page_size + 7, &ptr, loc);
- if (!ptr || *ptr != 'x')
- return (NULL);
-
- l = (float)_cupsStrScand(ptr + 1, &ptr, loc);
- if (!ptr)
- return (NULL);
-
- if (!strcasecmp(ptr, "in"))
- {
- w *= 2540.0;
- l *= 2540.0;
- }
- else if (!strcasecmp(ptr, "ft"))
- {
- w *= 12.0 * 2540.0;
- l *= 12.0 * 2540.0;
- }
- else if (!strcasecmp(ptr, "mm"))
- {
- w *= 100.0;
- l *= 100.0;
- }
- else if (!strcasecmp(ptr, "cm"))
- {
- w *= 1000.0;
- l *= 1000.0;
- }
- else if (!strcasecmp(ptr, "m"))
- {
- w *= 100000.0;
- l *= 100000.0;
- }
- else
- {
- w *= 2540.0 / 72.0;
- l *= 2540.0 / 72.0;
- }
-
- pwg->custom_size.width = (int)w;
- pwg->custom_size.length = (int)l;
-
- return (&(pwg->custom_size));
- }
-
- /*
- * Not a custom size - look it up...
- */
-
- for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
- if (!strcasecmp(page_size, size->map.ppd))
- return (size);
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetSource()' - Get the PWG media-source associated with a PPD InputSlot.
- */
-
-const char * /* O - PWG media-source keyword */
-_pwgGetSource(_pwg_t *pwg, /* I - PWG mapping data */
- const char *input_slot) /* I - PPD InputSlot */
-{
- int i; /* Looping var */
- _pwg_map_t *source; /* Current source */
-
-
- /*
- * Range check input...
- */
-
- if (!pwg || !input_slot)
- return (NULL);
-
- for (i = pwg->num_sources, source = pwg->sources; i > 0; i --, source ++)
- if (!strcasecmp(input_slot, source->ppd))
- return (source->pwg);
-
- return (NULL);
-}
-
-
-/*
- * '_pwgGetType()' - Get the PWG media-type associated with a PPD MediaType.
- */
-
-const char * /* O - PWG media-type keyword */
-_pwgGetType(_pwg_t *pwg, /* I - PWG mapping data */
- const char *media_type) /* I - PPD MediaType */
-{
- int i; /* Looping var */
- _pwg_map_t *type; /* Current type */
-
-
- /*
- * Range check input...
- */
-
- if (!pwg || !media_type)
- return (NULL);
-
- for (i = pwg->num_types, type = pwg->types; i > 0; i --, type ++)
- if (!strcasecmp(media_type, type->ppd))
- return (type->pwg);
-
- return (NULL);
-}
-
-
-/*
- * '_pwgInputSlotForSource()' - Get the InputSlot name for the given PWG source.
- */
-
-const char * /* O - InputSlot name */
-_pwgInputSlotForSource(
- const char *media_source, /* I - PWG media-source */
- char *name, /* I - Name buffer */
- size_t namesize) /* I - Size of name buffer */
-{
- /*
- * Range check input...
- */
-
- if (!media_source || !name || namesize < PPD_MAX_NAME)
- return (NULL);
-
- if (strcasecmp(media_source, "main"))
- strlcpy(name, "Cassette", namesize);
- else if (strcasecmp(media_source, "alternate"))
- strlcpy(name, "Multipurpose", namesize);
- else if (strcasecmp(media_source, "large-capacity"))
- strlcpy(name, "LargeCapacity", namesize);
- else if (strcasecmp(media_source, "bottom"))
- strlcpy(name, "Lower", namesize);
- else if (strcasecmp(media_source, "middle"))
- strlcpy(name, "Middle", namesize);
- else if (strcasecmp(media_source, "top"))
- strlcpy(name, "Upper", namesize);
- else if (strcasecmp(media_source, "rear"))
- strlcpy(name, "Rear", namesize);
- else if (strcasecmp(media_source, "side"))
- strlcpy(name, "Side", namesize);
- else if (strcasecmp(media_source, "envelope"))
- strlcpy(name, "Envelope", namesize);
- else if (strcasecmp(media_source, "main-roll"))
- strlcpy(name, "Roll", namesize);
- else if (strcasecmp(media_source, "alternate-roll"))
- strlcpy(name, "Roll2", namesize);
- else
- pwg_ppdize_name(media_source, name, namesize);
-
- return (name);
-}
-
-
-/*
- * '_pwgMediaTypeForType()' - Get the MediaType name for the given PWG type.
- */
-
-const char * /* O - MediaType name */
-_pwgMediaTypeForType(
- const char *media_type, /* I - PWG media-source */
- char *name, /* I - Name buffer */
- size_t namesize) /* I - Size of name buffer */
-{
- /*
- * Range check input...
- */
-
- if (!media_type || !name || namesize < PPD_MAX_NAME)
- return (NULL);
-
- if (strcasecmp(media_type, "auto"))
- strlcpy(name, "Auto", namesize);
- else if (strcasecmp(media_type, "cardstock"))
- strlcpy(name, "Cardstock", namesize);
- else if (strcasecmp(media_type, "envelope"))
- strlcpy(name, "Envelope", namesize);
- else if (strcasecmp(media_type, "photographic-glossy"))
- strlcpy(name, "Glossy", namesize);
- else if (strcasecmp(media_type, "photographic-high-gloss"))
- strlcpy(name, "HighGloss", namesize);
- else if (strcasecmp(media_type, "photographic-matte"))
- strlcpy(name, "Matte", namesize);
- else if (strcasecmp(media_type, "stationery"))
- strlcpy(name, "Plain", namesize);
- else if (strcasecmp(media_type, "stationery-coated"))
- strlcpy(name, "Coated", namesize);
- else if (strcasecmp(media_type, "stationery-inkjet"))
- strlcpy(name, "Inkjet", namesize);
- else if (strcasecmp(media_type, "stationery-letterhead"))
- strlcpy(name, "Letterhead", namesize);
- else if (strcasecmp(media_type, "stationery-preprinted"))
- strlcpy(name, "Preprinted", namesize);
- else if (strcasecmp(media_type, "transparency"))
- strlcpy(name, "Transparency", namesize);
- else
- pwg_ppdize_name(media_type, name, namesize);
-
- return (name);
-}
-
-
-/*
- * '_pwgPageSizeForMedia()' - Get the PageSize name for the given media.
- */
-
-const char * /* O - PageSize name */
-_pwgPageSizeForMedia(
- _pwg_media_t *media, /* I - Media */
- char *name, /* I - PageSize name buffer */
- size_t namesize) /* I - Size of name buffer */
-{
- const char *sizeptr, /* Pointer to size in PWG name */
- *dimptr; /* Pointer to dimensions in PWG name */
-
-
- /*
- * Range check input...
- */
-
- if (!media || !name || namesize < PPD_MAX_NAME)
- return (NULL);
-
- /*
- * Copy or generate a PageSize name...
- */
-
- if (media->ppd)
- {
- /*
- * Use a standard Adobe name...
- */
-
- strlcpy(name, media->ppd, namesize);
- }
- else if (!media->pwg || !strncmp(media->pwg, "custom_", 7) ||
- (sizeptr = strchr(media->pwg, '_')) == NULL ||
- (dimptr = strchr(sizeptr + 1, '_')) == NULL ||
- (size_t)(dimptr - sizeptr) > namesize)
- {
- /*
- * Use a name of the form "wNNNhNNN"...
- */
-
- snprintf(name, namesize, "w%dh%d", (int)_PWG_TOPTS(media->width),
- (int)_PWG_TOPTS(media->length));
- }
- else
- {
- /*
- * Copy the size name from class_sizename_dimensions...
- */
-
- memcpy(name, sizeptr + 1, dimptr - sizeptr - 1);
- name[dimptr - sizeptr - 1] = '\0';
- }
-
- return (name);
-}
-
-
-/*
- * 'pwg_ppdize_name()' - Convert an IPP keyword to a PPD keyword.
- */
-
-static void
-pwg_ppdize_name(const char *ipp, /* I - IPP keyword */
- char *name, /* I - Name buffer */
- size_t namesize) /* I - Size of name buffer */
-{
- char *ptr, /* Pointer into name buffer */
- *end; /* End of name buffer */
-
-
- *name = toupper(*ipp++);
-
- for (ptr = name + 1, end = name + namesize - 1; *ipp && ptr < end;)
- {
- if (*ipp == '-' && _cups_isalpha(ipp[1]))
- {
- ipp ++;
- *ptr++ = toupper(*ipp++ & 255);
- }
- else
- *ptr++ = *ipp++;
- }
-
- *ptr = '\0';
-}
-
-
-/*
- * 'pwg_unppdize_name()' - Convert a PPD keyword to a lowercase IPP keyword.
- */
-
-static void
-pwg_unppdize_name(const char *ppd, /* I - PPD keyword */
- char *name, /* I - Name buffer */
- size_t namesize) /* I - Size of name buffer */
-{
- char *ptr, /* Pointer into name buffer */
- *end; /* End of name buffer */
-
-
- for (ptr = name, end = name + namesize - 1; *ppd && ptr < end; ppd ++)
- {
- if (_cups_isalnum(*ppd) || *ppd == '-')
- *ptr++ = tolower(*ppd & 255);
- else if (*ppd == '_' || *ppd == '.')
- *ptr++ = '-';
-
- if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) &&
- _cups_isupper(ppd[1]) && ptr < end)
- *ptr++ = '-';
- }
-
- *ptr = '\0';
-}
-
-
-/*
- * End of "$Id$".
- */
diff --git a/cups/request.c b/cups/request.c
index cf8426fb6..641a51ce0 100644
--- a/cups/request.c
+++ b/cups/request.c
@@ -22,6 +22,7 @@
* cupsGetResponse() - Get a response to an IPP request.
* cupsLastError() - Return the last IPP status code.
* cupsLastErrorString() - Return the last IPP status-message.
+ * _cupsNextDelay() - Return the next retry delay value.
* cupsReadResponseData() - Read additional data after the IPP response.
* cupsSendRequest() - Send an IPP request.
* cupsWriteRequestData() - Write additional data after an IPP request.
@@ -414,11 +415,13 @@ cupsGetResponse(http_t *http, /* I - Connection to server or @code CUPS_HTTP
if (state == IPP_ERROR)
{
/*
- * Delete the response...
+ * Flush remaining data and delete the response...
*/
DEBUG_puts("1cupsGetResponse: IPP read error!");
+ httpFlush(http);
+
ippDelete(response);
response = NULL;
@@ -513,6 +516,36 @@ cupsLastErrorString(void)
/*
+ * '_cupsNextDelay()' - Return the next retry delay value.
+ *
+ * This function currently returns the Fibonacci sequence 1 1 2 3 5 8.
+ *
+ * Pass 0 for the current delay value to initialize the sequence.
+ */
+
+int /* O - Next delay value */
+_cupsNextDelay(int current, /* I - Current delay value or 0 */
+ int *previous) /* IO - Previous delay value */
+{
+ int next; /* Next delay value */
+
+
+ if (current > 0)
+ {
+ next = (current + *previous) % 12;
+ *previous = next < current ? 0 : current;
+ }
+ else
+ {
+ next = 1;
+ *previous = 0;
+ }
+
+ return (next);
+}
+
+
+/*
* 'cupsReadResponseData()' - Read additional data after the IPP response.
*
* This function is used after cupsGetResponse() to read the PPD or document
@@ -658,10 +691,10 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
* "replay" attack...
*/
- cupsDoAuthentication(http, "POST", resource);
+ _cupsSetNegotiateAuthString(http);
}
- else
#endif /* HAVE_GSSAPI */
+
httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
DEBUG_printf(("2cupsSendRequest: authstring=\"%s\"", http->authstring));
diff --git a/cups/sidechannel.c b/cups/sidechannel.c
index 17abb2b3f..460eae351 100644
--- a/cups/sidechannel.c
+++ b/cups/sidechannel.c
@@ -3,7 +3,7 @@
*
* Side-channel API code for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -205,7 +205,7 @@ cupsSideChannelRead(
*/
if (buffer[0] < CUPS_SC_CMD_SOFT_RESET ||
- buffer[0] > CUPS_SC_CMD_SNMP_GET_NEXT)
+ buffer[0] >= CUPS_SC_CMD_MAX)
{
DEBUG_printf(("1cupsSideChannelRead: Bad command %d!", buffer[0]));
*command = CUPS_SC_CMD_NONE;
@@ -499,7 +499,7 @@ cupsSideChannelWrite(
* Range check input...
*/
- if (command < CUPS_SC_CMD_SOFT_RESET || command > CUPS_SC_CMD_SNMP_GET_NEXT ||
+ if (command < CUPS_SC_CMD_SOFT_RESET || command >= CUPS_SC_CMD_MAX ||
datalen < 0 || datalen > 16384 || (datalen > 0 && !data))
return (-1);
diff --git a/cups/sidechannel.h b/cups/sidechannel.h
index c52cd51cb..29cc01a76 100644
--- a/cups/sidechannel.h
+++ b/cups/sidechannel.h
@@ -1,9 +1,9 @@
/*
* "$Id: sidechannel.h 7616 2008-05-28 00:34:13Z mike $"
*
- * Side-channel API definitions for the Common UNIX Printing System (CUPS).
+ * Side-channel API definitions for CUPS.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -62,11 +62,22 @@ enum cups_sc_command_e /**** Request command codes ****/
CUPS_SC_CMD_GET_DEVICE_ID = 4, /* Return the IEEE-1284 device ID */
CUPS_SC_CMD_GET_STATE = 5, /* Return the device state */
CUPS_SC_CMD_SNMP_GET = 6, /* Query an SNMP OID @since CUPS 1.4/Mac OS X 10.6@ */
- CUPS_SC_CMD_SNMP_GET_NEXT = 7 /* Query the next SNMP OID @since CUPS 1.4/Mac OS X 10.6@ */
+ CUPS_SC_CMD_SNMP_GET_NEXT = 7, /* Query the next SNMP OID @since CUPS 1.4/Mac OS X 10.6@ */
+ CUPS_SC_CMD_GET_CONNECTED = 8, /* Return whether the backend is "connected" to the printer @since CUPS 1.5@ */
+ CUPS_SC_CMD_MAX /* End of valid values @private@ */
};
typedef enum cups_sc_command_e cups_sc_command_t;
/**** Request command codes ****/
+enum cups_sc_connected_e /**** Connectivity values ****/
+{
+ CUPS_SC_NOT_CONNECTED = 0, /* Backend is not "connected" to printer */
+ CUPS_SC_CONNECTED = 1 /* Backend is "connected" to printer */
+};
+typedef enum cups_sc_connected_e cups_sc_connected_t;
+ /**** Connectivity values ****/
+
+
enum cups_sc_state_e /**** Printer state bits ****/
{
CUPS_SC_STATE_OFFLINE = 0, /* Device is offline */
diff --git a/cups/testppd.c b/cups/testppd.c
index 47cfa01e9..d788f9ace 100644
--- a/cups/testppd.c
+++ b/cups/testppd.c
@@ -3,7 +3,7 @@
*
* PPD test program for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -441,6 +441,21 @@ main(int argc, /* I - Number of command-line arguments */
else
puts("PASS");
+ fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout);
+ num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0,
+ &options);
+ cupsMarkOptions(ppd, num_options, options);
+ cupsFreeOptions(num_options, options);
+
+ size = ppdPageSize(ppd, NULL);
+ if (!size || strcmp(size->name, "Letter.Fullbleed"))
+ {
+ printf("FAIL (%s)\n", size ? size->name : "unknown");
+ status ++;
+ }
+ else
+ puts("PASS");
+
fputs("cupsMarkOptions(media=A4): ", stdout);
num_options = cupsAddOption("media", "A4", 0, &options);
cupsMarkOptions(ppd, num_options, options);
diff --git a/cups/testpwg.c b/cups/testpwg.c
index f15e11e4c..9cf2faadc 100644
--- a/cups/testpwg.c
+++ b/cups/testpwg.c
@@ -3,7 +3,7 @@
*
* PWG test program for CUPS.
*
- * Copyright 2009-2010 by Apple Inc.
+ * Copyright 2009-2011 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -15,9 +15,9 @@
*
* Contents:
*
- * main() - Main entry.
- * test_pagesize() - Test the PWG mapping functions.
- * test_pwg() - Test the PWG mapping functions.
+ * main() - Main entry.
+ * test_pagesize() - Test the PWG mapping functions.
+ * test_ppd_cache() - Test the PPD cache functions.
*/
/*
@@ -32,9 +32,9 @@
* Local functions...
*/
-static int test_pwg(_pwg_t *pwg, ppd_file_t *ppd);
-static int test_pagesize(_pwg_t *pwg, ppd_file_t *ppd,
+static int test_pagesize(_ppd_cache_t *pc, ppd_file_t *ppd,
const char *ppdsize);
+static int test_ppd_cache(_ppd_cache_t *pc, ppd_file_t *ppd);
/*
@@ -48,7 +48,7 @@ main(int argc, /* I - Number of command-line args */
int status; /* Status of tests (0 = success, 1 = fail) */
const char *ppdfile; /* PPD filename */
ppd_file_t *ppd; /* PPD file */
- _pwg_t *pwg; /* PWG mapping data */
+ _ppd_cache_t *pc; /* PPD cache and PWG mapping data */
_pwg_media_t *pwgmedia; /* PWG media size */
@@ -78,8 +78,8 @@ main(int argc, /* I - Number of command-line args */
else
puts("PASS");
- fputs("_pwgCreateWithPPD(ppd): ", stdout);
- if ((pwg = _pwgCreateWithPPD(ppd)) == NULL)
+ fputs("_ppdCacheCreateWithPPD(ppd): ", stdout);
+ if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
{
puts("FAIL");
status ++;
@@ -87,7 +87,7 @@ main(int argc, /* I - Number of command-line args */
else
{
puts("PASS");
- status += test_pwg(pwg, ppd);
+ status += test_ppd_cache(pc, ppd);
if (argc == 3)
{
@@ -112,13 +112,14 @@ main(int argc, /* I - Number of command-line args */
media = NULL;
if (media)
- printf("_pwgGetPageSize(media=%s): ", media->values[0].string.text);
+ printf("_ppdCacheGetPageSize(media=%s): ",
+ media->values[0].string.text);
else
- fputs("_pwgGetPageSize(media-col): ", stdout);
+ fputs("_ppdCacheGetPageSize(media-col): ", stdout);
fflush(stdout);
- if ((pagesize = _pwgGetPageSize(pwg, job, NULL, NULL)) == NULL)
+ if ((pagesize = _ppdCacheGetPageSize(pc, job, NULL, NULL)) == NULL)
{
puts("FAIL (Not Found)");
status = 1;
@@ -142,11 +143,11 @@ main(int argc, /* I - Number of command-line args */
}
/*
- * _pwgDestroy should never fail...
+ * _ppdCacheDestroy should never fail...
*/
- fputs("_pwgDestroy(pwg): ", stdout);
- _pwgDestroy(pwg);
+ fputs("_ppdCacheDestroy(pc): ", stdout);
+ _ppdCacheDestroy(pc);
puts("PASS");
}
@@ -268,9 +269,9 @@ main(int argc, /* I - Number of command-line args */
*/
static int /* O - 1 on failure, 0 on success */
-test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */
- ppd_file_t *ppd, /* I - PPD file */
- const char *ppdsize) /* I - PPD page size */
+test_pagesize(_ppd_cache_t *pc, /* I - PWG mapping data */
+ ppd_file_t *ppd, /* I - PPD file */
+ const char *ppdsize) /* I - PPD page size */
{
int status = 0; /* Return status */
ipp_t *job; /* Job attributes */
@@ -279,10 +280,10 @@ test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */
if (ppdPageSize(ppd, ppdsize))
{
- printf("_pwgGetPageSize(keyword=%s): ", ppdsize);
+ printf("_ppdCacheGetPageSize(keyword=%s): ", ppdsize);
fflush(stdout);
- if ((pagesize = _pwgGetPageSize(pwg, NULL, ppdsize, NULL)) == NULL)
+ if ((pagesize = _ppdCacheGetPageSize(pc, NULL, ppdsize, NULL)) == NULL)
{
puts("FAIL (Not Found)");
status = 1;
@@ -298,10 +299,10 @@ test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */
job = ippNew();
ippAddString(job, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media", NULL, ppdsize);
- printf("_pwgGetPageSize(media=%s): ", ppdsize);
+ printf("_ppdCacheGetPageSize(media=%s): ", ppdsize);
fflush(stdout);
- if ((pagesize = _pwgGetPageSize(pwg, job, NULL, NULL)) == NULL)
+ if ((pagesize = _ppdCacheGetPageSize(pc, job, NULL, NULL)) == NULL)
{
puts("FAIL (Not Found)");
status = 1;
@@ -322,16 +323,16 @@ test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */
/*
- * 'test_pwg()' - Test the PWG mapping functions.
+ * 'test_ppd_cache()' - Test the PPD cache functions.
*/
static int /* O - 1 on failure, 0 on success */
-test_pwg(_pwg_t *pwg, /* I - PWG mapping data */
- ppd_file_t *ppd) /* I - PPD file */
+test_ppd_cache(_ppd_cache_t *pc, /* I - PWG mapping data */
+ ppd_file_t *ppd) /* I - PPD file */
{
int i, /* Looping var */
status = 0; /* Return status */
- _pwg_t *pwg2; /* Loaded data */
+ _ppd_cache_t *pc2; /* Loaded data */
_pwg_size_t *size, /* Size from original */
*size2; /* Size from saved */
_pwg_map_t *map, /* Map from original */
@@ -342,8 +343,8 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */
* Verify that we can write and read back the same data...
*/
- fputs("_pwgWriteFile(test.pwg): ", stdout);
- if (!_pwgWriteFile(pwg, "test.pwg"))
+ fputs("_ppdCacheWriteFile(test.pwg): ", stdout);
+ if (!_ppdCacheWriteFile(pc, "test.pwg", NULL))
{
puts("FAIL");
status ++;
@@ -351,27 +352,28 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */
else
puts("PASS");
- fputs("_pwgCreateWithFile(test.pwg): ", stdout);
- if ((pwg2 = _pwgCreateWithFile("test.pwg")) == NULL)
+ fputs("_ppdCacheCreateWithFile(test.pwg): ", stdout);
+ if ((pc2 = _ppdCacheCreateWithFile("test.pwg", NULL)) == NULL)
{
puts("FAIL");
status ++;
}
else
{
- if (pwg2->num_sizes != pwg->num_sizes)
+ // TODO: FINISH ADDING ALL VALUES IN STRUCTURE
+ if (pc2->num_sizes != pc->num_sizes)
{
if (!status)
puts("FAIL");
- printf(" SAVED num_sizes=%d, ORIG num_sizes=%d\n", pwg2->num_sizes,
- pwg->num_sizes);
+ printf(" SAVED num_sizes=%d, ORIG num_sizes=%d\n", pc2->num_sizes,
+ pc->num_sizes);
status ++;
}
else
{
- for (i = pwg->num_sizes, size = pwg->sizes, size2 = pwg2->sizes;
+ for (i = pc->num_sizes, size = pc->sizes, size2 = pc2->sizes;
i > 0;
i --, size ++, size2 ++)
{
@@ -424,7 +426,7 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */
}
}
- for (i = pwg->num_sources, map = pwg->sources, map2 = pwg2->sources;
+ for (i = pc->num_sources, map = pc->sources, map2 = pc2->sources;
i > 0;
i --, map ++, map2 ++)
{
@@ -447,7 +449,7 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */
}
}
- for (i = pwg->num_types, map = pwg->types, map2 = pwg2->types;
+ for (i = pc->num_types, map = pc->types, map2 = pc2->types;
i > 0;
i --, map ++, map2 ++)
{
@@ -474,17 +476,17 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */
if (!status)
puts("PASS");
- _pwgDestroy(pwg2);
+ _ppdCacheDestroy(pc2);
}
/*
* Test PageSize mapping code...
*/
- status += test_pagesize(pwg, ppd, "Letter");
- status += test_pagesize(pwg, ppd, "na-letter");
- status += test_pagesize(pwg, ppd, "A4");
- status += test_pagesize(pwg, ppd, "iso-a4");
+ status += test_pagesize(pc, ppd, "Letter");
+ status += test_pagesize(pc, ppd, "na-letter");
+ status += test_pagesize(pc, ppd, "A4");
+ status += test_pagesize(pc, ppd, "iso-a4");
return (status);
}
diff --git a/filter/commandtops.c b/filter/commandtops.c
index 47a49072b..f858610a3 100644
--- a/filter/commandtops.c
+++ b/filter/commandtops.c
@@ -3,7 +3,7 @@
*
* PostScript command filter for CUPS.
*
- * Copyright 2008-2010 by Apple Inc.
+ * Copyright 2008-2011 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -162,6 +162,19 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */
*/
begin_ps(ppd, user);
+ fflush(stdout);
+
+ /*
+ * Wait for the printer to become connected...
+ */
+
+ do
+ {
+ sleep(1);
+ datalen = 1;
+ }
+ while (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_CONNECTED, buffer, &datalen,
+ 5.0) == CUPS_SC_STATUS_OK && !buffer[0]);
/*
* Then loop through every option in the PPD file and ask for the current
@@ -199,7 +212,7 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */
* Read the response data...
*/
- while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 5.0)) > 0)
+ while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 90.0)) > 0)
{
/*
* Trim whitespace from both ends...
@@ -215,6 +228,8 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */
for (bufptr = buffer; isspace(*bufptr & 255); bufptr ++);
+ fprintf(stderr, "DEBUG: Got \"%s\" (%d bytes)\n", bufptr, (int)bytes);
+
/*
* Skip blank lines...
*/
@@ -223,6 +238,13 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */
continue;
/*
+ * Verify the result is a valid option choice...
+ */
+
+ if (!ppdFindChoice(option, bufptr))
+ continue;
+
+ /*
* Write out the result and move on to the next option...
*/
diff --git a/filter/raster.c b/filter/raster.c
index d864634a9..a57dd1874 100644
--- a/filter/raster.c
+++ b/filter/raster.c
@@ -84,6 +84,7 @@ struct _cups_raster_s /**** Raster stream data ****/
* Local functions...
*/
+static int cups_raster_io(cups_raster_t *r, unsigned char *buf, int bytes);
static unsigned cups_raster_read_header(cups_raster_t *r);
static int cups_raster_read(cups_raster_t *r, unsigned char *buf,
int bytes);
@@ -189,7 +190,7 @@ cupsRasterOpenIO(
* Open for read - get sync word...
*/
- if ((*r->iocb)(r->ctx, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
+ if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
sizeof(r->sync))
{
_cupsRasterAddError("Unable to read header from raster stream: %s\n",
@@ -246,7 +247,7 @@ cupsRasterOpenIO(
break;
}
- if ((*r->iocb)(r->ctx, (unsigned char *)&(r->sync), sizeof(r->sync))
+ if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync))
< sizeof(r->sync))
{
_cupsRasterAddError("Unable to write raster stream header: %s\n",
@@ -284,7 +285,7 @@ cupsRasterReadHeader(
if (!cups_raster_read_header(r))
return (0);
-
+
/*
* Copy the header to the user-supplied buffer...
*/
@@ -313,7 +314,7 @@ cupsRasterReadHeader2(
if (!cups_raster_read_header(r))
return (0);
-
+
/*
* Copy the header to the user-supplied buffer...
*/
@@ -357,7 +358,7 @@ cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */
r->remaining -= len / r->header.cupsBytesPerLine;
- if ((*r->iocb)(r->ctx, p, len) < (ssize_t)len)
+ if (cups_raster_io(r, p, len) < (ssize_t)len)
return (0);
/*
@@ -538,7 +539,7 @@ cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */
*
* @deprecated@
*/
-
+
unsigned /* O - 1 on success, 0 on failure */
cupsRasterWriteHeader(
cups_raster_t *r, /* I - Raster stream */
@@ -581,10 +582,10 @@ cupsRasterWriteHeader(
fh.cupsColorOrder = htonl(r->header.cupsColorOrder);
fh.cupsColorSpace = htonl(r->header.cupsColorSpace);
- return ((*r->iocb)(r->ctx, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
+ return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
}
else
- return ((*r->iocb)(r->ctx, (unsigned char *)&(r->header), sizeof(r->header))
+ return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
== sizeof(r->header));
}
@@ -597,7 +598,7 @@ cupsRasterWriteHeader(
*
* @since CUPS 1.2/Mac OS X 10.5@
*/
-
+
unsigned /* O - 1 on success, 0 on failure */
cupsRasterWriteHeader2(
cups_raster_t *r, /* I - Raster stream */
@@ -639,10 +640,10 @@ cupsRasterWriteHeader2(
fh.cupsColorOrder = htonl(r->header.cupsColorOrder);
fh.cupsColorSpace = htonl(r->header.cupsColorSpace);
- return ((*r->iocb)(r->ctx, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
+ return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
}
else
- return ((*r->iocb)(r->ctx, (unsigned char *)&(r->header), sizeof(r->header))
+ return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
== sizeof(r->header));
}
@@ -722,10 +723,10 @@ cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
* Write the byte-swapped buffer...
*/
- return ((*r->iocb)(r->ctx, r->buffer, len));
+ return (cups_raster_io(r, r->buffer, len));
}
else
- return ((*r->iocb)(r->ctx, p, len));
+ return (cups_raster_io(r, p, len));
}
/*
@@ -898,6 +899,37 @@ cups_raster_read_header(
/*
+ * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
+ */
+
+static int /* O - Bytes read or -1 */
+cups_raster_io(cups_raster_t *r, /* I - Raster stream */
+ unsigned char *buf, /* I - Buffer for read/write */
+ int bytes) /* I - Number of bytes to read/write */
+{
+ ssize_t count; /* Number of bytes read/written */
+ size_t total; /* Total bytes read/written */
+
+
+ DEBUG_printf(("4cups_raster_io(r=%p, buf=%p, bytes=%d)", r, buf, bytes));
+
+ for (total = 0; total < bytes; total += count, buf += count)
+ {
+ count = (*r->iocb)(r->ctx, buf, bytes - total);
+
+ DEBUG_printf(("5cups_raster_io: count=%d, total=%d", (int)count,
+ (int)total));
+ if (count == 0)
+ return (0);
+ else if (count < 0)
+ return (-1);
+ }
+
+ return ((int)total);
+}
+
+
+/*
* 'cups_raster_read()' - Read through the raster buffer.
*/
@@ -914,7 +946,7 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */
DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r, buf, bytes));
if (!r->compressed)
- return ((*r->iocb)(r->ctx, buf, bytes));
+ return (cups_raster_io(r, buf, bytes));
/*
* Allocate a read buffer as needed...
@@ -1256,7 +1288,7 @@ cups_raster_write(
count ++;
ptr += bpp;
}
-
+
*wptr++ = 257 - count;
count *= bpp;
@@ -1265,7 +1297,7 @@ cups_raster_write(
}
}
- return ((*r->iocb)(r->ctx, r->buffer, wptr - r->buffer));
+ return (cups_raster_io(r, r->buffer, wptr - r->buffer));
}
@@ -1276,30 +1308,18 @@ cups_raster_write(
static ssize_t /* O - Bytes read or -1 */
cups_read_fd(void *ctx, /* I - File descriptor as pointer */
unsigned char *buf, /* I - Buffer for read */
- size_t bytes) /* I - Number of bytes to read */
+ size_t bytes) /* I - Maximum number of bytes to read */
{
int fd = (int)((intptr_t)ctx);
/* File descriptor */
ssize_t count; /* Number of bytes read */
- size_t total; /* Total bytes read */
-
- for (total = 0; total < bytes; total += count, buf += count)
- {
- count = read(fd, buf, bytes - total);
- if (count == 0)
- return (0);
- else if (count < 0)
- {
- if (errno == EINTR)
- count = 0;
- else
- return (-1);
- }
- }
+ while ((count = read(fd, buf, bytes)) < 0)
+ if (errno != EINTR && errno != EAGAIN)
+ return (-1);
- return ((ssize_t)total);
+ return (count);
}
@@ -1341,23 +1361,13 @@ cups_write_fd(void *ctx, /* I - File descriptor pointer */
int fd = (int)((intptr_t)ctx);
/* File descriptor */
ssize_t count; /* Number of bytes written */
- size_t total; /* Total bytes written */
-
- for (total = 0; total < bytes; total += count, buf += count)
- {
- count = write(fd, buf, bytes - total);
- if (count < 0)
- {
- if (errno == EINTR)
- count = 0;
- else
- return (-1);
- }
- }
+ while ((count = write(fd, buf, bytes)) < 0)
+ if (errno != EINTR && errno != EAGAIN)
+ return (-1);
- return ((ssize_t)total);
+ return (count);
}
diff --git a/filter/testraster.c b/filter/testraster.c
index 48085c4fb..a8188d11f 100644
--- a/filter/testraster.c
+++ b/filter/testraster.c
@@ -19,6 +19,7 @@
* main() - Test the raster functions.
* do_ppd_tests() - Test the default option commands in a PPD file.
* do_ps_tests() - Test standard PostScript commands.
+ * do_ras_file() - Test reading of a raster file.
* do_raster_tests() - Test reading and writing of raster data.
* print_changes() - Print differences in the page header.
*/
@@ -28,6 +29,12 @@
*/
#include "image-private.h"
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+#endif /* WIN32 */
/*
@@ -193,6 +200,7 @@ static cups_page_header2_t setpagedevice_header =
static int do_ppd_tests(const char *filename, int num_options,
cups_option_t *options);
static int do_ps_tests(void);
+static int do_ras_file(const char *filename);
static int do_raster_tests(cups_mode_t mode);
static void print_changes(cups_page_header2_t *header,
cups_page_header2_t *expected);
@@ -207,6 +215,7 @@ main(int argc, /* I - Number of command-line args */
char *argv[]) /* I - Command-line arguments */
{
int errors; /* Number of errors */
+ const char *ext; /* Filename extension */
if (argc == 1)
@@ -239,6 +248,7 @@ main(int argc, /* I - Number of command-line args */
else
{
puts("Usage: testraster [-o name=value ...] [filename.ppd ...]");
+ puts(" testraster [filename.ras ...]");
return (1);
}
}
@@ -246,11 +256,23 @@ main(int argc, /* I - Number of command-line args */
else
{
puts("Usage: testraster [-o name=value ...] [filename.ppd ...]");
+ puts(" testraster [filename.ras ...]");
return (1);
}
}
+ else if ((ext = strrchr(argv[i], '.')) != NULL)
+ {
+ if (!strcmp(ext, ".ppd"))
+ errors += do_ppd_tests(argv[i], num_options, options);
+ else
+ errors += do_ras_file(argv[i]);
+ }
else
- errors += do_ppd_tests(argv[i], num_options, options);
+ {
+ puts("Usage: testraster [-o name=value ...] [filename.ppd ...]");
+ puts(" testraster [filename.ras ...]");
+ return (1);
+ }
}
cupsFreeOptions(num_options, options);
@@ -352,7 +374,7 @@ do_ps_tests(void)
}
else
puts("PASS");
-
+
fputs("_cupsRasterExecPS(\"roll\"): ", stdout);
fflush(stdout);
@@ -431,92 +453,66 @@ do_ps_tests(void)
else
puts("PASS");
-#if 0
- fputs("_cupsRasterExecPS(\"\"): ", stdout);
- fflush(stdout);
+ return (errors);
+}
- if (_cupsRasterExecPS(&header, &preferred_bits,
- ""))
- {
- puts("FAIL (error from function)");
- errors ++;
- }
- else if (header.)
- {
- printf("FAIL ()\n");
- errors ++;
- }
- else
- puts("PASS");
- fputs("_cupsRasterExecPS(\"\"): ", stdout);
- fflush(stdout);
+/*
+ * 'do_ras_file()' - Test reading of a raster file.
+ */
- if (_cupsRasterExecPS(&header, &preferred_bits,
- ""))
- {
- puts("FAIL (error from function)");
- errors ++;
- }
- else if (header.)
- {
- printf("FAIL ()\n");
- errors ++;
- }
- else
- puts("PASS");
+static int /* O - Number of errors */
+do_ras_file(const char *filename) /* I - Filename */
+{
+ unsigned y; /* Looping vars */
+ int fd; /* File descriptor */
+ cups_raster_t *ras; /* Raster stream */
+ cups_page_header2_t header; /* Page header */
+ unsigned char *data; /* Raster data */
+ int errors = 0; /* Number of errors */
+ unsigned pages = 0; /* Number of pages */
- fputs("_cupsRasterExecPS(\"\"): ", stdout);
- fflush(stdout);
- if (_cupsRasterExecPS(&header, &preferred_bits,
- ""))
+ if ((fd = open(filename, O_RDONLY)) < 0)
{
- puts("FAIL (error from function)");
- errors ++;
+ printf("%s: %s\n", filename, strerror(errno));
+ return (1);
}
- else if (header.)
+
+ if ((ras = cupsRasterOpen(fd, CUPS_RASTER_READ)) == NULL)
{
- printf("FAIL ()\n");
- errors ++;
+ printf("%s: cupsRasterOpen failed.\n", filename);
+ close(fd);
+ return (1);
}
- else
- puts("PASS");
- fputs("_cupsRasterExecPS(\"\"): ", stdout);
- fflush(stdout);
+ printf("%s:\n", filename);
- if (_cupsRasterExecPS(&header, &preferred_bits,
- ""))
+ while (cupsRasterReadHeader2(ras, &header))
{
- puts("FAIL (error from function)");
- errors ++;
- }
- else if (header.)
- {
- printf("FAIL ()\n");
- errors ++;
- }
- else
- puts("PASS");
+ pages ++;
+ data = malloc(header.cupsBytesPerLine);
- fputs("_cupsRasterExecPS(\"\"): ", stdout);
- fflush(stdout);
+ printf(" Page %u: %ux%ux%u@%ux%udpi", pages,
+ header.cupsWidth, header.cupsHeight, header.cupsBitsPerPixel,
+ header.HWResolution[0], header.HWResolution[1]);
+ fflush(stdout);
- if (_cupsRasterExecPS(&header, &preferred_bits,
- ""))
- {
- puts("FAIL (error from function)");
- errors ++;
- }
- else if (header.)
- {
- printf("FAIL ()\n");
- errors ++;
+ for (y = 0; y < header.cupsHeight; y ++)
+ if (cupsRasterReadPixels(ras, data, header.cupsBytesPerLine) <
+ header.cupsBytesPerLine)
+ break;
+
+ if (y < header.cupsHeight)
+ printf(" ERROR AT LINE %d\n", y);
+ else
+ putchar('\n');
+
+ free(data);
}
- else
- puts("PASS");
-#endif /* 0 */
+
+ cupsRasterClose(ras);
+ close(fd);
return (errors);
}
diff --git a/notifier/dbus.c b/notifier/dbus.c
index 62a6aaffc..542a929da 100644
--- a/notifier/dbus.c
+++ b/notifier/dbus.c
@@ -332,7 +332,7 @@ main(int argc, /* I - Number of command-line args */
const char *word2 = event + 4; /* Second word */
params = PARAMS_JOB;
- if (!strcmp(word2, "state"))
+ if (!strcmp(word2, "state-changed"))
signame = "JobState";
else if (!strcmp(word2, "created"))
signame = "JobCreated";
diff --git a/ppdc/sample.drv b/ppdc/sample.drv
index 7a4426b75..9410cd787 100644
--- a/ppdc/sample.drv
+++ b/ppdc/sample.drv
@@ -315,6 +315,7 @@ Version "1.5"
Throughput 8
ModelNumber $HP_LASERJET
ColorDevice No
+ Attribute 1284DeviceID "" "CMD:PCL;"
UIConstraints "*Duplex *Option1 False"
UIConstraints "*PageSize A3 *InputSlot Envelope"
@@ -367,6 +368,7 @@ Version "1.5"
ColorDevice Yes
Attribute PSVersion "" "(2016.0) 0"
Attribute LanguageLevel "" 2
+ Attribute 1284DeviceID "" "CMD:PS;"
UIConstraints "*Duplex *Option1 False"
@@ -392,6 +394,7 @@ Version "1.5"
Duplex Yes
Installable "Option1/Duplexer"
+ Attribute "?Option1" "" "save currentpagedevice/Duplex known{(True)}{(False)}ifelse = flush restore"
}
}
@@ -409,6 +412,7 @@ Version "1.5"
ManualCopies Yes
ColorDevice Yes
Throughput 1
+ Attribute 1284DeviceID "" "MFG:HP;MDL:HP DeskJet;CMD:PCL;"
UIConstraints "*PageSize A3 *InputSlot Envelope"
UIConstraints "*PageSize A4 *InputSlot Envelope"
@@ -461,6 +465,7 @@ Version "1.5"
Throughput 8
ModelNumber $HP_LASERJET
ColorDevice No
+ Attribute 1284DeviceID "" "MFG:HP;MDL:HP LaserJet;CMD:PCL;"
UIConstraints "*Duplex *Option1 False"
UIConstraints "*PageSize A3 *InputSlot Envelope"
diff --git a/scheduler/auth.c b/scheduler/auth.c
index 191e17fc2..16c83b8cd 100644
--- a/scheduler/auth.c
+++ b/scheduler/auth.c
@@ -501,11 +501,23 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
struct passwd *pwd; /* Password entry for this user */
cupsd_ucred_t peercred; /* Peer credentials */
socklen_t peersize; /* Size of peer credentials */
+#ifdef HAVE_AUTHORIZATION_H
+ const char *name; /* Authorizing name */
+ for (name = (char *)cupsArrayFirst(con->best->names);
+ name;
+ name = (char *)cupsArrayNext(con->best->names))
+ if (!strncasecmp(name, "@AUTHKEY(", 9) || !strcasecmp(name, "@SYSTEM"))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "PeerCred authentication not allowed for resource.");
+ return;
+ }
+#endif /* HAVE_AUTHORIZATION_H */
if ((pwd = getpwnam(authorization + 9)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "User \"%s\" does not exist!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "User \"%s\" does not exist.",
authorization + 9);
return;
}
diff --git a/scheduler/conf.c b/scheduler/conf.c
index 26b80870c..193c03f8f 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -145,7 +145,6 @@ static const cupsd_var_t variables[] =
{ "MaxJobsPerUser", &MaxJobsPerUser, CUPSD_VARTYPE_INTEGER },
{ "MaxLeaseDuration", &MaxLeaseDuration, CUPSD_VARTYPE_INTEGER },
{ "MaxLogSize", &MaxLogSize, CUPSD_VARTYPE_INTEGER },
- { "MaxPrinterHistory", &MaxPrinterHistory, CUPSD_VARTYPE_INTEGER },
{ "MaxRequestSize", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
{ "MaxSubscriptions", &MaxSubscriptions, CUPSD_VARTYPE_INTEGER },
{ "MaxSubscriptionsPerJob", &MaxSubscriptionsPerJob, CUPSD_VARTYPE_INTEGER },
@@ -626,7 +625,6 @@ cupsdReadConfiguration(void)
MaxClients = 100;
MaxClientsPerHost = 0;
MaxLogSize = 1024 * 1024;
- MaxPrinterHistory = 0;
MaxRequestSize = 0;
MultipleOperationTimeout = DEFAULT_TIMEOUT;
ReloadTimeout = DEFAULT_KEEPALIVE;
diff --git a/scheduler/conf.h b/scheduler/conf.h
index 86a3e5a07..052725cce 100644
--- a/scheduler/conf.h
+++ b/scheduler/conf.h
@@ -183,8 +183,6 @@ VAR int MaxClients VALUE(100),
/* Maximum number of copies per job */
MaxLogSize VALUE(1024 * 1024),
/* Maximum size of log files */
- MaxPrinterHistory VALUE(10),
- /* Maximum printer state history */
MaxRequestSize VALUE(0),
/* Maximum size of IPP requests */
HostNameLookups VALUE(FALSE),
diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx
index 4b9d87855..5ddf5b3cf 100644
--- a/scheduler/cups-driverd.cxx
+++ b/scheduler/cups-driverd.cxx
@@ -1,13 +1,13 @@
/*
* "$Id$"
*
- * PPD/driver support for the Common UNIX Printing System (CUPS).
+ * PPD/driver support for CUPS.
*
* This program handles listing and installing static PPD files, PPD files
* created from driver information files, and dynamically generated PPD files
* using driver helper programs.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -2391,15 +2391,34 @@ regex_device_id(const char *device_id) /* I - IEEE-1284 device ID */
*ptr++ = '(';
- while (*device_id && *device_id != ';' && ptr < (res + sizeof(res) - 4))
+ while (*device_id && *device_id != ';' && ptr < (res + sizeof(res) - 8))
{
if (strchr("[]{}().*\\|", *device_id))
*ptr++ = '\\';
- *ptr++ = *device_id++;
+ if (*device_id == ':')
+ {
+ /*
+ * KEY:.*value
+ */
+
+ *ptr++ = *device_id++;
+ *ptr++ = '.';
+ *ptr++ = '*';
+ }
+ else
+ *ptr++ = *device_id++;
}
if (*device_id == ';' || !*device_id)
+ {
+ /*
+ * KEY:.*value.*;
+ */
+
+ *ptr++ = '.';
+ *ptr++ = '*';
*ptr++ = ';';
+ }
*ptr++ = ')';
if (cmd)
*ptr++ = '?';
diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
index bf1041287..99182c674 100644
--- a/scheduler/dirsvc.c
+++ b/scheduler/dirsvc.c
@@ -2396,7 +2396,7 @@ dnssdBuildTxtRecord(
keyvalue[i++][1] = for_lpd ? "100" : "0";
keyvalue[i ][0] = "product";
- keyvalue[i++][1] = p->product ? p->product : "Unknown";
+ keyvalue[i++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";
snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
snprintf(state_str, sizeof(state_str), "%d", p->state);
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
index fd1c6b6b5..9e3c80bc7 100644
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -926,8 +926,6 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */
printer->accepting = 1;
printer->state_message[0] = '\0';
- cupsdAddPrinterHistory(printer);
-
cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
"Now accepting jobs.");
@@ -1137,7 +1135,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */
pclass->name, attr->values[0].boolean, pclass->accepting);
pclass->accepting = attr->values[0].boolean;
- cupsdAddPrinterHistory(pclass);
cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s accepting jobs.",
pclass->accepting ? "Now" : "No longer");
@@ -1184,7 +1181,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */
{
strlcpy(pclass->state_message, attr->values[0].string.text,
sizeof(pclass->state_message));
- cupsdAddPrinterHistory(pclass);
cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s",
pclass->state_message);
@@ -1275,8 +1271,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */
}
else
{
- cupsdAddPrinterHistory(pclass);
-
cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED,
pclass, NULL, "New class \"%s\" added by \"%s\".",
pclass->name, get_username(con));
@@ -1546,7 +1540,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */
if (!ippFindAttribute(con->request, "PageRegion", IPP_TAG_ZERO) &&
!ippFindAttribute(con->request, "PageSize", IPP_TAG_ZERO) &&
- _pwgGetPageSize(printer->pwg, con->request, NULL, &exact))
+ _ppdCacheGetPageSize(printer->pc, con->request, NULL, &exact))
{
if (!exact &&
(media_col = ippFindAttribute(con->request, "media-col",
@@ -2697,7 +2691,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */
printer->name, attr->values[0].boolean, printer->accepting);
printer->accepting = attr->values[0].boolean;
- cupsdAddPrinterHistory(printer);
cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
"%s accepting jobs.",
@@ -2745,7 +2738,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */
{
strlcpy(printer->state_message, attr->values[0].string.text,
sizeof(printer->state_message));
- cupsdAddPrinterHistory(printer);
cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL, "%s",
printer->state_message);
@@ -2952,11 +2944,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */
char cache_name[1024]; /* Cache filename for printer attrs */
- snprintf(cache_name, sizeof(cache_name), "%s/%s.ipp4", CacheDir,
- printer->name);
- unlink(cache_name);
-
- snprintf(cache_name, sizeof(cache_name), "%s/%s.pwg3", CacheDir,
+ snprintf(cache_name, sizeof(cache_name), "%s/%s.data", CacheDir,
printer->name);
unlink(cache_name);
@@ -3047,8 +3035,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */
}
else
{
- cupsdAddPrinterHistory(printer);
-
cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED,
printer, NULL, "New printer \"%s\" added by \"%s\".",
printer->name, get_username(con));
@@ -6025,7 +6011,6 @@ copy_printer_attrs(
/* Printer icons */
time_t curtime; /* Current time */
int i; /* Looping var */
- ipp_attribute_t *history; /* History collection */
/*
@@ -6163,23 +6148,6 @@ copy_printer_attrs(
ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"printer-state-change-time", printer->state_time);
- if (MaxPrinterHistory > 0 && printer->num_history > 0 &&
- cupsArrayFind(ra, "printer-state-history"))
- {
- /*
- * Printer history is only sent if specifically requested, so that
- * older CUPS/IPP clients won't barf on the collection attributes.
- */
-
- history = ippAddCollections(con->response, IPP_TAG_PRINTER,
- "printer-state-history",
- printer->num_history, NULL);
-
- for (i = 0; i < printer->num_history; i ++)
- copy_attrs(history->values[i].collection = ippNew(), printer->history[i],
- NULL, IPP_TAG_ZERO, 0, NULL);
- }
-
if (!ra || cupsArrayFind(ra, "printer-state-message"))
ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-state-message", NULL, printer->state_message);
@@ -6191,7 +6159,6 @@ copy_printer_attrs(
{
int type; /* printer-type value */
-
/*
* Add the CUPS-specific printer-type attribute...
*/
@@ -7043,13 +7010,10 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */
printer->name);
unlink(filename);
- snprintf(filename, sizeof(filename), "%s/%s.ipp4", CacheDir, printer->name);
- unlink(filename);
-
snprintf(filename, sizeof(filename), "%s/%s.png", CacheDir, printer->name);
unlink(filename);
- snprintf(filename, sizeof(filename), "%s/%s.pwg3", CacheDir, printer->name);
+ snprintf(filename, sizeof(filename), "%s/%s.data", CacheDir, printer->name);
unlink(filename);
#ifdef __APPLE__
@@ -8980,7 +8944,6 @@ hold_new_jobs(cupsd_client_t *con, /* I - Connection */
printer->holding_new_jobs = 1;
cupsdSetPrinterReasons(printer, "+hold-new-jobs");
- cupsdAddPrinterHistory(printer);
if (dtype & CUPS_PRINTER_CLASS)
cupsdLogMessage(CUPSD_LOG_INFO,
@@ -9827,8 +9790,6 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */
strlcpy(printer->state_message, attr->values[0].string.text,
sizeof(printer->state_message));
- cupsdAddPrinterHistory(printer);
-
cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
"No longer accepting jobs.");
@@ -9904,7 +9865,6 @@ release_held_new_jobs(
printer->holding_new_jobs = 0;
cupsdSetPrinterReasons(printer, "-hold-new-jobs");
- cupsdAddPrinterHistory(printer);
if (dtype & CUPS_PRINTER_CLASS)
cupsdLogMessage(CUPSD_LOG_INFO,
diff --git a/scheduler/job.c b/scheduler/job.c
index efacdd318..d511e80f4 100644
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -291,7 +291,7 @@ cupsdCheckJobs(void)
if (job->kill_time && job->kill_time <= curtime)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job!",
job->id);
stop_job(job, CUPSD_JOB_FORCE);
@@ -904,9 +904,9 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */
if (filter && filter->dst)
{
- if (strchr(filter->dst->type, '/'))
+ if ((ptr = strchr(filter->dst->type, '/')) != NULL)
snprintf(final_content_type, sizeof(final_content_type),
- "FINAL_CONTENT_TYPE=%s", filter->dst->type);
+ "FINAL_CONTENT_TYPE=%s", ptr + 1);
else
snprintf(final_content_type, sizeof(final_content_type),
"FINAL_CONTENT_TYPE=%s/%s", filter->dst->super,
@@ -3034,12 +3034,13 @@ get_options(cupsd_job_t *job, /* I - Job */
char *optptr, /* Pointer to options */
*valptr; /* Pointer in value string */
ipp_attribute_t *attr; /* Current attribute */
- _pwg_t *pwg; /* PWG->PPD mapping data */
+ _ppd_cache_t *pc; /* PPD cache and mapping data */
int num_pwgppds; /* Number of PWG->PPD options */
cups_option_t *pwgppds, /* PWG->PPD options */
*pwgppd, /* Current PWG->PPD option */
*preset; /* Current preset option */
- int output_mode, /* Output mode (if any) */
+ int print_color_mode,
+ /* Output mode (if any) */
print_quality; /* Print quality (if any) */
const char *ppd; /* PPD option choice */
int exact; /* Did we get an exact match? */
@@ -3055,28 +3056,31 @@ get_options(cupsd_job_t *job, /* I - Job */
* First build an options array for any PWG->PPD mapped option/choice pairs.
*/
- pwg = job->printer->pwg;
+ pc = job->printer->pc;
num_pwgppds = 0;
pwgppds = NULL;
- if (pwg &&
+ if (pc &&
!ippFindAttribute(job->attrs,
"com.apple.print.DocumentTicket.PMSpoolFormat",
IPP_TAG_ZERO) &&
!ippFindAttribute(job->attrs, "APPrinterPreset", IPP_TAG_ZERO) &&
(ippFindAttribute(job->attrs, "output-mode", IPP_TAG_ZERO) ||
+ ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) ||
ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ZERO)))
{
/*
* Map output-mode and print-quality to a preset...
*/
- if ((attr = ippFindAttribute(job->attrs, "output-mode",
- IPP_TAG_KEYWORD)) != NULL &&
- !strcmp(attr->values[0].string.text, "monochrome"))
- output_mode = _PWG_OUTPUT_MODE_MONOCHROME;
+ if ((attr = ippFindAttribute(job->attrs, "print-color-mode",
+ IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "output-mode", IPP_TAG_KEYWORD);
+
+ if (attr && !strcmp(attr->values[0].string.text, "monochrome"))
+ print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME;
else
- output_mode = _PWG_OUTPUT_MODE_COLOR;
+ print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
if ((attr = ippFindAttribute(job->attrs, "print-quality",
IPP_TAG_ENUM)) != NULL &&
@@ -3086,33 +3090,33 @@ get_options(cupsd_job_t *job, /* I - Job */
else
print_quality = _PWG_PRINT_QUALITY_NORMAL;
- if (pwg->num_presets[output_mode][print_quality] == 0)
+ if (pc->num_presets[print_color_mode][print_quality] == 0)
{
/*
* Try to find a preset that works so that we maximize the chances of us
* getting a good print using IPP attributes.
*/
- if (pwg->num_presets[output_mode][_PWG_PRINT_QUALITY_NORMAL] > 0)
+ if (pc->num_presets[print_color_mode][_PWG_PRINT_QUALITY_NORMAL] > 0)
print_quality = _PWG_PRINT_QUALITY_NORMAL;
- else if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][print_quality] > 0)
- output_mode = _PWG_OUTPUT_MODE_COLOR;
+ else if (pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][print_quality] > 0)
+ print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
else
{
- print_quality = _PWG_PRINT_QUALITY_NORMAL;
- output_mode = _PWG_OUTPUT_MODE_COLOR;
+ print_quality = _PWG_PRINT_QUALITY_NORMAL;
+ print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
}
}
- if (pwg->num_presets[output_mode][print_quality] > 0)
+ if (pc->num_presets[print_color_mode][print_quality] > 0)
{
/*
* Copy the preset options as long as the corresponding names are not
* already defined in the IPP request...
*/
- for (i = pwg->num_presets[output_mode][print_quality],
- preset = pwg->presets[output_mode][print_quality];
+ for (i = pc->num_presets[print_color_mode][print_quality],
+ preset = pc->presets[print_color_mode][print_quality];
i > 0;
i --, preset ++)
{
@@ -3123,13 +3127,13 @@ get_options(cupsd_job_t *job, /* I - Job */
}
}
- if (pwg)
+ if (pc)
{
if (!ippFindAttribute(job->attrs, "InputSlot", IPP_TAG_ZERO) &&
!ippFindAttribute(job->attrs, "HPPaperSource", IPP_TAG_ZERO))
{
- if ((ppd = _pwgGetInputSlot(pwg, job->attrs, NULL)) != NULL)
- num_pwgppds = cupsAddOption(pwg->source_option, ppd, num_pwgppds,
+ if ((ppd = _ppdCacheGetInputSlot(pc, job->attrs, NULL)) != NULL)
+ num_pwgppds = cupsAddOption(pc->source_option, ppd, num_pwgppds,
&pwgppds);
else if (!ippFindAttribute(job->attrs, "AP_D_InputSlot", IPP_TAG_ZERO))
num_pwgppds = cupsAddOption("AP_D_InputSlot", "", num_pwgppds,
@@ -3137,12 +3141,12 @@ get_options(cupsd_job_t *job, /* I - Job */
}
if (!ippFindAttribute(job->attrs, "MediaType", IPP_TAG_ZERO) &&
- (ppd = _pwgGetMediaType(pwg, job->attrs, NULL)) != NULL)
+ (ppd = _ppdCacheGetMediaType(pc, job->attrs, NULL)) != NULL)
num_pwgppds = cupsAddOption("MediaType", ppd, num_pwgppds, &pwgppds);
if (!ippFindAttribute(job->attrs, "PageRegion", IPP_TAG_ZERO) &&
!ippFindAttribute(job->attrs, "PageSize", IPP_TAG_ZERO) &&
- (ppd = _pwgGetPageSize(pwg, job->attrs, NULL, &exact)) != NULL)
+ (ppd = _ppdCacheGetPageSize(pc, job->attrs, NULL, &exact)) != NULL)
{
num_pwgppds = cupsAddOption("PageSize", ppd, num_pwgppds, &pwgppds);
@@ -3155,7 +3159,7 @@ get_options(cupsd_job_t *job, /* I - Job */
IPP_TAG_ZERO)) != NULL &&
(attr->value_tag == IPP_TAG_KEYWORD ||
attr->value_tag == IPP_TAG_NAME) &&
- (ppd = _pwgGetOutputBin(pwg, attr->values[0].string.text)) != NULL)
+ (ppd = _ppdCacheGetOutputBin(pc, attr->values[0].string.text)) != NULL)
{
/*
* Map output-bin to OutputBin option...
@@ -3164,8 +3168,8 @@ get_options(cupsd_job_t *job, /* I - Job */
num_pwgppds = cupsAddOption("OutputBin", ppd, num_pwgppds, &pwgppds);
}
- if (pwg->sides_option &&
- !ippFindAttribute(job->attrs, pwg->sides_option, IPP_TAG_ZERO) &&
+ if (pc->sides_option &&
+ !ippFindAttribute(job->attrs, pc->sides_option, IPP_TAG_ZERO) &&
(attr = ippFindAttribute(job->attrs, "sides", IPP_TAG_KEYWORD)) != NULL)
{
/*
@@ -3173,13 +3177,13 @@ get_options(cupsd_job_t *job, /* I - Job */
*/
if (!strcmp(attr->values[0].string.text, "one-sided"))
- num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_1sided,
+ num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_1sided,
num_pwgppds, &pwgppds);
else if (!strcmp(attr->values[0].string.text, "two-sided-long-edge"))
- num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_2sided_long,
+ num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_long,
num_pwgppds, &pwgppds);
else if (!strcmp(attr->values[0].string.text, "two-sided-short-edge"))
- num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_2sided_short,
+ num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_short,
num_pwgppds, &pwgppds);
}
}
@@ -4210,10 +4214,7 @@ update_job(cupsd_job_t *job) /* I - Job to check */
return;
}
else if (cupsdSetPrinterReasons(job->printer, message))
- {
- cupsdAddPrinterHistory(job->printer);
event |= CUPSD_EVENT_PRINTER_STATE;
- }
update_job_attrs(job, 0);
}
@@ -4379,7 +4380,6 @@ update_job(cupsd_job_t *job) /* I - Job to check */
{
strlcpy(job->printer->state_message, ptr,
sizeof(job->printer->state_message));
- cupsdAddPrinterHistory(job->printer);
event |= CUPSD_EVENT_PRINTER_STATE | CUPSD_EVENT_JOB_PROGRESS;
diff --git a/scheduler/main.c b/scheduler/main.c
index 9d99264f5..2bed2e834 100644
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -1800,7 +1800,6 @@ process_children(void)
{
strlcpy(job->printer->state_message, message,
sizeof(job->printer->state_message));
- cupsdAddPrinterHistory(job->printer);
}
if (!job->attrs)
diff --git a/scheduler/printers.c b/scheduler/printers.c
index b04b75646..044902e2a 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -15,7 +15,6 @@
* Contents:
*
* cupsdAddPrinter() - Add a printer to the system.
- * cupsdAddPrinterHistory() - Add the current printer state to the history.
* cupsdCreateCommonData() - Create the common printer data.
* cupsdDeleteAllPrinters() - Delete all printers from the system.
* cupsdDeletePrinter() - Delete a printer from the system.
@@ -43,10 +42,8 @@
* add_printer_filter() - Add a MIME filter for a printer.
* add_printer_formats() - Add document-format-supported values for a
* printer.
- * add_string_array() - Add a string to an array of CUPS strings.
* compare_printers() - Compare two printers.
* delete_printer_filters() - Delete all MIME filters for a printer.
- * delete_string_array() - Delete an array of CUPS strings.
* dirty_printer() - Mark config and state files dirty for the
* specified printer.
* load_ppd() - Load a cached PPD file, updating the cache as
@@ -89,10 +86,8 @@ static void add_printer_defaults(cupsd_printer_t *p);
static void add_printer_filter(cupsd_printer_t *p, mime_type_t *type,
const char *filter);
static void add_printer_formats(cupsd_printer_t *p);
-static void add_string_array(cups_array_t **a, const char *s);
static int compare_printers(void *first, void *second, void *data);
static void delete_printer_filters(cupsd_printer_t *p);
-static void delete_string_array(cups_array_t **a);
static void dirty_printer(cupsd_printer_t *p);
static void load_ppd(cupsd_printer_t *p);
static ipp_t *new_media_col(_pwg_size_t *size, const char *source,
@@ -155,9 +150,6 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */
p->op_policy_ptr = DefaultPolicyPtr;
- if (MaxPrinterHistory)
- p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *));
-
/*
* Insert the printer in the printer list alphabetically...
*/
@@ -181,67 +173,6 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */
/*
- * 'cupsdAddPrinterHistory()' - Add the current printer state to the history.
- */
-
-void
-cupsdAddPrinterHistory(
- cupsd_printer_t *p) /* I - Printer */
-{
- ipp_t *history; /* History collection */
-
-
- /*
- * Stop early if we aren't keeping history data...
- */
-
- if (MaxPrinterHistory <= 0)
- return;
-
- /*
- * Retire old history data as needed...
- */
-
- p->sequence_number ++;
-
- if (p->num_history >= MaxPrinterHistory)
- {
- p->num_history --;
- ippDelete(p->history[0]);
- memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *));
- }
-
- /*
- * Create a collection containing the current printer-state, printer-up-time,
- * printer-state-message, and printer-state-reasons attributes.
- */
-
- history = ippNew();
- ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
- p->state);
- ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-accepting-jobs",
- p->accepting);
- ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-shared", p->shared);
- ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message",
- NULL, p->state_message);
- if (p->num_reasons == 0)
- ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "printer-state-reasons", NULL, "none");
- else
- ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "printer-state-reasons", p->num_reasons, NULL,
- (const char * const *)p->reasons);
- ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "printer-state-change-time", p->state_time);
- ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "printer-state-sequence-number", p->sequence_number);
-
- p->history[p->num_history] = history;
- p->num_history ++;
-}
-
-
-/*
* 'cupsdCreateCommonData()' - Create the common printer data.
*/
@@ -880,14 +811,6 @@ cupsdDeletePrinter(
if (p->printers != NULL)
free(p->printers);
- if (MaxPrinterHistory)
- {
- for (i = 0; i < p->num_history; i ++)
- ippDelete(p->history[i]);
-
- free(p->history);
- }
-
delete_printer_filters(p);
for (i = 0; i < p->num_reasons; i ++)
@@ -899,9 +822,6 @@ cupsdDeletePrinter(
mimeDeleteType(MimeDatabase, p->filetype);
mimeDeleteType(MimeDatabase, p->prefiltertype);
- delete_string_array(&(p->filters));
- delete_string_array(&(p->pre_filters));
-
cupsdFreeStrings(&(p->users));
cupsdFreeQuotas(p);
@@ -923,7 +843,6 @@ cupsdDeletePrinter(
cupsdClearString(&p->alert_description);
#ifdef HAVE_DNSSD
- cupsdClearString(&p->product);
cupsdClearString(&p->pdl);
#endif /* HAVE_DNSSD */
@@ -1059,7 +978,6 @@ cupsdLoadAllPrinters(void)
*/
cupsdSetPrinterAttrs(p);
- cupsdAddPrinterHistory(p);
if (strncmp(p->device_uri, "file:", 5) &&
p->state != IPP_PRINTER_STOPPED)
@@ -1251,44 +1169,6 @@ cupsdLoadAllPrinters(void)
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
}
- else if (!strcasecmp(line, "Product"))
- {
- if (value)
- {
-#ifdef HAVE_DNSSD
- p->product = _cupsStrAlloc(value);
-#endif /* HAVE_DNSSD */
- }
- else
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Syntax error on line %d of printers.conf.", linenum);
- }
- else if (!strcasecmp(line, "Filter"))
- {
- if (value)
- {
- if (!p->filters)
- p->filters = cupsArrayNew(NULL, NULL);
-
- cupsArrayAdd(p->filters, _cupsStrAlloc(value));
- }
- else
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Syntax error on line %d of printers.conf.", linenum);
- }
- else if (!strcasecmp(line, "PreFilter"))
- {
- if (value)
- {
- if (!p->pre_filters)
- p->pre_filters = cupsArrayNew(NULL, NULL);
-
- cupsArrayAdd(p->pre_filters, _cupsStrAlloc(value));
- }
- else
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Syntax error on line %d of printers.conf.", linenum);
- }
else if (!strcasecmp(line, "Shared"))
{
/*
@@ -1671,21 +1551,6 @@ cupsdSaveAllPrinters(void)
cupsFilePrintf(fp, "Type %d\n", printer->type);
-#ifdef HAVE_DNSSD
- if (printer->product)
- cupsFilePutConf(fp, "Product", printer->product);
-#endif /* HAVE_DNSSD */
-
- for (ptr = (char *)cupsArrayFirst(printer->filters);
- ptr;
- ptr = (char *)cupsArrayNext(printer->filters))
- cupsFilePutConf(fp, "Filter", ptr);
-
- for (ptr = (char *)cupsArrayFirst(printer->pre_filters);
- ptr;
- ptr = (char *)cupsArrayNext(printer->pre_filters))
- cupsFilePutConf(fp, "PreFilter", ptr);
-
if (printer->accepting)
cupsFilePuts(fp, "Accepting Yes\n");
else
@@ -2469,18 +2334,55 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
cupsdSetPrinterReasons(p, "-cups-missing-filter-warning,"
"cups-insecure-filter-warning");
- for (filter = (char *)cupsArrayFirst(p->filters);
- filter;
- filter = (char *)cupsArrayNext(p->filters))
- add_printer_filter(p, p->filetype, filter);
+ if (p->pc && p->pc->filters)
+ {
+ for (filter = (char *)cupsArrayFirst(p->pc->filters);
+ filter;
+ filter = (char *)cupsArrayNext(p->pc->filters))
+ add_printer_filter(p, p->filetype, filter);
+ }
+ else if (!(p->type & CUPS_PRINTER_REMOTE))
+ {
+ char interface[1024]; /* Interface script */
+
+
+ snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot,
+ p->name);
+ if (!access(interface, X_OK))
+ {
+ /*
+ * Yes, we have a System V style interface script; use it!
+ */
+
+ snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s",
+ ServerRoot, p->name);
+ add_printer_filter(p, p->filetype, interface);
+ }
+ else
+ {
+ /*
+ * Add a filter from application/vnd.cups-raw to printer/name to
+ * handle "raw" printing by users.
+ */
+
+ add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -");
- if (p->pre_filters)
+ /*
+ * Add a PostScript filter, since this is still possibly PS printer.
+ */
+
+ add_printer_filter(p, p->filetype,
+ "application/vnd.cups-postscript 0 -");
+ }
+ }
+
+ if (p->pc && p->pc->prefilters)
{
p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name);
- for (filter = (char *)cupsArrayFirst(p->pre_filters);
+ for (filter = (char *)cupsArrayFirst(p->pc->prefilters);
filter;
- filter = (char *)cupsArrayNext(p->pre_filters))
+ filter = (char *)cupsArrayNext(p->pc->prefilters))
add_printer_filter(p, p->prefiltertype, filter);
}
}
@@ -2913,12 +2815,6 @@ cupsdSetPrinterState(
p->state_message[0] = '\0';
/*
- * Update the printer history...
- */
-
- cupsdAddPrinterHistory(p);
-
- /*
* Let the browse protocols reflect the change...
*/
@@ -3602,6 +3498,11 @@ add_printer_filter(
struct stat fileinfo; /* File information */
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "add_printer_filter(p=%p(%s), filtertype=%p(%s/%s), "
+ "filter=\"%s\")", p, p->name, filtertype, filtertype->super,
+ filtertype->type, filter);
+
/*
* Parse the filter string; it should be in one of the following formats:
*
@@ -3612,14 +3513,24 @@ add_printer_filter(
if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
super, type, dsuper, dtype, &cost, program) == 6)
{
- snprintf(dest, sizeof(dest), "%s/%s", dsuper, dtype);
+ snprintf(dest, sizeof(dest), "%s/%s/%s", p->name, dsuper, dtype);
+
+ if ((desttype = mimeType(MimeDatabase, "printer", dest)) == NULL)
+ {
+ desttype = mimeAddType(MimeDatabase, "printer", dest);
+ if (!p->dest_types)
+ p->dest_types = cupsArrayNew(NULL, NULL);
+
+ cupsArrayAdd(p->dest_types, desttype);
+ }
+
}
else
{
if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost,
program) == 4)
{
- strlcpy(dest, p->name, sizeof(dest));
+ desttype = filtertype;
}
else
{
@@ -3706,15 +3617,6 @@ add_printer_filter(
* Add the filter to the MIME database, supporting wildcards as needed...
*/
- if ((desttype = mimeType(MimeDatabase, "printer", dest)) == NULL)
- {
- desttype = mimeAddType(MimeDatabase, "printer", dest);
- if (!p->dest_types)
- p->dest_types = cupsArrayNew(NULL, NULL);
-
- cupsArrayAdd(p->dest_types, desttype);
- }
-
for (temptype = mimeFirstType(MimeDatabase);
temptype;
temptype = mimeNextType(MimeDatabase))
@@ -3909,21 +3811,6 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */
/*
- * 'add_string_array()' - Add a string to an array of CUPS strings.
- */
-
-static void
-add_string_array(cups_array_t **a, /* I - Array */
- const char *s) /* I - String */
-{
- if (!*a)
- *a = cupsArrayNew(NULL, NULL);
-
- cupsArrayAdd(*a, _cupsStrAlloc(s));
-}
-
-
-/*
* 'compare_printers()' - Compare two printers.
*/
@@ -3988,26 +3875,6 @@ delete_printer_filters(
/*
- * 'delete_string_array()' - Delete an array of CUPS strings.
- */
-
-static void
-delete_string_array(cups_array_t **a) /* I - Array */
-{
- char *ptr; /* Current string */
-
-
- for (ptr = (char *)cupsArrayFirst(*a);
- ptr;
- ptr = (char *)cupsArrayNext(*a))
- _cupsStrFree(ptr);
-
- cupsArrayDelete(*a);
- *a = NULL;
-}
-
-
-/*
* 'dirty_printer()' - Mark config and state files dirty for the specified
* printer.
*/
@@ -4035,11 +3902,8 @@ static void
load_ppd(cupsd_printer_t *p) /* I - Printer */
{
int i, j, k; /* Looping vars */
- cups_file_t *cache; /* IPP cache file */
- char cache_name[1024]; /* IPP cache filename */
- struct stat cache_info; /* IPP cache file info */
- char pwg_name[1024]; /* PWG cache filename */
- struct stat pwg_info; /* PWG cache file info */
+ char cache_name[1024]; /* Cache filename */
+ struct stat cache_info; /* Cache file info */
ppd_file_t *ppd; /* PPD file */
char ppd_name[1024]; /* PPD filename */
struct stat ppd_info; /* PPD file info */
@@ -4067,6 +3931,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
qualities[3]; /* print-quality values */
int num_margins, /* Number of media-*-margin-supported values */
margins[16]; /* media-*-margin-supported values */
+ const char *filter; /* Current filter */
static const char * const sides[3] = /* sides-supported values */
{
"one-sided",
@@ -4085,14 +3950,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* Check to see if the cache is up-to-date...
*/
- snprintf(cache_name, sizeof(cache_name), "%s/%s.ipp4", CacheDir, p->name);
+ snprintf(cache_name, sizeof(cache_name), "%s/%s.data", CacheDir, p->name);
if (stat(cache_name, &cache_info))
cache_info.st_mtime = 0;
- snprintf(pwg_name, sizeof(pwg_name), "%s/%s.pwg3", CacheDir, p->name);
- if (stat(pwg_name, &pwg_info))
- pwg_info.st_mtime = 0;
-
snprintf(ppd_name, sizeof(ppd_name), "%s/ppd/%s.ppd", ServerRoot, p->name);
if (stat(ppd_name, &ppd_info))
ppd_info.st_mtime = 1;
@@ -4100,29 +3961,22 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
ippDelete(p->ppd_attrs);
p->ppd_attrs = ippNew();
- _pwgDestroy(p->pwg);
- p->pwg = NULL;
-
- if (pwg_info.st_mtime >= ppd_info.st_mtime)
- p->pwg = _pwgCreateWithFile(pwg_name);
+ _ppdCacheDestroy(p->pc);
+ p->pc = NULL;
- if (cache_info.st_mtime >= ppd_info.st_mtime && p->pwg &&
- (cache = cupsFileOpen(cache_name, "r")) != NULL)
+ if (cache_info.st_mtime >= ppd_info.st_mtime)
{
- /*
- * Load cached information and return...
- */
-
cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", cache_name);
- if (ippReadIO(cache, (ipp_iocb_t)cupsFileRead, 1, NULL,
- p->ppd_attrs) == IPP_DATA)
+ if ((p->pc = _ppdCacheCreateWithFile(cache_name, &p->ppd_attrs)) != NULL &&
+ p->ppd_attrs)
{
- cupsFileClose(cache);
+ /*
+ * Loaded successfully!
+ */
+
return;
}
-
- cupsFileClose(cache);
}
/*
@@ -4131,14 +3985,8 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
- _pwgDestroy(p->pwg);
- p->pwg = NULL;
-
cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", ppd_name);
- delete_string_array(&(p->filters));
- delete_string_array(&(p->pre_filters));
-
p->type &= ~CUPS_PRINTER_OPTIONS;
p->type |= CUPS_PRINTER_BW;
@@ -4151,7 +3999,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* Add make/model and other various attributes...
*/
- p->pwg = _pwgCreateWithPPD(ppd);
+ p->pc = _ppdCacheCreateWithPPD(ppd);
ppdMarkDefaults(ppd);
@@ -4195,9 +4043,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
if (ppdFindChoice(output_mode, "draft") ||
ppdFindChoice(output_mode, "fast"))
qualities[num_qualities ++] = IPP_QUALITY_DRAFT;
- if (ppdFindChoice(output_mode, "normal") ||
- ppdFindChoice(output_mode, "good"))
- qualities[num_qualities ++] = IPP_QUALITY_NORMAL;
+
+ qualities[num_qualities ++] = IPP_QUALITY_NORMAL;
+
if (ppdFindChoice(output_mode, "best") ||
ppdFindChoice(output_mode, "high"))
qualities[num_qualities ++] = IPP_QUALITY_HIGH;
@@ -4219,8 +4067,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
qualities[num_qualities ++] = IPP_QUALITY_NORMAL;
qualities[num_qualities ++] = IPP_QUALITY_HIGH;
}
-
- if (num_qualities == 0)
+ else
qualities[num_qualities ++] = IPP_QUALITY_NORMAL;
ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
@@ -4255,7 +4102,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* Add media options from the PPD file...
*/
- if (ppd->num_sizes == 0 || !p->pwg)
+ if (ppd->num_sizes == 0 || !p->pc)
{
if (!ppdFindAttr(ppd, "APScannerOnly", NULL))
cupsdLogMessage(CUPSD_LOG_CRIT,
@@ -4274,7 +4121,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
*/
if ((size = ppdPageSize(ppd, NULL)) != NULL)
- pwgsize = _pwgGetSize(p->pwg, size->name);
+ pwgsize = _ppdCacheGetSize(p->pc, size->name);
else
pwgsize = NULL;
@@ -4294,12 +4141,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
media_type = ppdFindMarkedChoice(ppd, "MediaType");
col = new_media_col(pwgsize,
input_slot ?
- _pwgGetSource(p->pwg,
- input_slot->choice) :
+ _ppdCacheGetSource(p->pc,
+ input_slot->choice) :
NULL,
media_type ?
- _pwgGetType(p->pwg,
- media_type->choice) :
+ _ppdCacheGetType(p->pc,
+ media_type->choice) :
NULL);
ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-default",
@@ -4311,8 +4158,8 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* media-supported
*/
- num_media = p->pwg->num_sizes;
- if (p->pwg->custom_min_keyword)
+ num_media = p->pc->num_sizes;
+ if (p->pc->custom_min_keyword)
num_media += 2;
if ((attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
@@ -4321,16 +4168,16 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
{
val = attr->values;
- for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes;
+ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes;
i > 0;
i --, pwgsize ++, val ++)
val->string.text = _cupsStrRetain(pwgsize->map.pwg);
- if (p->pwg->custom_min_keyword)
+ if (p->pc->custom_min_keyword)
{
- val->string.text = _cupsStrRetain(p->pwg->custom_min_keyword);
+ val->string.text = _cupsStrRetain(p->pc->custom_min_keyword);
val ++;
- val->string.text = _cupsStrRetain(p->pwg->custom_max_keyword);
+ val->string.text = _cupsStrRetain(p->pc->custom_max_keyword);
}
}
@@ -4338,12 +4185,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* media-source-supported
*/
- if (p->pwg->num_sources > 0 &&
+ if (p->pc->num_sources > 0 &&
(attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "media-source-supported", p->pwg->num_sources,
+ "media-source-supported", p->pc->num_sources,
NULL, NULL)) != NULL)
{
- for (i = p->pwg->num_sources, pwgsource = p->pwg->sources,
+ for (i = p->pc->num_sources, pwgsource = p->pc->sources,
val = attr->values;
i > 0;
i --, pwgsource ++, val ++)
@@ -4354,12 +4201,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* media-type-supported
*/
- if (p->pwg->num_types > 0 &&
+ if (p->pc->num_types > 0 &&
(attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "media-type-supported", p->pwg->num_types,
+ "media-type-supported", p->pc->num_types,
NULL, NULL)) != NULL)
{
- for (i = p->pwg->num_types, pwgtype = p->pwg->types,
+ for (i = p->pc->num_types, pwgtype = p->pc->types,
val = attr->values;
i > 0;
i --, pwgtype ++, val ++)
@@ -4370,7 +4217,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* media-*-margin-supported
*/
- for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0;
+ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0;
i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0]));
i --, pwgsize ++)
{
@@ -4392,7 +4239,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"media-bottom-margin-supported", 0);
- for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0;
+ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0;
i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0]));
i --, pwgsize ++)
{
@@ -4414,7 +4261,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"media-left-margin-supported", 0);
- for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0;
+ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0;
i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0]));
i --, pwgsize ++)
{
@@ -4436,7 +4283,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"media-right-margin-supported", 0);
- for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0;
+ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0;
i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0]));
i --, pwgsize ++)
{
@@ -4462,23 +4309,23 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* media-col-database
*/
- num_media = p->pwg->num_sizes;
- if (p->pwg->num_sources)
+ num_media = p->pc->num_sizes;
+ if (p->pc->num_sources)
{
- if (p->pwg->num_types > 0)
- num_media += p->pwg->num_sizes * p->pwg->num_sources *
- p->pwg->num_types;
+ if (p->pc->num_types > 0)
+ num_media += p->pc->num_sizes * p->pc->num_sources *
+ p->pc->num_types;
else
- num_media += p->pwg->num_sizes * p->pwg->num_sources;
+ num_media += p->pc->num_sizes * p->pc->num_sources;
}
- else if (p->pwg->num_types)
- num_media += p->pwg->num_sizes * p->pwg->num_types;
+ else if (p->pc->num_types)
+ num_media += p->pc->num_sizes * p->pc->num_types;
if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER,
"media-col-database", num_media,
NULL)) != NULL)
{
- for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, val = attr->values;
+ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, val = attr->values;
i > 0;
i --, pwgsize ++)
{
@@ -4496,17 +4343,17 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* type...
*/
- if (p->pwg->num_sources > 0)
+ if (p->pc->num_sources > 0)
{
- for (j = p->pwg->num_sources, pwgsource = p->pwg->sources;
+ for (j = p->pc->num_sources, pwgsource = p->pc->sources;
j > 0;
j --, pwgsource ++)
{
ppdMarkOption(ppd, "InputSlot", pwgsource->ppd);
- if (p->pwg->num_types > 0)
+ if (p->pc->num_types > 0)
{
- for (k = p->pwg->num_types, pwgtype = p->pwg->types;
+ for (k = p->pc->num_types, pwgtype = p->pc->types;
k > 0;
k --, pwgtype ++)
{
@@ -4525,9 +4372,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
}
}
}
- else if (p->pwg->num_types > 0)
+ else if (p->pc->num_types > 0)
{
- for (j = p->pwg->num_types, pwgtype = p->pwg->types;
+ for (j = p->pc->num_types, pwgtype = p->pc->types;
j > 0;
j --, pwgtype ++)
{
@@ -4552,35 +4399,35 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
* Output bin...
*/
- if (p->pwg && p->pwg->num_bins > 0)
+ if (p->pc && p->pc->num_bins > 0)
{
attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-bin-supported", p->pwg->num_bins,
+ "output-bin-supported", p->pc->num_bins,
NULL, NULL);
if (attr != NULL)
{
for (i = 0, val = attr->values;
- i < p->pwg->num_bins;
+ i < p->pc->num_bins;
i ++, val ++)
- val->string.text = _cupsStrAlloc(p->pwg->bins[i].pwg);
+ val->string.text = _cupsStrAlloc(p->pc->bins[i].pwg);
}
if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL)
{
- for (i = 0; i < p->pwg->num_bins; i ++)
- if (!strcmp(p->pwg->bins[i].ppd, output_bin->defchoice))
+ for (i = 0; i < p->pc->num_bins; i ++)
+ if (!strcmp(p->pc->bins[i].ppd, output_bin->defchoice))
break;
- if (i >= p->pwg->num_bins)
+ if (i >= p->pc->num_bins)
i = 0;
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-bin-default", NULL, p->pwg->bins[i].pwg);
+ "output-bin-default", NULL, p->pc->bins[i].pwg);
}
else
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-bin-default", NULL, p->pwg->bins[0].pwg);
+ "output-bin-default", NULL, p->pc->bins[0].pwg);
}
else if (((ppd_attr = ppdFindAttr(ppd, "DefaultOutputOrder",
NULL)) != NULL &&
@@ -4608,7 +4455,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
}
/*
- * output-mode...
+ * output-mode and print-color-mode...
*/
if (ppd->color_device)
@@ -4623,6 +4470,11 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
"output-mode-supported", 2, NULL, output_modes);
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"output-mode-default", NULL, "color");
+
+ ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "print-color-mode-supported", 2, NULL, output_modes);
+ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "print-color-mode-default", NULL, "color");
}
else
{
@@ -4630,6 +4482,11 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
"output-mode-supported", NULL, "monochrome");
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"output-mode-default", NULL, "monochrome");
+
+ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "print-color-mode-supported", NULL, "monochrome");
+ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "print-color-mode-default", NULL, "monochrome");
}
/*
@@ -4795,106 +4652,21 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
}
/*
- * Add a filter from application/vnd.cups-raw to printer/name to
- * handle "raw" printing by users.
+ * Scan the filters in the PPD file...
*/
- add_string_array(&(p->filters), "application/vnd.cups-raw 0 -");
-
- /*
- * Add any pre-filters in the PPD file...
- */
-
- if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
- {
- for (; ppd_attr; ppd_attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL))
- if (ppd_attr->value)
- add_string_array(&(p->pre_filters), ppd_attr->value);
- }
-
- /*
- * Add any filters in the PPD file...
- */
-
- if ((ppd_attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) != NULL)
- {
- /*
- * Use new cupsFilter2 filter syntax...
- */
-
- for (; ppd_attr; ppd_attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL))
- {
- add_string_array(&(p->filters), ppd_attr->value);
-
- if (!strncasecmp(ppd_attr->value, "application/vnd.cups-command", 28) &&
- isspace(ppd_attr->value[28] & 255))
- p->type |= CUPS_PRINTER_COMMANDS;
- }
- }
- else
+ if (p->pc)
{
- /*
- * Use old cupsFilter syntax...
- */
-
- DEBUG_printf(("ppd->num_filters = %d\n", ppd->num_filters));
- for (i = 0; i < ppd->num_filters; i ++)
+ for (filter = (const char *)cupsArrayFirst(p->pc->filters);
+ filter;
+ filter = (const char *)cupsArrayNext(p->pc->filters))
{
- DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i]));
- add_string_array(&(p->filters), ppd->filters[i]);
-
- if (!strncasecmp(ppd->filters[i], "application/vnd.cups-command", 28) &&
- isspace(ppd->filters[i][28] & 255))
- p->type |= CUPS_PRINTER_COMMANDS;
- }
- }
-
- if ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL &&
- ppd_attr->value &&
- (!ppd_attr->value[0] || !strcasecmp(ppd_attr->value, "none")))
- {
- /*
- * Printer does not support CUPS command files (or any commands as far as
- * CUPS is concerned...
- */
-
- p->type &= ~CUPS_PRINTER_COMMANDS;
- }
- else if (ppd->num_filters == 0)
- {
- /*
- * If there are no filters, add PostScript printing filters.
- */
-
- add_string_array(&(p->filters),
- "application/vnd.cups-command 0 commandtops");
- add_string_array(&(p->filters),
- "application/vnd.cups-postscript 0 -");
-
- p->type |= CUPS_PRINTER_COMMANDS;
- }
- else if (!(p->type & CUPS_PRINTER_COMMANDS))
- {
- /*
- * See if this is a PostScript device without a command filter...
- */
-
- for (i = 0; i < ppd->num_filters; i ++)
- if (!strncasecmp(ppd->filters[i],
- "application/vnd.cups-postscript", 31) &&
- isspace(ppd->filters[i][31] & 255))
+ if (!strncasecmp(filter, "application/vnd.cups-command", 28) &&
+ _cups_isspace(filter[28]))
+ {
+ p->type |= CUPS_PRINTER_COMMANDS;
break;
-
- if (i < ppd->num_filters)
- {
- /*
- * Add the generic PostScript command filter...
- */
-
- add_string_array(&(p->filters),
- "application/vnd.cups-command application/postscript "
- "0 commandtops");
- p->type |= CUPS_PRINTER_COMMANDS;
+ }
}
}
@@ -4905,12 +4677,11 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
*end; /* End of name */
int count; /* Number of commands */
-
- if (ppd_attr && ppd_attr->value && ppd_attr->value[0])
+ if ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL)
{
for (count = 0, start = ppd_attr->value; *start; count ++)
{
- while (isspace(*start & 255))
+ while (_cups_isspace(*start))
start ++;
if (!*start)
@@ -5017,10 +4788,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
attr->values[i].string.text = _cupsStrAlloc("bcp");
}
-#ifdef HAVE_DNSSD
- cupsdSetString(&p->product, ppd->product);
-#endif /* HAVE_DNSSD */
-
if (ppdFindAttr(ppd, "APRemoteQueueID", NULL))
p->type |= CUPS_PRINTER_REMOTE;
@@ -5179,19 +4946,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
cupsdLogMessage(CUPSD_LOG_INFO,
"Hint: Run \"cupstestppd %s\" and fix any errors.",
ppd_name);
-
- /*
- * Add a filter from application/vnd.cups-raw to printer/name to
- * handle "raw" printing by users.
- */
-
- add_string_array(&(p->filters), "application/vnd.cups-raw 0 -");
-
- /*
- * Add a PostScript filter, since this is still possibly PS printer.
- */
-
- add_string_array(&(p->filters), "application/vnd.cups-postscript 0 -");
}
else
{
@@ -5213,10 +4967,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL,
"Local System V Printer");
-
- snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s",
- ServerRoot, p->name);
- add_string_array(&(p->filters), interface);
}
else if (!strncmp(p->device_uri, "ipp://", 6) &&
(strstr(p->device_uri, "/printers/") != NULL ||
@@ -5289,7 +5039,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"finishings-default", IPP_FINISHINGS_NONE);
- if (ppd && (cache = cupsFileOpen(cache_name, "w9")) != NULL)
+ if (ppd && p->pc)
{
/*
* Save cached PPD attributes to disk...
@@ -5297,20 +5047,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Saving %s...", cache_name);
- p->ppd_attrs->state = IPP_IDLE;
-
- if (ippWriteIO(cache, (ipp_iocb_t)cupsFileWrite, 1, NULL,
- p->ppd_attrs) != IPP_DATA)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to save PPD cache file \"%s\" - %s", cache_name,
- strerror(errno));
- unlink(cache_name);
- }
-
- cupsFileClose(cache);
-
- _pwgWriteFile(p->pwg, pwg_name);
+ _ppdCacheWriteFile(p->pc, cache_name, p->ppd_attrs);
}
else
{
@@ -5320,9 +5057,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */
if (cache_info.st_mtime)
unlink(cache_name);
-
- if (pwg_info.st_mtime)
- unlink(pwg_name);
}
}
diff --git a/scheduler/printers.h b/scheduler/printers.h
index dcbf302f4..9dd9ded68 100644
--- a/scheduler/printers.h
+++ b/scheduler/printers.h
@@ -70,7 +70,8 @@ struct cupsd_printer_s
int remote; /* Remote queue? */
mime_type_t *filetype, /* Pseudo-filetype for printer */
*prefiltertype; /* Pseudo-filetype for pre-filters */
- cups_array_t *filetypes; /* Supported file types */
+ cups_array_t *filetypes, /* Supported file types */
+ *dest_types; /* Destination types for queue */
cupsd_job_t *job; /* Current job in queue */
ipp_t *attrs, /* Attributes supported by this printer */
*ppd_attrs; /* Attributes based on the PPD */
@@ -83,8 +84,6 @@ struct cupsd_printer_s
cups_array_t *quotas; /* Quota records */
int deny_users; /* 1 = deny, 0 = allow */
cups_array_t *users; /* Allowed/denied users */
- int num_history; /* Number of history collections */
- ipp_t **history; /* History data */
int sequence_number; /* Increasing sequence number */
int num_options; /* Number of default options */
cups_option_t *options; /* Default options */
@@ -93,14 +92,10 @@ struct cupsd_printer_s
char *alert, /* PSX printer-alert value */
*alert_description; /* PSX printer-alert-description value */
time_t marker_time; /* Last time marker attributes were updated */
- cups_array_t *filters, /* Filters for queue */
- *pre_filters, /* Pre-filters for queue */
- *dest_types; /* Destination types for queue */
- _pwg_t *pwg; /* PWG<->PPD mapping data */
+ _ppd_cache_t *pc; /* PPD cache and mapping data */
#ifdef HAVE_DNSSD
char *reg_name, /* Name used for service registration */
- *product, /* PPD Product string */
*pdl, /* pdl value for TXT record */
*ipp_txt, /* IPP TXT record contents */
*printer_txt; /* LPD TXT record contents */
@@ -138,7 +133,6 @@ VAR cupsd_policy_t *DefaultPolicyPtr
*/
extern cupsd_printer_t *cupsdAddPrinter(const char *name);
-extern void cupsdAddPrinterHistory(cupsd_printer_t *p);
extern void cupsdCreateCommonData(void);
extern void cupsdDeleteAllPrinters(void);
extern int cupsdDeletePrinter(cupsd_printer_t *p, int update);
diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
index 7179209a4..084d39544 100755
--- a/test/run-stp-tests.sh
+++ b/test/run-stp-tests.sh
@@ -251,6 +251,7 @@ ln -s $root/backend/ipp /tmp/cups-$user/bin/backend
ln -s $root/backend/lpd /tmp/cups-$user/bin/backend
ln -s $root/backend/mdns /tmp/cups-$user/bin/backend
ln -s $root/backend/parallel /tmp/cups-$user/bin/backend
+ln -s $root/backend/pseudo /tmp/cups-$user/bin/backend
ln -s $root/backend/serial /tmp/cups-$user/bin/backend
ln -s $root/backend/snmp /tmp/cups-$user/bin/backend
ln -s $root/backend/socket /tmp/cups-$user/bin/backend
@@ -810,20 +811,6 @@ else
echo "<P>PASS: $count debug2 messages.</P>" >>$strfile
fi
-# Page log file...
-if test `uname` = Darwin; then
- # Currently just test for Mac OS X since others do not have UI to
- # select a user-wide default media size...
- if $GREP -iq 'testfile.pdf na_letter_8.5x11in' /tmp/cups-$user/log/page_log; then
- echo "PASS: page_log formatted correctly."
- echo "<P>PASS: page_log formatted correctly.</P>" >>$strfile
- else
- echo "FAIL: page_log formatted incorrectly."
- echo "<P>FAIL: page_log formatted incorrectly - no page size information.</P>" >>$strfile
- fail=`expr $fail + 1`
- fi
-fi
-
# Log files...
echo "<H2>access_log</H2>" >>$strfile
echo "<PRE>" >>$strfile