/*
- * "$Id: printers.c 5047 2006-02-02 05:14:15Z mike $"
+ * "$Id: printers.c 6970 2007-09-17 23:58:28Z mike $"
*
* Printer routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 2007-2008 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products 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 missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * 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/".
*
* Contents:
*
* cupsdAddPrinter() - Add a printer to the system.
- * cupsdAddPrinterFilter() - Add a MIME filter for a printer.
* cupsdAddPrinterHistory() - Add the current printer state to the history.
* cupsdAddPrinterUser() - Add a user to the ACL.
+ * cupsdCreateCommonData() - Create the common printer data.
* cupsdDeleteAllPrinters() - Delete all printers from the system.
* cupsdDeletePrinter() - Delete a printer from the system.
- * cupsdDeletePrinterFilters() - Delete all MIME filters for a printer.
* cupsdFindPrinter() - Find a printer in the list.
* cupsdFreePrinterUsers() - Free allow/deny users.
* cupsdLoadAllPrinters() - Load printers from the printers.conf file.
+ * cupsdRenamePrinter() - Rename a printer.
* cupsdSaveAllPrinters() - Save all printer definitions to the
* printers.conf file.
+ * cupsdSetAuthInfoRequired() - Set the required authentication info.
+ * cupsdSetPrinterAttr() - Set a printer attribute.
* cupsdSetPrinterAttrs() - Set printer attributes based upon the PPD
* file.
* cupsdSetPrinterReasons() - Set/update the reasons strings.
* cupsdWritePrintcap() - Write a pseudo-printcap file for older
* applications that need it...
* cupsdSanitizeURI() - Sanitize a device URI...
+ * add_printer_defaults() - Add name-default attributes to the printer
+ * attributes.
+ * add_printer_filter() - Add a MIME filter for a printer.
+ * add_printer_formats() - Add document-format-supported values for
+ * a printer.
* compare_printers() - Compare two printers.
+ * delete_printer_filters() - Delete all MIME filters for a printer.
* write_irix_config() - Update the config files used by the IRIX
* desktop tools.
* write_irix_state() - Update the status files used by IRIX
*/
#include "cupsd.h"
+#include <cups/dir.h>
/*
* Local functions...
*/
+static void add_printer_defaults(cupsd_printer_t *p);
+static void add_printer_filter(cupsd_printer_t *p, mime_type_t *type,
+ const char *filter);
+static void add_printer_formats(cupsd_printer_t *p);
static int compare_printers(void *first, void *second, void *data);
+static void delete_printer_filters(cupsd_printer_t *p);
#ifdef __sgi
static void write_irix_config(cupsd_printer_t *p);
static void write_irix_state(cupsd_printer_t *p);
cupsdSetString(&p->job_sheets[0], "none");
cupsdSetString(&p->job_sheets[1], "none");
- cupsdSetString(&p->error_policy, "stop-printer");
+ cupsdSetString(&p->error_policy, ErrorPolicy);
cupsdSetString(&p->op_policy, DefaultPolicy);
p->op_policy_ptr = DefaultPolicyPtr;
}
-/*
- * 'cupsdAddPrinterFilter()' - Add a MIME filter for a printer.
- */
-
-void
-cupsdAddPrinterFilter(
- cupsd_printer_t *p, /* I - Printer to add to */
- const char *filter) /* I - Filter to add */
-{
- char super[MIME_MAX_SUPER], /* Super-type for filter */
- type[MIME_MAX_TYPE], /* Type for filter */
- program[1024]; /* Program/filter name */
- int cost; /* Cost of filter */
- mime_type_t *temptype; /* MIME type looping var */
-
-
- /*
- * Range check input...
- */
-
- if (p == NULL || p->filetype == NULL || filter == NULL)
- return;
-
- /*
- * Parse the filter string; it should be in the following format:
- *
- * super/type cost program
- */
-
- if (sscanf(filter, "%15[^/]/%31s%d%1023s", super, type, &cost, program) != 4)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdAddPrinterFilter: Invalid filter string \"%s\"!",
- filter);
- return;
- }
-
- /*
- * Add the filter to the MIME database, supporting wildcards as needed...
- */
-
- for (temptype = mimeFirstType(MimeDatabase);
- temptype;
- temptype = mimeNextType(MimeDatabase))
- if (((super[0] == '*' && strcasecmp(temptype->super, "printer")) ||
- !strcasecmp(temptype->super, super)) &&
- (type[0] == '*' || !strcasecmp(temptype->type, type)))
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "Adding filter %s/%s %s/%s %d %s",
- temptype->super, temptype->type,
- p->filetype->super, p->filetype->type,
- cost, program);
- mimeAddFilter(MimeDatabase, temptype, p->filetype, cost, program);
- }
-}
-
-
/*
* 'cupsdAddPrinterHistory()' - Add the current printer state to the history.
*/
{
int i; /* Looping var */
ipp_attribute_t *attr; /* Attribute data */
+ cups_dir_t *dir; /* Notifier directory */
+ cups_dentry_t *dent; /* Notifier directory entry */
+ cups_array_t *notifiers; /* Notifier array */
+ char filename[1024], /* Filename */
+ *notifier; /* Current notifier */
+ cupsd_policy_t *p; /* Current policy */
static const int nups[] = /* number-up-supported values */
{ 1, 2, 4, 6, 9, 16 };
- static const ipp_orient_t orients[4] =/* orientation-requested-supported values */
+ static const int orients[4] =/* orientation-requested-supported values */
{
IPP_PORTRAIT,
IPP_LANDSCAPE,
"1.0",
"1.1"
};
- static const ipp_op_t ops[] = /* operations-supported values */
+ static const int ops[] = /* operations-supported values */
{
IPP_PRINT_JOB,
IPP_VALIDATE_JOB,
CUPS_GET_PPDS,
CUPS_MOVE_JOB,
CUPS_AUTHENTICATE_JOB,
+ CUPS_GET_PPD,
+ CUPS_GET_DOCUMENT,
IPP_RESTART_JOB
};
static const char * const charsets[] =/* charset-supported values */
sizeof(compressions) / sizeof(compressions[0]),
NULL, compressions);
- /* TODO: move to printer-specific section! */
- /* copies-default */
- ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "copies-default", 1);
-
/* copies-supported */
ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies);
- /* TODO: move to printer-specific section! */
- /* document-format-default */
- ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
- "document-format-default", NULL, "application/octet-stream");
-
- /* document-format-supported */
- ippAddStrings(CommonData, IPP_TAG_PRINTER,
- (ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
- "document-format-supported", NumMimeTypes, NULL, MimeTypes);
+ /* cups-version */
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_TEXT, "cups-version",
+ NULL, CUPS_SVERSION + 6);
/* generated-natural-language-supported */
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
"ipp-versions-supported", sizeof(versions) / sizeof(versions[0]),
NULL, versions);
- /* TODO: move to printer-specific section! */
- /* job-hold-until-default */
- ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "job-hold-until-default", NULL, "no-hold");
-
/* job-hold-until-supported */
ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"job-hold-until-supported", sizeof(holds) / sizeof(holds[0]),
NULL, holds);
- /* TODO: move to printer-specific section! */
- /* job-priority-default */
- ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "job-priority-default", 50);
-
/* job-priority-supported */
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-priority-supported", 100);
if (attr == NULL)
cupsdLogMessage(CUPSD_LOG_EMERG,
- "cupsdSetPrinterAttrs: Unable to allocate memory for "
+ "Unable to allocate memory for "
"job-sheets-supported attribute: %s!", strerror(errno));
else if (!Classification || ClassifyOverride)
{
cupsd_banner_t *banner; /* Current banner */
- attr->values[0].string.text = _cups_sp_alloc("none");
+ attr->values[0].string.text = _cupsStrAlloc("none");
for (i = 1, banner = (cupsd_banner_t *)cupsArrayFirst(Banners);
banner;
i ++, banner = (cupsd_banner_t *)cupsArrayNext(Banners))
- attr->values[i].string.text = _cups_sp_alloc(banner->name);
+ attr->values[i].string.text = _cupsStrAlloc(banner->name);
}
}
else
(int)(sizeof(notify_attrs) / sizeof(notify_attrs[0])),
NULL, notify_attrs);
- /* TODO: move to printer-specific section! */
- /* notify-lease-duration-default */
- ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "notify-lease-duration-default", DefaultLeaseDuration);
-
/* notify-lease-duration-supported */
ippAddRange(CommonData, IPP_TAG_PRINTER,
"notify-lease-duration-supported", 0,
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"notify-max-events-supported", MaxEvents);
- /* notify-notify-events-default */
- ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "notify-events-default", NULL, "job-completed");
-
- /* notify-notify-events-supported */
+ /* notify-events-supported */
ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"notify-events-supported",
(int)(sizeof(notify_events) / sizeof(notify_events[0])),
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"notify-pull-method-supported", NULL, "ippget");
- /* TODO: scan notifier directory */
/* notify-schemes-supported */
- ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "notify-schemes-supported", NULL, "mailto");
+ snprintf(filename, sizeof(filename), "%s/notifier", ServerBin);
+ if ((dir = cupsDirOpen(filename)) != NULL)
+ {
+ notifiers = cupsArrayNew((cups_array_func_t)strcmp, NULL);
- /* TODO: move to printer-specific section! */
- /* number-up-default */
- ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "number-up-default", 1);
+ while ((dent = cupsDirRead(dir)) != NULL)
+ if (S_ISREG(dent->fileinfo.st_mode) &&
+ (dent->fileinfo.st_mode & S_IXOTH) != 0)
+ cupsArrayAdd(notifiers, _cupsStrAlloc(dent->filename));
+
+ if (cupsArrayCount(notifiers) > 0)
+ {
+ attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "notify-schemes-supported",
+ cupsArrayCount(notifiers), NULL, NULL);
+
+ for (i = 0, notifier = (char *)cupsArrayFirst(notifiers);
+ notifier;
+ i ++, notifier = (char *)cupsArrayNext(notifiers))
+ attr->values[i].string.text = notifier;
+ }
+
+ cupsArrayDelete(notifiers);
+ cupsDirClose(dir);
+ }
/* number-up-supported */
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
/* operations-supported */
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"operations-supported",
- sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops);
-
- /* TODO: move to printer-specific section! */
- /* orientation-requested-default */
- ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "orientation-requested-default", IPP_PORTRAIT);
+ sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, ops);
/* orientation-requested-supported */
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "orientation-requested-supported", 4, (int *)orients);
+ "orientation-requested-supported", 4, orients);
/* page-ranges-supported */
ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1);
/* printer-op-policy-supported */
attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
- "printer-op-policy-supported", NumPolicies, NULL, NULL);
- for (i = 0; i < NumPolicies; i ++)
- attr->values[i].string.text = _cups_sp_alloc(Policies[i]->name);
+ "printer-op-policy-supported", cupsArrayCount(Policies),
+ NULL, NULL);
+ for (i = 0, p = (cupsd_policy_t *)cupsArrayFirst(Policies);
+ p;
+ i ++, p = (cupsd_policy_t *)cupsArrayNext(Policies))
+ attr->values[i].string.text = _cupsStrAlloc(p->name);
+
+ ippAddBoolean(CommonData, IPP_TAG_PRINTER, "server-is-sharing-printers",
+ BrowseLocalProtocols != 0 && Browsing);
}
cupsArrayRemove(Printers, p);
+ if (p->type & CUPS_PRINTER_IMPLICIT)
+ cupsArrayRemove(ImplicitPrinters, p);
+
/*
* Remove the dummy interface/icon/option files under IRIX...
*/
dp = (cupsd_printer_t *)cupsArrayNext(Printers))
if (dp != p && (dp->type & CUPS_PRINTER_DEFAULT))
{
- DefaultPrinter = p;
+ DefaultPrinter = dp;
break;
}
}
}
/*
- * Remove this printer from any classes and send a browse delete message...
+ * Remove this printer from any classes...
*/
if (!(p->type & CUPS_PRINTER_IMPLICIT))
{
cupsdDeletePrinterFromClasses(p);
- cupsdSendBrowseDelete(p);
+
+ /*
+ * Deregister from any browse protocols...
+ */
+
+ cupsdDeregisterPrinter(p, 1);
}
/*
ippDelete(p->attrs);
- cupsdDeletePrinterFilters(p);
+ delete_printer_filters(p);
mimeDeleteType(MimeDatabase, p->filetype);
+ mimeDeleteType(MimeDatabase, p->prefiltertype);
cupsdFreePrinterUsers(p);
cupsdFreeQuotas(p);
cupsdClearString(&p->op_policy);
cupsdClearString(&p->error_policy);
+ cupsdClearString(&p->alert);
+ cupsdClearString(&p->alert_description);
+
+#ifdef HAVE_DNSSD
+ cupsdClearString(&p->product);
+ cupsdClearString(&p->pdl);
+#endif /* HAVE_DNSSD */
+
+ cupsArrayDelete(p->filetypes);
+
+ if (p->browse_attrs)
+ free(p->browse_attrs);
+
#ifdef __APPLE__
cupsdClearString(&p->recoverable);
#endif /* __APPLE__ */
+ cupsFreeOptions(p->num_options, p->options);
+
free(p);
/*
}
-/*
- * 'cupsdDeletePrinterFilters()' - Delete all MIME filters for a printer.
- */
-
-void
-cupsdDeletePrinterFilters(
- cupsd_printer_t *p) /* I - Printer to remove from */
-{
- mime_filter_t *filter; /* MIME filter looping var */
-
-
- /*
- * Range check input...
- */
-
- if (p == NULL)
- return;
-
- /*
- * Remove all filters from the MIME database that have a destination
- * type == printer...
- */
-
- for (filter = mimeFirstFilter(MimeDatabase);
- filter;
- filter = mimeNextFilter(MimeDatabase))
- if (filter->dst == p->filetype)
- {
- /*
- * Delete the current filter...
- */
-
- mimeDeleteFilter(MimeDatabase, filter);
- }
-}
-
-
/*
* 'cupsdFindDest()' - Find a destination in the list.
*/
if ((fp = cupsFileOpen(line, "r")) == NULL)
{
if (errno != ENOENT)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdLoadAllPrinters: Unable to open %s - %s", line,
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open %s - %s", line,
strerror(errno));
return;
}
* Add the printer and a base file type...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdLoadAllPrinters: Loading printer %s...", value);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading printer %s...", value);
p = cupsdAddPrinter(value);
p->accepting = 1;
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "</Printer>"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!p)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
+ }
+ else if (!strcasecmp(line, "AuthInfoRequired"))
+ {
+ if (!cupsdSetAuthInfoRequired(p, value, NULL))
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad AuthInfoRequired on line %d of printers.conf.",
+ linenum);
}
else if (!strcasecmp(line, "Info"))
{
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
+ }
+ }
+ else if (!strcasecmp(line, "Option") && value)
+ {
+ /*
+ * Option name value
+ */
+
+ for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+ if (!*valueptr)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Syntax error on line %d of printers.conf.", linenum);
+ else
+ {
+ for (; *valueptr && isspace(*valueptr & 255); *valueptr++ = '\0');
+
+ p->num_options = cupsAddOption(value, valueptr, p->num_options,
+ &(p->options));
}
}
else if (!strcasecmp(line, "PortMonitor"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "State"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "StateMessage"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "Shared"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "JobSheets"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "AllowUser"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "DenyUser"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "QuotaPeriod"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "PageLimit"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "KLimit"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "OpPolicy"))
{
if (value)
- cupsdSetString(&p->op_policy, value);
+ {
+ cupsd_policy_t *pol; /* Policy */
+
+
+ if ((pol = cupsdFindPolicy(value)) != NULL)
+ {
+ cupsdSetString(&p->op_policy, value);
+ p->op_policy_ptr = pol;
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad policy \"%s\" on line %d of printers.conf",
+ value, linenum);
+ }
else
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "ErrorPolicy"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else
}
+/*
+ * 'cupsdRenamePrinter()' - Rename a printer.
+ */
+
+void
+cupsdRenamePrinter(
+ cupsd_printer_t *p, /* I - Printer */
+ const char *name) /* I - New name */
+{
+ /*
+ * Remove the printer from the array(s) first...
+ */
+
+ cupsArrayRemove(Printers, p);
+
+ if (p->type & CUPS_PRINTER_IMPLICIT)
+ cupsArrayRemove(ImplicitPrinters, p);
+
+ /*
+ * Rename the printer type...
+ */
+
+ mimeDeleteType(MimeDatabase, p->filetype);
+ p->filetype = mimeAddType(MimeDatabase, "printer", name);
+
+ mimeDeleteType(MimeDatabase, p->prefiltertype);
+ p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", name);
+
+ /*
+ * Rename the printer...
+ */
+
+ cupsdSetString(&p->name, name);
+
+ /*
+ * Reset printer attributes...
+ */
+
+ cupsdSetPrinterAttrs(p);
+
+ /*
+ * Add the printer back to the printer array(s)...
+ */
+
+ cupsArrayAdd(Printers, p);
+
+ if (p->type & CUPS_PRINTER_IMPLICIT)
+ cupsArrayAdd(ImplicitPrinters, p);
+}
+
+
/*
* 'cupsdSaveAllPrinters()' - Save all printer definitions to the printers.conf
* file.
cupsd_printer_t *printer; /* Current printer class */
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
+ cups_option_t *option; /* Current option */
+ const char *ptr; /* Pointer into info/location */
/*
* Skip remote destinations and printer classes...
*/
- if ((printer->type & CUPS_PRINTER_REMOTE) ||
+ if ((printer->type & CUPS_PRINTER_DISCOVERED) ||
(printer->type & CUPS_PRINTER_CLASS) ||
(printer->type & CUPS_PRINTER_IMPLICIT))
continue;
else
cupsFilePrintf(fp, "<Printer %s>\n", printer->name);
+ if (printer->num_auth_info_required > 0)
+ {
+ cupsFilePrintf(fp, "AuthInfoRequired %s", printer->auth_info_required[0]);
+ for (i = 1; i < printer->num_auth_info_required; i ++)
+ cupsFilePrintf(fp, ",%s", printer->auth_info_required[i]);
+ cupsFilePutChar(fp, '\n');
+ }
+
if (printer->info)
- cupsFilePrintf(fp, "Info %s\n", printer->info);
+ {
+ if ((ptr = strchr(printer->info, '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the info string...
+ */
+
+ cupsFilePuts(fp, "Info ");
+ cupsFileWrite(fp, printer->info, ptr - printer->info);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "Info %s\n", printer->info);
+ }
if (printer->location)
- cupsFilePrintf(fp, "Location %s\n", printer->location);
+ {
+ if ((ptr = strchr(printer->info, '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the location string...
+ */
+ cupsFilePuts(fp, "Location ");
+ cupsFileWrite(fp, printer->location, ptr - printer->location);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "Location %s\n", printer->location);
+ }
if (printer->device_uri)
cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
if (printer->error_policy)
cupsFilePrintf(fp, "ErrorPolicy %s\n", printer->error_policy);
+ for (i = printer->num_options, option = printer->options;
+ i > 0;
+ i --, option ++)
+ cupsFilePrintf(fp, "Option %s %s\n", option->name, option->value);
+
cupsFilePuts(fp, "</Printer>\n");
#ifdef __sgi
/*
- * 'cupsdSetPrinterAttrs()' - Set printer attributes based upon the PPD file.
+ * 'cupsdSetAuthInfoRequired()' - Set the required authentication info.
*/
-void
-cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
+int /* O - 1 if value OK, 0 otherwise */
+cupsdSetAuthInfoRequired(
+ cupsd_printer_t *p, /* I - Printer */
+ const char *values, /* I - Plain text value (or NULL) */
+ ipp_attribute_t *attr) /* I - IPP attribute value (or NULL) */
{
- char uri[HTTP_MAX_URI];
- /* URI for printer */
- char resource[HTTP_MAX_URI];
- /* Resource portion of URI */
- int i; /* Looping var */
- char filename[1024]; /* Name of PPD file */
- int num_media; /* Number of media options */
- cupsd_location_t *auth; /* Pointer to authentication element */
- const char *auth_supported;/* Authentication supported */
- cups_ptype_t printer_type; /* Printer type data */
- ppd_file_t *ppd; /* PPD file data */
- ppd_option_t *input_slot, /* InputSlot options */
- *media_type, /* MediaType options */
- *page_size, /* PageSize options */
- *output_bin, /* OutputBin options */
- *media_quality; /* EFMediaQualityMode options */
- ppd_attr_t *ppdattr; /* PPD attribute */
- ipp_attribute_t *attr; /* Attribute data */
- ipp_value_t *val; /* Attribute value */
- int num_finishings; /* Number of finishings */
- ipp_finish_t finishings[5]; /* finishings-supported values */
- static const char * const sides[3] = /* sides-supported values */
- {
- "one",
- "two-long-edge",
- "two-short-edge"
- };
+ int i; /* Looping var */
- DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name,
- p->type));
+ p->num_auth_info_required = 0;
/*
- * Make sure that we have the common attributes defined...
+ * Do we have a plain text value?
*/
- if (!CommonData)
- cupsdCreateCommonData();
+ if (values)
+ {
+ /*
+ * Yes, grab the keywords...
+ */
- /*
- * Clear out old filters, if any...
- */
+ const char *end; /* End of current value */
- cupsdDeletePrinterFilters(p);
- /*
- * Figure out the authentication that is required for the printer.
- */
+ while (*values && p->num_auth_info_required < 4)
+ {
+ if ((end = strchr(values, ',')) == NULL)
+ end = values + strlen(values);
- auth_supported = "requesting-user-name";
- if (!(p->type & CUPS_PRINTER_REMOTE))
- {
- if (p->type & CUPS_PRINTER_CLASS)
- snprintf(resource, sizeof(resource), "/classes/%s", p->name);
- else
- snprintf(resource, sizeof(resource), "/printers/%s", p->name);
+ if ((end - values) == 4 && !strncmp(values, "none", 4))
+ {
+ if (p->num_auth_info_required != 0 || *end)
+ return (0);
- if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL)
- auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
+ p->auth_info_required[p->num_auth_info_required] = "none";
+ p->num_auth_info_required ++;
- if (auth)
- {
- if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST)
- auth_supported = "basic";
- else if (auth->type == AUTH_DIGEST)
- auth_supported = "digest";
+ return (1);
+ }
+ else if ((end - values) == 9 && !strncmp(values, "negotiate", 9))
+ {
+ if (p->num_auth_info_required != 0 || *end)
+ return (0);
- if (auth->type != AUTH_NONE)
- p->type |= CUPS_PRINTER_AUTHENTICATED;
+ p->auth_info_required[p->num_auth_info_required] = "negotiate";
+ p->num_auth_info_required ++;
+ }
+ else if ((end - values) == 6 && !strncmp(values, "domain", 6))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "domain";
+ p->num_auth_info_required ++;
+ }
+ else if ((end - values) == 8 && !strncmp(values, "password", 8))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "password";
+ p->num_auth_info_required ++;
+ }
+ else if ((end - values) == 8 && !strncmp(values, "username", 8))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "username";
+ p->num_auth_info_required ++;
+ }
else
- p->type &= ~CUPS_PRINTER_AUTHENTICATED;
+ return (0);
+
+ values = (*end) ? end + 1 : end;
+ }
+
+ if (p->num_auth_info_required == 0)
+ {
+ p->auth_info_required[0] = "none";
+ p->num_auth_info_required = 1;
}
+
+ /*
+ * Update the printer-type value as needed...
+ */
+
+ if (p->num_auth_info_required > 1 ||
+ strcmp(p->auth_info_required[0], "none"))
+ p->type |= CUPS_PRINTER_AUTHENTICATED;
else
p->type &= ~CUPS_PRINTER_AUTHENTICATED;
+
+ return (1);
}
/*
- * Create the required IPP attributes for a printer...
+ * Grab values from an attribute instead...
+ */
+
+ if (!attr || attr->num_values > 4)
+ return (0);
+
+ /*
+ * Update the printer-type value as needed...
+ */
+
+ if (attr->num_values > 1 ||
+ strcmp(attr->values[0].string.text, "none"))
+ p->type |= CUPS_PRINTER_AUTHENTICATED;
+ else
+ p->type &= ~CUPS_PRINTER_AUTHENTICATED;
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (!strcmp(attr->values[i].string.text, "none"))
+ {
+ if (p->num_auth_info_required != 0 || attr->num_values != 1)
+ return (0);
+
+ p->auth_info_required[p->num_auth_info_required] = "none";
+ p->num_auth_info_required ++;
+
+ return (1);
+ }
+ else if (!strcmp(attr->values[i].string.text, "negotiate"))
+ {
+ if (p->num_auth_info_required != 0 || attr->num_values != 1)
+ return (0);
+
+ p->auth_info_required[p->num_auth_info_required] = "negotiate";
+ p->num_auth_info_required ++;
+
+ return (1);
+ }
+ else if (!strcmp(attr->values[i].string.text, "domain"))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "domain";
+ p->num_auth_info_required ++;
+ }
+ else if (!strcmp(attr->values[i].string.text, "password"))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "password";
+ p->num_auth_info_required ++;
+ }
+ else if (!strcmp(attr->values[i].string.text, "username"))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "username";
+ p->num_auth_info_required ++;
+ }
+ else
+ return (0);
+ }
+
+ return (1);
+}
+
+
+/*
+ * 'cupsdSetPrinterAttr()' - Set a printer attribute.
+ */
+
+void
+cupsdSetPrinterAttr(
+ cupsd_printer_t *p, /* I - Printer */
+ const char *name, /* I - Attribute name */
+ char *value) /* I - Attribute value string */
+{
+ ipp_attribute_t *attr; /* Attribute */
+ int i, /* Looping var */
+ count; /* Number of values */
+ char *ptr; /* Pointer into value */
+ ipp_tag_t value_tag; /* Value tag for this attribute */
+
+
+ /*
+ * Count the number of values...
+ */
+
+ for (count = 1, ptr = value;
+ (ptr = strchr(ptr, ',')) != NULL;
+ ptr ++, count ++);
+
+ /*
+ * Then add or update the attribute as needed...
+ */
+
+ if (!strcmp(name, "marker-levels"))
+ {
+ /*
+ * Integer values...
+ */
+
+ if ((attr = ippFindAttribute(p->attrs, name, IPP_TAG_INTEGER)) != NULL &&
+ attr->num_values < count)
+ {
+ ippDeleteAttribute(p->attrs, attr);
+ attr = NULL;
+ }
+
+ if (attr)
+ attr->num_values = count;
+ else
+ attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, name,
+ count, NULL);
+
+ if (!attr)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for printer attribute "
+ "(%d values)", count);
+ return;
+ }
+
+ for (i = 0; i < count; i ++)
+ {
+ if ((ptr = strchr(value, ',')) != NULL)
+ *ptr++ = '\0';
+
+ attr->values[i].integer = strtol(value, NULL, 10);
+
+ if (ptr)
+ value = ptr;
+ }
+ }
+ else
+ {
+ /*
+ * Name or keyword values...
+ */
+
+ if (!strcmp(name, "marker-types"))
+ value_tag = IPP_TAG_KEYWORD;
+ else
+ value_tag = IPP_TAG_NAME;
+
+ if ((attr = ippFindAttribute(p->attrs, name, value_tag)) != NULL &&
+ attr->num_values < count)
+ {
+ ippDeleteAttribute(p->attrs, attr);
+ attr = NULL;
+ }
+
+ if (attr)
+ attr->num_values = count;
+ else
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, value_tag, name,
+ count, NULL, NULL);
+
+ if (!attr)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for printer attribute "
+ "(%d values)", count);
+ return;
+ }
+
+ for (i = 0; i < count; i ++)
+ {
+ if ((ptr = strchr(value, ',')) != NULL)
+ *ptr++ = '\0';
+
+ _cupsStrFree(attr->values[i].string.text);
+ attr->values[i].string.text = _cupsStrAlloc(value);
+
+ if (ptr)
+ value = ptr;
+ }
+ }
+}
+
+
+/*
+ * 'cupsdSetPrinterAttrs()' - Set printer attributes based upon the PPD file.
+ */
+
+void
+cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
+{
+ int i, /* Looping var */
+ length; /* Length of browse attributes */
+ char uri[HTTP_MAX_URI]; /* URI for printer */
+ char resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ char filename[1024]; /* Name of PPD file */
+ int num_air; /* Number of auth-info-required values */
+ const char * const *air; /* auth-info-required values */
+ int num_media; /* Number of media options */
+ cupsd_location_t *auth; /* Pointer to authentication element */
+ const char *auth_supported; /* Authentication supported */
+ ppd_file_t *ppd; /* PPD file data */
+ ppd_option_t *input_slot, /* InputSlot options */
+ *media_type, /* MediaType options */
+ *page_size, /* PageSize options */
+ *output_bin, /* OutputBin options */
+ *media_quality, /* EFMediaQualityMode options */
+ *duplex; /* Duplex options */
+ ppd_attr_t *ppdattr; /* PPD attribute */
+ ipp_attribute_t *attr; /* Attribute data */
+ ipp_value_t *val; /* Attribute value */
+ int num_finishings; /* Number of finishings */
+ int finishings[5]; /* finishings-supported values */
+ cups_option_t *option; /* Current printer option */
+ static const char * const sides[3] = /* sides-supported values */
+ {
+ "one-sided",
+ "two-sided-long-edge",
+ "two-sided-short-edge"
+ };
+ static const char * const air_userpass[] =
+ { /* Basic/Digest authentication */
+ "username",
+ "password"
+ };
+#ifdef HAVE_GSSAPI
+ static const char * const air_negotiate[] =
+ { /* Kerberos authentication */
+ "negotiate"
+ };
+#endif /* HAVE_GSSAPI */
+ static const char * const air_none[] =
+ { /* No authentication */
+ "none"
+ };
+
+
+ DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name,
+ p->type));
+
+ /*
+ * Make sure that we have the common attributes defined...
+ */
+
+ if (!CommonData)
+ cupsdCreateCommonData();
+
+ /*
+ * Clear out old filters, if any...
+ */
+
+ delete_printer_filters(p);
+
+ /*
+ * Figure out the authentication that is required for the printer.
+ */
+
+ auth_supported = "requesting-user-name";
+ num_air = 1;
+ air = air_none;
+
+ if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
+ {
+ num_air = p->num_auth_info_required;
+ air = p->auth_info_required;
+
+ if (!strcmp(air[0], "username"))
+ auth_supported = "basic";
+ else
+ auth_supported = "negotiate";
+ }
+ else if (!(p->type & CUPS_PRINTER_DISCOVERED))
+ {
+ if (p->type & CUPS_PRINTER_CLASS)
+ snprintf(resource, sizeof(resource), "/classes/%s", p->name);
+ else
+ snprintf(resource, sizeof(resource), "/printers/%s", p->name);
+
+ if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
+ auth->type == CUPSD_AUTH_NONE)
+ auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
+
+ if (auth)
+ {
+ if (auth->type == CUPSD_AUTH_BASIC || auth->type == CUPSD_AUTH_BASICDIGEST)
+ {
+ auth_supported = "basic";
+ num_air = 2;
+ air = air_userpass;
+ }
+ else if (auth->type == CUPSD_AUTH_DIGEST)
+ {
+ auth_supported = "digest";
+ num_air = 2;
+ air = air_userpass;
+ }
+#ifdef HAVE_GSSAPI
+ else if (auth->type == CUPSD_AUTH_NEGOTIATE)
+ {
+ auth_supported = "negotiate";
+ num_air = 1;
+ air = air_negotiate;
+ }
+#endif /* HAVE_GSSAPI */
+
+ if (auth->type != CUPSD_AUTH_NONE)
+ p->type |= CUPS_PRINTER_AUTHENTICATED;
+ else
+ p->type &= ~CUPS_PRINTER_AUTHENTICATED;
+ }
+ else
+ p->type &= ~CUPS_PRINTER_AUTHENTICATED;
+ }
+ else if (p->type & CUPS_PRINTER_AUTHENTICATED)
+ {
+ num_air = 2;
+ air = air_userpass;
+ }
+
+ /*
+ * Create the required IPP attributes for a printer...
*/
if (p->attrs)
"job-k-limit", p->k_limit);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-page-limit", p->page_limit);
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "auth-info-required", num_air, NULL, air);
- if (cupsArrayCount(Banners) > 0 && !(p->type & CUPS_PRINTER_REMOTE))
+ if (cupsArrayCount(Banners) > 0 && !(p->type & CUPS_PRINTER_DISCOVERED))
{
/*
* Setup the job-sheets-default attribute...
if (attr != NULL)
{
- attr->values[0].string.text = _cups_sp_alloc(Classification ?
+ attr->values[0].string.text = _cupsStrAlloc(Classification ?
Classification : p->job_sheets[0]);
- attr->values[1].string.text = _cups_sp_alloc(Classification ?
+ attr->values[1].string.text = _cupsStrAlloc(Classification ?
Classification : p->job_sheets[1]);
}
}
- printer_type = p->type;
-
- p->raw = 0;
+ p->raw = 0;
+ p->remote = 0;
- if (p->type & CUPS_PRINTER_REMOTE)
+ if (p->type & CUPS_PRINTER_DISCOVERED)
{
/*
* Tell the client this is a remote printer of some type...
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
p->uri);
- p->raw = 1;
+ p->raw = 1;
+ p->remote = 1;
}
else
{
for (i = 0; i < p->num_printers; i ++)
{
if (attr != NULL)
- attr->values[i].string.text = _cups_sp_alloc(p->printers[i]->uri);
+ attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->uri);
p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
}
if (attr != NULL)
{
for (i = 0; i < p->num_printers; i ++)
- attr->values[i].string.text = _cups_sp_alloc(p->printers[i]->name);
+ attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->name);
}
}
}
"pages-per-minute", ppd->throughput);
if (ppd->nickname)
+ {
+ /*
+ * The NickName can be localized in the character set specified
+ * by the LanugageEncoding attribute. However, ppdOpen2() has
+ * already converted the ppd->nickname member to UTF-8 for us
+ * (the original attribute value is available separately)
+ */
+
cupsdSetString(&p->make_model, ppd->nickname);
+ }
else if (ppd->modelname)
+ {
+ /*
+ * Model name can only contain specific characters...
+ */
+
cupsdSetString(&p->make_model, ppd->modelname);
+ }
else
cupsdSetString(&p->make_model, "Bad PPD File");
- if (p->make_model)
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
- "printer-make-and-model", NULL, p->make_model);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, p->make_model);
/*
* Add media options from the PPD file...
if (num_media == 0)
{
- cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdSetPrinterAttrs: The PPD file for printer %s "
- "contains no media options and is therefore "
- "invalid!", p->name);
+ cupsdLogMessage(CUPSD_LOG_CRIT,
+ "The PPD file for printer %s contains no media "
+ "options and is therefore invalid!", p->name);
}
else
{
if (input_slot != NULL)
for (i = 0; i < input_slot->num_choices; i ++, val ++)
- val->string.text = _cups_sp_alloc(input_slot->choices[i].choice);
+ val->string.text = _cupsStrAlloc(input_slot->choices[i].choice);
if (media_type != NULL)
for (i = 0; i < media_type->num_choices; i ++, val ++)
- val->string.text = _cups_sp_alloc(media_type->choices[i].choice);
+ val->string.text = _cupsStrAlloc(media_type->choices[i].choice);
if (media_quality != NULL)
for (i = 0; i < media_quality->num_choices; i ++, val ++)
- val->string.text = _cups_sp_alloc(media_quality->choices[i].choice);
+ val->string.text = _cupsStrAlloc(media_quality->choices[i].choice);
if (page_size != NULL)
{
for (i = 0; i < page_size->num_choices; i ++, val ++)
- val->string.text = _cups_sp_alloc(page_size->choices[i].choice);
+ val->string.text = _cupsStrAlloc(page_size->choices[i].choice);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, page_size->defchoice);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-default", NULL, page_size->defchoice);
}
else if (input_slot != NULL)
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, input_slot->defchoice);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-default", NULL, input_slot->defchoice);
else if (media_type != NULL)
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, media_type->defchoice);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-default", NULL, media_type->defchoice);
else if (media_quality != NULL)
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, media_quality->defchoice);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-default", NULL, media_quality->defchoice);
else
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, "none");
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-default", NULL, "none");
}
}
for (i = 0, val = attr->values;
i < output_bin->num_choices;
i ++, val ++)
- val->string.text = _cups_sp_alloc(output_bin->choices[i].choice);
+ val->string.text = _cupsStrAlloc(output_bin->choices[i].choice);
}
}
* Duplexing, etc...
*/
- if (ppdFindOption(ppd, "Duplex") != NULL)
+ if ((duplex = ppdFindOption(ppd, "Duplex")) == NULL)
+ if ((duplex = ppdFindOption(ppd, "EFDuplex")) == NULL)
+ if ((duplex = ppdFindOption(ppd, "EFDuplexing")) == NULL)
+ if ((duplex = ppdFindOption(ppd, "KD03Duplex")) == NULL)
+ duplex = ppdFindOption(ppd, "JCLDuplex");
+
+ if (duplex && duplex->num_choices > 1)
{
p->type |= CUPS_PRINTER_DUPLEX;
- ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-supported",
- 3, NULL, sides);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-default",
- NULL, "one");
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "sides-supported", 3, NULL, sides);
+
+ if (!strcasecmp(duplex->defchoice, "DuplexTumble"))
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "sides-default", NULL, "two-sided-short-edge");
+ else if (!strcasecmp(duplex->defchoice, "DuplexNoTumble"))
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "sides-default", NULL, "two-sided-long-edge");
+ else
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "sides-default", NULL, "one-sided");
}
if (ppdFindOption(ppd, "Collate") != NULL)
* handle "raw" printing by users.
*/
- cupsdAddPrinterFilter(p, "application/vnd.cups-raw 0 -");
+ add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -");
+
+ /*
+ * Add any pre-filters in the PPD file...
+ */
+
+ if ((ppdattr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
+ {
+ p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name);
+
+ for (; ppdattr; ppdattr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL))
+ if (ppdattr->value)
+ add_printer_filter(p, p->prefiltertype, ppdattr->value);
+ }
/*
* Add any filters in the PPD file...
for (i = 0; i < ppd->num_filters; i ++)
{
DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i]));
- cupsdAddPrinterFilter(p, ppd->filters[i]);
+ add_printer_filter(p, p->filetype, ppd->filters[i]);
}
if (ppd->num_filters == 0)
* If there are no filters, add a PostScript printing filter.
*/
- cupsdAddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
+ add_printer_filter(p, p->filetype,
+ "application/vnd.cups-postscript 0 -");
}
/*
* Show current and available port monitors for this printer...
*/
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "port-monitor",
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
NULL, p->port_monitor ? p->port_monitor : "none");
-
for (i = 1, ppdattr = ppdFindAttr(ppd, "cupsPortMonitor", NULL);
ppdattr;
i ++, ppdattr = ppdFindNextAttr(ppd, "cupsPortMonitor", NULL));
i ++;
}
- attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
"port-monitor-supported", i, NULL, NULL);
- attr->values[0].string.text = _cups_sp_alloc("none");
+ attr->values[0].string.text = _cupsStrAlloc("none");
for (i = 1, ppdattr = ppdFindAttr(ppd, "cupsPortMonitor", NULL);
ppdattr;
i ++, ppdattr = ppdFindNextAttr(ppd, "cupsPortMonitor", NULL))
- attr->values[i].string.text = _cups_sp_alloc(ppdattr->value);
+ attr->values[i].string.text = _cupsStrAlloc(ppdattr->value);
if (ppd->protocols)
{
if (strstr(ppd->protocols, "TBCP"))
- attr->values[i].string.text = _cups_sp_alloc("tbcp");
+ attr->values[i].string.text = _cupsStrAlloc("tbcp");
else if (strstr(ppd->protocols, "BCP"))
- attr->values[i].string.text = _cups_sp_alloc("bcp");
+ attr->values[i].string.text = _cupsStrAlloc("bcp");
}
+#ifdef HAVE_DNSSD
+ cupsdSetString(&p->product, ppd->product);
+#endif /* HAVE_DNSSD */
+
+ if (ppdFindAttr(ppd, "APRemoteQueueID", NULL))
+ p->type |= CUPS_PRINTER_REMOTE;
+
/*
* Close the PPD and set the type...
*/
ppdClose(ppd);
-
- printer_type = p->type;
}
else if (!access(filename, 0))
{
pstatus = ppdLastError(&pline);
- cupsdLogMessage(CUPSD_LOG_ERROR, "PPD file for %s cannot be loaded!", p->name);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "PPD file for %s cannot be loaded!",
+ p->name);
if (pstatus <= PPD_ALLOC_ERROR)
cupsdLogMessage(CUPSD_LOG_ERROR, "%s", strerror(errno));
else
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s on line %d.", ppdErrorString(pstatus),
- pline);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s on line %d.",
+ ppdErrorString(pstatus), pline);
- cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.",
- filename);
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Hint: Run \"cupstestppd %s\" and fix any errors.",
+ filename);
/*
* Add a filter from application/vnd.cups-raw to printer/name to
* handle "raw" printing by users.
*/
- cupsdAddPrinterFilter(p, "application/vnd.cups-raw 0 -");
+ add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -");
/*
* Add a PostScript filter, since this is still possibly PS printer.
*/
- cupsdAddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
+ add_printer_filter(p, p->filetype,
+ "application/vnd.cups-postscript 0 -");
}
else
{
snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot,
p->name);
- if (access(filename, X_OK) == 0)
+ if (!access(filename, X_OK))
{
/*
* Yes, we have a System V style interface script; use it!
*/
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
- "printer-make-and-model", NULL, "Local System V Printer");
+ "printer-make-and-model", NULL,
+ "Local System V Printer");
snprintf(filename, sizeof(filename), "*/* 0 %s/interfaces/%s",
ServerRoot, p->name);
- cupsdAddPrinterFilter(p, filename);
+ add_printer_filter(p, p->filetype, filename);
}
else if (p->device_uri &&
!strncmp(p->device_uri, "ipp://", 6) &&
* Tell the client this is really a hard-wired remote printer.
*/
- printer_type |= CUPS_PRINTER_REMOTE;
+ p->type |= CUPS_PRINTER_REMOTE;
/*
* Point the printer-uri-supported attribute to the
* Print all files directly...
*/
- p->raw = 1;
+ p->raw = 1;
+ p->remote = 1;
}
else
{
}
ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "finishings-supported", num_finishings, (int *)finishings);
+ "finishings-supported", num_finishings, finishings);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"finishings-default", IPP_FINISHINGS_NONE);
}
}
+ /*
+ * Force sharing off for remote queues...
+ */
+
+ if (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT))
+ p->shared = 0;
+ else
+ {
+ /*
+ * Copy the printer options into a browse attributes string we can re-use.
+ */
+
+ const char *valptr; /* Pointer into value */
+ char *attrptr; /* Pointer into attribute string */
+
+
+ /*
+ * Free the old browse attributes as needed...
+ */
+
+ if (p->browse_attrs)
+ free(p->browse_attrs);
+
+ /*
+ * Compute the length of all attributes + job-sheets, lease-duration,
+ * and BrowseLocalOptions.
+ */
+
+ for (length = 1, i = p->num_options, option = p->options;
+ i > 0;
+ i --, option ++)
+ {
+ length += strlen(option->name) + 2;
+
+ if (option->value)
+ {
+ for (valptr = option->value; *valptr; valptr ++)
+ if (strchr(" \"\'\\", *valptr))
+ length += 2;
+ else
+ length ++;
+ }
+ }
+
+ length += 13 + strlen(p->job_sheets[0]) + strlen(p->job_sheets[1]);
+ length += 32;
+ if (BrowseLocalOptions)
+ length += 12 + strlen(BrowseLocalOptions);
+
+ if (p->num_auth_info_required > 0)
+ {
+ length += 18; /* auth-info-required */
+
+ for (i = 0; i < p->num_auth_info_required; i ++)
+ length += strlen(p->auth_info_required[i]) + 1;
+ }
+
+ /*
+ * Allocate the new string...
+ */
+
+ if ((p->browse_attrs = calloc(1, length)) == NULL)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate %d bytes for browse data!",
+ length);
+ else
+ {
+ /*
+ * Got the allocated string, now copy the options and attributes over...
+ */
+
+ sprintf(p->browse_attrs, "job-sheets=%s,%s lease-duration=%d",
+ p->job_sheets[0], p->job_sheets[1], BrowseTimeout);
+ attrptr = p->browse_attrs + strlen(p->browse_attrs);
+
+ if (BrowseLocalOptions)
+ {
+ sprintf(attrptr, " ipp-options=%s", BrowseLocalOptions);
+ attrptr += strlen(attrptr);
+ }
+
+ for (i = p->num_options, option = p->options;
+ i > 0;
+ i --, option ++)
+ {
+ *attrptr++ = ' ';
+ strcpy(attrptr, option->name);
+ attrptr += strlen(attrptr);
+
+ if (option->value)
+ {
+ *attrptr++ = '=';
+
+ for (valptr = option->value; *valptr; valptr ++)
+ {
+ if (strchr(" \"\'\\", *valptr))
+ *attrptr++ = '\\';
+
+ *attrptr++ = *valptr;
+ }
+ }
+ }
+
+ if (p->num_auth_info_required > 0)
+ {
+ strcpy(attrptr, "auth-info-required");
+ attrptr += 18;
+
+ for (i = 0; i < p->num_auth_info_required; i ++)
+ {
+ *attrptr++ = i ? ',' : '=';
+ strcpy(attrptr, p->auth_info_required[i]);
+ attrptr += strlen(attrptr);
+ }
+ }
+ else
+ *attrptr = '\0';
+ }
+ }
+
+ /*
+ * Populate the document-format-supported attribute...
+ */
+
+ add_printer_formats(p);
+
DEBUG_printf(("cupsdSetPrinterAttrs: leaving name = %s, type = %x\n", p->name,
p->type));
+ /*
+ * Add name-default attributes...
+ */
+
+ add_printer_defaults(p);
+
#ifdef __sgi
/*
* Write the IRIX printer config and status files...
write_irix_config(p);
write_irix_state(p);
#endif /* __sgi */
+
+ /*
+ * Let the browse protocols reflect the change
+ */
+
+ cupsdRegisterPrinter(p);
}
p->num_reasons = 0;
}
+ if (!strcmp(s, "none"))
+ return;
+
/*
* Loop through all of the reasons...
*/
(p->num_reasons - i) * sizeof(char *));
i --;
+
+ if (!strcmp(reason, "paused") && p->state == IPP_PRINTER_STOPPED)
+ cupsdSetPrinterState(p, IPP_PRINTER_IDLE, 1);
}
}
else if (p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
{
p->reasons[i] = strdup(reason);
p->num_reasons ++;
+
+ if (!strcmp(reason, "paused") && p->state != IPP_PRINTER_STOPPED)
+ cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, 1);
}
}
}
* Can't set status of remote printers...
*/
- if (p->type & CUPS_PRINTER_REMOTE)
+ if (p->type & CUPS_PRINTER_DISCOVERED)
return;
/*
if (old_state != s)
{
+ cupsdAddEvent(s == IPP_PRINTER_STOPPED ? CUPSD_EVENT_PRINTER_STOPPED :
+ CUPSD_EVENT_PRINTER_STATE, p, NULL,
+ "%s \"%s\" state changed.",
+ (p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer",
+ p->name);
+
/*
* Let the browse code know this needs to be updated...
*/
cupsdAddPrinterHistory(p);
+ /*
+ * Let the browse protocols reflect the change...
+ */
+
+ cupsdRegisterPrinter(p);
+
/*
* Save the printer configuration if a printer goes from idle or processing
* to stopped (or visa-versa)...
*/
job->state->values[0].integer = IPP_JOB_PENDING;
+ job->state_value = IPP_JOB_PENDING;
cupsdSaveJob(job);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job,
+ "Job stopped due to printer being paused");
}
}
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
{
- if (!Browsing && (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_REMOTE)))
+ /*
+ * Remove remote printers if we are no longer browsing...
+ */
+
+ if (!Browsing &&
+ (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_DISCOVERED)))
{
if (p->type & CUPS_PRINTER_IMPLICIT)
cupsArrayRemove(ImplicitPrinters, p);
cupsArrayRestore(Printers);
continue;
}
- else if (!(p->type & CUPS_PRINTER_REMOTE))
- cupsdSetPrinterAttrs(p);
/*
* Update the operation policy pointer...
if ((p->op_policy_ptr = cupsdFindPolicy(p->op_policy)) == NULL)
p->op_policy_ptr = DefaultPolicyPtr;
+
+ /*
+ * Update printer attributes as needed...
+ */
+
+ if (!(p->type & CUPS_PRINTER_DISCOVERED))
+ cupsdSetPrinterAttrs(p);
}
}
const char * /* O - Printer or class name */
cupsdValidateDest(
- const char *hostname, /* I - Host name */
- const char *resource, /* I - Resource name */
+ const char *uri, /* I - Printer URI */
cups_ptype_t *dtype, /* O - Type (printer or class) */
cupsd_printer_t **printer) /* O - Printer pointer */
{
cupsd_printer_t *p; /* Current printer */
char localname[1024],/* Localized hostname */
*lptr, /* Pointer into localized hostname */
- *sptr; /* Pointer into server name */
+ *sptr, /* Pointer into server name */
+ *rptr, /* Pointer into resource */
+ scheme[32], /* Scheme portion of URI */
+ username[64], /* Username portion of URI */
+ hostname[HTTP_MAX_HOST],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
- DEBUG_printf(("cupsdValidateDest(\"%s\", \"%s\", %p, %p)\n", hostname, resource,
+ DEBUG_printf(("cupsdValidateDest(uri=\"%s\", dtype=%p, printer=%p)\n", uri,
dtype, printer));
/*
if (printer)
*printer = NULL;
- *dtype = (cups_ptype_t)0;
+ if (dtype)
+ *dtype = (cups_ptype_t)0;
+
+ /*
+ * Pull the hostname and resource from the URI...
+ */
+
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
+ username, sizeof(username), hostname, sizeof(hostname),
+ &port, resource, sizeof(resource));
/*
* See if the resource is a class or printer...
* Class...
*/
- resource += 9;
+ rptr = resource + 9;
}
else if (!strncmp(resource, "/printers/", 10))
{
* Printer...
*/
- resource += 10;
+ rptr = resource + 10;
}
else
{
* See if the printer or class name exists...
*/
- p = cupsdFindDest(resource);
+ p = cupsdFindDest(rptr);
- if (p == NULL && strchr(resource, '@') == NULL)
+ if (p == NULL && strchr(rptr, '@') == NULL)
return (NULL);
else if (p != NULL)
{
if (printer)
*printer = p;
- *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
- CUPS_PRINTER_REMOTE);
+ if (dtype)
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED);
+
return (p->name);
}
*/
if (!strcasecmp(hostname, "localhost"))
- hostname = ServerName;
+ strlcpy(hostname, ServerName, sizeof(hostname));
strlcpy(localname, hostname, sizeof(localname));
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
if (!strcasecmp(p->hostname, localname) &&
- !strcasecmp(p->name, resource))
+ !strcasecmp(p->name, rptr))
{
if (printer)
*printer = p;
- *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
- CUPS_PRINTER_REMOTE);
+ if (dtype)
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED);
+
return (p->name);
}
* data has come from...
*/
- cupsFilePuts(fp, "# This file was automatically generated by cupsd(8) from the\n");
+ cupsFilePuts(fp,
+ "# This file was automatically generated by cupsd(8) from the\n");
cupsFilePrintf(fp, "# %s/printers.conf file. All changes to this file\n",
ServerRoot);
cupsFilePuts(fp, "# will be lost.\n");
if (DefaultPrinter)
cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter->name,
- DefaultPrinter->info, ServerName, DefaultPrinter->name);
+ DefaultPrinter->info, ServerName,
+ DefaultPrinter->name);
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
if (p != DefaultPrinter)
cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info,
- ServerName, p->name);
+ ServerName, p->name);
break;
case PRINTCAP_SOLARIS:
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
cupsFilePrintf(fp, "%s:\\\n"
- "\t:bsdaddr=%s,%s:\\\n"
- "\t:description=%s:\n",
- p->name, ServerName, p->name, p->info ? p->info : "");
+ "\t:bsdaddr=%s,%s:\\\n"
+ "\t:description=%s:\n",
+ p->name, ServerName, p->name,
+ p->info ? p->info : "");
break;
}
}
}
+/*
+ * 'add_printer_defaults()' - Add name-default attributes to the printer attributes.
+ */
+
+static void
+add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
+{
+ int i; /* Looping var */
+ int num_options; /* Number of default options */
+ cups_option_t *options, /* Default options */
+ *option; /* Current option */
+ char name[256]; /* name-default */
+
+
+ /*
+ * Maintain a common array of default attribute names...
+ */
+
+ if (!CommonDefaults)
+ {
+ CommonDefaults = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("copies-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("document-format-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("finishings-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-hold-until-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-priority-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-sheets-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("media-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("number-up-default"));
+ cupsArrayAdd(CommonDefaults,
+ _cupsStrAlloc("orientation-requested-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("sides-default"));
+ }
+
+ /*
+ * Add all of the default options from the .conf files...
+ */
+
+ for (num_options = 0, i = p->num_options, option = p->options;
+ i > 0;
+ i --, option ++)
+ {
+ if (strcmp(option->name, "ipp-options") &&
+ strcmp(option->name, "job-sheets") &&
+ strcmp(option->name, "lease-duration"))
+ {
+ snprintf(name, sizeof(name), "%s-default", option->name);
+ num_options = cupsAddOption(name, option->value, num_options, &options);
+
+ if (!cupsArrayFind(CommonDefaults, name))
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc(name));
+ }
+ }
+
+ /*
+ * Convert options to IPP attributes...
+ */
+
+ cupsEncodeOptions2(p->attrs, num_options, options, IPP_TAG_PRINTER);
+ cupsFreeOptions(num_options, options);
+
+ /*
+ * Add standard -default attributes as needed...
+ */
+
+ if (!cupsGetOption("copies", p->num_options, p->options))
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "copies-default",
+ 1);
+
+ if (!cupsGetOption("document-format", p->num_options, p->options))
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
+ "document-format-default", NULL, "application/octet-stream");
+
+ if (!cupsGetOption("job-hold-until", p->num_options, p->options))
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "job-hold-until-default", NULL, "no-hold");
+
+ if (!cupsGetOption("job-priority", p->num_options, p->options))
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-priority-default", 50);
+
+ if (!cupsGetOption("number-up", p->num_options, p->options))
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "number-up-default", 1);
+
+ if (!cupsGetOption("orientation-requested", p->num_options, p->options))
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NOVALUE,
+ "orientation-requested-default", NULL, NULL);
+
+ if (!cupsGetOption("notify-lease-duration", p->num_options, p->options))
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "notify-lease-duration-default", DefaultLeaseDuration);
+
+ if (!cupsGetOption("notify-events", p->num_options, p->options))
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "notify-events-default", NULL, "job-completed");
+}
+
+
+/*
+ * 'add_printer_filter()' - Add a MIME filter for a printer.
+ */
+
+static void
+add_printer_filter(
+ cupsd_printer_t *p, /* I - Printer to add to */
+ mime_type_t *filtertype, /* I - Filter or prefilter MIME type */
+ const char *filter) /* I - Filter to add */
+{
+ char super[MIME_MAX_SUPER], /* Super-type for filter */
+ type[MIME_MAX_TYPE], /* Type for filter */
+ program[1024]; /* Program/filter name */
+ int cost; /* Cost of filter */
+ mime_type_t *temptype; /* MIME type looping var */
+ char filename[1024]; /* Full filter filename */
+
+
+ /*
+ * Parse the filter string; it should be in the following format:
+ *
+ * super/type cost program
+ */
+
+ if (sscanf(filter, "%15[^/]/%31s%d%1023s", super, type, &cost, program) != 4)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s: invalid filter string \"%s\"!",
+ p->name, filter);
+ return;
+ }
+
+ /*
+ * See if the filter program exists; if not, stop the printer and flag
+ * the error!
+ */
+
+ if (strcmp(program, "-"))
+ {
+ if (program[0] == '/')
+ strlcpy(filename, program, sizeof(filename));
+ else
+ snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);
+
+ if (access(filename, X_OK))
+ {
+ snprintf(p->state_message, sizeof(p->state_message),
+ "Filter \"%s\" for printer \"%s\" not available: %s",
+ program, p->name, strerror(errno));
+ cupsdSetPrinterReasons(p, "+cups-missing-filter-error");
+ cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, 0);
+
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
+ }
+ }
+
+ /*
+ * Mark the CUPS_PRINTER_COMMANDS bit if we have a filter for
+ * application/vnd.cups-command...
+ */
+
+ if (!strcasecmp(super, "application") &&
+ !strcasecmp(type, "vnd.cups-command"))
+ p->type |= CUPS_PRINTER_COMMANDS;
+
+ /*
+ * Add the filter to the MIME database, supporting wildcards as needed...
+ */
+
+ for (temptype = mimeFirstType(MimeDatabase);
+ temptype;
+ temptype = mimeNextType(MimeDatabase))
+ if (((super[0] == '*' && strcasecmp(temptype->super, "printer")) ||
+ !strcasecmp(temptype->super, super)) &&
+ (type[0] == '*' || !strcasecmp(temptype->type, type)))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "add_printer_filter: %s: adding filter %s/%s %s/%s %d %s",
+ p->name, temptype->super, temptype->type,
+ filtertype->super, filtertype->type,
+ cost, program);
+ mimeAddFilter(MimeDatabase, temptype, filtertype, cost, program);
+ }
+}
+
+
+/*
+ * 'add_printer_formats()' - Add document-format-supported values for a printer.
+ */
+
+static void
+add_printer_formats(cupsd_printer_t *p) /* I - Printer */
+{
+ int i; /* Looping var */
+ mime_type_t *type; /* Current MIME type */
+ cups_array_t *filters; /* Filters */
+ ipp_attribute_t *attr; /* document-format-supported attribute */
+ char mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE + 2];
+ /* MIME type name */
+
+
+ /*
+ * Raw (and remote) queues advertise all of the supported MIME
+ * types...
+ */
+
+ cupsArrayDelete(p->filetypes);
+ p->filetypes = NULL;
+
+ if (p->raw)
+ {
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER,
+ (ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
+ "document-format-supported", NumMimeTypes, NULL, MimeTypes);
+ return;
+ }
+
+ /*
+ * Otherwise, loop through the supported MIME types and see if there
+ * are filters for them...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer_formats: %d types, %d filters",
+ mimeNumTypes(MimeDatabase), mimeNumFilters(MimeDatabase));
+
+ p->filetypes = cupsArrayNew(NULL, NULL);
+
+ for (type = mimeFirstType(MimeDatabase);
+ type;
+ type = mimeNextType(MimeDatabase))
+ {
+ snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type);
+
+ if ((filters = mimeFilter(MimeDatabase, type, p->filetype, NULL)) != NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "add_printer_formats: %s: %s needs %d filters",
+ p->name, mimetype, cupsArrayCount(filters));
+
+ cupsArrayDelete(filters);
+ cupsArrayAdd(p->filetypes, type);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "add_printer_formats: %s: %s not supported",
+ p->name, mimetype);
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "add_printer_formats: %s: %d supported types",
+ p->name, cupsArrayCount(p->filetypes) + 1);
+
+ /*
+ * Add the file formats that can be filtered...
+ */
+
+ if ((type = mimeType(MimeDatabase, "application", "octet-stream")) == NULL ||
+ !cupsArrayFind(p->filetypes, type))
+ i = 1;
+ else
+ i = 0;
+
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
+ "document-format-supported",
+ cupsArrayCount(p->filetypes) + 1, NULL, NULL);
+
+ if (i)
+ attr->values[0].string.text = _cupsStrAlloc("application/octet-stream");
+
+ for (type = (mime_type_t *)cupsArrayFirst(p->filetypes);
+ type;
+ i ++, type = (mime_type_t *)cupsArrayNext(p->filetypes))
+ {
+ snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type);
+
+ attr->values[i].string.text = _cupsStrAlloc(mimetype);
+ }
+
+#ifdef HAVE_DNSSD
+ {
+ char pdl[1024]; /* Buffer to build pdl list */
+ mime_filter_t *filter; /* MIME filter looping var */
+
+
+ pdl[0] = '\0';
+
+ if (mimeType(MimeDatabase, "application", "pdf"))
+ strlcat(pdl, "application/pdf,", sizeof(pdl));
+
+ if (mimeType(MimeDatabase, "application", "postscript"))
+ strlcat(pdl, "application/postscript,", sizeof(pdl));
+
+ if (mimeType(MimeDatabase, "application", "vnd.cups-raster"))
+ strlcat(pdl, "application/vnd.cups-raster,", sizeof(pdl));
+
+ /*
+ * Determine if this is a Tioga PrintJobMgr based queue...
+ */
+
+ for (filter = (mime_filter_t *)cupsArrayFirst(MimeDatabase->filters);
+ filter;
+ filter = (mime_filter_t *)cupsArrayNext(MimeDatabase->filters))
+ {
+ if (filter->dst == p->filetype && filter->filter &&
+ strstr(filter->filter, "PrintJobMgr"))
+ break;
+ }
+
+ /*
+ * We only support raw printing if this is not a Tioga PrintJobMgr based
+ * queue and if application/octet-stream is a known conversion...
+ */
+
+ if (!filter && mimeType(MimeDatabase, "application", "octet-stream"))
+ strlcat(pdl, "application/octet-stream,", sizeof(pdl));
+
+ if (mimeType(MimeDatabase, "image", "png"))
+ strlcat(pdl, "image/png,", sizeof(pdl));
+
+ if (pdl[0])
+ pdl[strlen(pdl) - 1] = '\0'; /* Remove trailing comma */
+
+ cupsdSetString(&p->pdl, pdl);
+ }
+#endif /* HAVE_DNSSD */
+}
+
+
/*
* 'compare_printers()' - Compare two printers.
*/
}
+/*
+ * 'delete_printer_filters()' - Delete all MIME filters for a printer.
+ */
+
+static void
+delete_printer_filters(
+ cupsd_printer_t *p) /* I - Printer to remove from */
+{
+ mime_filter_t *filter; /* MIME filter looping var */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (p == NULL)
+ return;
+
+ /*
+ * Remove all filters from the MIME database that have a destination
+ * type == printer...
+ */
+
+ for (filter = mimeFirstFilter(MimeDatabase);
+ filter;
+ filter = mimeNextFilter(MimeDatabase))
+ if (filter->dst == p->filetype)
+ {
+ /*
+ * Delete the current filter...
+ */
+
+ mimeDeleteFilter(MimeDatabase, filter);
+ }
+}
+
+
#ifdef __sgi
/*
* 'write_irix_config()' - Update the config files used by the IRIX
{
char filename[1024]; /* Interface script filename */
cups_file_t *fp; /* Interface script file */
-
+ ipp_attribute_t *attr; /* Attribute data */
/*
/*
- * End of "$Id: printers.c 5047 2006-02-02 05:14:15Z mike $".
+ * End of "$Id: printers.c 6970 2007-09-17 23:58:28Z mike $".
*/