summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt12
-rw-r--r--backend/dnssd.c94
-rw-r--r--backend/serial.c63
-rw-r--r--cups/cups.h2
-rw-r--r--cups/debug.h12
-rw-r--r--cups/dest.c263
-rw-r--r--cups/globals.h1
-rw-r--r--cups/http-private.h1
-rw-r--r--cups/http-support.c80
-rw-r--r--cups/http.c211
-rw-r--r--cups/libcups.exp2
-rw-r--r--cups/request.c22
-rw-r--r--cups/testhttp.c2
-rw-r--r--cups/util.c12
-rw-r--r--doc/de/index.html.in107
-rw-r--r--doc/help/spec-ipp.html21
-rw-r--r--ppdc/Dependencies208
-rw-r--r--ppdc/Makefile16
-rw-r--r--ppdc/genstrings.cxx2
-rw-r--r--ppdc/ppdc-array.cxx2
-rw-r--r--ppdc/ppdc-attr.cxx2
-rw-r--r--ppdc/ppdc-catalog.cxx3
-rw-r--r--ppdc/ppdc-choice.cxx2
-rw-r--r--ppdc/ppdc-constraint.cxx2
-rw-r--r--ppdc/ppdc-driver.cxx2
-rw-r--r--ppdc/ppdc-file.cxx2
-rw-r--r--ppdc/ppdc-filter.cxx2
-rw-r--r--ppdc/ppdc-font.cxx2
-rw-r--r--ppdc/ppdc-group.cxx2
-rw-r--r--ppdc/ppdc-import.cxx2
-rw-r--r--ppdc/ppdc-mediasize.cxx2
-rw-r--r--ppdc/ppdc-message.cxx2
-rw-r--r--ppdc/ppdc-option.cxx2
-rw-r--r--ppdc/ppdc-private.h41
-rw-r--r--ppdc/ppdc-profile.cxx2
-rw-r--r--ppdc/ppdc-shared.cxx10
-rw-r--r--ppdc/ppdc-source.cxx2
-rw-r--r--ppdc/ppdc-string.cxx2
-rw-r--r--ppdc/ppdc-variable.cxx2
-rw-r--r--ppdc/ppdc.cxx3
-rw-r--r--ppdc/ppdc.h19
-rw-r--r--ppdc/ppdhtml.cxx3
-rw-r--r--ppdc/ppdi.cxx3
-rw-r--r--ppdc/ppdpo.cxx3
-rw-r--r--ppdc/sample.drv19
-rw-r--r--ppdc/testcatalog.cxx2
-rw-r--r--scheduler/client.c44
-rw-r--r--scheduler/cupsd.h2
-rw-r--r--scheduler/dirsvc.c70
-rw-r--r--scheduler/ipp.c2
-rw-r--r--scheduler/job.c15
-rw-r--r--scheduler/printers.c78
-rw-r--r--scheduler/process.c30
-rw-r--r--scheduler/subscriptions.c2
-rw-r--r--templates/de/add-class.tmpl39
-rw-r--r--templates/de/add-printer.tmpl42
-rw-r--r--templates/de/add-rss-subscription.tmpl43
-rw-r--r--templates/de/admin.tmpl109
-rw-r--r--templates/de/choose-device.tmpl53
-rw-r--r--templates/de/choose-make.tmpl63
-rw-r--r--templates/de/choose-model.tmpl59
-rw-r--r--templates/de/choose-serial.tmpl51
-rw-r--r--templates/de/choose-uri.tmpl43
-rw-r--r--templates/de/class-added.tmpl8
-rw-r--r--templates/de/class-confirm.tmpl10
-rw-r--r--templates/de/class-deleted.tmpl7
-rw-r--r--templates/de/class-jobs-header.tmpl3
-rw-r--r--templates/de/class-modified.tmpl8
-rw-r--r--templates/de/class.tmpl41
-rw-r--r--templates/de/classes-header.tmpl1
-rw-r--r--templates/de/classes.tmpl11
-rw-r--r--templates/de/command.tmpl12
-rw-r--r--templates/de/edit-config.tmpl24
-rw-r--r--templates/de/error-op.tmpl9
-rw-r--r--templates/de/error.tmpl9
-rw-r--r--templates/de/header.tmpl.in29
-rw-r--r--templates/de/help-header.tmpl51
-rw-r--r--templates/de/help-printable.tmpl11
-rw-r--r--templates/de/help-trailer.tmpl1
-rw-r--r--templates/de/job-cancel.tmpl7
-rw-r--r--templates/de/job-hold.tmpl7
-rw-r--r--templates/de/job-move.tmpl26
-rw-r--r--templates/de/job-moved.tmpl8
-rw-r--r--templates/de/job-release.tmpl7
-rw-r--r--templates/de/job-restart.tmpl7
-rw-r--r--templates/de/jobs-header.tmpl5
-rw-r--r--templates/de/jobs.tmpl37
-rw-r--r--templates/de/list-available-printers.tmpl11
-rw-r--r--templates/de/modify-class.tmpl32
-rw-r--r--templates/de/modify-printer.tmpl37
-rw-r--r--templates/de/norestart.tmpl8
-rw-r--r--templates/de/option-boolean.tmpl6
-rw-r--r--templates/de/option-conflict.tmpl7
-rw-r--r--templates/de/option-header.tmpl5
-rw-r--r--templates/de/option-pickmany.tmpl6
-rw-r--r--templates/de/option-pickone.tmpl18
-rw-r--r--templates/de/option-trailer.tmpl5
-rw-r--r--templates/de/pager.tmpl6
-rw-r--r--templates/de/printer-accept.tmpl9
-rw-r--r--templates/de/printer-added.tmpl8
-rw-r--r--templates/de/printer-configured.tmpl8
-rw-r--r--templates/de/printer-confirm.tmpl10
-rw-r--r--templates/de/printer-default.tmpl13
-rw-r--r--templates/de/printer-deleted.tmpl7
-rw-r--r--templates/de/printer-jobs-header.tmpl3
-rw-r--r--templates/de/printer-modified.tmpl8
-rw-r--r--templates/de/printer-purge.tmpl9
-rw-r--r--templates/de/printer-reject.tmpl9
-rw-r--r--templates/de/printer-start.tmpl9
-rw-r--r--templates/de/printer-stop.tmpl9
-rw-r--r--templates/de/printer.tmpl45
-rw-r--r--templates/de/printers-header.tmpl1
-rw-r--r--templates/de/printers.tmpl11
-rw-r--r--templates/de/restart.tmpl8
-rw-r--r--templates/de/samba-export.tmpl54
-rw-r--r--templates/de/samba-exported.tmpl1
-rw-r--r--templates/de/search.tmpl10
-rw-r--r--templates/de/set-printer-options-header.tmpl25
-rw-r--r--templates/de/set-printer-options-trailer.tmpl16
-rw-r--r--templates/de/subscription-added.tmpl5
-rw-r--r--templates/de/subscription-canceled.tmpl5
-rw-r--r--templates/de/test-page.tmpl8
-rw-r--r--templates/de/trailer.tmpl8
-rw-r--r--templates/de/users.tmpl29
124 files changed, 2264 insertions, 560 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 928166abf..ff69828d0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,9 +1,15 @@
-CHANGES.txt - 2009-03-23
+CHANGES.txt - 2009-04-03
------------------------
CHANGES IN CUPS V1.4b3
- Documentation fixes (STR #3044, STR #3057)
+ - Added complete localizations for German, Japanese, Polish, and
+ Russian and partial localizations for Chinese, Danish, Finnish,
+ French, Italian, Korean, Norwegian, Portuguese, and Swedish
+ (STR #3096, STR #3098, STR #3109, STR #3111, STR #3141)
+ - cupsWriteRequestData() flushed the output buffer unnecessarily,
+ causing reduced performance in some situations.
- If a CGI process died before sending its MIME headers, the request
would hang on the client.
- The printer/class/job search feature on the web interface did not
@@ -21,10 +27,6 @@ CHANGES IN CUPS V1.4b3
devices (STR #3108)
- The cupsSideChannelSNMP* functions did not work.
- The scheduler could consume 100% CPU when jobs were canceled.
- - Added complete localizations for Japanese, Polish, and Russian and
- partial localizations for Chinese, Danish, German, Finnish, French,
- Italian, Korean, Norwegian, Portuguese, and Swedish (STR #3096,
- STR #3098, STR #3109, STR #3111)
- Clicking on "Select Another Make/Manufacturer" in the web interface
incorrectly added the printer (STR #3095)
- The scheduler no longer uses programs with insecure file
diff --git a/backend/dnssd.c b/backend/dnssd.c
index 47a8b608e..be08ddd7a 100644
--- a/backend/dnssd.c
+++ b/backend/dnssd.c
@@ -23,6 +23,7 @@
* resolved service name.
* get_device() - Create or update a device.
* query_callback() - Process query data.
+ * sigterm_handler() - Handle termination signals...
* unquote() - Unquote a name string.
*/
@@ -65,6 +66,14 @@ typedef struct
/*
+ * Local globals...
+ */
+
+static int job_canceled = 0;
+ /* Set to 1 on SIGTERM */
+
+
+/*
* Local functions...
*/
@@ -97,6 +106,7 @@ static void query_callback(DNSServiceRef sdRef,
uint16_t rrclass, uint16_t rdlen,
const void *rdata, uint32_t ttl,
void *context);
+static void sigterm_handler(int sig);
static void unquote(char *dst, const char *src, size_t dstsize);
@@ -126,14 +136,33 @@ main(int argc, /* I - Number of command-line args */
cups_array_t *devices; /* Device array */
cups_device_t *device; /* Current device */
char uriName[1024]; /* Unquoted fullName for URI */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
/*
- * Check command-line...
+ * Don't buffer stderr, and catch SIGTERM...
*/
setbuf(stderr, NULL);
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, sigterm_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, sigterm_handler);
+#else
+ signal(SIGTERM, sigterm_handler);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
if (argc >= 6)
exec_backend(argv);
else if (argc != 1)
@@ -221,7 +250,7 @@ main(int argc, /* I - Number of command-line args */
* Loop until we are killed...
*/
- for (;;)
+ while (!job_canceled)
{
FD_ZERO(&input);
FD_SET(fd, &input);
@@ -250,9 +279,6 @@ main(int argc, /* I - Number of command-line args */
cups_device_t *best; /* Best matching device */
char device_uri[1024]; /* Device URI */
int count; /* Number of queries */
- static const char * const schemes[] =
- { "lpd", "ipp", "ipp", "socket", "riousbprint" };
- /* URI schemes for devices */
for (device = (cups_device_t *)cupsArrayFirst(devices),
@@ -304,7 +330,7 @@ main(int argc, /* I - Number of command-line args */
unquote(uriName, best->fullName, sizeof(uriName));
httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri),
- schemes[best->type], NULL, uriName, 0,
+ "dnssd", NULL, uriName, 0,
best->cups_shared ? "/cups" : "/");
cupsBackendReport("network", device_uri, best->make_and_model,
@@ -328,7 +354,7 @@ main(int argc, /* I - Number of command-line args */
unquote(uriName, best->fullName, sizeof(uriName));
httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri),
- schemes[best->type], NULL, uriName, 0,
+ "dnssd", NULL, uriName, 0,
best->cups_shared ? "/cups" : "/");
cupsBackendReport("network", device_uri, best->make_and_model,
@@ -337,6 +363,8 @@ main(int argc, /* I - Number of command-line args */
}
}
}
+
+ return (CUPS_BACKEND_OK);
}
@@ -438,12 +466,7 @@ static int /* O - Result of comparison */
compare_devices(cups_device_t *a, /* I - First device */
cups_device_t *b) /* I - Second device */
{
- int result = strcmp(a->name, b->name);
-
- if (result)
- return (result);
- else
- return (strcmp(a->domain, b->domain));
+ return (strcmp(a->name, b->name));
}
@@ -467,7 +490,12 @@ exec_backend(char **argv) /* I - Command-line arguments */
*/
if ((resolved_uri = cupsBackendDeviceURI(argv)) == NULL)
- exit(CUPS_BACKEND_FAILED);
+ {
+ if (job_canceled)
+ exit(CUPS_BACKEND_OK);
+ else
+ exit(CUPS_BACKEND_FAILED);
+ }
/*
* Extract the scheme from the URI...
@@ -487,7 +515,7 @@ exec_backend(char **argv) /* I - Command-line arguments */
snprintf(filename, sizeof(filename), "%s/backend/%s", cups_serverbin, scheme);
/*
- * Overwrite the device URIs and run the new backend...
+ * Overwrite the device URI and run the new backend...
*/
setenv("DEVICE_URI", resolved_uri, 1);
@@ -524,8 +552,7 @@ get_device(cups_array_t *devices, /* I - Device array */
* See if this is a new device...
*/
- key.name = (char *)serviceName;
- key.domain = (char *)replyDomain;
+ key.name = (char *)serviceName;
if (!strcmp(regtype, "_ipp._tcp.") ||
!strcmp(regtype, "_ipp-tls._tcp."))
@@ -542,11 +569,29 @@ get_device(cups_array_t *devices, /* I - Device array */
for (device = cupsArrayFind(devices, &key);
device;
device = cupsArrayNext(devices))
- if (strcasecmp(device->name, key.name) ||
- strcasecmp(device->domain, key.domain))
+ if (strcasecmp(device->name, key.name))
break;
else if (device->type == key.type)
+ {
+ if (!strcasecmp(device->domain, "local.") &&
+ strcasecmp(device->domain, replyDomain))
+ {
+ /*
+ * Update the .local listing to use the "global" domain name instead.
+ * The backend will try local lookups first, then the global domain name.
+ */
+
+ free(device->domain);
+ device->domain = strdup(replyDomain);
+
+ DNSServiceConstructFullName(fullName, device->name, regtype,
+ replyDomain);
+ free(device->fullName);
+ device->fullName = strdup(fullName);
+ }
+
return (device);
+ }
/*
* Yes, add the device...
@@ -818,6 +863,17 @@ query_callback(
/*
+ * 'sigterm_handler()' - Handle termination signals...
+ */
+
+static void
+sigterm_handler(int sig) /* I - Signal number (unused) */
+{
+ job_canceled = 1;
+}
+
+
+/*
* 'unquote()' - Unquote a name string.
*/
diff --git a/backend/serial.c b/backend/serial.c
index 81d92de8d..803df0cb6 100644
--- a/backend/serial.c
+++ b/backend/serial.c
@@ -3,7 +3,7 @@
*
* Serial port backend for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2009 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -1211,38 +1211,51 @@ list_devices(void)
{
CFTypeRef serialNameAsCFString;
CFTypeRef bsdPathAsCFString;
+ CFTypeRef hiddenVal;
char serialName[128];
char bsdPath[1024];
Boolean result;
- serialNameAsCFString =
- IORegistryEntryCreateCFProperty(serialService,
- CFSTR(kIOTTYDeviceKey),
- kCFAllocatorDefault, 0);
- if (serialNameAsCFString)
+ /* Check if hidden... */
+ hiddenVal = IORegistryEntrySearchCFProperty(serialService,
+ kIOServicePlane,
+ CFSTR("HiddenPort"),
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively |
+ kIORegistryIterateParents);
+ if (hiddenVal)
+ CFRelease(hiddenVal); /* This interface should not be used */
+ else
{
- result = CFStringGetCString(serialNameAsCFString, serialName,
- sizeof(serialName),
- kCFStringEncodingASCII);
- CFRelease(serialNameAsCFString);
-
- if (result)
+ serialNameAsCFString =
+ IORegistryEntryCreateCFProperty(serialService,
+ CFSTR(kIOTTYDeviceKey),
+ kCFAllocatorDefault, 0);
+ if (serialNameAsCFString)
{
- bsdPathAsCFString =
- IORegistryEntryCreateCFProperty(serialService,
- CFSTR(kIOCalloutDeviceKey),
- kCFAllocatorDefault, 0);
- if (bsdPathAsCFString)
+ result = CFStringGetCString(serialNameAsCFString, serialName,
+ sizeof(serialName),
+ kCFStringEncodingASCII);
+ CFRelease(serialNameAsCFString);
+
+ if (result)
{
- result = CFStringGetCString(bsdPathAsCFString, bsdPath,
- sizeof(bsdPath),
- kCFStringEncodingASCII);
- CFRelease(bsdPathAsCFString);
-
- if (result)
- printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
- bsdPath, serialName);
+ bsdPathAsCFString =
+ IORegistryEntryCreateCFProperty(serialService,
+ CFSTR(kIOCalloutDeviceKey),
+ kCFAllocatorDefault, 0);
+ if (bsdPathAsCFString)
+ {
+ result = CFStringGetCString(bsdPathAsCFString, bsdPath,
+ sizeof(bsdPath),
+ kCFStringEncodingASCII);
+ CFRelease(bsdPathAsCFString);
+
+ if (result)
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
+ bsdPath, serialName);
+ }
}
}
}
diff --git a/cups/cups.h b/cups/cups.h
index 8742cf29d..8836aab94 100644
--- a/cups/cups.h
+++ b/cups/cups.h
@@ -288,8 +288,8 @@ extern int cupsGetConflicts(ppd_file_t *ppd, const char *option,
cups_option_t **options)
_CUPS_API_1_4;
extern ipp_status_t cupsGetDevices(http_t *http, int timeout,
- const char *exclude_schemes,
const char *include_schemes,
+ const char *exclude_schemes,
cups_device_cb_t callback,
void *user_data) _CUPS_API_1_4;
extern cups_dest_t *cupsGetNamedDest(http_t *http, const char *name,
diff --git a/cups/debug.h b/cups/debug.h
index 4efd1619c..0d81b46cb 100644
--- a/cups/debug.h
+++ b/cups/debug.h
@@ -19,6 +19,15 @@
# define _CUPS_DEBUG_H_
/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+
+/*
* The debug macros are used if you compile with DEBUG defined.
*
* Usage:
@@ -50,6 +59,9 @@ __attribute__ ((__format__ (__printf__, 1, 2)))
;
extern void _cups_debug_puts(const char *s);
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
#endif /* !_CUPS_DEBUG_H_ */
diff --git a/cups/dest.c b/cups/dest.c
index 9417bddc1..2886a0478 100644
--- a/cups/dest.c
+++ b/cups/dest.c
@@ -83,7 +83,6 @@
#ifdef __APPLE__
static CFArrayRef appleCopyLocations(void);
static CFStringRef appleCopyNetwork(void);
-static char *appleGetDefault(char *name, int namesize);
static char *appleGetPaperSize(char *name, int namesize);
static CFStringRef appleGetPrinter(CFArrayRef locations, CFStringRef network,
CFIndex *locindex);
@@ -99,8 +98,8 @@ static int cups_find_dest(const char *name, const char *instance,
static char *cups_get_default(const char *filename, char *namebuf,
size_t namesize, const char **instance);
static int cups_get_dests(const char *filename, const char *match_name,
- const char *match_inst, int num_dests,
- cups_dest_t **dests);
+ const char *match_inst, int user_default_set,
+ int num_dests, cups_dest_t **dests);
static int cups_get_sdests(http_t *http, ipp_op_t op, const char *name,
int num_dests, cups_dest_t **dests);
static char *cups_make_string(ipp_attribute_t *attr, char *buffer,
@@ -302,7 +301,8 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
char filename[1024]; /* Local ~/.cups/lpoptions file */
const char *defprinter; /* Default printer */
char name[1024], /* Copy of printer name */
- *instance; /* Pointer to instance name */
+ *instance, /* Pointer to instance name */
+ *user_default; /* User default printer */
int num_reals; /* Number of real queues */
cups_dest_t *reals; /* Real queues */
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
@@ -362,22 +362,20 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* Grab the default destination...
*/
-#ifdef __APPLE__
- if ((defprinter = appleGetDefault(name, sizeof(name))) == NULL)
-#endif /* __APPLE__ */
- defprinter = cupsGetDefault2(http);
+ if ((user_default = _cupsUserDefault(name, sizeof(name))) != NULL)
+ defprinter = name;
+ else if ((defprinter = cupsGetDefault2(http)) != NULL)
+ {
+ strlcpy(name, defprinter, sizeof(name));
+ defprinter = name;
+ }
if (defprinter)
{
/*
- * Grab printer and instance name...
+ * Separate printer and instance name...
*/
-#ifdef __APPLE__
- if (name != defprinter)
-#endif /* __APPLE__ */
- strlcpy(name, defprinter, sizeof(name));
-
if ((instance = strchr(name, '/')) != NULL)
*instance++ = '\0';
@@ -389,21 +387,15 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
dest->is_default = 1;
}
else
- {
- /*
- * This initialization of "instance" is unnecessary, but avoids a
- * compiler warning...
- */
-
instance = NULL;
- }
/*
* Load the /etc/cups/lpoptions and ~/.cups/lpoptions files...
*/
snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
- num_dests = cups_get_dests(filename, NULL, NULL, num_dests, dests);
+ num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL,
+ num_dests, dests);
if ((home = getenv("HOME")) != NULL)
{
@@ -411,7 +403,8 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
if (access(filename, 0))
snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
- num_dests = cups_get_dests(filename, NULL, NULL, num_dests, dests);
+ num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL,
+ num_dests, dests);
}
/*
@@ -497,6 +490,7 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
char filename[1024], /* Path to lpoptions */
defname[256]; /* Default printer name */
const char *home = getenv("HOME"); /* Home directory */
+ int set_as_default = 0; /* Set returned destination as default */
ipp_op_t op = IPP_GET_PRINTER_ATTRIBUTES;
/* IPP operation to get server ops */
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
@@ -508,9 +502,8 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
if (!name)
{
- if ((name = getenv("LPDEST")) == NULL)
- if ((name = getenv("PRINTER")) != NULL && !strcmp(name, "lp"))
- name = NULL;
+ set_as_default = 1;
+ name = _cupsUserDefault(defname, sizeof(defname));
if (!name && home)
{
@@ -571,12 +564,15 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
if (instance)
dest->instance = _cupsStrAlloc(instance);
+ if (set_as_default)
+ dest->is_default = 1;
+
/*
* Then add local options...
*/
snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
- cups_get_dests(filename, name, instance, 1, &dest);
+ cups_get_dests(filename, name, instance, 1, 1, &dest);
if (home)
{
@@ -585,7 +581,7 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
if (access(filename, 0))
snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
- cups_get_dests(filename, name, instance, 1, &dest);
+ cups_get_dests(filename, name, instance, 1, 1, &dest);
}
/*
@@ -762,7 +758,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* Merge in server defaults...
*/
- num_temps = cups_get_dests(filename, NULL, NULL, num_temps, &temps);
+ num_temps = cups_get_dests(filename, NULL, NULL, 0, num_temps, &temps);
/*
* Point to user defaults...
@@ -938,6 +934,106 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
}
+/*
+ * '_cupsUserDefault()' - Get the user default printer from environment
+ * variables and location information.
+ */
+
+char * /* O - Default printer or NULL */
+_cupsUserDefault(char *name, /* I - Name buffer */
+ size_t namesize) /* I - Size of name buffer */
+{
+ const char *env; /* LPDEST or PRINTER env variable */
+#ifdef __APPLE__
+ CFStringRef network; /* Network location */
+ CFArrayRef locations; /* Location array */
+ CFStringRef locprinter; /* Current printer */
+#endif /* __APPLE__ */
+
+
+ if ((env = getenv("LPDEST")) == NULL)
+ if ((env = getenv("PRINTER")) != NULL && !strcmp(env, "lp"))
+ env = NULL;
+
+ if (env)
+ {
+ strlcpy(name, env, namesize);
+ return (name);
+ }
+
+#ifdef __APPLE__
+ /*
+ * Use location-based defaults if "use last printer" is selected in the
+ * system preferences...
+ */
+
+ if (!appleUseLastPrinter())
+ {
+ DEBUG_puts("_cupsUserDefault: Not using last printer as default...");
+ name[0] = '\0';
+ return (NULL);
+ }
+
+ /*
+ * Get the current location...
+ */
+
+ if ((network = appleCopyNetwork()) == NULL)
+ {
+ DEBUG_puts("_cupsUserDefault: Unable to get current network...");
+ name[0] = '\0';
+ return (NULL);
+ }
+
+# ifdef DEBUG
+ CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8);
+ DEBUG_printf(("_cupsUserDefault: network=\"%s\"\n", name));
+# endif /* DEBUG */
+
+ /*
+ * Lookup the network in the preferences...
+ */
+
+ if ((locations = appleCopyLocations()) == NULL)
+ {
+ /*
+ * Missing or bad location array, so no location-based default...
+ */
+
+ DEBUG_puts("_cupsUserDefault: Missing or bad location history array...");
+
+ CFRelease(network);
+
+ name[0] = '\0';
+ return (NULL);
+ }
+
+ DEBUG_printf(("_cupsUserDefault: Got location, %d entries...\n",
+ (int)CFArrayGetCount(locations)));
+
+ if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL)
+ CFStringGetCString(locprinter, name, namesize, kCFStringEncodingUTF8);
+ else
+ name[0] = '\0';
+
+ CFRelease(network);
+ CFRelease(locations);
+
+ DEBUG_printf(("_cupsUserDefault: Returning \"%s\"...\n", name));
+
+ return (*name ? name : NULL);
+
+#else
+ /*
+ * No location-based defaults on this platform...
+ */
+
+ name[0] = '\0';
+ return (NULL);
+#endif /* __APPLE__ */
+}
+
+
#ifdef __APPLE__
/*
* 'appleCopyLocations()' - Copy the location history array.
@@ -1006,79 +1102,6 @@ appleCopyNetwork(void)
/*
- * 'appleGetDefault()' - Get the default printer for this location.
- */
-
-static char * /* O - Name or NULL if no default */
-appleGetDefault(char *name, /* I - Name buffer */
- int namesize) /* I - Size of name buffer */
-{
- CFStringRef network; /* Network location */
- CFArrayRef locations; /* Location array */
- CFStringRef locprinter; /* Current printer */
-
-
- /*
- * Use location-based defaults if "use last printer" is selected in the
- * system preferences...
- */
-
- if (!appleUseLastPrinter())
- {
- DEBUG_puts("appleGetDefault: Not using last printer as default...");
- return (NULL);
- }
-
- /*
- * Get the current location...
- */
-
- if ((network = appleCopyNetwork()) == NULL)
- {
- DEBUG_puts("appleGetDefault: Unable to get current network...");
- return (NULL);
- }
-
-#ifdef DEBUG
- CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8);
- DEBUG_printf(("appleGetDefault: network=\"%s\"\n", name));
-#endif /* DEBUG */
-
- /*
- * Lookup the network in the preferences...
- */
-
- if ((locations = appleCopyLocations()) == NULL)
- {
- /*
- * Missing or bad location array, so no location-based default...
- */
-
- DEBUG_puts("appleGetDefault: Missing or bad location history array...");
-
- CFRelease(network);
-
- return (NULL);
- }
-
- DEBUG_printf(("appleGetDefault: Got location, %d entries...\n",
- (int)CFArrayGetCount(locations)));
-
- if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL)
- CFStringGetCString(locprinter, name, namesize, kCFStringEncodingUTF8);
- else
- name[0] = '\0';
-
- CFRelease(network);
- CFRelease(locations);
-
- DEBUG_printf(("appleGetDefault: Returning \"%s\"...\n", name));
-
- return (*name ? name : NULL);
-}
-
-
-/*
* 'appleGetPaperSize()' - Get the default paper size.
*/
@@ -1237,6 +1260,7 @@ appleSetDefault(const char *name) /* I - Default printer/class name */
CFPreferencesSetAppValue(kLocationHistoryArrayKey, newlocations,
kPMPrintingPreferences);
CFPreferencesAppSynchronize(kPMPrintingPreferences);
+ notify_post("com.apple.printerPrefsChange");
}
if (newlocations)
@@ -1526,11 +1550,13 @@ cups_get_default(const char *filename, /* I - File to read */
*/
static int /* O - Number of destinations */
-cups_get_dests(const char *filename, /* I - File to read from */
- const char *match_name, /* I - Destination name we want */
- const char *match_inst, /* I - Instance name we want */
- int num_dests, /* I - Number of destinations */
- cups_dest_t **dests) /* IO - Destinations */
+cups_get_dests(
+ const char *filename, /* I - File to read from */
+ const char *match_name, /* I - Destination name we want */
+ const char *match_inst, /* I - Instance name we want */
+ int user_default_set, /* I - User default printer set? */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t **dests) /* IO - Destinations */
{
int i; /* Looping var */
cups_dest_t *dest; /* Current destination */
@@ -1540,13 +1566,12 @@ cups_get_dests(const char *filename, /* I - File to read from */
*name, /* Name of destination/option */
*instance; /* Instance of destination */
int linenum; /* Current line number */
- const char *printer; /* PRINTER or LPDEST */
DEBUG_printf(("cups_get_dests(filename=\"%s\", match_name=\"%s\", "
- "match_inst=\"%s\", num_dests=%d, dests=%p)\n", filename,
- match_name ? match_name : "(null)",
- match_inst ? match_inst : "(null)", num_dests, dests));
+ "match_inst=\"%s\", user_default_set=%d, num_dests=%d, "
+ "dests=%p)\n", filename, match_name, match_inst,
+ user_default_set, num_dests, dests));
/*
* Try to open the file...
@@ -1556,18 +1581,6 @@ cups_get_dests(const char *filename, /* I - File to read from */
return (num_dests);
/*
- * Check environment variables...
- */
-
- if ((printer = getenv("LPDEST")) == NULL)
- if ((printer = getenv("PRINTER")) != NULL)
- if (strcmp(printer, "lp") == 0)
- printer = NULL;
-
- DEBUG_printf(("cups_get_dests: printer=\"%s\"\n",
- printer ? printer : "(null)"));
-
- /*
* Read each printer; each line looks like:
*
* Dest name[/instance] options
@@ -1583,7 +1596,7 @@ cups_get_dests(const char *filename, /* I - File to read from */
*/
DEBUG_printf(("cups_get_dests: linenum=%d line=\"%s\" lineptr=\"%s\"\n",
- linenum, line, lineptr ? lineptr : "(null)"));
+ linenum, line, lineptr));
if ((strcasecmp(line, "dest") && strcasecmp(line, "default")) || !lineptr)
{
@@ -1682,7 +1695,7 @@ cups_get_dests(const char *filename, /* I - File to read from */
* Set this as default if needed...
*/
- if (!printer && !strcasecmp(line, "default"))
+ if (!user_default_set && !strcasecmp(line, "default"))
{
DEBUG_puts("cups_get_dests: Setting as default...");
diff --git a/cups/globals.h b/cups/globals.h
index 9a0a99842..cdf4d1fec 100644
--- a/cups/globals.h
+++ b/cups/globals.h
@@ -145,6 +145,7 @@ extern _cups_globals_t *_cupsGlobals(void);
extern void _cupsSetError(ipp_status_t status, const char *message,
int localize);
extern void _cupsSetHTTPError(http_status_t status);
+extern char *_cupsUserDefault(char *name, size_t namesize);
/*
diff --git a/cups/http-private.h b/cups/http-private.h
index 8ffe5a281..9362e36d7 100644
--- a/cups/http-private.h
+++ b/cups/http-private.h
@@ -268,6 +268,7 @@ extern char *_httpEncodeURI(char *dst, const char *src,
size_t dstsize);
extern const char *_httpResolveURI(const char *uri, char *resolved_uri,
size_t resolved_size, int log);
+extern int _httpWait(http_t *http, int msec, int usessl);
#endif /* !_CUPS_HTTP_PRIVATE_H_ */
/*
diff --git a/cups/http-support.c b/cups/http-support.c
index 342c383b2..c59ecfb50 100644
--- a/cups/http-support.c
+++ b/cups/http-support.c
@@ -52,6 +52,7 @@
#include <stdlib.h>
#ifdef HAVE_DNSSD
# include <dns_sd.h>
+# include <poll.h>
#endif /* HAVE_DNSSD */
@@ -1347,10 +1348,18 @@ _httpResolveURI(
if (strstr(hostname, "._tcp"))
{
#ifdef HAVE_DNSSD
- DNSServiceRef ref; /* DNS-SD service reference */
+ DNSServiceRef ref, /* DNS-SD master service reference */
+ domainref, /* DNS-SD service reference for domain */
+ localref; /* DNS-SD service reference for .local */
+ int domainsent = 0; /* Send the domain resolve? */
char *regtype, /* Pointer to type in hostname */
*domain; /* Pointer to domain in hostname */
_http_uribuf_t uribuf; /* URI buffer */
+ struct pollfd polldata; /* Polling data */
+
+
+ if (logit)
+ fprintf(stderr, "DEBUG: Resolving \"%s\"...\n", hostname);
/*
* Separate the hostname into service name, registration type, and domain...
@@ -1375,10 +1384,6 @@ _httpResolveURI(
return (NULL);
}
- domain = regtype + strlen(regtype) - 1;
- if (domain > regtype && *domain == '.')
- *domain = '\0';
-
for (domain = strchr(regtype, '.');
domain;
domain = strchr(domain + 1, '.'))
@@ -1398,28 +1403,69 @@ _httpResolveURI(
if (logit)
{
fputs("STATE: +connecting-to-device\n", stderr);
- fprintf(stderr, "DEBUG: Resolving %s, regtype=%s, domain=%s...\n",
- hostname, regtype, domain);
+ fprintf(stderr, "DEBUG: Resolving \"%s\", regtype=\"%s\", "
+ "domain=\"local.\"...\n", hostname, regtype);
_cupsLangPuts(stderr, _("INFO: Looking for printer...\n"));
}
- if (DNSServiceResolve(&ref, 0, 0, hostname, regtype, domain,
- resolve_callback,
- &uribuf) == kDNSServiceErr_NoError)
+ uri = NULL;
+
+ if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError)
{
- if (DNSServiceProcessResult(ref) != kDNSServiceErr_NoError &&
- resolved_uri[0])
- uri = NULL;
- else
- uri = resolved_uri;
+ localref = ref;
+ if (DNSServiceResolve(&localref, kDNSServiceFlagsShareConnection, 0,
+ hostname, regtype, "local.", resolve_callback,
+ &uribuf) == kDNSServiceErr_NoError)
+ {
+ if (strcasecmp(domain, "local."))
+ {
+ /*
+ * Wait 2 seconds for a response to the local resolve; if nothing comes
+ * in, do an additional domain resolution...
+ */
+
+ polldata.fd = DNSServiceRefSockFD(ref);
+ polldata.events = POLLIN;
+
+ if (poll(&polldata, 1, 2000) != 1)
+ {
+ /*
+ * OK, send the domain name resolve...
+ */
+
+ if (logit)
+ fprintf(stderr, "DEBUG: Resolving \"%s\", regtype=\"%s\", "
+ "domain=\"%s\"...\n", hostname, regtype, domain);
+
+ domainref = ref;
+ if (DNSServiceResolve(&domainref, kDNSServiceFlagsShareConnection, 0,
+ hostname, regtype, domain, resolve_callback,
+ &uribuf) == kDNSServiceErr_NoError)
+ domainsent = 1;
+ }
+ }
+
+ if (DNSServiceProcessResult(ref) == kDNSServiceErr_NoError)
+ uri = resolved_uri;
+
+ if (domainsent)
+ DNSServiceRefDeallocate(domainref);
+
+ DNSServiceRefDeallocate(localref);
+ }
DNSServiceRefDeallocate(ref);
}
- else
- uri = NULL;
if (logit)
+ {
+ if (uri)
+ fputs("DEBUG: Unable to resolve URI!\n", stderr);
+ else
+ fprintf(stderr, "DEBUG: Resolved as \"%s\"...\n", uri);
+
fputs("STATE: -connecting-to-device\n", stderr);
+ }
#else
/*
diff --git a/cups/http.c b/cups/http.c
index 4d4ef2a7a..eef9973b8 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -3,7 +3,7 @@
*
* HTTP routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2009 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
@@ -21,13 +21,14 @@
*
* _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP connections.
* httpBlocking() - Set blocking/non-blocking behavior on a connection.
- * httpCheck() - Check to see if there is a pending response from
- * the server.
+ * httpCheck() - Check to see if there is a pending response from the
+ * server.
* httpClearCookie() - Clear the cookie value(s).
* httpClearFields() - Clear HTTP request fields.
* httpClose() - Close an HTTP connection...
* httpConnect() - Connect to a HTTP server.
* httpConnectEncrypt() - Connect to a HTTP server using encryption.
+ * _httpCreate() - Create an unconnected HTTP connection.
* httpDelete() - Send a DELETE request to the server.
* httpEncryption() - Set the required encryption on the link.
* httpError() - Get the last error on a connection.
@@ -46,6 +47,7 @@
* content-length or transfer-encoding fields.
* httpGetStatus() - Get the status of the last HTTP request.
* httpGetSubField() - Get a sub-field value.
+ * httpGetSubField2() - Get a sub-field value.
* httpGets() - Get a line of text from a HTTP connection.
* httpHead() - Send a HEAD request to the server.
* httpInitialize() - Initialize the HTTP interface library and set the
@@ -58,14 +60,15 @@
* httpRead2() - Read data from a HTTP connection.
* _httpReadCDSA() - Read function for the CDSA library.
* _httpReadGNUTLS() - Read function for the GNU TLS library.
- * httpReconnect() - Reconnect to a HTTP server...
+ * httpReconnect() - Reconnect to a HTTP server.
* httpSetAuthString() - Set the current authorization string.
* httpSetCookie() - Set the cookie value(s)...
* httpSetExpect() - Set the Expect: header in a request.
* httpSetField() - Set the value of an HTTP header.
- * httpSetLength() - Set the content-length and transfer-encoding.
+ * httpSetLength() - Set the content-length and content-encoding.
* httpTrace() - Send an TRACE request to the server.
* httpUpdate() - Update the current HTTP state for incoming data.
+ * _httpWait() - Wait for data available on a connection (no flush).
* httpWait() - Wait for data available on a connection.
* httpWrite() - Write data to a HTTP connection.
* httpWrite2() - Write data to a HTTP connection.
@@ -82,11 +85,11 @@
* http_read_ssl() - Read from a SSL/TLS connection.
* http_send() - Send a request with all fields and the trailing
* blank line.
- * http_setup_ssl() - Set up SSL/TLS on a connection.
+ * http_setup_ssl() - Set up SSL/TLS support on a connection.
* http_shutdown_ssl() - Shut down SSL/TLS on a connection.
* http_upgrade() - Force upgrade to TLS encryption.
- * http_wait() - Wait for data available on a connection.
- * http_write() - Write data to a connection.
+ * http_write() - Write a buffer to a HTTP connection.
+ * http_write_chunk() - Write a chunked buffer.
* http_write_ssl() - Write to a SSL/TLS connection.
*/
@@ -131,7 +134,6 @@ static void http_debug_hex(const char *prefix, const char *buffer,
static http_field_t http_field(const char *name);
static int http_send(http_t *http, http_state_t request,
const char *uri);
-static int http_wait(http_t *http, int msec, int usessl);
static int http_write(http_t *http, const char *buffer,
int length);
static int http_write_chunk(http_t *http, const char *buffer,
@@ -1012,7 +1014,7 @@ httpGets(char *line, /* I - Line to read into */
* No newline; see if there is more data to be read...
*/
- if (!http->blocking && !http_wait(http, 10000, 1))
+ if (!http->blocking && !_httpWait(http, 10000, 1))
{
DEBUG_puts("httpGets: Timed out!");
#ifdef WIN32
@@ -1539,7 +1541,7 @@ _httpReadCDSA(
* Make sure we have data before we read...
*/
- if (!http_wait(http, 10000, 0))
+ if (!_httpWait(http, 10000, 0))
{
http->error = ETIMEDOUT;
return (-1);
@@ -1600,7 +1602,7 @@ _httpReadGNUTLS(
* Make sure we have data before we read...
*/
- if (!http_wait(http, 10000, 0))
+ if (!_httpWait(http, 10000, 0))
{
http->error = ETIMEDOUT;
return (-1);
@@ -2075,6 +2077,95 @@ httpUpdate(http_t *http) /* I - Connection to server */
/*
+ * '_httpWait()' - Wait for data available on a connection (no flush).
+ */
+
+int /* O - 1 if data is available, 0 otherwise */
+_httpWait(http_t *http, /* I - Connection to server */
+ int msec, /* I - Milliseconds to wait */
+ int usessl) /* I - Use SSL context? */
+{
+#ifdef HAVE_POLL
+ struct pollfd pfd; /* Polled file descriptor */
+#else
+ fd_set input_set; /* select() input set */
+ struct timeval timeout; /* Timeout */
+#endif /* HAVE_POLL */
+ int nfds; /* Result from select()/poll() */
+
+
+ DEBUG_printf(("_httpWait(http=%p, msec=%d, usessl=%d)\n", http, msec, usessl));
+
+ if (http->fd < 0)
+ return (0);
+
+ /*
+ * Check the SSL/TLS buffers for data first...
+ */
+
+#ifdef HAVE_SSL
+ if (http->tls && usessl)
+ {
+# ifdef HAVE_LIBSSL
+ if (SSL_pending((SSL *)(http->tls)))
+ return (1);
+# elif defined(HAVE_GNUTLS)
+ if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
+ return (1);
+# elif defined(HAVE_CDSASSL)
+ size_t bytes; /* Bytes that are available */
+
+ if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) &&
+ bytes > 0)
+ return (1);
+# endif /* HAVE_LIBSSL */
+ }
+#endif /* HAVE_SSL */
+
+ /*
+ * Then try doing a select() or poll() to poll the socket...
+ */
+
+#ifdef HAVE_POLL
+ pfd.fd = http->fd;
+ pfd.events = POLLIN;
+
+ while ((nfds = poll(&pfd, 1, msec)) < 0 && errno == EINTR);
+
+#else
+ do
+ {
+ FD_ZERO(&input_set);
+ FD_SET(http->fd, &input_set);
+
+ DEBUG_printf(("_httpWait: msec=%d, http->fd=%d\n", msec, http->fd));
+
+ if (msec >= 0)
+ {
+ timeout.tv_sec = msec / 1000;
+ timeout.tv_usec = (msec % 1000) * 1000;
+
+ nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
+ }
+ else
+ nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
+
+ DEBUG_printf(("_httpWait: select() returned %d...\n", nfds));
+ }
+# ifdef WIN32
+ while (nfds < 0 && WSAGetLastError() == WSAEINTR);
+# else
+ while (nfds < 0 && errno == EINTR);
+# endif /* WIN32 */
+#endif /* HAVE_POLL */
+
+ DEBUG_printf(("_httpWait: returning with nfds=%d...\n", nfds));
+
+ return (nfds > 0);
+}
+
+
+/*
* 'httpWait()' - Wait for data available on a connection.
*
* @since CUPS 1.1.19/Mac OS X 10.3@
@@ -2108,7 +2199,7 @@ httpWait(http_t *http, /* I - Connection to server */
* If not, check the SSL/TLS buffers and do a select() on the connection...
*/
- return (http_wait(http, msec, 1));
+ return (_httpWait(http, msec, 1));
}
@@ -2174,7 +2265,8 @@ httpWrite2(http_t *http, /* I - Connection to server */
httpFlushWrite(http);
}
- if ((length + http->wused) <= sizeof(http->wbuffer))
+ if ((length + http->wused) <= sizeof(http->wbuffer) &&
+ length < sizeof(http->wbuffer))
{
/*
* Write to buffer...
@@ -2436,7 +2528,7 @@ http_bio_read(BIO *h, /* I - BIO data */
* Make sure we have data before we read...
*/
- if (!http_wait(http, 10000, 0))
+ if (!_httpWait(http, 10000, 0))
{
#ifdef WIN32
http->error = WSAETIMEDOUT;
@@ -3038,95 +3130,6 @@ http_upgrade(http_t *http) /* I - Connection to server */
/*
- * 'http_wait()' - Wait for data available on a connection.
- */
-
-static int /* O - 1 if data is available, 0 otherwise */
-http_wait(http_t *http, /* I - Connection to server */
- int msec, /* I - Milliseconds to wait */
- int usessl) /* I - Use SSL context? */
-{
-#ifdef HAVE_POLL
- struct pollfd pfd; /* Polled file descriptor */
-#else
- fd_set input_set; /* select() input set */
- struct timeval timeout; /* Timeout */
-#endif /* HAVE_POLL */
- int nfds; /* Result from select()/poll() */
-
-
- DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
-
- if (http->fd < 0)
- return (0);
-
- /*
- * Check the SSL/TLS buffers for data first...
- */
-
-#ifdef HAVE_SSL
- if (http->tls && usessl)
- {
-# ifdef HAVE_LIBSSL
- if (SSL_pending((SSL *)(http->tls)))
- return (1);
-# elif defined(HAVE_GNUTLS)
- if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
- return (1);
-# elif defined(HAVE_CDSASSL)
- size_t bytes; /* Bytes that are available */
-
- if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) &&
- bytes > 0)
- return (1);
-# endif /* HAVE_LIBSSL */
- }
-#endif /* HAVE_SSL */
-
- /*
- * Then try doing a select() or poll() to poll the socket...
- */
-
-#ifdef HAVE_POLL
- pfd.fd = http->fd;
- pfd.events = POLLIN;
-
- while ((nfds = poll(&pfd, 1, msec)) < 0 && errno == EINTR);
-
-#else
- do
- {
- FD_ZERO(&input_set);
- FD_SET(http->fd, &input_set);
-
- DEBUG_printf(("http_wait: msec=%d, http->fd=%d\n", msec, http->fd));
-
- if (msec >= 0)
- {
- timeout.tv_sec = msec / 1000;
- timeout.tv_usec = (msec % 1000) * 1000;
-
- nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
- }
- else
- nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
-
- DEBUG_printf(("http_wait: select() returned %d...\n", nfds));
- }
-# ifdef WIN32
- while (nfds < 0 && WSAGetLastError() == WSAEINTR);
-# else
- while (nfds < 0 && errno == EINTR);
-# endif /* WIN32 */
-#endif /* HAVE_POLL */
-
- DEBUG_printf(("http_wait: returning with nfds=%d...\n", nfds));
-
- return (nfds > 0);
-}
-
-
-/*
* 'http_write()' - Write a buffer to a HTTP connection.
*/
diff --git a/cups/libcups.exp b/cups/libcups.exp
index 74914ae44..4bb5cd67a 100644
--- a/cups/libcups.exp
+++ b/cups/libcups.exp
@@ -306,6 +306,8 @@ _ippRead
_ippReadFile
_ippReadIO
_ippSetPort
+_ippTagString
+_ippTagValue
_ippTimeToDate
_ippWrite
_ippWriteFile
diff --git a/cups/request.c b/cups/request.c
index bf291eabf..8179e51cb 100644
--- a/cups/request.c
+++ b/cups/request.c
@@ -753,6 +753,9 @@ cupsWriteRequestData(
const char *buffer, /* I - Bytes to write */
size_t length) /* I - Number of bytes to write */
{
+ int wused; /* Previous bytes in buffer */
+
+
/*
* Get the default connection as needed...
*/
@@ -776,6 +779,8 @@ cupsWriteRequestData(
* Then write to the HTTP connection...
*/
+ wused = http->wused;
+
if (httpWrite2(http, buffer, length) < 0)
return (HTTP_ERROR);
@@ -783,10 +788,19 @@ cupsWriteRequestData(
* Finally, check if we have any pending data from the server...
*/
- if (httpCheck(http))
- return (httpUpdate(http));
- else
- return (HTTP_CONTINUE);
+ if (length > HTTP_MAX_BUFFER ||
+ http->wused < wused ||
+ (wused > 0 && http->wused == length))
+ {
+ /*
+ * We've written something to the server, so check for response data...
+ */
+
+ if (_httpWait(http, 0, 1))
+ return (httpUpdate(http));
+ }
+
+ return (HTTP_CONTINUE);
}
diff --git a/cups/testhttp.c b/cups/testhttp.c
index fda2147b2..3e10a7634 100644
--- a/cups/testhttp.c
+++ b/cups/testhttp.c
@@ -468,7 +468,7 @@ main(int argc, /* I - Number of command-line arguments */
printf("_httpResolveURI(%s): ", argv[1]);
fflush(stdout);
- if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), 0))
+ if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), 1))
{
puts("FAIL");
return (1);
diff --git a/cups/util.c b/cups/util.c
index 1a6dd50a3..ee1cdf372 100644
--- a/cups/util.c
+++ b/cups/util.c
@@ -458,21 +458,15 @@ cupsGetDefault2(http_t *http) /* I - Connection to server or @code CUPS_HTTP_DE
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
- const char *var; /* Environment variable */
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
/*
- * First see if the LPDEST or PRINTER environment variables are
- * set... However, if PRINTER is set to "lp", ignore it to work
- * around a "feature" in most Linux distributions - the default
- * user login scripts set PRINTER to "lp"...
+ * See if we have a user default printer set...
*/
- if ((var = getenv("LPDEST")) != NULL)
- return (var);
- else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
- return (var);
+ if (_cupsUserDefault(cg->def_printer, sizeof(cg->def_printer)))
+ return (cg->def_printer);
/*
* Connect to the server as needed...
diff --git a/doc/de/index.html.in b/doc/de/index.html.in
new file mode 100644
index 000000000..dade62df5
--- /dev/null
+++ b/doc/de/index.html.in
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+ <TITLE>Home - CUPS @CUPS_VERSION@@CUPS_REVISION@</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <LINK REL="SHORTCUT ICON" HREF="/favicon.png" TYPE="image/png">
+</HEAD>
+<BODY>
+<TABLE CLASS="page" SUMMARY="{title}">
+<TR><TD CLASS="body">
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" SUMMARY="">
+<TR HEIGHT="36">
+<TD><A HREF="http://www.cups.org/" TARGET="_blank"><IMG
+SRC="/images/left.gif" WIDTH="64" HEIGHT="36" BORDER="0" ALT=""></A></TD>
+<TD CLASS="sel"><A HREF="/">&nbsp;&nbsp;Startseite&nbsp;&nbsp;</A></TD>
+<TD CLASS="unsel"><A HREF="/admin">&nbsp;&nbsp;Verwaltung&nbsp;&nbsp;</A></TD>
+<TD CLASS="unsel"><A HREF="/classes/">&nbsp;&nbsp;Klassen&nbsp;&nbsp;</A></TD>
+<TD CLASS="unsel"><A HREF="/help/">&nbsp;&nbsp;On-Line&nbsp;Hilfe&nbsp;&nbsp;</A></TD>
+<TD CLASS="unsel"><A HREF="/jobs/">&nbsp;&nbsp;Auftr&uuml;ge&nbsp;&nbsp;</A></TD>
+<TD CLASS="unsel"><A HREF="/printers/">&nbsp;&nbsp;Drucker&nbsp;&nbsp;</A></TD>
+<TD CLASS="unsel" WIDTH="100%"><FORM ACTION="/help/" METHOD="GET"><INPUT
+TYPE="SEARCH" NAME="QUERY" SIZE="20" PLACEHOLDER="Search Help"
+AUTOSAVE="org.cups.help" RESULTS="20"></FORM></TD>
+<TD><IMG SRC="/images/right.gif" WIDTH="4" HEIGHT="36" ALT=""></TD>
+</TR>
+</TABLE>
+
+<TABLE CLASS="indent" SUMMARY="">
+<TR><TD STYLE="padding-right: 20px;">
+
+<H1>Common UNIX Printing System @CUPS_VERSION@</H1>
+
+<P>CUPS ist das auf Standards basierte, Open-Source Drucker System, welches von
+<A HREF="http://www.apple.com/">Apple Inc.</A> f&uuml;r Mac OS<SUP>&reg;</SUP> X und
+andere UNIX<SUP>&reg;</SUP>-&auml;hnliche Betriebssysteme entwickelt wird.</P>
+
+</TD>
+<TD><A HREF="http://www.cups.org/"><IMG SRC="images/cups-icon.png" WIDTH="128"
+HEIGHT="128" ALT="CUPS"></A></TD>
+</TR>
+</TABLE>
+
+<TABLE CLASS="indent" SUMMARY="">
+<TR><TD VALIGN="top" STYLE="border-right: dotted thin #cccccc; padding-right: 20px;">
+
+<H2>CUPS f&uuml;r Benutzer</H2>
+
+<P><A HREF="help/overview.html">CUPS &Uuml;bersicht</A></P>
+
+<P><A HREF="help/options.html">Kommandozeilendruck und Einstellungen</A></P>
+
+<P><A HREF="help/whatsnew.html">Neues in CUPS 1.4</A></P>
+
+<P><A HREF="http://www.cups.org/newsgroups.php?gcups.general">Benutzer Forum</A></P>
+
+</TD><TD VALIGN="top" STYLE="border-right: dotted thin #cccccc; padding-left: 20px; padding-right: 20px;">
+
+<H2>CUPS f&uuml;r Administratoren</H2>
+
+<P><A HREF="admin">Drucker und Klassen hinzuf&uuml;gen</A></P>
+
+<P><A HREF="help/policies.html">Betriebsrichtlinien verwalten</A></P>
+
+<P><A HREF="help/accounting.html">Basiswissen Druckabrechnung</A></P>
+
+<P><A HREF="help/security.html">Sicherheit des Servers</A></P>
+
+<P><A HREF="help/kerberos.html">Benutzen der Kerberos Authentifizierung</A></P>
+
+<P><A HREF="help/network.html">Benutzen von Netzwerkdruckern</A></P>
+
+<P><A HREF="help/ref-cupsd-conf.html">cupsd.conf Referenz</A></P>
+
+<P><A HREF="http://www.cups.org/ppd.php">Druckertreiber finden</A></P>
+
+</TD><TD VALIGN="top" STYLE="padding-left: 20px;">
+
+<H2>CUPS f&uuml;r Entwickler</H2>
+
+<P><A HREF="help/api-overview.html">Einf&uuml;hrung in die CUPS Programmierung</A></P>
+
+<P><A HREF="help/api-cups.html">CUPS API</A></P>
+
+<P><A HREF="help/api-filter.html">Filter und Backend Programmierung</A></P>
+
+<P><A HREF="help/api-httpipp.html">HTTP und IPP APIs</A></P>
+
+<P><A HREF="help/api-ppd.html">PPD API</A></P>
+
+<P><A HREF="help/api-raster.html">Raster API</A></P>
+
+<P><A HREF="help/ref-ppdcfile.html">PPD Compiler Driver Information File Reference</A></P>
+
+<P><A HREF="http://www.cups.org/newsgroups.php?gcups.development">Entwickler Forum</A></P>
+
+</TD></TR>
+</TABLE>
+
+</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR><TD CLASS="trailer">CUPS und das CUPS Logo sind
+eingetragene Warenzeichen der <A HREF="http://www.apple.com">Apple Inc.</A>
+CUPS ist urheberrechtlich gesch&uuml;tzt 2007-2009 von Apple Inc, alle Rechte vorbehalten.</TD></TR>
+</TABLE>
+</BODY>
+</HTML>
diff --git a/doc/help/spec-ipp.html b/doc/help/spec-ipp.html
index f0272f893..39839068b 100644
--- a/doc/help/spec-ipp.html
+++ b/doc/help/spec-ipp.html
@@ -2678,6 +2678,27 @@ are supported.</p>
name for the printer. If the printer is not being shared using this protocol,
printer-dns-sd-name will have the noValue value.</p>
+<h4><a name="printer-state-reasons">printer-state-reasons (1setOf type2 keyword)</a></h4>
+
+<p>The printer-state-reasons attribute provides additional persistent state
+information for a printer. In addition to the keywords defined in RFC 2911,
+CUPS supports vendor-specific keywords with a domain prefix ("com.vendor.foo")
+and the following CUPS-specific keywords:</p>
+
+<ul>
+
+ <li><tt>cups-insecure-filter-warning</tt> - a filter or backend (or the
+ directory containing the filter or backend) has insecure file
+ permissions. CUPS will not execute programs with world write permissions
+ or setuid programs. When run as root (the default), CUPS also does not
+ execute programs that are not owned by root.
+ <span class='info'>CUPS 1.4</span></li>
+
+ <li><tt>cups-missing-filter-warning</tt> - a filter or backend is not
+ installed. <span class='info'>CUPS 1.4</span></li>
+
+</ul>
+
<h4><a name="printer-type">printer-type (type2 enum)</a></h4>
<p>The printer-type attribute specifies printer type and
diff --git a/ppdc/Dependencies b/ppdc/Dependencies
index 1e53cc2a4..4320ad74c 100644
--- a/ppdc/Dependencies
+++ b/ppdc/Dependencies
@@ -1,78 +1,160 @@
# DO NOT DELETE
-ppdc-array.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-array.o: ../cups/versioning.h
-ppdc-attr.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-attr.o: ../cups/versioning.h
-ppdc-catalog.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-catalog.o: ../cups/versioning.h ../cups/globals.h ../cups/string.h
-ppdc-catalog.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
-ppdc-catalog.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
-ppdc-catalog.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-array.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-array.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-array.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-array.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-array.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+ppdc-array.o: ../cups/i18n.h ../cups/transcode.h
+ppdc-attr.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-attr.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-attr.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-attr.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h ../cups/ppd.h
+ppdc-attr.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdc-attr.o: ../cups/transcode.h
+ppdc-catalog.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-catalog.o: ../cups/debug.h ../cups/globals.h ../cups/string.h
+ppdc-catalog.o: ../config.h ../cups/http-private.h ../cups/http.h
+ppdc-catalog.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h
+ppdc-catalog.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h
ppdc-catalog.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
-ppdc-choice.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-choice.o: ../cups/versioning.h
-ppdc-constraint.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-constraint.o: ../cups/versioning.h
-ppdc-driver.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-driver.o: ../cups/versioning.h ../cups/globals.h ../cups/string.h
+ppdc-choice.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-choice.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-choice.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-choice.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-choice.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-choice.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-constraint.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-constraint.o: ../cups/debug.h ../cups/globals.h ../cups/string.h
+ppdc-constraint.o: ../config.h ../cups/http-private.h ../cups/http.h
+ppdc-constraint.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h
+ppdc-constraint.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h
+ppdc-constraint.o: ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdc-constraint.o: ../cups/transcode.h
+ppdc-driver.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-driver.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
ppdc-driver.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
ppdc-driver.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
ppdc-driver.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
ppdc-driver.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
-ppdc-file.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-file.o: ../cups/versioning.h ../cups/i18n.h ../cups/transcode.h
-ppdc-file.o: ../cups/language.h ../cups/array.h
-ppdc-filter.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-filter.o: ../cups/versioning.h
-ppdc-font.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-font.o: ../cups/versioning.h
-ppdc-group.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-group.o: ../cups/versioning.h
-ppdc-import.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-import.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-ppdc-import.o: ../cups/file.h ../cups/i18n.h ../cups/transcode.h
-ppdc-import.o: ../cups/language.h
-ppdc-mediasize.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-mediasize.o: ../cups/versioning.h
-ppdc-message.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-message.o: ../cups/versioning.h
-ppdc-option.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-option.o: ../cups/versioning.h
-ppdc-profile.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-profile.o: ../cups/versioning.h
-ppdc-shared.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-shared.o: ../cups/versioning.h
-ppdc-source.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-source.o: ../cups/versioning.h ../cups/globals.h ../cups/string.h
+ppdc-file.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-file.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-file.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-file.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h ../cups/ppd.h
+ppdc-file.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdc-file.o: ../cups/transcode.h ../cups/i18n.h
+ppdc-filter.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-filter.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-filter.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-filter.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-filter.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-filter.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-font.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-font.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-font.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-font.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h ../cups/ppd.h
+ppdc-font.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdc-font.o: ../cups/transcode.h
+ppdc-group.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-group.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-group.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-group.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-group.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+ppdc-group.o: ../cups/i18n.h ../cups/transcode.h
+ppdc-import.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-import.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-import.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-import.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-import.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-import.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-import.o: ../cups/ppd.h ../cups/i18n.h
+ppdc-mediasize.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-mediasize.o: ../cups/debug.h ../cups/globals.h ../cups/string.h
+ppdc-mediasize.o: ../config.h ../cups/http-private.h ../cups/http.h
+ppdc-mediasize.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h
+ppdc-mediasize.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-mediasize.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-message.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-message.o: ../cups/debug.h ../cups/globals.h ../cups/string.h
+ppdc-message.o: ../config.h ../cups/http-private.h ../cups/http.h
+ppdc-message.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h
+ppdc-message.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-message.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-option.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-option.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-option.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-option.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-option.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-option.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-profile.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-profile.o: ../cups/debug.h ../cups/globals.h ../cups/string.h
+ppdc-profile.o: ../config.h ../cups/http-private.h ../cups/http.h
+ppdc-profile.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h
+ppdc-profile.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-profile.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-shared.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-shared.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-shared.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-shared.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-shared.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-shared.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-source.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-source.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
ppdc-source.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
ppdc-source.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
ppdc-source.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
ppdc-source.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
ppdc-source.o: ../cups/raster.h ../cups/cups.h ../data/epson.h ../data/escp.h
ppdc-source.o: ../data/hp.h ../data/label.h ../data/pcl.h
-ppdc-string.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-string.o: ../cups/versioning.h
-ppdc-variable.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc-variable.o: ../cups/versioning.h
-genstrings.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-genstrings.o: ../cups/versioning.h
-ppdc.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdc.o: ../cups/versioning.h ../cups/i18n.h ../cups/transcode.h
-ppdc.o: ../cups/language.h ../cups/array.h
-ppdhtml.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdhtml.o: ../cups/versioning.h ../cups/i18n.h ../cups/transcode.h
-ppdhtml.o: ../cups/language.h ../cups/array.h
-ppdi.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdi.o: ../cups/versioning.h ../cups/i18n.h ../cups/transcode.h
-ppdi.o: ../cups/language.h ../cups/array.h
+ppdc-string.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-string.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc-string.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc-string.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ppdc-string.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-string.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+ppdc-variable.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc-variable.o: ../cups/debug.h ../cups/globals.h ../cups/string.h
+ppdc-variable.o: ../config.h ../cups/http-private.h ../cups/http.h
+ppdc-variable.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h
+ppdc-variable.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h
+ppdc-variable.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
+genstrings.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+genstrings.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+genstrings.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+genstrings.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+genstrings.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+genstrings.o: ../cups/i18n.h ../cups/transcode.h
+ppdc.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdc.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdc.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdc.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h ../cups/ppd.h
+ppdc.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdc.o: ../cups/transcode.h
+ppdhtml.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdhtml.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdhtml.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdhtml.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h ../cups/ppd.h
+ppdhtml.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdhtml.o: ../cups/transcode.h
+ppdi.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdi.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdi.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdi.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h ../cups/ppd.h
+ppdi.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdi.o: ../cups/transcode.h
ppdmerge.o: ../cups/ppd-private.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-ppdmerge.o: ../cups/versioning.h ../cups/string.h ../cups/ppd.h
+ppdmerge.o: ../cups/versioning.h ../cups/string.h ../config.h ../cups/ppd.h
ppdmerge.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/cups.h
-ppdmerge.o: ../cups/array.h ../cups/string.h ../config.h ../cups/i18n.h
-ppdmerge.o: ../cups/transcode.h
-ppdpo.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-ppdpo.o: ../cups/versioning.h ../cups/i18n.h ../cups/transcode.h
-ppdpo.o: ../cups/language.h ../cups/array.h
-testcatalog.o: ppdc.h ../cups/string.h ../config.h ../cups/file.h
-testcatalog.o: ../cups/versioning.h
+ppdmerge.o: ../cups/array.h ../cups/string.h ../cups/i18n.h
+ppdpo.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+ppdpo.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+ppdpo.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+ppdpo.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h ../cups/ppd.h
+ppdpo.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
+ppdpo.o: ../cups/transcode.h
+testcatalog.o: ppdc-private.h ppdc.h ../cups/file.h ../cups/versioning.h
+testcatalog.o: ../cups/debug.h ../cups/globals.h ../cups/string.h ../config.h
+testcatalog.o: ../cups/http-private.h ../cups/http.h ../cups/md5.h
+testcatalog.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+testcatalog.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
+testcatalog.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
diff --git a/ppdc/Makefile b/ppdc/Makefile
index 55c85b3c0..db4d1896e 100644
--- a/ppdc/Makefile
+++ b/ppdc/Makefile
@@ -312,9 +312,9 @@ testcatalog: testcatalog.o libcupsppdc.a ../cups/libcups.a
# libcupsppdc.so.1, libcupsppdc.sl.1
#
-libcupsppdc.so.1 libcupsppdc.sl.1: $(LIBOBJS)
+libcupsppdc.so.1 libcupsppdc.sl.1: $(LIBOBJS) ../cups/$(LIBCUPS)
echo Linking $@...
- $(DSOXX) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS) $(LIBS)
+ $(DSOXX) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS) $(LINKCUPS)
$(RM) `basename $@ .1`
$(LN) $@ `basename $@ .1`
@@ -323,7 +323,7 @@ libcupsppdc.so.1 libcupsppdc.sl.1: $(LIBOBJS)
# libcupsppdc.1.dylib
#
-libcupsppdc.1.dylib: $(LIBOBJS)
+libcupsppdc.1.dylib: $(LIBOBJS) ../cups/$(LIBCUPS)
echo Creating export list for $@...
nm $(LIBOBJS) | grep "T __" | awk '{print $$3}' | sort >t.exp
echo Linking $@...
@@ -332,7 +332,7 @@ libcupsppdc.1.dylib: $(LIBOBJS)
-current_version 1.0.0 \
-compatibility_version 1.0.0 \
-exported_symbols_list t.exp \
- $(LIBOBJS) $(LIBS)
+ $(LIBOBJS) $(LINKCUPS)
$(RM) libcupsppdc.dylib t.exp
$(LN) $@ libcupsppdc.dylib
@@ -341,9 +341,9 @@ libcupsppdc.1.dylib: $(LIBOBJS)
# libcupsppdc_s.a
#
-libcupsppdc_s.a: $(LIBOBJS)
+libcupsppdc_s.a: $(LIBOBJS) ../cups/$(LIBCUPS)
echo Creating $@...
- $(DSOXX) $(DSOFLAGS) -o libcupsppdc_s.o $(LIBOBJS) $(LIBS)
+ $(DSOXX) $(DSOFLAGS) -o libcupsppdc_s.o $(LIBOBJS) $(LINKCUPS)
$(RM) $@
$(AR) $(ARFLAGS) $@ libcupsppdc_s.o
@@ -352,10 +352,10 @@ libcupsppdc_s.a: $(LIBOBJS)
# libcupsppdc.la
#
-libcupsppdc.la: $(LIBOBJS)
+libcupsppdc.la: $(LIBOBJS) ../cups/$(LIBCUPS)
echo Linking $@...
$(CC) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS:.o=.lo) -rpath $(LIBDIR) \
- -version-info 1:0 $(LIBS)
+ -version-info 1:0 $(LINKCUPS)
#
diff --git a/ppdc/genstrings.cxx b/ppdc/genstrings.cxx
index 1fec252bf..f5441a1dc 100644
--- a/ppdc/genstrings.cxx
+++ b/ppdc/genstrings.cxx
@@ -31,7 +31,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <unistd.h>
diff --git a/ppdc/ppdc-array.cxx b/ppdc/ppdc-array.cxx
index 30bd48319..33d8bf773 100644
--- a/ppdc/ppdc-array.cxx
+++ b/ppdc/ppdc-array.cxx
@@ -26,7 +26,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-attr.cxx b/ppdc/ppdc-attr.cxx
index 67b93e9af..1ea0337a9 100644
--- a/ppdc/ppdc-attr.cxx
+++ b/ppdc/ppdc-attr.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-catalog.cxx b/ppdc/ppdc-catalog.cxx
index 4f4995c70..451b1d8ed 100644
--- a/ppdc/ppdc-catalog.cxx
+++ b/ppdc/ppdc-catalog.cxx
@@ -30,8 +30,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
-#include <cups/globals.h>
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-choice.cxx b/ppdc/ppdc-choice.cxx
index 03dc646e9..2c12de2b9 100644
--- a/ppdc/ppdc-choice.cxx
+++ b/ppdc/ppdc-choice.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-constraint.cxx b/ppdc/ppdc-constraint.cxx
index f0a6c76a1..6e6f0241e 100644
--- a/ppdc/ppdc-constraint.cxx
+++ b/ppdc/ppdc-constraint.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-driver.cxx b/ppdc/ppdc-driver.cxx
index 8453cce30..ba9c78c9c 100644
--- a/ppdc/ppdc-driver.cxx
+++ b/ppdc/ppdc-driver.cxx
@@ -34,7 +34,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <cups/globals.h>
diff --git a/ppdc/ppdc-file.cxx b/ppdc/ppdc-file.cxx
index 171eb1d80..9b30bcca4 100644
--- a/ppdc/ppdc-file.cxx
+++ b/ppdc/ppdc-file.cxx
@@ -24,7 +24,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <cups/i18n.h>
diff --git a/ppdc/ppdc-filter.cxx b/ppdc/ppdc-filter.cxx
index a99fd608a..33994849b 100644
--- a/ppdc/ppdc-filter.cxx
+++ b/ppdc/ppdc-filter.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-font.cxx b/ppdc/ppdc-font.cxx
index c2d9fed63..b6d9bcb2a 100644
--- a/ppdc/ppdc-font.cxx
+++ b/ppdc/ppdc-font.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-group.cxx b/ppdc/ppdc-group.cxx
index 1924dc751..0fc61e971 100644
--- a/ppdc/ppdc-group.cxx
+++ b/ppdc/ppdc-group.cxx
@@ -23,7 +23,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-import.cxx b/ppdc/ppdc-import.cxx
index ad2c45154..530592936 100644
--- a/ppdc/ppdc-import.cxx
+++ b/ppdc/ppdc-import.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <cups/ppd.h>
#include <cups/i18n.h>
diff --git a/ppdc/ppdc-mediasize.cxx b/ppdc/ppdc-mediasize.cxx
index b80481b7e..844028a39 100644
--- a/ppdc/ppdc-mediasize.cxx
+++ b/ppdc/ppdc-mediasize.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-message.cxx b/ppdc/ppdc-message.cxx
index 69bcd19a1..11e5e3eaa 100644
--- a/ppdc/ppdc-message.cxx
+++ b/ppdc/ppdc-message.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-option.cxx b/ppdc/ppdc-option.cxx
index 8ad1c5c08..c495264ba 100644
--- a/ppdc/ppdc-option.cxx
+++ b/ppdc/ppdc-option.cxx
@@ -24,7 +24,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-private.h b/ppdc/ppdc-private.h
new file mode 100644
index 000000000..4222a3d5d
--- /dev/null
+++ b/ppdc/ppdc-private.h
@@ -0,0 +1,41 @@
+//
+// "$Id$"
+//
+// Private definitions for the CUPS PPD Compiler.
+//
+// Copyright 2009 by Apple Inc.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Apple Inc. and are protected by Federal copyright
+// law. Distribution and use rights are outlined in the file "LICENSE.txt"
+// which should have been included with this file. If this file is
+// file is missing or damaged, see the license at "http://www.cups.org/".
+//
+
+#ifndef _PPDC_PRIVATE_H_
+# define _PPDC_PRIVATE_H_
+
+//
+// Include necessary headers...
+//
+
+# include "ppdc.h"
+# include <cups/debug.h>
+# include <cups/globals.h>
+# include <errno.h>
+
+
+//
+// Macros...
+//
+
+# define PPDC_NEW DEBUG_printf(("%s: %p new", class_name(), this))
+# define PPDC_NEWVAL(s) DEBUG_printf(("%s(\"%s\"): %p new", class_name(), s, this))
+# define PPDC_DELETE DEBUG_printf(("%s: %p delete", class_name(), this))
+
+
+#endif // !_PPDC_PRIVATE_H_
+
+//
+// End of "$Id$".
+//
diff --git a/ppdc/ppdc-profile.cxx b/ppdc/ppdc-profile.cxx
index 0e85cae87..90625f423 100644
--- a/ppdc/ppdc-profile.cxx
+++ b/ppdc/ppdc-profile.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-shared.cxx b/ppdc/ppdc-shared.cxx
index 551fd72ab..1a83564b9 100644
--- a/ppdc/ppdc-shared.cxx
+++ b/ppdc/ppdc-shared.cxx
@@ -24,7 +24,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
@@ -53,9 +53,7 @@ ppdcShared::~ppdcShared()
void
ppdcShared::release(void)
{
-#ifdef DEBUG
- fprintf(stderr, "DEBUG: %p release %s use=%d\n", this, class_name(), use);
-#endif // DEBUG
+ DEBUG_printf(("%s: %p release use=%d", class_name(), this, use));
use --;
if (!use)
@@ -72,9 +70,7 @@ ppdcShared::retain()
{
use ++;
-#ifdef DEBUG
- fprintf(stderr, "DEBUG: %p retain %s use=%d\n", this, class_name(), use);
-#endif // DEBUG
+ DEBUG_printf(("%s: %p retain use=%d", class_name(), this, use));
}
diff --git a/ppdc/ppdc-source.cxx b/ppdc/ppdc-source.cxx
index c06109a82..237b0fd0f 100644
--- a/ppdc/ppdc-source.cxx
+++ b/ppdc/ppdc-source.cxx
@@ -60,7 +60,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <cups/globals.h>
#include <limits.h>
#include <math.h>
diff --git a/ppdc/ppdc-string.cxx b/ppdc/ppdc-string.cxx
index 90a42c447..371ea74d7 100644
--- a/ppdc/ppdc-string.cxx
+++ b/ppdc/ppdc-string.cxx
@@ -22,7 +22,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc-variable.cxx b/ppdc/ppdc-variable.cxx
index e7708c730..22a175ad4 100644
--- a/ppdc/ppdc-variable.cxx
+++ b/ppdc/ppdc-variable.cxx
@@ -23,7 +23,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/ppdc/ppdc.cxx b/ppdc/ppdc.cxx
index 49d5a6ab5..2b006105f 100644
--- a/ppdc/ppdc.cxx
+++ b/ppdc/ppdc.cxx
@@ -22,11 +22,10 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <cups/i18n.h>
//
diff --git a/ppdc/ppdc.h b/ppdc/ppdc.h
index b75f40dec..8e856f1ea 100644
--- a/ppdc/ppdc.h
+++ b/ppdc/ppdc.h
@@ -3,7 +3,7 @@
//
// Definitions for the CUPS PPD Compiler.
//
-// Copyright 2007-2008 by Apple Inc.
+// Copyright 2007-2009 by Apple Inc.
// Copyright 2002-2007 by Easy Software Products.
//
// These coded instructions, statements, and computer programs are the
@@ -20,28 +20,15 @@
// Include necessary headers...
//
-# include <cups/string.h>
-
# include <cups/file.h>
# include <stdlib.h>
-# include <errno.h>
//
// Macros...
//
-# ifdef DEBUG
-# define PPDC_NAME(s) const char *class_name() { return (s); }
-# define PPDC_NEW fprintf(stderr, "DEBUG: %p new %s\n", this, class_name())
-# define PPDC_NEWVAL(s) fprintf(stderr, "DEBUG: %p new %s(\"%s\")\n", this, class_name(), s)
-# define PPDC_DELETE fprintf(stderr, "DEBUG: %p delete %s\n", this, class_name())
-# else
-# define PPDC_NAME(s)
-# define PPDC_NEW
-# define PPDC_NEWVAL(s)
-# define PPDC_DELETE
-# endif // DEBUG
+# define PPDC_NAME(s) const char *class_name() { return (s); }
//
@@ -113,9 +100,7 @@ class ppdcShared //// Shared Data Value
ppdcShared();
virtual ~ppdcShared();
-# ifdef DEBUG
virtual const char *class_name() = 0;
-# endif // DEBUG
void retain();
void release();
diff --git a/ppdc/ppdhtml.cxx b/ppdc/ppdhtml.cxx
index 90ed5e62a..bcbb81e94 100644
--- a/ppdc/ppdhtml.cxx
+++ b/ppdc/ppdhtml.cxx
@@ -22,10 +22,9 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <sys/stat.h>
#include <sys/types.h>
-#include <cups/i18n.h>
//
diff --git a/ppdc/ppdi.cxx b/ppdc/ppdi.cxx
index 6abddeb12..4e8aa3f50 100644
--- a/ppdc/ppdi.cxx
+++ b/ppdc/ppdi.cxx
@@ -22,11 +22,10 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <cups/i18n.h>
//
diff --git a/ppdc/ppdpo.cxx b/ppdc/ppdpo.cxx
index c32b2acf4..3b7904f45 100644
--- a/ppdc/ppdpo.cxx
+++ b/ppdc/ppdpo.cxx
@@ -23,10 +23,9 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
#include <sys/stat.h>
#include <sys/types.h>
-#include <cups/i18n.h>
//
diff --git a/ppdc/sample.drv b/ppdc/sample.drv
index 195466e41..fedc82965 100644
--- a/ppdc/sample.drv
+++ b/ppdc/sample.drv
@@ -134,6 +134,7 @@ Version "1.4"
{
Manufacturer "Dymo"
ModelName "Label Printer"
+ Attribute NickName "" "Dymo Label Printer"
PCFileName "dymo.ppd"
DriverType label
ModelNumber $DYMO_3x0
@@ -179,6 +180,7 @@ Version "1.4"
// Epson 24-Pin Series
{
ModelName "24-Pin Series"
+ Attribute NickName "" "Epson 24-Pin Series"
PCFileName "epson24.ppd"
ModelNumber $EPSON_24PIN
@@ -198,6 +200,7 @@ Version "1.4"
// Epson 9-Pin Series
{
ModelName "9-Pin Series"
+ Attribute NickName "" "Epson 9-Pin Series"
PCFileName "epson9.ppd"
ModelNumber $EPSON_9PIN
ColorDevice No
@@ -216,6 +219,7 @@ Version "1.4"
// Epson Stylus Color Series
{
ModelName "Stylus Color Series"
+ Attribute NickName "" "Epson Stylus Color Series"
PCFileName "stcolor.ppd"
ModelNumber $EPSON_COLOR
ColorDevice Yes
@@ -236,6 +240,7 @@ Version "1.4"
// Epson New Stylus Color Series
{
ModelName "New Stylus Color Series"
+ Attribute NickName "" "Epson New Stylus Color Series"
PCFileName "stcolor2.ppd"
ModelNumber $EPSON_ICOLOR
ColorDevice Yes
@@ -256,6 +261,7 @@ Version "1.4"
// Epson Stylus Color Series
{
ModelName "Stylus Photo Series"
+ Attribute NickName "" "Epson Stylus Photo Series"
PCFileName "stphoto.ppd"
ModelNumber $EPSON_PHOTO
ColorDevice Yes
@@ -276,6 +282,7 @@ Version "1.4"
// Epson New Stylus Color Series
{
ModelName "New Stylus Photo Series"
+ Attribute NickName "" "Epson New Stylus Photo Series"
PCFileName "stphoto2.ppd"
ModelNumber $EPSON_IPHOTO
ColorDevice Yes
@@ -303,6 +310,7 @@ Version "1.4"
DriverType hp
ModelName "PCL Laser Printer"
+ Attribute NickName "" "Generic PCL Laser Printer"
PCFileName "generpcl.ppd"
Throughput 8
ModelNumber $HP_LASERJET
@@ -353,6 +361,7 @@ Version "1.4"
DriverType ps
ModelName "PostScript Printer"
+ Attribute NickName "" "Generic PostScript Printer"
PCFileName "generic.ppd"
Throughput 8
ColorDevice No
@@ -394,6 +403,7 @@ Version "1.4"
// HP DeskJet Series
{
ModelName "DeskJet Series"
+ Attribute NickName "" "HP DeskJet Series"
PCFileName "deskjet.ppd"
ModelNumber $HP_DESKJET
ManualCopies Yes
@@ -447,6 +457,7 @@ Version "1.4"
// HP LaserJet Series PCL 4/5
{
ModelName "LaserJet Series PCL 4/5"
+ Attribute NickName "" "HP LaserJet Series PCL 4/5"
PCFileName "laserjet.ppd"
Throughput 8
ModelNumber $HP_LASERJET
@@ -498,7 +509,7 @@ Version "1.4"
{
Manufacturer "Intellitech"
ModelName "IntelliBar Label Printer"
- Attribute ShortNickName "" "Intellibar Label Printer"
+ Attribute ShortNickName "" "IntelliBar Label Printer"
PCFileName "intelbar.ppd"
DriverType label
ModelNumber $INTELLITECH_PCL
@@ -624,6 +635,7 @@ Version "1.4"
// Oki 24-Pin Series
{
ModelName "24-Pin Series"
+ Attribute NickName "" "Oki 24-Pin Series"
PCFileName "okidat24.ppd"
ModelNumber $EPSON_24PIN
@@ -637,6 +649,7 @@ Version "1.4"
// Oki 9-Pin Series
{
ModelName "9-Pin Series"
+ Attribute NickName "" "Oki 9-Pin Series"
PCFileName "okidata9.ppd"
ModelNumber $EPSON_9PIN
ColorDevice No
@@ -658,6 +671,7 @@ Version "1.4"
// Zebra CPCL Label Printer
{
ModelName "CPCL Label Printer"
+ Attribute NickName "" "Zebra CPCL Label Printer"
PCFileName "zebracpl.ppd"
ModelNumber $ZEBRA_CPCL
@@ -787,6 +801,7 @@ Version "1.4"
// Zebra EPL1 Label Printer
{
ModelName "EPL1 Label Printer"
+ Attribute NickName "" "Zebra EPL1 Label Printer"
PCFileName "zebraep1.ppd"
ModelNumber $ZEBRA_EPL_LINE
@@ -884,6 +899,7 @@ Version "1.4"
// Zebra EPL2 Label Printer
{
ModelName "EPL2 Label Printer"
+ Attribute NickName "" "Zebra EPL2 Label Printer"
PCFileName "zebraep2.ppd"
ModelNumber $ZEBRA_EPL_PAGE
@@ -990,6 +1006,7 @@ Version "1.4"
// Zebra ZPL Label Printer
{
ModelName "ZPL Label Printer"
+ Attribute NickName "" "Zebra ZPL Label Printer"
PCFileName "zebra.ppd"
ModelNumber $ZEBRA_ZPL
diff --git a/ppdc/testcatalog.cxx b/ppdc/testcatalog.cxx
index e173877a2..a9e2e8655 100644
--- a/ppdc/testcatalog.cxx
+++ b/ppdc/testcatalog.cxx
@@ -20,7 +20,7 @@
// Include necessary headers...
//
-#include "ppdc.h"
+#include "ppdc-private.h"
//
diff --git a/scheduler/client.c b/scheduler/client.c
index ecd91a04b..c3ed3ca08 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -2819,7 +2819,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
if (bytes <= 0 ||
(con->http.state != HTTP_GET_SEND && con->http.state != HTTP_POST_SEND))
{
- if (!con->sent_header && !con->response)
+ if (!con->sent_header && con->pipe_pid)
cupsdSendError(con, HTTP_SERVER_ERROR, CUPSD_AUTH_NONE);
else
{
@@ -3985,8 +3985,8 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
envp[envc++] = home;
envp[envc] = NULL;
- if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, NULL, 0,
- &pid))
+ if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, NULL,
+ NULL, &pid))
{
unlink(seedfile);
return (0);
@@ -4064,7 +4064,7 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
infofd = open(infofile, O_RDONLY);
if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
- 0, &pid))
+ NULL, &pid))
{
close(infofd);
unlink(infofile);
@@ -4298,7 +4298,7 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
infofd = open(infofile, O_RDONLY);
if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
- 0, &pid))
+ NULL, &pid))
{
close(infofd);
unlink(infofile);
@@ -4622,7 +4622,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
{
# if !defined(HAVE_KRB5_CC_NEW_UNIQUE) && !defined(HAVE_HEIMDAL)
cupsdLogMessage(CUPSD_LOG_INFO,
- "Sorry, your version of Kerberos does not support "
+ "[CGI] Sorry, your version of Kerberos does not support "
"delegated credentials!");
# else
@@ -4655,7 +4655,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
KerberosContext = NULL;
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to initialize Kerberos context");
+ "[CGI] Unable to initialize Kerberos context");
}
}
@@ -4682,7 +4682,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
# endif /* HAVE_KRB5_CC_NEW_UNIQUE */
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create new credentials cache (%d/%s)",
+ "[CGI] Unable to create new credentials cache (%d/%s)",
error, strerror(errno));
ccache = NULL;
}
@@ -4690,8 +4690,8 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
&principal)) != 0)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to parse kerberos username (%d/%s)", error,
- strerror(errno));
+ "[CGI] Unable to parse kerberos username (%d/%s)",
+ error, strerror(errno));
krb5_cc_destroy(KerberosContext, ccache);
ccache = NULL;
}
@@ -4699,7 +4699,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
principal)))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to initialize credentials cache (%d/%s)",
+ "[CGI] Unable to initialize credentials cache (%d/%s)",
error, strerror(errno));
krb5_cc_destroy(KerberosContext, ccache);
krb5_free_principal(KerberosContext, principal);
@@ -4719,7 +4719,8 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
if (GSS_ERROR(major_status))
{
cupsdLogGSSMessage(CUPSD_LOG_ERROR, major_status, minor_status,
- "Unable to import client credentials cache");
+ "[CGI] Unable to import client credentials "
+ "cache");
krb5_cc_destroy(KerberosContext, ccache);
ccache = NULL;
}
@@ -4815,14 +4816,14 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
envp[envc] = NULL;
- if (LogLevel == CUPSD_LOG_DEBUG2)
+ if (LogLevel >= CUPSD_LOG_DEBUG)
{
for (i = 0; i < argc; i ++)
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "pipe_command: argv[%d] = \"%s\"", i, argv[i]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[CGI] argv[%d] = \"%s\"", i, argv[i]);
for (i = 0; i < envc; i ++)
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "pipe_command: envp[%d] = \"%s\"", i, envp[i]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[CGI] envp[%d] = \"%s\"", i, envp[i]);
}
/*
@@ -4831,7 +4832,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
if (cupsdOpenPipe(fds))
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create pipes for CGI %s - %s",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[CGI] Unable to create pipe for %s - %s",
argv[0], strerror(errno));
return (0);
}
@@ -4841,13 +4842,13 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
*/
if (cupsdStartProcess(command, argv, envp, infile, fds[1], CGIPipes[1],
- -1, -1, root, DefaultProfile, 0, &pid) < 0)
+ -1, -1, root, DefaultProfile, NULL, &pid) < 0)
{
/*
* Error - can't fork!
*/
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork for CGI %s - %s", argv[0],
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[CGI] Unable to start %s - %s", argv[0],
strerror(errno));
cupsdClosePipe(fds);
@@ -4866,8 +4867,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
cupsdAddCert(pid, con->username, NULL);
#endif /* HAVE_GSSAPI */
- cupsdLogMessage(CUPSD_LOG_DEBUG, "[CGI] %s started - PID = %d",
- command, pid);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[CGI] Started %s (PID %d)", command, pid);
*outfile = fds[0];
close(fds[1]);
diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h
index f71225b07..93763a216 100644
--- a/scheduler/cupsd.h
+++ b/scheduler/cupsd.h
@@ -225,7 +225,7 @@ extern const char *cupsdFinishProcess(int pid, char *name, int namelen,
extern int cupsdStartProcess(const char *command, char *argv[],
char *envp[], int infd, int outfd,
int errfd, int backfd, int sidefd,
- int root, void *profile, int job_id,
+ int root, void *profile, cupsd_job_t *job,
int *pid);
extern int cupsdAddSelect(int fd, cupsd_selfunc_t read_cb,
diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
index dfa996a86..c73e99a14 100644
--- a/scheduler/dirsvc.c
+++ b/scheduler/dirsvc.c
@@ -1748,7 +1748,7 @@ cupsdStartPolling(void)
argv[1] = pollp->hostname;
if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, -1,
- 0, DefaultProfile, 0, &(pollp->pid)) < 0)
+ 0, DefaultProfile, NULL, &(pollp->pid)) < 0)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdStartPolling: Unable to fork polling daemon - %s",
@@ -1895,6 +1895,7 @@ cupsdUpdateDNSSDName(void)
DNSServiceErrorType error; /* Error from service creation */
char webif[1024]; /* Web interface share name */
#ifdef HAVE_COREFOUNDATION_H
+ SCDynamicStoreRef sc; /* Context for dynamic store */
CFStringRef nameRef; /* Computer name CFString */
char nameBuffer[1024]; /* C-string buffer */
CFStringEncoding nameEncoding; /* Computer name encoding */
@@ -1914,21 +1915,27 @@ cupsdUpdateDNSSDName(void)
*/
#ifdef HAVE_COREFOUNDATION_H
- cupsdClearString(&DNSSDName);
+ sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
- if ((nameRef = SCDynamicStoreCopyComputerName(NULL,
- &nameEncoding)) != NULL)
+ if (sc)
{
- if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
- kCFStringEncodingUTF8))
- cupsdSetString(&DNSSDName, nameBuffer);
+ if ((nameRef = SCDynamicStoreCopyComputerName(sc,
+ &nameEncoding)) != NULL)
+ {
+ if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
+ kCFStringEncodingUTF8))
+ cupsdSetString(&DNSSDName, nameBuffer);
- CFRelease(nameRef);
- }
+ CFRelease(nameRef);
+ }
+ else
+ cupsdSetString(&DNSSDName, ServerName);
-#else
- cupsdSetString(&DNSSDName, ServerName);
+ CFRelease(sc);
+ }
+ else
#endif /* HAVE_COREFOUNDATION_H */
+ cupsdSetString(&DNSSDName, ServerName);
/*
* Then (re)register the web interface if enabled...
@@ -2545,12 +2552,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
*nameptr; /* Pointer into name */
int ipp_len, /* IPP TXT record length */
printer_len; /* LPD TXT record length */
- char resource[1024]; /* Resource path for printer */
const char *regtype; /* Registration type */
- const char *domain; /* Registration domain */
- cupsd_location_t *location, /* Printer location */
- *policy; /* Operation policy for Print-Job */
- unsigned address[4]; /* INADDR_ANY address */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
@@ -2597,26 +2599,6 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
}
/*
- * If 'Allow printing from the Internet' is enabled (i.e. from any address)
- * let dnssd decide on the domain, otherwise restrict it to ".local".
- */
-
- if (p->type & CUPS_PRINTER_CLASS)
- snprintf(resource, sizeof(resource), "/classes/%s", p->name);
- else
- snprintf(resource, sizeof(resource), "/printers/%s", p->name);
-
- address[0] = address[1] = address[2] = address[3] = 0;
- location = cupsdFindBest(resource, HTTP_POST);
- policy = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
-
- if ((location && !cupsdCheckAccess(address, "", 0, location)) ||
- (policy && !cupsdCheckAccess(address, "", 0, policy)))
- domain = "local.";
- else
- domain = NULL;
-
- /*
* Register IPP and (optionally) LPD...
*/
@@ -2666,9 +2648,8 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
"_ipp._tcp,_cups";
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Registering DNS-SD printer %s with name \"%s\", "
- "type \"%s\", and domain \"%s\"", p->name, name, regtype,
- domain ? domain : "(null)");
+ "Registering DNS-SD printer %s with name \"%s\" and "
+ "type \"%s\"", p->name, name, regtype);
/*
* Register the queue, dropping characters as needed until we succeed...
@@ -2680,7 +2661,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
{
p->ipp_ref = DNSSDRef;
if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection,
- 0, name, regtype, domain, NULL,
+ 0, name, regtype, NULL, NULL,
htons(DNSSDPort), ipp_len, ipp_txt,
dnssdRegisterCallback,
p)) == kDNSServiceErr_BadParam)
@@ -2763,14 +2744,13 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
*/
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Registering DNS-SD printer %s with name \"%s\", "
- "type \"_printer._tcp\", and domain \"%s\"", p->name,
- name, domain ? domain : "(null)");
+ "Registering DNS-SD printer %s with name \"%s\" and "
+ "type \"_printer._tcp\"", p->name, name);
p->printer_ref = DNSSDRef;
if ((se = DNSServiceRegister(&p->printer_ref,
kDNSServiceFlagsShareConnection,
- 0, name, "_printer._tcp", domain, NULL,
+ 0, name, "_printer._tcp", NULL, NULL,
htons(515), printer_len, printer_txt,
dnssdRegisterCallback,
p)) == kDNSServiceErr_NoError)
@@ -5273,7 +5253,7 @@ update_lpd(int onoff) /* - 1 = turn on, 0 = turn off */
argv[4] = NULL;
cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
- NULL, 0, &pid);
+ NULL, NULL, &pid);
}
#endif /* __APPLE__ */
else
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
index edf5c44c3..d2ece64c4 100644
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -5115,7 +5115,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
"copy_model: Running \"cups-driverd cat %s\"...", from);
if (!cupsdStartProcess(buffer, argv, envp, -1, temppipe[1], CGIPipes[1],
- -1, -1, 0, DefaultProfile, 0, &temppid))
+ -1, -1, 0, DefaultProfile, NULL, &temppid))
{
close(tempfd);
unlink(tempfile);
diff --git a/scheduler/job.c b/scheduler/job.c
index d5d40cf7b..d1be75f69 100644
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -1049,7 +1049,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], job->status_pipes[1],
job->back_pipes[0], job->side_pipes[0], 0,
- job->profile, job->id, job->filters + i);
+ job->profile, job, job->filters + i);
cupsdClosePipe(filterfds[!slot]);
@@ -1104,7 +1104,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], job->status_pipes[1],
job->back_pipes[1], job->side_pipes[1],
- backroot, job->profile, job->id, &(job->backend));
+ backroot, job->profile, job, &(job->backend));
if (pid == 0)
{
@@ -1160,6 +1160,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */
cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job, "Job #%d started.",
job->id);
+ /*
+ * If we get here than we are able to run the printer driver filters, so clear
+ * the missing and insecure warnings...
+ */
+
+ cupsdSetPrinterReasons(job->printer, "-cups-missing-filter-warning,"
+ "cups-insecure-filter-warning");
+
return;
@@ -3608,6 +3616,9 @@ start_job(cupsd_job_t *job, /* I - Job ID */
job->status_buffer = cupsdStatBufNew(job->status_pipes[0], NULL);
job->status_level = CUPSD_LOG_INFO;
+ if (job->printer_message)
+ cupsdSetString(&(job->printer_message->values[0].string.text), "");
+
/*
* Create the backchannel pipes and make them non-blocking...
*/
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 7fdb4e510..b8cef369f 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -1102,8 +1102,8 @@ cupsdLoadAllPrinters(void)
if (value &&
strcmp(value, "com.apple.print.recoverable-warning") &&
strcmp(value, "connecting-to-device") &&
- strcmp(value, "cups-insecure-filter-error") &&
- strcmp(value, "cups-missing-filter-error"))
+ strcmp(value, "cups-insecure-filter-warning") &&
+ strcmp(value, "cups-missing-filter-warning"))
{
for (i = 0 ; i < p->num_reasons; i ++)
if (!strcmp(value, p->reasons[i]))
@@ -1596,8 +1596,8 @@ cupsdSaveAllPrinters(void)
for (i = 0; i < printer->num_reasons; i ++)
if (strcmp(printer->reasons[i], "com.apple.print.recoverable-warning") &&
strcmp(printer->reasons[i], "connecting-to-device") &&
- strcmp(printer->reasons[i], "cups-insecure-filter-error") &&
- strcmp(printer->reasons[i], "cups-missing-filter-error"))
+ strcmp(printer->reasons[i], "cups-insecure-filter-warning") &&
+ strcmp(printer->reasons[i], "cups-missing-filter-warning"))
cupsFilePutConf(fp, "Reason", printer->reasons[i]);
cupsFilePrintf(fp, "Type %d\n", printer->type);
@@ -2395,7 +2395,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
* Add filters for printer...
*/
- cupsdSetPrinterReasons(p, "-cups-missing-filter-error");
+ cupsdSetPrinterReasons(p, "-cups-missing-filter-warning,"
+ "cups-insecure-filter-warning");
for (filter = (char *)cupsArrayFirst(p->filters);
filter;
@@ -3580,11 +3581,12 @@ add_printer_filter(
snprintf(p->state_message, sizeof(p->state_message),
"Filter \"%s\" for printer \"%s\" not available: %s",
filename, p->name, strerror(errno));
- cupsdSetPrinterReasons(p, "+cups-missing-filter-error");
+ cupsdSetPrinterReasons(p, "+cups-missing-filter-warning");
cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
- return;
}
+ else
+ memset(&fileinfo, 0, sizeof(fileinfo));
/*
* When running as root, do additional security checks...
@@ -3597,7 +3599,7 @@ add_printer_filter(
* permissions.
*/
- if (fileinfo.st_uid || (fileinfo.st_mode & S_IWOTH) != 0)
+ if (fileinfo.st_uid || (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0)
{
if (fileinfo.st_uid)
snprintf(p->state_message, sizeof(p->state_message),
@@ -3608,45 +3610,37 @@ add_printer_filter(
"Filter \"%s\" for printer \"%s\" has insecure permissions "
"(0%o)", filename, p->name, fileinfo.st_mode);
- cupsdSetPrinterReasons(p, "+cups-insecure-filter-error");
+ cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning");
cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
- return;
}
-
- /*
- * Similarly, check that the parent directory is also owned by root and
- * does not have world write permissions.
- */
-
- if ((dirsep = strrchr(filename, '/')) != NULL)
- *dirsep = '\0';
-
- if (stat(filename, &fileinfo))
+ else if (fileinfo.st_mode)
{
- snprintf(p->state_message, sizeof(p->state_message),
- "Filter directory \"%s\" for printer \"%s\" not accessible: %s",
- filename, p->name, strerror(errno));
- cupsdSetPrinterReasons(p, "+cups-missing-filter-error");
+ /*
+ * Similarly, check that the parent directory is also owned by root and
+ * does not have world write permissions.
+ */
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
- return;
- }
- else if (fileinfo.st_uid || (fileinfo.st_mode & S_IWOTH) != 0)
- {
- if (fileinfo.st_uid)
- snprintf(p->state_message, sizeof(p->state_message),
- "Filter directory \"%s\" for printer \"%s\" not owned by "
- "root", filename, p->name);
- else
- snprintf(p->state_message, sizeof(p->state_message),
- "Filter directory \"%s\" for printer \"%s\" has insecure "
- "permissions (0%o)", filename, p->name, fileinfo.st_mode);
+ if ((dirsep = strrchr(filename, '/')) != NULL)
+ *dirsep = '\0';
- cupsdSetPrinterReasons(p, "+cups-insecure-filter-error");
+ if (!stat(filename, &fileinfo) &&
+ (fileinfo.st_uid ||
+ (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0))
+ {
+ if (fileinfo.st_uid)
+ snprintf(p->state_message, sizeof(p->state_message),
+ "Filter directory \"%s\" for printer \"%s\" not owned by "
+ "root", filename, p->name);
+ else
+ snprintf(p->state_message, sizeof(p->state_message),
+ "Filter directory \"%s\" for printer \"%s\" has insecure "
+ "permissions (0%o)", filename, p->name, fileinfo.st_mode);
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
- return;
+ cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning");
+
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
+ }
}
}
}
@@ -3878,8 +3872,8 @@ delete_printer_filters(
mimeDeleteFilter(MimeDatabase, filter);
}
- cupsdSetPrinterReasons(p, "-cups-insecure-filter-error"
- ",cups-missing-filter-error");
+ cupsdSetPrinterReasons(p, "-cups-insecure-filter-warning"
+ ",cups-missing-filter-warning");
}
diff --git a/scheduler/process.c b/scheduler/process.c
index 45d3bcfb6..1b587ca31 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -250,7 +250,7 @@ cupsdStartProcess(
int sidefd, /* I - Sidechannel file descriptor */
int root, /* I - Run as root? */
void *profile, /* I - Security profile to use */
- int job_id, /* I - Job associated with process */
+ cupsd_job_t *job, /* I - Job associated with process */
int *pid) /* O - Process ID */
{
int user; /* Command UID */
@@ -280,28 +280,36 @@ cupsdStartProcess(
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
"infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
- "profile=%p, job_id=%d, pid=%p) = %d",
+ "profile=%p, job=%p(%d), pid=%p) = %d",
command, argv, envp, infd, outfd, errfd, backfd, sidefd,
- root, profile, job_id, pid, *pid);
+ root, profile, job, job ? job->id : 0, pid, *pid);
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to execute %s: %s", command,
strerror(errno));
+
+ if (job && job->printer)
+ cupsdSetPrinterReasons(job->printer, "+cups-missing-filter-warning");
+
return (0);
}
- else if (commandinfo.st_mode & S_IWOTH)
+ else if (commandinfo.st_mode & (S_ISUID | S_IWOTH))
{
*pid = 0;
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
"infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
- "profile=%p, job_id=%d, pid=%p) = %d",
+ "profile=%p, job=%p(%d), pid=%p) = %d",
command, argv, envp, infd, outfd, errfd, backfd, sidefd,
- root, profile, job_id, pid, *pid);
+ root, profile, job, job ? job->id : 0, pid, *pid);
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to execute %s: insecure file permissions (0%o)",
command, commandinfo.st_mode);
+ if (job && job->printer)
+ cupsdSetPrinterReasons(job->printer, "+cups-insecure-filter-warning");
+
errno = EPERM;
+
return (0);
}
else if ((commandinfo.st_uid != user || !(commandinfo.st_mode & S_IXUSR)) &&
@@ -313,9 +321,9 @@ cupsdStartProcess(
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
"infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
- "profile=%p, job_id=%d, pid=%p) = %d",
+ "profile=%p, job=%p(%d), pid=%p) = %d",
command, argv, envp, infd, outfd, errfd, backfd, sidefd,
- root, profile, job_id, pid, *pid);
+ root, profile, job, job ? job->id : 0, pid, *pid);
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to execute %s: no execute permissions (0%o)",
command, commandinfo.st_mode);
@@ -527,7 +535,7 @@ cupsdStartProcess(
if ((proc = calloc(1, sizeof(cupsd_proc_t) + strlen(command))) != NULL)
{
proc->pid = *pid;
- proc->job_id = job_id;
+ proc->job_id = job ? job->id : 0;
strcpy(proc->name, command);
cupsArrayAdd(process_array, proc);
@@ -540,9 +548,9 @@ cupsdStartProcess(
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
"infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
- "profile=%p, job_id=%d, pid=%p) = %d",
+ "profile=%p, job=%p(%d), pid=%p) = %d",
command, argv, envp, infd, outfd, errfd, backfd, sidefd,
- root, profile, job_id, pid, *pid);
+ root, profile, job, job ? job->id : 0, pid, *pid);
return (*pid);
}
diff --git a/scheduler/subscriptions.c b/scheduler/subscriptions.c
index ba866ca10..4781ac147 100644
--- a/scheduler/subscriptions.c
+++ b/scheduler/subscriptions.c
@@ -1622,7 +1622,7 @@ cupsd_start_notifier(
*/
if (cupsdStartProcess(command, argv, envp, fds[0], -1, NotifierPipes[1],
- -1, -1, 0, DefaultProfile, 0, &pid) < 0)
+ -1, -1, 0, DefaultProfile, NULL, &pid) < 0)
{
/*
* Error - can't fork!
diff --git a/templates/de/add-class.tmpl b/templates/de/add-class.tmpl
new file mode 100644
index 000000000..019bdf2b2
--- /dev/null
+++ b/templates/de/add-class.tmpl
@@ -0,0 +1,39 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">>Klasse hinzuf&uuml;gen</H2>
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+
+<TABLE>
+<TR>
+<TH CLASS="label">Name:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"><BR>
+<SMALL>(Darf alle druckbaren Zeichen au&szlig;er "/", "#", und Leerzeichen enthalten)</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Beschreibung:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"><BR>
+<SMALL>(F&uuml;r Menschen lesbare Beschreibung wie "HP LaserJet with Duplexer")</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Ort:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"><BR>
+<SMALL>(F&uuml;r Menschen lesbarer Ort wie "Lab 1")</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Mitglieder:</TH>
+<TD>
+<SELECT NAME="MEMBER_URIS" SIZE="10" MULTIPLE>
+{[member_uris]<OPTION VALUE="{member_uris}" {?member_selected}>{member_names}}
+</SELECT>
+</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Klasse hinzuf&uuml;gen"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/add-printer.tmpl b/templates/de/add-printer.tmpl
new file mode 100644
index 000000000..8e31628e2
--- /dev/null
+++ b/templates/de/add-printer.tmpl
@@ -0,0 +1,42 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Drucker hinzuf&uuml;gen</H2>
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{?current_make!?<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE" VALUE="{current_make}">:}
+{?current_make_and_model!?<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{current_make_and_model}">:}
+
+<TABLE>
+<TR>
+<TH CLASS="label">Name:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127" VALUE="{?template_name}"><BR>
+<SMALL>(Darf alle druckbaren Zeichen au&szlig;er "/", "#", und Leerzeichen enthalten)</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Beschreibung:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127" VALUE="{?PRINTER_INFO}"><BR>
+<SMALL>(F&uuml;r Menschen lesbare Beschreibung wie "HP LaserJet with Duplexer")</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Ort:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127" VALUE="{?PRINTER_LOCATION}"><BR>
+<SMALL>(F&uuml;r Menschen lesbarer Ort wie "Lab 1")</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Verbindung:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">{device_uri}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Freigabe:</TH>
+<TD><INPUT TYPE="CHECKBOX" NAME="PRINTER_IS_SHARED" {PRINTER_IS_SHARED=1?CHECKED:}">
+Diesen Drucker freigeben</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Weiter"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/add-rss-subscription.tmpl b/templates/de/add-rss-subscription.tmpl
new file mode 100644
index 000000000..264457de0
--- /dev/null
+++ b/templates/de/add-rss-subscription.tmpl
@@ -0,0 +1,43 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
+
+<H2 CLASS="title">>RSS Subskription hinzuf&uuml;gen</H2>
+
+<TABLE SUMMARY="Forumlar zum Hinzufügen einer RSS Subskription">
+<TR>
+<TH CLASS="label">Name:</TH>
+<TD COLSPAN="5"><INPUT TYPE="TEXT" NAME="SUBSCRIPTION_NAME" SIZE="40" MAXLENGTH="127" VALUE="{?SUBSCRIPTION_NAME}"><BR>
+<SMALL>(Darf alle druckbaren Zeichen au&szlig;er Leerzeichen, "/", "?", und "#" enthalten)</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Warteschlange:</TH>
+<TD COLSPAN="5"><SELECT NAME="PRINTER_URI" SIZE="10"><OPTION VALUE="#ALL#"{?PRINTER_URI=#ALL#? SELECTED:}>Alle Warteschlangen</OPTION>{[printer_name]<OPTION VALUE="{printer_uri_supported}"{?PRINTER_URI={printer_uri_supported}? SELECTED:}>{printer_name}</OPTION>}</SELECT></TD>
+</TR>
+<TR VALIGN="TOP">
+<TH CLASS="label">Ereignisse:</TH>
+<TD><INPUT TYPE="CHECKBOX" NAME="EVENT_JOB_CREATED" {?EVENT_JOB_CREATED}>Auftrag Erstellt<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_JOB_COMPLETED" {?EVENT_JOB_COMPLETED}>Auftrag Abgeschlossen<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_JOB_STOPPED" {?EVENT_JOB_STOPPED}>Auftrag Gestoppt<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_JOB_CONFIG_CHANGED" {?EVENT_JOB_CONFIG_CHANGED}>Auftrags Parameter Ge&auml;ndert</TD>
+<TD>&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+<TD><INPUT TYPE="CHECKBOX" NAME="EVENT_PRINTER_STOPPED" {?EVENT_PRINTER_STOPPED}>Warteschlange Gestoppt<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_PRINTER_ADDED" {?EVENT_PRINTER_ADDED}>Warteschlange Hinzugef&uuml;gt<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_PRINTER_MODIFIED" {?EVENT_PRINTER_MODIFIED}>Warteschlange Ge&auml;ndert<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_PRINTER_DELETED" {?EVENT_PRINTER_DELETED}>Warteschlange Gel&ouml;scht</TD>
+<TD>&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+<TD><INPUT TYPE="CHECKBOX" NAME="EVENT_SERVER_STARTED" {?EVENT_SERVER_STARTED}>Server Gestartet<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_SERVER_STOPPED" {?EVENT_SERVER_STOPPED}>Server Gestoppt<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_SERVER_RESTARTED" {?EVENT_SERVER_RESTARTED}>Server Neu Gestartet<BR>
+<INPUT TYPE="CHECKBOX" NAME="EVENT_SERVER_AUDIT" {?EVENT_SERVER_AUDIT}>Server Sicherheits Pr&uuml;fung</TD>
+</TR>
+<TR>
+<TH CLASS="label">Maximale Ereignisse in Durchf&uuml;hrung:</TH>
+<TD COLSPAN="5"><INPUT TYPE="TEXT" NAME="MAX_EVENTS" SIZE="4" MAXLENGTH="4" VALUE="{MAX_EVENTS?{MAX_EVENTS}:20}"></TD>
+</TR>
+<TR>
+<TD></TD>
+<TD COLSPAN="5"><INPUT TYPE="SUBMIT" VALUE="RSS Subskription hinzuf&uuml;gen"></TD>
+</TR>
+</TABLE>
+
+</FORM>
diff --git a/templates/de/admin.tmpl b/templates/de/admin.tmpl
new file mode 100644
index 000000000..508733b22
--- /dev/null
+++ b/templates/de/admin.tmpl
@@ -0,0 +1,109 @@
+<TABLE CLASS="indent" SUMMARY="Administrative T&auml;tigkeiten">
+<TR><TD VALIGN="TOP">
+
+<H2 CLASS="title">Drucker</H2>
+
+<P>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Drucker hinzuf&uuml;gen"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Verf&uuml;gbare Drucker auflisten"></FORM>
+<FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Drucker verwalten"></FORM>
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Drucker f&uuml;r Samba freigeben"></FORM>:}
+</P>
+
+<H2 CLASS="title">Klassen</H2>
+
+<P>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Klasse hinzuf&uuml;gen"></FORM>
+<FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Klassen verwalten"></FORM>
+</P>
+
+<H2 CLASS="title">Druckauftr&auml;ge</H2>
+
+<P>
+<FORM ACTION="/jobs/" METHDO="GET"><INPUT TYPE="SUBMIT" VALUE="Auftr&auml;ge verwalten"></FORM>
+</P>
+
+</TD><TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+
+<H2 CLASS="title">Server</H2>
+
+<P>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Konfigurationsdatei bearbeiten"></FORM>
+<FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Zugriffsprotokoll betrachten"></FORM>
+<FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Fehlerprotokoll betrachten"></FORM>
+<FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Seitenprotokoll betrachten"></FORM>
+</P>
+
+{SETTINGS_ERROR?<P>{SETTINGS_MESSAGE}</P>
+<BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
+
+<FORM METHOD="POST" ACTION="/admin">
+
+{ADVANCEDSETTINGS?<P><B>Erweiterte Servereinstellungen\:</B></P>
+
+<P><A HREF="/admin/">Erweitert <SMALL>&#x25bc;</SMALL></A><BR>
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
+<INPUT TYPE="HIDDEN" NAME="ADVANCEDSETTINGS" VALUE="YES">
+<INPUT TYPE="CHECKBOX" NAME="REMOTE_PRINTERS" {?remote_printers}> Zeige freigegebene Drucker von anderen Systemen<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Protokolle\:
+<INPUT TYPE="CHECKBOX" NAME="BROWSE_REMOTE_CUPS" {?browse_remote_cups}> CUPS
+{HAVE_LDAP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_REMOTE_LDAP" {?browse_remote_ldap}> LDAP:}
+{HAVE_LIBSLP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_REMOTE_SLP" {?browse_remote_slp}> SLP:}<BR>
+<INPUT TYPE="CHECKBOX" NAME="SHARE_PRINTERS" {?share_printers}> Freigeben von Druckern welche mit diesem System verbunden sind<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Klienten maximal\:
+<INPUT TYPE="TEXT" NAME="MAX_CLIENTS" VALUE="{?max_clients}" SIZE="6"><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Protokolle\:
+<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_CUPS" {?browse_local_cups}> CUPS
+{HAVE_DNSSD?<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_DNSSD" {?browse_local_dnssd}> DNS-SD:}
+{HAVE_LDAP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_LDAP" {?browse_local_ldap}> LDAP:}
+{HAVE_LIBSLP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_SLP" {?browse_local_slp}> SLP:}<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="REMOTE_ANY" {?remote_any}> Erlaube Drucken vom Internet aus<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="BROWSE_WEB_IF" {?browse_web_if}> Ver&ouml;ffentliche Webinterface<BR>
+<INPUT TYPE="CHECKBOX" NAME="REMOTE_ADMIN" {?remote_admin}> Erlaube entfernte Verwaltung<BR>
+{have_gssapi?<INPUT TYPE="CHECKBOX" NAME="KERBEROS" {?kerberos}> Benutze Kerberos Authentifizierung (<A HREF="/help/kerberos.html?TOPIC=Getting+Started">FAQ</A>)<BR>:}
+<INPUT TYPE="CHECKBOX" NAME="USER_CANCEL_ANY" {?user_cancel_any}> Erlaube Benutzern jeden Auftrag abzubrechen (nicht nur die Eigenen)<BR>
+<INPUT TYPE="CHECKBOX" NAME="PRESERVE_JOB_HISTORY" {?preserve_job_history}> Auftragsverlauf aufbewahren<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Anzahl der Auftr&auml;ge\:
+<INPUT TYPE="TEXT" NAME="MAX_JOBS" VALUE="{?max_jobs}" SIZE="6"><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="PRESERVE_JOB_FILES" {?preserve_job_files}> Dateien von Druckauftr&auml;gen aufbewahren<BR>
+<INPUT TYPE="CHECKBOX" NAME="DEBUG_LOGGING" {?debug_logging}> Speichere Fehlerinformationen f&uuml;r Fehlersuche<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Maximale Gr&ouml;&szlig;e der Protokolldatei\:
+<INPUT TYPE="TEXT" NAME="MAX_LOG_SIZE" VALUE="{?max_log_size}" SIZE="6"></P>
+
+:<P><B>Grundlegende Servereinstellungen:</B></P>
+
+<P><A HREF="/admin/?ADVANCEDSETTINGS=YES">Erweitert <SMALL>&#x25b6;</SMALL></A><BR>
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
+<INPUT TYPE="CHECKBOX" NAME="REMOTE_PRINTERS" {?remote_printers}> Zeige freigegebene Drucker von anderen Systemen<BR>
+<INPUT TYPE="CHECKBOX" NAME="SHARE_PRINTERS" {?share_printers}> Freigeben von Druckern welche mit diesem System verbunden sind<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="REMOTE_ANY" {?remote_any}> Erlaube Drucken vom Internet aus<BR>
+<INPUT TYPE="CHECKBOX" NAME="REMOTE_ADMIN" {?remote_admin}> Erlaube entfernte Verwaltung<BR>
+{have_gssapi?<INPUT TYPE="CHECKBOX" NAME="KERBEROS" {?kerberos}> Benutze Kerberos Authentifizierung (<A HREF="/help/kerberos.html?TOPIC=Getting+Started">FAQ</A>)<BR>:}
+<INPUT TYPE="CHECKBOX" NAME="USER_CANCEL_ANY" {?user_cancel_any}> Erlaube Benutzern jeden Auftrag abzubrechen (nicht nur die Eigenen)<BR>
+<INPUT TYPE="CHECKBOX" NAME="DEBUG_LOGGING" {?debug_logging}> Speichere Fehlerinformationen f&uuml;r Fehlersuche</P>
+
+}
+<P><INPUT TYPE="SUBMIT" NAME="CHANGESETTINGS" VALUE="Einstellungen &auml;ndern"></P>
+
+</FORM>}
+
+</TD></TR>
+</TABLE>
+
+<DIV CLASS="indent">
+
+<H2 CLASS="title">RSS Subskriptionen</H2>
+
+<P>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="RSS Subskription hinzuf&uuml;gen"></FORM>
+</P>
+
+</DIV>
+
+{notify_subscription_id?<TABLE CLASS="list" SUMMARY=">RSS Subskriptionen">
+<THEAD><TR><TH>Name</TH><TH>Ereignis</TH><TH>Warteschlange</TH></TR></THEAD>
+<TBODY>{[notify_subscription_id]
+<TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="RSS Subskription k&uuml;ndigen"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Alle Warteschlangen}</TD></TR>}
+</TBODY>
+</TABLE>:}
diff --git a/templates/de/choose-device.tmpl b/templates/de/choose-device.tmpl
new file mode 100644
index 000000000..c292f0a37
--- /dev/null
+++ b/templates/de/choose-device.tmpl
@@ -0,0 +1,53 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
+
+{CUPS_GET_DEVICES_DONE?:<P><IMG SRC="/images/wait.gif" WIDTH="16" HEIGHT="16" ALIGN="ABSMIDDLE"
+ALT="Busy Indicator"> Suche nach Druckern...</P>}
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
+
+<TABLE>
+{op=add-printer?:<TR>
+<TH CLASS="label">Aktuelle Verbindung:</TH>
+<TD><INPUT TYPE="RADIO" NAME="DEVICE_URI" VALUE="{current_device_uri}" CHECKED>
+{current_device_uri}</TD>
+</TR>}
+<TR>
+<TH CLASS="label">Lokale Drucker:</TH>
+<TD>
+{[device_uri]{device_class!network?<INPUT TYPE="RADIO" NAME="DEVICE_URI"
+VALUE="{device_uri}{?device_make_and_model!Unbekannt?|{device_make_and_model}:}">
+{device_info} {?device_make_and_model!Unbekannt?({device_make_and_model}):}<BR>
+:}}
+</TD>
+</TR>
+<TR>
+<TH CLASS="label">Entdeckte Netzwerkdrucker:</TH>
+<TD>
+{[device_uri]{device_class=network?{device_uri~[a-z]+://?<INPUT TYPE="RADIO" NAME="DEVICE_URI"
+VALUE="{device_uri}{?device_make_and_model!Unbekannt?|{device_make_and_model}:}">
+{device_info} {?device_make_and_model!Unbekannt?({device_make_and_model}):}<BR>
+:}:}}
+</TD>
+</TR>
+<TR>
+<TR>
+<TH CLASS="label">Andere Netzwerkdrucker:</TH>
+<TD>
+{[device_uri]{device_class=network?{device_uri~[a-z]+://?:<INPUT TYPE="RADIO" NAME="DEVICE_URI"
+VALUE="{device_uri}{?device_make_and_model!Unbekannt?|{device_make_and_model}:}">
+{device_info} {?device_make_and_model!Unbekannt?({device_make_and_model}):}<BR>
+}:}}
+</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Weiter"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/choose-make.tmpl b/templates/de/choose-make.tmpl
new file mode 100644
index 000000000..96b32e309
--- /dev/null
+++ b/templates/de/choose-make.tmpl
@@ -0,0 +1,63 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
+
+<FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+
+<TABLE>
+{op=modify-printer?:<TR>
+<TH CLASS="label">Name:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">{printer_name}</TD>
+</TR>}
+<TR>
+<TH CLASS="label">Beschreibung:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{printer_info}">{printer_info}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Ort:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{printer_location}">{printer_location}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Verbindung:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">{device_uri}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Freigabe:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_IS_SHARED" VALUE="{?printer_is_shared}">
+Diesen Drucker {?printer_is_shared=?nicht:{?printer_is_shared=0?nicht:}} freigeben</TD>
+</TR>
+<TR>
+<TH CLASS="label">Marke:</TH>
+<TD>
+<SELECT NAME="PPD_MAKE" SIZE="10">
+{[ppd_make]<OPTION VALUE="{ppd_make}" {?current_make={ppd_make}?SELECTED:}>{ppd_make}}
+</SELECT>
+</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Weiter"></TD>
+</TR>
+<TR>
+<TD></TD>
+<TD>&nbsp;</TD>
+</TR>
+<TR>
+<TH CLASS="label">Oder stellen Sie eine PPD Datei bereit:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="262144"><INPUT
+TYPE="FILE" NAME="PPD_FILE"></TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="{op=add-printer?Drucker hinzuf&uuml;gen:Drucker &auml;ndern}"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/choose-model.tmpl b/templates/de/choose-model.tmpl
new file mode 100644
index 000000000..0b651fcbb
--- /dev/null
+++ b/templates/de/choose-model.tmpl
@@ -0,0 +1,59 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
+
+<FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE>
+{op=modify-printer?:<TR>
+<TH CLASS="label">Name:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">{printer_name}</TD>
+</TR>}
+<TR>
+<TH CLASS="label">Beschreibung:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{printer_info}">{printer_info}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Ort:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{printer_location}">{printer_location}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Verbindung:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">{device_uri}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Freigabe:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="PRINTER_IS_SHARED" VALUE="{?printer_is_shared}">
+Diesen Drucker {?printer_is_shared=?nicht:{?printer_is_shared=0?nicht:}} freigeben</TD>
+</TR>
+<TR>
+<TH CLASS="label">Marke:</TH>
+<TD>{PPD_MAKE} <INPUT TYPE="SUBMIT" NAME="SELECT_MAKE" VALUE="Andere(n) Marke/Hersteller ausw&auml;hlen"></TD>
+</TR>
+<TR>
+<TH CLASS="label">Modell:</TH>
+<TD>
+<SELECT NAME="PPD_NAME" SIZE="10">
+{op=add-printer?:<OPTION VALUE="__no_change__" SELECTED>Aktueller Treiber - {current_make_and_model}</OPTION>:}
+{[ppd_name]<OPTION VALUE="{ppd_name}" {op=modify-printer?:{?current_make_and_model={ppd_make_and_model}?SELECTED:}}>{ppd_make_and_model} ({ppd_natural_language})
+}</SELECT>
+</TD>
+</TR>
+<TR>
+<TH CLASS="label">>Oder stellen Sie eine PPD Datei bereit:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="262144"><INPUT
+TYPE="FILE" NAME="PPD_FILE"></TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="{op=add-printer?Drucker hinzuf&uuml;gen:Drucker &auml;ndern}"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/choose-serial.tmpl b/templates/de/choose-serial.tmpl
new file mode 100644
index 000000000..7fab7ca94
--- /dev/null
+++ b/templates/de/choose-serial.tmpl
@@ -0,0 +1,51 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
+
+<TABLE>
+<TR>
+<TH CLASS="label">Verbindung:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">{device_uri}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Baud Rate:</TH>
+<TD><SELECT NAME="BAUDRATE">
+{[baudrates]<OPTION {?baudrate={baudrates}?SELECTED:}>{baudrates}}
+</SELECT></TD>
+</TR>
+<TR>
+<TH CLASS="label">Parit&auml;t:</TH>
+<TD><SELECT NAME="PARITY">
+<OPTION VALUE="none" {?parity=none?SELECTED:}>Keine
+<OPTION VALUE="even" {?parity=even?SELECTED:}>Gerade
+<OPTION VALUE="odd" {?parity=odd?SELECTED:}>Ungerade
+</SELECT></TD>
+</TR>
+<TR>
+<TH CLASS="label">Daten Bits:</TH>
+<TD><SELECT NAME="BITS">
+<OPTION {?bits=8?SELECTED:}>8
+<OPTION {?bits=7?SELECTED:}>7
+</SELECT></TD>
+</TR>
+<TR>
+<TH CLASS="label">Flu&szlig;kontrolle:</TH>
+<TD><SELECT NAME="FLOW">
+<OPTION VALUE="none" {?flow=none?SELECTED:}>None
+<OPTION VALUE="soft" {?flow=soft?SELECTED:}>XON/XOFF (Software)
+<OPTION VALUE="hard" {?flow=hard?SELECTED:}>RTS/CTS (Hardware)
+<OPTION VALUE="dtrdsr" {?flow=dtrdsr?SELECTED:}>DTR/DSR (Hardware)
+</SELECT></TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Weiter"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/choose-uri.tmpl b/templates/de/choose-uri.tmpl
new file mode 100644
index 000000000..6d2244f58
--- /dev/null
+++ b/templates/de/choose-uri.tmpl
@@ -0,0 +1,43 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+
+<TABLE>
+<TR>
+<TH CLASS="label">Verbindung:</TH>
+<TD><INPUT TYPE="TEXT" SIZE="60" MAXLENGTH="1024" NAME="DEVICE_URI" VALUE="{current_device_uri?{current_device_uri}:{device_uri}}"></TD>
+</TR>
+<TR>
+<TD></TD>
+<TD>Beispiele:
+<PRE>
+ http://Hostname:631/ipp/
+ http://Hostname:631/ipp/Anschluss1
+
+ ipp://Hostname/ipp/
+ ipp://Hostname/ipp/Anschluss1
+
+ lpd://Hostname/Warteschlange
+
+ socket://Hostname
+ socket://Hostname:9100
+</PRE>
+
+<P>Bitte lesen Sie <A HREF="/help/network.html" TARGET="_blank">"Netzwerk
+Drucker"</A> um die korrekte URI f&uuml;r Ihren Drucker zu benutzen.</P>
+
+</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Weiter"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/class-added.tmpl b/templates/de/class-added.tmpl
new file mode 100644
index 000000000..3b05769a3
--- /dev/null
+++ b/templates/de/class-added.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Klasse hinzuf&uuml;gen</H2>
+
+<P>Die Klasse <A HREF="/classes/{printer_name}">{printer_name}</A> wurde erfolgreich
+hinzugef&uuml;gt.
+
+</DIV>
diff --git a/templates/de/class-confirm.tmpl b/templates/de/class-confirm.tmpl
new file mode 100644
index 000000000..bb25035d1
--- /dev/null
+++ b/templates/de/class-confirm.tmpl
@@ -0,0 +1,10 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Klasse {printer_name} l&ouml;schen</H2>
+
+<P><B>Warning:</B> Sind Sie sicher Sie wollen die Klasse
+{printer_name} l&ouml;schen?</P>
+
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Klasse l&ouml;schen"></FORM></P>
+
+</DIV>
diff --git a/templates/de/class-deleted.tmpl b/templates/de/class-deleted.tmpl
new file mode 100644
index 000000000..9357924c1
--- /dev/null
+++ b/templates/de/class-deleted.tmpl
@@ -0,0 +1,7 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Klasse {printer_name} l&ouml;schen</H2>
+
+<P>Die Klasse {printer_name} wurde erfolgreich gel&ouml;scht.
+
+</DIV>
diff --git a/templates/de/class-jobs-header.tmpl b/templates/de/class-jobs-header.tmpl
new file mode 100644
index 000000000..4f3de9340
--- /dev/null
+++ b/templates/de/class-jobs-header.tmpl
@@ -0,0 +1,3 @@
+<DIV CLASS="indent">
+<H3 CLASS="title">Auftr&auml;ge</H3>
+</DIV>
diff --git a/templates/de/class-modified.tmpl b/templates/de/class-modified.tmpl
new file mode 100644
index 000000000..b5ad0daec
--- /dev/null
+++ b/templates/de/class-modified.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Klasse {printer_name} &auml;ndern</H2>
+
+<P>Die Klasse <A HREF="/classes/{printer_name}">{printer_name}</A> wurde
+erfolgreich ge&auml;ndert.
+
+</DIV>
diff --git a/templates/de/class.tmpl b/templates/de/class.tmpl
new file mode 100644
index 000000000..da72bc44c
--- /dev/null
+++ b/templates/de/class.tmpl
@@ -0,0 +1,41 @@
+<DIV CLASS="indent">
+<H2 CLASS="title"><A HREF="{printer_uri_supported}">{printer_name}</A>
+({printer_state=3?Frei:{printer_state=4?Besch&auml;ftigt:Angehalten}},
+{printer_is_accepting_jobs=0?Auftr&auml;ge werden ablehnt:Auftr&auml;ge werden akzeptiert},
+{server_is_sharing_printers=0?Nicht:{printer_is_shared=0?Nicht:}} Freigegeben{default_name={printer_name}?, Standarddrucker:})</H2>
+
+<FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
+<OPTION VALUE="">Wartung</OPTION>
+<OPTION VALUE="print-test-page">Drucke Testseite</OPTION>
+{printer_state=5?<OPTION VALUE="start-class">Klasse starten</OPTION>:<OPTION VALUE="stop-class">Klasse stoppen</OPTION>}
+{printer_is_accepting_jobs=0?<OPTION VALUE="accept-jobs">Auftr&auml;ge akzeptieren</OPTION>:<OPTION VALUE="reject-jobs">Auftr&auml;ge ablehnen</OPTION>}
+<OPTION VALUE="move-jobs">Alle Auftr&auml;ge verschieben</OPTION>
+<OPTION VALUE="purge-jobs">Alle Auftr&auml;ge abbrechen</OPTION>
+</SELECT>
+<INPUT TYPE="SUBMIT" VALUE="Go" STYLE="display: none;">
+</FORM>
+
+<FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
+<SELECT NAME="OP" ONCHANGE="document.administration.submit();">
+<OPTION VALUE="">Administration</OPTION>
+<OPTION VALUE="modify-class">Klasse &auml;ndern</OPTION>
+<OPTION VALUE="delete-class">Klasse l&ouml;schen</OPTION>
+<OPTION VALUE="set-class-options">Standardeinstellungen festlegen</OPTION>
+<OPTION VALUE="set-as-default">Als Standard festlegen</OPTION>
+<OPTION VALUE="set-allowed-users">Erlaubte Benutzer festlegen</OPTION>
+</SELECT>
+<INPUT TYPE="SUBMIT" VALUE="Go" STYLE="display: none;">
+</FORM>
+
+<TABLE SUMMARY="{printer_name}">
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Beschreibung:</TH><TD>{printer_info}</TD></TR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Ort:</TH><TD>{printer_location}</TD></TR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Mitglieder:</TH><TD>{?member_uris=?None:{member_uris}}</TD></TR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Standardeinstellungen:</TH><TD>job-sheets={job_sheets_default}
+media={media_default?{media_default}:unbekannt}
+{sides_default?sides={sides_default}:}</TD></TR>
+</TABLE>
+
+</DIV>
diff --git a/templates/de/classes-header.tmpl b/templates/de/classes-header.tmpl
new file mode 100644
index 000000000..5fa4d4ae3
--- /dev/null
+++ b/templates/de/classes-header.tmpl
@@ -0,0 +1 @@
+<P ALIGN="CENTER">{total=0?Keine Klassen:Zeige {#printer_name} von {total} Klasse{total=1?:n}}.</P>
diff --git a/templates/de/classes.tmpl b/templates/de/classes.tmpl
new file mode 100644
index 000000000..1a919a80e
--- /dev/null
+++ b/templates/de/classes.tmpl
@@ -0,0 +1,11 @@
+{#printer_name=0?:
+<TABLE CLASS="list" SUMMARY="Class List">
+<THEAD>
+<TR><TH><A HREF="{THISURL}?QUERY={?QUERY}&amp;WHICH_JOBS={?WHICH_JOBS}&amp;FIRST={FIRST}&amp;ORDER={ORDER=dec?asc:dec}">{ORDER=dec?<SMALL>&#x25b2;</SMALL> Wartweschlange <SMALL>&#x25b2;</SMALL>:<SMALL>&#x25bc;</SMALL> Warteschlange <SMALL>&#x25bc;</SMALL>}</A></TH><TH>Beschreibung</TH><TH>Ort</TH><TH>Mitglieder</TH><TH>Status</TH></TR>
+</THEAD>
+<TBODY>
+{[printer_name]
+<TR><TD><A HREF="{printer_uri_supported}">{printer_name}</A></TD><TD>{printer_info}</TD><TD>{printer_location}</TD><TD>{?member_uris=?Keine:{member_uris}}</TD><TD>{printer_state=3?Frei:{printer_state=4?Besch&auml;ftigt:Angehalten}}{printer_state_message? - "{printer_state_message}":}</TD></TR>
+}
+</TBODY>
+</TABLE></DIV>}
diff --git a/templates/de/command.tmpl b/templates/de/command.tmpl
new file mode 100644
index 000000000..45e8dce56
--- /dev/null
+++ b/templates/de/command.tmpl
@@ -0,0 +1,12 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{title} auf {printer_name}</H2>
+
+<P>{job_state>5?:<IMG SRC="/images/wait.gif" WIDTH="16" HEIGHT="16"
+ALIGN="ABSMIDDLE" ALT="Busy Indicator"> }Drucker Befehlsauftrag
+{job_state=3?unerledigt:{job_state=4?gehalten:
+{job_state=5?verarbeite:{job_state=6?gestoppt:
+{job_state=7?gel&ouml;scht:{job_state=8?abgebrochen:beendet}}}}}}{job_state=9?:{job_printer_state_message?,
+<EM>"{job_printer_state_message}"</EM>:}}</P>
+
+</DIV>
diff --git a/templates/de/edit-config.tmpl b/templates/de/edit-config.tmpl
new file mode 100644
index 000000000..7439c9884
--- /dev/null
+++ b/templates/de/edit-config.tmpl
@@ -0,0 +1,24 @@
+<SCRIPT TYPE="text/javascript">
+function reset_config()
+{
+ document.cups.CUPSDCONF.value = "{?cupsdconf_default}";
+}
+</SCRIPT>
+
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Konfigurationsdatei &auml;ndern</H2>
+
+<FORM NAME="cups" METHOD="POST" ACTION="/admin/">
+
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
+
+<TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
+
+<P><INPUT TYPE="SUBMIT" NAME="SAVECHANGES" VALUE="&Auml;nderungen speichern">
+<INPUT TYPE="BUTTON" VALUE="Standard Konfigurationsdatei verwenden"
+onClick="reset_config();"></P>
+
+</FORM>
+
+</DIV>
diff --git a/templates/de/error-op.tmpl b/templates/de/error-op.tmpl
new file mode 100644
index 000000000..d47e73089
--- /dev/null
+++ b/templates/de/error-op.tmpl
@@ -0,0 +1,9 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{?title} {?printer_name} Error</H2>
+
+<P>Fehler:</P>
+
+<BLOCKQUOTE>Unbekannte Operation "{op}"!</BLOCKQUOTE>
+
+</DIV>
diff --git a/templates/de/error.tmpl b/templates/de/error.tmpl
new file mode 100644
index 000000000..1a7f6503c
--- /dev/null
+++ b/templates/de/error.tmpl
@@ -0,0 +1,9 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{?title} {?printer_name} Error</H2>
+
+<P>{?message?{message}:Fehler:}</P>
+
+<BLOCKQUOTE>{error}</BLOCKQUOTE>
+
+</DIV>
diff --git a/templates/de/header.tmpl.in b/templates/de/header.tmpl.in
new file mode 100644
index 000000000..fffe7aaa8
--- /dev/null
+++ b/templates/de/header.tmpl.in
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+ <TITLE>{title} - CUPS @CUPS_VERSION@@CUPS_REVISION@</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <LINK REL="SHORTCUT ICON" HREF="/favicon.png" TYPE="image/png">
+ {refresh_page?<META HTTP-EQUIV="Refresh" CONTENT="{refresh_page}">:}
+</HEAD>
+<BODY>
+<TABLE CLASS="page" SUMMARY="{title}">
+<TR><TD CLASS="body">
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" SUMMARY="">
+<TR HEIGHT="36">
+<TD><A HREF="http://www.cups.org/" TARGET="_blank"><IMG
+SRC="/images/left.gif" WIDTH="64" HEIGHT="36" BORDER="0" ALT=""></A></TD>
+<TD CLASS="unsel"><A HREF="/">&nbsp;&nbsp;Startseite&nbsp;&nbsp;</A></TD>
+<TD CLASS="{SECTION=admin?:un}sel"><A HREF="/admin">&nbsp;&nbsp;Verwaltung&nbsp;&nbsp;</A></TD>
+<TD CLASS="{SECTION=classes?:un}sel"><A HREF="/classes/">&nbsp;&nbsp;Klassen&nbsp;&nbsp;</A></TD>
+<TD CLASS="{SECTION=help?:un}sel"><A HREF="/help/">&nbsp;&nbsp;Online&nbsp;Hilfe&nbsp;&nbsp;</A></TD>
+<TD CLASS="{SECTION=jobs?:un}sel"><A HREF="/jobs/">&nbsp;&nbsp;Auftr&auml;ge&nbsp;&nbsp;</A></TD>
+<TD CLASS="{SECTION=printers?:un}sel"><A HREF="/printers/">&nbsp;&nbsp;Drucker&nbsp;&nbsp;</A></TD>
+<TD CLASS="unsel" WIDTH="100%"><FORM ACTION="/help/" METHOD="GET"><INPUT
+TYPE="SEARCH" NAME="QUERY" SIZE="20" PLACEHOLDER="Search Help"
+VALUE="{SECTION=help?{?QUERY}:}" AUTOSAVE="org.cups.help" RESULTS="20"></FORM></TD>
+<TD><IMG SRC="/images/right.gif" WIDTH="4" HEIGHT="36" ALT=""></TD>
+</TR>
+<TR><TD COLSPAN="9">&nbsp;</TD></TR>
+</TABLE>
diff --git a/templates/de/help-header.tmpl b/templates/de/help-header.tmpl
new file mode 100644
index 000000000..23fc4fc0d
--- /dev/null
+++ b/templates/de/help-header.tmpl
@@ -0,0 +1,51 @@
+<DIV CLASS="indent">
+<FORM ACTION="/help/{?HELPFILE}" METHOD="GET">
+{TOPIC?<INPUT TYPE="HIDDEN" NAME="TOPIC" VALUE="{TOPIC}">:}
+
+<P ALIGN="CENTER"><B>Suche in
+{HELPTITLE?{HELPTITLE}:{TOPIC?{TOPIC}:allen Dokumenten}}:</B> <INPUT
+TYPE="SEARCH" NAME="QUERY" VALUE="{?QUERY}" SIZE="40" PLACEHOLDER=""
+AUTOSAVE="org.cups.help" RESULTS="20">
+<INPUT TYPE="SUBMIT" NAME="SEARCH" VALUE="Suchen">
+<INPUT TYPE="SUBMIT" NAME="CLEAR" VALUE="Leeren"></P>
+
+</FORM>
+
+<!-- Bookmarks -->
+<DIV CLASS="sidebar"><TABLE CLASS="inset" SUMMARY="Inhalt">
+<TR><TD>
+
+<H3 CLASS="title">On-Line Hilfe Dokumente</H3>
+
+<P CLASS="l0"><A HREF="/help/{QUERY??QUERY={QUERY}:}">Alle Dokumente</A></P>
+<HR>
+
+{[BMTEXT]<P CLASS="l{BMINDENT}"><A HREF="{BMLINK}">{BMTEXT}</A></P>
+}
+</TD></TR>
+</TABLE></DIV>
+
+{QUERY?<P>Suchergebnisse in {HELPFILE?{HELPTITLE}:{TOPIC?{TOPIC}:allen Dokumenten}}\:</P>
+{QTEXT?<UL>
+{[QTEXT]<LI><A HREF="{QLINK}">{QTEXT}</A>{QPTEXT? (in <I><A HREF="{QPLINK}">{QPTEXT}</A></I>):}</LI>}
+{QTEXT?</UL>:}
+:<P>Keine &Uuml;bereinstimmung gefunden.</P>}
+<HR NOSHADE>:}
+{HELPTITLE?<H1>{HELPTITLE}</H1>
+<FORM ACTION="/help/{?HELPFILE}" METHOD="GET"><INPUT TYPE="HIDDEN" NAME="PRINTABLE" VALUE="YES"><INPUT TYPE="SUBMIT" VALUE="Druckversion anzeigen"></FORM>:
+
+<H1>CUPS Hilfeseiten</H1>
+
+<P>Dies ist das CUPS online Hilfesystem. Geben Sie Ihren Suchbegriff
+oben ein oder klicken Sie auf einen der Dokumentationslinks
+um sich die Online Hilfe Informationen anzeigen zu lassen.</P>
+
+<P>Wenn Sie noch unerfahren im Umgang mit CUPS sind, lesen Sie die "<a
+href="/help/overview.html">CUPS &Uuml;bersicht</a>".
+Erfahrene Benutzer sollten "<a href="/help/whatsnew.html">Was ist neu in CUPS
+1.4</a>" lesen.</P>
+
+<P>Die <A HREF="http://www.cups.org/">CUPS Webseite</A> bietet
+ebenfalls viele Angebote inklusive Benutzer Diskussionsforen,
+Antworten auf h&auml;ufig gestellte Fragen, und ein Formular für
+Fehlerberichte und W&uuml;nsche.</P>}
diff --git a/templates/de/help-printable.tmpl b/templates/de/help-printable.tmpl
new file mode 100644
index 000000000..a326d9762
--- /dev/null
+++ b/templates/de/help-printable.tmpl
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+ <TITLE>{HELPTITLE}</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups-printable.css">
+ <LINK REL="SHORTCUT ICON" HREF="/favicon.ico" TYPE="image/x-icon">
+</HEAD>
+<BODY>
+
+<H1>{HELPTITLE}</H1>
diff --git a/templates/de/help-trailer.tmpl b/templates/de/help-trailer.tmpl
new file mode 100644
index 000000000..4c1ebed85
--- /dev/null
+++ b/templates/de/help-trailer.tmpl
@@ -0,0 +1 @@
+</DIV>
diff --git a/templates/de/job-cancel.tmpl b/templates/de/job-cancel.tmpl
new file mode 100644
index 000000000..9bf6f3883
--- /dev/null
+++ b/templates/de/job-cancel.tmpl
@@ -0,0 +1,7 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Auftrag {job_id} l&ouml;schen</H2>
+
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde gel&ouml;scht.
+
+</DIV>
diff --git a/templates/de/job-hold.tmpl b/templates/de/job-hold.tmpl
new file mode 100644
index 000000000..aaddb20b6
--- /dev/null
+++ b/templates/de/job-hold.tmpl
@@ -0,0 +1,7 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Auftrag {job_id} anhalten</H2>
+
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde vom Drucken abgehalten.
+
+</DIV>
diff --git a/templates/de/job-move.tmpl b/templates/de/job-move.tmpl
new file mode 100644
index 000000000..90cc98e7a
--- /dev/null
+++ b/templates/de/job-move.tmpl
@@ -0,0 +1,26 @@
+<DIV CLASS="indent">
+
+<FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
+
+<H2 CLASS="title">{job_id?Auftrag {job_id} verschieben:Alle Auftr&auml;ge verschieben}</H2>
+
+<TABLE>
+<TR>
+<TH CLASS="label">Neues Ziel:</TH>
+<TD>
+<SELECT NAME="JOB_PRINTER_URI" SIZE="10">
+{[job_printer_uri]<OPTION VALUE="{job_printer_uri}">{job_printer_name}}
+</SELECT>
+</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="{job_id?Auftrag verschieben:Auftr&auml;ge verschieben}"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+
+</DIV>
diff --git a/templates/de/job-moved.tmpl b/templates/de/job-moved.tmpl
new file mode 100644
index 000000000..ad9624ea6
--- /dev/null
+++ b/templates/de/job-moved.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{job_id?Auftrag {job_id} verschieben:Alle Auftr&auml;ge verschieben}</H2>
+
+<P>{job_id?<A HREF="/jobs/{job_id}">Auftrag {job_id}</A>:Alle Auftr&auml;ge} nach
+<A HREF="{job_printer_uri}">{job_printer_name}</A> verschoben.</P>
+
+</DIV>
diff --git a/templates/de/job-release.tmpl b/templates/de/job-release.tmpl
new file mode 100644
index 000000000..e1d4227fe
--- /dev/null
+++ b/templates/de/job-release.tmpl
@@ -0,0 +1,7 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Auftrag {job_id} freigeben</H2>
+
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde zum Drucken freigegeben.
+
+</DIV>
diff --git a/templates/de/job-restart.tmpl b/templates/de/job-restart.tmpl
new file mode 100644
index 000000000..b4876978f
--- /dev/null
+++ b/templates/de/job-restart.tmpl
@@ -0,0 +1,7 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Auftrag {job_id} neu starten</H2>
+
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde neu gestartet.
+
+</DIV>
diff --git a/templates/de/jobs-header.tmpl b/templates/de/jobs-header.tmpl
new file mode 100644
index 000000000..6565af41e
--- /dev/null
+++ b/templates/de/jobs-header.tmpl
@@ -0,0 +1,5 @@
+<DIV CLASS="indent">{?which_jobs=?:<FORM ACTION="{?printer_name=?/jobs:{printer_uri_supported}}" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Aktive Auftr&auml;ge anzeigen"></FORM>}
+{?which_jobs=completed?:<FORM ACTION="{?printer_name=?/jobs:{printer_uri_supported}}" METHOD="GET"><INPUT TYPE="HIDDEN" NAME="which_jobs" VALUE="completed"><INPUT TYPE="SUBMIT" VALUE="Fertige Auftr&auml;ge anzeigen"></FORM>}
+{?which_jobs=all?:<FORM ACTION="{?printer_name=?/jobs:{printer_uri_supported}}" METHOD="GET"><INPUT TYPE="HIDDEN" NAME="which_jobs" VALUE="all"><INPUT TYPE="SUBMIT" VALUE="Alle Auftr&auml;ge anzeigen"></FORM>}</DIV>
+
+<P ALIGN="CENTER">{total=0?Keine Auftr&auml;ge:Zeige {#job_id} von {total} {?which_jobs=?aktiven:{which_jobs=all?:beendeten}} {total=1?Auftrag:Auftr&auml;gen}}.</P>
diff --git a/templates/de/jobs.tmpl b/templates/de/jobs.tmpl
new file mode 100644
index 000000000..38885f995
--- /dev/null
+++ b/templates/de/jobs.tmpl
@@ -0,0 +1,37 @@
+{#job_id=0?:
+<TABLE CLASS="list" SUMMARY="Auftragsliste">
+<THEAD>
+<TR><TH><A HREF="{THISURL}?QUERY={?QUERY}&amp;WHICH_JOBS={?WHICH_JOBS}&amp;FIRST={FIRST}&amp;ORDER={ORDER=dec?asc:dec}">{ORDER=dec?<SMALL>&#x25b2;</SMALL> ID <SMALL>&#x25b2;</SMALL>:<SMALL>&#x25bc;</SMALL> ID <SMALL>&#x25bc;</SMALL>}</A></TH><TH>Name</TH><TH>Benutzer</TH><TH>Gr&ouml;&szlig;e</TH><TH>Seiten</TH><TH>Status</TH><TH>Kontrolle</TH></TR>
+</THEAD>
+<TBODY>
+{[job_id]
+<TR VALIGN="TOP">
+<TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+<TD>{?job_name=?Unbekannt:{job_name}}&nbsp;</TD>
+<TD>{job_originating_user_name}&nbsp;</TD>
+<TD>{job_k_octets}k&nbsp;</TD>
+<TD>{job_media_sheets_completed=0?Unbekannt:{?job_media_sheets_completed}}&nbsp;</TD>
+<TD>{job_state=3?unerledigt seit<BR>{time_at_creation}:{job_state=4?angehalten seit<BR>{time_at_creation}:
+{job_state=5?verarbeitet seit<BR>{time_at_processing}:{job_state=6?gestoppt:
+{job_state=7?getl&ouml;scht am<BR>{time_at_completed}:{job_state=8?abgebrochen:beendet am<BR>{time_at_completed}}}}}}}&nbsp;{job_printer_state_message?<BR>
+<EM>"{job_printer_state_message}"</EM>:}</TD>
+<TD>
+{job_preserved>0?{job_state>5?
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<INPUT TYPE="SUBMIT" VALUE="Auftrag neu drucken"></FORM>:}:}
+{job_state=4?
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<INPUT TYPE="SUBMIT" VALUE="Auftrag freigeben"></FORM>:}
+{job_state=3?
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<INPUT TYPE="SUBMIT" VALUE="Auftrag anhalten"></FORM>:}
+{job_state<7?
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<INPUT TYPE="SUBMIT" VALUE="Auftrag l&ouml;schen"></FORM>
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Auftrag verschieben"></FORM>:}
+&nbsp;</TD>
+</TR>
+}
+</TBODY>
+</TABLE>
+}
diff --git a/templates/de/list-available-printers.tmpl b/templates/de/list-available-printers.tmpl
new file mode 100644
index 000000000..9ca2b5377
--- /dev/null
+++ b/templates/de/list-available-printers.tmpl
@@ -0,0 +1,11 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Verf&uuml;gbare Drucker</H2>
+
+{#device_uri=0?<P>Keine Drucker gefunden.</P>
+:<UL>{[device_uri]
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Diesen Drucker hinzuf&uuml;gen"></FORM>
+{device_make_and_model} ({device_info})</LI>
+}</UL>}
+
+</DIV>
diff --git a/templates/de/modify-class.tmpl b/templates/de/modify-class.tmpl
new file mode 100644
index 000000000..853d929c8
--- /dev/null
+++ b/templates/de/modify-class.tmpl
@@ -0,0 +1,32 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Klasse {printer_name} &auml;ndern</H2>
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+
+<TABLE>
+<TR>
+<TH CLASS="label">Beschreibung:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+<TH CLASS="label">Ort:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+<TH CLASS="label">Mitglieder:</TH>
+<TD>
+<SELECT NAME="MEMBER_URIS" SIZE="10" MULTIPLE>
+{[member_uris]<OPTION VALUE="{member_uris}" {?member_selected}>{member_names}}
+</SELECT>
+</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Klasse &auml;ndern"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/modify-printer.tmpl b/templates/de/modify-printer.tmpl
new file mode 100644
index 000000000..61bebdeb6
--- /dev/null
+++ b/templates/de/modify-printer.tmpl
@@ -0,0 +1,37 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{printer_name} &auml;ndern</H2>
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+
+<TABLE>
+<TR>
+<TH CLASS="label">Beschreibung:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"><BR>
+<SMALL>(F&uuml;r Menschen lesbare Beschreibung wie "HP LaserJet with Duplexer")</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Ort:</TH>
+<TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"><BR>
+<SMALL>(F&uuml;r Menschen lesbarer Ort wie "Lab 1")</SMALL></TD>
+</TR>
+<TR>
+<TH CLASS="label">Verbindung:</TH>
+<TD><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">{device_uri}</TD>
+</TR>
+<TR>
+<TH CLASS="label">Freigabe:</TH>
+<TD><INPUT TYPE="CHECKBOX" NAME="PRINTER_IS_SHARED" {PRINTER_IS_SHARED=1?CHECKED:}">
+Diesen Drucker freigeben</TD>
+</TR>
+<TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Weiter"></TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>
diff --git a/templates/de/norestart.tmpl b/templates/de/norestart.tmpl
new file mode 100644
index 000000000..fb22b154e
--- /dev/null
+++ b/templates/de/norestart.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Change Settings</H2>
+
+<P>Der Server wurde nicht neu gestartet, da die Konfiguration
+nicht ge&auml;ndert wurde...</P>
+
+</DIV>
diff --git a/templates/de/option-boolean.tmpl b/templates/de/option-boolean.tmpl
new file mode 100644
index 000000000..2d0dd551a
--- /dev/null
+++ b/templates/de/option-boolean.tmpl
@@ -0,0 +1,6 @@
+<TR>
+<TH {conflicted=1?CLASS="conflict":CLASS="label"} WIDTH="50%"><A NAME="{keyword}">{keytext}</A>:</TH>
+<TD>
+{[choices]<INPUT TYPE="RADIO" NAME="{keyword}" {choices={defchoice}?CHECKED:} VALUE="{choices}">{text}}
+</TD>
+</TR>
diff --git a/templates/de/option-conflict.tmpl b/templates/de/option-conflict.tmpl
new file mode 100644
index 000000000..8c59cdad6
--- /dev/null
+++ b/templates/de/option-conflict.tmpl
@@ -0,0 +1,7 @@
+<P><B>Error:</B> The following options are conflicting:</P>
+
+<UL>
+{[ckeyword]<LI><A HREF="#{ckeyword}">{ckeytext}</A></LI>
+}</UL>
+
+<P>Bitte &auml;ndern sie eine oder mehrere Einstellungen um die Konflikte zu l&ouml;sen.</P>
diff --git a/templates/de/option-header.tmpl b/templates/de/option-header.tmpl
new file mode 100644
index 000000000..464726a50
--- /dev/null
+++ b/templates/de/option-header.tmpl
@@ -0,0 +1,5 @@
+<DIV CLASS="tab" ID="{group_id}">
+
+<H3 ALIGN="CENTER">{group}</H3>
+
+<TABLE WIDTH="100%">
diff --git a/templates/de/option-pickmany.tmpl b/templates/de/option-pickmany.tmpl
new file mode 100644
index 000000000..067075aec
--- /dev/null
+++ b/templates/de/option-pickmany.tmpl
@@ -0,0 +1,6 @@
+<TR>
+<TH {conflicted=1?CLASS="conflict":CLASS="label"} WIDTH="50%"><A NAME="{keyword}">{keytext}</A>:</TH>
+<TD><SELECT NAME="{keyword}" MULTIPLE SIZE="10">
+{[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+</SELECT></TD>
+</TR>
diff --git a/templates/de/option-pickone.tmpl b/templates/de/option-pickone.tmpl
new file mode 100644
index 000000000..e467d5fd5
--- /dev/null
+++ b/templates/de/option-pickone.tmpl
@@ -0,0 +1,18 @@
+<TR>
+<TH {conflicted=1?CLASS="conflict":CLASS="label"} WIDTH="50%"><A NAME="{keyword}">{keytext}</A>:</TH>
+<TD><SELECT NAME="{keyword}" ID="select-{keyword}" ONCHANGE="update_paramtable('{keyword}')">
+{[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+</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:}>Punkte</OPTION>
+<OPTION VALUE="mm"{paramvalue=mm? SELECTED:}>Millimeter</OPTION>
+<OPTION VALUE="cm"{paramvalue=cm? SELECTED:}>Zentimeter</OPTION>
+<OPTION VALUE="in"{paramvalue=in? SELECTED:}>Zoll</OPTION>
+<OPTION VALUE="ft"{paramvalue=ft? SELECTED:}>Fu&szlig;</OPTION>
+<OPTION VALUE="m"{paramvalue=m? SELECTED:}>Meter</OPTION>
+</SELECT>:<INPUT TYPE="{inputtype}" NAME="{keyword}.{params}" VALUE="{paramvalue}">}</TD></TR>
+}</TABLE>
+</TD>:}
+</TR>
diff --git a/templates/de/option-trailer.tmpl b/templates/de/option-trailer.tmpl
new file mode 100644
index 000000000..87adedb44
--- /dev/null
+++ b/templates/de/option-trailer.tmpl
@@ -0,0 +1,5 @@
+</TABLE>
+
+<P ALIGN="CENTER"><INPUT TYPE="SUBMIT" VALUE="Standardeinstellungen festlegen"></P>
+
+</DIV>
diff --git a/templates/de/pager.tmpl b/templates/de/pager.tmpl
new file mode 100644
index 000000000..6bc63d673
--- /dev/null
+++ b/templates/de/pager.tmpl
@@ -0,0 +1,6 @@
+<TABLE CLASS="inset" SUMMARY="Seitenverwaltung">
+<TR>
+ <TD WIDTH="50%">{PREV?<FORM ACTION="{THISURL}" METHOD="GET"><INPUT TYPE="HIDDEN" NAME="QUERY" VALUE="{?QUERY}"><INPUT TYPE="HIDDEN" NAME="ORDER" VALUE="{?ORDER}"><INPUT TYPE="HIDDEN" NAME="WHICH_JOBS" VALUE="{?WHICH_JOBS}"><INPUT TYPE="HIDDEN" NAME="FIRST" VALUE="{PREV}"><INPUT TYPE="SUBMIT" VALUE="&#x25c0; Vorherige anzeigen"></FORM>:&nbsp;}</TD>
+ <TD WIDTH="50%" ALIGN="RIGHT">{NEXT?<FORM ACTION="{THISURL}" METHOD="GET"><INPUT TYPE="HIDDEN" NAME="QUERY" VALUE="{?QUERY}"><INPUT TYPE="HIDDEN" NAME="ORDER" VALUE="{?ORDER}"><INPUT TYPE="HIDDEN" NAME="WHICH_JOBS" VALUE="{?WHICH_JOBS}"><INPUT TYPE="HIDDEN" NAME="FIRST" VALUE="{NEXT}"><INPUT TYPE="SUBMIT" VALUE="N&auml;chste anzeigen &#x25b6;"></FORM>:&nbsp;}</TD>
+</TR>
+</TABLE>
diff --git a/templates/de/printer-accept.tmpl b/templates/de/printer-accept.tmpl
new file mode 100644
index 000000000..25045fa03
--- /dev/null
+++ b/templates/de/printer-accept.tmpl
@@ -0,0 +1,9 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Auftr&auml;ge von {is_class?Klasse:Drucker} {printer_name} akzeptieren</H2>
+
+<P>{is_class?Klasse:Drucker} <A
+HREF="/{is_class?classes:printers}/{printer_name}">{printer_name}</A>
+aktzeptiert jetzt Auftr&auml;ge.</P>
+
+</DIV>
diff --git a/templates/de/printer-added.tmpl b/templates/de/printer-added.tmpl
new file mode 100644
index 000000000..fe712beaa
--- /dev/null
+++ b/templates/de/printer-added.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Drucker hinzuf&uuml;gen</H2>
+
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> wurde erfolgreich
+hinzuf&uuml;gt.
+
+</DIV>
diff --git a/templates/de/printer-configured.tmpl b/templates/de/printer-configured.tmpl
new file mode 100644
index 000000000..60e27c2a5
--- /dev/null
+++ b/templates/de/printer-configured.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Standardeinstellungen f&uuml;r {printer_name} festlegen</H2>
+
+<P>Standardeinstellungen f&uuml;r {OP=set-class-options?Klasse <A HREF="/classes/{printer_name}">:Drucker <A HREF="/printers/{printer_name}">}{printer_name}</A>
+wurden erfolgreich gesetzt.
+
+</DIV>
diff --git a/templates/de/printer-confirm.tmpl b/templates/de/printer-confirm.tmpl
new file mode 100644
index 000000000..5290c85e5
--- /dev/null
+++ b/templates/de/printer-confirm.tmpl
@@ -0,0 +1,10 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Drucker {printer_name} l&ouml;schen</H2>
+
+<P><B>Warnung:</B> Sind sie sicher sie wollen den Drucker
+{printer_name} l&ouml;schen?</P>
+
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Drucker l&ouml;schen"></FORM></P>
+
+</DIV>
diff --git a/templates/de/printer-default.tmpl b/templates/de/printer-default.tmpl
new file mode 100644
index 000000000..ac2221f62
--- /dev/null
+++ b/templates/de/printer-default.tmpl
@@ -0,0 +1,13 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{is_class?Klasse:Drucker} {printer_name} als Standard festlegen</H2>
+
+<P>{is_class?Klasse:Drucker} <A
+HREF="/{is_class?classes:printers}/{printer_name}">{printer_name}</A>
+wurde zum Standarddrucker für diesen Server gemacht.</P>
+
+<BLOCKQUOTE><B>Notiz:</B> Die Einstellungen des Standarddruckers
+welche von Benutzern mittels dem <TT>lpoptions</TT> Befehl gesetzt wurden,
+&uuml;berschreiben diese Einstellung.</BLOCKQUOTE>
+
+</DIV>
diff --git a/templates/de/printer-deleted.tmpl b/templates/de/printer-deleted.tmpl
new file mode 100644
index 000000000..604611303
--- /dev/null
+++ b/templates/de/printer-deleted.tmpl
@@ -0,0 +1,7 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Drucker {printer_name} l&ouml;schen</H2>
+
+<P>Drucker {printer_name} wurde erfolgreich gel&ouml;scht.
+
+</DIV>
diff --git a/templates/de/printer-jobs-header.tmpl b/templates/de/printer-jobs-header.tmpl
new file mode 100644
index 000000000..4f3de9340
--- /dev/null
+++ b/templates/de/printer-jobs-header.tmpl
@@ -0,0 +1,3 @@
+<DIV CLASS="indent">
+<H3 CLASS="title">Auftr&auml;ge</H3>
+</DIV>
diff --git a/templates/de/printer-modified.tmpl b/templates/de/printer-modified.tmpl
new file mode 100644
index 000000000..b6e10bd4e
--- /dev/null
+++ b/templates/de/printer-modified.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Drucker {printer_name} &auml;ndern</H2>
+
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> wurde
+erfolgreich ge&auml;ndert.
+
+</DIV>
diff --git a/templates/de/printer-purge.tmpl b/templates/de/printer-purge.tmpl
new file mode 100644
index 000000000..1ff63ac0f
--- /dev/null
+++ b/templates/de/printer-purge.tmpl
@@ -0,0 +1,9 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Auftr&auml;ge f&uuml;r {is_class?die Klasse:den Drucker} {printer_name} verwerfen</H2>
+
+<P>Auftr&auml;ge f&uuml;r {is_class?die Klasse:den Drucker} <A
+HREF="/{is_class?classes:printers}/{printer_name}">{printer_name}</A>
+wurden verworfen.</P>
+
+</DIV>
diff --git a/templates/de/printer-reject.tmpl b/templates/de/printer-reject.tmpl
new file mode 100644
index 000000000..1a5de730f
--- /dev/null
+++ b/templates/de/printer-reject.tmpl
@@ -0,0 +1,9 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Auftr&auml;ge f&uuml;r {is_class?die Klasse:den Drucker} {printer_name} ablehnen</H2>
+
+<P>{is_class?Die Klasse:Der Drucker} <A
+HREF="/{is_class?classes:printers}/{printer_name}">{printer_name}</A>
+akzeptiert keine weiteren Auftr&auml;ge.</P>
+
+</DIV>
diff --git a/templates/de/printer-start.tmpl b/templates/de/printer-start.tmpl
new file mode 100644
index 000000000..7a78568e6
--- /dev/null
+++ b/templates/de/printer-start.tmpl
@@ -0,0 +1,9 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{is_class?Die Klasse:Den Drucker} {printer_name} fortfahren</H2>
+
+<P>{is_class?Die Klassen:Der Drucker} <A
+HREF="/{is_class?classes:printers}/{printer_name}">{printer_name}</A>
+wird fortgesetzt.</P>
+
+</DIV>
diff --git a/templates/de/printer-stop.tmpl b/templates/de/printer-stop.tmpl
new file mode 100644
index 000000000..b304bd929
--- /dev/null
+++ b/templates/de/printer-stop.tmpl
@@ -0,0 +1,9 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">{is_class?Die Klasse:Den Drucker} {printer_name} anhalten</H2>
+
+<P>{is_class?Die Klasse:Der Drucker} <A
+HREF="/{is_class?classes:printers}/{printer_name}">{printer_name}</A>
+wurde angehalten.</P>
+
+</DIV>
diff --git a/templates/de/printer.tmpl b/templates/de/printer.tmpl
new file mode 100644
index 000000000..330c070be
--- /dev/null
+++ b/templates/de/printer.tmpl
@@ -0,0 +1,45 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title"><A HREF="{printer_uri_supported}">{printer_name}</A>
+({printer_state=3?Frei:{printer_state=4?Besch&auml;ftig:Angehalten}},
+{printer_is_accepting_jobs=0?Auftr&auml;ge werden ablehnt:Auftr&auml;ge werden akzeptiert},
+{server_is_sharing_printers=0?Nicht:{printer_is_shared=0?Nicht:}} freigegeben{default_name={printer_name}?, Standarddrucker:})</H2>
+
+<FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
+<OPTION VALUE="">Wartung</OPTION>
+<OPTION VALUE="print-test-page">Testseite drucken</OPTION>
+{printer_commands~.*Clean.*?<OPTION VALUE="clean-print-heads">Druckk&ouml;pfe reinigen</OPTION>:}
+{printer_commands~.*PrintSelfTestPage.*?<OPTION VALUE="print-self-test-page">Selbsttest-Seite drucken</OPTION>:}
+{printer_state=5?<OPTION VALUE="start-printer">Drucker starten</OPTION>:<OPTION VALUE="stop-printer">Drucker stoppen</OPTION>}
+{printer_is_accepting_jobs=0?<OPTION VALUE="accept-jobs">Auftr&auml;ge akzeptieren</OPTION>:<OPTION VALUE="reject-jobs">Auftr&auml;ge ablehnen</OPTION>}
+<OPTION VALUE="move-jobs">Alle Auftr&auml;ge verschieben</OPTION>
+<OPTION VALUE="purge-jobs">Alle Auftr&auml;ge abbrechen</OPTION>
+</SELECT>
+<INPUT TYPE="SUBMIT" VALUE="Go" STYLE="display: none;">
+</FORM>
+
+<FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
+<SELECT NAME="OP" ONCHANGE="document.administration.submit();">
+<OPTION VALUE="">Administration</OPTION>
+<OPTION VALUE="modify-printer">Drucker &auml;ndern</OPTION>
+<OPTION VALUE="delete-printer">Drucker l&ouml;schen</OPTION>
+<OPTION VALUE="set-printer-options">Standardeinstellungen festlegen</OPTION>
+<OPTION VALUE="set-as-default">Als Standard festlegen</OPTION>
+<OPTION VALUE="set-allowed-users">Erlaubte Benutzer festlegen</OPTION>
+</SELECT>
+<INPUT TYPE="SUBMIT" VALUE="Go" STYLE="display: none;">
+</FORM>
+
+<TABLE SUMMARY="{printer_name}">
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Beschreibung:</TH><TD>{printer_info}</TD></TR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Ort:</TH><TD>{printer_location}</TD></TR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Treiber:</TH><TD>{printer_make_and_model} ({color_supported=1?color:grayscale}{sides_supported?, 2-sided printing:})<BR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Verbindung:</TH><TD>{device_uri}</TD></TR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Einstellungen:</TH><TD>job-sheets={job_sheets_default}
+media={media_default?{media_default}:unknown}
+{sides_default?sides={sides_default}:}</TD></TR>
+</TABLE>
+
+</DIV>
diff --git a/templates/de/printers-header.tmpl b/templates/de/printers-header.tmpl
new file mode 100644
index 000000000..d07f783f9
--- /dev/null
+++ b/templates/de/printers-header.tmpl
@@ -0,0 +1 @@
+<P ALIGN="CENTER">{total=0?Keine Drucker:Zeige {#printer_name} von {total} Drucker}.</P>
diff --git a/templates/de/printers.tmpl b/templates/de/printers.tmpl
new file mode 100644
index 000000000..2180a0818
--- /dev/null
+++ b/templates/de/printers.tmpl
@@ -0,0 +1,11 @@
+{#printer_name=0?:
+<TABLE CLASS="list" SUMMARY="Druckerliste">
+<THEAD>
+<TR><TH><A HREF="{THISURL}?QUERY={?QUERY}&amp;WHICH_JOBS={?WHICH_JOBS}&amp;FIRST={FIRST}&amp;ORDER={ORDER=dec?asc:dec}">{ORDER=dec?<SMALL>&#x25b2;</SMALL> Queue Name <SMALL>&#x25b2;</SMALL>:<SMALL>&#x25bc;</SMALL> Queue Name <SMALL>&#x25bc;</SMALL>}</A></TH><TH>Beschreibung</TH><TH>Ort</TH><TH>Marke und Modell</TH><TH>Status</TH></TR>
+</THEAD>
+<TBODY>
+{[printer_name]
+<TR><TD><A HREF="{printer_uri_supported}">{printer_name}</A></TD><TD>{printer_info}</TD><TD>{printer_location}</TD><TD>{printer_make_and_model}</TD><TD>{printer_state=3?Frei:{printer_state=4?Besch&auml;ftigt:Angehalten}}{printer_state_message? - "{printer_state_message}":}</TD></TR>
+}
+</TBODY>
+</TABLE></DIV>}
diff --git a/templates/de/restart.tmpl b/templates/de/restart.tmpl
new file mode 100644
index 000000000..245300f9c
--- /dev/null
+++ b/templates/de/restart.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Einstellungen &auml;ndern</H2>
+
+<P><IMG SRC="/images/wait.gif" WIDTH="16" HEIGHT="16" ALIGN="ABSMIDDLE"
+ALT="Busy Indicator"> Bitte warten Sie w&auml;hrend der Server neu startet...</P>
+
+</DIV>
diff --git a/templates/de/samba-export.tmpl b/templates/de/samba-export.tmpl
new file mode 100644
index 000000000..1cb202b90
--- /dev/null
+++ b/templates/de/samba-export.tmpl
@@ -0,0 +1,54 @@
+<SCRIPT TYPE="text/javascript"><!--
+function select_printers() {
+ var list = document.export_samba.EXPORT_NAME;
+ var sel = document.export_samba.EXPORT_ALL.checked;
+
+ for (i = 0; i < list.length; i ++) {
+ list.options[i].selected = sel;
+ }
+}
+--></SCRIPT>
+
+<FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
+
+<H2 CLASS="title">Drucker f&uuml;r Samba freigeben</H2>
+
+{error?<P>Kann Drucker nicht f&uuml;r Samba freigeben\:</P>
+<BLOCKQUOTE>{error}</BLOCKQUOTE>
+<P>Consult the <A HREF="/admin/log/error_log"
+TARGET="_blank">Fehlerprotokoll</A> Datei um mehr Informationen zu erhalten.</P>:
+<P>Diese Seite erlaubt es Ihnen Drucker f&uuml;r Samba bereitzustellen
+damit auf diese mittels Windows Clients &uuml;ber die Desktopsymbole
+<VAR>Netzwerk Nachbarn</VAR> oder <VAR>Netzwerkumgebung</VAR>
+zugegriffen werden kann. Sie müssen zuerst einen
+Windows PostScript Druckerteiber installieren wie diese in der Hilfe f&uuml;r <A
+HREF="/help/man-cupsaddsmb.html"
+TARGET="_blank">cupsaddsmb(8)</A> beschrieben ist.</P>}
+
+<TABLE>
+<TR>
+<TH CLASS="label">Drucker:</TH>
+<TD>
+<SELECT NAME="EXPORT_NAME" SIZE="10" MULTIPLE>
+{[printer_name]<OPTION VALUE="{printer_name}"{export_all? SELECTED:{printer_export? SELECTED:}}>{printer_name}}
+</SELECT><BR>
+<INPUT TYPE="CHECKBOX" NAME="EXPORT_ALL"{export_all? CHECKED:}
+onChange="select_printers()"> Alle Drucker freigeben
+</TD>
+</TR>
+<TR>
+<TH CLASS="label">Samba Benutzername:</TH>
+<TD><INPUT TYPE="TEXT" NAME="USERNAME" VALUE="{?USERNAME}"> (ben&ouml;tigt)</TD>
+</TR>
+<TR>
+<TH CLASS="label">Samba Passwort:</TH>
+<TD><INPUT TYPE="PASSWORD" NAME="PASSWORD" VALUE=""> (ben&ouml;tigt)</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD><INPUT TYPE="SUBMIT" VALUE="Drucker f&uuml;r Samba freigeben"></TD>
+</TR>
+</TABLE>
+
+</FORM>
diff --git a/templates/de/samba-exported.tmpl b/templates/de/samba-exported.tmpl
new file mode 100644
index 000000000..cf5db8894
--- /dev/null
+++ b/templates/de/samba-exported.tmpl
@@ -0,0 +1 @@
+<P>Drucker wurden erfolgreich f&uuml;r Samba freigegeben.</P>
diff --git a/templates/de/search.tmpl b/templates/de/search.tmpl
new file mode 100644
index 000000000..fd1d5d954
--- /dev/null
+++ b/templates/de/search.tmpl
@@ -0,0 +1,10 @@
+<FORM ACTION="{THIS_URL}" METHOD="GET">
+{WHICH_JOBS?<INPUT TYPE="HIDDEN" NAME="WHICH_JOBS" VALUE="{WHICH_JOBS}">:}
+{ORDER?<INPUT TYPE="HIDDEN" NAME="ORDER" VALUE="{ORDER}">:}
+
+<P ALIGN="CENTER"><B>Suche in
+{SEARCH_DEST?{SEARCH_DEST}:{SECTION=classes?Klassen:{SECTION=jobs?Auftr&auml;gen:Drucker}}}:</B>
+<INPUT TYPE="SEARCH" NAME="QUERY" VALUE="{?QUERY}" SIZE="40" PLACEHOLDER="" AUTOSAVE="org.cups.{SECTION}" RESULTS="20"> <INPUT
+TYPE="SUBMIT" VALUE="Suchen"> <INPUT TYPE="SUBMIT" NAME="CLEAR" VALUE="Leeren"></P>
+
+</FORM>
diff --git a/templates/de/set-printer-options-header.tmpl b/templates/de/set-printer-options-header.tmpl
new file mode 100644
index 000000000..dbe93f658
--- /dev/null
+++ b/templates/de/set-printer-options-header.tmpl
@@ -0,0 +1,25 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Standardeinstellungen f%uuml;r {printer_name} festlegen</H2>
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Drucker nach Standardeinstellungen fragen">:}
+
+<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>
+
+<H3 CLASS="title">{[group_id]
+<A HREF="#{group_id}">{group}</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</H3>
+
+<DIV CLASS="tabs">
diff --git a/templates/de/set-printer-options-trailer.tmpl b/templates/de/set-printer-options-trailer.tmpl
new file mode 100644
index 000000000..11adc7012
--- /dev/null
+++ b/templates/de/set-printer-options-trailer.tmpl
@@ -0,0 +1,16 @@
+</DIV>
+
+<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>
+
+</DIV>
diff --git a/templates/de/subscription-added.tmpl b/templates/de/subscription-added.tmpl
new file mode 100644
index 000000000..fe4f1cd42
--- /dev/null
+++ b/templates/de/subscription-added.tmpl
@@ -0,0 +1,5 @@
+<DIV CLASS="indent">
+
+<P>Subskription {subscription_name} wurde erfolgreich hinzugef&uuml;gt.</P>
+
+</DIV>
diff --git a/templates/de/subscription-canceled.tmpl b/templates/de/subscription-canceled.tmpl
new file mode 100644
index 000000000..56f7a977e
--- /dev/null
+++ b/templates/de/subscription-canceled.tmpl
@@ -0,0 +1,5 @@
+<DIV CLASS="indent">
+
+<P>Subskription #{notify_subscription_id} wurde gek&uuml;ndigt.</P>
+
+</DIV>
diff --git a/templates/de/test-page.tmpl b/templates/de/test-page.tmpl
new file mode 100644
index 000000000..82ce97166
--- /dev/null
+++ b/templates/de/test-page.tmpl
@@ -0,0 +1,8 @@
+<DIV CLASS="indent">
+
+<H2 CLASS="title">Print Test Page On {printer_name}</H2>
+
+<P>Testseite gesendet; Auftrags ID ist <A HREF="/{SECTION}/{printer_name}">
+{printer_name}-{job_id}</A>.</P>
+
+</DIV>
diff --git a/templates/de/trailer.tmpl b/templates/de/trailer.tmpl
new file mode 100644
index 000000000..bdf09f556
--- /dev/null
+++ b/templates/de/trailer.tmpl
@@ -0,0 +1,8 @@
+</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR><TD CLASS="trailer">CUPS und das CUPS Logo sind
+eingetragene Warenzeichen der <A HREF="http://www.apple.com">Apple Inc.</A> CUPS
+ist urheberrechtlich gesch&uuml;tzt 2007-2009 von Apple Inc, alle Rechte vorbehalten.</TD></TR>
+</TABLE>
+</BODY>
+</HTML>
diff --git a/templates/de/users.tmpl b/templates/de/users.tmpl
new file mode 100644
index 000000000..acb889272
--- /dev/null
+++ b/templates/de/users.tmpl
@@ -0,0 +1,29 @@
+<DIV CLASS="indent">
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+{IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
+
+<H2 CLASS="title">Erlaubte Benutzer f&uuml;r {printer_name}</H2>
+
+<TABLE>
+<TR>
+<TH CLASS="label">Benutzer:</TH>
+<TD>
+<INPUT TYPE='TEXT' NAME='users' SIZE='60' VALUE='{?requesting_user_name_allowed}{?requesting_user_name_denied}'>
+<BR>
+<INPUT TYPE='RADIO' NAME='type' VALUE='requesting-user-name-allowed' {requesting_user_name_allowed?checked:}>Erlaube diesen Benutzern zu drucken
+<INPUT TYPE='RADIO' NAME='type' VALUE='requesting-user-name-denied' {requesting_user_name_denied?checked:}>Verweigere diesen Benutzern zu drucken
+</TD>
+</TR>
+<TR>
+<TD></TD>
+<TD>
+<INPUT TYPE="SUBMIT" VALUE="Erlaubte Benutzer festlegen">
+</TD>
+</TR>
+</TABLE>
+
+</FORM>
+</DIV>