summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2008-07-30 23:42:12 +0000
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2008-07-30 23:42:12 +0000
commit749b1e90a80fd8245f9cb84d2f78ab65034eeb81 (patch)
tree41c2eb9f8c465165197a146aadd4df3e37ca362f
parent005dd1eb9e7844f4bf631111847c26c9a4b56df3 (diff)
Merge changes from CUPS 1.4svn-r7817.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@901 a1ca3aef-8c08-0410-bb20-df032aa958be
-rw-r--r--CHANGES-1.3.txt1
-rw-r--r--CHANGES.txt13
-rw-r--r--Makedefs.in2
-rw-r--r--Makefile5
-rw-r--r--backend/backend-private.h3
-rw-r--r--backend/mdns.c14
-rw-r--r--backend/parallel.c12
-rw-r--r--backend/snmp.c344
-rw-r--r--backend/usb-darwin.c148
-rw-r--r--backend/usb-libusb.c5
-rw-r--r--backend/usb-unix.c9
-rw-r--r--cgi-bin/admin.c498
-rw-r--r--config-scripts/cups-common.m413
-rw-r--r--config-scripts/cups-compiler.m41
-rw-r--r--config-scripts/cups-directories.m411
-rw-r--r--config-scripts/cups-ldap.m426
-rw-r--r--config.h.in11
-rw-r--r--configure.in2
-rw-r--r--cups/adminutil.c57
-rw-r--r--cups/backend.c72
-rw-r--r--cups/backend.h9
-rw-r--r--cups/cups.h3
-rw-r--r--cups/dest.c89
-rw-r--r--cups/getdevices.c18
-rw-r--r--cups/globals.h3
-rw-r--r--cups/langprintf.c8
-rw-r--r--cups/libcups.exp1
-rw-r--r--cups/ppd.c39
-rw-r--r--cups/request.c67
-rw-r--r--cups/testppd.c7
-rw-r--r--cups/util.c54
-rw-r--r--cups/versioning.h63
-rw-r--r--doc/cups.css6
-rw-r--r--doc/help/kerberos.html134
-rw-r--r--doc/help/options.html70
-rw-r--r--doc/help/ref-cupsd-conf.html.in14
-rw-r--r--doc/help/spec-ipp.html45
-rw-r--r--doc/help/spec-ppd.html139
-rw-r--r--init/cups.xml.in212
-rw-r--r--man/backend.man12
-rw-r--r--man/cupsd.conf.man.in20
-rw-r--r--notifier/Makefile9
-rw-r--r--scheduler/Makefile5
-rw-r--r--scheduler/client.c42
-rw-r--r--scheduler/cups-deviced.c184
-rw-r--r--scheduler/cups-driverd.cxx2
-rw-r--r--scheduler/dirsvc.c1358
-rw-r--r--scheduler/dirsvc.h19
-rw-r--r--scheduler/main.c113
-rw-r--r--systemv/cupstestppd.c303
-rw-r--r--systemv/lpinfo.c9
-rw-r--r--templates/option-pickone.tmpl16
-rw-r--r--templates/set-printer-options-header.tmpl13
-rw-r--r--templates/set-printer-options-trailer.tmpl11
54 files changed, 3282 insertions, 1062 deletions
diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt
index fca0738fa..ea573a924 100644
--- a/CHANGES-1.3.txt
+++ b/CHANGES-1.3.txt
@@ -3,6 +3,7 @@ CHANGES-1.3.txt
CHANGES IN CUPS V1.3.9
+ - Refined the cupstestppd utility.
- ppdEmit*() did not support custom JCL options (STR #2889)
- The cupstestppd utility incorrectly reported missing
"en" base translations (STR #2887)
diff --git a/CHANGES.txt b/CHANGES.txt
index f3f407183..8a1984e9a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,8 +1,19 @@
-CHANGES.txt - 2008-07-23
+CHANGES.txt - 2008-07-28
------------------------
CHANGES IN CUPS V1.4b1
+ - Added support for a device-location attribute which provides
+ the physical location of a printer device.
+ - Added a cupsBackendReport() API which handles quoting of the
+ device data by a backend.
+ - Added support for custom options in the web interface
+ (STR #1729)
+ - Added support for Mozilla LDAP, reconnection to LDAP servers,
+ and improved LDAP performance (STR #1962)
+ - Added Solaris SMF support (STR #1477)
+ - Added optional support for using TCP wrappers to limit access
+ to CUPS (STR #263)
- Added ppdPageSizeLimits API.
- Added support for new cupsMediaQualifier2, cupsMediaQualifier3,
cupsMinSize, and cupsMaxSize attributes.
diff --git a/Makedefs.in b/Makedefs.in
index 0e5068553..b34c7ae0e 100644
--- a/Makedefs.in
+++ b/Makedefs.in
@@ -92,6 +92,7 @@ LIBSLP = @LIBSLP@
LIBGSSAPI = @LIBGSSAPI@
LIBTIFF = @LIBTIFF@
LIBUSB = @LIBUSB@
+LIBWRAP = @LIBWRAP@
LIBZ = @LIBZ@
#
@@ -229,6 +230,7 @@ REQUESTS = $(BUILDROOT)@CUPS_REQUESTS@
SBINDIR = $(BUILDROOT)@sbindir@
SERVERBIN = $(BUILDROOT)@CUPS_SERVERBIN@
SERVERROOT = $(BUILDROOT)@CUPS_SERVERROOT@
+SMFMANIFESTDIR = @SMFMANIFESTDIR@
STATEDIR = $(BUILDROOT)@CUPS_STATEDIR@
XINETD = @XINETD@
diff --git a/Makefile b/Makefile
index 9074d6731..017378db3 100644
--- a/Makefile
+++ b/Makefile
@@ -182,6 +182,11 @@ install-data:
$(INSTALL_SCRIPT) init/cups.sh $(BUILDROOT)$(INITDDIR)/cups; \
fi \
fi
+ if test "x$(SMFMANIFESTDIR)" != x; then \
+ echo Installing SMF manifest in $(SMFMANIFESTDIR)...;\
+ $(INSTALL_DIR) $(BUILDROOT)/$(SMFMANIFESTDIR); \
+ $(INSTALL_SCRIPT) init/cups.xml $(BUILDROOT)$(SMFMANIFESTDIR)/cups.xml; \
+ fi
if test "x$(DBUSDIR)" != x; then \
echo Installing cups.conf in $(DBUSDIR)...;\
$(INSTALL_DIR) -m 755 $(BUILDROOT)$(DBUSDIR)/system.d; \
diff --git a/backend/backend-private.h b/backend/backend-private.h
index b7912d59d..c124274a9 100644
--- a/backend/backend-private.h
+++ b/backend/backend-private.h
@@ -51,6 +51,9 @@ extern "C" {
/* Host MIB */
#define CUPS_OID_mib2 1,3,6,1,2,1
+#define CUPS_OID_system CUPS_OID_mib2,1
+#define CUPS_OID_sysLocation CUPS_OID_system,6
+
#define CUPS_OID_host CUPS_OID_mib2,25
#define CUPS_OID_hrSystem CUPS_OID_host,1
diff --git a/backend/mdns.c b/backend/mdns.c
index 4ae2c8121..419b12dc3 100644
--- a/backend/mdns.c
+++ b/backend/mdns.c
@@ -280,11 +280,8 @@ main(int argc, /* I - Number of command-line args */
schemes[best->type], NULL, best->fullName, 0,
best->cups_shared ? "/cups" : "/");
- printf("network %s \"%s\" \"%s\"\n", device_uri,
- best->make_and_model ? best->make_and_model : "Unknown",
- best->name);
- fflush(stdout);
-
+ cupsBackendReport("network", device_uri, best->make_and_model,
+ best->name, NULL, NULL);
best->sent = 1;
best = device;
}
@@ -305,11 +302,8 @@ main(int argc, /* I - Number of command-line args */
schemes[best->type], NULL, best->fullName, 0,
best->cups_shared ? "/cups" : "/");
- printf("network %s \"%s\" \"%s\"\n", device_uri,
- best->make_and_model ? best->make_and_model : "Unknown",
- best->name);
- fflush(stdout);
-
+ cupsBackendReport("network", device_uri, best->make_and_model,
+ best->name, NULL, NULL);
best->sent = 1;
}
}
diff --git a/backend/parallel.c b/backend/parallel.c
index bba472095..e20499545 100644
--- a/backend/parallel.c
+++ b/backend/parallel.c
@@ -328,6 +328,7 @@ list_devices(void)
basedevice[255], /* Base device filename for ports */
device_id[1024], /* Device ID string */
make_model[1024], /* Make and model */
+ info[1024], /* Info string */
uri[1024]; /* Device URI */
@@ -359,10 +360,15 @@ list_devices(void)
if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
make_model, sizeof(make_model),
NULL, uri, sizeof(uri)))
- printf("direct %s \"%s\" \"%s LPT #%d\" \"%s\"\n", uri,
- make_model, make_model, i + 1, device_id);
+ {
+ snprintf(info, sizeof(info), "%s LPT #%d", make_model, i + 1);
+ cupsBackendReport("direct", uri, make_model, info, device_id, NULL);
+ }
else
- printf("direct %s \"Unknown\" \"LPT #%d\"\n", uri, i + 1);
+ {
+ snprintf(info, sizeof(info), "LPT #%d", i + 1);
+ cupsBackendReport("direct", uri, NULL, info, NULL, NULL);
+ }
close(fd);
}
diff --git a/backend/snmp.c b/backend/snmp.c
index b7bafbf56..712981cfd 100644
--- a/backend/snmp.c
+++ b/backend/snmp.c
@@ -111,6 +111,16 @@
* Types...
*/
+enum /**** Request IDs for each field ****/
+{
+ DEVICE_TYPE = 1,
+ DEVICE_DESCRIPTION,
+ DEVICE_LOCATION,
+ DEVICE_ID,
+ DEVICE_URI,
+ DEVICE_PRODUCT
+};
+
typedef struct device_uri_s /**** DeviceURI values ****/
{
regex_t re; /* Regular expression to match */
@@ -124,7 +134,9 @@ typedef struct snmp_cache_s /**** SNMP scan cache ****/
*uri, /* device-uri */
*id, /* device-id */
*info, /* device-info */
+ *location, /* device-location */
*make_and_model; /* device-make-and-model */
+ int sent; /* Has this device been listed? */
} snmp_cache_t;
@@ -174,14 +186,15 @@ static cups_array_t *Addresses = NULL;
static cups_array_t *Communities = NULL;
static cups_array_t *Devices = NULL;
static int DebugLevel = 0;
-static const int DeviceDescOID[] = { CUPS_OID_hrDeviceDescr, 1, -1 };
-static unsigned DeviceDescRequest;
+static const int DescriptionOID[] = { CUPS_OID_hrDeviceDescr, 1, -1 };
+static const int LocationOID[] = { CUPS_OID_sysLocation, 0, -1 };
static const int DeviceTypeOID[] = { CUPS_OID_hrDeviceType, 1, -1 };
-static unsigned DeviceTypeRequest;
static const int DeviceIdOID[] = { CUPS_OID_ppmPrinterIEEE1284DeviceId, 1, -1 };
-static unsigned DeviceIdRequest;
-static const int DeviceUriOID[] = { CUPS_OID_ppmPortServiceNameOrURI, 1, 1, -1 };
-static unsigned DeviceUriRequest;
+static const int UriOID[] = { CUPS_OID_ppmPortServiceNameOrURI, 1, 1, -1 };
+static const int LexmarkProductOID[] = { 1,3,6,1,4,1,641,2,1,2,1,2,1,-1 };
+static const int LexmarkProductOID2[] = { 1,3,6,1,4,1,674,10898,100,2,1,2,1,2,1,-1 };
+static const int LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 };
+static const int XeroxProductOID[] = { 1,3,6,1,4,1,128,2,1,3,1,2,0,-1 };
static cups_array_t *DeviceURIs = NULL;
static int HostNameLookups = 0;
static int MaxRunTime = 120;
@@ -660,15 +673,8 @@ static void
list_device(snmp_cache_t *cache) /* I - Cached device */
{
if (cache->uri)
- {
- printf("network %s \"%s\" \"%s %s\" \"%s\"\n",
- cache->uri,
- cache->make_and_model ? cache->make_and_model : "Unknown",
- cache->info ? cache->info : "Unknown",
- cache->addrname,
- cache->id ? cache->id : "");
- fflush(stdout);
- }
+ cupsBackendReport("network", cache->uri, cache->make_and_model,
+ cache->info, cache->id, cache->location);
}
@@ -953,156 +959,172 @@ read_snmp_response(int fd) /* I - SNMP socket file descriptor */
* Process the message...
*/
- if (packet.request_id == DeviceTypeRequest)
+ switch (packet.request_id)
{
- /*
- * Got the device type response...
- */
-
- if (device)
- {
- debug_printf("DEBUG: Discarding duplicate device type for \"%s\"...\n",
- addrname);
- return;
- }
-
- /*
- * Add the device and request the device description...
- */
-
- add_cache(&(packet.address), addrname, NULL, NULL, NULL);
+ case DEVICE_TYPE :
+ /*
+ * Got the device type response...
+ */
+
+ if (device)
+ {
+ debug_printf("DEBUG: Discarding duplicate device type for \"%s\"...\n",
+ addrname);
+ return;
+ }
+
+ /*
+ * Add the device and request the device data...
+ */
+
+ add_cache(&(packet.address), addrname, NULL, NULL, NULL);
+
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_DESCRIPTION, DescriptionOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_ID, DeviceIdOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_URI, UriOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_LOCATION, LocationOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_PRODUCT, LexmarkProductOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_PRODUCT, LexmarkProductOID2);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_URI, LexmarkDeviceIdOID);
+ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ packet.community, CUPS_ASN1_GET_REQUEST,
+ DEVICE_PRODUCT, XeroxProductOID);
+ break;
+
+ case DEVICE_DESCRIPTION :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING)
+ {
+ /*
+ * Update an existing cache entry...
+ */
+
+ char make_model[256]; /* Make and model */
+
+
+ if (strchr(packet.object_value.string, ':') &&
+ strchr(packet.object_value.string, ';'))
+ {
+ /*
+ * Description is the IEEE-1284 device ID...
+ */
- _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community,
- CUPS_ASN1_GET_REQUEST, DeviceDescRequest, DeviceDescOID);
- _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community,
- CUPS_ASN1_GET_REQUEST, DeviceIdRequest, DeviceIdOID);
- _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, packet.community,
- CUPS_ASN1_GET_REQUEST, DeviceUriRequest, DeviceUriOID);
- }
- else if (packet.request_id == DeviceDescRequest &&
- packet.object_type == CUPS_ASN1_OCTET_STRING)
- {
- /*
- * Update an existing cache entry...
- */
+ if (!device->id)
+ device->id = strdup(packet.object_value.string);
- char make_model[256]; /* Make and model */
+ backendGetMakeModel(packet.object_value.string, make_model,
+ sizeof(make_model));
+ if (device->info)
+ free(device->info);
- if (!device)
- {
- debug_printf("DEBUG: Discarding device description for \"%s\"...\n",
- addrname);
- return;
- }
-
- if (strchr(packet.object_value.string, ':') &&
- strchr(packet.object_value.string, ';'))
- {
- /*
- * Description is the IEEE-1284 device ID...
- */
-
- if (!device->id)
- device->id = strdup(packet.object_value.string);
-
- backendGetMakeModel(packet.object_value.string, make_model,
- sizeof(make_model));
- device->info = strdup(make_model);
- }
- else
- {
- /*
- * Description is plain text...
- */
+ device->info = strdup(make_model);
+ }
+ else
+ {
+ /*
+ * Description is plain text...
+ */
- fix_make_model(make_model, packet.object_value.string,
- sizeof(make_model));
+ fix_make_model(make_model, packet.object_value.string,
+ sizeof(make_model));
- device->info = strdup(packet.object_value.string);
- }
+ if (device->info)
+ free(device->info);
- if (!device->make_and_model)
- device->make_and_model = strdup(make_model);
+ device->info = strdup(packet.object_value.string);
+ }
- /*
- * List the device now if we have all the info...
- */
+ if (!device->make_and_model)
+ device->make_and_model = strdup(make_model);
+ }
+ break;
- if (device->id && device->info && device->make_and_model && device->uri)
- list_device(device);
- }
- else if (packet.request_id == DeviceIdRequest &&
- packet.object_type == CUPS_ASN1_OCTET_STRING)
- {
- /*
- * Update an existing cache entry...
- */
+ case DEVICE_ID :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING)
+ {
+ /*
+ * Update an existing cache entry...
+ */
- char make_model[256]; /* Make and model */
+ char make_model[256]; /* Make and model */
- if (!device)
- {
- debug_printf("DEBUG: Discarding device ID for \"%s\"...\n",
- addrname);
- return;
- }
+ if (device->id)
+ free(device->id);
- if (device->id)
- free(device->id);
+ device->id = strdup(packet.object_value.string);
- device->id = strdup(packet.object_value.string);
+ /*
+ * Convert the ID to a make and model string...
+ */
- /*
- * Convert the ID to a make and model string...
- */
+ backendGetMakeModel(packet.object_value.string, make_model,
+ sizeof(make_model));
+ if (device->make_and_model)
+ free(device->make_and_model);
- backendGetMakeModel(packet.object_value.string, make_model,
- sizeof(make_model));
- if (device->make_and_model)
- free(device->make_and_model);
+ device->make_and_model = strdup(make_model);
+ }
+ break;
- device->make_and_model = strdup(make_model);
+ case DEVICE_LOCATION :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
+ !device->location)
+ device->location = strdup(packet.object_value.string);
+ break;
- /*
- * List the device now if we have all the info...
- */
+ case DEVICE_PRODUCT :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
+ !device->id)
+ {
+ /*
+ * Update an existing cache entry...
+ */
- if (device->id && device->info && device->make_and_model && device->uri)
- list_device(device);
- }
- else if (packet.request_id == DeviceUriRequest &&
- packet.object_type == CUPS_ASN1_OCTET_STRING)
- {
- /*
- * Update an existing cache entry...
- */
+ if (!device->info)
+ device->info = strdup(packet.object_value.string);
- if (!device)
- {
- debug_printf("DEBUG: Discarding device URI for \"%s\"...\n",
- addrname);
- return;
- }
+ if (device->make_and_model)
+ free(device->make_and_model);
- if (!strncmp(packet.object_value.string, "lpr:", 4))
- {
- /*
- * We want "lpd://..." for the URI...
- */
+ device->make_and_model = strdup(packet.object_value.string);
+ }
+ break;
- packet.object_value.string[2] = 'd';
- }
+ case DEVICE_URI :
+ if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
+ !device->uri)
+ {
+ /*
+ * Update an existing cache entry...
+ */
- device->uri = strdup(packet.object_value.string);
+ if (!strncmp(packet.object_value.string, "lpr:", 4))
+ {
+ /*
+ * We want "lpd://..." for the URI...
+ */
- /*
- * List the device now if we have all the info...
- */
+ packet.object_value.string[2] = 'd';
+ }
- if (device->id && device->info && device->make_and_model && device->uri)
- list_device(device);
+ device->uri = strdup(packet.object_value.string);
+ }
+ break;
}
}
@@ -1141,15 +1163,8 @@ scan_devices(int fd) /* I - SNMP socket */
snmp_cache_t *device; /* Current device */
- /*
- * Setup the request IDs...
- */
-
gettimeofday(&StartTime, NULL);
- DeviceTypeRequest = StartTime.tv_sec;
- DeviceDescRequest = StartTime.tv_sec + 1;
-
/*
* First send all of the broadcast queries...
*/
@@ -1189,7 +1204,7 @@ scan_devices(int fd) /* I - SNMP socket */
for (addr = addrs; addr; addr = addr->next)
_cupsSNMPWrite(fd, &(addr->addr), CUPS_SNMP_VERSION_1, community,
- CUPS_ASN1_GET_REQUEST, DeviceTypeRequest, DeviceTypeOID);
+ CUPS_ASN1_GET_REQUEST, DEVICE_TYPE, DeviceTypeOID);
}
httpAddrFreeList(addrs);
@@ -1219,21 +1234,30 @@ scan_devices(int fd) /* I - SNMP socket */
if (FD_ISSET(fd, &input))
read_snmp_response(fd);
else
- break;
- }
+ {
+ /*
+ * List devices with complete information...
+ */
- /*
- * Finally, probe all of the printers we discovered to see how they are
- * connected...
- */
+ int sent_something = 0;
- for (device = (snmp_cache_t *)cupsArrayFirst(Devices);
- device;
- device = (snmp_cache_t *)cupsArrayNext(Devices))
- if (MaxRunTime > 0 && run_time() >= MaxRunTime)
- break;
- else if (!device->uri)
- probe_device(device);
+ for (device = (snmp_cache_t *)cupsArrayFirst(Devices);
+ device;
+ device = (snmp_cache_t *)cupsArrayNext(Devices))
+ if (!device->sent && device->info && device->make_and_model)
+ {
+ if (device->uri)
+ list_device(device);
+ else
+ probe_device(device);
+
+ device->sent = sent_something = 1;
+ }
+
+ if (!sent_something)
+ break;
+ }
+ }
debug_printf("DEBUG: %.3f Scan complete!\n", run_time());
}
diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c
index d0371378b..d33379564 100644
--- a/backend/usb-darwin.c
+++ b/backend/usb-darwin.c
@@ -65,7 +65,7 @@
* cfstr_create_trim() - Create CFString and trim whitespace characters.
* parse_options() - Parse uri options.
* setup_cfLanguage() - Create AppleLanguages array from LANG environment var.
-* run_ppc_backend() - Re-exec i386 backend as ppc.
+* run_legacy_backend() - Re-exec backend as ppc or i386.
* sigterm_handler() - SIGTERM handler.
* next_line() - Find the next line in a buffer.
* parse_pserror() - Scan the backchannel data for postscript errors.
@@ -98,8 +98,11 @@
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
+#include <spawn.h>
#include <pthread.h>
+extern char **environ;
+
/*
* WAIT_EOF_DELAY is number of seconds we'll wait for responses from
@@ -275,11 +278,11 @@ static void setup_cfLanguage(void);
static void soft_reset();
static void status_timer_cb(CFRunLoopTimerRef timer, void *info);
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
static pid_t child_pid; /* Child PID */
-static void run_ppc_backend(int argc, char *argv[], int fd); /* Starts child backend process running as a ppc executable */
+static void run_legacy_backend(int argc, char *argv[], int fd); /* Starts child backend process running as a ppc executable */
static void sigterm_handler(int sig); /* SIGTERM handler */
-#endif /* __i386__ */
+#endif /* __i386__ || __x86_64__ */
#ifdef PARSE_PS_ERRORS
static const char *next_line (const char *buffer);
@@ -392,17 +395,18 @@ print_device(const char *uri, /* I - Device URI */
status = registry_open(&driverBundlePath);
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
/*
- * If we were unable to load the class drivers for this printer it's probably because they're ppc-only.
- * In this case try to fork & exec this backend as a ppc executable so we can use them...
+ * If we were unable to load the class drivers for this printer it's
+ * probably because they're ppc or i386. In this case try to run this
+ * backend as i386 or ppc executables so we can use them...
*/
if (status == -2)
{
- run_ppc_backend(argc, argv, print_fd);
+ run_legacy_backend(argc, argv, print_fd);
/* Never returns here */
}
-#endif /* __i386__ */
+#endif /* __i386__ || __x86_64__ */
if (status == -2)
{
@@ -518,7 +522,7 @@ print_device(const char *uri, /* I - Device URI */
if (print_fd != STDIN_FILENO)
{
- fputs("PAGE: 1 1", stderr);
+ fputs("PAGE: 1 1\n", stderr);
lseek(print_fd, 0, SEEK_SET);
}
@@ -1052,8 +1056,8 @@ static Boolean list_device_cb(void *refcon,
httpAssembleURI(HTTP_URI_CODING_ALL, uristr, sizeof(uristr), "usb", NULL, makestr, 0, modelstr);
strncat(uristr, optionsstr, sizeof(uristr));
- printf("direct %s \"%s\" \"%s USB\" \"%s\"\n", uristr, make_modelstr,
- make_modelstr, idstr);
+ cupsBackendReport("direct", uristr, make_modelstr, make_modelstr, idstr,
+ NULL);
release_deviceinfo(&make, &model, &serial);
CFRelease(deviceIDString);
@@ -1154,7 +1158,7 @@ static void status_timer_cb(CFRunLoopTimerRef timer,
void *info)
{
fputs("STATE: +offline-error\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Printer is currently offline.\n"));
+ _cupsLangPuts(stderr, _("INFO: Printer is offline.\n"));
if (getenv("CLASS") != NULL)
{
@@ -1729,36 +1733,42 @@ static void setup_cfLanguage(void)
}
#pragma mark -
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
/*!
- * @function run_ppc_backend
+ * @function run_legacy_backend
*
- * @abstract Starts child backend process running as a ppc executable.
+ * @abstract Starts child backend process running as a ppc or i386 executable.
*
* @result Never returns; always calls exit().
*
* @discussion
*/
-static void run_ppc_backend(int argc,
- char *argv[],
- int fd)
+static void run_legacy_backend(int argc,
+ char *argv[],
+ int fd)
{
int i;
int exitstatus = 0;
int childstatus;
pid_t waitpid_status;
char *my_argv[32];
- char *usb_ppc_status;
+ char *usb_legacy_status;
- /*
- * If we're running as i386 and couldn't load the class driver (because they'it's
- * ppc-only) then try to re-exec ourselves in ppc mode to try again. If we don't have
- * a ppc architecture we may be running i386 again so guard against this by setting
- * and testing an environment variable...
- */
- usb_ppc_status = getenv("USB_PPC_STATUS");
+ /*
+ * If we're running as x86_64 or i386 and couldn't load the class driver
+ * (because it's ppc or i386), then try to re-exec ourselves in ppc or i386
+ * mode to try again. If we don't have a ppc or i386 architecture we may be
+ * running with the same architecture again so guard against this by setting
+ * and testing an environment variable...
+ */
- if (usb_ppc_status == NULL)
+# ifdef __x86_64__
+ usb_legacy_status = getenv("USB_I386_STATUS");
+# else
+ usb_legacy_status = getenv("USB_PPC_STATUS");
+# endif /* __x86_64__ */
+
+ if (!usb_legacy_status)
{
/*
* Setup a SIGTERM handler then block it before forking...
@@ -1777,57 +1787,49 @@ static void run_ppc_backend(int argc,
sigaddset(&newmask, SIGTERM);
sigprocmask(SIG_BLOCK, &newmask, &oldmask);
- if ((child_pid = fork()) == 0)
- {
- /*
- * Child comes here...
- */
-
- setenv("USB_PPC_STATUS", "1", false);
-
- /*
- * Unblock signals before doing the exec...
- */
-
- memset(&action, 0, sizeof(action));
- sigemptyset(&action.sa_mask);
- action.sa_handler = SIG_DFL;
- sigaction(SIGTERM, &action, NULL);
+ /*
+ * Set the environment variable...
+ */
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
+# ifdef __x86_64__
+ setenv("USB_I386_STATUS", "1", false);
+# else
+ setenv("USB_PPC_STATUS", "1", false);
+# endif /* __x86_64__ */
- /*
- * Tell the kernel the next exec call should favor the ppc architecture...
- */
+ /*
+ * Tell the kernel to use the specified CPU architecture...
+ */
- int mib[] = { CTL_KERN, KERN_AFFINITY, 1, 1 };
- int namelen = 4;
- sysctl(mib, namelen, NULL, NULL, NULL, 0);
+# ifdef __x86_64__
+ cpu_type_t cpu = CPU_TYPE_I386;
+# else
+ cpu_type_t cpu = CPU_TYPE_POWERPC;
+# endif /* __x86_64__ */
+ size_t ocount = 0;
+ posix_spawnattr_t attrs;
- /*
- * Set up the arguments and call exec...
- */
+ if (!posix_spawnattr_init(&attrs))
+ {
+ posix_spawnattr_setsigdefault(attrs, &oldmask);
+ posix_spawnattr_setbinpref_np(attrs, 1, &cpu, &ocount);
+ }
- for (i = 0; i < argc && i < (sizeof(my_argv)/sizeof(my_argv[0])) - 1; i++)
- my_argv[i] = argv[i];
+ /*
+ * Set up the arguments and call posix_spawn...
+ */
- my_argv[i] = NULL;
+ for (i = 0; i < argc && i < (sizeof(my_argv) / sizeof(my_argv[0])) - 1; i ++)
+ my_argv[i] = argv[i];
- execv("/usr/libexec/cups/backend/usb", my_argv);
+ my_argv[i] = NULL;
- _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n"));
- perror("DEBUG: Unable to exec /usr/libexec/cups/backend/usb");
- exit(errno);
- }
- else if (child_pid < 0)
+ if (posix_spawn(&child_pid, "/usr/libexec/cups/backend/usb", NULL, &attrs,
+ my_argv, environ))
{
- /*
- * Error - couldn't fork a new process!
- */
-
_cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n"));
- perror("DEBUG: Unable to fork");
- exit(errno);
+ perror("DEBUG: Unable to exec /usr/libexec/cups/backend/usb");
+ exit(CUPS_BACKEND_STOP);
}
/*
@@ -1851,9 +1853,9 @@ static void run_ppc_backend(int argc,
if (WIFSIGNALED(childstatus))
{
- exitstatus = WTERMSIG(childstatus);
+ exitstatus = CUPS_BACKEND_STOP;
fprintf(stderr, "DEBUG: usb(legacy) backend %d crashed on signal %d!\n",
- child_pid, exitstatus);
+ child_pid, WTERMSIG(childstatus));
}
else
{
@@ -1869,7 +1871,7 @@ static void run_ppc_backend(int argc,
else
{
fputs("DEBUG: usb(legacy) backend running native again\n", stderr);
- exitstatus = ENOENT;
+ exitstatus = CUPS_BACKEND_STOP;
}
exit(exitstatus);
@@ -1889,7 +1891,7 @@ static void sigterm_handler(int sig)
exit(1);
}
-#endif /* __i386__ */
+#endif /* __i386__ || __x86_64__ */
#ifdef PARSE_PS_ERRORS
diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c
index 4a7716ec3..cad8d87ca 100644
--- a/backend/usb-libusb.c
+++ b/backend/usb-libusb.c
@@ -447,9 +447,8 @@ list_cb(usb_printer_t *printer, /* I - Printer */
* Report the printer...
*/
- printf("direct %s \"%s\" \"%s USB\" \"%s\"\n", device_uri, make_model,
- make_model, device_id);
- fflush(stdout);
+ cupsBackendReport("direct", device_uri, make_model, make_model, device_id,
+ NULL);
/*
* Keep going...
diff --git a/backend/usb-unix.c b/backend/usb-unix.c
index 5fbed6ecd..de4ab4e29 100644
--- a/backend/usb-unix.c
+++ b/backend/usb-unix.c
@@ -210,6 +210,7 @@ list_devices(void)
device_uri[1024], /* Device URI string */
make_model[1024]; /* Make and model */
+
/*
* Try to open each USB device...
*/
@@ -245,8 +246,8 @@ list_devices(void)
if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
make_model, sizeof(make_model),
"usb", device_uri, sizeof(device_uri)))
- printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri,
- make_model, make_model, i + 1, device_id);
+ cupsBackendReport("direct", device_uri, make_model, make_model,
+ device_id, NULL);
close(fd);
}
@@ -273,8 +274,8 @@ list_devices(void)
if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
make_model, sizeof(make_model),
"usb", device_uri, sizeof(device_uri)))
- printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri,
- make_model, make_model, i + 1, device_id);
+ cupsBackendReport("direct", device_uri, make_model, make_model,
+ device_id, NULL);
close(fd);
}
diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c
index e67582d02..bddc2d038 100644
--- a/cgi-bin/admin.c
+++ b/cgi-bin/admin.c
@@ -20,15 +20,17 @@
* do_am_printer() - Add or modify a printer.
* do_cancel_subscription() - Cancel a subscription.
* do_config_server() - Configure server settings.
- * do_delete_class() - Delete a class...
- * do_delete_printer() - Delete a printer...
- * do_export() - Export printers to Samba...
- * do_list_printers() - List available printers...
- * do_menu() - Show the main menu...
+ * do_delete_class() - Delete a class.
+ * do_delete_printer() - Delete a printer.
+ * do_export() - Export printers to Samba.
+ * do_list_printers() - List available printers.
+ * do_menu() - Show the main menu.
* do_printer_op() - Do a printer operation.
* do_set_allowed_users() - Set the allowed/denied users for a queue.
* do_set_options() - Configure the default options for a queue.
- * do_set_sharing() - Set printer-is-shared value...
+ * do_set_sharing() - Set printer-is-shared value.
+ * get_option_value() - Return the value of an option.
+ * get_points() - Get a value in points.
* match_string() - Return the number of matching characters.
*/
@@ -43,6 +45,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
+#include <limits.h>
/*
@@ -64,6 +67,9 @@ static void do_printer_op(http_t *http,
ipp_op_t op, const char *title);
static void do_set_allowed_users(http_t *http);
static void do_set_sharing(http_t *http);
+static char *get_option_value(ppd_file_t *ppd, const char *name,
+ char *buffer, size_t bufsize);
+static double get_points(double number, const char *uval);
static int match_string(const char *a, const char *b);
@@ -177,7 +183,7 @@ main(int argc, /* I - Number of command-line arguments */
else
{
/*
- * Bad operation code... Display an error...
+ * Bad operation code - display an error...
*/
cgiStartHTML(cgiText(_("Administration")));
@@ -206,7 +212,7 @@ main(int argc, /* I - Number of command-line arguments */
else
{
/*
- * Form data but no operation code... Display an error...
+ * Form data but no operation code - display an error...
*/
cgiStartHTML(cgiText(_("Administration")));
@@ -1769,7 +1775,7 @@ do_config_server(http_t *http) /* I - HTTP connection */
/*
- * 'do_delete_class()' - Delete a class...
+ * 'do_delete_class()' - Delete a class.
*/
static void
@@ -1854,7 +1860,7 @@ do_delete_class(http_t *http) /* I - HTTP connection */
/*
- * 'do_delete_printer()' - Delete a printer...
+ * 'do_delete_printer()' - Delete a printer.
*/
static void
@@ -1939,7 +1945,7 @@ do_delete_printer(http_t *http) /* I - HTTP connection */
/*
- * 'do_export()' - Export printers to Samba...
+ * 'do_export()' - Export printers to Samba.
*/
static void
@@ -2075,7 +2081,7 @@ do_export(http_t *http) /* I - HTTP connection */
/*
- * 'do_list_printers()' - List available printers...
+ * 'do_list_printers()' - List available printers.
*/
static void
@@ -2278,7 +2284,7 @@ do_list_printers(http_t *http) /* I - HTTP connection */
/*
- * 'do_menu()' - Show the main menu...
+ * 'do_menu()' - Show the main menu.
*/
static void
@@ -2774,12 +2780,15 @@ do_set_options(http_t *http, /* I - HTTP connection */
char tempfile[1024]; /* Temporary filename */
cups_file_t *in, /* Input file */
*out; /* Output file */
- char line[1024]; /* Line from PPD file */
- char keyword[1024], /* Keyword from Default line */
+ char line[1024], /* Line from PPD file */
+ value[1024], /* Option value */
+ keyword[1024], /* Keyword from Default line */
*keyptr; /* Pointer into keyword... */
ppd_file_t *ppd; /* PPD file */
ppd_group_t *group; /* Option group */
ppd_option_t *option; /* Option */
+ ppd_coption_t *coption; /* Custom option */
+ ppd_cparam_t *cparam; /* Custom parameter */
ppd_attr_t *protocol; /* cupsProtocol attribute */
const char *title; /* Page title */
@@ -2847,32 +2856,14 @@ do_set_options(http_t *http, /* I - HTTP connection */
{
ppdMarkDefaults(ppd);
- DEBUG_printf(("<P>ppd->num_groups = %d\n"
- "<UL>\n", ppd->num_groups));
-
- for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
- {
- DEBUG_printf(("<LI>%s<UL>\n", group->text));
-
- for (j = group->num_options, option = group->options;
- j > 0;
- j --, option ++)
- if ((var = cgiGetVariable(option->keyword)) != NULL)
- {
- DEBUG_printf(("<LI>%s = \"%s\"</LI>\n", option->keyword, var));
- have_options = 1;
- ppdMarkOption(ppd, option->keyword, var);
- }
-#ifdef DEBUG
- else
- printf("<LI>%s not defined!</LI>\n", option->keyword);
-#endif /* DEBUG */
-
- DEBUG_puts("</UL></LI>");
- }
-
- DEBUG_printf(("</UL>\n"
- "<P>ppdConflicts(ppd) = %d\n", ppdConflicts(ppd)));
+ for (option = ppdFirstOption(ppd);
+ option;
+ option = ppdNextOption(ppd))
+ if ((var = cgiGetVariable(option->keyword)) != NULL)
+ {
+ have_options = 1;
+ ppdMarkOption(ppd, option->keyword, var);
+ }
}
if (!have_options || ppdConflicts(ppd))
@@ -2928,7 +2919,7 @@ do_set_options(http_t *http, /* I - HTTP connection */
cgiSetVariable("KEYWORD", option->keyword);
cgiSetVariable("KEYTEXT", option->text);
-
+
if (option->conflicted)
cgiSetVariable("CONFLICTED", "1");
else
@@ -2938,13 +2929,6 @@ do_set_options(http_t *http, /* I - HTTP connection */
cgiSetSize("TEXT", 0);
for (k = 0, m = 0; k < option->num_choices; k ++)
{
- /*
- * Hide custom option values...
- */
-
- if (!strcmp(option->choices[k].choice, "Custom"))
- continue;
-
cgiSetArray("CHOICES", m, option->choices[k].choice);
cgiSetArray("TEXT", m, option->choices[k].text);
@@ -2954,6 +2938,118 @@ do_set_options(http_t *http, /* I - HTTP connection */
cgiSetVariable("DEFCHOICE", option->choices[k].choice);
}
+ cgiSetSize("PARAMS", 0);
+ cgiSetSize("PARAMTEXT", 0);
+ cgiSetSize("PARAMVALUE", 0);
+ cgiSetSize("INPUTTYPE", 0);
+
+ if ((coption = ppdFindCustomOption(ppd, option->keyword)))
+ {
+ const char *units = NULL; /* Units value, if any */
+
+
+ cgiSetVariable("ISCUSTOM", "1");
+
+ for (cparam = ppdFirstCustomParam(coption), m = 0;
+ cparam;
+ cparam = ppdNextCustomParam(coption), m ++)
+ {
+ if (!strcasecmp(option->keyword, "PageSize") &&
+ strcasecmp(cparam->name, "Width") &&
+ strcasecmp(cparam->name, "Height"))
+ {
+ m --;
+ continue;
+ }
+
+ cgiSetArray("PARAMS", m, cparam->name);
+ cgiSetArray("PARAMTEXT", m, cparam->text);
+ cgiSetArray("INPUTTYPE", m, "text");
+
+ switch (cparam->type)
+ {
+ case PPD_CUSTOM_POINTS :
+ if (!strncasecmp(option->defchoice, "Custom.", 7))
+ {
+ units = option->defchoice + strlen(option->defchoice) - 2;
+
+ if (strcmp(units, "mm") && strcmp(units, "cm") &&
+ strcmp(units, "in") && strcmp(units, "ft"))
+ {
+ if (units[1] == 'm')
+ units ++;
+ else
+ units = "pt";
+ }
+ }
+ else
+ units = "pt";
+
+ if (!strcmp(units, "mm"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 * 25.4);
+ else if (!strcmp(units, "cm"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 * 2.54);
+ else if (!strcmp(units, "in"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0);
+ else if (!strcmp(units, "ft"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 / 12.0);
+ else if (!strcmp(units, "m"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 * 0.0254);
+ else
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points);
+ cgiSetArray("PARAMVALUE", m, value);
+ break;
+
+ case PPD_CUSTOM_CURVE :
+ case PPD_CUSTOM_INVCURVE :
+ case PPD_CUSTOM_REAL :
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_real);
+ cgiSetArray("PARAMVALUE", m, value);
+ break;
+
+ case PPD_CUSTOM_INT:
+ snprintf(value, sizeof(value), "%d",
+ cparam->current.custom_int);
+ cgiSetArray("PARAMVALUE", m, value);
+ break;
+
+ case PPD_CUSTOM_PASSCODE:
+ case PPD_CUSTOM_PASSWORD:
+ if (cparam->current.custom_password)
+ cgiSetArray("PARAMVALUE", m,
+ cparam->current.custom_password);
+ else
+ cgiSetArray("PARAMVALUE", m, "");
+ cgiSetArray("INPUTTYPE", m, "password");
+ break;
+
+ case PPD_CUSTOM_STRING:
+ if (cparam->current.custom_string)
+ cgiSetArray("PARAMVALUE", m,
+ cparam->current.custom_string);
+ else
+ cgiSetArray("PARAMVALUE", m, "");
+ break;
+ }
+ }
+
+ if (units)
+ {
+ cgiSetArray("PARAMS", m, "Units");
+ cgiSetArray("PARAMTEXT", m, cgiText(_("Units")));
+ cgiSetArray("PARAMVALUE", m, units);
+ }
+ }
+ else
+ cgiSetVariable("ISCUSTOM", "0");
+
switch (option->ui)
{
case PPD_UI_BOOLEAN :
@@ -3199,17 +3295,21 @@ do_set_options(http_t *http, /* I - HTTP connection */
if (!strcmp(keyword, "PageRegion") ||
!strcmp(keyword, "PaperDimension") ||
!strcmp(keyword, "ImageableArea"))
- var = cgiGetVariable("PageSize");
+ var = get_option_value(ppd, "PageSize", value, sizeof(value));
else
- var = cgiGetVariable(keyword);
+ var = get_option_value(ppd, keyword, value, sizeof(value));
- if (var != NULL)
- cupsFilePrintf(out, "*Default%s: %s\n", keyword, var);
- else
+ if (!var)
cupsFilePrintf(out, "%s\n", line);
+ else
+ cupsFilePrintf(out, "*Default%s: %s\n", keyword, var);
}
}
+ /*
+ * TODO: We need to set the port-monitor attribute!
+ */
+
if ((var = cgiGetVariable("protocol")) != NULL)
cupsFilePrintf(out, "*cupsProtocol: %s\n", var);
@@ -3307,7 +3407,7 @@ do_set_options(http_t *http, /* I - HTTP connection */
/*
- * 'do_set_sharing()' - Set printer-is-shared value...
+ * 'do_set_sharing()' - Set printer-is-shared value.
*/
static void
@@ -3400,6 +3500,294 @@ do_set_sharing(http_t *http) /* I - HTTP connection */
/*
+ * 'get_option_value()' - Return the value of an option.
+ *
+ * This function also handles generation of custom option values.
+ */
+
+static char * /* O - Value string or NULL on error */
+get_option_value(
+ ppd_file_t *ppd, /* I - PPD file */
+ const char *name, /* I - Option name */
+ char *buffer, /* I - String buffer */
+ size_t bufsize) /* I - Size of buffer */
+{
+ char *bufptr, /* Pointer into buffer */
+ *bufend; /* End of buffer */
+ ppd_coption_t *coption; /* Custom option */
+ ppd_cparam_t *cparam; /* Current custom parameter */
+ char keyword[256]; /* Parameter name */
+ const char *val, /* Parameter value */
+ *uval; /* Units value */
+ long integer; /* Integer value */
+ double number, /* Number value */
+ number_points; /* Number in points */
+
+
+ /*
+ * See if we have a custom option choice...
+ */
+
+ if ((val = cgiGetVariable(name)) == NULL)
+ {
+ /*
+ * Option not found!
+ */
+
+ return (NULL);
+ }
+ else if (strcasecmp(val, "Custom") ||
+ (coption = ppdFindCustomOption(ppd, name)) == NULL)
+ {
+ /*
+ * Not a custom choice...
+ */
+
+ strlcpy(buffer, val, bufsize);
+ return (buffer);
+ }
+
+ /*
+ * OK, we have a custom option choice, format it...
+ */
+
+ *buffer = '\0';
+
+ if (!strcmp(coption->keyword, "PageSize"))
+ {
+ const char *lval; /* Length string value */
+ double width, /* Width value */
+ width_points, /* Width in points */
+ length, /* Length value */
+ length_points; /* Length in points */
+
+
+ val = cgiGetVariable("PageSize.Width");
+ lval = cgiGetVariable("PageSize.Height");
+ uval = cgiGetVariable("PageSize.Units");
+
+ if (!val || !lval || !uval ||
+ (width = strtod(val, NULL)) == 0.0 ||
+ (length = strtod(lval, NULL)) == 0.0 ||
+ (strcmp(uval, "pt") && strcmp(uval, "in") && strcmp(uval, "ft") &&
+ strcmp(uval, "cm") && strcmp(uval, "mm") && strcmp(uval, "m")))
+ return (NULL);
+
+ width_points = get_points(width, uval);
+ length_points = get_points(length, uval);
+
+ if (width_points < ppd->custom_min[0] ||
+ width_points > ppd->custom_max[0] ||
+ length_points < ppd->custom_min[1] ||
+ length_points > ppd->custom_max[1])
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%gx%g%s", width, length, uval);
+ }
+ else if (cupsArrayCount(coption->params) == 1)
+ {
+ cparam = ppdFirstCustomParam(coption);
+ snprintf(keyword, sizeof(keyword), "%s.%s", coption->keyword, cparam->name);
+
+ if ((val = cgiGetVariable(keyword)) == NULL)
+ return (NULL);
+
+ switch (cparam->type)
+ {
+ case PPD_CUSTOM_CURVE :
+ case PPD_CUSTOM_INVCURVE :
+ case PPD_CUSTOM_REAL :
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ number < cparam->minimum.custom_real ||
+ number > cparam->maximum.custom_real)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%g", number);
+ break;
+
+ case PPD_CUSTOM_INT :
+ if (!*val || (integer = strtol(val, NULL, 10)) == LONG_MIN ||
+ integer == LONG_MAX ||
+ integer < cparam->minimum.custom_int ||
+ integer > cparam->maximum.custom_int)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%ld", integer);
+ break;
+
+ case PPD_CUSTOM_POINTS :
+ snprintf(keyword, sizeof(keyword), "%s.Units", coption->keyword);
+
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ (uval = cgiGetVariable(keyword)) == NULL ||
+ (strcmp(uval, "pt") && strcmp(uval, "in") && strcmp(uval, "ft") &&
+ strcmp(uval, "cm") && strcmp(uval, "mm") && strcmp(uval, "m")))
+ return (NULL);
+
+ number_points = get_points(number, uval);
+ if (number_points < cparam->minimum.custom_points ||
+ number_points > cparam->maximum.custom_points)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%g%s", number, uval);
+ break;
+
+ case PPD_CUSTOM_PASSCODE :
+ for (uval = val; *uval; uval ++)
+ if (!isdigit(*uval & 255))
+ return (NULL);
+
+ case PPD_CUSTOM_PASSWORD :
+ case PPD_CUSTOM_STRING :
+ integer = (long)strlen(val);
+ if (integer < cparam->minimum.custom_string ||
+ integer > cparam->maximum.custom_string)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%s", val);
+ break;
+ }
+ }
+ else
+ {
+ const char *prefix = "{"; /* Prefix string */
+
+
+ bufptr = buffer;
+ bufend = buffer + bufsize;
+
+ for (cparam = ppdFirstCustomParam(coption);
+ cparam;
+ cparam = ppdNextCustomParam(coption))
+ {
+ snprintf(keyword, sizeof(keyword), "%s.%s", coption->keyword,
+ cparam->name);
+
+ if ((val = cgiGetVariable(keyword)) == NULL)
+ return (NULL);
+
+ snprintf(bufptr, bufend - bufptr, "%s%s=", prefix, cparam->name);
+ bufptr += strlen(bufptr);
+ prefix = " ";
+
+ switch (cparam->type)
+ {
+ case PPD_CUSTOM_CURVE :
+ case PPD_CUSTOM_INVCURVE :
+ case PPD_CUSTOM_REAL :
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ number < cparam->minimum.custom_real ||
+ number > cparam->maximum.custom_real)
+ return (NULL);
+
+ snprintf(bufptr, bufend - bufptr, "%g", number);
+ break;
+
+ case PPD_CUSTOM_INT :
+ if (!*val || (integer = strtol(val, NULL, 10)) == LONG_MIN ||
+ integer == LONG_MAX ||
+ integer < cparam->minimum.custom_int ||
+ integer > cparam->maximum.custom_int)
+ return (NULL);
+
+ snprintf(bufptr, bufend - bufptr, "%ld", integer);
+ break;
+
+ case PPD_CUSTOM_POINTS :
+ snprintf(keyword, sizeof(keyword), "%s.Units", coption->keyword);
+
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ (uval = cgiGetVariable(keyword)) == NULL ||
+ (strcmp(uval, "pt") && strcmp(uval, "in") &&
+ strcmp(uval, "ft") && strcmp(uval, "cm") &&
+ strcmp(uval, "mm") && strcmp(uval, "m")))
+ return (NULL);
+
+ number_points = get_points(number, uval);
+ if (number_points < cparam->minimum.custom_points ||
+ number_points > cparam->maximum.custom_points)
+ return (NULL);
+
+ snprintf(bufptr, bufend - bufptr, "%g%s", number, uval);
+ break;
+
+ case PPD_CUSTOM_PASSCODE :
+ for (uval = val; *uval; uval ++)
+ if (!isdigit(*uval & 255))
+ return (NULL);
+
+ case PPD_CUSTOM_PASSWORD :
+ case PPD_CUSTOM_STRING :
+ integer = (long)strlen(val);
+ if (integer < cparam->minimum.custom_string ||
+ integer > cparam->maximum.custom_string)
+ return (NULL);
+
+ if ((bufptr + 2) > bufend)
+ return (NULL);
+
+ bufend --;
+ *bufptr++ = '\"';
+
+ while (*val && bufptr < bufend)
+ {
+ if (*val == '\\' || *val == '\"')
+ {
+ if ((bufptr + 1) >= bufend)
+ return (NULL);
+
+ *bufptr++ = '\\';
+ }
+
+ *bufptr++ = *val++;
+ }
+
+ if (bufptr >= bufend)
+ return (NULL);
+
+ *bufptr++ = '\"';
+ *bufptr = '\0';
+ bufend ++;
+ break;
+ }
+
+ bufptr += strlen(bufptr);
+ }
+
+ if (bufptr == buffer || (bufend - bufptr) < 2)
+ return (NULL);
+
+ strcpy(bufptr, "}");
+ }
+
+ return (buffer);
+}
+
+
+/*
+ * 'get_points()' - Get a value in points.
+ */
+
+static double /* O - Number in points */
+get_points(double number, /* I - Original number */
+ const char *uval) /* I - Units */
+{
+ if (!strcmp(uval, "mm")) /* Millimeters */
+ return (number * 72.0 / 25.4);
+ else if (!strcmp(uval, "cm")) /* Centimeters */
+ return (number * 72.0 / 2.54);
+ else if (!strcmp(uval, "in")) /* Inches */
+ return (number * 72.0);
+ else if (!strcmp(uval, "ft")) /* Feet */
+ return (number * 72.0 * 12.0);
+ else if (!strcmp(uval, "m")) /* Meters */
+ return (number * 72.0 / 0.0254);
+ else /* Points */
+ return (number);
+}
+
+
+/*
* 'match_string()' - Return the number of matching characters.
*/
diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4
index e48fc0fe4..16e6b2b0e 100644
--- a/config-scripts/cups-common.m4
+++ b/config-scripts/cups-common.m4
@@ -188,6 +188,19 @@ if test $check_libusb = yes; then
LIBUSB="-lusb")])
fi
+dnl See if we have libwrap for TCP wrappers support...
+AC_ARG_ENABLE(tcp_wrappers, [ --enable-tcp-wrappers use libwrap for TCP wrappers support, default=no])
+
+LIBWRAP=""
+AC_SUBST(LIBWRAP)
+
+if test x$enable_tcp_wrappers = xyes; then
+ AC_CHECK_LIB(wrap, hosts_access,[
+ AC_CHECK_HEADER(tcpd.h,
+ AC_DEFINE(HAVE_TCPD_H)
+ LIBWRAP="-lwrap")])
+fi
+
dnl Flags for "ar" command...
case $uname in
Darwin* | *BSD*)
diff --git a/config-scripts/cups-compiler.m4 b/config-scripts/cups-compiler.m4
index 8598aebb9..8d30df79c 100644
--- a/config-scripts/cups-compiler.m4
+++ b/config-scripts/cups-compiler.m4
@@ -145,6 +145,7 @@ if test -n "$GCC"; then
# Additional warning options for development testing...
if test -d .svn; then
OPTIM="-Wshadow -Wunused $OPTIM"
+ CFLAGS="-Werror-implicit-function-declaration $CFLAGS"
PHPOPTIONS="-Wno-shadow"
fi
fi
diff --git a/config-scripts/cups-directories.m4 b/config-scripts/cups-directories.m4
index 4105ba17f..16d414d22 100644
--- a/config-scripts/cups-directories.m4
+++ b/config-scripts/cups-directories.m4
@@ -123,12 +123,14 @@ AC_ARG_WITH(rcdir, [ --with-rcdir set path for rc scripts],rcdir="$w
AC_ARG_WITH(rclevels, [ --with-rclevels set run levels for rc scripts],rclevels="$withval",rclevels="2 3 5")
AC_ARG_WITH(rcstart, [ --with-rcstart set start number for rc scripts],rcstart="$withval",rcstart="99")
AC_ARG_WITH(rcstop, [ --with-rcstop set stop number for rc scripts],rcstop="$withval",rcstop="00")
+AC_ARG_WITH(smfmanifestdir, [ --with-smfmanifestdir set path for Solaris SMF manifest],smfmanifestdir="$withval",smfmanifestdir="")
INITDIR=""
INITDDIR=""
RCLEVELS="$rclevels"
RCSTART="$rcstart"
RCSTOP="$rcstop"
+SMFMANIFESTDIR=""
if test x$rcdir = x; then
case "$uname" in
@@ -192,8 +194,12 @@ if test x$rcdir = x; then
SunOS*)
# Solaris
- INITDIR="/etc"
- RCSTART="81"
+ if test "x$smfmanifestdir" != x; then
+ SMFMANIFESTDIR=$smfmanifestdir
+ else
+ INITDIR="/etc"
+ RCSTART="81"
+ fi
;;
*)
@@ -214,6 +220,7 @@ AC_SUBST(INITDDIR)
AC_SUBST(RCLEVELS)
AC_SUBST(RCSTART)
AC_SUBST(RCSTOP)
+AC_SUBST(SMFMANIFESTDIR)
dnl Xinetd support...
AC_ARG_WITH(xinetd, [ --with-xinetd set path for xinetd config files],XINETD="$withval",XINETD="")
diff --git a/config-scripts/cups-ldap.m4 b/config-scripts/cups-ldap.m4
index 3f5adec23..1c5f516bc 100644
--- a/config-scripts/cups-ldap.m4
+++ b/config-scripts/cups-ldap.m4
@@ -14,22 +14,34 @@ dnl file is missing or damaged, see the license at "http://www.cups.org/".
dnl
AC_ARG_ENABLE(ldap, [ --enable-ldap turn on LDAP support, default=yes])
-AC_ARG_WITH(openldap-libs, [ --with-openldap-libs set directory for OpenLDAP library],
+AC_ARG_WITH(ldap-libs, [ --with-ldap-libs set directory for LDAP library],
LDFLAGS="-L$withval $LDFLAGS"
DSOFLAGS="-L$withval $DSOFLAGS",)
-AC_ARG_WITH(openldap-includes, [ --with-openldap-includes
- set directory for OpenLDAP includes],
+AC_ARG_WITH(ldap-includes, [ --with-ldap-includes set directory for LDAP includes],
CFLAGS="-I$withval $CFLAGS"
CPPFLAGS="-I$withval $CPPFLAGS",)
LIBLDAP=""
if test x$enable_ldap != xno; then
- AC_CHECK_HEADER(ldap.h,
+ AC_CHECK_HEADER(ldap.h, [
AC_CHECK_LIB(ldap, ldap_initialize,
- AC_DEFINE(HAVE_LDAP)
- AC_DEFINE(HAVE_OPENLDAP)
- LIBLDAP="-lldap"))
+ AC_DEFINE(HAVE_LDAP)
+ AC_DEFINE(HAVE_OPENLDAP)
+ LIBLDAP="-lldap"
+ AC_CHECK_LIB(ldap, ldap_start_tls,
+ AC_DEFINE(HAVE_LDAP_SSL)),
+
+ AC_CHECK_LIB(ldap, ldap_init,
+ AC_DEFINE(HAVE_LDAP)
+ AC_DEFINE(HAVE_MOZILLA_LDAP)
+ LIBLDAP="-lldap"
+ AC_CHECK_HEADER(ldap_ssl.h, AC_DEFINE(HAVE_LDAP_SSL_H),,[#include <ldap.h>])
+ AC_CHECK_LIB(ldap, ldapssl_init,
+ AC_DEFINE(HAVE_LDAP_SSL)))
+ )
+ AC_CHECK_LIB(ldap, ldap_set_rebind_proc, AC_DEFINE(HAVE_LDAP_REBIND_PROC))
+ ])
fi
AC_SUBST(LIBLDAP)
diff --git a/config.h.in b/config.h.in
index cd801f72e..9a95a084f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -307,6 +307,10 @@
#undef HAVE_LDAP
#undef HAVE_OPENLDAP
+#undef HAVE_MOZILLA_LDAP
+#undef HAVE_LDAP_SSL_H
+#undef HAVE_LDAP_SSL
+#undef HAVE_LDAP_REBIND_PROC
/*
@@ -586,6 +590,13 @@
#undef HAVE_USB_H
+/*
+ * Do we have libwrap and tcpd.h?
+ */
+
+#undef HAVE_TCPD_H
+
+
#endif /* !_CUPS_CONFIG_H_ */
/*
diff --git a/configure.in b/configure.in
index 0425660be..8ff9a0e0c 100644
--- a/configure.in
+++ b/configure.in
@@ -65,7 +65,7 @@ AC_SUBST(UNINSTALL_LANGUAGES)
AC_OUTPUT(Makedefs packaging/cups.list init/cups.sh init/cups-lpd cups-config
conf/cupsd.conf conf/mime.convs conf/pam.std conf/snmp.conf
doc/index.html doc/help/ref-cupsd-conf.html doc/help/standard.html
- init/org.cups.cups-lpd.plist
+ init/org.cups.cups-lpd.plist init/cups.xml
man/client.conf.man man/cups-deviced.man man/cups-driverd.man
man/cups-lpd.man man/cupsaddsmb.man man/cupsd.man
man/cupsd.conf.man man/drv.man man/lpoptions.man
diff --git a/cups/adminutil.c b/cups/adminutil.c
index 87ff36fd7..3ea7e81af 100644
--- a/cups/adminutil.c
+++ b/cups/adminutil.c
@@ -260,9 +260,9 @@ cupsAdminCreateWindowsPPD(
if ((ptr = strchr(line, ':')) == NULL)
{
snprintf(line, sizeof(line),
- _cupsLangString(language, _("Missing value on line %d!")),
- linenum);
- _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+ _cupsLangString(language, _("Missing value on line %d!")),
+ linenum);
+ _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line, 0);
cupsFileClose(srcfp);
cupsFileClose(dstfp);
@@ -281,7 +281,7 @@ cupsAdminCreateWindowsPPD(
_cupsLangString(language,
_("Missing double quote on line %d!")),
linenum);
- _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+ _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line, 0);
cupsFileClose(srcfp);
cupsFileClose(dstfp);
@@ -300,7 +300,7 @@ cupsAdminCreateWindowsPPD(
_cupsLangString(language,
_("Bad option + choice on line %d!")),
linenum);
- _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+ _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line, 0);
cupsFileClose(srcfp);
cupsFileClose(dstfp);
@@ -343,10 +343,7 @@ cupsAdminCreateWindowsPPD(
if (linenum == 0)
{
- snprintf(line, sizeof(line),
- _cupsLangString(language, _("Empty PPD file!")),
- linenum);
- _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+ _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, _("Empty PPD file!"), 1);
cupsFileClose(dstfp);
unlink(buffer);
@@ -434,7 +431,7 @@ cupsAdminExportSamba(
if (!dest || !ppd || !samba_server || !samba_user || !samba_password)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (0);
}
@@ -444,7 +441,7 @@ cupsAdminExportSamba(
if ((fp = cupsTempFile2(authfile, sizeof(authfile))) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
return (0);
}
@@ -497,7 +494,7 @@ cupsAdminExportSamba(
_("Unable to copy Windows 2000 printer "
"driver files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -532,7 +529,7 @@ cupsAdminExportSamba(
_("Unable to copy CUPS printer driver "
"files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -575,7 +572,7 @@ cupsAdminExportSamba(
_("Unable to install Windows 2000 printer "
"driver files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -620,7 +617,7 @@ cupsAdminExportSamba(
_("Unable to copy Windows 9x printer "
"driver files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -649,7 +646,7 @@ cupsAdminExportSamba(
_("Unable to install Windows 9x printer "
"driver files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -701,7 +698,7 @@ cupsAdminExportSamba(
_("Unable to copy 64-bit Windows printer "
"driver files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -736,7 +733,7 @@ cupsAdminExportSamba(
_("Unable to copy 64-bit CUPS printer driver "
"files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -779,7 +776,7 @@ cupsAdminExportSamba(
_("Unable to install Windows 2000 printer "
"driver files (%d)!")), status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -804,13 +801,13 @@ cupsAdminExportSamba(
"are installed!")),
sizeof(message));
- _cupsSetError(IPP_NOT_FOUND, message);
+ _cupsSetError(IPP_NOT_FOUND, message, 0);
_cupsLangPrintf(logfile, "%s\n", message);
}
if (have_drivers == 0)
{
- _cupsSetError(IPP_NOT_FOUND, message);
+ _cupsSetError(IPP_NOT_FOUND, message, 0);
unlink(authfile);
@@ -831,7 +828,7 @@ cupsAdminExportSamba(
_("Unable to set Windows printer driver (%d)!")),
status);
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
if (logfile)
_cupsLangPrintf(logfile, "%s\n", message);
@@ -901,7 +898,7 @@ _cupsAdminGetServerSettings(
if (!http || !num_settings || !settings)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
if (num_settings)
*num_settings = 0;
@@ -928,9 +925,9 @@ _cupsAdminGetServerSettings(
snprintf(message, sizeof(message),
- _cupsLangString(cupsLangDefault(), _("open of %s failed: %s")),
+ _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")),
cupsdconf, strerror(errno));
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
}
}
else
@@ -1224,7 +1221,7 @@ _cupsAdminSetServerSettings(
if (!http || !num_settings || !settings)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (0);
}
@@ -1238,7 +1235,7 @@ _cupsAdminSetServerSettings(
{
if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
return (0);
}
}
@@ -1395,7 +1392,7 @@ _cupsAdminSetServerSettings(
if (remote)
unlink(cupsdconf);
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
return (0);
}
@@ -2203,7 +2200,7 @@ get_cupsd_conf(
snprintf(message, sizeof(message),
_cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")),
name, strerror(errno));
- _cupsSetError(IPP_INTERNAL_ERROR, message);
+ _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
*name = '\0';
@@ -2225,7 +2222,7 @@ get_cupsd_conf(
{
*name = '\0';
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
invalidate_cupsd_cache(cg);
diff --git a/cups/backend.c b/cups/backend.c
index 021dad2e2..ca4fad2f3 100644
--- a/cups/backend.c
+++ b/cups/backend.c
@@ -1,5 +1,5 @@
/*
- * "$Id: backend.c 7583 2008-05-16 17:47:16Z mike $"
+ * "$Id: backend.c 7810 2008-07-29 01:11:15Z mike $"
*
* Backend functions for the Common UNIX Printing System (CUPS).
*
@@ -17,6 +17,8 @@
* Contents:
*
* cupsBackendDeviceURI() - Get the device URI for a backend.
+ * cupsBackendReport() - Write a device line from a backend.
+ * quote_string() - Write a quoted string to stdout, escaping \ and ".
*/
/*
@@ -29,6 +31,13 @@
/*
+ * Local functions...
+ */
+
+static void quote_string(const char *s);
+
+
+/*
* 'cupsBackendDeviceURI()' - Get the device URI for a backend.
*
* The "argv" argument is the argv argument passed to main(). This
@@ -58,5 +67,64 @@ cupsBackendDeviceURI(char **argv) /* I - Command-line arguments */
/*
- * End of "$Id: backend.c 7583 2008-05-16 17:47:16Z mike $".
+ * 'cupsBackendReport()' - Write a device line from a backend.
+ *
+ * This function writes a single device line to stdout for a backend.
+ * It handles quoting of special characters in the device-make-and-model,
+ * device-info, device-id, and device-location strings.
+ */
+
+void
+cupsBackendReport(
+ const char *device_scheme, /* I - device-scheme string */
+ const char *device_uri, /* I - device-uri string */
+ const char *device_make_and_model, /* I - device-make-and-model string or @code NULL@ */
+ const char *device_info, /* I - device-info string or @code NULL@ */
+ const char *device_id, /* I - device-id string or @code NULL@ */
+ const char *device_location) /* I - device-location string or @code NULL@ */
+{
+ if (!device_scheme || !device_uri)
+ return;
+
+ printf("%s %s", device_scheme, device_uri);
+ if (device_make_and_model && *device_make_and_model)
+ quote_string(device_make_and_model);
+ else
+ quote_string("unknown");
+ quote_string(device_info);
+ quote_string(device_id);
+ quote_string(device_location);
+ putchar('\n');
+ fflush(stdout);
+}
+
+
+/*
+ * 'quote_string()' - Write a quoted string to stdout, escaping \ and ".
+ */
+
+static void
+quote_string(const char *s) /* I - String to write */
+{
+ fputs(" \"", stdout);
+
+ if (s)
+ {
+ while (*s)
+ {
+ if (*s == '\\' || *s == '\"')
+ putchar('\\');
+
+ putchar(*s);
+
+ s ++;
+ }
+ }
+
+ putchar('\"');
+}
+
+
+/*
+ * End of "$Id: backend.c 7810 2008-07-29 01:11:15Z mike $".
*/
diff --git a/cups/backend.h b/cups/backend.h
index 77bf57569..f128895da 100644
--- a/cups/backend.h
+++ b/cups/backend.h
@@ -48,7 +48,14 @@ typedef enum cups_backend_e cups_backend_t;
*/
extern const char *cupsBackendDeviceURI(char **argv) _CUPS_API_1_2;
-
+extern void cupsBackendReport(const char *device_scheme,
+ const char *device_uri,
+ const char *device_make_and_model,
+ const char *device_info,
+ const char *device_id,
+ const char *device_location)
+ _CUPS_API_1_4;
+
#endif /* !_CUPS_BACKEND_H_ */
diff --git a/cups/cups.h b/cups/cups.h
index 1038c8313..08aaf3479 100644
--- a/cups/cups.h
+++ b/cups/cups.h
@@ -124,7 +124,8 @@ typedef const char *(*cups_password_cb_t)(const char *prompt);
typedef void (*cups_device_cb_t)(const char *device_class,
const char *device_id, const char *device_info,
const char *device_make_and_model,
- const char *device_uri, void *user_data);
+ const char *device_uri,
+ const char *device_location, void *user_data);
/**** Device callback @since CUPS 1.4@ ****/
typedef struct cups_option_s /**** Printer Options ****/
diff --git a/cups/dest.c b/cups/dest.c
index 66289b2c7..d2a9b3462 100644
--- a/cups/dest.c
+++ b/cups/dest.c
@@ -31,9 +31,9 @@
* server.
* cupsSetDests2() - Save the list of destinations for the specified
* server.
+ * appleCopyNetwork() - Get the network ID for the current location.
* appleGetDefault() - Get the default printer for this location.
* appleGetLocations() - Get the location history array.
- * appleGetNetwork() - Get the network ID for the current location.
* appleGetPrinter() - Get a printer from the history array.
* appleSetDefault() - Set the default printer for this location.
* appleUseLastPrinter() - Get the default printer preference value.
@@ -73,9 +73,9 @@
*/
#ifdef __APPLE__
+static CFStringRef appleCopyNetwork(void);
static char *appleGetDefault(char *name, int namesize);
static CFArrayRef appleGetLocations(void);
-static CFStringRef appleGetNetwork(void);
static CFStringRef appleGetPrinter(CFArrayRef locations, CFStringRef network,
CFIndex *locindex);
static void appleSetDefault(const char *name);
@@ -930,6 +930,44 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
#ifdef __APPLE__
/*
+ * 'appleCopyNetwork()' - Get the network ID for the current location.
+ */
+
+static CFStringRef /* O - Network ID */
+appleCopyNetwork(void)
+{
+ SCDynamicStoreRef dynamicStore; /* System configuration data */
+ CFStringRef key; /* Current network configuration key */
+ CFDictionaryRef ip_dict; /* Network configuration data */
+ CFStringRef network = NULL; /* Current network ID */
+
+
+ if ((dynamicStore = SCDynamicStoreCreate(NULL, CFSTR("Printing"), NULL,
+ NULL)) != NULL)
+ {
+ 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);
+ }
+
+ return (network);
+}
+
+
+/*
* 'appleGetDefault()' - Get the default printer for this location.
*/
@@ -957,7 +995,7 @@ appleGetDefault(char *name, /* I - Name buffer */
* Get the current location...
*/
- if ((network = appleGetNetwork()) == NULL)
+ if ((network = appleCopyNetwork()) == NULL)
{
DEBUG_puts("appleGetDefault: Unable to get current network...");
return (NULL);
@@ -980,6 +1018,8 @@ appleGetDefault(char *name, /* I - Name buffer */
DEBUG_puts("appleGetDefault: Missing or bad location history array...");
+ CFRelease(network);
+
return (NULL);
}
@@ -991,6 +1031,8 @@ appleGetDefault(char *name, /* I - Name buffer */
else
name[0] = '\0';
+ CFRelease(network);
+
DEBUG_printf(("appleGetDefault: Returning \"%s\"...\n", name));
return (*name ? name : NULL);
@@ -1026,44 +1068,6 @@ appleGetLocations(void)
/*
- * 'appleGetNetwork()' - Get the network ID for the current location.
- */
-
-static CFStringRef /* O - Network ID */
-appleGetNetwork(void)
-{
- SCDynamicStoreRef dynamicStore; /* System configuration data */
- CFStringRef key; /* Current network configuration key */
- CFDictionaryRef ip_dict; /* Network configuration data */
- CFStringRef network = NULL; /* Current network ID */
-
-
- if ((dynamicStore = SCDynamicStoreCreate(NULL, CFSTR("Printing"), NULL,
- NULL)) != NULL)
- {
- 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);
- }
-
- return (network);
-}
-
-
-/*
* 'appleGetPrinter()' - Get a printer from the history array.
*/
@@ -1122,7 +1126,7 @@ appleSetDefault(const char *name) /* I - Default printer/class name */
* Get the current location...
*/
- if ((network = appleGetNetwork()) == NULL)
+ if ((network = appleCopyNetwork()) == NULL)
{
DEBUG_puts("appleSetDefault: Unable to get current network...");
return;
@@ -1202,6 +1206,7 @@ appleSetDefault(const char *name) /* I - Default printer/class name */
CFRelease(newlocation);
}
+ CFRelease(network);
CFRelease(newprinter);
}
diff --git a/cups/getdevices.c b/cups/getdevices.c
index d0e1cf2fa..c6f7ddac3 100644
--- a/cups/getdevices.c
+++ b/cups/getdevices.c
@@ -15,6 +15,7 @@
*
* Contents:
*
+ * cupsGetDevices() - Get available printer devices.
*/
/*
@@ -50,6 +51,7 @@ cupsGetDevices(
const char *device_class, /* device-class value */
*device_id, /* device-id value */
*device_info, /* device-info value */
+ *device_location, /* device-location value */
*device_make_and_model, /* device-make-and-model value */
*device_uri; /* device-uri value */
int blocking; /* Current blocking-IO mode */
@@ -160,6 +162,7 @@ cupsGetDevices(
device_class = NULL;
device_id = NULL;
device_info = NULL;
+ device_location = "";
device_make_and_model = NULL;
device_uri = NULL;
attr = NULL;
@@ -192,11 +195,13 @@ cupsGetDevices(
if (device_class && device_id && device_info && device_make_and_model &&
device_uri)
(*callback)(device_class, device_id, device_info,
- device_make_and_model, device_uri, user_data);
+ device_make_and_model, device_uri, device_location,
+ user_data);
device_class = NULL;
device_id = NULL;
device_info = NULL;
+ device_location = "";
device_make_and_model = NULL;
device_uri = NULL;
}
@@ -209,6 +214,9 @@ cupsGetDevices(
else if (!strcmp(attr->name, "device-info") &&
attr->value_tag == IPP_TAG_TEXT)
device_info = attr->values[0].string.text;
+ else if (!strcmp(attr->name, "device-location") &&
+ attr->value_tag == IPP_TAG_TEXT)
+ device_location = attr->values[0].string.text;
else if (!strcmp(attr->name, "device-make-and-model") &&
attr->value_tag == IPP_TAG_TEXT)
device_make_and_model = attr->values[0].string.text;
@@ -225,7 +233,7 @@ cupsGetDevices(
if (device_class && device_id && device_info && device_make_and_model &&
device_uri)
(*callback)(device_class, device_id, device_info,
- device_make_and_model, device_uri, user_data);
+ device_make_and_model, device_uri, device_location, user_data);
/*
* Set the IPP status and return...
@@ -235,7 +243,7 @@ cupsGetDevices(
httpFlush(http);
if (status == IPP_ERROR)
- _cupsSetError(IPP_ERROR, NULL);
+ _cupsSetError(IPP_ERROR, NULL, 0);
else
{
attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT);
@@ -245,8 +253,8 @@ cupsGetDevices(
attr ? attr->values[0].string.text : ""));
_cupsSetError(response->request.status.status_code,
- attr ? attr->values[0].string.text :
- ippErrorString(response->request.status.status_code));
+ attr ? attr->values[0].string.text :
+ ippErrorString(response->request.status.status_code), 0);
}
ippDelete(response);
diff --git a/cups/globals.h b/cups/globals.h
index d098e868e..f2ae63b97 100644
--- a/cups/globals.h
+++ b/cups/globals.h
@@ -136,7 +136,8 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/
extern http_t *_cupsConnect(void);
extern const char *_cupsGetPassword(const char *prompt);
extern _cups_globals_t *_cupsGlobals(void);
-extern void _cupsSetError(ipp_status_t status, const char *message);
+extern void _cupsSetError(ipp_status_t status, const char *message,
+ int localize);
extern void _cupsSetHTTPError(http_status_t status);
diff --git a/cups/langprintf.c b/cups/langprintf.c
index 84956888c..059e9983f 100644
--- a/cups/langprintf.c
+++ b/cups/langprintf.c
@@ -17,9 +17,11 @@
*
* Contents:
*
- * _cupsLangPrintf() - Print a formatted message string to a file.
- * _cupsLangPuts() - Print a static message string to a file.
- * _cupsSetLocale() - Set the current locale and transcode the command-line.
+ * _cupsLangPrintError() - Print a message followed by a standard error.
+ * _cupsLangPrintf() - Print a formatted message string to a file.
+ * _cupsLangPuts() - Print a static message string to a file.
+ * _cupsSetLocale() - Set the current locale and transcode the
+ * command-line.
*/
/*
diff --git a/cups/libcups.exp b/cups/libcups.exp
index 8f34b3ccc..3da3642b0 100644
--- a/cups/libcups.exp
+++ b/cups/libcups.exp
@@ -86,6 +86,7 @@ _cupsArrayUserData
_cupsBackChannelRead
_cupsBackChannelWrite
_cupsBackendDeviceURI
+_cupsBackendReport
_cupsCancelJob
_cupsCancelJob2
_cupsCharsetToUTF8
diff --git a/cups/ppd.c b/cups/ppd.c
index 75db5c5ac..e88dad15b 100644
--- a/cups/ppd.c
+++ b/cups/ppd.c
@@ -1050,14 +1050,15 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */
* Add the "custom" option...
*/
- if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
- {
- DEBUG_puts("Unable to add Custom choice!");
+ if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
+ if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
+ {
+ DEBUG_puts("Unable to add Custom choice!");
- cg->ppd_status = PPD_ALLOC_ERROR;
+ cg->ppd_status = PPD_ALLOC_ERROR;
- goto error;
- }
+ goto error;
+ }
strlcpy(choice->text, text[0] ? text : _("Custom"),
sizeof(choice->text));
@@ -1089,14 +1090,15 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */
if (custom_option)
{
- if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
- {
- DEBUG_puts("Unable to add Custom choice!");
+ if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
+ if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
+ {
+ DEBUG_puts("Unable to add Custom choice!");
- cg->ppd_status = PPD_ALLOC_ERROR;
+ cg->ppd_status = PPD_ALLOC_ERROR;
- goto error;
- }
+ goto error;
+ }
strlcpy(choice->text, text[0] ? text : _("Custom"),
sizeof(choice->text));
@@ -1301,14 +1303,15 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */
if ((custom_attr = ppdFindAttr(ppd, custom_name, "True")) != NULL)
{
- if ((choice = ppd_add_choice(option, "Custom")) == NULL)
- {
- DEBUG_puts("Unable to add Custom choice!");
+ if ((choice = ppdFindChoice(option, "Custom")) == NULL)
+ if ((choice = ppd_add_choice(option, "Custom")) == NULL)
+ {
+ DEBUG_puts("Unable to add Custom choice!");
- cg->ppd_status = PPD_ALLOC_ERROR;
+ cg->ppd_status = PPD_ALLOC_ERROR;
- goto error;
- }
+ goto error;
+ }
strlcpy(choice->text,
custom_attr->text[0] ? custom_attr->text : _("Custom"),
diff --git a/cups/request.c b/cups/request.c
index f8978a627..fc6a7fa18 100644
--- a/cups/request.c
+++ b/cups/request.c
@@ -80,7 +80,7 @@ cupsDoFileRequest(http_t *http, /* I - Connection to server or @code CUPS_HT
*/
_cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
+ NULL, 0);
ippDelete(request);
@@ -143,7 +143,7 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
{
ippDelete(request);
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (NULL);
}
@@ -169,7 +169,7 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
*/
_cupsSetError(errno == EBADF ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
+ NULL, 0);
ippDelete(request);
@@ -188,7 +188,7 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
ippDelete(request);
- _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
+ _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR), 0);
return (NULL);
}
@@ -395,7 +395,7 @@ cupsGetResponse(http_t *http, /* I - Connection to server or @code CUPS_HTTP
ippDelete(response);
response = NULL;
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
+ _cupsSetError(IPP_SERVICE_UNAVAILABLE, NULL, 0);
}
}
else if (status != HTTP_ERROR)
@@ -453,8 +453,8 @@ cupsGetResponse(http_t *http, /* I - Connection to server or @code CUPS_HTTP
attr ? attr->values[0].string.text : ""));
_cupsSetError(response->request.status.status_code,
- attr ? attr->values[0].string.text :
- ippErrorString(response->request.status.status_code));
+ attr ? attr->values[0].string.text :
+ ippErrorString(response->request.status.status_code), 0);
}
else if (status != HTTP_OK)
_cupsSetHTTPError(status);
@@ -492,7 +492,7 @@ cupsReadResponseData(
if ((http = cg->http) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, "No active connection");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("No active connection"), 1);
return (-1);
}
}
@@ -542,7 +542,7 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
if (!request || !resource)
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (HTTP_ERROR);
}
@@ -724,7 +724,7 @@ cupsWriteRequestData(
if ((http = cg->http) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, "No active connection");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("No active connection"), 1);
return (HTTP_ERROR);
}
}
@@ -753,26 +753,49 @@ cupsWriteRequestData(
void
_cupsSetError(ipp_status_t status, /* I - IPP status code */
- const char *message) /* I - status-message value */
+ const char *message, /* I - status-message value */
+ int localize) /* I - Localize the message? */
{
_cups_globals_t *cg; /* Global data */
+ if (!message && errno)
+ {
+ message = strerror(errno);
+ localize = 0;
+ }
+
cg = _cupsGlobals();
cg->last_error = status;
if (cg->last_status_message)
{
- free(cg->last_status_message);
+ _cupsStrFree(cg->last_status_message);
cg->last_status_message = NULL;
}
if (message)
- cg->last_status_message = strdup(message);
+ {
+ if (localize)
+ {
+ /*
+ * Get the message catalog...
+ */
+
+ if (!cg->lang_default)
+ cg->lang_default = cupsLangDefault();
+
+ cg->last_status_message = _cupsStrAlloc(_cupsLangString(cg->lang_default,
+ message));
+ }
+ else
+ cg->last_status_message = _cupsStrAlloc(message);
+ }
DEBUG_printf(("_cupsSetError: last_error=%s, last_status_message=\"%s\"\n",
- ippErrorString(cg->last_error), message ? message : ""));
+ ippErrorString(cg->last_error),
+ cg->last_status_message ? cg->last_status_message : ""));
}
@@ -786,37 +809,37 @@ _cupsSetHTTPError(http_status_t status) /* I - HTTP status code */
switch (status)
{
case HTTP_NOT_FOUND :
- _cupsSetError(IPP_NOT_FOUND, httpStatus(status));
+ _cupsSetError(IPP_NOT_FOUND, httpStatus(status), 0);
break;
case HTTP_UNAUTHORIZED :
- _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status));
+ _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status), 0);
break;
case HTTP_FORBIDDEN :
- _cupsSetError(IPP_FORBIDDEN, httpStatus(status));
+ _cupsSetError(IPP_FORBIDDEN, httpStatus(status), 0);
break;
case HTTP_BAD_REQUEST :
- _cupsSetError(IPP_BAD_REQUEST, httpStatus(status));
+ _cupsSetError(IPP_BAD_REQUEST, httpStatus(status), 0);
break;
case HTTP_REQUEST_TOO_LARGE :
- _cupsSetError(IPP_REQUEST_VALUE, httpStatus(status));
+ _cupsSetError(IPP_REQUEST_VALUE, httpStatus(status), 0);
break;
case HTTP_NOT_IMPLEMENTED :
- _cupsSetError(IPP_OPERATION_NOT_SUPPORTED, httpStatus(status));
+ _cupsSetError(IPP_OPERATION_NOT_SUPPORTED, httpStatus(status), 0);
break;
case HTTP_NOT_SUPPORTED :
- _cupsSetError(IPP_VERSION_NOT_SUPPORTED, httpStatus(status));
+ _cupsSetError(IPP_VERSION_NOT_SUPPORTED, httpStatus(status), 0);
break;
default :
DEBUG_printf(("HTTP error %d mapped to IPP_SERVICE_UNAVAILABLE!\n",
status));
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status));
+ _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status), 0);
break;
}
}
diff --git a/cups/testppd.c b/cups/testppd.c
index 943e390e1..cfd872d29 100644
--- a/cups/testppd.c
+++ b/cups/testppd.c
@@ -602,7 +602,14 @@ main(int argc, /* I - Number of command-line arguments */
if (!strncmp(argv[1], "-d", 2))
+ {
filename = cupsGetPPD(argv[1] + 2);
+ if (!filename)
+ {
+ printf("%s: %s\n", argv[1], cupsLastErrorString());
+ return (1);
+ }
+ }
else
filename = argv[1];
diff --git a/cups/util.c b/cups/util.c
index 605cd89e8..f52bbe7f0 100644
--- a/cups/util.c
+++ b/cups/util.c
@@ -131,7 +131,7 @@ cupsCancelJob2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
if (job_id < -1 || (!name && job_id == 0))
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (0);
}
@@ -229,7 +229,7 @@ cupsCreateJob(
if (!name)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (0);
}
@@ -239,7 +239,7 @@ cupsCreateJob(
if ((request = ippNewRequest(IPP_CREATE_JOB)) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
return (0);
}
@@ -346,7 +346,7 @@ cupsGetClasses(char ***classes) /* O - Classes */
if (!classes)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (0);
}
@@ -596,7 +596,7 @@ cupsGetJobs2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_D
if (!jobs)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (-1);
}
@@ -610,7 +610,7 @@ cupsGetJobs2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_D
if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
"localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri!"), 1);
return (-1);
}
@@ -764,7 +764,7 @@ cupsGetJobs2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_D
* Ran out of memory!
*/
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
cupsFreeJobs(n, *jobs);
*jobs = NULL;
@@ -921,19 +921,19 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL
if (!name)
{
- _cupsSetError(IPP_INTERNAL_ERROR, "No printer name!");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name!"), 1);
return (HTTP_NOT_ACCEPTABLE);
}
if (!modtime)
{
- _cupsSetError(IPP_INTERNAL_ERROR, "No modification time!");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time!"), 1);
return (HTTP_NOT_ACCEPTABLE);
}
if (!buffer || bufsize <= 1)
{
- _cupsSetError(IPP_INTERNAL_ERROR, "Bad filename buffer!");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer!"), 1);
return (HTTP_NOT_ACCEPTABLE);
}
@@ -1010,7 +1010,7 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL
* Can't open file; close the server connection and return NULL...
*/
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
if (http2 != http)
httpClose(http2);
@@ -1043,17 +1043,17 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL
switch (status)
{
case HTTP_NOT_FOUND :
- _cupsSetError(IPP_NOT_FOUND, httpStatus(status));
+ _cupsSetError(IPP_NOT_FOUND, httpStatus(status), 0);
break;
case HTTP_UNAUTHORIZED :
- _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status));
+ _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status), 0);
break;
default :
DEBUG_printf(("HTTP error %d mapped to IPP_SERVICE_UNAVAILABLE!\n",
status));
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status));
+ _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status), 0);
break;
}
@@ -1096,7 +1096,7 @@ cupsGetPrinters(char ***printers) /* O - Printers */
if (!printers)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (0);
}
@@ -1208,7 +1208,7 @@ cupsGetServerPPD(http_t *http, /* I - Connection to server or @code CUPS_HTT
if (!name)
{
- _cupsSetError(IPP_INTERNAL_ERROR, "No PPD name!");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("No PPD name!"), 1);
return (NULL);
}
@@ -1227,7 +1227,7 @@ cupsGetServerPPD(http_t *http, /* I - Connection to server or @code CUPS_HTT
* Can't open file; close the server connection and return NULL...
*/
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
return (NULL);
}
@@ -1388,7 +1388,7 @@ cupsPrintFiles2(
if (!name || num_files < 1 || !files)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
return (0);
}
@@ -1490,7 +1490,7 @@ cupsStartDocument(
if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
return (0);
}
@@ -1583,8 +1583,13 @@ _cupsConnect(void)
{
if ((cg->http = httpConnectEncrypt(cupsServer(), ippPort(),
cupsEncryption())) == NULL)
- _cupsSetError(IPP_SERVICE_UNAVAILABLE,
- errno ? strerror(errno) : "Unable to connect to host.");
+ {
+ if (errno)
+ _cupsSetError(IPP_SERVICE_UNAVAILABLE, NULL, 0);
+ else
+ _cupsSetError(IPP_SERVICE_UNAVAILABLE,
+ _("Unable to connect to host."), 1);
+ }
}
/*
@@ -1642,7 +1647,7 @@ cups_get_printer_uri(
if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
"localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
{
- _cupsSetError(IPP_INTERNAL_ERROR, "Unable to create printer-uri!");
+ _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri!"), 1);
*host = '\0';
*resource = '\0';
@@ -1777,7 +1782,8 @@ cups_get_printer_uri(
if (!strncmp(resource, "/classes/", 9))
{
- _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found for class!"));
+ _cupsSetError(IPP_INTERNAL_ERROR,
+ _("No printer-uri found for class!"), 1);
*host = '\0';
*resource = '\0';
@@ -1792,7 +1798,7 @@ cups_get_printer_uri(
}
if (cupsLastError() != IPP_NOT_FOUND)
- _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!"));
+ _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!"), 1);
*host = '\0';
*resource = '\0';
diff --git a/cups/versioning.h b/cups/versioning.h
index 659d55bef..96972ee74 100644
--- a/cups/versioning.h
+++ b/cups/versioning.h
@@ -3,7 +3,7 @@
*
* API versioning definitions for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -22,48 +22,33 @@
* _CUPS_API_1_1, _CUPS_API_1_1_19, _CUPS_API_1_1_20, _CUPS_API_1_1_21,
* _CUPS_API_1_2, _CUPS_API_1_3, _CUPS_API_1_4 - which add compiler-
* specific attributes that flag functions that are deprecated or added
- * in particular releases. On Mac OS X, the _CUPS_API_* constants are
- * defined based on the value of the MAC_OS_X_VERSION_MAX_ALLOWED constant
+ * in particular releases.
+ *
+ * On Mac OS X, the _CUPS_API_* constants are defined based on the values of
+ * the MAC_OS_X_VERSION_MIN_ALLOWED and MAC_OS_X_VERSION_MAX_ALLOWED constants
* provided by the compiler.
*/
# if defined(__APPLE__) && !defined(_CUPS_SOURCE)
-# if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3
-# define _CUPS_API_1_1_19 __attribute__((unavailable))
-# define _CUPS_API_1_1_20 __attribute__((unavailable))
-# define _CUPS_API_1_1_21 __attribute__((unavailable))
-# define _CUPS_API_1_2 __attribute__((unavailable))
-# define _CUPS_API_1_3 __attribute__((unavailable))
-# define _CUPS_API_1_4 __attribute__((unavailable))
-# elif MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
-# define _CUPS_API_1_1_19
-# define _CUPS_API_1_1_20 __attribute__((unavailable))
-# define _CUPS_API_1_1_21 __attribute__((unavailable))
-# define _CUPS_API_1_2 __attribute__((unavailable))
-# define _CUPS_API_1_3 __attribute__((unavailable))
-# define _CUPS_API_1_4 __attribute__((unavailable))
-# elif MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
-# define _CUPS_API_1_1_19
-# define _CUPS_API_1_1_20
-# define _CUPS_API_1_1_21
-# define _CUPS_API_1_2 __attribute__((unavailable))
-# define _CUPS_API_1_3 __attribute__((unavailable))
-# define _CUPS_API_1_4 __attribute__((unavailable))
-# elif MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5
-# define _CUPS_API_1_1_19
-# define _CUPS_API_1_1_20
-# define _CUPS_API_1_1_21
-# define _CUPS_API_1_2
-# define _CUPS_API_1_3
-# define _CUPS_API_1_4 __attribute__((unavailable))
-# else
-# define _CUPS_API_1_1_19
-# define _CUPS_API_1_1_20
-# define _CUPS_API_1_1_21
-# define _CUPS_API_1_2
-# define _CUPS_API_1_3
-# define _CUPS_API_1_4
-# endif /* MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_x */
+# include <AvailabilityMacros.h>
+# ifndef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER
+# define AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER __attribute__((unavailable))
+# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER */
+# ifndef AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER
+# define AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER __attribute__((unavailable))
+# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER */
+# ifndef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
+# define AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER __attribute__((unavailable))
+# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
+# ifndef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+# define AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER __attribute__((unavailable))
+# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER */
+# define _CUPS_API_1_1_19 AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER
+# define _CUPS_API_1_1_20 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER
+# define _CUPS_API_1_1_21 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER
+# define _CUPS_API_1_2 AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
+# define _CUPS_API_1_3 AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
+# define _CUPS_API_1_4 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
# else
# define _CUPS_API_1_1_19
# define _CUPS_API_1_1_20
diff --git a/doc/cups.css b/doc/cups.css
index 637f3d885..7588d1149 100644
--- a/doc/cups.css
+++ b/doc/cups.css
@@ -204,6 +204,12 @@ TH.label {
vertical-align: top;
}
+TH.sublabel {
+ padding-top: 0pt;
+ text-align: right;
+ font-weight: normal;
+}
+
HR {
border: solid thin;
}
diff --git a/doc/help/kerberos.html b/doc/help/kerberos.html
index 83c5fe8f0..d30758118 100644
--- a/doc/help/kerberos.html
+++ b/doc/help/kerberos.html
@@ -5,20 +5,43 @@
</HEAD>
<BODY>
-<P>CUPS 1.3 adds Kerberos support which allows you to use a Key Distribution
-Center (KDC) for authentication on your local CUPS server and when printing
-to a remote authenticated queue. This document describes how to configure
-CUPS to use Kerberos authentication and provides helpful links to the MIT
-help pages for configuring Kerberos on your systems and network.</P>
+<P>CUPS allows you to use a Key Distribution Center (KDC) for authentication
+on your local CUPS server and when printing to a remote authenticated queue.
+This document describes how to configure CUPS to use Kerberos authentication
+and provides links to the MIT help pages for configuring Kerberos on your
+systems and network.</P>
-<BLOCKQUOTE><B>Note:</B>
-<P>In order to use Kerberos-authenticated shared printers, you <EM>must</EM> be
-running a version of MIT Kerberos with the <TT>krb5_cc_new_unique()</TT>
-function or Heimdal Kerberos. Otherwise, only local Kerberos authentication
-is supported.</P>
+<H2 CLASS="title"><A NAME="REQUIREMENTS">System Requirements</A></H2>
-</BLOCKQUOTE>
+<p>The following are required to use Kerberos with CUPS:</p>
+
+<ol>
+
+ <li>Heimdal Kerberos (any version) or MIT Kerberos (1.6.3 or newer)</li>
+
+ <li>Properly configured Domain Name System (DNS)
+ infrastructure:<ol type='a'>
+ <li>DNS server(s) with static IP addresses for all CUPS clients
+ and servers or configured to allow DHCP updates to the host
+ addresses</li>
+ <li>All CUPS clients and servers configured to use the same
+ DNS server(s)</li>
+ </ol></li>
+
+ <li>Properly configured Kerberos infrastructure:<ol type='a'>
+ <li>KDC configured to allow CUPS clients and servers to obtain
+ Service Granting Tickets (SGTs) for the "ipp" service</li>
+ <li>LDAP-based user accounts - both OpenDirectory and
+ ActiveDirectory provide this with the KDC</li>
+ <li>CUPS clients and servers bound to the KDC and LDAP
+ server(s)</li>
+ </ol></li>
+
+ <li>An "ipp" Service Granting Ticket (SGT) for every CUPS client and
+ server</li>
+
+</ol>
<H2 CLASS="title"><A NAME="KRB5">Configuring Kerberos on Your System</A></H2>
@@ -68,80 +91,29 @@ Settings</VAR>:</P>
http://localhost:631/admin
</PRE>
-<P>After you have enabled Kerberos authentication, add <tt>AuthType Default</tt>
-lines to the policies you want to protect with authentication, for example:</P>
-
-<PRE CLASS="command">
-<EM>Listing 1: <A NAME="LISTING01">Remote Printer Operation Policy</A></EM>
-
- 1 &lt;Policy remote>
- 2 # Job-related operations must be done by the owner or an
- administrator...
- 3 &lt;Limit Send-Document Send-URI Hold-Job Release-Job
- Restart-Job Purge-Jobs Set-Job-Attributes
- Create-Job-Subscription Renew-Subscription
- Cancel-Subscription Get-Notifications Reprocess-Job
- Cancel-Current-Job Suspend-Current-Job Resume-Job
- CUPS-Move-Job>
- 4 AuthType Default
- 5 Require user @OWNER @SYSTEM
- 6 Order deny,allow
- 7 &lt;/Limit>
- 8
- 9 # Require authentication when creating jobs
-10 &lt;Limit Create-Job Print-Job Print-URI>
-11 AuthType Default
-12 Require valid-user
-13 Order deny,allow
-14 &lt;/Limit>
-15
-16 # All administration operations require an administrator
- to authenticate...
-17 &lt;Limit CUPS-Add-Printer CUPS-Delete-Printer
- CUPS-Add-Class CUPS-Delete-Class CUPS-Set-Default>
-18 AuthType Default
-19 Require user @SYSTEM
-20 Order deny,allow
-21 &lt;/Limit>
-22
-23 # All printer operations require a printer operator
- to authenticate...
-24 &lt;Limit Pause-Printer Resume-Printer
- Set-Printer-Attributes Enable-Printer Disable-Printer
- Pause-Printer-After-Current-Job Hold-New-Jobs
- Release-Held-New-Jobs Deactivate-Printer Activate-Printer
- Restart-Printer Shutdown-Printer Startup-Printer
- Promote-Job Schedule-Job-After CUPS-Accept-Jobs
- CUPS-Reject-Jobs>
-25 AuthType Default
-26 Require user <em>varies by OS</em>
-27 Order deny,allow
-28 &lt;/Limit>
-29
-30 # Only the owner or an administrator can cancel or
- authenticate a job...
-31 &lt;Limit Cancel-Job CUPS-Authenticate-Job>
-32 Require user @OWNER @SYSTEM
-33 Order deny,allow
-34 &lt;/Limit>
-35
-36 &lt;Limit All>
-37 Order deny,allow
-38 &lt;/Limit>
-39 &lt;/Policy>
-</PRE>
+<P>After you have enabled Kerberos authentication, use the built-in
+"authenticated" policy or your own custom policies with the printers you
+will be sharing. See <a href="policies.html">Managing Operation Policies</a>
+for more information.</P>
<H2 CLASS="title"><A NAME="IMPLEMENT">Implementation Information</A></H2>
-<P>CUPS implements Kerberos over HTTP using GSS API and the service name
-"ipp". Delegation of credentials, which is needed when printing to a
-remote/shared printer with Kerberos authentication, is currently only supported
-when using a single KDC on your network.</P>
-
-<P>After getting a user's Kerberos credentials, CUPS strips the "@KDC"
-portion of the username so that it can check the group membership locally,
-effectively treating the Kerberos account as a local user account.</P>
+<P>CUPS implements Kerberos over HTTP using GSSAPI and the service name
+"ipp". Because of limitations in the HTTP GSSAPI protocol extension, only
+a single domain/KDC is supported for authentication.</P>
+
+<P>When doing printing tasks that require authentication, CUPS requests a
+single-use "ticket" from your login session to authenticate who you are.
+This ticket gives CUPS a username of the form "user@REALM", which is then
+converted to just "user" for purposes of user and group checks.</P>
+
+<P>In order to support printing to a shared printer, CUPS has to ask the KDC
+for a copy of your credentials (this is called delegation) that can be sent to
+the remote server for authenticatation. Delegation only works when the system
+has a stable hostname which maps to the current address of the system, which
+is why you need a static IP address or DHCP that updates the DNS entry for your
+system.</P>
</BODY>
</HTML>
diff --git a/doc/help/options.html b/doc/help/options.html
index 8ad4ffada..c2d37220c 100644
--- a/doc/help/options.html
+++ b/doc/help/options.html
@@ -720,76 +720,6 @@ at half its natural size. If the specified scaling makes the
image larger than the page, multiple pages will be printed to
satisfy the request.
-<H3><A NAME="hue">Adjusting Image Hue (Tint)</A></H3>
-
-<P>The <CODE>-o hue=value</CODE> option will adjust the hue of the
-printed image, much like the tint control on your television:
-
-<PRE CLASS="command">
-lp -o hue=<EM>value</EM> filename
-lpr -o hue=<EM>value</EM> filename
-</PRE>
-
-<P>The <CODE>value</CODE> argument is a number from -360 to 360 and represents
-the color hue rotation. The following table summarizes the change you'll see
-with different colors:</P>
-
-<DIV CLASS="table"><TABLE SUMMARY="Hue Values">
-<TR>
- <TH>Original</TH>
- <TH>hue=-45</TH>
- <TH>hue=45</TH>
-</TR>
-<TR>
- <TD>Red</TD>
- <TD>Purple</TD>
- <TD>Yellow-orange</TD>
-</TR>
-<TR>
- <TD>Green</TD>
- <TD>Yellow-green</TD>
- <TD>Blue-green</TD>
-</TR>
-<TR>
- <TD>Yellow</TD>
- <TD>Orange</TD>
- <TD>Green-yellow</TD>
-</TR>
-<TR>
- <TD>Blue</TD>
- <TD>Sky-blue</TD>
- <TD>Purple</TD>
-</TR>
-<TR>
- <TD>Magenta</TD>
- <TD>Indigo</TD>
- <TD>Crimson</TD>
-</TR>
-<TR>
- <TD>Cyan</TD>
- <TD>Blue-green</TD>
- <TD>Light-navy-blue</TD>
-</TR>
-</TABLE></DIV>
-
-<P>The default hue adjustment is 0.
-
-<H3><A NAME="saturation">Adjusting Image Saturation (Color)</A></H3>
-
-<P>The <CODE>-o saturation=percent</CODE> option adjusts the saturation
-of the colors in an image, much like the color control on your television:</P>
-
-<PRE CLASS="command">
-lp -o saturation=<EM>percent</EM> filename
-lpr -o saturation=<EM>percent</EM> filename
-</PRE>
-
-<P>The <CODE>percent</CODE> argument specifies the color saturation
-from 0 to 200. A color saturation of 0 produces a black-and-white
-print, while a value of 200 will make the colors extremely intense.</P>
-
-<P>The default saturation is 100.</P>
-
<H2 CLASS="title"><A NAME="HPGL2OPTIONS">HP-GL/2 Options</A></H2>
diff --git a/doc/help/ref-cupsd-conf.html.in b/doc/help/ref-cupsd-conf.html.in
index 37ddc448a..9d5ca0e5b 100644
--- a/doc/help/ref-cupsd-conf.html.in
+++ b/doc/help/ref-cupsd-conf.html.in
@@ -474,6 +474,20 @@ domain name to use when listening for printer registrations. The
default is undefined.</P>
+<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.4</SPAN><A NAME="BrowseLDAPCACertFile">BrowseLDAPCACertFile</A></H2>
+
+<H3>Examples</H3>
+
+<PRE CLASS="command">
+BrowseLDAPCACertFile /etc/cups/ssl/certs
+</PRE>
+
+<H3>Description</H3>
+
+<P>The <CODE>BrowseLDAPCACertFile</CODE> directive specifies the SSL certificate
+authority file to use for LDAP + SSL. The default is undefined.</P>
+
+
<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2</SPAN><A NAME="BrowseLDAPDN">BrowseLDAPDN</A></H2>
<H3>Examples</H3>
diff --git a/doc/help/spec-ipp.html b/doc/help/spec-ipp.html
index a1c85a825..63a5fe5a6 100644
--- a/doc/help/spec-ipp.html
+++ b/doc/help/spec-ipp.html
@@ -2043,9 +2043,14 @@ string for the device.</p>
<p>The device-info attribute specifies a human-readable string describing
the device, e.g. "Parallel Port #1".
+<h4><a name="device-location">device-location (text(127))</a><span class="info">CUPS 1.4</span></h4>
+
+<p>The device-location attribute specifies the physical location of the
+printer.
+
<h4><a name="device-make-and-model">device-make-and-model (text(127))</a></h4>
-<p>The device-makr-and-model attribute specifies a device
+<p>The device-make-and-model attribute specifies a device
identification string provided by the printer connected to the device.
If the device or printer does not support identification then this
attribute contains the string "unknown".
@@ -2108,7 +2113,7 @@ of the device-class attribute:
rendered entirely in black ink (blackplot=true) or using the colors and shades
specified in the file (blackplot=false). The default value is false.
-<h4><a name="brightness">brightness (integer(0:200))</a></h4>
+<h4><a name="brightness">brightness (integer(0:200))</a><span class="info">Deprecated</span></h4>
<p>The brightness attribute specifies the overall brightness of the printed
output in percent. A brightness of 100 is normal, while 200 is twice as
@@ -2117,6 +2122,13 @@ bright and 50 is half as bright. The default value is 100.
<p>Brightness is applied to the Cyan, Magenta, Yellow, and Black values using
the function "f(x) = brightness / 100 * x".
+<blockquote><b>Note:</b>
+
+<p>This attribute is deprecated and will be removed from a future CUPS
+release.</p>
+
+</blockquote>
+
<h4><a name="columns">columns (integer(1:4))</a></h4>
<p>The columns attribute specifies the number of columns to generate when
@@ -2139,7 +2151,7 @@ are present in the job.
fit on the selected media (fitplot=true) or use the physical scale specified
in the plot file (fitplot=false). The default value is false.
-<h4><a name="gamma">gamma (integer(1:10000))</a></h4>
+<h4><a name="gamma">gamma (integer(1:10000))</a><span class="info">Deprecated</span></h4>
<p>The gamma attribute specifies the luminance correction for the output.
A value of 1000 specifies no correction, while values of 2000 and 500 will
@@ -2147,13 +2159,27 @@ generate lighter and darker output, respectively. The default value is
1000.
<p>Gamma is applied to the Red, Green, and Blue values (or luminance for
-grayscale output) using the function "f(x) = x<SUp>(1000/gamma)</SUp>".
+grayscale output) using the function "f(x) = x<sup>(1000/gamma)</sup>".
+
+<blockquote><b>Note:</b>
+
+<p>This attribute is deprecated and will be removed from a future CUPS
+release.</p>
-<h4><a name="hue">hue (integer(-180:180))</a></h4>
+</blockquote>
+
+<h4><a name="hue">hue (integer(-180:180))</a><span class="info">Deprecated</span></h4>
<p>The hue attribute specifies a color hue rotation when printing image
files. The default value is 0.
+<blockquote><b>Note:</b>
+
+<p>This attribute is deprecated and will be removed from a future CUPS
+release.</p>
+
+</blockquote>
+
<h4><a name="job-billing">job-billing (text(MAX))</a><span class='info'>CUPS 1.1</span></h4>
<p>The job-billing attribute provides a text value to associate with a job
@@ -2344,13 +2370,20 @@ per inch. The default value is the resolution included with the file or
with a shaded header and keyword highlighting (prettyprint=true) or without
additional formatting (prettyprint=false). The default value is false.
-<h4><a name="saturation">saturation (integer(0:200))</a></h4>
+<h4><a name="saturation">saturation (integer(0:200))</a><span class="info">Deprecated</span></h4>
<p>The saturation attribute specifies the color saturation when
printing image files. A saturation of 100 is normal, while values of 50
and 200 will be half and twice as colorful, respectively. The default
value is 100.
+<blockquote><b>Note:</b>
+
+<p>This attribute is deprecated and will be removed from a future CUPS
+release.</p>
+
+</blockquote>
+
<h4><a name="scaling">scaling (integer(1:1000))</a></h4>
<p>The scaling attribute specifies the scaling of image files with
diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html
index 5a9865090..33254bd14 100644
--- a/doc/help/spec-ppd.html
+++ b/doc/help/spec-ppd.html
@@ -1022,6 +1022,96 @@ PRE B {
</table></div>
+<h2 class='title'><a name='MEDIA'>Media Attributes</a></h2>
+
+<p>The CUPS media attributes allow drivers to specify alternate custom page
+size limits based on up to two options.</p>
+
+<h3><span class='info'>CUPS 1.4</span><a name='cupsMediaQualifier2'>cupsMediaQualifier2</a></h3>
+
+<p class='summary'>*cupsMediaQualifier2: MainKeyword</p>
+
+<p>This attribute specifies the second option to use for overriding the
+custom page size limits.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify alternate custom page size limits based on InputSlot and Quality</em>
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+</pre>
+
+<h3><span class='info'>CUPS 1.4</span><a name='cupsMediaQualifier3'>cupsMediaQualifier3</a></h3>
+
+<p class='summary'>*cupsMediaQualifier3: MainKeyword</p>
+
+<p>This attribute specifies the third option to use for overriding the
+custom page size limits.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify alternate custom page size limits based on InputSlot and Quality</em>
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+</pre>
+
+<h3><span class='info'>CUPS 1.4</span><a name='cupsMinSize'>cupsMinSize</a></h3>
+
+<p class='summary'>*cupsMinSize .Qualifier2.Qualifier3: "width length"<br>
+*cupsMinSize .Qualifier2.: "width length"<br>
+*cupsMinSize ..Qualifier3: "width length"</p>
+
+<p>This attribute specifies alternate minimum custom page sizes in points.
+The <a href='#cupsMediaQualifier2'><tt>cupsMediaQualifier2</tt></a> and
+<a href='#cupsMediaQualifier3'><tt>cupsMediaQualifier3</tt></a> attributes
+are used to identify options to use for matching.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify alternate custom page size limits based on InputSlot and Quality</em>
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+</pre>
+
+<h3><span class='info'>CUPS 1.4</span><a name='cupsMaxSize'>cupsMaxSize</a></h3>
+
+<p class='summary'>*cupsMaxSize .Qualifier2.Qualifier3: "width length"<br>
+*cupsMaxSize .Qualifier2.: "width length"<br>
+*cupsMaxSize ..Qualifier3: "width length"</p>
+
+<p>This attribute specifies alternate maximum custom page sizes in points.
+The <a href='#cupsMediaQualifier2'><tt>cupsMediaQualifier2</tt></a> and
+<a href='#cupsMediaQualifier3'><tt>cupsMediaQualifier3</tt></a> attributes
+are used to identify options to use for matching.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify alternate custom page size limits based on InputSlot and Quality</em>
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+</pre>
+
+
<h2 class='title'><a name='ATTRIBUTES'>General Attributes</a></h2>
<h3><span class='info'>CUPS 1.3</span><a name='cupsBackSide'>cupsBackSide</a></h3>
@@ -1711,17 +1801,28 @@ the device.</p>
<ul>
- <li>Added <tt>cupsCommands</tt> attribute.</li>
+ <li>Added <a href='#cupsCommands'><tt>cupsCommands</tt></a>
+ attribute.</li>
- <li>Added <tt>cupsMarkerName</tt> attribute.</li>
+ <li>Added <a href='#cupsMarkerName'><tt>cupsMarkerName</tt></a>
+ attribute.</li>
- <li>Added <tt>cupsMarkerNotice</tt> attribute.</li>
+ <li>Added <a href='#cupsMarkerNotice'><tt>cupsMarkerNotice</tt></a>
+ attribute.</li>
- <li>Added <tt>cupsPJLDisplay</tt> attribute.</li>
+ <li>Added <a href='#cupsPJLDisplay'><tt>cupsPJLDisplay</tt></a>
+ attribute.</li>
- <li>Added <tt>cupsUIResolver</tt> and <tt>cupsUIConstraints</tt>
+ <li>Added <a href='#cupsUIResolver'><tt>cupsUIResolver</tt></a> and
+ <a href='#cupsUIConstraints'><tt>cupsUIConstraints</tt></a>
attributes.</li>
+ <li>Added
+ <a href='#cupsMediaQualifier2'><tt>cupsMediaQualifier2</tt></a>,
+ <a href='#cupsMediaQualifier3'><tt>cupsMediaQualifier3</tt></a>,
+ <a href='#cupsMinSize'><tt>cupsMinSize</tt></a>, and
+ <a href='#cupsMaxSize'><tt>cupsMaxSize</tt></a> attributes.</li>
+
</ul>
@@ -1744,13 +1845,18 @@ the device.</p>
<ul>
- <li>Added <tt>cupsBackSide</tt> and deprecated <tt>cupsFlipDuplex</tt>.</li>
+ <li>Added <a href='#cupsBackSide'><tt>cupsBackSide</tt></a> and
+ deprecated <a href='#cupsFlipDuplex'><tt>cupsFlipDuplex</tt></a>.</li>
- <li>Added text URI information to <tt>cupsIPPReason</tt> documentation.</li>
+ <li>Added text URI information to
+ <a href='#cupsIPPReason'><tt>cupsIPPReason</tt></a> documentation.</li>
- <li>Added <tt>APPrinterPreset</tt>, <tt>cupsIPPFinishings</tt>, and <tt>cupsPreFilter</tt> attributes.</li>
+ <li>Added <a href='#APPrinterPreset'><tt>APPrinterPreset</tt></a>,
+ <a href='#cupsIPPFinishings'><tt>cupsIPPFinishings</tt></a>, and
+ <a href='#cupsPreFilter'><tt>cupsPreFilter</tt></a> attributes.</li>
- <li>Added discussion of custom option code, sample <tt>CustomPageSize</tt> code, and "do not use dict and put" note.</li>
+ <li>Added discussion of custom option code, sample
+ <tt>CustomPageSize</tt> code, and "do not use dict and put" note.</li>
</ul>
@@ -1771,17 +1877,18 @@ the device.</p>
<li>Added custom option values support</li>
- <li>Added <tt>APHelpBook</tt> attribute</li>
+ <li>Added <a href='#APHelpBook'><tt>APHelpBook</tt></a> attribute</li>
- <li>Added <tt>APDuplexRequiresFlippedMargin</tt> attribute</li>
+ <li>Added <a href='#APDuplexRequiresFlippedMargin'><tt>APDuplexRequiresFlippedMargin</tt></a>
+ attribute</li>
- <li>Added <tt>cupsICCProfile</tt> attribute</li>
+ <li>Added <a href='#cupsICCProfile'><tt>cupsICCProfile</tt></a> attribute</li>
- <li>Added <tt>cupsIPPReason</tt> attribute</li>
+ <li>Added <a href='#cupsIPPReason'><tt>cupsIPPReason</tt></a> attribute</li>
- <li>Added <tt>cupsLanguages</tt> attribute</li>
+ <li>Added <a href='#cupsLanguages'><tt>cupsLanguages</tt></a> attribute</li>
- <li>Added <tt>cupsPortMonitor</tt> attribute</li>
+ <li>Added <a href='#cupsPortMonitor'><tt>cupsPortMonitor</tt></a> attribute</li>
<li>Removed <tt>cupsProtocol</tt> attribute</li>
@@ -1791,7 +1898,7 @@ the device.</p>
<ul>
- <li>Added <tt>cupsFlipDuplex</tt> attribute</li>
+ <li>Added <a href='#cupsFlipDuplex'><tt>cupsFlipDuplex</tt></a> attribute</li>
<li>Added <tt>cupsProtocol</tt> attribute</li>
diff --git a/init/cups.xml.in b/init/cups.xml.in
new file mode 100644
index 000000000..e47398ae4
--- /dev/null
+++ b/init/cups.xml.in
@@ -0,0 +1,212 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Service manifest for CUPS.
+
+ This service manifest introduces smf(5) services for CUPS. The services
+ described in this file are as follows:
+
+ svc:/application/cups/scheduler:default
+ svc:/application/cups/in-lpd:default
+
+ NOTE: This service manifest is not editable; its contents will be
+ overwritten by package or patch operations, including operating system
+ upgrade. Make customizations in a different file.
+
+ Norm.Jacobs@Sun.COM
+
+ $Id$
+-->
+
+<service_bundle type='manifest' name='SUNWcups:services'>
+
+<service
+ name='application/cups/scheduler'
+ type='service'
+ version='1'>
+
+ <dependency
+ name='filesystem_minimal'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/filesystem/minimal' />
+ </dependency>
+
+ <dependency
+ name='loopback'
+ grouping='optional_all'
+ restart_on='error'
+ type='service'>
+ <service_fmri value='svc:/network/loopback' />
+ </dependency>
+
+
+ <dependency
+ name='network'
+ grouping='optional_all'
+ restart_on='error'
+ type='service'>
+ <service_fmri value='svc:/milestone/network' />
+ </dependency>
+
+ <dependency
+ name='lpsched'
+ grouping='exclude_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/application/print/server' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':kill'
+ timeout_seconds='60' />
+
+ <instance name='default' enabled='false' >
+
+ <dependency
+ name='config_data'
+ grouping='require_all'
+ restart_on='none'
+ type='path'>
+ <service_fmri value='file://localhost@sysconfdir@/cups/cupsd.conf' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='@sbindir@/cupsd'
+ timeout_seconds='60' >
+ <method_context>
+ <method_credential user='root' group='@CUPS_GROUP@' />
+ </method_context>
+ </exec_method>
+
+ <property_group name='general' type='framework'>
+ <propval name='action_authorization' type='astring'
+ value='solaris.smf.manage.cups' />
+ <propval name='value_authorization' type='astring'
+ value='solaris.smf.value.cups' />
+ </property_group>
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ CUPS Print Spooler
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='cupsd' section='8'
+ manpath='@mandir@' />
+ </documentation>
+ </template>
+
+ </instance>
+
+ <stability value='Stable' />
+
+</service>
+
+<service
+ name='application/cups/in-lpd'
+ type='service'
+ version='1'>
+
+ <dependency
+ name='filesystem_minimal'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/filesystem/minimal' />
+ </dependency>
+
+ <dependency
+ name='loopback'
+ grouping='require_any'
+ restart_on='error'
+ type='service'>
+ <service_fmri value='svc:/network/loopback' />
+ </dependency>
+
+ <dependency
+ name='network'
+ grouping='optional_all'
+ restart_on='error'
+ type='service'>
+ <service_fmri value='svc:/milestone/network' />
+ </dependency>
+
+ <dependency
+ name='in-lpd'
+ grouping='exclude_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/application/print/rfc1179' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':kill'
+ timeout_seconds='60' />
+
+ <instance name='default' enabled='false' >
+ <restarter>
+ <service_fmri value='svc:/network/inetd:default' />
+ </restarter>
+
+ <dependency
+ name='cupsd'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/application/cups/scheduler' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='inetd_start'
+ exec='@CUPS_SERVERBIN@/daemon/cups-lpd -o document-format=application/octet-stream'
+ timeout_seconds='0'>
+ <method_context>
+ <method_credential user='@CUPS_USER@' group='@CUPS_GROUP@' />
+ </method_context>
+ </exec_method>
+
+ <property_group name='inetd' type='framework'>
+ <stability value='Evolving' />
+ <propval name='endpoint_type' type='astring' value='stream' />
+ <propval name='name' type='astring' value='printer' />
+ <propval name='wait' type='boolean' value='false' />
+ <propval name='isrpc' type='boolean' value='false' />
+ <propval name='proto' type='astring' value='tcp6' />
+ </property_group>
+
+ <property_group name='general' type='framework'>
+ <propval name='action_authorization' type='astring'
+ value='solaris.smf.manage.cups' />
+ <propval name='value_authorization' type='astring'
+ value='solaris.smf.value.cups' />
+ </property_group>
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ CUPS Line Printer Daemon mini-server
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='cups-lpd' section='8'
+ manpath='@mandir@' />
+ </documentation>
+ </template>
+
+ </instance>
+
+ <stability value='Stable' />
+
+</service>
+
+</service_bundle>
diff --git a/man/backend.man b/man/backend.man
index b8a52d9ba..b4ba42516 100644
--- a/man/backend.man
+++ b/man/backend.man
@@ -3,7 +3,7 @@
.\"
.\" Backend man page for the Common UNIX Printing System (CUPS).
.\"
-.\" Copyright 2007 by Apple Inc.
+.\" Copyright 2007-2008 by Apple Inc.
.\" Copyright 1997-2006 by Easy Software Products.
.\"
.\" These coded instructions, statements, and computer programs are the
@@ -12,7 +12,7 @@
.\" which should have been included with this file. If this file is
.\" file is missing or damaged, see the license at "http://www.cups.org/".
.\"
-.TH backend 7 "Common UNIX Printing System" "20 March 2006" "Apple Inc."
+.TH backend 7 "Common UNIX Printing System" "28 July 2008" "Apple Inc."
.SH NAME
backend \- cups backend transmission interfaces
@@ -59,6 +59,7 @@ forms:
device-class scheme "Unknown" "device-info"
device-class device-uri "device-make-and-model" "device-info"
device-class device-uri "device-make-and-model" "device-info" "device-id"
+ device-class device-uri "device-make-and-model" "device-info" "device-id" "device-location"
.fi
.LP
@@ -111,6 +112,11 @@ The optional \fIdevice-id\fR field specifies the IEEE-1284 device
ID string for the device, which is used to select a matching
driver.
+.LP
+The optional \fIdevice-location\fR field specifies the physical location of
+the device, which is often used to pre-populate the printer-location attribute
+when adding a printer.
+
.SH PERMISSIONS
Backends without world execute permissions are run as the root
user. Otherwise, the backend is run using the unprivileged user
@@ -173,7 +179,7 @@ All other exit code values are reserved.
http://localhost:631/help
.SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
.\"
.\" End of "$Id: backend.man 7600 2008-05-20 21:06:23Z mike $".
.\"
diff --git a/man/cupsd.conf.man.in b/man/cupsd.conf.man.in
index 6fbdd31bb..4421c1df4 100644
--- a/man/cupsd.conf.man.in
+++ b/man/cupsd.conf.man.in
@@ -146,6 +146,26 @@ BrowseInterval seconds
.br
Specifies the maximum interval between printer information broadcasts.
.TP 5
+BrowseLDAPBindDN
+.br
+Specifies the LDAP domain name to use when registering printers.
+.TP 5
+BrowseLDAPCACertFile
+.br
+Specifies the SSL certificate authority file to use.
+.TP 5
+BrowseLDAPDN
+.br
+Specifies the LDAP domain name to use when discovering printers.
+.TP 5
+BrowseLDAPPassword
+.br
+Specifies the password to use when accessing the LDAP server.
+.TP 5
+BrowseLDAPServer
+.br
+Specifies the LDAP server to use.
+.TP 5
BrowseOrder allow,deny
.TP 5
BrowseOrder deny,allow
diff --git a/notifier/Makefile b/notifier/Makefile
index 4f05e374f..90b51b4d7 100644
--- a/notifier/Makefile
+++ b/notifier/Makefile
@@ -58,9 +58,7 @@ install-data:
-chgrp $(CUPS_GROUP) $(CACHEDIR)/rss
if test "x$(SYMROOT)" != "x"; then \
$(INSTALL_DIR) $(SYMROOT); \
- for file in $(TARGETS); do \
- cp $$file $(SYMROOT); \
- done \
+ cp mailto rss $(SYMROOT); \
fi
@@ -70,9 +68,8 @@ install-data:
install-exec:
$(INSTALL_DIR) -m 755 $(SERVERBIN)/notifier
- for file in $(TARGETS); do \
- $(INSTALL_BIN) $$file $(SERVERBIN)/notifier; \
- done
+ $(INSTALL_BIN) mailto $(SERVERBIN)/notifier
+ $(INSTALL_BIN) rss $(SERVERBIN)/notifier
#
diff --git a/scheduler/Makefile b/scheduler/Makefile
index c199e697c..e580c2ddc 100644
--- a/scheduler/Makefile
+++ b/scheduler/Makefile
@@ -333,14 +333,15 @@ cupsd: $(CUPSDOBJS) $(LIBCUPSMIME) ../cups/$(LIBCUPS)
$(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) -L. -lcupsmime \
$(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \
$(LIBPAPER) $(LIBMALLOC) $(CUPSDLIBS) $(DNSSDLIBS) $(LIBS) \
- $(LIBGSSAPI)
+ $(LIBGSSAPI) $(LIBWRAP)
cupsd-static: $(CUPSDOBJS) libcupsmime.a ../cups/libcups.a
echo Linking $@...
$(CC) $(LDFLAGS) -o cupsd-static $(CUPSDOBJS) libcupsmime.a \
$(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \
../cups/libcups.a $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \
- $(LIBMALLOC) $(CUPSDLIBS) $(DNSSDLIBS) $(LIBGSSAPI)
+ $(LIBMALLOC) $(CUPSDLIBS) $(DNSSDLIBS) $(LIBGSSAPI) \
+ $(LIBWRAP)
#
diff --git a/scheduler/client.c b/scheduler/client.c
index 25be7a491..ac52bd99e 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -76,6 +76,10 @@ extern const char *cssmErrorString(int error);
# include <gnutls/x509.h>
#endif /* HAVE_GNUTLS */
+#ifdef HAVE_TCPD_H
+# include <tcpd.h>
+#endif /* HAVE_TCPD_H */
+
/*
* Local functions...
@@ -125,6 +129,9 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
char *hostname; /* Hostname for address */
http_addr_t temp; /* Temporary address variable */
static time_t last_dos = 0; /* Time of last DoS attack */
+#ifdef HAVE_TCPD_H
+ struct request_info wrap_req; /* TCP wrappers request information */
+#endif /* HAVE_TCPD_H */
cupsdLogMessage(CUPSD_LOG_DEBUG2,
@@ -240,7 +247,9 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
cupsdLogMessage(CUPSD_LOG_WARN,
"Possible DoS attack - more than %d clients connecting "
"from %s!",
- MaxClientsPerHost, con->http.hostname);
+ MaxClientsPerHost,
+ httpAddrString(con->http.hostaddr, con->http.hostname,
+ sizeof(con->http.hostname)));
}
#ifdef WIN32
@@ -322,7 +331,8 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
* Do double lookups as needed...
*/
- if ((addrlist = httpAddrGetList(con->http.hostname, AF_UNSPEC, NULL)) != NULL)
+ if ((addrlist = httpAddrGetList(con->http.hostname, AF_UNSPEC, NULL))
+ != NULL)
{
/*
* See if the hostname maps to the same IP address...
@@ -362,6 +372,34 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
}
}
+#ifdef HAVE_TCPD_H
+ /*
+ * See if the connection is denied by TCP wrappers...
+ */
+
+ request_init(&wrap_req, RQ_DAEMON, "cupsd", RQ_FILE, con->http.fd, NULL);
+ fromhost(&wrap_req);
+
+ if (!hosts_access(&wrap_req))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAcceptClient: Closing connection %d...",
+ con->http.fd);
+
+#ifdef WIN32
+ closesocket(con->http.fd);
+#else
+ close(con->http.fd);
+#endif /* WIN32 */
+
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "Connection from %s refused by /etc/hosts.allow and "
+ "/etc/hosts.deny rules.", con->http.hostname);
+ free(con);
+ return;
+ }
+#endif /* HAVE_TCPD_H */
+
#ifdef AF_INET6
if (con->http.hostaddr->addr.sa_family == AF_INET6)
cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s:%d (IPv6)",
diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c
index 3fb619e1e..8b634a27c 100644
--- a/scheduler/cups-deviced.c
+++ b/scheduler/cups-deviced.c
@@ -65,10 +65,8 @@ typedef struct
typedef struct
{
char device_class[128], /* Device class */
- device_make_and_model[128], /* Make and model, if known */
device_info[128], /* Device info/description */
- device_uri[1024], /* Device URI */
- device_id[1024]; /* 1284 Device ID */
+ device_uri[1024]; /* Device URI */
} cupsd_device_t;
@@ -92,7 +90,8 @@ static int send_class, /* Send device-class attribute? */
send_make_and_model,
/* Send device-make-and-model attribute? */
send_uri, /* Send device-uri attribute? */
- send_id; /* Send device-id attribute? */
+ send_id, /* Send device-id attribute? */
+ send_location; /* Send device-location attribute? */
static int dead_children = 0;
/* Dead children? */
@@ -105,7 +104,8 @@ static int add_device(const char *device_class,
const char *device_make_and_model,
const char *device_info,
const char *device_uri,
- const char *device_id);
+ const char *device_id,
+ const char *device_location);
static int compare_devices(cupsd_device_t *p0,
cupsd_device_t *p1);
static cups_array_t *create_strings_array(const char *s);
@@ -198,7 +198,10 @@ main(int argc, /* I - Number of command-line args */
num_options, options));
if (!requested || cupsArrayFind(requested, "all") != NULL)
- send_class = send_info = send_make_and_model = send_uri = send_id = 1;
+ {
+ send_class = send_info = send_make_and_model = send_uri = send_id =
+ send_location = 1;
+ }
else
{
send_class = cupsArrayFind(requested, "device-class") != NULL;
@@ -206,6 +209,7 @@ main(int argc, /* I - Number of command-line args */
send_make_and_model = cupsArrayFind(requested, "device-make-and-model") != NULL;
send_uri = cupsArrayFind(requested, "device-uri") != NULL;
send_id = cupsArrayFind(requested, "device-id") != NULL;
+ send_location = cupsArrayFind(requested, "device-location") != NULL;
}
/*
@@ -345,7 +349,8 @@ add_device(
const char *device_make_and_model, /* I - Device make and model */
const char *device_info, /* I - Device information */
const char *device_uri, /* I - Device URI */
- const char *device_id) /* I - 1284 device ID */
+ const char *device_id, /* I - 1284 device ID */
+ const char *device_location) /* I - Physical location */
{
cupsd_device_t *device; /* New device */
@@ -366,11 +371,8 @@ add_device(
*/
strlcpy(device->device_class, device_class, sizeof(device->device_class));
- strlcpy(device->device_make_and_model, device_make_and_model,
- sizeof(device->device_make_and_model));
strlcpy(device->device_info, device_info, sizeof(device->device_info));
strlcpy(device->device_uri, device_uri, sizeof(device->device_uri));
- strlcpy(device->device_id, device_id, sizeof(device->device_id));
/*
* Add the device to the array and return...
@@ -397,16 +399,20 @@ add_device(
cupsdSendIPPGroup(IPP_TAG_PRINTER);
if (send_class)
cupsdSendIPPString(IPP_TAG_KEYWORD, "device-class",
- device->device_class);
+ device_class);
if (send_info)
- cupsdSendIPPString(IPP_TAG_TEXT, "device-info", device->device_info);
+ cupsdSendIPPString(IPP_TAG_TEXT, "device-info", device_info);
if (send_make_and_model)
cupsdSendIPPString(IPP_TAG_TEXT, "device-make-and-model",
- device->device_make_and_model);
+ device_make_and_model);
if (send_uri)
- cupsdSendIPPString(IPP_TAG_URI, "device-uri", device->device_uri);
+ cupsdSendIPPString(IPP_TAG_URI, "device-uri", device_uri);
if (send_id)
- cupsdSendIPPString(IPP_TAG_TEXT, "device-id", device->device_id);
+ cupsdSendIPPString(IPP_TAG_TEXT, "device-id",
+ device_id ? device_id : "");
+ if (send_location)
+ cupsdSendIPPString(IPP_TAG_TEXT, "device-location",
+ device_location ? device_location : "");
fflush(stdout);
fputs("DEBUG: Flushed attributes...\n", stderr);
@@ -508,11 +514,14 @@ static int /* O - 0 on success, -1 on error */
get_device(cupsd_backend_t *backend) /* I - Backend to read from */
{
char line[2048], /* Line from backend */
- dclass[64], /* Device class */
- uri[1024], /* Device URI */
- info[128], /* Device info */
- make_model[256], /* Make and model */
- device_id[1024]; /* 1284 device ID */
+ temp[2048], /* Copy of line */
+ *ptr, /* Pointer into line */
+ *dclass, /* Device class */
+ *uri, /* Device URI */
+ *make_model, /* Make and model */
+ *info, /* Device info */
+ *device_id, /* 1284 device ID */
+ *location; /* Physical location */
if (cupsFileGets(backend->pipe, line, sizeof(line)))
@@ -520,35 +529,123 @@ get_device(cupsd_backend_t *backend) /* I - Backend to read from */
/*
* Each line is of the form:
*
- * class URI "make model" "name" ["1284 device ID"]
+ * class URI "make model" "name" ["1284 device ID"] ["location"]
+ */
+
+ strlcpy(temp, line, sizeof(temp));
+
+ /*
+ * device-class
+ */
+
+ dclass = temp;
+
+ for (ptr = temp; *ptr; ptr ++)
+ if (isspace(*ptr & 255))
+ break;
+
+ while (isspace(*ptr & 255))
+ *ptr++ = '\0';
+
+ /*
+ * device-uri
+ */
+
+ if (!*ptr)
+ goto error;
+
+ for (uri = ptr; *ptr; ptr ++)
+ if (isspace(*ptr & 255))
+ break;
+
+ while (isspace(*ptr & 255))
+ *ptr++ = '\0';
+
+ /*
+ * device-make-and-model
*/
- device_id[0] = '\0';
+ if (*ptr != '\"')
+ goto error;
- if (sscanf(line,
- "%63s%1023s%*[ \t]\"%255[^\"]\"%*[ \t]\"%127[^\"]\""
- "%*[ \t]\"%1023[^\"]",
- dclass, uri, make_model, info, device_id) < 4)
+ for (ptr ++, make_model = ptr; *ptr && *ptr != '\"'; ptr ++)
{
- /*
- * Bad format; strip trailing newline and write an error message.
- */
+ if (*ptr == '\\' && ptr[1])
+ _cups_strcpy(ptr, ptr + 1);
+ }
+
+ if (*ptr != '\"')
+ goto error;
+
+ for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
+
+ /*
+ * device-info
+ */
- if (line[strlen(line) - 1] == '\n')
- line[strlen(line) - 1] = '\0';
+ if (*ptr != '\"')
+ goto error;
- fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n",
- backend->name, line);
+ for (ptr ++, info = ptr; *ptr && *ptr != '\"'; ptr ++)
+ {
+ if (*ptr == '\\' && ptr[1])
+ _cups_strcpy(ptr, ptr + 1);
}
- else
+
+ if (*ptr != '\"')
+ goto error;
+
+ for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
+
+ /*
+ * device-id
+ */
+
+ if (*ptr == '\"')
{
+ for (ptr ++, device_id = ptr; *ptr && *ptr != '\"'; ptr ++)
+ {
+ if (*ptr == '\\' && ptr[1])
+ _cups_strcpy(ptr, ptr + 1);
+ }
+
+ if (*ptr != '\"')
+ goto error;
+
+ for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
+
/*
- * Add the device to the array of available devices...
+ * device-location
*/
- if (!add_device(dclass, make_model, info, uri, device_id))
- fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri);
+ if (*ptr == '\"')
+ {
+ for (ptr ++, location = ptr; *ptr && *ptr != '\"'; ptr ++)
+ {
+ if (*ptr == '\\' && ptr[1])
+ _cups_strcpy(ptr, ptr + 1);
+ }
+
+ if (*ptr != '\"')
+ goto error;
+
+ *ptr = '\0';
+ }
+ else
+ location = NULL;
}
+ else
+ {
+ device_id = NULL;
+ location = NULL;
+ }
+
+ /*
+ * Add the device to the array of available devices...
+ */
+
+ if (!add_device(dclass, make_model, info, uri, device_id, location))
+ fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri);
return (0);
}
@@ -561,6 +658,19 @@ get_device(cupsd_backend_t *backend) /* I - Backend to read from */
backend->pipe = NULL;
return (-1);
+
+ /*
+ * Bad format; strip trailing newline and write an error message.
+ */
+
+ error:
+
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+
+ fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n",
+ backend->name, line);
+ return (0);
}
diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx
index bed393eae..7742abc93 100644
--- a/scheduler/cups-driverd.cxx
+++ b/scheduler/cups-driverd.cxx
@@ -76,7 +76,7 @@ static const char * const ppd_types[] = /* ppd-type values */
typedef struct /**** PPD record ****/
{
time_t mtime; /* Modification time */
- size_t size; /* Size in bytes */
+ off_t size; /* Size in bytes */
int model_number; /* cupsModelNumber */
int type; /* ppd-type */
char filename[512], /* Filename */
diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
index b2960d65d..27efd0d00 100644
--- a/scheduler/dirsvc.c
+++ b/scheduler/dirsvc.c
@@ -14,55 +14,6 @@
*
* Contents:
*
- * cupsdDeregisterPrinter() - Stop sending broadcast information for a local
- * printer and remove any pending references to
- * remote printers.
- * cupsdLoadRemoteCache() - Load the remote printer cache.
- * cupsdRegisterPrinter() - Start sending broadcast information for a
- * printer or update the broadcast contents.
- * cupsdRestartPolling() - Restart polling servers as needed.
- * cupsdSaveRemoteCache() - Save the remote printer cache.
- * cupsdSendBrowseList() - Send new browsing information as necessary.
- * cupsdStartBrowsing() - Start sending and receiving broadcast
- * information.
- * cupsdStartPolling() - Start polling servers as needed.
- * cupsdStopBrowsing() - Stop sending and receiving broadcast
- * information.
- * cupsdStopPolling() - Stop polling servers as needed.
- * cupsdUpdateDNSSDName() - Update the computer name we use for
- * browsing...
- * cupsdUpdateLDAPBrowse() - Scan for new printers via LDAP...
- * cupsdUpdateSLPBrowse() - Get browsing information via SLP.
- * dequote() - Remote quotes from a string.
- * dnssdBuildTxtRecord() - Build a TXT record from printer info.
- * dnssdComparePrinters() - Compare the registered names of two printers.
- * dnssdDeregisterPrinter() - Stop sending broadcast information for a
- * printer.
- * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT
- * record format.
- * dnssdRegisterCallback() - DNSServiceRegister callback.
- * dnssdRegisterPrinter() - Start sending broadcast information for a
- * printer or update the broadcast contents.
- * dnssdUpdate() - Handle DNS-SD queries.
- * get_hostconfig() - Get an /etc/hostconfig service setting.
- * is_local_queue() - Determine whether the URI points at a local
- * queue.
- * process_browse_data() - Process new browse data.
- * process_implicit_classes() - Create/update implicit classes as needed.
- * send_cups_browse() - Send new browsing information using the CUPS
- * protocol.
- * send_ldap_browse() - Send LDAP printer registrations.
- * send_slp_browse() - Register the specified printer with SLP.
- * slp_attr_callback() - SLP attribute callback
- * slp_dereg_printer() - SLPDereg() the specified printer
- * slp_get_attr() - Get an attribute from an SLP registration.
- * slp_reg_callback() - Empty SLPRegReport.
- * slp_url_callback() - SLP service url callback
- * update_cups_browse() - Update the browse lists using the CUPS
- * protocol.
- * update_lpd() - Update the LPD configuration as needed.
- * update_polling() - Read status messages from the poll daemons.
- * update_smb() - Update the SMB configuration as needed.
*/
/*
@@ -104,7 +55,36 @@ static void process_browse_data(const char *uri, const char *host,
static void process_implicit_classes(void);
static void send_cups_browse(cupsd_printer_t *p);
#ifdef HAVE_LDAP
+static LDAP *ldap_connect(void);
+static void ldap_reconnect(void);
+static void ldap_disconnect(LDAP *ld);
+static int ldap_search_rec(LDAP *ld, char *base, int scope,
+ char *filter, char *attrs[],
+ int attrsonly, LDAPMessage **res);
+static int ldap_getval_firststring(LDAP *ld, LDAPMessage *entry,
+ char *attr, char *retval,
+ unsigned long maxsize);
+static void ldap_freeres(LDAPMessage *entry);
+static void send_ldap_ou(char *ou, char *basedn, char *descstring);
static void send_ldap_browse(cupsd_printer_t *p);
+static void ldap_dereg_printer(cupsd_printer_t *p);
+static void ldap_dereg_ou(char *ou, char *basedn);
+# ifdef HAVE_LDAP_REBIND_PROC
+# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+static int ldap_rebind_proc(LDAP *RebindLDAPHandle,
+ LDAP_CONST char *refsp,
+ ber_tag_t request,
+ ber_int_t msgid,
+ void *params);
+# else
+static int ldap_rebind_proc(LDAP *RebindLDAPHandle,
+ char **dnp,
+ char **passwdp,
+ int *authmethodp,
+ int freeit,
+ void *arg);
+# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+# endif /* HAVE_LDAP_REBIND_PROC */
#endif /* HAVE_LDAP */
#ifdef HAVE_LIBSLP
static void send_slp_browse(cupsd_printer_t *p);
@@ -131,7 +111,7 @@ static void dnssdRegisterPrinter(cupsd_printer_t *p);
static void dnssdUpdate(void);
#endif /* HAVE_DNSSD */
-#ifdef HAVE_OPENLDAP
+#ifdef HAVE_LDAP
static const char * const ldap_attrs[] =/* CUPS LDAP attributes */
{
"printerDescription",
@@ -141,7 +121,7 @@ static const char * const ldap_attrs[] =/* CUPS LDAP attributes */
"printerURI",
NULL
};
-#endif /* HAVE_OPENLDAP */
+#endif /* HAVE_LDAP */
#ifdef HAVE_LIBSLP
/*
@@ -224,6 +204,11 @@ cupsdDeregisterPrinter(
slp_dereg_printer(p);
#endif /* HAVE_LIBSLP */
+#ifdef HAVE_LDAP
+ if (BrowseLocalProtocols & BROWSE_LDAP)
+ ldap_dereg_printer(p);
+#endif /* HAVE_LDAP */
+
#ifdef HAVE_DNSSD
if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
dnssdDeregisterPrinter(p);
@@ -928,6 +913,425 @@ cupsdSendBrowseList(void)
}
+#ifdef HAVE_LDAP_REBIND_PROC
+# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+/*
+ * 'ldap_rebind_proc()' - Callback function for LDAP rebind
+ */
+
+static int
+ldap_rebind_proc (LDAP *RebindLDAPHandle,
+ LDAP_CONST char *refsp,
+ ber_tag_t request,
+ ber_int_t msgid,
+ void *params)
+{
+ int rc;
+
+ /*
+ * Bind to new LDAP server...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "ldap_rebind_proc: Rebind to %s", refsp);
+
+# if LDAP_API_VERSION > 3000
+ struct berval bval;
+ bval.bv_val = BrowseLDAPPassword;
+ bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
+
+ rc = ldap_sasl_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE, &bval, NULL, NULL, NULL);
+# else
+ rc = ldap_bind_s(RebindLDAPHandle, BrowseLDAPBindDN,
+ BrowseLDAPPassword, LDAP_AUTH_SIMPLE);
+# endif /* LDAP_API_VERSION > 3000 */
+
+ return (rc);
+}
+
+# else /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+
+/*
+ * 'ldap_rebind_proc()' - Callback function for LDAP rebind
+ */
+
+static int
+ldap_rebind_proc (LDAP *RebindLDAPHandle,
+ char **dnp,
+ char **passwdp,
+ int *authmethodp,
+ int freeit,
+ void *arg)
+{
+ switch ( freeit ) {
+
+ case 1:
+
+ /*
+ * Free current values...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "ldap_rebind_proc: Free values...");
+
+ if ( dnp && *dnp ) {
+ free( *dnp );
+ }
+ if ( passwdp && *passwdp ) {
+ free( *passwdp );
+ }
+ break;
+
+ case 0:
+
+ /*
+ * Return credentials for LDAP referal...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "ldap_rebind_proc: Return necessary values...");
+
+ *dnp = strdup(BrowseLDAPBindDN);
+ *passwdp = strdup(BrowseLDAPPassword);
+ *authmethodp = LDAP_AUTH_SIMPLE;
+ break;
+
+ default:
+
+ /*
+ * Should never happen...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP rebind has been called with wrong freeit value!");
+ break;
+
+ }
+
+ return (LDAP_SUCCESS);
+}
+# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+#endif /* HAVE_LDAP_REBIND_PROC */
+
+
+#ifdef HAVE_LDAP
+/*
+ * 'ldap_connect()' - Start new LDAP connection
+ */
+
+static LDAP *
+ldap_connect(void)
+{
+ /*
+ * Open LDAP handle...
+ */
+
+ int rc; /* LDAP API status */
+ int version = 3; /* LDAP version */
+ struct berval bv = {0, ""}; /* SASL bind value */
+ LDAP *TempBrowseLDAPHandle=NULL; /* Temporary LDAP Handle */
+# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
+ int ldap_ssl = 0; /* LDAP SSL indicator */
+ int ssl_err = 0; /* LDAP SSL error value */
+# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */
+
+# ifdef HAVE_OPENLDAP
+# ifdef HAVE_LDAP_SSL
+
+ /*
+ * Set the certificate file to use for encrypted LDAP sessions...
+ */
+
+ if (BrowseLDAPCACertFile)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdStartBrowsing: Setting CA certificate file \"%s\"",
+ BrowseLDAPCACertFile);
+
+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
+ (void *)BrowseLDAPCACertFile)) != LDAP_SUCCESS)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to set CA certificate file for LDAP "
+ "connections: %d - %s", rc, ldap_err2string(rc));
+ }
+
+# endif /* HAVE_LDAP_SSL */
+ /*
+ * Initialize OPENLDAP connection...
+ * LDAP stuff currently only supports ldapi EXTERNAL SASL binds...
+ */
+
+ if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
+ rc = ldap_initialize(&TempBrowseLDAPHandle, "ldapi:///");
+ else
+ rc = ldap_initialize(&TempBrowseLDAPHandle, BrowseLDAPServer);
+
+# else /* HAVE_OPENLDAP */
+
+ int ldap_port = 0; /* LDAP port */
+ char ldap_protocol[11], /* LDAP protocol */
+ ldap_host[255]; /* LDAP host */
+
+ /*
+ * Split LDAP URI into its components...
+ */
+
+ if (! BrowseLDAPServer)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "BrowseLDAPServer not configured! Disable LDAP browsing!");
+ BrowseLocalProtocols &= ~BROWSE_LDAP;
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ return (NULL);
+ }
+
+ sscanf(BrowseLDAPServer, "%10[^:]://%254[^:/]:%d", ldap_protocol, ldap_host, &ldap_port);
+
+ if (strcmp(ldap_protocol, "ldap") == 0) {
+ ldap_ssl = 0;
+ } else if (strcmp(ldap_protocol, "ldaps") == 0) {
+ ldap_ssl = 1;
+ } else {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "unrecognised ldap protocol (%s)!", ldap_protocol);
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Disable LDAP browsing!");
+ BrowseLocalProtocols &= ~BROWSE_LDAP;
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ return (NULL);
+ }
+
+ if (ldap_port == 0)
+ {
+ if (ldap_ssl)
+ ldap_port = LDAPS_PORT;
+ else
+ ldap_port = LDAP_PORT;
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "LDAP Connection Details: PROT:%s HOST:%s PORT:%d",
+ ldap_protocol, ldap_host, ldap_port);
+
+ /*
+ * Initialize LDAP connection...
+ */
+
+ if (! ldap_ssl)
+ {
+ if ((TempBrowseLDAPHandle = ldap_init(ldap_host, ldap_port)) == NULL)
+ rc = LDAP_OPERATIONS_ERROR;
+ else
+ rc = LDAP_SUCCESS;
+
+# ifdef HAVE_LDAP_SSL
+ }
+ else
+ {
+
+ /*
+ * Initialize SSL LDAP connection...
+ */
+ if (BrowseLDAPCACertFile)
+ {
+ rc = ldapssl_client_init(BrowseLDAPCACertFile, (void *)NULL);
+ if (rc != LDAP_SUCCESS) {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Failed to initialize LDAP SSL client!");
+ rc = LDAP_OPERATIONS_ERROR;
+ } else {
+ if ((TempBrowseLDAPHandle = ldapssl_init(ldap_host, ldap_port, 1)) == NULL)
+ rc = LDAP_OPERATIONS_ERROR;
+ else
+ rc = LDAP_SUCCESS;
+ }
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP SSL certificate file/database not configured!");
+ rc = LDAP_OPERATIONS_ERROR;
+ }
+
+# else /* HAVE_LDAP_SSL */
+
+ /*
+ * Return error, because client libraries doesn't support SSL
+ */
+
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP client libraries does not support TLS");
+ rc = LDAP_OPERATIONS_ERROR;
+
+# endif /* HAVE_LDAP_SSL */
+ }
+# endif /* HAVE_OPENLDAP */
+
+ /*
+ * Check return code from LDAP initialize...
+ */
+
+ if (rc != LDAP_SUCCESS)
+ {
+ if ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to initialize LDAP! Temporary disable LDAP browsing...");
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to initialize LDAP! Disable LDAP browsing!");
+ BrowseLocalProtocols &= ~BROWSE_LDAP;
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ }
+
+ ldap_disconnect(TempBrowseLDAPHandle);
+ TempBrowseLDAPHandle = NULL;
+ }
+
+ /*
+ * Upgrade LDAP version...
+ */
+
+ else if (ldap_set_option(TempBrowseLDAPHandle, LDAP_OPT_PROTOCOL_VERSION,
+ (const void *)&version) != LDAP_SUCCESS)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to set LDAP protocol version %d! Disable LDAP browsing!",
+ version);
+ BrowseLocalProtocols &= ~BROWSE_LDAP;
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ ldap_disconnect(TempBrowseLDAPHandle);
+ TempBrowseLDAPHandle = NULL;
+ }
+ else
+ {
+
+ /*
+ * Register LDAP rebind procedure...
+ */
+
+# ifdef HAVE_LDAP_REBIND_PROC
+# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+
+ rc = ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, (void *)NULL);
+ if ( rc != LDAP_SUCCESS )
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Setting LDAP rebind function failed with status %d: %s",
+ rc, ldap_err2string(rc));
+
+# else
+
+ ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, (void *)NULL);
+
+# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+# endif /* HAVE_LDAP_REBIND_PROC */
+
+ /*
+ * Start LDAP bind...
+ */
+
+# if LDAP_API_VERSION > 3000
+ struct berval bval;
+ bval.bv_val = BrowseLDAPPassword;
+ bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
+
+ if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
+ rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, NULL, "EXTERNAL", &bv, NULL,
+ NULL, NULL);
+ else
+ rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE, &bval, NULL, NULL, NULL);
+# else
+ rc = ldap_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN,
+ BrowseLDAPPassword, LDAP_AUTH_SIMPLE);
+# endif /* LDAP_API_VERSION > 3000 */
+
+ if (rc != LDAP_SUCCESS)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP bind failed with error %d: %s",
+ rc, ldap_err2string(rc));
+# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
+ if (ldap_ssl && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR)))
+ {
+ ssl_err = PORT_GetError();
+ if (ssl_err != 0)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP SSL error %d: %s",
+ ssl_err, ldapssl_err2string(ssl_err));
+ }
+# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */
+ ldap_disconnect(TempBrowseLDAPHandle);
+ TempBrowseLDAPHandle = NULL;
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "LDAP connection established");
+ }
+
+ }
+ return (TempBrowseLDAPHandle);
+}
+
+
+/*
+ * 'ldap_reconnect()' - Reconnect to LDAP Server
+ */
+
+static void
+ldap_reconnect(void)
+{
+ LDAP *TempBrowseLDAPHandle = NULL; /* Temp Handle to LDAP server */
+
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Try LDAP reconnect...");
+
+ /*
+ * Get a new LDAP Handle and replace the global Handle
+ * if the new connection was successful
+ */
+
+ TempBrowseLDAPHandle = ldap_connect();
+
+ if (TempBrowseLDAPHandle != NULL)
+ {
+ if (BrowseLDAPHandle != NULL)
+ {
+ ldap_disconnect(BrowseLDAPHandle);
+ }
+ BrowseLDAPHandle = TempBrowseLDAPHandle;
+ }
+}
+
+
+/*
+ * 'ldap_disconnect()' - Disconnect from LDAP Server
+ */
+
+static void
+ldap_disconnect(LDAP *ld) /* I - LDAP handle */
+{
+ int rc; /* return code */
+
+ /*
+ * Close LDAP handle...
+ */
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ rc = ldap_unbind_ext_s(ld, NULL, NULL);
+# else
+ rc = ldap_unbind_s(ld);
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ if (rc != LDAP_SUCCESS)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unbind from LDAP server failed with status %d: %s",
+ rc, ldap_err2string(rc));
+}
+#endif /* HAVE_LDAP */
+
+
/*
* 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
*/
@@ -1125,7 +1529,7 @@ cupsdStartBrowsing(void)
BrowseSLPHandle = NULL;
#endif /* HAVE_LIBSLP */
-#ifdef HAVE_OPENLDAP
+#ifdef HAVE_LDAP
if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP)
{
if (!BrowseLDAPDN)
@@ -1137,84 +1541,13 @@ cupsdStartBrowsing(void)
}
else
{
- /*
- * Open LDAP handle...
- */
-
- int rc; /* LDAP API status */
- int version = 3; /* LDAP version */
- struct berval bv = {0, ""}; /* SASL bind value */
-
-
- /*
- * Set the certificate file to use for encrypted LDAP sessions...
- */
-
- if (BrowseLDAPCACertFile)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdStartBrowsing: Setting CA certificate file \"%s\"",
- BrowseLDAPCACertFile);
-
- if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
- (void *)BrowseLDAPCACertFile))
- != LDAP_SUCCESS)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to set CA certificate file for LDAP "
- "connections: %d - %s", rc, ldap_err2string(rc));
- }
-
- /*
- * LDAP stuff currently only supports ldapi EXTERNAL SASL binds...
- */
-
- if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
- rc = ldap_initialize(&BrowseLDAPHandle, "ldapi:///");
- else
- rc = ldap_initialize(&BrowseLDAPHandle, BrowseLDAPServer);
-
- if (rc != LDAP_SUCCESS)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to initialize LDAP; disabling LDAP browsing!");
- BrowseLocalProtocols &= ~BROWSE_LDAP;
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
- }
- else if (ldap_set_option(BrowseLDAPHandle, LDAP_OPT_PROTOCOL_VERSION,
- (const void *)&version) != LDAP_SUCCESS)
- {
- ldap_unbind_ext(BrowseLDAPHandle, NULL, NULL);
- BrowseLDAPHandle = NULL;
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to set LDAP protocol version; "
- "disabling LDAP browsing!");
- BrowseLocalProtocols &= ~BROWSE_LDAP;
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
- }
- else
- {
- if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
- rc = ldap_sasl_bind_s(BrowseLDAPHandle, NULL, "EXTERNAL", &bv, NULL,
- NULL, NULL);
- else
- rc = ldap_bind_s(BrowseLDAPHandle, BrowseLDAPBindDN,
- BrowseLDAPPassword, LDAP_AUTH_SIMPLE);
-
- if (rc != LDAP_SUCCESS)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to bind to LDAP server; "
- "disabling LDAP browsing!");
- ldap_unbind_ext(BrowseLDAPHandle, NULL, NULL);
- BrowseLocalProtocols &= ~BROWSE_LDAP;
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
- }
- }
+ /* Open LDAP handle... */
+ BrowseLDAPHandle = ldap_connect();
}
BrowseLDAPRefresh = 0;
}
-#endif /* HAVE_OPENLDAP */
+#endif /* HAVE_LDAP */
/*
* Enable LPD and SMB printer sharing as needed through external programs...
@@ -1425,11 +1758,12 @@ cupsdStopBrowsing(void)
}
#endif /* HAVE_LIBSLP */
-#ifdef HAVE_OPENLDAP
+#ifdef HAVE_LDAP
if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP) &&
BrowseLDAPHandle)
{
- ldap_unbind(BrowseLDAPHandle);
+ ldap_dereg_ou(ServerName, BrowseLDAPDN);
+ ldap_disconnect(BrowseLDAPHandle);
BrowseLDAPHandle = NULL;
}
#endif /* HAVE_OPENLDAP */
@@ -1545,7 +1879,7 @@ cupsdUpdateDNSSDName(void)
#endif /* HAVE_DNSSD */
-#ifdef HAVE_OPENLDAP
+#ifdef HAVE_LDAP
/*
* 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP...
*/
@@ -1559,36 +1893,72 @@ cupsdUpdateLDAPBrowse(void)
location[1024], /* Printer location */
info[1024], /* Printer information */
make_model[1024], /* Printer make and model */
- **value; /* Holds the returned data from LDAP */
+ type_num[30]; /* Printer type number */
int type; /* Printer type */
int rc; /* LDAP status */
int limit; /* Size limit */
LDAPMessage *res, /* LDAP search results */
*e; /* Current entry from search */
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "UpdateLDAPBrowse: %s", ServerName);
+
+ BrowseLDAPRefresh = time(NULL) + BrowseInterval;
+
+ /*
+ * Reconnect if LDAP Handle is invalid...
+ */
+
+ if (! BrowseLDAPHandle)
+ {
+ ldap_reconnect();
+ return;
+ }
/*
- * Search for printers...
+ * Search for cups printers in LDAP directory...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "UpdateLDAPBrowse: %s", ServerName);
+ rc = ldap_search_rec(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
+ "(objectclass=cupsPrinter)", (char **)ldap_attrs, 0, &res);
- BrowseLDAPRefresh = time(NULL) + BrowseInterval;
+ /*
+ * If ldap search was successfull then exit function
+ * and temporary disable LDAP updates...
+ */
- rc = ldap_search_s(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
- "(objectclass=cupsPrinter)", (char **)ldap_attrs, 0, &res);
if (rc != LDAP_SUCCESS)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "LDAP search returned error %d: %s", rc,
- ldap_err2string(rc));
+ if (BrowseLDAPUpdate && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR)))
+ {
+ BrowseLDAPUpdate = FALSE;
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "LDAP update temporary disabled");
+ }
return;
}
+ /*
+ * If LDAP updates were disabled, we will reenable them...
+ */
+
+ if (! BrowseLDAPUpdate)
+ {
+ BrowseLDAPUpdate = TRUE;
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "LDAP update enabled");
+ }
+
+ /*
+ * Count LDAP entries and return if no entry exist...
+ */
+
limit = ldap_count_entries(BrowseLDAPHandle, res);
cupsdLogMessage(CUPSD_LOG_DEBUG2, "LDAP search returned %d entries", limit);
if (limit < 1)
+ {
+ ldap_freeres(res);
return;
+ }
/*
* Loop through the available printers...
@@ -1602,41 +1972,28 @@ cupsdUpdateLDAPBrowse(void)
* Get the required values from this entry...
*/
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerDescription")) == NULL)
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerDescription", info, sizeof(info)) == -1)
continue;
- strlcpy(info, *value, sizeof(info));
- ldap_value_free(value);
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerLocation")) == NULL)
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerLocation", location, sizeof(location)) == -1)
continue;
- strlcpy(location, *value, sizeof(location));
- ldap_value_free(value);
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerMakeAndModel")) == NULL)
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerMakeAndModel", make_model, sizeof(make_model)) == -1)
continue;
- strlcpy(make_model, *value, sizeof(make_model));
- ldap_value_free(value);
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerType")) == NULL)
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerType", type_num, sizeof(type_num)) == -1)
continue;
- type = atoi(*value);
- ldap_value_free(value);
+ type = atoi(type_num);
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerURI")) == NULL)
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerURI", uri, sizeof(uri)) == -1)
continue;
- strlcpy(uri, *value, sizeof(uri));
- ldap_value_free(value);
-
/*
* Process the entry as browse data...
*/
@@ -1646,8 +2003,10 @@ cupsdUpdateLDAPBrowse(void)
location, info, make_model, 0, NULL);
}
+
+ ldap_freeres(res);
}
-#endif /* HAVE_OPENLDAP */
+#endif /* HAVE_LDAP */
#ifdef HAVE_LIBSLP
@@ -3232,7 +3591,346 @@ send_cups_browse(cupsd_printer_t *p) /* I - Printer to send */
}
-#ifdef HAVE_OPENLDAP
+#ifdef HAVE_LDAP
+/*
+ * 'ldap_search_rec()' - LDAP Search with reconnect
+ */
+
+static int
+ldap_search_rec(LDAP *ld, /* I - LDAP handler */
+ char *base, /* I - Base dn */
+ int scope, /* I - LDAP search scope */
+ char *filter, /* I - Filter string */
+ char *attrs[], /* I - Requested attributes */
+ int attrsonly, /* I - Return only attributes? */
+ LDAPMessage **res) /* I - LDAP handler */
+{
+ int rc; /* Return code */
+
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ rc = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL,
+ NULL, LDAP_NO_LIMIT, res);
+# else
+ rc = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res);
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+
+ /*
+ * If we have a connection problem try again...
+ */
+
+ if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP search failed with status %d: %s",
+ rc, ldap_err2string(rc));
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "We try the LDAP search once again after reconnecting to "
+ "the server");
+ ldap_freeres(*res);
+ ldap_reconnect();
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ rc = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL,
+ NULL, NULL, LDAP_NO_LIMIT, res);
+# else
+ rc = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res);
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ }
+
+ if (rc == LDAP_NO_SUCH_OBJECT)
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "ldap_search_rec: LDAP entry/object not found");
+ else if (rc != LDAP_SUCCESS)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "ldap_search_rec: LDAP search failed with status %d: %s",
+ rc, ldap_err2string(rc));
+
+ if (rc != LDAP_SUCCESS)
+ ldap_freeres(*res);
+
+ return (rc);
+}
+
+
+/*
+ * 'ldap_freeres()' - Free LDAPMessage
+ */
+
+static void
+ldap_freeres(LDAPMessage *entry) /* I - LDAP handler */
+{
+ int rc; /* Return value */
+
+
+ rc = ldap_msgfree(entry);
+ if (rc == -1)
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "Can't free LDAPMessage!");
+ else if (rc == 0)
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "Freeing LDAPMessage was unnecessary");
+}
+
+
+/*
+ * 'ldap_getval_char()' - Get first LDAP value and convert to string
+ */
+
+static int
+ldap_getval_firststring(
+ LDAP *ld, /* I - LDAP handler */
+ LDAPMessage *entry, /* I - LDAP message or search result */
+ char *attr, /* I - the wanted attribute */
+ char *retval, /* O - String to return */
+ unsigned long maxsize) /* I - Max string size */
+{
+ char *dn; /* LDAP DN */
+ int rc = 0; /* Return code */
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ struct berval **bval; /* LDAP value array */
+ unsigned long size; /* String size */
+
+
+ /*
+ * Get value from LDAPMessage...
+ */
+
+ if ((bval = ldap_get_values_len(ld, entry, attr)) == NULL)
+ {
+ rc = -1;
+ dn = ldap_get_dn(ld, entry);
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "Failed to get LDAP value %s for %s!",
+ attr, dn);
+ ldap_memfree(dn);
+ }
+ else
+ {
+
+ /*
+ * Check size and copy value into our string...
+ */
+
+ size = maxsize;
+ if (size < bval[0]->bv_len)
+ {
+ rc = -1;
+ dn = ldap_get_dn(ld, entry);
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "Attribute %s is too big! (dn: %s)",
+ attr, dn);
+ ldap_memfree(dn);
+ }
+ else
+ size = bval[0]->bv_len;
+
+ strlcpy(retval, bval[0]->bv_val, size);
+ ldap_value_free_len(bval);
+ }
+# else
+ char **value; /* LDAP value */
+
+ /*
+ * Get value from LDAPMessage...
+ */
+
+ if ((value = (char **)ldap_get_values(ld, entry, attr)) == NULL)
+ {
+ rc = -1;
+ dn = ldap_get_dn(ld, entry);
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "Failed to get LDAP value %s for %s!",
+ attr, dn);
+ ldap_memfree(dn);
+ }
+ else
+ {
+ strlcpy(retval, *value, maxsize);
+ ldap_value_free(value);
+ }
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+
+ return (rc);
+}
+
+
+/*
+ * 'send_ldap_ou()' - Send LDAP ou registrations.
+ */
+
+static void
+send_ldap_ou(char *ou, /* I - Servername/ou to register */
+ char *basedn, /* I - Our base dn */
+ char *descstring) /* I - Description for ou */
+{
+ int i; /* Looping var... */
+ LDAPMod mods[3]; /* The 3 attributes we will be adding */
+ LDAPMod *pmods[4]; /* Pointers to the 3 attributes + NULL */
+ LDAPMessage *res, /* Search result token */
+ *e; /* Current entry from search */
+ int rc; /* LDAP status */
+ char dn[1024], /* DN of the organizational unit we are adding */
+ *desc[2], /* Change records */
+ *ou_value[2];
+ char old_desc[1024]; /* Old description */
+ static const char * const objectClass_values[] =
+ { /* The 2 objectClass's we use in */
+ "top", /* our LDAP entries */
+ "organizationalUnit",
+ NULL
+ };
+ static const char * const ou_attrs[] =/* CUPS LDAP attributes */
+ {
+ "description",
+ NULL
+ };
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_ou: %s", ou);
+
+ /*
+ * Reconnect if LDAP Handle is invalid...
+ */
+
+ if (! BrowseLDAPHandle)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_ou: LDAP Handle is invalid. Try "
+ "reconnecting...");
+ ldap_reconnect();
+ return;
+ }
+
+ /*
+ * Prepare ldap search...
+ */
+
+ snprintf(dn, sizeof(dn), "ou=%s, %s", ou, basedn);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_ou: dn=\"%s\"", dn);
+
+ ou_value[0] = ou;
+ ou_value[1] = NULL;
+ desc[0] = descstring;
+ desc[1] = NULL;
+
+ mods[0].mod_type = "ou";
+ mods[0].mod_values = ou_value;
+ mods[1].mod_type = "description";
+ mods[1].mod_values = desc;
+ mods[2].mod_type = "objectClass";
+ mods[2].mod_values = (char **)objectClass_values;
+
+ rc = ldap_search_rec(BrowseLDAPHandle, dn, LDAP_SCOPE_BASE, NULL,
+ (char **)ou_attrs, 0, &res);
+
+ /*
+ * If ldap search was not successfull then exit function...
+ */
+
+ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT)
+ return;
+
+ /*
+ * Check if we need to insert or update the LDAP entry...
+ */
+
+ if (ldap_count_entries(BrowseLDAPHandle, res) > 0 &&
+ rc != LDAP_NO_SUCH_OBJECT)
+ {
+ /*
+ * Printserver has already been registered, check if
+ * modification is required...
+ */
+
+ e = ldap_first_entry(BrowseLDAPHandle, res);
+
+ /*
+ * Get the required values from this entry...
+ */
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e, "description", old_desc,
+ sizeof(old_desc)) == -1)
+ old_desc[0] = '\0';
+
+ /*
+ * Check if modification is required...
+ */
+
+ if ( strcmp(desc[0], old_desc) == 0 )
+ {
+ /*
+ * LDAP entry for the printer exists.
+ * Printer has already been registered,
+ * no modifications required...
+ */
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_ou: No updates required for %s", ou);
+ }
+ else
+ {
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_ou: Replace entry for %s", ou);
+
+ for (i = 0; i < 3; i ++)
+ {
+ pmods[i] = mods + i;
+ pmods[i]->mod_op = LDAP_MOD_REPLACE;
+ }
+ pmods[i] = NULL;
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_modify_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
+ if ((rc = ldap_modify_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP modify for %s failed with status %d: %s",
+ ou, rc, ldap_err2string(rc));
+ if ( LDAP_SERVER_DOWN == rc )
+ ldap_reconnect();
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Printserver has never been registered,
+ * add registration...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_ou: Add entry for %s", ou);
+
+ for (i = 0; i < 3; i ++)
+ {
+ pmods[i] = mods + i;
+ pmods[i]->mod_op = LDAP_MOD_ADD;
+ }
+ pmods[i] = NULL;
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_add_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
+ if ((rc = ldap_add_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP add for %s failed with status %d: %s",
+ ou, rc, ldap_err2string(rc));
+ if ( LDAP_SERVER_DOWN == rc )
+ ldap_reconnect();
+ }
+ }
+
+ ldap_freeres(res);
+}
+
+
/*
* 'send_ldap_browse()' - Send LDAP printer registrations.
*/
@@ -3243,7 +3941,8 @@ send_ldap_browse(cupsd_printer_t *p) /* I - Printer to register */
int i; /* Looping var... */
LDAPMod mods[7]; /* The 7 attributes we will be adding */
LDAPMod *pmods[8]; /* Pointers to the 7 attributes + NULL */
- LDAPMessage *res; /* Search result token */
+ LDAPMessage *res, /* Search result token */
+ *e; /* Current entry from search */
char *cn_value[2], /* Change records */
*uri[2],
*info[2],
@@ -3251,9 +3950,14 @@ send_ldap_browse(cupsd_printer_t *p) /* I - Printer to register */
*make_model[2],
*type[2],
typestring[255], /* String to hold printer-type */
- filter[256], /* Search filter for possible UPDATEs */
dn[1024]; /* DN of the printer we are adding */
int rc; /* LDAP status */
+ char old_uri[HTTP_MAX_URI], /* Printer URI */
+ old_location[1024], /* Printer location */
+ old_info[1024], /* Printer information */
+ old_make_model[1024], /* Printer make and model */
+ old_type_string[30]; /* Temporary type number */
+ int old_type; /* Printer type */
static const char * const objectClass_values[] =
{ /* The 3 objectClass's we use in */
"top", /* our LDAP entries */
@@ -3262,9 +3966,35 @@ send_ldap_browse(cupsd_printer_t *p) /* I - Printer to register */
NULL
};
+
cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: %s", p->name);
/*
+ * Exit function if LDAP updates has been disabled...
+ */
+
+ if (!BrowseLDAPUpdate)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_browse: Updates temporary disabled; "
+ "skipping...");
+ return;
+ }
+
+ /*
+ * Reconnect if LDAP Handle is invalid...
+ */
+
+ if (!BrowseLDAPHandle)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_browse: LDAP Handle is invalid. Try "
+ "reconnecting...");
+ ldap_reconnect();
+ return;
+ }
+
+ /*
* Everything in ldap is ** so we fudge around it...
*/
@@ -3283,63 +4013,153 @@ send_ldap_browse(cupsd_printer_t *p) /* I - Printer to register */
uri[0] = p->uri;
uri[1] = NULL;
- snprintf(filter, sizeof(filter),
- "(&(objectclass=cupsPrinter)(printerURI=%s))", p->uri);
+ /*
+ * Get ldap entry for printer ...
+ */
+
+ snprintf(dn, sizeof(dn), "cn=%s, ou=%s, %s", p->name, ServerName,
+ BrowseLDAPDN);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: dn=\"%s\"", dn);
+
+ rc = ldap_search_rec(BrowseLDAPHandle, dn, LDAP_SCOPE_BASE, NULL,
+ (char **)ldap_attrs, 0, &res);
+
+ /*
+ * If ldap search was not successfull then exit function
+ * and temporary disable LDAP updates...
+ */
+
+ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT)
+ {
+ if (BrowseLDAPUpdate &&
+ (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR))
+ {
+ BrowseLDAPUpdate = FALSE;
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "LDAP update temporary disabled");
+ }
+
+ return;
+ }
- ldap_search_s(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
- filter, (char **)ldap_attrs, 0, &res);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: Searching \"%s\"",
- filter);
+ /*
+ * Fill modification array...
+ */
- mods[0].mod_type = "cn";
+ mods[0].mod_type = "cn";
mods[0].mod_values = cn_value;
- mods[1].mod_type = "printerDescription";
+ mods[1].mod_type = "printerDescription";
mods[1].mod_values = info;
- mods[2].mod_type = "printerURI";
+ mods[2].mod_type = "printerURI";
mods[2].mod_values = uri;
- mods[3].mod_type = "printerLocation";
+ mods[3].mod_type = "printerLocation";
mods[3].mod_values = location;
- mods[4].mod_type = "printerMakeAndModel";
+ mods[4].mod_type = "printerMakeAndModel";
mods[4].mod_values = make_model;
- mods[5].mod_type = "printerType";
+ mods[5].mod_type = "printerType";
mods[5].mod_values = type;
- mods[6].mod_type = "objectClass";
+ mods[6].mod_type = "objectClass";
mods[6].mod_values = (char **)objectClass_values;
- snprintf(dn, sizeof(dn), "cn=%s,ou=printers,%s", p->name, BrowseLDAPDN);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: dn=\"%s\"", dn);
+ /*
+ * Check if we need to insert or update the LDAP entry...
+ */
- if (ldap_count_entries(BrowseLDAPHandle, res) > 0)
+ if (ldap_count_entries(BrowseLDAPHandle, res) > 0 &&
+ rc != LDAP_NO_SUCH_OBJECT)
{
/*
- * Printer has already been registered, modify the current
- * registration...
+ * Printer has already been registered, check if
+ * modification is required...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "send_ldap_browse: Replacing entry...");
+ e = ldap_first_entry(BrowseLDAPHandle, res);
- for (i = 0; i < 7; i ++)
+ /*
+ * Get the required values from this entry...
+ */
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerDescription",
+ old_info, sizeof(old_info)) == -1)
+ old_info[0] = '\0';
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerLocation",
+ old_location, sizeof(old_location)) == -1)
+ old_info[0] = '\0';
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerMakeAndModel",
+ old_make_model, sizeof(old_make_model)) == -1)
+ old_info[0] = '\0';
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerType",
+ old_type_string, sizeof(old_type_string)) == -1)
+ old_info[0] = '\0';
+
+ old_type = atoi(old_type_string);
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerURI", old_uri,
+ sizeof(old_uri)) == -1)
+ old_info[0] = '\0';
+
+ /*
+ * Check if modification is required...
+ */
+
+ if (!strcmp(info[0], old_info) && !strcmp(uri[0], old_uri) &&
+ !strcmp(location[0], old_location) &&
+ !strcmp(make_model[0], old_make_model) && p->type == old_type)
{
- pmods[i] = mods + i;
- pmods[i]->mod_op = LDAP_MOD_REPLACE;
+ /*
+ * LDAP entry for the printer exists. Printer has already been registered,
+ * no modifications required...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_browse: No updates required for %s", p->name);
}
- pmods[i] = NULL;
+ else
+ {
+ /*
+ * LDAP entry for the printer exists. Printer has already been registered,
+ * modify the current registration...
+ */
- if ((rc = ldap_modify_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "LDAP modify for %s failed with status %d: %s",
- p->name, rc, ldap_err2string(rc));
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "send_ldap_browse: Replace entry for %s", p->name);
+
+ for (i = 0; i < 7; i ++)
+ {
+ pmods[i] = mods + i;
+ pmods[i]->mod_op = LDAP_MOD_REPLACE;
+ }
+ pmods[i] = NULL;
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_modify_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
+ if ((rc = ldap_modify_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP modify for %s failed with status %d: %s",
+ p->name, rc, ldap_err2string(rc));
+ if (rc == LDAP_SERVER_DOWN)
+ ldap_reconnect();
+ }
+ }
}
else
{
/*
- * Printer has never been registered, add the current
- * registration...
+ * No LDAP entry exists for the printer. Printer has never been registered,
+ * add the current registration...
*/
+ send_ldap_ou(ServerName, BrowseLDAPDN, "CUPS Server");
+
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "send_ldap_browse: Adding entry...");
+ "send_ldap_browse: Add entry for %s", p->name);
for (i = 0; i < 7; i ++)
{
@@ -3348,13 +4168,155 @@ send_ldap_browse(cupsd_printer_t *p) /* I - Printer to register */
}
pmods[i] = NULL;
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_add_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
if ((rc = ldap_add_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ {
cupsdLogMessage(CUPSD_LOG_ERROR,
"LDAP add for %s failed with status %d: %s",
p->name, rc, ldap_err2string(rc));
+ if (rc == LDAP_SERVER_DOWN)
+ ldap_reconnect();
+ }
}
+
+ ldap_freeres(res);
}
-#endif /* HAVE_OPENLDAP */
+
+
+/*
+ * 'ldap_dereg_printer()' - Delete printer from directory
+ */
+
+static void
+ldap_dereg_printer(cupsd_printer_t *p) /* I - Printer to deregister */
+{
+ char dn[1024]; /* DN of the printer */
+ int rc; /* LDAP status */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_printer: Remove entry for %s",
+ p->name);
+
+ /*
+ * Reconnect if LDAP Handle is invalid...
+ */
+
+ if (!BrowseLDAPHandle)
+ {
+ ldap_reconnect();
+ return;
+ }
+
+ /*
+ * Get dn for printer and delete LDAP entry...
+ */
+
+ snprintf(dn, sizeof(dn), "cn=%s, ou=%s, %s", p->name, ServerName,
+ BrowseLDAPDN);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_printer: dn=\"%s\"", dn);
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
+ if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ {
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "LDAP delete for %s failed with status %d: %s",
+ p->name, rc, ldap_err2string(rc));
+
+ /*
+ * If we had a connection problem (connection timed out, etc.)
+ * we should reconnect and try again to delete the entry...
+ */
+
+ if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
+ {
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Retry deleting LDAP entry for %s after a reconnect...", p->name);
+ ldap_reconnect();
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
+ if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "LDAP delete for %s failed with status %d: %s",
+ p->name, rc, ldap_err2string(rc));
+ }
+ }
+}
+
+
+static void
+ldap_dereg_ou(char *ou, /* I - Organizational unit (servername) */
+ char *basedn) /* I - Dase dn */
+{
+ char dn[1024]; /* DN of the printer */
+ int rc; /* LDAP status */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_ou: Remove entry for %s", ou);
+
+ /*
+ * Reconnect if LDAP Handle is invalid...
+ */
+
+ if (!BrowseLDAPHandle)
+ {
+ ldap_reconnect();
+ return;
+ }
+
+ /*
+ * Get dn for printer and delete LDAP entry...
+ */
+
+ snprintf(dn, sizeof(dn), "ou=%s, %s", ou, basedn);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_ou: dn=\"%s\"", dn);
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
+ if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ {
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "LDAP delete for %s failed with status %d: %s",
+ ou, rc, ldap_err2string(rc));
+
+ /*
+ * If we had a connection problem (connection timed out, etc.)
+ * we should reconnect and try again to delete the entry...
+ */
+
+ if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
+ {
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Retry deleting LDAP entry for %s after a reconnect...", ou);
+ ldap_reconnect();
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
+ NULL)) != LDAP_SUCCESS)
+# else
+ if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "LDAP delete for %s failed with status %d: %s",
+ ou, rc, ldap_err2string(rc));
+ }
+
+ }
+}
+#endif /* HAVE_LDAP */
#ifdef HAVE_LIBSLP
diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h
index 60c22c3bd..7de4e2d56 100644
--- a/scheduler/dirsvc.h
+++ b/scheduler/dirsvc.h
@@ -22,12 +22,15 @@
# include <slp.h>
#endif /* HAVE_LIBSLP */
-#ifdef HAVE_OPENLDAP
+#ifdef HAVE_LDAP
# ifdef __sun
# include <lber.h>
# endif /* __sun */
# include <ldap.h>
-#endif /* HAVE_OPENLDAP */
+# ifdef HAVE_LDAP_SSL_H
+# include <ldap_ssl.h>
+# endif /* HAVE_LDAP_SSL_H */
+#endif /* HAVE_LDAP */
/*
* Browse protocols...
@@ -150,22 +153,26 @@ VAR time_t BrowseSLPRefresh VALUE(0);
#endif /* HAVE_LIBSLP */
#ifdef HAVE_LDAP
-# ifdef HAVE_OPENLDAP
VAR LDAP *BrowseLDAPHandle VALUE(NULL);
/* Handle to LDAP server */
-# endif /* HAVE_OPENLDAP */
VAR time_t BrowseLDAPRefresh VALUE(0);
/* Next LDAP refresh time */
VAR char *BrowseLDAPBindDN VALUE(NULL),
/* LDAP login DN */
+ *BrowseLDAPCACertFile VALUE(NULL),
+ /* LDAP CA cert file */
*BrowseLDAPDN VALUE(NULL),
/* LDAP search DN */
*BrowseLDAPPassword VALUE(NULL),
/* LDAP login password */
- *BrowseLDAPServer VALUE(NULL),
+ *BrowseLDAPServer VALUE(NULL);
/* LDAP server to use */
- *BrowseLDAPCACertFile VALUE(NULL);
+VAR int BrowseLDAPUpdate VALUE(TRUE);
+ /* enables LDAP updates */
+# ifdef HAVE_LDAP_SSL
+VAR char *BrowseLDAPCACertFile VALUE(NULL);
/* LDAP CA CERT file to use */
+# endif /* HAVE_LDAP_SSL */
#endif /* HAVE_LDAP */
VAR char *LPDConfigFile VALUE(NULL),
/* LPD configuration file */
diff --git a/scheduler/main.c b/scheduler/main.c
index b6beb3ee0..571b3a7fc 100644
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -1418,6 +1418,7 @@ launchd_checkin(void)
"launchd_checkin: launch_msg(\"" LAUNCH_KEY_CHECKIN
"\") IPC failure");
exit(EXIT_FAILURE);
+ return; /* anti-compiler-warning */
}
if (launch_data_get_type(ld_resp) == LAUNCH_DATA_ERRNO)
@@ -1426,28 +1427,32 @@ launchd_checkin(void)
cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Check-in failed: %s",
strerror(errno));
exit(EXIT_FAILURE);
+ return; /* anti-compiler-warning */
}
/*
* Get the sockets dictionary...
*/
- if (!(ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS)))
+ if ((ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS))
+ == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"launchd_checkin: No sockets found to answer requests on!");
exit(EXIT_FAILURE);
+ return; /* anti-compiler-warning */
}
/*
* Get the array of listener sockets...
*/
- if (!(ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")))
+ if ((ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"launchd_checkin: No sockets found to answer requests on!");
exit(EXIT_FAILURE);
+ return; /* anti-compiler-warning */
}
/*
@@ -1464,73 +1469,75 @@ launchd_checkin(void)
* Get the launchd file descriptor and address...
*/
- tmp = launch_data_array_get_index(ld_array, i);
- fd = launch_data_get_fd(tmp);
- addrlen = sizeof(addr);
-
- if (getsockname(fd, (struct sockaddr *)&addr, &addrlen))
+ if ((tmp = launch_data_array_get_index(ld_array, i)) != NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_checkin: Unable to get local address - %s",
- strerror(errno));
- continue;
- }
+ fd = launch_data_get_fd(tmp);
+ addrlen = sizeof(addr);
- /*
- * Try to match the launchd socket address to one of the listeners...
- */
+ if (getsockname(fd, (struct sockaddr *)&addr, &addrlen))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "launchd_checkin: Unable to get local address - %s",
+ strerror(errno));
+ continue;
+ }
- for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
- lis;
- lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
- if (httpAddrEqual(&lis->address, &addr))
- break;
+ /*
+ * Try to match the launchd socket address to one of the listeners...
+ */
- /*
- * Add a new listener If there's no match...
- */
+ for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+ lis;
+ lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+ if (httpAddrEqual(&lis->address, &addr))
+ break;
- if (lis)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_checkin: Matched existing listener %s with fd %d...",
- httpAddrString(&(lis->address), s, sizeof(s)), fd);
- }
- else
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_checkin: Adding new listener %s with fd %d...",
- httpAddrString(&addr, s, sizeof(s)), fd);
+ /*
+ * Add a new listener If there's no match...
+ */
- if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_checkin: Unable to allocate listener - %s.",
- strerror(errno));
- exit(EXIT_FAILURE);
- }
+ if (lis)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "launchd_checkin: Matched existing listener %s with fd %d...",
+ httpAddrString(&(lis->address), s, sizeof(s)), fd);
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "launchd_checkin: Adding new listener %s with fd %d...",
+ httpAddrString(&addr, s, sizeof(s)), fd);
- cupsArrayAdd(Listeners, lis);
+ if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "launchd_checkin: Unable to allocate listener - %s.",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
- memcpy(&lis->address, &addr, sizeof(lis->address));
- }
+ cupsArrayAdd(Listeners, lis);
- lis->fd = fd;
+ memcpy(&lis->address, &addr, sizeof(lis->address));
+ }
+
+ lis->fd = fd;
# ifdef HAVE_SSL
- portnum = 0;
+ portnum = 0;
# ifdef AF_INET6
- if (lis->address.addr.sa_family == AF_INET6)
- portnum = ntohs(lis->address.ipv6.sin6_port);
- else
+ if (lis->address.addr.sa_family == AF_INET6)
+ portnum = ntohs(lis->address.ipv6.sin6_port);
+ else
# endif /* AF_INET6 */
- if (lis->address.addr.sa_family == AF_INET)
- portnum = ntohs(lis->address.ipv4.sin_port);
+ if (lis->address.addr.sa_family == AF_INET)
+ portnum = ntohs(lis->address.ipv4.sin_port);
- if (portnum == 443)
- lis->encryption = HTTP_ENCRYPT_ALWAYS;
+ if (portnum == 443)
+ lis->encryption = HTTP_ENCRYPT_ALWAYS;
# endif /* HAVE_SSL */
+ }
}
}
diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c
index b8052b3b5..e398d3f4c 100644
--- a/systemv/cupstestppd.c
+++ b/systemv/cupstestppd.c
@@ -21,8 +21,11 @@
* main() - Main entry for test program.
* check_basics() - Check for CR LF, mixed line endings, and blank
* lines.
+ * check_case() - Check that there are no duplicate groups, options,
+ * or choices that differ only by case.
* check_constraints() - Check UIConstraints in the PPD file.
* check_defaults() - Check default option keywords in the PPD file.
+ * check_duplex() - Check duplex keywords in the PPD file.
* check_filters() - Check filters in the PPD file.
* check_profiles() - Check ICC color profiles in the PPD file.
* check_translations() - Check translations in the PPD file.
@@ -58,7 +61,8 @@ enum
WARN_FILTERS = 4,
WARN_PROFILES = 8,
WARN_TRANSLATIONS = 16,
- WARN_ALL = 31
+ WARN_DUPLEX = 32,
+ WARN_ALL = 63
};
@@ -96,8 +100,11 @@ enum
static void check_basics(const char *filename);
static int check_constraints(ppd_file_t *ppd, int errors, int verbose,
int warn);
+static int check_case(ppd_file_t *ppd, int errors, int verbose);
static int check_defaults(ppd_file_t *ppd, int errors, int verbose,
int warn);
+static int check_duplex(ppd_file_t *ppd, int errors, int verbose,
+ int warn);
static int check_filters(ppd_file_t *ppd, const char *root, int errors,
int verbose, int warn);
static int check_profiles(ppd_file_t *ppd, const char *root, int errors,
@@ -190,6 +197,8 @@ main(int argc, /* I - Number of command-line args */
warn |= WARN_CONSTRAINTS;
else if (!strcmp(argv[i], "defaults"))
warn |= WARN_DEFAULTS;
+ else if (!strcmp(argv[i], "duplex"))
+ warn |= WARN_DUPLEX;
else if (!strcmp(argv[i], "filters"))
warn |= WARN_FILTERS;
else if (!strcmp(argv[i], "profiles"))
@@ -1008,55 +1017,6 @@ main(int argc, /* I - Number of command-line args */
}
}
- /*
- * Check for a duplex option, and for standard values...
- */
-
- if ((option = ppdFindOption(ppd, "Duplex")) == NULL)
- if ((option = ppdFindOption(ppd, "JCLDuplex")) == NULL)
- if ((option = ppdFindOption(ppd, "EFDuplex")) == NULL)
- option = ppdFindOption(ppd, "KD03Duplex");
-
- if (option != NULL)
- {
- if (ppdFindChoice(option, "None") == NULL)
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** REQUIRED %s does not define "
- "choice None!\n"
- " REF: Page 122, section 5.17\n"),
- option->keyword);
- }
-
- errors ++;
- }
-
- for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++)
- if (strcmp(choice->choice, "None") &&
- strcmp(choice->choice, "DuplexNoTumble") &&
- strcmp(choice->choice, "DuplexTumble") &&
- strcmp(choice->choice, "SimplexTumble"))
- {
- if (verbose >= 0)
- {
- if (!errors && !verbose)
- _cupsLangPuts(stdout, _(" FAIL\n"));
-
- _cupsLangPrintf(stdout,
- _(" **FAIL** Bad %s choice %s!\n"
- " REF: Page 122, section 5.17\n"),
- option->keyword, choice->choice);
- }
-
- errors ++;
- }
- }
-
if ((attr = ppdFindAttr(ppd, "1284DeviceID", NULL)) &&
strcmp(attr->name, "1284DeviceID"))
{
@@ -1074,6 +1034,8 @@ main(int argc, /* I - Number of command-line args */
errors ++;
}
+ errors = check_case(ppd, errors, verbose);
+
if (!(warn & WARN_CONSTRAINTS))
errors = check_constraints(ppd, errors, verbose, 0);
@@ -1086,6 +1048,9 @@ main(int argc, /* I - Number of command-line args */
if (!(warn & WARN_TRANSLATIONS))
errors = check_translations(ppd, errors, verbose, 0);
+ if (!(warn & WARN_DUPLEX))
+ errors = check_duplex(ppd, errors, verbose, 0);
+
if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) != NULL &&
attr->value)
{
@@ -1217,6 +1182,24 @@ main(int argc, /* I - Number of command-line args */
if (warn & WARN_TRANSLATIONS)
errors = check_translations(ppd, errors, verbose, 1);
+ if (warn & WARN_DUPLEX)
+ errors = check_duplex(ppd, errors, verbose, 1);
+
+ /*
+ * Look for legacy duplex keywords...
+ */
+
+ if ((option = ppdFindOption(ppd, "JCLDuplex")) == NULL)
+ if ((option = ppdFindOption(ppd, "EFDuplex")) == NULL)
+ option = ppdFindOption(ppd, "KD03Duplex");
+
+ if (option)
+ _cupsLangPrintf(stdout,
+ _(" WARN Duplex option keyword %s may not "
+ "work as expected and should be named Duplex!\n"
+ " REF: Page 122, section 5.17\n"),
+ option->keyword);
+
/*
* Look for default keywords with no corresponding option...
*/
@@ -1246,22 +1229,6 @@ main(int argc, /* I - Number of command-line args */
attr->name);
}
- /*
- * Check for old Duplex option names...
- */
-
- if ((option = ppdFindOption(ppd, "EFDuplex")) == NULL)
- option = ppdFindOption(ppd, "KD03Duplex");
-
- if (option)
- {
- _cupsLangPrintf(stdout,
- _(" WARN Duplex option keyword %s "
- "should be named Duplex or JCLDuplex!\n"
- " REF: Page 122, section 5.17\n"),
- option->keyword);
- }
-
ppdMarkDefaults(ppd);
if (ppdConflicts(ppd))
{
@@ -1965,6 +1932,116 @@ check_constraints(ppd_file_t *ppd, /* I - PPD file */
/*
+ * 'check_case()' - Check that there are no duplicate groups, options,
+ * or choices that differ only by case.
+ */
+
+static int /* O - Errors found */
+check_case(ppd_file_t *ppd, /* I - PPD file */
+ int errors, /* I - Errors found */
+ int verbose) /* I - Verbosity level */
+{
+ int i, j; /* Looping vars */
+ ppd_group_t *groupa, /* First group */
+ *groupb; /* Second group */
+ ppd_option_t *optiona, /* First option */
+ *optionb; /* Second option */
+ ppd_choice_t *choicea, /* First choice */
+ *choiceb; /* Second choice */
+
+
+ /*
+ * Check that the groups do not have any duplicate names...
+ */
+
+ for (i = ppd->num_groups, groupa = ppd->groups; i > 1; i --, groupa ++)
+ for (j = i - 1, groupb = groupa + 1; j > 0; j --, groupb ++)
+ if (!strcasecmp(groupa->name, groupb->name))
+ {
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" **FAIL** Group names %s and %s differ only "
+ "by case!\n"),
+ groupa->name, groupb->name);
+
+ errors ++;
+ }
+
+ /*
+ * Check that the options do not have any duplicate names...
+ */
+
+ for (optiona = ppdFirstOption(ppd); optiona; optiona = ppdNextOption(ppd))
+ {
+ cupsArraySave(ppd->options);
+ for (optionb = ppdNextOption(ppd); optionb; optionb = ppdNextOption(ppd))
+ if (!strcasecmp(optiona->keyword, optionb->keyword))
+ {
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" **FAIL** Option names %s and %s differ only "
+ "by case!\n"),
+ optiona->keyword, optionb->keyword);
+
+ errors ++;
+ }
+ cupsArrayRestore(ppd->options);
+
+ /*
+ * Then the choices...
+ */
+
+ for (i = optiona->num_choices, choicea = optiona->choices;
+ i > 1;
+ i --, choicea ++)
+ for (j = i - 1, choiceb = choicea + 1; j > 0; j --, choiceb ++)
+ if (!strcmp(choicea->choice, choiceb->choice))
+ {
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" **FAIL** Multiple occurrences of %s "
+ "choice name %s!\n"),
+ optiona->keyword, choicea->choice);
+
+ errors ++;
+
+ choicea ++;
+ i --;
+ break;
+ }
+ else if (!strcasecmp(choicea->choice, choiceb->choice))
+ {
+ if (!errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ if (verbose >= 0)
+ _cupsLangPrintf(stdout,
+ _(" **FAIL** %s choice names %s and %s "
+ "differ only by case!\n"),
+ optiona->keyword, choicea->choice, choiceb->choice);
+
+ errors ++;
+ }
+ }
+
+ /*
+ * Return the number of errors found...
+ */
+
+ return (errors);
+}
+
+
+/*
* 'check_defaults()' - Check default option keywords in the PPD file.
*/
@@ -2032,6 +2109,76 @@ check_defaults(ppd_file_t *ppd, /* I - PPD file */
/*
+ * 'check_duplex()' - Check duplex keywords in the PPD file.
+ */
+
+static int /* O - Errors found */
+check_duplex(ppd_file_t *ppd, /* I - PPD file */
+ int errors, /* I - Error found */
+ int verbose, /* I - Verbosity level */
+ int warn) /* I - Warnings only? */
+{
+ int i; /* Looping var */
+ ppd_option_t *option; /* PPD option */
+ ppd_choice_t *choice; /* Current choice */
+ const char *prefix; /* Message prefix */
+
+
+ prefix = warn ? " WARN " : "**FAIL**";
+
+ /*
+ * Check for a duplex option, and for standard values...
+ */
+
+ if ((option = ppdFindOption(ppd, "Duplex")) != NULL)
+ {
+ if (!ppdFindChoice(option, "None"))
+ {
+ if (verbose >= 0)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ _cupsLangPrintf(stdout,
+ _(" %s REQUIRED %s does not define "
+ "choice None!\n"
+ " REF: Page 122, section 5.17\n"),
+ prefix, option->keyword);
+ }
+
+ if (!warn)
+ errors ++;
+ }
+
+ for (i = option->num_choices, choice = option->choices;
+ i > 0;
+ i --, choice ++)
+ if (strcmp(choice->choice, "None") &&
+ strcmp(choice->choice, "DuplexNoTumble") &&
+ strcmp(choice->choice, "DuplexTumble") &&
+ strcmp(choice->choice, "SimplexTumble"))
+ {
+ if (verbose >= 0)
+ {
+ if (!warn && !errors && !verbose)
+ _cupsLangPuts(stdout, _(" FAIL\n"));
+
+ _cupsLangPrintf(stdout,
+ _(" %s Bad %s choice %s!\n"
+ " REF: Page 122, section 5.17\n"),
+ prefix, option->keyword, choice->choice);
+ }
+
+ if (!warn)
+ errors ++;
+ }
+ }
+
+ return (errors);
+}
+
+
+/*
* 'check_filters()' - Check filters in the PPD file.
*/
@@ -2071,7 +2218,7 @@ check_filters(ppd_file_t *ppd, /* I - PPD file */
if (!warn)
errors ++;
}
- else
+ else if (strcmp(program, "-"))
{
if (program[0] == '/')
snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
@@ -2122,7 +2269,7 @@ check_filters(ppd_file_t *ppd, /* I - PPD file */
if (!warn)
errors ++;
}
- else
+ else if (strcmp(program, "-"))
{
if (program[0] == '/')
snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
@@ -2310,6 +2457,7 @@ check_translations(ppd_file_t *ppd, /* I - PPD file */
ppd_cparam_t *cparam; /* Custom parameter */
char ll[3]; /* Base language */
const char *prefix; /* WARN/FAIL prefix */
+ const char *text; /* Pointer into UI text */
prefix = warn ? " WARN " : "**FAIL**";
@@ -2397,6 +2545,22 @@ check_translations(ppd_file_t *ppd, /* I - PPD file */
for (j = 0; j < option->num_choices; j ++)
{
+ /*
+ * First see if this choice is a number; if so, don't require
+ * translation...
+ */
+
+ for (text = option->choices[j].text; *text; text ++)
+ if (!strchr("0123456789-+.", *text))
+ break;
+
+ if (!*text)
+ continue;
+
+ /*
+ * Check custom choices differently...
+ */
+
if (!strcasecmp(option->choices[j].choice, "Custom") &&
(coption = ppdFindCustomOption(ppd,
option->keyword)) != NULL)
@@ -2725,7 +2889,8 @@ usage(void)
"Options:\n"
"\n"
" -R root-directory Set alternate root\n"
- " -W {all,none,constraints,defaults,filters,translations}\n"
+ " -W {all,none,constraints,defaults,duplex,filters,"
+ "translations}\n"
" Issue warnings instead of errors\n"
" -q Run silently\n"
" -r Use 'relaxed' open mode\n"
diff --git a/systemv/lpinfo.c b/systemv/lpinfo.c
index bd7fb0311..3e7cc1c6e 100644
--- a/systemv/lpinfo.c
+++ b/systemv/lpinfo.c
@@ -40,7 +40,8 @@
static void device_cb(const char *device_clas, const char *device_id,
const char *device_info,
const char *device_make_and_model,
- const char *device_uri, void *user_data);
+ const char *device_uri, const char *device_location,
+ void *user_data);
static int show_devices(http_t *, int);
static int show_models(http_t *, int);
@@ -173,6 +174,7 @@ device_cb(
const char *device_info, /* I - device-info string */
const char *device_make_and_model, /* I - device-make-and-model string */
const char *device_uri, /* I - device-uri string */
+ const char *device_location, /* I - device-location string */
void *user_data) /* I - User data */
{
int *long_status; /* Show verbose info? */
@@ -191,9 +193,10 @@ device_cb(
" class = %s\n"
" info = %s\n"
" make-and-model = %s\n"
- " device-id = %s\n"),
+ " device-id = %s\n"
+ " location = %s\n"),
device_uri, device_class, device_info,
- device_make_and_model, device_id);
+ device_make_and_model, device_id, device_location);
}
else
_cupsLangPrintf(stdout, "%s %s\n", device_class, device_uri);
diff --git a/templates/option-pickone.tmpl b/templates/option-pickone.tmpl
index 08342d06e..a2ce9d8c8 100644
--- a/templates/option-pickone.tmpl
+++ b/templates/option-pickone.tmpl
@@ -1,6 +1,18 @@
<TR>
<TH CLASS="label"{conflicted=1? CLASS="conflict":}><A NAME="{keyword}">{keytext}</A>:</TH>
-<TD><SELECT NAME="{keyword}">
+<TD><SELECT NAME="{keyword}" ID="select-{keyword}" ONCHANGE="update_paramtable('{keyword}')">
{[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
-</SELECT></TD>
+</SELECT>
+{iscustom=1?<TABLE NAME="paramtable" id="{keyword}-params">{[params]
+<TR><TH CLASS="sublabel">{paramtext}:</TH>
+<TD>{params=Units?<SELECT NAME="{keyword}.{params}">
+<OPTION VALUE="pt"{paramvalue=pt? SELECTED:}>Points</OPTION>
+<OPTION VALUE="mm"{paramvalue=mm? SELECTED:}>Millimeters</OPTION>
+<OPTION VALUE="cm"{paramvalue=cm? SELECTED:}>Centimeters</OPTION>
+<OPTION VALUE="in"{paramvalue=in? SELECTED:}>Inches</OPTION>
+<OPTION VALUE="ft"{paramvalue=ft? SELECTED:}>Feet</OPTION>
+<OPTION VALUE="m"{paramvalue=m? SELECTED:}>Meters</OPTION>
+</SELECT>:<INPUT TYPE="{inputtype}" NAME="{keyword}.{params}" VALUE="{paramvalue}">}</TD></TR>
+}</TABLE>
+</TD>:}
</TR>
diff --git a/templates/set-printer-options-header.tmpl b/templates/set-printer-options-header.tmpl
index 864f9f0ce..56d2bb766 100644
--- a/templates/set-printer-options-header.tmpl
+++ b/templates/set-printer-options-header.tmpl
@@ -1,3 +1,16 @@
<FORM METHOD="POST" ACTION="/admin">
<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+
+<SCRIPT TYPE="text/javascript"><!--
+function update_paramtable(option)
+{
+ var cb = document.getElementById("select-" + option)
+ var paramstable = document.getElementById(option + "-params");
+ if (cb.value == "Custom")
+ paramstable.style.display = "table";
+ else
+ paramstable.style.display = "none";
+}
+--></SCRIPT>
+
diff --git a/templates/set-printer-options-trailer.tmpl b/templates/set-printer-options-trailer.tmpl
index a3d1e1ffa..ac07cc9e1 100644
--- a/templates/set-printer-options-trailer.tmpl
+++ b/templates/set-printer-options-trailer.tmpl
@@ -1 +1,12 @@
+<SCRIPT TYPE="text/javascript"><!--
+// Hide custom options parameters for browsers that understand Javascript
+var paramtables = document.getElementsByName("paramtable");
+for (var i = 0; i < paramtables.length; i++)
+{
+ var opt = paramtables[i].id.substr(0, paramtables[i].id.lastIndexOf("-"));
+ var cb = document.getElementById("select-" + opt);
+ if (cb.value != "Custom")
+ paramtables[i].style.display = "none";
+}
+--></SCRIPT>
</FORM>