diff options
author | Richard Hughes <richard@hughsie.com> | 2011-01-12 10:38:37 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2011-01-12 10:38:37 +0000 |
commit | 2df8859f1ec4672d94717cd79373fbab936784f0 (patch) | |
tree | 20dfa0c5b612afe203c978a2099b6717691551aa | |
parent | 2f8c2519309dc16ef47fd6c5ec9c60e361c8843c (diff) | |
download | colord-2df8859f1ec4672d94717cd79373fbab936784f0.tar.gz |
Revert the last change, as we need to make changes to the whole CUPS tree
Find the new tree at http://gitorious.org/cups-colord
-rw-r--r-- | doc/printers.c | 6674 |
1 files changed, 0 insertions, 6674 deletions
diff --git a/doc/printers.c b/doc/printers.c deleted file mode 100644 index 0f8c499..0000000 --- a/doc/printers.c +++ /dev/null @@ -1,6674 +0,0 @@ -/* - * "$Id: printers.c 9313 2010-09-22 18:35:07Z mike $" - * - * Printer routines for the CUPS scheduler. - * - * Copyright 2007-2010 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. - * - * 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/". - * - * Contents: - * - * cupsdAddPrinter() - Add a printer to the system. - * cupsdAddPrinterHistory() - Add the current printer state to the history. - * cupsdAddPrinterUser() - Add a user to the ACL. - * cupsdCreateCommonData() - Create the common printer data. - * cupsdDeleteAllPrinters() - Delete all printers from the system. - * cupsdDeletePrinter() - Delete a printer from the system. - * cupsdFindDest() - Find a destination in the list. - * 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. - * cupsdSetDeviceURI() - Set the device URI for a printer. - * cupsdSetPrinterAttr() - Set a printer attribute. - * cupsdSetPrinterAttrs() - Set printer attributes based upon the PPD - * file. - * cupsdSetPrinterReasons() - Set/update the reasons strings. - * cupsdSetPrinterState() - Update the current state of a printer. - * cupsdStopPrinter() - Stop a printer from printing any jobs... - * cupsdUpdatePrinterPPD() - Update keywords in a printer's PPD file. - * cupsdUpdatePrinters() - Update printers after a partial reload. - * cupsdValidateDest() - Validate a printer/class destination. - * cupsdWritePrintcap() - Write a pseudo-printcap file for older - * applications that need it... - * apple_init_profile() - Initialize a color profile. - * dbus_create_profile() - Initialise a color profile. - * dbus_create_device() - Initialise a color device. - * cupsdRegisterColorProfiles() - * - Register color profiles for a printer. - * cupsdUnregisterColorProfiles() - * - Remove color profiles for the specified - * printer. - * 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. - * add_string_array() - Add a string to an array of CUPS strings. - * compare_printers() - Compare two printers. - * delete_printer_filters() - Delete all MIME filters for a printer. - * delete_string_array() - Delete an array of CUPS strings. - * load_ppd() - Load a cached PPD file, updating the cache as - * needed. - * new_media_col() - Create a media-col collection value. - * write_irix_config() - Update the config files used by the IRIX - * desktop tools. - * write_irix_state() - Update the status files used by IRIX printing - * desktop tools. - * write_xml_string() - Write a string with XML escaping. - */ - -/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ - -/* - * Include necessary headers... - */ - -#include "cupsd.h" -#include <cups/ppd-private.h> -#include <cups/dir.h> -#ifdef HAVE_APPLICATIONSERVICES_H -# include <ApplicationServices/ApplicationServices.h> -#endif /* HAVE_APPLICATIONSERVICES_H */ -#ifdef __APPLE__ -# include <CoreFoundation/CoreFoundation.h> -#endif /* __APPLE__ */ -#ifdef HAVE_SYS_MOUNT_H -# include <sys/mount.h> -#endif /* HAVE_SYS_MOUNT_H */ -#ifdef HAVE_SYS_STATFS_H -# include <sys/statfs.h> -#endif /* HAVE_SYS_STATFS_H */ -#ifdef HAVE_SYS_STATVFS_H -# include <sys/statvfs.h> -#endif /* HAVE_SYS_STATVFS_H */ -#ifdef HAVE_SYS_VFS_H -# include <sys/vfs.h> -#endif /* HAVE_SYS_VFS_H */ - -#ifdef HAVE_DBUS -# include <dbus/dbus.h> -# ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND -# define dbus_message_append_iter_init dbus_message_iter_init_append -# define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &(v)) -# define dbus_message_iter_append_object_path(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_OBJECT_PATH, &(v)) -# define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &(v)) -# endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */ -#endif /* HAVE_DBUS */ - - -/* - * 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 void add_string_array(cups_array_t **a, const char *s); -static int compare_printers(void *first, void *second, void *data); -static void delete_printer_filters(cupsd_printer_t *p); -static void delete_string_array(cups_array_t **a); -static void load_ppd(cupsd_printer_t *p); -static ipp_t *new_media_col(_pwg_size_t *size, const char *source, - const char *type); -#ifdef __sgi -static void write_irix_config(cupsd_printer_t *p); -static void write_irix_state(cupsd_printer_t *p); -#endif /* __sgi */ -static void write_xml_string(cups_file_t *fp, const char *s); -#ifdef __APPLE__ -static void apple_init_profile(ppd_file_t *ppd, cups_array_t *languages, - CMDeviceProfileInfo *profile, unsigned id, - const char *name, const char *text, - const char *iccfile); -#endif /* __APPLE__ */ - -#ifdef WITH_LSPP -# include <libaudit.h> -# include <selinux/context.h> -#endif /* WITH_LSPP */ - -/* - * 'cupsdAddPrinter()' - Add a printer to the system. - */ - -cupsd_printer_t * /* O - New printer */ -cupsdAddPrinter(const char *name) /* I - Name of printer */ -{ - cupsd_printer_t *p; /* New printer */ - char uri[1024]; /* Printer URI */ - - - /* - * Range check input... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddPrinter(\"%s\")", name); - - /* - * Create a new printer entity... - */ - - if ((p = calloc(1, sizeof(cupsd_printer_t))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_CRIT, "Unable to allocate memory for printer - %s", - strerror(errno)); - return (NULL); - } - - cupsdSetString(&p->name, name); - cupsdSetString(&p->info, name); - cupsdSetString(&p->hostname, ServerName); - - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - ServerName, RemotePort, "/printers/%s", name); - cupsdSetString(&p->uri, uri); - cupsdSetDeviceURI(p, "file:///dev/null"); - - p->state = IPP_PRINTER_STOPPED; - p->state_time = time(NULL); - p->accepting = 0; - p->shared = DefaultShared; - p->filetype = mimeAddType(MimeDatabase, "printer", name); - - cupsdSetString(&p->job_sheets[0], "none"); - cupsdSetString(&p->job_sheets[1], "none"); - - cupsdSetString(&p->error_policy, ErrorPolicy); - cupsdSetString(&p->op_policy, DefaultPolicy); - - p->op_policy_ptr = DefaultPolicyPtr; - - if (MaxPrinterHistory) - p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *)); - - /* - * Insert the printer in the printer list alphabetically... - */ - - if (!Printers) - Printers = cupsArrayNew(compare_printers, NULL); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddPrinter: Adding %s to Printers", p->name); - cupsArrayAdd(Printers, p); - - if (!ImplicitPrinters) - ImplicitPrinters = cupsArrayNew(compare_printers, NULL); - - /* - * Return the new printer... - */ - - return (p); -} - - -/* - * 'cupsdAddPrinterHistory()' - Add the current printer state to the history. - */ - -void -cupsdAddPrinterHistory( - cupsd_printer_t *p) /* I - Printer */ -{ - ipp_t *history; /* History collection */ - - - /* - * Stop early if we aren't keeping history data... - */ - - if (MaxPrinterHistory <= 0) - return; - - /* - * Retire old history data as needed... - */ - - p->sequence_number ++; - - if (p->num_history >= MaxPrinterHistory) - { - p->num_history --; - ippDelete(p->history[0]); - memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *)); - } - - /* - * Create a collection containing the current printer-state, printer-up-time, - * printer-state-message, and printer-state-reasons attributes. - */ - - history = ippNew(); - ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", - p->state); - ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-accepting-jobs", - p->accepting); - ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-shared", p->shared); - ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message", - NULL, p->state_message); -#ifdef __APPLE__ - if (p->recoverable) - ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "com.apple.print.recoverable-message", NULL, p->recoverable); -#endif /* __APPLE__ */ - if (p->num_reasons == 0) - ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "printer-state-reasons", NULL, "none"); - else - ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "printer-state-reasons", p->num_reasons, NULL, - (const char * const *)p->reasons); - ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "printer-state-change-time", p->state_time); - ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "printer-state-sequence-number", p->sequence_number); - - p->history[p->num_history] = history; - p->num_history ++; -} - - -/* - * 'cupsdAddPrinterUser()' - Add a user to the ACL. - */ - -void -cupsdAddPrinterUser( - cupsd_printer_t *p, /* I - Printer */ - const char *username) /* I - User */ -{ - const char **temp; /* Temporary array pointer */ - - - if (!p || !username) - return; - - if (p->num_users == 0) - temp = malloc(sizeof(char **)); - else - temp = realloc(p->users, sizeof(char **) * (p->num_users + 1)); - - if (!temp) - return; - - p->users = temp; - temp += p->num_users; - - if ((*temp = strdup(username)) != NULL) - p->num_users ++; -} - - -/* - * 'cupsdCreateCommonData()' - Create the common printer data. - */ - -void -cupsdCreateCommonData(void) -{ - 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 */ - int k_supported; /* Maximum file size supported */ -#ifdef HAVE_STATFS - struct statfs spoolinfo; /* FS info for spool directory */ - double spoolsize; /* FS size */ -#elif defined(HAVE_STATVFS) - struct statvfs spoolinfo; /* FS info for spool directory */ - double spoolsize; /* FS size */ -#endif /* HAVE_STATFS */ - static const int nups[] = /* number-up-supported values */ - { 1, 2, 4, 6, 9, 16 }; - static const int orients[4] =/* orientation-requested-supported values */ - { - IPP_PORTRAIT, - IPP_LANDSCAPE, - IPP_REVERSE_LANDSCAPE, - IPP_REVERSE_PORTRAIT - }; - static const char * const holds[] = /* job-hold-until-supported values */ - { - "no-hold", - "indefinite", - "day-time", - "evening", - "night", - "second-shift", - "third-shift", - "weekend" - }; - static const char * const versions[] =/* ipp-versions-supported values */ - { - "1.0", - "1.1", - "2.0", - "2.1" - }; - static const int ops[] = /* operations-supported values */ - { - IPP_PRINT_JOB, - IPP_VALIDATE_JOB, - IPP_CREATE_JOB, - IPP_SEND_DOCUMENT, - IPP_CANCEL_JOB, - IPP_GET_JOB_ATTRIBUTES, - IPP_GET_JOBS, - IPP_GET_PRINTER_ATTRIBUTES, - IPP_HOLD_JOB, - IPP_RELEASE_JOB, - IPP_PAUSE_PRINTER, - IPP_RESUME_PRINTER, - IPP_PURGE_JOBS, - IPP_SET_PRINTER_ATTRIBUTES, - IPP_SET_JOB_ATTRIBUTES, - IPP_GET_PRINTER_SUPPORTED_VALUES, - IPP_CREATE_PRINTER_SUBSCRIPTION, - IPP_CREATE_JOB_SUBSCRIPTION, - IPP_GET_SUBSCRIPTION_ATTRIBUTES, - IPP_GET_SUBSCRIPTIONS, - IPP_RENEW_SUBSCRIPTION, - IPP_CANCEL_SUBSCRIPTION, - IPP_GET_NOTIFICATIONS, - IPP_ENABLE_PRINTER, - IPP_DISABLE_PRINTER, - IPP_HOLD_NEW_JOBS, - IPP_RELEASE_HELD_NEW_JOBS, - CUPS_GET_DEFAULT, - CUPS_GET_PRINTERS, - CUPS_ADD_PRINTER, - CUPS_DELETE_PRINTER, - CUPS_GET_CLASSES, - CUPS_ADD_CLASS, - CUPS_DELETE_CLASS, - CUPS_ACCEPT_JOBS, - CUPS_REJECT_JOBS, - CUPS_SET_DEFAULT, - CUPS_GET_DEVICES, - 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 */ - { - "us-ascii", - "utf-8" - }; - static const char * const compressions[] = - { /* document-compression-supported values */ - "none" -#ifdef HAVE_LIBZ - ,"gzip" -#endif /* HAVE_LIBZ */ - }; - static const char * const media_col_supported[] = - { /* media-col-supported values */ - "media-bottom-margin", - "media-left-margin", - "media-right-margin", - "media-size", - "media-source", - "media-top-margin", - "media-type" - }; - static const char * const multiple_document_handling[] = - { /* multiple-document-handling-supported values */ - "separate-documents-uncollated-copies", - "separate-documents-collated-copies" - }; - static const char * const notify_attrs[] = - { /* notify-attributes-supported values */ - "printer-state-change-time", - "notify-lease-expiration-time", - "notify-subscriber-user-name" - }; - static const char * const notify_events[] = - { /* notify-events-supported values */ - "job-completed", - "job-config-changed", - "job-created", - "job-progress", - "job-state-changed", - "job-stopped", - "printer-added", - "printer-changed", - "printer-config-changed", - "printer-deleted", - "printer-finishings-changed", - "printer-media-changed", - "printer-modified", - "printer-restarted", - "printer-shutdown", - "printer-state-changed", - "printer-stopped", - "server-audit", - "server-restarted", - "server-started", - "server-stopped" - }; - static const char * const job_creation[] = - { /* job-creation-attributes-supported */ - "copies", - "finishings", - "ipp-attribute-fidelity", - "job-hold-until", - "job-name", - "job-priority", - "job-sheets", - "media", - "media-col", - "multiple-document-handling", - "number-up", - "output-bin", - "output-mode", - "orientation-requested", - "page-ranges", - "print-quality", - "printer-resolution", - "sides" - }; - static const char * const job_settable[] = - { /* job-settable-attributes-supported */ - "copies", - "finishings", - "job-hold-until", - "job-name", - "job-priority", - "media", - "media-col", - "multiple-document-handling", - "number-up", - "output-bin", - "output-mode", - "orientation-requested", - "page-ranges", - "print-quality", - "printer-resolution", - "sides" - }; - static const char * const printer_settable[] = - { /* printer-settable-attributes-supported */ - "printer-info", - "printer-location" - }; - - - if (CommonData) - ippDelete(CommonData); - - CommonData = ippNew(); - - /* - * Get the maximum spool size based on the size of the filesystem used for - * the RequestRoot directory. If the host OS doesn't support the statfs call - * or the filesystem is larger than 2TiB, always report INT_MAX. - */ - -#ifdef HAVE_STATFS - if (statfs(RequestRoot, &spoolinfo)) - k_supported = INT_MAX; - else if ((spoolsize = (double)spoolinfo.f_bsize * spoolinfo.f_blocks / 1024) > - INT_MAX) - k_supported = INT_MAX; - else - k_supported = (int)spoolsize; - -#elif defined(HAVE_STATVFS) - if (statvfs(RequestRoot, &spoolinfo)) - k_supported = INT_MAX; - else if ((spoolsize = (double)spoolinfo.f_frsize * spoolinfo.f_blocks / 1024) > - INT_MAX) - k_supported = INT_MAX; - else - k_supported = (int)spoolsize; - -#else - k_supported = INT_MAX; -#endif /* HAVE_STATFS */ - - /* - * This list of attributes is sorted to improve performance when the - * client provides a requested-attributes attribute... - */ - - /* charset-configured */ - ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET | IPP_TAG_COPY, - "charset-configured", NULL, "utf-8"); - - /* charset-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET | IPP_TAG_COPY, - "charset-supported", sizeof(charsets) / sizeof(charsets[0]), - NULL, charsets); - - /* compression-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "compression-supported", - sizeof(compressions) / sizeof(compressions[0]), - NULL, compressions); - - /* copies-supported */ - ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies); - - /* cups-version */ - ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_TEXT | IPP_TAG_COPY, - "cups-version", NULL, CUPS_SVERSION + 6); - - /* generated-natural-language-supported (no IPP_TAG_COPY) */ - ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, - "generated-natural-language-supported", NULL, DefaultLanguage); - - /* ipp-versions-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]), - NULL, versions); - - /* ippget-event-life */ - ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "ippget-event-life", 15); - - /* job-creation-attributes-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "job-creation-attributes-supported", - sizeof(job_creation) / sizeof(job_creation[0]), - NULL, job_creation); - - /* job-hold-until-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "job-hold-until-supported", sizeof(holds) / sizeof(holds[0]), - NULL, holds); - - /* job-priority-supported */ - ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "job-priority-supported", 100); - - /* job-settable-attributes-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "job-settable-attributes-supported", - sizeof(job_settable) / sizeof(job_settable[0]), - NULL, job_settable); - - /* job-sheets-supported */ - if (cupsArrayCount(Banners) > 0) - { - /* - * Setup the job-sheets-supported attribute... - */ - - if (Classification && !ClassifyOverride) - attr = ippAddString(CommonData, IPP_TAG_PRINTER, - IPP_TAG_NAME | IPP_TAG_COPY, - "job-sheets-supported", NULL, Classification); - else - attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, - IPP_TAG_NAME | IPP_TAG_COPY, - "job-sheets-supported", cupsArrayCount(Banners) + 1, - NULL, NULL); - - if (attr == NULL) - cupsdLogMessage(CUPSD_LOG_EMERG, - "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 = _cupsStrAlloc("none"); - - for (i = 1, banner = (cupsd_banner_t *)cupsArrayFirst(Banners); - banner; - i ++, banner = (cupsd_banner_t *)cupsArrayNext(Banners)) - attr->values[i].string.text = banner->name; - } - } - else - ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, - "job-sheets-supported", NULL, "none"); - - /* media-col-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "media-col-supported", - sizeof(media_col_supported) / - sizeof(media_col_supported[0]), NULL, - media_col_supported); - - /* multiple-document-handling-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "multiple-document-handling-supported", - sizeof(multiple_document_handling) / - sizeof(multiple_document_handling[0]), NULL, - multiple_document_handling); - - /* multiple-document-jobs-supported */ - ippAddBoolean(CommonData, IPP_TAG_PRINTER, - "multiple-document-jobs-supported", 1); - - /* multiple-operation-time-out */ - ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "multiple-operation-time-out", MultipleOperationTimeout); - - /* natural-language-configured (no IPP_TAG_COPY) */ - ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, - "natural-language-configured", NULL, DefaultLanguage); - - /* notify-attributes-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "notify-attributes-supported", - (int)(sizeof(notify_attrs) / sizeof(notify_attrs[0])), - NULL, notify_attrs); - - /* notify-lease-duration-supported */ - ippAddRange(CommonData, IPP_TAG_PRINTER, - "notify-lease-duration-supported", 0, - MaxLeaseDuration ? MaxLeaseDuration : 2147483647); - - /* notify-max-events-supported */ - ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "notify-max-events-supported", MaxEvents); - - /* notify-events-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "notify-events-supported", - (int)(sizeof(notify_events) / sizeof(notify_events[0])), - NULL, notify_events); - - /* notify-pull-method-supported */ - ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "notify-pull-method-supported", NULL, "ippget"); - - /* notify-schemes-supported */ - snprintf(filename, sizeof(filename), "%s/notifier", ServerBin); - if ((dir = cupsDirOpen(filename)) != NULL) - { - notifiers = cupsArrayNew((cups_array_func_t)strcmp, NULL); - - 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, - "number-up-supported", sizeof(nups) / sizeof(nups[0]), nups); - - /* operations-supported */ - ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "operations-supported", - sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, ops); - - /* orientation-requested-supported */ - ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "orientation-requested-supported", 4, orients); - - /* page-ranges-supported */ - ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1); - - /* pdl-override-supported */ - ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "pdl-override-supported", NULL, "attempted"); - - /* printer-op-policy-supported */ - attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, - "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 = p->name; - - /* printer-settable-attributes-supported */ - ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "printer-settable-attributes-supported", - sizeof(printer_settable) / sizeof(printer_settable[0]), - NULL, printer_settable); - - /* server-is-sharing-printers */ - ippAddBoolean(CommonData, IPP_TAG_PRINTER, "server-is-sharing-printers", - BrowseLocalProtocols != 0 && Browsing); -} - - -/* - * 'cupsdDeleteAllPrinters()' - Delete all printers from the system. - */ - -void -cupsdDeleteAllPrinters(void) -{ - cupsd_printer_t *p; /* Pointer to current printer/class */ - - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - p->op_policy_ptr = DefaultPolicyPtr; - cupsdDeletePrinter(p, 0); - } -} - - -/* - * 'cupsdDeletePrinter()' - Delete a printer from the system. - */ - -int /* O - 1 if classes affected, 0 otherwise */ -cupsdDeletePrinter( - cupsd_printer_t *p, /* I - Printer to delete */ - int update) /* I - Update printers.conf? */ -{ - int i, /* Looping var */ - changed = 0; /* Class changed? */ -#ifdef __sgi - char filename[1024]; /* Interface script filename */ -#endif /* __sgi */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeletePrinter(p=%p(%s), update=%d)", - p, p->name, update); - - /* - * Save the current position in the Printers array... - */ - - cupsArraySave(Printers); - - /* - * Stop printing on this printer... - */ - - cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, update); - p->state = IPP_PRINTER_STOPPED; - - if (p->job) - cupsdSetJobState(p->job, IPP_JOB_PENDING, CUPSD_JOB_FORCE, - update ? "Job stopped due to printer being deleted." : - "Job stopped."); - -#ifdef HAVE_DBUS - /* - * Unregister the color profiles - */ - - cupsdUnregisterColorProfiles(p); -#endif /* HAVE_DBUS */ - - /* - * If this printer is the next for browsing, point to the next one... - */ - - if (p == BrowseNext) - { - cupsArrayFind(Printers, p); - BrowseNext = (cupsd_printer_t *)cupsArrayNext(Printers); - } - - /* - * Remove the printer from the list... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDeletePrinter: Removing %s from Printers", p->name); - cupsArrayRemove(Printers, p); - - if (p->type & CUPS_PRINTER_IMPLICIT) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDeletePrinter: Removing %s from ImplicitPrinters", - p->name); - cupsArrayRemove(ImplicitPrinters, p); - } - - /* - * Remove the dummy interface/icon/option files under IRIX... - */ - -#ifdef __sgi - snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", - p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name); - unlink(filename); -#endif /* __sgi */ - - /* - * If p is the default printer, assign a different one... - */ - - if (p == DefaultPrinter) - { - DefaultPrinter = NULL; - - if (UseNetworkDefault) - { - /* - * Find the first network default printer and use it... - */ - - cupsd_printer_t *dp; /* New default printer */ - - - for (dp = (cupsd_printer_t *)cupsArrayFirst(Printers); - dp; - dp = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (dp != p && (dp->type & CUPS_PRINTER_DEFAULT)) - { - DefaultPrinter = dp; - break; - } - } - } - - /* - * Remove this printer from any classes... - */ - - if (!(p->type & CUPS_PRINTER_IMPLICIT)) - { - changed = cupsdDeletePrinterFromClasses(p); - - /* - * Deregister from any browse protocols... - */ - - cupsdDeregisterPrinter(p, 1); - } - - /* - * Free all memory used by the printer... - */ - - if (p->printers != NULL) - free(p->printers); - - if (MaxPrinterHistory) - { - for (i = 0; i < p->num_history; i ++) - ippDelete(p->history[i]); - - free(p->history); - } - - delete_printer_filters(p); - - for (i = 0; i < p->num_reasons; i ++) - _cupsStrFree(p->reasons[i]); - - ippDelete(p->attrs); - ippDelete(p->ppd_attrs); - - mimeDeleteType(MimeDatabase, p->filetype); - mimeDeleteType(MimeDatabase, p->prefiltertype); - - delete_string_array(&(p->filters)); - delete_string_array(&(p->pre_filters)); - - cupsdFreePrinterUsers(p); - cupsdFreeQuotas(p); - - cupsdClearString(&p->uri); - cupsdClearString(&p->hostname); - cupsdClearString(&p->name); - cupsdClearString(&p->location); - cupsdClearString(&p->make_model); - cupsdClearString(&p->info); - cupsdClearString(&p->job_sheets[0]); - cupsdClearString(&p->job_sheets[1]); - cupsdClearString(&p->device_uri); - cupsdClearString(&p->sanitized_device_uri); - cupsdClearString(&p->port_monitor); - cupsdClearString(&p->op_policy); - cupsdClearString(&p->error_policy); - - cupsdClearString(&p->alert); - cupsdClearString(&p->alert_description); - -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - cupsdClearString(&p->product); - cupsdClearString(&p->pdl); -#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ - - 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); - - /* - * Restore the previous position in the Printers array... - */ - - cupsArrayRestore(Printers); - - return (changed); -} - - -/* - * 'cupsdFindDest()' - Find a destination in the list. - */ - -cupsd_printer_t * /* O - Destination in list */ -cupsdFindDest(const char *name) /* I - Name of printer or class to find */ -{ - cupsd_printer_t key; /* Search key */ - - - key.name = (char *)name; - return ((cupsd_printer_t *)cupsArrayFind(Printers, &key)); -} - - -/* - * 'cupsdFindPrinter()' - Find a printer in the list. - */ - -cupsd_printer_t * /* O - Printer in list */ -cupsdFindPrinter(const char *name) /* I - Name of printer to find */ -{ - cupsd_printer_t *p; /* Printer in list */ - - - if ((p = cupsdFindDest(name)) != NULL && (p->type & CUPS_PRINTER_CLASS)) - return (NULL); - else - return (p); -} - - -/* - * 'cupsdFreePrinterUsers()' - Free allow/deny users. - */ - -void -cupsdFreePrinterUsers( - cupsd_printer_t *p) /* I - Printer */ -{ - int i; /* Looping var */ - - - if (!p || !p->num_users) - return; - - for (i = 0; i < p->num_users; i ++) - free((void *)p->users[i]); - - free(p->users); - - p->num_users = 0; - p->users = NULL; -} - - -/* - * 'cupsdLoadAllPrinters()' - Load printers from the printers.conf file. - */ - -void -cupsdLoadAllPrinters(void) -{ - int i; /* Looping var */ - cups_file_t *fp; /* printers.conf file */ - int linenum; /* Current line number */ - char line[4096], /* Line from file */ - *value, /* Pointer to value */ - *valueptr; /* Pointer into value */ - cupsd_printer_t *p; /* Current printer */ - - - /* - * Open the printers.conf file... - */ - - snprintf(line, sizeof(line), "%s/printers.conf", ServerRoot); - if ((fp = cupsFileOpen(line, "r")) == NULL) - { - if (errno != ENOENT) - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open %s - %s", line, - strerror(errno)); - return; - } - - /* - * Read printer configurations until we hit EOF... - */ - - linenum = 0; - p = NULL; - - while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) - { - /* - * Decode the directive... - */ - - if (!strcasecmp(line, "<Printer") || - !strcasecmp(line, "<DefaultPrinter")) - { - /* - * <Printer name> or <DefaultPrinter name> - */ - - if (p == NULL && value) - { - /* - * Add the printer and a base file type... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading printer %s...", value); - - p = cupsdAddPrinter(value); - p->accepting = 1; - p->state = IPP_PRINTER_IDLE; - - /* - * Set the default printer as needed... - */ - - if (!strcasecmp(line, "<DefaultPrinter")) - DefaultPrinter = p; - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "</Printer>")) - { - if (p != NULL) - { - /* - * Close out the current printer... - */ - - cupsdSetPrinterAttrs(p); - cupsdAddPrinterHistory(p); - - if (strncmp(p->device_uri, "file:", 5) && - p->state != IPP_PRINTER_STOPPED) - { - /* - * See if the backend exists... - */ - - snprintf(line, sizeof(line), "%s/backend/%s", ServerBin, - p->device_uri); - - if ((valueptr = strchr(line + strlen(ServerBin), ':')) != NULL) - *valueptr = '\0'; /* Chop everything but URI scheme */ - - if (access(line, 0)) - { - /* - * Backend does not exist, stop printer... - */ - -#ifdef __x86_64__ - snprintf(line, sizeof(line), "%s/backend/%s", ServerBin_compat, - p->device_uri); - if (access(line, 0)) - { -#endif /* __x86_64__ */ - - p->state = IPP_PRINTER_STOPPED; - snprintf(p->state_message, sizeof(p->state_message), - "Backend %s does not exist!", line); -#ifdef __x86_64__ - } -#endif /* __x86_64__ */ - } - } - - p = NULL; - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!p) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - 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")) - { - if (value) - cupsdSetString(&p->info, value); - } - else if (!strcasecmp(line, "MakeModel")) - { - if (value) - cupsdSetString(&p->make_model, value); - } - else if (!strcasecmp(line, "Location")) - { - if (value) - cupsdSetString(&p->location, value); - } - else if (!strcasecmp(line, "DeviceURI")) - { - if (value) - cupsdSetDeviceURI(p, value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - 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")) - { - if (value && strcmp(value, "none")) - cupsdSetString(&p->port_monitor, value); - else if (value) - cupsdClearString(&p->port_monitor); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "Reason")) - { - if (value && - strcmp(value, "com.apple.print.recoverable-warning") && - strcmp(value, "connecting-to-device") && - 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])) - break; - - if (i >= p->num_reasons && - p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) - { - p->reasons[p->num_reasons] = _cupsStrAlloc(value); - p->num_reasons ++; - } - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "State")) - { - /* - * Set the initial queue state... - */ - - if (value && !strcasecmp(value, "idle")) - p->state = IPP_PRINTER_IDLE; - else if (value && !strcasecmp(value, "stopped")) - { - p->state = IPP_PRINTER_STOPPED; - - for (i = 0 ; i < p->num_reasons; i ++) - if (!strcmp("paused", p->reasons[i])) - break; - - if (i >= p->num_reasons && - p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) - { - p->reasons[p->num_reasons] = _cupsStrAlloc("paused"); - p->num_reasons ++; - } - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "StateMessage")) - { - /* - * Set the initial queue state message... - */ - - if (value) - strlcpy(p->state_message, value, sizeof(p->state_message)); - } - else if (!strcasecmp(line, "StateTime")) - { - /* - * Set the state time... - */ - - if (value) - p->state_time = atoi(value); - } - else if (!strcasecmp(line, "Accepting")) - { - /* - * Set the initial accepting state... - */ - - if (value && - (!strcasecmp(value, "yes") || - !strcasecmp(value, "on") || - !strcasecmp(value, "true"))) - p->accepting = 1; - else if (value && - (!strcasecmp(value, "no") || - !strcasecmp(value, "off") || - !strcasecmp(value, "false"))) - p->accepting = 0; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "Type")) - { - if (value) - p->type = atoi(value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "Product")) - { - if (value) - { -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - p->product = _cupsStrAlloc(value); -#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "Filter")) - { - if (value) - { - if (!p->filters) - p->filters = cupsArrayNew(NULL, NULL); - - cupsArrayAdd(p->filters, _cupsStrAlloc(value)); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "PreFilter")) - { - if (value) - { - if (!p->pre_filters) - p->pre_filters = cupsArrayNew(NULL, NULL); - - cupsArrayAdd(p->pre_filters, _cupsStrAlloc(value)); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "Shared")) - { - /* - * Set the initial shared state... - */ - - if (value && - (!strcasecmp(value, "yes") || - !strcasecmp(value, "on") || - !strcasecmp(value, "true"))) - p->shared = 1; - else if (value && - (!strcasecmp(value, "no") || - !strcasecmp(value, "off") || - !strcasecmp(value, "false"))) - p->shared = 0; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "JobSheets")) - { - /* - * Set the initial job sheets... - */ - - if (value) - { - for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++); - - if (*valueptr) - *valueptr++ = '\0'; - - cupsdSetString(&p->job_sheets[0], value); - - while (isspace(*valueptr & 255)) - valueptr ++; - - if (*valueptr) - { - for (value = valueptr; *valueptr && !isspace(*valueptr & 255); valueptr ++); - - if (*valueptr) - *valueptr = '\0'; - - cupsdSetString(&p->job_sheets[1], value); - } - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "AllowUser")) - { - if (value) - { - p->deny_users = 0; - cupsdAddPrinterUser(p, value); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "DenyUser")) - { - if (value) - { - p->deny_users = 1; - cupsdAddPrinterUser(p, value); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "QuotaPeriod")) - { - if (value) - p->quota_period = atoi(value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "PageLimit")) - { - if (value) - p->page_limit = atoi(value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "KLimit")) - { - if (value) - p->k_limit = atoi(value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "OpPolicy")) - { - if (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); - } - else if (!strcasecmp(line, "ErrorPolicy")) - { - if (value) - cupsdSetString(&p->error_policy, value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "Attribute") && 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'); - - if (!p->attrs) - cupsdSetPrinterAttrs(p); - - if (!strcmp(value, "marker-change-time")) - p->marker_time = atoi(valueptr); - else - cupsdSetPrinterAttr(p, value, valueptr); - } - } - else - { - /* - * Something else we don't understand... - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown configuration directive %s on line %d of printers.conf.", - line, linenum); - } - } - - cupsFileClose(fp); -} - - -/* - * '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... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRenamePrinter: Removing %s from Printers", p->name); - cupsArrayRemove(Printers, p); - - if (p->type & CUPS_PRINTER_IMPLICIT) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRenamePrinter: Removing %s from ImplicitPrinters", - p->name); - 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); - -#ifdef HAVE_DBUS - /* - * Unregister the color profiles - */ - - cupsdUnregisterColorProfiles(p); -#endif /* HAVE_DBUS */ - - /* - * Rename the printer... - */ - - cupsdSetString(&p->name, name); - - /* - * Reset printer attributes... - */ - - cupsdSetPrinterAttrs(p); - - /* - * Add the printer back to the printer array(s)... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRenamePrinter: Adding %s to Printers", p->name); - cupsArrayAdd(Printers, p); - - if (p->type & CUPS_PRINTER_IMPLICIT) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRenamePrinter: Adding %s to ImplicitPrinters", - p->name); - cupsArrayAdd(ImplicitPrinters, p); - } -} - - -/* - * 'cupsdSaveAllPrinters()' - Save all printer definitions to the printers.conf - * file. - */ - -void -cupsdSaveAllPrinters(void) -{ - int i; /* Looping var */ - cups_file_t *fp; /* printers.conf file */ - char temp[1024], /* Temporary string */ - backup[1024], /* printers.conf.O file */ - value[2048], /* Value string */ - *ptr; /* Pointer into value */ - cupsd_printer_t *printer; /* Current printer class */ - time_t curtime; /* Current time */ - struct tm *curdate; /* Current date */ - cups_option_t *option; /* Current option */ - ipp_attribute_t *marker; /* Current marker attribute */ - - - /* - * Create the printers.conf file... - */ - - snprintf(temp, sizeof(temp), "%s/printers.conf", ServerRoot); - snprintf(backup, sizeof(backup), "%s/printers.conf.O", ServerRoot); - - if (rename(temp, backup)) - { - if (errno != ENOENT) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to backup printers.conf - %s", strerror(errno)); - } - - if ((fp = cupsFileOpen(temp, "w")) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to save printers.conf - %s", strerror(errno)); - - if (rename(backup, temp)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to restore printers.conf - %s", strerror(errno)); - return; - } - else - cupsdLogMessage(CUPSD_LOG_INFO, "Saving printers.conf..."); - - /* - * Restrict access to the file... - */ - - fchown(cupsFileNumber(fp), getuid(), Group); - fchmod(cupsFileNumber(fp), ConfigFilePerm & 0600); - - /* - * Write a small header to the file... - */ - - curtime = time(NULL); - curdate = localtime(&curtime); - strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate); - - cupsFilePuts(fp, "# Printer configuration file for " CUPS_SVERSION "\n"); - cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); - cupsFilePuts(fp, "# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING\n"); - - /* - * Write each local printer known to the system... - */ - - for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers); - printer; - printer = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - /* - * Skip remote destinations and printer classes... - */ - - if ((printer->type & CUPS_PRINTER_DISCOVERED) || - (printer->type & CUPS_PRINTER_CLASS) || - (printer->type & CUPS_PRINTER_IMPLICIT)) - continue; - - /* - * Write printers as needed... - */ - - if (printer == DefaultPrinter) - cupsFilePrintf(fp, "<DefaultPrinter %s>\n", printer->name); - else - cupsFilePrintf(fp, "<Printer %s>\n", printer->name); - - if (printer->num_auth_info_required > 0) - { - switch (printer->num_auth_info_required) - { - case 1 : - strlcpy(value, printer->auth_info_required[0], sizeof(value)); - break; - - case 2 : - snprintf(value, sizeof(value), "%s,%s", - printer->auth_info_required[0], - printer->auth_info_required[1]); - break; - - case 3 : - default : - snprintf(value, sizeof(value), "%s,%s,%s", - printer->auth_info_required[0], - printer->auth_info_required[1], - printer->auth_info_required[2]); - break; - } - - cupsFilePutConf(fp, "AuthInfoRequired", value); - } - - if (printer->info) - cupsFilePutConf(fp, "Info", printer->info); - - if (printer->location) - cupsFilePutConf(fp, "Location", printer->location); - - if (printer->make_model) - cupsFilePutConf(fp, "MakeModel", printer->make_model); - - cupsFilePutConf(fp, "DeviceURI", printer->device_uri); - - if (printer->port_monitor) - cupsFilePutConf(fp, "PortMonitor", printer->port_monitor); - - if (printer->state == IPP_PRINTER_STOPPED) - { - cupsFilePuts(fp, "State Stopped\n"); - - if (printer->state_message) - cupsFilePutConf(fp, "StateMessage", printer->state_message); - } - else - cupsFilePuts(fp, "State Idle\n"); - - cupsFilePrintf(fp, "StateTime %d\n", (int)printer->state_time); - - 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-warning") && - strcmp(printer->reasons[i], "cups-missing-filter-warning")) - cupsFilePutConf(fp, "Reason", printer->reasons[i]); - - cupsFilePrintf(fp, "Type %d\n", printer->type); - -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - if (printer->product) - cupsFilePutConf(fp, "Product", printer->product); -#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ - - for (ptr = (char *)cupsArrayFirst(printer->filters); - ptr; - ptr = (char *)cupsArrayNext(printer->filters)) - cupsFilePutConf(fp, "Filter", ptr); - - for (ptr = (char *)cupsArrayFirst(printer->pre_filters); - ptr; - ptr = (char *)cupsArrayNext(printer->pre_filters)) - cupsFilePutConf(fp, "PreFilter", ptr); - - if (printer->accepting) - cupsFilePuts(fp, "Accepting Yes\n"); - else - cupsFilePuts(fp, "Accepting No\n"); - - if (printer->shared) - cupsFilePuts(fp, "Shared Yes\n"); - else - cupsFilePuts(fp, "Shared No\n"); - - snprintf(value, sizeof(value), "%s %s", printer->job_sheets[0], - printer->job_sheets[1]); - cupsFilePutConf(fp, "JobSheets", value); - - cupsFilePrintf(fp, "QuotaPeriod %d\n", printer->quota_period); - cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit); - cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit); - - for (i = 0; i < printer->num_users; i ++) - cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser", - printer->users[i]); - - if (printer->op_policy) - cupsFilePutConf(fp, "OpPolicy", printer->op_policy); - if (printer->error_policy) - cupsFilePutConf(fp, "ErrorPolicy", printer->error_policy); - - for (i = printer->num_options, option = printer->options; - i > 0; - i --, option ++) - { - snprintf(value, sizeof(value), "%s %s", option->name, option->value); - cupsFilePutConf(fp, "Option", value); - } - - if ((marker = ippFindAttribute(printer->attrs, "marker-colors", - IPP_TAG_NAME)) != NULL) - { - snprintf(value, sizeof(value), "%s ", marker->name); - - for (i = 0, ptr = value + strlen(value); - i < marker->num_values && ptr < (value + sizeof(value) - 1); - i ++) - { - if (i) - *ptr++ = ','; - - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); - ptr += strlen(ptr); - } - - *ptr = '\0'; - cupsFilePutConf(fp, "Attribute", value); - } - - if ((marker = ippFindAttribute(printer->attrs, "marker-levels", - IPP_TAG_INTEGER)) != NULL) - { - cupsFilePrintf(fp, "Attribute %s %d", marker->name, - marker->values[0].integer); - for (i = 1; i < marker->num_values; i ++) - cupsFilePrintf(fp, ",%d", marker->values[i].integer); - cupsFilePuts(fp, "\n"); - } - - if ((marker = ippFindAttribute(printer->attrs, "marker-low-levels", - IPP_TAG_INTEGER)) != NULL) - { - cupsFilePrintf(fp, "Attribute %s %d", marker->name, - marker->values[0].integer); - for (i = 1; i < marker->num_values; i ++) - cupsFilePrintf(fp, ",%d", marker->values[i].integer); - cupsFilePuts(fp, "\n"); - } - - if ((marker = ippFindAttribute(printer->attrs, "marker-high-levels", - IPP_TAG_INTEGER)) != NULL) - { - cupsFilePrintf(fp, "Attribute %s %d", marker->name, - marker->values[0].integer); - for (i = 1; i < marker->num_values; i ++) - cupsFilePrintf(fp, ",%d", marker->values[i].integer); - cupsFilePuts(fp, "\n"); - } - - if ((marker = ippFindAttribute(printer->attrs, "marker-message", - IPP_TAG_TEXT)) != NULL) - { - snprintf(value, sizeof(value), "%s %s", marker->name, - marker->values[0].string.text); - - cupsFilePutConf(fp, "Attribute", value); - } - - if ((marker = ippFindAttribute(printer->attrs, "marker-names", - IPP_TAG_NAME)) != NULL) - { - snprintf(value, sizeof(value), "%s ", marker->name); - - for (i = 0, ptr = value + strlen(value); - i < marker->num_values && ptr < (value + sizeof(value) - 1); - i ++) - { - if (i) - *ptr++ = ','; - - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); - ptr += strlen(ptr); - } - - *ptr = '\0'; - cupsFilePutConf(fp, "Attribute", value); - } - - if ((marker = ippFindAttribute(printer->attrs, "marker-types", - IPP_TAG_KEYWORD)) != NULL) - { - snprintf(value, sizeof(value), "%s ", marker->name); - - for (i = 0, ptr = value + strlen(value); - i < marker->num_values && ptr < (value + sizeof(value) - 1); - i ++) - { - if (i) - *ptr++ = ','; - - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); - ptr += strlen(ptr); - } - - *ptr = '\0'; - cupsFilePutConf(fp, "Attribute", value); - } - - if (printer->marker_time) - cupsFilePrintf(fp, "Attribute marker-change-time %ld\n", - (long)printer->marker_time); - - cupsFilePuts(fp, "</Printer>\n"); - -#ifdef __sgi - /* - * Make IRIX desktop & printer status happy - */ - - write_irix_state(printer); -#endif /* __sgi */ - } - - cupsFileClose(fp); -} - - -/* - * 'cupsdSetAuthInfoRequired()' - Set the required authentication info. - */ - -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) */ -{ - int i; /* Looping var */ - - - p->num_auth_info_required = 0; - - /* - * Do we have a plain text value? - */ - - if (values) - { - /* - * Yes, grab the keywords... - */ - - const char *end; /* End of current value */ - - - while (*values && p->num_auth_info_required < 4) - { - if ((end = strchr(values, ',')) == NULL) - end = values + strlen(values); - - if ((end - values) == 4 && !strncmp(values, "none", 4)) - { - if (p->num_auth_info_required != 0 || *end) - return (0); - - p->auth_info_required[p->num_auth_info_required] = "none"; - p->num_auth_info_required ++; - - return (1); - } - else if ((end - values) == 9 && !strncmp(values, "negotiate", 9)) - { - if (p->num_auth_info_required != 0 || *end) - return (0); - - 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 - 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); - } - - /* - * 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); -} - - -/* - * 'cupsdSetDeviceURI()' - Set the device URI for a printer. - */ - -void -cupsdSetDeviceURI(cupsd_printer_t *p, /* I - Printer */ - const char *uri) /* I - Device URI */ -{ - char buffer[1024], /* URI buffer */ - *start, /* Start of data after scheme */ - *slash, /* First slash after scheme:// */ - *ptr; /* Pointer into user@host:port part */ - - - /* - * Set the full device URI.. - */ - - cupsdSetString(&(p->device_uri), uri); - - /* - * Copy the device URI to a temporary buffer so we can sanitize any auth - * info in it... - */ - - strlcpy(buffer, uri, sizeof(buffer)); - - /* - * Find the end of the scheme:// part... - */ - - if ((ptr = strchr(buffer, ':')) != NULL) - { - for (start = ptr + 1; *start; start ++) - if (*start != '/') - break; - - /* - * Find the next slash (/) in the URI... - */ - - if ((slash = strchr(start, '/')) == NULL) - slash = start + strlen(start); /* No slash, point to the end */ - - /* - * Check for an @ sign before the slash... - */ - - if ((ptr = strchr(start, '@')) != NULL && ptr < slash) - { - /* - * Found an @ sign and it is before the resource part, so we have - * an authentication string. Copy the remaining URI over the - * authentication string... - */ - - _cups_strcpy(start, ptr + 1); - } - } - - /* - * Save the sanitized URI... - */ - - cupsdSetString(&(p->sanitized_device_uri), buffer); -} - - -/* - * '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 */ - - - /* - * Don't allow empty values... - */ - - if (!*value && strcmp(name, "marker-message")) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Ignoring empty \"%s\" attribute", name); - return; - } - - /* - * 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") || !strcmp(name, "marker-low-levels") || - !strcmp(name, "marker-high-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 if (!strcmp(name, "marker-message")) - value_tag = IPP_TAG_TEXT; - 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) - { - for (i = 0; i < attr->num_values; i ++) - _cupsStrFree(attr->values[i].string.text); - - 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'; - - 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 resource[HTTP_MAX_URI]; /* Resource portion of URI */ - int num_air; /* Number of auth-info-required values */ - const char * const *air; /* auth-info-required values */ - cupsd_location_t *auth; /* Pointer to authentication element */ - const char *auth_supported; /* Authentication supported */ - ipp_t *oldattrs; /* Old printer attributes */ - ipp_attribute_t *attr; /* Attribute data */ - cups_option_t *option; /* Current printer option */ - char *filter; /* Current filter */ - static const char * const air_none[] = - { /* No authentication */ - "none" - }; - static const char * const air_userpass[] = - { /* Basic/Digest authentication */ - "username", - "password" - }; -#ifdef WITH_LSPP - char *audit_message; /* Audit message string */ - char *printerfile; /* Path to a local printer dev */ - char *rangestr; /* Printer's range if its available */ - security_context_t devcon; /* Printer SELinux context */ - context_t printercon; /* context_t for the printer */ -#endif /* WITH_LSPP */ - - - 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; - } - else if ((p->type & CUPS_PRINTER_AUTHENTICATED) && - (p->type & CUPS_PRINTER_DISCOVERED)) - { - num_air = 2; - air = air_userpass; - } - - 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) - { - int auth_type; /* Authentication type */ - - - if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT) - auth_type = DefaultAuthType; - - if (auth_type == CUPSD_AUTH_BASIC || auth_type == CUPSD_AUTH_BASICDIGEST) - auth_supported = "basic"; - else if (auth_type == CUPSD_AUTH_DIGEST) - auth_supported = "digest"; -#ifdef HAVE_GSSAPI - else if (auth_type == CUPSD_AUTH_NEGOTIATE) - auth_supported = "negotiate"; -#endif /* HAVE_GSSAPI */ - - if (!(p->type & CUPS_PRINTER_DISCOVERED)) - { - if (auth_type != CUPSD_AUTH_NONE) - p->type |= CUPS_PRINTER_AUTHENTICATED; - else - p->type &= ~CUPS_PRINTER_AUTHENTICATED; - } - } - else if (!(p->type & CUPS_PRINTER_DISCOVERED)) - p->type &= ~CUPS_PRINTER_AUTHENTICATED; - - /* - * Create the required IPP attributes for a printer... - */ - - oldattrs = p->attrs; - p->attrs = ippNew(); - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "uri-authentication-supported", NULL, auth_supported); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "uri-security-supported", NULL, "none"); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL, - p->name); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", - NULL, p->location ? p->location : ""); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", - NULL, p->info ? p->info : ""); - - if (p->num_users) - { - if (p->deny_users) - ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "requesting-user-name-denied", p->num_users, NULL, - p->users); - else - ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "requesting-user-name-allowed", p->num_users, NULL, - p->users); - } - - ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "job-quota-period", p->quota_period); - ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "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_DISCOVERED)) - { - /* - * Setup the job-sheets-default attribute... - */ - - attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "job-sheets-default", 2, NULL, NULL); - - if (attr != NULL) - { - attr->values[0].string.text = _cupsStrAlloc(Classification ? - Classification : p->job_sheets[0]); - attr->values[1].string.text = _cupsStrAlloc(Classification ? - Classification : p->job_sheets[1]); - } -#ifdef WITH_LSPP - if (AuditLog != -1) - { - audit_message = NULL; - rangestr = NULL; - printercon = 0; - printerfile = strstr(p->device_uri, "/dev/"); - if (printerfile == NULL && (strncmp(p->device_uri, "file:/", 6) == 0)) - printerfile = p->device_uri + strlen("file:"); - - if (printerfile != NULL) - { - if (getfilecon(printerfile, &devcon) == -1) - { - if(is_selinux_enabled()) - cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdSetPrinterAttrs: Unable to get printer context"); - } - else - { - printercon = context_new(devcon); - freecon(devcon); - } - } - - if (printercon && context_range_get(printercon)) - rangestr = strdup(context_range_get(printercon)); - else - rangestr = strdup("unknown"); - - cupsdSetStringf(&audit_message, "printer=%s uri=%s banners=%s,%s range=%s", - p->name, p->sanitized_device_uri, p->job_sheets[0], p->job_sheets[1], rangestr); - audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message, - ServerName, NULL, NULL, 1); - if (printercon) - context_free(printercon); - free(rangestr); - cupsdClearString(&audit_message); - } -#endif /* WITH_LSPP */ - } - - p->raw = 0; - p->remote = 0; - - 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, - "printer-uri-supported", NULL, p->uri); - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", - NULL, p->uri); - - 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_URI, "device-uri", NULL, - p->uri); - - p->raw = 1; - p->remote = 1; - } - else - { - /* - * Assign additional attributes depending on whether this is a printer - * or class... - */ - - if (p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) - { - p->raw = 1; - p->type &= ~CUPS_PRINTER_OPTIONS; - - /* - * Add class-specific attributes... - */ - - if ((p->type & CUPS_PRINTER_IMPLICIT) && p->num_printers > 0 && - p->printers[0]->make_model) - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, p->printers[0]->make_model); - else - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, "Local Printer Class"); - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, - "file:///dev/null"); - - if (p->num_printers > 0) - { - /* - * Add a list of member names; URIs are added in copy_printer_attrs... - */ - - attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "member-names", p->num_printers, NULL, NULL); - p->type |= CUPS_PRINTER_OPTIONS; - - for (i = 0; i < p->num_printers; i ++) - { - if (attr != NULL) - attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name); - - p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type; - } - } - } - else - { - /* - * Add printer-specific attributes... - */ - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, - p->sanitized_device_uri); - - /* - * Assign additional attributes from the PPD file (if any)... - */ - - load_ppd(p); - - /* - * Add filters for printer... - */ - - cupsdSetPrinterReasons(p, "-cups-missing-filter-warning," - "cups-insecure-filter-warning"); - - for (filter = (char *)cupsArrayFirst(p->filters); - filter; - filter = (char *)cupsArrayNext(p->filters)) - add_printer_filter(p, p->filetype, filter); - - if (p->pre_filters) - { - p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name); - - for (filter = (char *)cupsArrayFirst(p->pre_filters); - filter; - filter = (char *)cupsArrayNext(p->pre_filters)) - add_printer_filter(p, p->prefiltertype, filter); - } - } - } - - /* - * Copy marker attributes as needed... - */ - - if (oldattrs) - { - ipp_attribute_t *oldattr; /* Old attribute */ - - - if ((oldattr = ippFindAttribute(oldattrs, "marker-colors", - IPP_TAG_NAME)) != NULL) - { - if ((attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "marker-colors", oldattr->num_values, NULL, - NULL)) != NULL) - { - for (i = 0; i < oldattr->num_values; i ++) - attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); - } - } - - if ((oldattr = ippFindAttribute(oldattrs, "marker-levels", - IPP_TAG_INTEGER)) != NULL) - { - if ((attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "marker-levels", oldattr->num_values, - NULL)) != NULL) - { - for (i = 0; i < oldattr->num_values; i ++) - attr->values[i].integer = oldattr->values[i].integer; - } - } - - if ((oldattr = ippFindAttribute(oldattrs, "marker-message", - IPP_TAG_TEXT)) != NULL) - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "marker-message", - NULL, oldattr->values[0].string.text); - - if ((oldattr = ippFindAttribute(oldattrs, "marker-low-levels", - IPP_TAG_INTEGER)) != NULL) - { - if ((attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "marker-low-levels", oldattr->num_values, - NULL)) != NULL) - { - for (i = 0; i < oldattr->num_values; i ++) - attr->values[i].integer = oldattr->values[i].integer; - } - } - - if ((oldattr = ippFindAttribute(oldattrs, "marker-high-levels", - IPP_TAG_INTEGER)) != NULL) - { - if ((attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "marker-high-levels", oldattr->num_values, - NULL)) != NULL) - { - for (i = 0; i < oldattr->num_values; i ++) - attr->values[i].integer = oldattr->values[i].integer; - } - } - - if ((oldattr = ippFindAttribute(oldattrs, "marker-names", - IPP_TAG_NAME)) != NULL) - { - if ((attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "marker-names", oldattr->num_values, NULL, - NULL)) != NULL) - { - for (i = 0; i < oldattr->num_values; i ++) - attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); - } - } - - if ((oldattr = ippFindAttribute(oldattrs, "marker-types", - IPP_TAG_KEYWORD)) != NULL) - { - if ((attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "marker-types", oldattr->num_values, NULL, - NULL)) != NULL) - { - for (i = 0; i < oldattr->num_values; i ++) - attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); - } - } - - ippDelete(oldattrs); - } - - /* - * 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); - - /* - * 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; - } - } - } - } - } - - /* - * 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 */ - -#ifdef HAVE_DBUS - /* - * (Re-)register the color profiles - */ - cupsdUnregisterColorProfiles(p); - cupsdRegisterColorProfiles(p); -#endif /* HAVE_DBUS */ - - /* - * Let the browse protocols reflect the change - */ - - cupsdRegisterPrinter(p); -} - - -/* - * 'cupsdSetPrinterReasons()' - Set/update the reasons strings. - */ - -int /* O - 1 if something changed, 0 otherwise */ -cupsdSetPrinterReasons( - cupsd_printer_t *p, /* I - Printer */ - const char *s) /* I - Reasons strings */ -{ - int i, /* Looping var */ - changed = 0; /* Did something change? */ - const char *sptr; /* Pointer into reasons */ - char reason[255], /* Reason string */ - *rptr; /* Pointer into reason */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSetPrinterReasons(p=%p(%s),s=\"%s\"", p, p->name, s); - - if (s[0] == '-' || s[0] == '+') - { - /* - * Add/remove reasons... - */ - - sptr = s + 1; - } - else - { - /* - * Replace reasons... - */ - - sptr = s; - - for (i = 0; i < p->num_reasons; i ++) - _cupsStrFree(p->reasons[i]); - - p->num_reasons = 0; - changed = 1; - - cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); - - if (PrintcapFormat == PRINTCAP_PLIST) - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); - } - - if (!strcmp(s, "none")) - return (changed); - - /* - * Loop through all of the reasons... - */ - - while (*sptr) - { - /* - * Skip leading whitespace and commas... - */ - - while (isspace(*sptr & 255) || *sptr == ',') - sptr ++; - - for (rptr = reason; *sptr && !isspace(*sptr & 255) && *sptr != ','; sptr ++) - if (rptr < (reason + sizeof(reason) - 1)) - *rptr++ = *sptr; - - if (rptr == reason) - break; - - *rptr = '\0'; - - if (s[0] == '-') - { - /* - * Remove reason... - */ - - for (i = 0; i < p->num_reasons; i ++) - if (!strcmp(reason, p->reasons[i])) - { - /* - * Found a match, so remove it... - */ - - p->num_reasons --; - changed = 1; - _cupsStrFree(p->reasons[i]); - - if (i < p->num_reasons) - memmove(p->reasons + i, p->reasons + i + 1, - (p->num_reasons - i) * sizeof(char *)); - - if (!strcmp(reason, "paused") && p->state == IPP_PRINTER_STOPPED) - cupsdSetPrinterState(p, IPP_PRINTER_IDLE, 1); - - if (strcmp(reason, "connecting-to-device")) - { - cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); - - if (PrintcapFormat == PRINTCAP_PLIST) - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); - } - break; - } - } - else if (p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) - { - /* - * Add reason... - */ - - for (i = 0; i < p->num_reasons; i ++) - if (!strcmp(reason, p->reasons[i])) - break; - - if (i >= p->num_reasons) - { - if (i >= (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) - { - cupsdLogMessage(CUPSD_LOG_ALERT, - "Too many printer-state-reasons values for %s (%d)", - p->name, i + 1); - return (changed); - } - - p->reasons[i] = _cupsStrAlloc(reason); - p->num_reasons ++; - changed = 1; - - if (!strcmp(reason, "paused") && p->state != IPP_PRINTER_STOPPED) - cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, 1); - - if (strcmp(reason, "connecting-to-device")) - { - cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); - - if (PrintcapFormat == PRINTCAP_PLIST) - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); - } - } - } - } - - return (changed); -} - - -/* - * 'cupsdSetPrinterState()' - Update the current state of a printer. - */ - -void -cupsdSetPrinterState( - cupsd_printer_t *p, /* I - Printer to change */ - ipp_pstate_t s, /* I - New state */ - int update) /* I - Update printers.conf? */ -{ - ipp_pstate_t old_state; /* Old printer state */ - static const char * const printer_states[] = - { /* State strings */ - "idle", - "processing", - "stopped" - }; - - - /* - * Can't set status of remote printers... - */ - - if (p->type & CUPS_PRINTER_DISCOVERED) - return; - - /* - * Set the new state... - */ - - if (PrintcapFormat == PRINTCAP_PLIST) - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); - - old_state = p->state; - p->state = s; - - if (old_state != s) - { - cupsdAddEvent(s == IPP_PRINTER_STOPPED ? CUPSD_EVENT_PRINTER_STOPPED : - CUPSD_EVENT_PRINTER_STATE, p, NULL, - "%s \"%s\" state changed to %s.", - (p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer", - p->name, printer_states[p->state]); - - /* - * Let the browse code know this needs to be updated... - */ - - BrowseNext = p; - p->state_time = time(NULL); - p->browse_time = 0; - -#ifdef __sgi - write_irix_state(p); -#endif /* __sgi */ - } - - /* - * Set/clear the paused reason as needed... - */ - - if (s == IPP_PRINTER_STOPPED) - cupsdSetPrinterReasons(p, "+paused"); - else - cupsdSetPrinterReasons(p, "-paused"); - - /* - * Clear the message for the queue when going to processing... - */ - - if (s == IPP_PRINTER_PROCESSING) - p->state_message[0] = '\0'; - - /* - * Update the printer history... - */ - - cupsdAddPrinterHistory(p); - - /* - * Let the browse protocols reflect the change... - */ - - if (update) - cupsdRegisterPrinter(p); - - /* - * Save the printer configuration if a printer goes from idle or processing - * to stopped (or visa-versa)... - */ - - if (update && - (old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED)) - { - if (p->type & CUPS_PRINTER_CLASS) - cupsdMarkDirty(CUPSD_DIRTY_CLASSES); - else - cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); - } -} - - -/* - * 'cupsdStopPrinter()' - Stop a printer from printing any jobs... - */ - -void -cupsdStopPrinter(cupsd_printer_t *p, /* I - Printer to stop */ - int update)/* I - Update printers.conf? */ -{ - /* - * Set the printer state... - */ - - cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, update); - - /* - * See if we have a job printing on this printer... - */ - - if (p->job && p->job->state_value == IPP_JOB_PROCESSING) - cupsdSetJobState(p->job, IPP_JOB_PENDING, CUPSD_JOB_DEFAULT, - "Job stopped due to printer being paused."); -} - - -/* - * 'cupsdUpdatePrinterPPD()' - Update keywords in a printer's PPD file. - */ - -int /* O - 1 if successful, 0 otherwise */ -cupsdUpdatePrinterPPD( - cupsd_printer_t *p, /* I - Printer */ - int num_keywords, /* I - Number of keywords */ - cups_option_t *keywords) /* I - Keywords */ -{ - int i; /* Looping var */ - cups_file_t *src, /* Original file */ - *dst; /* New file */ - char srcfile[1024], /* Original filename */ - dstfile[1024], /* New filename */ - line[1024], /* Line from file */ - keystring[41]; /* Keyword from line */ - cups_option_t *keyword; /* Current keyword */ - - - cupsdLogMessage(CUPSD_LOG_INFO, "Updating keywords in PPD file for %s...", - p->name); - - /* - * Get the old and new PPD filenames... - */ - - snprintf(srcfile, sizeof(srcfile), "%s/ppd/%s.ppd.O", ServerRoot, p->name); - snprintf(dstfile, sizeof(srcfile), "%s/ppd/%s.ppd", ServerRoot, p->name); - - /* - * Rename the old file and open the old and new... - */ - - if (rename(dstfile, srcfile)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to backup PPD file for %s: %s", - p->name, strerror(errno)); - return (0); - } - - if ((src = cupsFileOpen(srcfile, "r")) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open PPD file \"%s\": %s", - srcfile, strerror(errno)); - rename(srcfile, dstfile); - return (0); - } - - if ((dst = cupsFileOpen(dstfile, "w")) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create PPD file \"%s\": %s", - dstfile, strerror(errno)); - cupsFileClose(src); - rename(srcfile, dstfile); - return (0); - } - - /* - * Copy the first line and then write out all of the keywords... - */ - - if (!cupsFileGets(src, line, sizeof(line))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to read PPD file \"%s\": %s", - srcfile, strerror(errno)); - cupsFileClose(src); - cupsFileClose(dst); - rename(srcfile, dstfile); - return (0); - } - - cupsFilePrintf(dst, "%s\n", line); - - for (i = num_keywords, keyword = keywords; i > 0; i --, keyword ++) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "*%s: %s", keyword->name, keyword->value); - cupsFilePrintf(dst, "*%s: %s\n", keyword->name, keyword->value); - } - - /* - * Then copy the rest of the PPD file, dropping any keywords we changed. - */ - - while (cupsFileGets(src, line, sizeof(line))) - { - /* - * Skip keywords we've already set... - */ - - if (sscanf(line, "*%40[^:]:", keystring) == 1 && - cupsGetOption(keystring, num_keywords, keywords)) - continue; - - /* - * Otherwise write the line... - */ - - cupsFilePrintf(dst, "%s\n", line); - } - - /* - * Close files and return... - */ - - cupsFileClose(src); - cupsFileClose(dst); - - return (1); -} - - -/* - * 'cupsdUpdatePrinters()' - Update printers after a partial reload. - */ - -void -cupsdUpdatePrinters(void) -{ - cupsd_printer_t *p; /* Current printer */ - - - /* - * Loop through the printers and recreate the printer attributes - * for any local printers since the policy and/or access control - * stuff may have changed. Also, if browsing is disabled, remove - * any remote printers... - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - /* - * 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); - - cupsArraySave(Printers); - cupsdDeletePrinter(p, 0); - cupsArrayRestore(Printers); - continue; - } - - /* - * 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); - } -} - - -/* - * 'cupsdValidateDest()' - Validate a printer/class destination. - */ - -const char * /* O - Printer or class name */ -cupsdValidateDest( - 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 */ - *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(uri=\"%s\", dtype=%p, printer=%p)\n", uri, - dtype, printer)); - - /* - * Initialize return values... - */ - - if (printer) - *printer = NULL; - - 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... - */ - - if (!strncmp(resource, "/classes/", 9)) - { - /* - * Class... - */ - - rptr = resource + 9; - } - else if (!strncmp(resource, "/printers/", 10)) - { - /* - * Printer... - */ - - rptr = resource + 10; - } - else - { - /* - * Bad resource name... - */ - - return (NULL); - } - - /* - * See if the printer or class name exists... - */ - - p = cupsdFindDest(rptr); - - if (p == NULL && strchr(rptr, '@') == NULL) - return (NULL); - else if (p != NULL) - { - if (printer) - *printer = p; - - if (dtype) - *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED); - - return (p->name); - } - - /* - * Change localhost to the server name... - */ - - if (!strcasecmp(hostname, "localhost")) - strlcpy(hostname, ServerName, sizeof(hostname)); - - strlcpy(localname, hostname, sizeof(localname)); - - if (!strcasecmp(hostname, ServerName)) - { - /* - * Localize the hostname... - */ - - lptr = strchr(localname, '.'); - sptr = strchr(ServerName, '.'); - - if (sptr != NULL && lptr != NULL) - { - /* - * Strip the common domain name components... - */ - - while (lptr != NULL) - { - if (!strcasecmp(lptr, sptr)) - { - *lptr = '\0'; - break; - } - else - lptr = strchr(lptr + 1, '.'); - } - } - } - - DEBUG_printf(("localized hostname is \"%s\"...\n", localname)); - - /* - * Find a matching printer or class... - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!strcasecmp(p->hostname, localname) && - !strcasecmp(p->name, rptr)) - { - if (printer) - *printer = p; - - if (dtype) - *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED); - - return (p->name); - } - - return (NULL); -} - - -/* - * 'cupsdWritePrintcap()' - Write a pseudo-printcap file for older applications - * that need it... - */ - -void -cupsdWritePrintcap(void) -{ - int i; /* Looping var */ - cups_file_t *fp; /* Printcap file */ - cupsd_printer_t *p; /* Current printer */ - - -#ifdef __sgi - /* - * Update the IRIX printer state for the default printer; if - * no printers remain, then the default printer file will be - * removed... - */ - - write_irix_state(DefaultPrinter); -#endif /* __sgi */ - - /* - * See if we have a printcap file; if not, don't bother writing it. - */ - - if (!Printcap || !*Printcap) - return; - - cupsdLogMessage(CUPSD_LOG_INFO, "Generating printcap %s...", Printcap); - - /* - * Open the printcap file... - */ - - if ((fp = cupsFileOpen(Printcap, "w")) == NULL) - return; - - /* - * Put a comment header at the top so that users will know where the - * data has come from... - */ - - if (PrintcapFormat != PRINTCAP_PLIST) - cupsFilePrintf(fp, "# This file was automatically generated by cupsd(8) " - "from the\n" - "# %s/printers.conf file. All changes to this file\n" - "# will be lost.\n", ServerRoot); - - /* - * Write a new printcap with the current list of printers. - */ - - switch (PrintcapFormat) - { - case PRINTCAP_BSD : - /* - * Each printer is put in the file as: - * - * Printer1: - * Printer2: - * Printer3: - * ... - * PrinterN: - */ - - if (DefaultPrinter) - cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", 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); - break; - - case PRINTCAP_PLIST : - /* - * Each printer is written as a dictionary in a plist file. - * Currently the printer-name, printer-info, printer-is-accepting-jobs, - * printer-location, printer-make-and-model, printer-state, - * printer-state-reasons, printer-type, and (sanitized) device-uri. - */ - - cupsFilePuts(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD " - "PLIST 1.0//EN\" \"http://www.apple.com/DTDs/" - "PropertyList-1.0.dtd\">\n" - "<plist version=\"1.0\">\n" - "<array>\n"); - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - cupsFilePuts(fp, "\t<dict>\n" - "\t\t<key>printer-name</key>\n" - "\t\t<string>"); - write_xml_string(fp, p->name); - cupsFilePuts(fp, "</string>\n" - "\t\t<key>printer-info</key>\n" - "\t\t<string>"); - write_xml_string(fp, p->info); - cupsFilePrintf(fp, "</string>\n" - "\t\t<key>printer-is-accepting-jobs</key>\n" - "\t\t<%s/>\n" - "\t\t<key>printer-location</key>\n" - "\t\t<string>", p->accepting ? "true" : "false"); - write_xml_string(fp, p->location); - cupsFilePuts(fp, "</string>\n" - "\t\t<key>printer-make-and-model</key>\n" - "\t\t<string>"); - write_xml_string(fp, p->make_model); - cupsFilePrintf(fp, "</string>\n" - "\t\t<key>printer-state</key>\n" - "\t\t<integer>%d</integer>\n" - "\t\t<key>printer-state-reasons</key>\n" - "\t\t<array>\n", p->state); - for (i = 0; i < p->num_reasons; i ++) - { - cupsFilePuts(fp, "\t\t\t<string>"); - write_xml_string(fp, p->reasons[i]); - cupsFilePuts(fp, "</string>\n"); - } - cupsFilePrintf(fp, "\t\t</array>\n" - "\t\t<key>printer-type</key>\n" - "\t\t<integer>%d</integer>\n" - "\t\t<key>device-uri</key>\n" - "\t\t<string>", p->type); - write_xml_string(fp, p->sanitized_device_uri); - cupsFilePuts(fp, "</string>\n" - "\t</dict>\n"); - } - cupsFilePuts(fp, "</array>\n" - "</plist>\n"); - break; - - case PRINTCAP_SOLARIS : - /* - * Each printer is put in the file as: - * - * _all:all=Printer1,Printer2,Printer3,...,PrinterN - * _default:use=DefaultPrinter - * Printer1:\ - * :bsdaddr=ServerName,Printer1:\ - * :description=Description: - * Printer2: - * :bsdaddr=ServerName,Printer2:\ - * :description=Description: - * Printer3: - * :bsdaddr=ServerName,Printer3:\ - * :description=Description: - * ... - * PrinterN: - * :bsdaddr=ServerName,PrinterN:\ - * :description=Description: - */ - - cupsFilePuts(fp, "_all:all="); - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayCurrent(Printers)) - cupsFilePrintf(fp, "%s%c", p->name, - cupsArrayNext(Printers) ? ',' : '\n'); - - if (DefaultPrinter) - cupsFilePrintf(fp, "_default:use=%s\n", DefaultPrinter->name); - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - 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 : ""); - break; - } - - /* - * Close the file... - */ - - cupsFileClose(fp); -} - - -/* - * '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-col-default")); - cupsArrayAdd(CommonDefaults, _cupsStrAlloc("number-up-default")); - cupsArrayAdd(CommonDefaults, - _cupsStrAlloc("orientation-requested-default")); - } - - /* - * Add all of the default options from the .conf files... - */ - - for (num_options = 0, options = NULL, 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(p->attrs, 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("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"); - - 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("print-quality", p->num_options, p->options)) - ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "print-quality-default", IPP_QUALITY_NORMAL); -} - - -/* - * '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 */ - *dirsep; /* Pointer to directory separator */ - struct stat fileinfo; /* File information */ - - - /* - * Parse the filter string; it should be in the following format: - * - * super/type cost program - */ - - if (sscanf(filter, "%15[^/]/%31s%d%*[ \t]%1023[^\n]", 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 (stat(filename, &fileinfo)) - { -#ifdef __x86_64__ - snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin_compat, - program); - if (stat(filename, &fileinfo)) - { - snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, - program); -#endif /* __x86_64__ */ - memset(&fileinfo, 0, sizeof(fileinfo)); - - 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-warning"); - - cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message); -#ifdef __x86_64__ - } -#endif /* __x86_64__ */ - } - - /* - * When running as root, do additional security checks... - */ - - if (!RunUser) - { - /* - * Only use filters that are owned by root and do not have world write - * permissions. - */ - - if (fileinfo.st_uid || (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0) - { - if (fileinfo.st_uid) - snprintf(p->state_message, sizeof(p->state_message), - "Filter \"%s\" for printer \"%s\" not owned by root", - filename, p->name); - else - snprintf(p->state_message, sizeof(p->state_message), - "Filter \"%s\" for printer \"%s\" has insecure permissions " - "(0%o)", filename, p->name, fileinfo.st_mode); - - cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message); - } - else if (fileinfo.st_mode) - { - /* - * 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) && - (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); - - cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message); - } - } - } - } - - /* - * 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); - } - - /* - * 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; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "add_printer_formats: %s: %d supported types", - p->name, cupsArrayCount(p->filetypes) + i); - - attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, - "document-format-supported", - cupsArrayCount(p->filetypes) + i, 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); - } - -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - { - char pdl[1024]; /* Buffer to build pdl list */ - mime_filter_t *filter; /* MIME filter looping var */ - - - /* - * We only support raw printing if this is not a Tioga PrintJobMgr based - * queue and if application/octet-stream is a known type... - */ - - 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; - } - - pdl[0] = '\0'; - - if (!filter && mimeType(MimeDatabase, "application", "octet-stream")) - strlcat(pdl, "application/octet-stream,", sizeof(pdl)); - - /* - * Then list a bunch of formats that are supported by the printer... - */ - - for (type = (mime_type_t *)cupsArrayFirst(p->filetypes); - type; - type = (mime_type_t *)cupsArrayNext(p->filetypes)) - { - if (!strcasecmp(type->super, "application")) - { - if (!strcasecmp(type->type, "pdf")) - strlcat(pdl, "application/pdf,", sizeof(pdl)); - else if (!strcasecmp(type->type, "postscript")) - strlcat(pdl, "application/postscript,", sizeof(pdl)); - } - else if (!strcasecmp(type->super, "image")) - { - if (!strcasecmp(type->type, "jpeg")) - strlcat(pdl, "image/jpeg,", sizeof(pdl)); - else if (!strcasecmp(type->type, "png")) - strlcat(pdl, "image/png,", sizeof(pdl)); - } - } - - if (pdl[0]) - pdl[strlen(pdl) - 1] = '\0'; /* Remove trailing comma */ - - cupsdSetString(&p->pdl, pdl); - } -#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ -} - - -/* - * 'add_string_array()' - Add a string to an array of CUPS strings. - */ - -static void -add_string_array(cups_array_t **a, /* I - Array */ - const char *s) /* I - String */ -{ - if (!*a) - *a = cupsArrayNew(NULL, NULL); - - cupsArrayAdd(*a, _cupsStrAlloc(s)); -} - - -/* - * 'compare_printers()' - Compare two printers. - */ - -static int /* O - Result of comparison */ -compare_printers(void *first, /* I - First printer */ - void *second, /* I - Second printer */ - void *data) /* I - App data (not used) */ -{ - return (strcasecmp(((cupsd_printer_t *)first)->name, - ((cupsd_printer_t *)second)->name)); -} - - -/* - * '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 || filter->dst == p->prefiltertype) - { - /* - * Delete the current filter... - */ - - mimeDeleteFilter(MimeDatabase, filter); - } - - cupsdSetPrinterReasons(p, "-cups-insecure-filter-warning" - ",cups-missing-filter-warning"); -} - - -/* - * 'delete_string_array()' - Delete an array of CUPS strings. - */ - -static void -delete_string_array(cups_array_t **a) /* I - Array */ -{ - char *ptr; /* Current string */ - - - for (ptr = (char *)cupsArrayFirst(*a); - ptr; - ptr = (char *)cupsArrayNext(*a)) - _cupsStrFree(ptr); - - cupsArrayDelete(*a); - *a = NULL; -} - - -/* - * 'load_ppd()' - Load a cached PPD file, updating the cache as needed. - */ - -static void -load_ppd(cupsd_printer_t *p) /* I - Printer */ -{ - int i, j, k; /* Looping vars */ - cups_file_t *cache; /* IPP cache file */ - char cache_name[1024]; /* IPP cache filename */ - struct stat cache_info; /* IPP cache file info */ - char pwg_name[1024]; /* PWG cache filename */ - struct stat pwg_info; /* PWG cache file info */ - ppd_file_t *ppd; /* PPD file */ - char ppd_name[1024]; /* PPD filename */ - struct stat ppd_info; /* PPD file info */ - int num_media; /* Number of media options */ - ppd_size_t *size; /* Current PPD size */ - ppd_option_t *duplex, /* Duplex option */ - *output_bin, /* OutputBin option */ - *output_mode, /* OutputMode option */ - *resolution; /* (Set|JCL|)Resolution option */ - ppd_choice_t *choice, /* Current PPD choice */ - *input_slot, /* Current input slot */ - *media_type; /* Current media type */ - ppd_attr_t *ppd_attr; /* PPD attribute */ - int xdpi, /* Horizontal resolution */ - ydpi; /* Vertical resolution */ - const char *resptr; /* Pointer into resolution keyword */ - _pwg_size_t *pwgsize; /* Current PWG size */ - _pwg_map_t *pwgsource, /* Current PWG source */ - *pwgtype; /* Current PWG type */ - ipp_attribute_t *attr; /* Attribute data */ - ipp_value_t *val; /* Attribute value */ - int num_finishings, /* Number of finishings */ - finishings[5]; /* finishings-supported values */ - int num_qualities, /* Number of print-quality values */ - qualities[3]; /* print-quality values */ - int num_margins, /* Number of media-*-margin-supported values */ - margins[16]; /* media-*-margin-supported values */ - static const char * const sides[3] = /* sides-supported values */ - { - "one-sided", - "two-sided-long-edge", - "two-sided-short-edge" - }; - static const char * const standard_commands[] = - { /* Standard CUPS commands */ - "AutoConfigure", - "Clean", - "PrintSelfTestPage" - }; - - - /* - * Check to see if the cache is up-to-date... - */ - - snprintf(cache_name, sizeof(cache_name), "%s/%s.ipp4", CacheDir, p->name); - if (stat(cache_name, &cache_info)) - cache_info.st_mtime = 0; - - snprintf(pwg_name, sizeof(pwg_name), "%s/%s.pwg3", CacheDir, p->name); - if (stat(pwg_name, &pwg_info)) - pwg_info.st_mtime = 0; - - snprintf(ppd_name, sizeof(ppd_name), "%s/ppd/%s.ppd", ServerRoot, p->name); - if (stat(ppd_name, &ppd_info)) - ppd_info.st_mtime = 1; - - ippDelete(p->ppd_attrs); - p->ppd_attrs = ippNew(); - - _pwgDestroy(p->pwg); - p->pwg = NULL; - - if (pwg_info.st_mtime >= ppd_info.st_mtime) - p->pwg = _pwgCreateWithFile(pwg_name); - - if (cache_info.st_mtime >= ppd_info.st_mtime && p->pwg && - (cache = cupsFileOpen(cache_name, "r")) != NULL) - { - /* - * Load cached information and return... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", cache_name); - - if (ippReadIO(cache, (ipp_iocb_t)cupsFileRead, 1, NULL, - p->ppd_attrs) == IPP_DATA) - { - cupsFileClose(cache); - return; - } - - cupsFileClose(cache); - } - - /* - * Reload PPD attributes from disk... - */ - - cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); - - _pwgDestroy(p->pwg); - p->pwg = NULL; - - cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", ppd_name); - - delete_string_array(&(p->filters)); - delete_string_array(&(p->pre_filters)); - - p->type &= ~CUPS_PRINTER_OPTIONS; - p->type |= CUPS_PRINTER_BW; - - finishings[0] = IPP_FINISHINGS_NONE; - num_finishings = 1; - - if ((ppd = ppdOpenFile(ppd_name)) != NULL) - { - /* - * Add make/model and other various attributes... - */ - - p->pwg = _pwgCreateWithPPD(ppd); - - ppdMarkDefaults(ppd); - - if (ppd->color_device) - p->type |= CUPS_PRINTER_COLOR; - if (ppd->variable_sizes) - p->type |= CUPS_PRINTER_VARIABLE; - if (!ppd->manual_copies) - p->type |= CUPS_PRINTER_COPIES; - if ((ppd_attr = ppdFindAttr(ppd, "cupsFax", NULL)) != NULL) - if (ppd_attr->value && !strcasecmp(ppd_attr->value, "true")) - p->type |= CUPS_PRINTER_FAX; - - ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "color-supported", - ppd->color_device); - if (ppd->throughput) - { - ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "pages-per-minute", ppd->throughput); - if (ppd->color_device) - ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "pages-per-minute-color", ppd->throughput); - } - - num_qualities = 0; - - if ((output_mode = ppdFindOption(ppd, "OutputMode")) != NULL) - { - if (ppdFindChoice(output_mode, "draft") || - ppdFindChoice(output_mode, "fast")) - qualities[num_qualities ++] = IPP_QUALITY_DRAFT; - if (ppdFindChoice(output_mode, "normal") || - ppdFindChoice(output_mode, "good")) - qualities[num_qualities ++] = IPP_QUALITY_NORMAL; - if (ppdFindChoice(output_mode, "best") || - ppdFindChoice(output_mode, "high")) - qualities[num_qualities ++] = IPP_QUALITY_HIGH; - } - else if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL) - { - do - { - if (strstr(ppd_attr->spec, "draft") || - strstr(ppd_attr->spec, "Draft")) - { - qualities[num_qualities ++] = IPP_QUALITY_DRAFT; - break; - } - } - while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", - NULL)) != NULL); - - qualities[num_qualities ++] = IPP_QUALITY_NORMAL; - qualities[num_qualities ++] = IPP_QUALITY_HIGH; - } - - if (num_qualities == 0) - qualities[num_qualities ++] = IPP_QUALITY_NORMAL; - - ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "print-quality-supported", num_qualities, qualities); - - 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"); - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, p->make_model); - - /* - * Add media options from the PPD file... - */ - - if (ppd->num_sizes == 0 || !p->pwg) - { - if (!ppdFindAttr(ppd, "APScannerOnly", NULL)) - cupsdLogMessage(CUPSD_LOG_CRIT, - "The PPD file for printer %s contains no media " - "options and is therefore invalid!", p->name); - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-default", NULL, "unknown"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-supported", NULL, "unknown"); - } - else - { - /* - * media-default - */ - - if ((size = ppdPageSize(ppd, NULL)) != NULL) - pwgsize = _pwgGetSize(p->pwg, size->name); - else - pwgsize = NULL; - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-default", NULL, - pwgsize ? pwgsize->map.pwg : "unknown"); - - /* - * media-col-default - */ - - if (pwgsize) - { - ipp_t *col; /* Collection value */ - - input_slot = ppdFindMarkedChoice(ppd, "InputSlot"); - media_type = ppdFindMarkedChoice(ppd, "MediaType"); - col = new_media_col(pwgsize, - input_slot ? - _pwgGetSource(p->pwg, - input_slot->choice) : - NULL, - media_type ? - _pwgGetType(p->pwg, - media_type->choice) : - NULL); - - ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-default", - col); - ippDelete(col); - } - - /* - * media-supported - */ - - num_media = p->pwg->num_sizes; - if (p->pwg->custom_min_keyword) - num_media += 2; - - if ((attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-supported", num_media, NULL, - NULL)) != NULL) - { - val = attr->values; - - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes; - i > 0; - i --, pwgsize ++, val ++) - val->string.text = _cupsStrRetain(pwgsize->map.pwg); - - if (p->pwg->custom_min_keyword) - { - val->string.text = _cupsStrRetain(p->pwg->custom_min_keyword); - val ++; - val->string.text = _cupsStrRetain(p->pwg->custom_max_keyword); - } - } - - /* - * media-source-supported - */ - - if (p->pwg->num_sources > 0 && - (attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-source-supported", p->pwg->num_sources, - NULL, NULL)) != NULL) - { - for (i = p->pwg->num_sources, pwgsource = p->pwg->sources, - val = attr->values; - i > 0; - i --, pwgsource ++, val ++) - val->string.text = _cupsStrRetain(pwgsource->pwg); - } - - /* - * media-type-supported - */ - - if (p->pwg->num_types > 0 && - (attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-type-supported", p->pwg->num_types, - NULL, NULL)) != NULL) - { - for (i = p->pwg->num_types, pwgtype = p->pwg->types, - val = attr->values; - i > 0; - i --, pwgtype ++, val ++) - val->string.text = _cupsStrRetain(pwgtype->pwg); - } - - /* - * media-*-margin-supported - */ - - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; - i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); - i --, pwgsize ++) - { - for (j = 0; j < num_margins; j ++) - if (pwgsize->bottom == margins[j]) - break; - - if (j >= num_margins) - { - margins[num_margins] = pwgsize->bottom; - num_margins ++; - } - } - - if (num_margins > 0) - ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-bottom-margin-supported", num_margins, margins); - else - ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-bottom-margin-supported", 0); - - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; - i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); - i --, pwgsize ++) - { - for (j = 0; j < num_margins; j ++) - if (pwgsize->left == margins[j]) - break; - - if (j >= num_margins) - { - margins[num_margins] = pwgsize->left; - num_margins ++; - } - } - - if (num_margins > 0) - ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-left-margin-supported", num_margins, margins); - else - ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-left-margin-supported", 0); - - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; - i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); - i --, pwgsize ++) - { - for (j = 0; j < num_margins; j ++) - if (pwgsize->right == margins[j]) - break; - - if (j >= num_margins) - { - margins[num_margins] = pwgsize->right; - num_margins ++; - } - } - - if (num_margins > 0) - ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-right-margin-supported", num_margins, margins); - else - ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-right-margin-supported", 0); - - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; - i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); - i --, pwgsize ++) - { - for (j = 0; j < num_margins; j ++) - if (pwgsize->top == margins[j]) - break; - - if (j >= num_margins) - { - margins[num_margins] = pwgsize->top; - num_margins ++; - } - } - - if (num_margins > 0) - ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-top-margin-supported", num_margins, margins); - else - ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-top-margin-supported", 0); - - /* - * media-col-database - */ - - num_media = p->pwg->num_sizes; - if (p->pwg->num_sources) - { - if (p->pwg->num_types > 0) - num_media += p->pwg->num_sizes * p->pwg->num_sources * - p->pwg->num_types; - else - num_media += p->pwg->num_sizes * p->pwg->num_sources; - } - else if (p->pwg->num_types) - num_media += p->pwg->num_sizes * p->pwg->num_types; - - if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, - "media-col-database", num_media, - NULL)) != NULL) - { - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, val = attr->values; - i > 0; - i --, pwgsize ++) - { - /* - * Start by adding the page size without source or type... - */ - - ppdMarkOption(ppd, "PageSize", pwgsize->map.ppd); - - val->collection = new_media_col(pwgsize, NULL, NULL); - val ++; - - /* - * Then add the specific, supported combinations of size, source, and - * type... - */ - - if (p->pwg->num_sources > 0) - { - for (j = p->pwg->num_sources, pwgsource = p->pwg->sources; - j > 0; - j --, pwgsource ++) - { - ppdMarkOption(ppd, "InputSlot", pwgsource->ppd); - - if (p->pwg->num_types > 0) - { - for (k = p->pwg->num_types, pwgtype = p->pwg->types; - k > 0; - k --, pwgtype ++) - { - if (!ppdMarkOption(ppd, "MediaType", pwgtype->ppd)) - { - val->collection = new_media_col(pwgsize, pwgsource->pwg, - pwgtype->pwg); - val ++; - } - } - } - else if (!ppdConflicts(ppd)) - { - val->collection = new_media_col(pwgsize, pwgsource->pwg, NULL); - val ++; - } - } - } - else if (p->pwg->num_types > 0) - { - for (j = p->pwg->num_types, pwgtype = p->pwg->types; - j > 0; - j --, pwgtype ++) - { - if (!ppdMarkOption(ppd, "MediaType", pwgtype->ppd)) - { - val->collection = new_media_col(pwgsize, NULL, pwgtype->pwg); - val ++; - } - } - } - } - - /* - * Update the number of media-col-database values... - */ - - attr->num_values = val - attr->values; - } - } - - /* - * Output bin... - */ - - if (p->pwg && p->pwg->num_bins > 0) - { - attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-supported", p->pwg->num_bins, - NULL, NULL); - - if (attr != NULL) - { - for (i = 0, val = attr->values; - i < p->pwg->num_bins; - i ++, val ++) - val->string.text = _cupsStrAlloc(p->pwg->bins[i].pwg); - } - - if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL) - { - for (i = 0; i < p->pwg->num_bins; i ++) - if (!strcmp(p->pwg->bins[i].ppd, output_bin->defchoice)) - break; - - if (i >= p->pwg->num_bins) - i = 0; - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-default", NULL, p->pwg->bins[i].pwg); - } - else - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-default", NULL, p->pwg->bins[0].pwg); - } - else if (((ppd_attr = ppdFindAttr(ppd, "DefaultOutputOrder", - NULL)) != NULL && - !strcasecmp(ppd_attr->value, "Reverse")) || - (!ppd_attr && ppd->manufacturer && /* "Compatibility heuristic" */ - (!strcasecmp(ppd->manufacturer, "epson") || - !strcasecmp(ppd->manufacturer, "lexmark")))) - { - /* - * Report that this printer has a single output bin that leaves pages face - * up. - */ - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-supported", NULL, "face-up"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-default", NULL, "face-up"); - } - else - { - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-supported", NULL, "face-down"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-default", NULL, "face-down"); - } - - /* - * output-mode... - */ - - if (ppd->color_device) - { - static const char * const output_modes[] = - { - "monochrome", - "color" - }; - - ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-supported", 2, NULL, output_modes); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-default", NULL, "color"); - } - else - { - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-supported", NULL, "monochrome"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-default", NULL, "monochrome"); - } - - /* - * Printer resolutions... - */ - - if ((resolution = ppdFindOption(ppd, "Resolution")) == NULL) - if ((resolution = ppdFindOption(ppd, "JCLResolution")) == NULL) - if ((resolution = ppdFindOption(ppd, "SetResolution")) == NULL) - resolution = ppdFindOption(ppd, "CNRes_PGP"); - - if (resolution) - { - /* - * Report all supported resolutions... - */ - - attr = ippAddResolutions(p->ppd_attrs, IPP_TAG_PRINTER, - "printer-resolution-supported", - resolution->num_choices, IPP_RES_PER_INCH, - NULL, NULL); - - for (i = 0, choice = resolution->choices; - i < resolution->num_choices; - i ++, choice ++) - { - xdpi = ydpi = (int)strtol(choice->choice, (char **)&resptr, 10); - if (resptr > choice->choice && xdpi > 0 && *resptr == 'x') - ydpi = (int)strtol(resptr + 1, (char **)&resptr, 10); - - if (xdpi <= 0 || ydpi <= 0) - { - cupsdLogMessage(CUPSD_LOG_WARN, - "Bad resolution \"%s\" for printer %s.", - choice->choice, p->name); - xdpi = ydpi = 300; - } - - attr->values[i].resolution.xres = xdpi; - attr->values[i].resolution.yres = ydpi; - attr->values[i].resolution.units = IPP_RES_PER_INCH; - - if (choice->marked) - ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, - "printer-resolution-default", IPP_RES_PER_INCH, - xdpi, ydpi); - } - } - else if ((ppd_attr = ppdFindAttr(ppd, "DefaultResolution", NULL)) != NULL && - ppd_attr->value) - { - /* - * Just the DefaultResolution to report... - */ - - xdpi = ydpi = (int)strtol(ppd_attr->value, (char **)&resptr, 10); - if (resptr > ppd_attr->value && xdpi > 0) - { - if (*resptr == 'x') - ydpi = (int)strtol(resptr + 1, (char **)&resptr, 10); - else - ydpi = xdpi; - } - - if (xdpi <= 0 || ydpi <= 0) - { - cupsdLogMessage(CUPSD_LOG_WARN, - "Bad default resolution \"%s\" for printer %s.", - ppd_attr->value, p->name); - xdpi = ydpi = 300; - } - - ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, - "printer-resolution-default", IPP_RES_PER_INCH, - xdpi, ydpi); - ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, - "printer-resolution-supported", IPP_RES_PER_INCH, - xdpi, ydpi); - } - else - { - /* - * No resolutions in PPD - make one up... - */ - - ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, - "printer-resolution-default", IPP_RES_PER_INCH, - 300, 300); - ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, - "printer-resolution-supported", IPP_RES_PER_INCH, - 300, 300); - } - - /* - * Duplexing, etc... - */ - - ppdMarkDefaults(ppd); - - 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 && - !ppdInstallableConflict(ppd, duplex->keyword, "DuplexTumble")) - { - p->type |= CUPS_PRINTER_DUPLEX; - - ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "sides-supported", 3, NULL, sides); - - if (!strcasecmp(duplex->defchoice, "DuplexTumble")) - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "sides-default", NULL, "two-sided-short-edge"); - else if (!strcasecmp(duplex->defchoice, "DuplexNoTumble")) - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "sides-default", NULL, "two-sided-long-edge"); - else - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "sides-default", NULL, "one-sided"); - } - else - { - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "sides-supported", NULL, "one-sided"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "sides-default", NULL, "one-sided"); - } - - if (ppdFindOption(ppd, "Collate") != NULL) - p->type |= CUPS_PRINTER_COLLATE; - - if (ppdFindOption(ppd, "StapleLocation") != NULL) - { - p->type |= CUPS_PRINTER_STAPLE; - finishings[num_finishings++] = IPP_FINISHINGS_STAPLE; - } - - if (ppdFindOption(ppd, "BindEdge") != NULL) - { - p->type |= CUPS_PRINTER_BIND; - finishings[num_finishings++] = IPP_FINISHINGS_BIND; - } - - for (i = 0; i < ppd->num_sizes; i ++) - if (ppd->sizes[i].length > 1728) - p->type |= CUPS_PRINTER_LARGE; - else if (ppd->sizes[i].length > 1008) - p->type |= CUPS_PRINTER_MEDIUM; - else - p->type |= CUPS_PRINTER_SMALL; - - if ((ppd_attr = ppdFindAttr(ppd, "APICADriver", NULL)) != NULL && - ppd_attr->value && !strcasecmp(ppd_attr->value, "true")) - { - if ((ppd_attr = ppdFindAttr(ppd, "APScannerOnly", NULL)) != NULL && - ppd_attr->value && !strcasecmp(ppd_attr->value, "true")) - p->type |= CUPS_PRINTER_SCANNER; - else - p->type |= CUPS_PRINTER_MFP; - } - - /* - * Add a filter from application/vnd.cups-raw to printer/name to - * handle "raw" printing by users. - */ - - add_string_array(&(p->filters), "application/vnd.cups-raw 0 -"); - - /* - * Add any pre-filters in the PPD file... - */ - - if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL) - { - for (; ppd_attr; ppd_attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL)) - if (ppd_attr->value) - add_string_array(&(p->pre_filters), ppd_attr->value); - } - - /* - * Add any filters in the PPD file... - */ - - DEBUG_printf(("ppd->num_filters = %d\n", ppd->num_filters)); - for (i = 0; i < ppd->num_filters; i ++) - { - DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i])); - add_string_array(&(p->filters), ppd->filters[i]); - - if (!strncasecmp(ppd->filters[i], "application/vnd.cups-command", 28) && - isspace(ppd->filters[i][28] & 255)) - p->type |= CUPS_PRINTER_COMMANDS; - } - - if (ppd->num_filters == 0) - { - /* - * If there are no filters, add PostScript printing filters. - */ - - add_string_array(&(p->filters), - "application/vnd.cups-command 0 commandtops"); - add_string_array(&(p->filters), - "application/vnd.cups-postscript 0 -"); - - p->type |= CUPS_PRINTER_COMMANDS; - } - else if (!(p->type & CUPS_PRINTER_COMMANDS)) - { - /* - * See if this is a PostScript device without a command filter... - */ - - for (i = 0; i < ppd->num_filters; i ++) - if (!strncasecmp(ppd->filters[i], - "application/vnd.cups-postscript", 31) && - isspace(ppd->filters[i][31] & 255)) - break; - - if (i < ppd->num_filters) - { - /* - * Add the generic PostScript command filter... - */ - - add_string_array(&(p->filters), - "application/vnd.cups-command 0 commandtops"); - p->type |= CUPS_PRINTER_COMMANDS; - } - } - - if (p->type & CUPS_PRINTER_COMMANDS) - { - char *commands, /* Copy of commands */ - *start, /* Start of name */ - *end; /* End of name */ - int count; /* Number of commands */ - - - if ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL && - ppd_attr->value && ppd_attr->value[0]) - { - for (count = 0, start = ppd_attr->value; *start; count ++) - { - while (isspace(*start & 255)) - start ++; - - if (!*start) - break; - - while (*start && !isspace(*start & 255)) - start ++; - } - } - else - count = 0; - - if (count > 0) - { - /* - * Make a copy of the commands string and count how many ... - */ - - attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "printer-commands", count, NULL, NULL); - - commands = strdup(ppd_attr->value); - - for (count = 0, start = commands; *start; count ++) - { - while (isspace(*start & 255)) - start ++; - - if (!*start) - break; - - end = start; - while (*end && !isspace(*end & 255)) - end ++; - - if (*end) - *end++ = '\0'; - - attr->values[count].string.text = _cupsStrAlloc(start); - - start = end; - } - - free(commands); - } - else - { - /* - * Add the standard list of commands... - */ - - ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "printer-commands", - (int)(sizeof(standard_commands) / - sizeof(standard_commands[0])), NULL, - standard_commands); - } - } - else - { - /* - * No commands supported... - */ - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "printer-commands", NULL, "none"); - } - - /* - * Show current and available port monitors for this printer... - */ - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor", - NULL, p->port_monitor ? p->port_monitor : "none"); - - for (i = 1, ppd_attr = ppdFindAttr(ppd, "cupsPortMonitor", NULL); - ppd_attr; - i ++, ppd_attr = ppdFindNextAttr(ppd, "cupsPortMonitor", NULL)); - - if (ppd->protocols) - { - if (strstr(ppd->protocols, "TBCP")) - i ++; - else if (strstr(ppd->protocols, "BCP")) - i ++; - } - - attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "port-monitor-supported", i, NULL, NULL); - - attr->values[0].string.text = _cupsStrAlloc("none"); - - for (i = 1, ppd_attr = ppdFindAttr(ppd, "cupsPortMonitor", NULL); - ppd_attr; - i ++, ppd_attr = ppdFindNextAttr(ppd, "cupsPortMonitor", NULL)) - attr->values[i].string.text = _cupsStrAlloc(ppd_attr->value); - - if (ppd->protocols) - { - if (strstr(ppd->protocols, "TBCP")) - attr->values[i].string.text = _cupsStrAlloc("tbcp"); - else if (strstr(ppd->protocols, "BCP")) - attr->values[i].string.text = _cupsStrAlloc("bcp"); - } - -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - cupsdSetString(&p->product, ppd->product); -#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ - - if (ppdFindAttr(ppd, "APRemoteQueueID", NULL)) - p->type |= CUPS_PRINTER_REMOTE; - -#ifdef HAVE_APPLICATIONSERVICES_H - /* - * Convert the file referenced in APPrinterIconPath to a 128x128 PNG - * and save it as cacheDir/printername.png - */ - - if ((ppd_attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL)) != NULL && - ppd_attr->value) - { - CGImageRef imageRef = NULL;/* Current icon image */ - CGImageRef biggestIconRef = NULL; - /* Biggest icon image */ - CGImageRef closestTo128IconRef = NULL; - /* Icon image closest to and >= 128 */ - CGImageSourceRef sourceRef; /* The file's image source */ - char outPath[HTTP_MAX_URI]; - /* The path to the PNG file */ - CFURLRef outUrl; /* The URL made from the outPath */ - CFURLRef icnsFileUrl; /* The URL of the original ICNS icon file */ - CGImageDestinationRef destRef; /* The image destination to write */ - size_t bytesPerRow; /* The bytes per row used for resizing */ - CGContextRef context; /* The CG context used for resizing */ - - snprintf(outPath, sizeof(outPath), "%s/%s.png", CacheDir, p->name); - outUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, - (UInt8 *)outPath, - strlen(outPath), - FALSE); - icnsFileUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, - (UInt8 *)ppd_attr->value, - strlen(ppd_attr->value), - FALSE); - if (outUrl && icnsFileUrl) - { - sourceRef = CGImageSourceCreateWithURL(icnsFileUrl, NULL); - if (sourceRef) - { - for (i = 0; i < CGImageSourceGetCount(sourceRef); i ++) - { - imageRef = CGImageSourceCreateImageAtIndex(sourceRef, i, NULL); - if (imageRef && - CGImageGetWidth(imageRef) == CGImageGetHeight(imageRef)) - { - /* - * Loop through remembering the icon closest to 128 but >= 128 - * and then remember the largest icon. - */ - - if (CGImageGetWidth(imageRef) >= 128 && - (!closestTo128IconRef || - CGImageGetWidth(imageRef) < - CGImageGetWidth(closestTo128IconRef))) - { - CGImageRelease(closestTo128IconRef); - CGImageRetain(imageRef); - closestTo128IconRef = imageRef; - } - - if (!biggestIconRef || - CGImageGetWidth(imageRef) > CGImageGetWidth(biggestIconRef)) - { - CGImageRelease(biggestIconRef); - CGImageRetain(imageRef); - biggestIconRef = imageRef; - } - - CGImageRelease(imageRef); - } - } - - if (biggestIconRef) - { - /* - * If biggestIconRef is NULL, we found no icons. Otherwise we first - * want the closest to 128, but if none are larger than 128, we want - * the largest icon available. - */ - - imageRef = closestTo128IconRef ? closestTo128IconRef : - biggestIconRef; - CGImageRetain(imageRef); - CGImageRelease(biggestIconRef); - CGImageRelease(closestTo128IconRef); - destRef = CGImageDestinationCreateWithURL(outUrl, kUTTypePNG, 1, - NULL); - if (destRef) - { - if (CGImageGetWidth(imageRef) != 128) - { - bytesPerRow = CGImageGetBytesPerRow(imageRef) / - CGImageGetWidth(imageRef) * 128; - context = CGBitmapContextCreate(NULL, 128, 128, - CGImageGetBitsPerComponent(imageRef), - bytesPerRow, - CGImageGetColorSpace(imageRef), - kCGImageAlphaPremultipliedFirst); - if (context) - { - CGContextDrawImage(context, CGRectMake(0, 0, 128, 128), - imageRef); - CGImageRelease(imageRef); - imageRef = CGBitmapContextCreateImage(context); - CGContextRelease(context); - } - } - - CGImageDestinationAddImage(destRef, imageRef, NULL); - CGImageDestinationFinalize(destRef); - CFRelease(destRef); - } - - CGImageRelease(imageRef); - } - - CFRelease(sourceRef); - CFRelease(icnsFileUrl); - } - - CFRelease(outUrl); - } - } -#endif /* HAVE_APPLICATIONSERVICES_H */ - - /* - * Close the PPD and set the type... - */ - - ppdClose(ppd); - } - else if (!access(ppd_name, 0)) - { - int pline; /* PPD line number */ - ppd_status_t pstatus; /* PPD load status */ - - - pstatus = ppdLastError(&pline); - - 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_INFO, - "Hint: Run \"cupstestppd %s\" and fix any errors.", - ppd_name); - - /* - * Add a filter from application/vnd.cups-raw to printer/name to - * handle "raw" printing by users. - */ - - add_string_array(&(p->filters), "application/vnd.cups-raw 0 -"); - - /* - * Add a PostScript filter, since this is still possibly PS printer. - */ - - add_string_array(&(p->filters), "application/vnd.cups-postscript 0 -"); - } - else - { - /* - * If we have an interface script, add a filter entry for it... - */ - - char interface[1024]; /* Interface script */ - - - snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot, - p->name); - if (!access(interface, X_OK)) - { - /* - * Yes, we have a System V style interface script; use it! - */ - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, - "Local System V Printer"); - - snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s", - ServerRoot, p->name); - add_string_array(&(p->filters), interface); - } - else if (!strncmp(p->device_uri, "ipp://", 6) && - (strstr(p->device_uri, "/printers/") != NULL || - strstr(p->device_uri, "/classes/") != NULL || - (strstr(p->device_uri, "._ipp.") != NULL && - !strcmp(p->device_uri + strlen(p->device_uri) - 5, - "/cups")))) - { - /* - * Tell the client this is really a hard-wired remote printer. - */ - - p->type |= CUPS_PRINTER_REMOTE; - - /* - * Point the printer-uri-supported attribute to the - * remote printer... - */ - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, - "printer-uri-supported", NULL, p->device_uri); - - /* - * Then set the make-and-model accordingly... - */ - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, "Remote Printer"); - - /* - * Print all files directly... - */ - - p->raw = 1; - p->remote = 1; - } - else - { - /* - * Otherwise we have neither - treat this as a "dumb" printer - * with no PPD file... - */ - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, "Local Raw Printer"); - - p->raw = 1; - } - } - - ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "finishings-supported", num_finishings, finishings); - ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "finishings-default", IPP_FINISHINGS_NONE); - - if (ppd && (cache = cupsFileOpen(cache_name, "w9")) != NULL) - { - /* - * Save cached PPD attributes to disk... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Saving %s...", cache_name); - - p->ppd_attrs->state = IPP_IDLE; - - if (ippWriteIO(cache, (ipp_iocb_t)cupsFileWrite, 1, NULL, - p->ppd_attrs) != IPP_DATA) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to save PPD cache file \"%s\" - %s", cache_name, - strerror(errno)); - unlink(cache_name); - } - - cupsFileClose(cache); - - _pwgWriteFile(p->pwg, pwg_name); - } - else - { - /* - * Remove cache files... - */ - - if (cache_info.st_mtime) - unlink(cache_name); - - if (pwg_info.st_mtime) - unlink(pwg_name); - } -} - - -/* - * 'new_media_col()' - Create a media-col collection value. - */ - -static ipp_t * /* O - Collection value */ -new_media_col(_pwg_size_t *size, /* I - media-size/margin values */ - const char *source, /* I - media-source value */ - const char *type) /* I - media-type value */ -{ - ipp_t *media_col, /* Collection value */ - *media_size; /* media-size value */ - - - media_col = ippNew(); - - media_size = ippNew(); - ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "x-dimension", size->width); - ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "y-dimension", size->length); - ippAddCollection(media_col, IPP_TAG_PRINTER, "media-size", media_size); - ippDelete(media_size); - - ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-bottom-margin", size->bottom); - ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-left-margin", size->left); - ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-right-margin", size->right); - ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "media-top-margin", size->top); - - if (source) - ippAddString(media_col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-source", - NULL, source); - - if (type) - ippAddString(media_col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-type", - NULL, type); - - return (media_col); -} - - -#ifdef __sgi -/* - * 'write_irix_config()' - Update the config files used by the IRIX - * desktop tools. - */ - -static void -write_irix_config(cupsd_printer_t *p) /* I - Printer to update */ -{ - char filename[1024]; /* Interface script filename */ - cups_file_t *fp; /* Interface script file */ - ipp_attribute_t *attr; /* Attribute data */ - - - /* - * Add dummy interface and GUI scripts to fool SGI's "challenged" printing - * tools. First the interface script that tells the tools what kind of - * printer we have... - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePuts(fp, "#!/bin/sh\n"); - - if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model", - IPP_TAG_TEXT)) != NULL) - cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text); - else if (p->type & CUPS_PRINTER_CLASS) - cupsFilePuts(fp, "NAME=\"Printer Class\"\n"); - else - cupsFilePuts(fp, "NAME=\"Remote Destination\"\n"); - - if (p->type & CUPS_PRINTER_COLOR) - cupsFilePuts(fp, "TYPE=ColorPostScript\n"); - else - cupsFilePuts(fp, "TYPE=MonoPostScript\n"); - - cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName); - cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name); - - cupsFileClose(fp); - - chmod(filename, 0755); - chown(filename, User, Group); - } - - /* - * Then the member file that tells which device file the queue is connected - * to... Networked printers use "/dev/null" in this file, so that's what - * we use (the actual device URI can confuse some apps...) - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePuts(fp, "/dev/null\n"); - - cupsFileClose(fp); - - chmod(filename, 0644); - chown(filename, User, Group); - } - - /* - * The gui_interface file is a script or program that launches a GUI - * option panel for the printer, using options specified on the - * command-line in the third argument. The option panel must send - * any printing options to stdout on a single line when the user - * accepts them, or nothing if the user cancels the dialog. - * - * The default options panel program is /usr/bin/glpoptions, from - * the ESP Print Pro software. You can select another using the - * PrintcapGUI option. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePuts(fp, "#!/bin/sh\n"); - cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name); - - cupsFileClose(fp); - - chmod(filename, 0755); - chown(filename, User, Group); - } - - /* - * The POD config file is needed by the printstatus command to show - * the printer location and device. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePrintf(fp, "Printer Class | %s\n", - (p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript"); - cupsFilePrintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : ""); - cupsFilePrintf(fp, "Location Code | %s\n", p->location ? p->location : ""); - cupsFilePrintf(fp, "Physical Location | %s\n", p->info ? p->info : ""); - cupsFilePrintf(fp, "Port Path | %s\n", p->device_uri); - cupsFilePrintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name); - cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name); - cupsFilePuts(fp, "Status Update Wait | 10 seconds\n"); - - cupsFileClose(fp); - - chmod(filename, 0664); - chown(filename, User, Group); - } -} - - -/* - * 'write_irix_state()' - Update the status files used by IRIX printing - * desktop tools. - */ - -static void -write_irix_state(cupsd_printer_t *p) /* I - Printer to update */ -{ - char filename[1024]; /* Interface script filename */ - cups_file_t *fp; /* Interface script file */ - int tag; /* Status tag value */ - - - if (p) - { - /* - * The POD status file is needed for the printstatus window to - * provide the current status of the printer. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePrintf(fp, "Operational Status | %s\n", - (p->state == IPP_PRINTER_IDLE) ? "Idle" : - (p->state == IPP_PRINTER_PROCESSING) ? "Busy" : - "Faulted"); - cupsFilePrintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION); - cupsFilePrintf(fp, "Information | 02 00 00 | Device URI: %s\n", - p->device_uri); - cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n", - p->accepting ? "Accepting" : "Not accepting"); - cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message); - - cupsFileClose(fp); - - chmod(filename, 0664); - chown(filename, User, Group); - } - - /* - * The activeicons file is needed to provide desktop icons for printers: - * - * [ quoted from /usr/lib/print/tagit ] - * - * --- Type of printer tags (base values) - * - * Dumb=66048 # 0x10200 - * DumbColor=66080 # 0x10220 - * Raster=66112 # 0x10240 - * ColorRaster=66144 # 0x10260 - * Plotter=66176 # 0x10280 - * PostScript=66208 # 0x102A0 - * ColorPostScript=66240 # 0x102C0 - * MonoPostScript=66272 # 0x102E0 - * - * --- Printer state modifiers for local printers - * - * Idle=0 # 0x0 - * Busy=1 # 0x1 - * Faulted=2 # 0x2 - * Unknown=3 # 0x3 (Faulted due to unknown reason) - * - * --- Printer state modifiers for network printers - * - * NetIdle=8 # 0x8 - * NetBusy=9 # 0x9 - * NetFaulted=10 # 0xA - * NetUnknown=11 # 0xB (Faulted due to unknown reason) - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - if (p->type & CUPS_PRINTER_COLOR) - tag = 66240; - else - tag = 66272; - - if (p->type & CUPS_PRINTER_REMOTE) - tag |= 8; - - if (p->state == IPP_PRINTER_PROCESSING) - tag |= 1; - - else if (p->state == IPP_PRINTER_STOPPED) - tag |= 2; - - cupsFilePuts(fp, "#!/bin/sh\n"); - cupsFilePrintf(fp, "#Tag %d\n", tag); - - cupsFileClose(fp); - - chmod(filename, 0755); - chown(filename, User, Group); - } - } - - /* - * The default file is needed by the printers window to show - * the default printer. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/default"); - - if (DefaultPrinter != NULL) - { - if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePrintf(fp, "%s\n", DefaultPrinter->name); - - cupsFileClose(fp); - - chmod(filename, 0644); - chown(filename, User, Group); - } - } - else - unlink(filename); -} -#endif /* __sgi */ - -/* - * 'write_xml_string()' - Write a string with XML escaping. - */ - -static void -write_xml_string(cups_file_t *fp, /* I - File to write to */ - const char *s) /* I - String to write */ -{ - const char *start; /* Start of current sequence */ - - - if (!s) - return; - - for (start = s; *s; s ++) - { - if (*s == '&') - { - if (s > start) - cupsFileWrite(fp, start, s - start); - - cupsFilePuts(fp, "&"); - start = s + 1; - } - else if (*s == '<') - { - if (s > start) - cupsFileWrite(fp, start, s - start); - - cupsFilePuts(fp, "<"); - start = s + 1; - } - } - - if (s > start) - cupsFilePuts(fp, start); -} - - -#ifdef __APPLE__ -/* - * 'apple_init_profile()' - Initialize a color profile. - */ - -static void -apple_init_profile( - ppd_file_t *ppd, /* I - PPD file */ - cups_array_t *languages, /* I - Languages in the PPD file */ - CMDeviceProfileInfo *profile, /* I - Profile record */ - unsigned id, /* I - Profile ID */ - const char *name, /* I - Profile name */ - const char *text, /* I - Profile UI text */ - const char *iccfile) /* I - ICC filename */ -{ - char url[1024]; /* URL for profile filename */ - CFMutableDictionaryRef dict; /* Dictionary for name */ - char *language; /* Current language */ - ppd_attr_t *attr; /* Profile attribute */ - CFStringRef cflang, /* Language string */ - cftext; /* Localized text */ - - - /* - * Build the profile name dictionary... - */ - - dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - cftext = CFStringCreateWithCString(kCFAllocatorDefault, text, - kCFStringEncodingUTF8); - - if (cftext) - { - CFDictionarySetValue(dict, CFSTR("en"), cftext); - CFRelease(cftext); - } - - if (languages) - { - /* - * Find localized names for the color profiles... - */ - - cupsArraySave(ppd->sorted_attrs); - - for (language = (char *)cupsArrayFirst(languages); - language; - language = (char *)cupsArrayNext(languages)) - { - if (iccfile) - { - if ((attr = _ppdLocalizedAttr(ppd, "cupsICCProfile", name, - language)) == NULL) - attr = _ppdLocalizedAttr(ppd, "APTiogaProfile", name, language); - } - else - attr = _ppdLocalizedAttr(ppd, "ColorModel", name, language); - - if (attr && attr->text[0]) - { - cflang = CFStringCreateWithCString(kCFAllocatorDefault, language, - kCFStringEncodingUTF8); - cftext = CFStringCreateWithCString(kCFAllocatorDefault, attr->text, - kCFStringEncodingUTF8); - - if (cflang && cftext) - CFDictionarySetValue(dict, cflang, cftext); - - if (cflang) - CFRelease(cflang); - - if (cftext) - CFRelease(cftext); - } - } - - cupsArrayRestore(ppd->sorted_attrs); - } - - /* - * Fill in the profile data... - */ - - if (iccfile) - httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "file", NULL, "", 0, - iccfile); - - profile->dataVersion = cmDeviceProfileInfoVersion1; - profile->profileID = id; - profile->profileLoc.locType = iccfile ? cmPathBasedProfile : cmNoProfileBase; - profile->profileName = dict; - - if (iccfile) - strlcpy(profile->profileLoc.u.pathLoc.path, iccfile, - sizeof(profile->profileLoc.u.pathLoc.path)); -} -#endif /* __APPLE__ */ - - -#if !defined(__APPLE__) && defined(HAVE_DBUS) -/* - * 'dbus_create_profile()' - Create a color profile for a printer. - */ - -static void -dbus_create_profile (cups_array_t *profiles, /* I - Profiles array */ - DBusConnection *con, /* I - D-Bus connection */ - const char *printer_name, /* I - Printer name */ - const char *qualifier, /* I - Profile qualifier */ - const char *iccfile) /* I - ICC filename */ -{ - DBusMessage *message; /* D-Bus message */ - DBusMessageIter args; /* D-Bus method arguments */ - DBusPendingCall *pending; /* D-Bus method call */ - char *path = NULL; /* Profile path */ - char *idstr; /* Profile ID string */ - size_t idstrlen; /* Profile ID allocated length */ - int options = 1; /* Options for CreateProfile */ - - /* - * Create the profile... - */ - - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - "/org/freedesktop/ColorManager", - "org.freedesktop.ColorManager", - "CreateProfile"); - - dbus_message_append_iter_init(message, &args); - idstrlen = strlen (printer_name) + 1 + strlen (qualifier) + 1; - idstr = malloc (idstrlen); - if (!idstr) - goto out; - - snprintf (idstr, idstrlen, "%s-%s", printer_name, qualifier); - dbus_message_iter_append_string(&args, idstr); - dbus_message_iter_append_uint32(&args, options); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateProfile(%s,%d)", - idstr, options); - if (!dbus_connection_send_with_reply(con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); - message = dbus_pending_call_steal_reply(pending); -// dbus_pending_call_unref(pending); <-fixme - - if (!message || - !dbus_message_iter_init(message, &args) || - dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) - goto out; - - dbus_message_iter_get_basic(&args, &path); - path = strdup(path); - cupsArrayAdd(profiles, strdup(path)); - - /* - * Set the qualifier... - */ - - dbus_message_unref(message); - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - path, - "org.freedesktop.ColorManager.Profile", - "SetQualifier"); - dbus_message_append_iter_init(message, &args); - dbus_message_iter_append_string(&args, qualifier); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling SetQualifier(%s)", qualifier); - if (!dbus_connection_send_with_reply(con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); - message = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - - /* - * If we know the ICC file for it, set that now... - */ - - if (!iccfile) - goto out; - - dbus_message_unref(message); - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - path, - "org.freedesktop.ColorManager.Profile", - "SetFilename"); - dbus_message_append_iter_init(message, &args); - dbus_message_iter_append_string(&args, iccfile); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling SetFilename(%s)", iccfile); - if (!dbus_connection_send_with_reply(con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); - message = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - -out: - free (path); - free (idstr); - dbus_message_unref(message); -} - - -/* - * 'dbus_create_device()' - Create a device and register profiles. - */ - -static void -dbus_create_device (DBusConnection *con, /* I - D-Bus connection */ - const char *name, /* I - Printer name */ - cups_array_t *profiles, /* I - Profiles array */ - const char *default_profile_id) /* I - Default profile */ -{ - DBusMessage *message; /* D-Bus message */ - DBusMessageIter args; /* D-Bus method arguments */ - DBusPendingCall *pending; /* D-Bus method call */ - const char *device_path_tmp; /* Device path data */ - char *device_path = NULL; /* Device path */ - const char *profile_path; /* Profile path */ - char *default_profile_path = NULL; - /* Default profile path */ - size_t default_path_len; - /* Length of profile path */ - int options = 1; /* Options for CreateDevice */ - - /* - * Create the device... - */ - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - "/org/freedesktop/ColorManager", - "org.freedesktop.ColorManager", - "CreateDevice"); - - dbus_message_append_iter_init(message, &args); - dbus_message_iter_append_string(&args, name); - dbus_message_iter_append_uint32(&args, options); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateDevice(%s,%d)", - name, options); - if (!dbus_connection_send_with_reply (con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); - message = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - - if (!message || - !dbus_message_iter_init(message, &args) || - dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) - goto out; - - /* get device path, and duplicate so we can free the method */ - dbus_message_iter_get_basic(&args, &device_path_tmp); - device_path = strdup (device_path_tmp); - dbus_message_unref(message); - for (profile_path = cupsArrayFirst(profiles); - profile_path; - profile_path = cupsArrayNext(profiles)) - { - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - device_path, - "org.freedesktop.ColorManager.Device", - "AddProfile"); - - dbus_message_append_iter_init(message, &args); - dbus_message_iter_append_object_path(&args, profile_path); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling AddProfile(%s)", profile_path); - pending = NULL; - if (!dbus_connection_send_with_reply (con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); -// message = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - } - - /* - * Set the default profile - */ - default_path_len = strlen (name) + 1 + strlen (default_profile_id) + 1; - default_profile_path = malloc (default_path_len); - if (!default_profile_path) - goto out; - - snprintf(default_profile_path, default_path_len, "%s-%s", name, - default_profile_id); - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - device_path, - "org.freedesktop.ColorManager.Device", - "MakeProfileDefault"); - - dbus_message_append_iter_init(message, &args); - dbus_message_iter_append_string(&args, default_profile_path); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling MakeProfileDefault(%s)", - default_profile_path); - if (!dbus_connection_send_with_reply (con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); -// message = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - -out: - free(default_profile_path); - free(device_path); -// dbus_message_unref(message); -} - - -/* - * 'dbus_delete_device_and_profiles()' - Delete previously registered - * color device and profiles - */ - -static void -dbus_delete_device_and_profiles(cupsd_printer_t *p) /* I - Printer */ -{ - DBusConnection *con; /* System D-Bus connection */ - DBusMessage *message; /* D-Bus message */ - DBusMessageIter args, array_args; /* D-Bus method arguments */ - DBusPendingCall *pending; /* D-Bus method call */ - const char *device_path; /* Device path */ - const char *options = ""; /* Options for GetProfilesForDevice */ - cups_array_t *profile_paths; /* Profile paths array */ - char *profile_path; /* Profile path */ - - con = dbus_bus_get (DBUS_BUS_SYSTEM, NULL); - if (!con) - return; - - /* - * Get the device path - */ - - profile_paths = cupsArrayNew(NULL, NULL); - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - "/org/freedesktop/ColorManager", - "org.freedesktop.ColorManager", - "FindDeviceById"); - - dbus_message_append_iter_init(message, &args); - dbus_message_iter_append_string(&args, p->name); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling FindDeviceById"); - if (!dbus_connection_send_with_reply(con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); - message = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - - if (!message || - !dbus_message_iter_init(message, &args) || - dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) - goto out; - - dbus_message_iter_get_basic(&args, &device_path); - device_path = strdup(device_path); - - /* - * Get the profiles - */ - - dbus_message_unref(message); - message = dbus_message_new_method_call("org.freedesktop.ColorManager", - "/org/freedesktop/ColorManager", - "org.freedesktop.ColorManager", - "GetProfilesForDevice"); - - dbus_message_append_iter_init(message, &args); - dbus_message_iter_append_object_path(&args, device_path); - dbus_message_iter_append_string(&args, options); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling GetProfilesForDevice(%s,\"\")", - device_path); - if (!dbus_connection_send_with_reply(con, message, &pending, -1)) - goto out; - - dbus_connection_flush(con); - dbus_message_unref(message); - dbus_pending_call_block(pending); - message = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - - if (!message || - !dbus_message_iter_init(message, &args) || - dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY) - goto out; - - dbus_message_iter_recurse(&args, &array_args); - do - { - if (dbus_message_iter_get_arg_type(&array_args) == DBUS_TYPE_OBJECT_PATH) - { - dbus_message_iter_get_basic(&array_args, &profile_path); - cupsArrayAdd(profile_paths, strdup (profile_path)); - } - } while (dbus_message_iter_next(&array_args)); - - /* - * Delete each profile. - */ - - -out: - for (profile_path = cupsArrayFirst(profile_paths); - profile_path; - profile_path = cupsArrayNext(profile_paths)) - free (profile_path); - - cupsArrayDelete(profile_paths); - dbus_message_unref(message); - dbus_connection_unref(con); -} -#endif /* !defined(__APPLE__) && defined(HAVE_DBUS) */ - - -/* - * 'cupsdRegisterColorProfiles()' - Register color profiles for a printer. - */ - -void -cupsdRegisterColorProfiles( - cupsd_printer_t *p) /* I - Printer */ -{ - int i; /* Looping var */ - char ppdfile[1024], /* PPD filename */ - iccfile[1024], /* ICC filename */ - selector[PPD_MAX_NAME]; - /* Profile selection string */ - ppd_file_t *ppd; /* PPD file */ - ppd_attr_t *attr, /* Profile attributes */ - *q1_attr, /* ColorModel (or other) qualifier */ - *q2_attr, /* MediaType (or other) qualifier */ - *q3_attr; /* Resolution (or other) qualifier */ - char q_keyword[PPD_MAX_NAME]; - /* Qualifier keyword */ - const char *q1_choice, /* ColorModel (or other) choice */ - *q2_choice, /* MediaType (or other) choice */ - *q3_choice; /* Resolution (or other) choice */ - const char *profile_key; /* Profile keyword */ - ppd_option_t *cm_option; /* Color model option */ - ppd_choice_t *cm_choice; /* Color model choice */ - int num_profiles; /* Number of profiles */ -#ifdef __APPLE__ - ppd_attr_t *profileid_attr;/* cupsProfileID attribute */ - unsigned profile_id, /* Profile ID */ - default_profile_id = 0; - /* Default profile ID */ - CMError error; /* Last error */ - CFMutableDictionaryRef device_name; /* Printer device name dictionary */ - unsigned device_id; /* Printer device ID */ - CFStringRef printer_name; /* Printer name string */ - CMDeviceScope scope = /* Scope of the registration */ - { - kCFPreferencesAnyUser, - kCFPreferencesCurrentHost - }; - CMDeviceProfileArrayPtr profiles; /* Profiles */ - CMDeviceProfileInfo *profile; /* Current profile */ - cups_array_t *languages; /* Languages array */ -#elif HAVE_DBUS - const char *profile_id = NULL, - /* Profile ID */ - *default_profile_id = NULL; - /* Default profile ID */ - DBusError error; /* Error, if any */ - static DBusConnection *con; /* System D-Bus connection */ - cups_array_t *profiles; /* Profile paths array */ - char *profile_path; /* Profile path */ -#endif /* HAVE_DBUS */ - - -#ifdef __APPLE__ - /* - * Make sure ColorSync is available... - */ - - if (CMRegisterColorDevice == NULL) - return; -#elif defined(HAVE_DBUS) - if (con && !dbus_connection_get_is_connected(con)) - { - dbus_connection_unref(con); - con = NULL; - } - - if (!con) - { - dbus_error_init(&error); - - con = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if (!con) - { - if (dbus_error_is_set(&error)) - cupsdLogMessage(CUPSD_LOG_DEBUG, - "D-Bus connection error: %s", error.message); - - dbus_error_free(&error); - return; - } - } - - profiles = cupsArrayNew (NULL, NULL); -#else /* defined(__APPLE__) || defined(HAVE_DBUS) */ - return; -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - - /* - * Try opening the PPD file for this printer... - */ - - snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name); - if ((ppd = ppdOpenFile(ppdfile)) == NULL) - return; - - /* - * See if we have any profiles... - */ - - if ((attr = ppdFindAttr(ppd, "APTiogaProfile", NULL)) != NULL) - profile_key = "APTiogaProfile"; - else - { - attr = ppdFindAttr(ppd, "cupsICCProfile", NULL); - profile_key = "cupsICCProfile"; - } - - for (num_profiles = 0; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL)) - if (attr->spec[0] && attr->value && attr->value[0]) - { - if (attr->value[0] != '/') - snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, - attr->value); - else - strlcpy(iccfile, attr->value, sizeof(iccfile)); - - if (access(iccfile, 0)) - continue; - - num_profiles ++; - } - - - /* - * If we have profiles, add them... - */ - - if (num_profiles > 0) - { - if (profile_key[0] == 'A') - { - /* - * For Tioga PPDs, get the default profile using the DefaultAPTiogaProfile - * attribute... - */ - - if ((attr = ppdFindAttr(ppd, "DefaultAPTiogaProfile", NULL)) != NULL && - attr->value) - { -#ifdef __APPLE__ - default_profile_id = atoi(attr->value); -#elif HAVE_DBUS - default_profile_id = attr->value; -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - } - - q1_choice = q2_choice = q3_choice = NULL; - } - else - { - /* - * For CUPS PPDs, figure out the default profile selector values... - */ - - if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL && - attr->value && attr->value[0]) - { - snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); - q1_attr = ppdFindAttr(ppd, q_keyword, NULL); - } - else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL) - q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); - - if (q1_attr && q1_attr->value && q1_attr->value[0]) - q1_choice = q1_attr->value; - else - q1_choice = ""; - - if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL && - attr->value && attr->value[0]) - { - snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); - q2_attr = ppdFindAttr(ppd, q_keyword, NULL); - } - else - q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL); - - if (q2_attr && q2_attr->value && q2_attr->value[0]) - q2_choice = q2_attr->value; - else - q2_choice = NULL; - - if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL && - attr->value && attr->value[0]) - { - snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); - q3_attr = ppdFindAttr(ppd, q_keyword, NULL); - } - else - q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL); - - if (q3_attr && q3_attr->value && q3_attr->value[0]) - q3_choice = q3_attr->value; - else - q3_choice = NULL; - } - -#ifdef __APPLE__ - /* - * Build the array of profiles... - * - * Note: This calloc actually requests slightly more memory than needed. - */ - - if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate memory for %d profiles!", - num_profiles); - ppdClose(ppd); - return; - } - - profiles->profileCount = num_profiles; - languages = _ppdGetLanguages(ppd); - profile = profiles->profiles; -#endif /* __APPLE__ */ - - for (attr = ppdFindAttr(ppd, profile_key, NULL); - attr; - attr = ppdFindNextAttr(ppd, profile_key, NULL)) - if (attr->spec[0] && attr->value && attr->value[0]) - { - /* - * Add this profile... - */ - - if (attr->value[0] != '/') - snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, - attr->value); - else - strlcpy(iccfile, attr->value, sizeof(iccfile)); - - if (access(iccfile, 0)) - continue; - -#ifdef __APPLE__ - if (profile_key[0] == 'c') - { - cupsArraySave(ppd->sorted_attrs); - - if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID", - attr->spec)) != NULL && - profileid_attr->value && isdigit(profileid_attr->value[0] & 255)) - profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10); - else - profile_id = _ppdHashName(attr->spec); - - cupsArrayRestore(ppd->sorted_attrs); - } - else - profile_id = atoi(attr->spec); - - apple_init_profile(ppd, languages, profile, profile_id, attr->spec, - attr->text[0] ? attr->text : attr->spec, iccfile); - profile ++; -#elif defined(HAVE_DBUS) - profile_id = attr->spec; - dbus_create_profile(profiles, con, p->name, attr->spec, iccfile); -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - - /* - * See if this is the default profile... - */ - - if (!default_profile_id) - { - if (q2_choice) - { - if (q3_choice) - { - snprintf(selector, sizeof(selector), "%s.%s.%s", - q1_choice, q2_choice, q3_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - - if (!default_profile_id) - { - snprintf(selector, sizeof(selector), "%s.%s.", q1_choice, - q2_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - } - - if (!default_profile_id && q3_choice) - { - snprintf(selector, sizeof(selector), "%s..%s", q1_choice, - q3_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - - if (!default_profile_id) - { - snprintf(selector, sizeof(selector), "%s..", q1_choice); - if (!strcmp(selector, attr->spec)) - default_profile_id = profile_id; - } - } - } - -#ifdef __APPLE__ - _ppdFreeLanguages(languages); -#endif /* __APPLE__ */ - } - else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL) - { - /* - * Extract profiles from ColorModel option... - */ - - const char *profile_name; /* Name of generic profile */ - - - num_profiles = cm_option->num_choices; - -#ifdef __APPLE__ - if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate memory for %d profiles!", - num_profiles); - ppdClose(ppd); - return; - } - - profiles->profileCount = num_profiles; - profile = profiles->profiles; -#endif /* __APPLE__ */ - - for (i = cm_option->num_choices, cm_choice = cm_option->choices; - i > 0; - i --, cm_choice ++) - { - if (!strcmp(cm_choice->choice, "Gray") || - !strcmp(cm_choice->choice, "Black")) - profile_name = "Gray"; - else if (!strcmp(cm_choice->choice, "RGB") || - !strcmp(cm_choice->choice, "CMY")) - profile_name = "RGB"; - else if (!strcmp(cm_choice->choice, "CMYK") || - !strcmp(cm_choice->choice, "KCMY")) - profile_name = "CMYK"; - else - profile_name = "DeviceN"; - - snprintf(selector, sizeof(selector), "%s..", profile_name); - -#ifdef __APPLE__ - profile_id = _ppdHashName(selector); - apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice, - cm_choice->text, NULL); - profile ++; -#elif defined(HAVE_DBUS) - profile_id = selector; - dbus_create_profile(profiles, con, p->name, selector, NULL); -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - - if (cm_choice->marked) - default_profile_id = profile_id; - } - } - else - { - /* - * Use the default colorspace... - */ - - attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); - - num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2; - -#ifdef __APPLE__ - if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate memory for %d profiles!", - num_profiles); - ppdClose(ppd); - return; - } - - profiles->profileCount = num_profiles; - - apple_init_profile(ppd, NULL, profiles->profiles, _ppdHashName("Gray.."), - "Gray", "Gray", NULL); -#elif defined(HAVE_DBUS) - profile_id = "Gray.."; - dbus_create_profile(profiles, con, p->name, profile_id, NULL); -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - - switch (ppd->colorspace) - { - case PPD_CS_RGB : - case PPD_CS_CMY : -#ifdef __APPLE__ - apple_init_profile(ppd, NULL, profiles->profiles + 1, - _ppdHashName("RGB.."), "RGB", "RGB", NULL); -#elif defined(HAVE_DBUS) - profile_id = "RGB.."; - dbus_create_profile(profiles, con, p->name, profile_id, NULL); -#endif /* HAVE_DBUS */ - break; - case PPD_CS_RGBK : - case PPD_CS_CMYK : -#ifdef __APPLE__ - apple_init_profile(ppd, NULL, profiles->profiles + 1, - _ppdHashName("CMYK.."), "CMYK", "CMYK", NULL); -#elif defined(HAVE_DBUS) - profile_id = "CMYK.."; - dbus_create_profile(profiles, con, p->name, profile_id, NULL); -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - break; - - case PPD_CS_GRAY : - if (attr) - break; - - case PPD_CS_N : -#ifdef __APPLE__ - apple_init_profile(ppd, NULL, profiles->profiles + 1, - _ppdHashName("DeviceN.."), "DeviceN", "DeviceN", - NULL); -#elif defined(HAVE_DBUS) - profile_id = "DeviceN.."; - dbus_create_profile(profiles, con, p->name, profile_id, NULL); -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - - break; - } - } - - if (num_profiles > 0) - { - /* - * Make sure we have a default profile ID... - */ - - if (!default_profile_id) - { -#ifdef __APPLE__ - default_profile_id = profiles->profiles[num_profiles - 1].profileID; -#elif HAVE_DBUS - default_profile_id = profile_id; -#endif /* __APPLE__ */ - } - - /* - * Get the device ID hash and pathelogical name dictionary. - */ - - cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"", - p->name); - -#ifdef __APPLE__ - device_id = _ppdHashName(p->name); - - device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - printer_name = CFStringCreateWithCString(kCFAllocatorDefault, - p->name, kCFStringEncodingUTF8); - - if (device_name && printer_name) - { - CFDictionarySetValue(device_name, CFSTR("en"), printer_name); - - /* - * Register the device with ColorSync... - */ - - error = CMRegisterColorDevice(cmPrinterDeviceClass, device_id, - device_name, &scope); - - /* - * Register the profiles... - */ - - if (error == noErr) - error = CMSetDeviceFactoryProfiles(cmPrinterDeviceClass, device_id, - default_profile_id, profiles); - } - else - error = 1000; -#elif defined(HAVE_DBUS) - dbus_create_device (con, p->name, profiles, default_profile_id); -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - - /* - * Clean up... - */ - -#ifdef __APPLE__ - if (error != noErr) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to register ICC color profiles for \"%s\" - %d", - p->name, (int)error); - - for (profile = profiles->profiles; - num_profiles > 0; - profile ++, num_profiles --) - CFRelease(profile->profileName); - - free(profiles); - - if (printer_name) - CFRelease(printer_name); - - if (device_name) - CFRelease(device_name); -#elif defined(HAVE_DBUS) - for (profile_path = cupsArrayFirst(profiles); - profile_path; - profile_path = cupsArrayNext(profiles)) - free (profile_path); - - cupsArrayDelete(profiles); - dbus_connection_flush(con); - - /* - * Don't unref the connection but instead keep it around for future - * calls (it is a local static variable). Once we disconnect from - * the bus all our devices and profiles will be gone. - */ -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ - } - - ppdClose(ppd); -} - - -/* - * 'cupsdUnregisterColorProfiles()' - Remove color profiles for the specified - * printer. - */ - -void -cupsdUnregisterColorProfiles( - cupsd_printer_t *p) /* I - Printer */ -{ -#ifdef __APPLE__ - /* - * Make sure ColorSync is available... - */ - - if (CMUnregisterColorDevice != NULL) - CMUnregisterColorDevice(cmPrinterDeviceClass, _ppdHashName(p->name)); -#elif defined(HAVE_DBUS) - dbus_delete_device_and_profiles (p); -#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */ -} - - -/* - * End of "$Id: printers.c 9313 2010-09-22 18:35:07Z mike $". - */ |