X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=scheduler%2Fprinters.c;h=e4841c0713cd2580fe1345d3385be05ecd352b8c;hb=53cac1d08bba395942df638d74526470c9fc7975;hp=044902e2a6193097edc680af174565b46f66a013;hpb=f14324a7920bee90b63469ce754e8040933f38e1;p=thirdparty%2Fcups.git diff --git a/scheduler/printers.c b/scheduler/printers.c index 044902e2a..e4841c071 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -1,59 +1,11 @@ /* - * "$Id: printers.c 7968 2008-09-19 23:03:01Z mike $" + * Printer routines for the CUPS scheduler. * - * Printer routines for the CUPS scheduler. + * Copyright © 2007-2019 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * 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. - * 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. - * 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... - * add_printer_defaults() - Add name-default attributes to the printer - * attributes. - * add_printer_filter() - Add a MIME filter for a printer. - * add_printer_formats() - Add document-format-supported values for a - * printer. - * compare_printers() - Compare two printers. - * delete_printer_filters() - Delete all MIME filters for a printer. - * dirty_printer() - Mark config and state files dirty for the - * specified printer. - * 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. + * Licensed under Apache License v2.0. See the file "LICENSE" for more + * information. */ /* @@ -76,6 +28,9 @@ #ifdef HAVE_SYS_VFS_H # include #endif /* HAVE_SYS_VFS_H */ +#ifdef __APPLE__ +# include +#endif /* __APPLE__ */ /* @@ -90,12 +45,7 @@ static int compare_printers(void *first, void *second, void *data); static void delete_printer_filters(cupsd_printer_t *p); static void dirty_printer(cupsd_printer_t *p); static void load_ppd(cupsd_printer_t *p); -static ipp_t *new_media_col(_pwg_size_t *size, const char *source, - 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 ipp_t *new_media_col(pwg_size_t *size); static void write_xml_string(cups_file_t *fp, const char *s); @@ -107,7 +57,8 @@ 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 */ + char uri[1024], /* Printer URI */ + uuid[64]; /* Printer UUID */ /* @@ -127,6 +78,8 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ return (NULL); } + _cupsRWInit(&p->lock); + cupsdSetString(&p->name, name); cupsdSetString(&p->info, name); cupsdSetString(&p->hostname, ServerName); @@ -134,13 +87,16 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, ServerName, RemotePort, "/printers/%s", name); cupsdSetString(&p->uri, uri); + cupsdSetString(&p->uuid, httpAssembleUUID(ServerName, RemotePort, name, 0, + uuid, sizeof(uuid))); 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); + p->config_time = time(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"); @@ -161,9 +117,6 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ "cupsdAddPrinter: Adding %s to Printers", p->name); cupsArrayAdd(Printers, p); - if (!ImplicitPrinters) - ImplicitPrinters = cupsArrayNew(compare_printers, NULL); - /* * Return the new printer... */ @@ -195,8 +148,32 @@ cupsdCreateCommonData(void) struct statfs spoolinfo; /* FS info for spool directory */ double spoolsize; /* FS size */ #endif /* HAVE_STATVFS */ - static const int nups[] = /* number-up-supported values */ + static const char * const page_delivery[] = + { /* page-delivery-supported values */ + "reverse-order", + "same-order" + }; + static const char * const print_scaling[] = + { /* print-scaling-supported values */ + "auto", + "auto-fit", + "fill", + "fit", + "none" + }; + static const int number_up[] = /* number-up-supported values */ { 1, 2, 4, 6, 9, 16 }; + static const char * const number_up_layout[] = + { /* number-up-layout-supported values */ + "btlr", + "btrl", + "lrbt", + "lrtb", + "rlbt", + "rltb", + "tblr", + "tbrl" + }; static const int orients[4] =/* orientation-requested-supported values */ { IPP_PORTRAIT, @@ -215,6 +192,10 @@ cupsdCreateCommonData(void) "third-shift", "weekend" }; + static const char * const features[] =/* ipp-features-supported values */ + { + "subscription-object" + }; static const char * const versions[] =/* ipp-versions-supported values */ { "1.0", @@ -224,54 +205,53 @@ cupsdCreateCommonData(void) }; 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_RESTART_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, - IPP_CANCEL_JOBS, - IPP_CANCEL_MY_JOBS, - IPP_CLOSE_JOB, - 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 + IPP_OP_PRINT_JOB, + IPP_OP_VALIDATE_JOB, + IPP_OP_CREATE_JOB, + IPP_OP_SEND_DOCUMENT, + IPP_OP_CANCEL_JOB, + IPP_OP_GET_JOB_ATTRIBUTES, + IPP_OP_GET_JOBS, + IPP_OP_GET_PRINTER_ATTRIBUTES, + IPP_OP_HOLD_JOB, + IPP_OP_RELEASE_JOB, + IPP_OP_PAUSE_PRINTER, + IPP_OP_RESUME_PRINTER, + IPP_OP_PURGE_JOBS, + IPP_OP_SET_PRINTER_ATTRIBUTES, + IPP_OP_SET_JOB_ATTRIBUTES, + IPP_OP_GET_PRINTER_SUPPORTED_VALUES, + IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS, + IPP_OP_CREATE_JOB_SUBSCRIPTIONS, + IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES, + IPP_OP_GET_SUBSCRIPTIONS, + IPP_OP_RENEW_SUBSCRIPTION, + IPP_OP_CANCEL_SUBSCRIPTION, + IPP_OP_GET_NOTIFICATIONS, + IPP_OP_ENABLE_PRINTER, + IPP_OP_DISABLE_PRINTER, + IPP_OP_HOLD_NEW_JOBS, + IPP_OP_RELEASE_HELD_NEW_JOBS, + IPP_OP_CANCEL_JOBS, + IPP_OP_CANCEL_MY_JOBS, + IPP_OP_CLOSE_JOB, + IPP_OP_CUPS_GET_DEFAULT, + IPP_OP_CUPS_GET_PRINTERS, + IPP_OP_CUPS_ADD_MODIFY_PRINTER, + IPP_OP_CUPS_DELETE_PRINTER, + IPP_OP_CUPS_GET_CLASSES, + IPP_OP_CUPS_ADD_MODIFY_CLASS, + IPP_OP_CUPS_DELETE_CLASS, + IPP_OP_CUPS_ACCEPT_JOBS, + IPP_OP_CUPS_REJECT_JOBS, + IPP_OP_CUPS_SET_DEFAULT, + IPP_OP_CUPS_GET_DEVICES, + IPP_OP_CUPS_GET_PPDS, + IPP_OP_CUPS_MOVE_JOB, + IPP_OP_CUPS_AUTHENTICATE_JOB, + IPP_OP_CUPS_GET_PPD, + IPP_OP_CUPS_GET_DOCUMENT, + IPP_OP_RESTART_JOB }; static const char * const charsets[] =/* charset-supported values */ { @@ -334,6 +314,7 @@ cupsdCreateCommonData(void) { /* job-creation-attributes-supported */ "copies", "finishings", + "finishings-col", "ipp-attribute-fidelity", "job-hold-until", "job-name", @@ -343,11 +324,14 @@ cupsdCreateCommonData(void) "media-col", "multiple-document-handling", "number-up", - "output-bin", - "output-mode", + "number-up-layout", "orientation-requested", + "output-bin", + "page-delivery", "page-ranges", + "print-color-mode", "print-quality", + "print-scaling", "printer-resolution", "sides" }; @@ -363,17 +347,32 @@ cupsdCreateCommonData(void) "multiple-document-handling", "number-up", "output-bin", - "output-mode", "orientation-requested", "page-ranges", + "print-color-mode", "print-quality", "printer-resolution", "sides" }; + static const char * const pdf_versions[] = + { /* pdf-versions-supported */ + "adobe-1.2", + "adobe-1.3", + "adobe-1.4", + "adobe-1.5", + "adobe-1.6", + "adobe-1.7", + "iso-19005-1_2005", + "iso-32000-1_2008", + "pwg-5102.3" + }; static const char * const printer_settable[] = { /* printer-settable-attributes-supported */ + "printer-geo-location", "printer-info", - "printer-location" + "printer-location", + "printer-organization", + "printer-organizational-unit" }; static const char * const which_jobs[] = { /* which-jobs-supported values */ @@ -453,6 +452,9 @@ cupsdCreateCommonData(void) ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "generated-natural-language-supported", NULL, DefaultLanguage); + /* ipp-features-supported */ + ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-features-supported", sizeof(features) / sizeof(features[0]), NULL, features); + /* ipp-versions-supported */ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]), @@ -462,6 +464,10 @@ cupsdCreateCommonData(void) ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "ippget-event-life", 15); + /* job-cancel-after-supported */ + ippAddRange(CommonData, IPP_TAG_PRINTER, "job-cancel-after-supported", + 0, INT_MAX); + /* job-creation-attributes-supported */ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-creation-attributes-supported", @@ -477,8 +483,8 @@ cupsdCreateCommonData(void) ippAddBoolean(CommonData, IPP_TAG_PRINTER, "job-ids-supported", 1); /* job-k-octets-supported */ - ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "job-k-octets-supported", k_supported); + ippAddRange(CommonData, IPP_TAG_PRINTER, "job-k-octets-supported", 0, + k_supported); /* job-priority-supported */ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -528,6 +534,18 @@ cupsdCreateCommonData(void) ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, "job-sheets-supported", NULL, "none"); + /* jpeg-k-octets-supported */ + ippAddRange(CommonData, IPP_TAG_PRINTER, "jpeg-k-octets-supported", 0, + k_supported); + + /* jpeg-x-dimension-supported */ + ippAddRange(CommonData, IPP_TAG_PRINTER, "jpeg-x-dimension-supported", 0, + 65535); + + /* jpeg-y-dimension-supported */ + ippAddRange(CommonData, IPP_TAG_PRINTER, "jpeg-y-dimension-supported", 1, + 65535); + /* media-col-supported */ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "media-col-supported", @@ -550,6 +568,9 @@ cupsdCreateCommonData(void) ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "multiple-operation-time-out", MultipleOperationTimeout); + /* multiple-operation-time-out-action */ + ippAddString(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-operation-time-out-action", NULL, "process-job"); + /* natural-language-configured (no IPP_TAG_COPY) */ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "natural-language-configured", NULL, DefaultLanguage); @@ -608,24 +629,45 @@ cupsdCreateCommonData(void) /* number-up-supported */ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "number-up-supported", sizeof(nups) / sizeof(nups[0]), nups); + "number-up-supported", sizeof(number_up) / sizeof(number_up[0]), number_up); + + /* number-up-layout-supported */ + ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "number-up-layout-supported", sizeof(number_up_layout) / sizeof(number_up_layout[0]), NULL, number_up_layout); /* operations-supported */ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "operations-supported", - sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, ops); + "operations-supported", sizeof(ops) / sizeof(ops[0]), ops); /* orientation-requested-supported */ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, "orientation-requested-supported", 4, orients); + /* page-delivery-supported */ + ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "page-delivery-supported", sizeof(page_delivery) / sizeof(page_delivery[0]), NULL, page_delivery); + /* page-ranges-supported */ ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1); + /* pdf-k-octets-supported */ + ippAddRange(CommonData, IPP_TAG_PRINTER, "pdf-k-octets-supported", 0, + k_supported); + + /* pdf-versions-supported */ + ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + "pdf-versions-supported", + sizeof(pdf_versions) / sizeof(pdf_versions[0]), NULL, + pdf_versions); + /* pdl-override-supported */ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "pdl-override-supported", NULL, "attempted"); + /* print-scaling-supported */ + ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-scaling-supported", sizeof(print_scaling) / sizeof(print_scaling[0]), NULL, print_scaling); + + /* printer-get-attributes-supported */ + ippAddString(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-get-attributes-supported", NULL, "document-format"); + /* printer-op-policy-supported */ attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, "printer-op-policy-supported", cupsArrayCount(Policies), @@ -683,9 +725,6 @@ cupsdDeletePrinter( { 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)", @@ -710,16 +749,6 @@ cupsdDeletePrinter( update ? "Job stopped due to printer being deleted." : "Job stopped."); - /* - * 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... */ @@ -728,80 +757,54 @@ cupsdDeletePrinter( "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... + * If p is the default printer, assign a different one... */ -#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); + if (p == DefaultPrinter) + DefaultPrinter = NULL; - snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name); - unlink(filename); + /* + * Remove this printer from any classes... + */ - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name); - unlink(filename); + changed = cupsdDeletePrinterFromClasses(p); - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name); - unlink(filename); + /* + * Deregister from any browse protocols... + */ - snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name); - unlink(filename); -#endif /* __sgi */ + cupsdDeregisterPrinter(p, 1); /* - * If p is the default printer, assign a different one... + * Remove support files if this is a temporary queue and deregister color + * profiles... */ - if (p == DefaultPrinter) + if (p->temporary) { - DefaultPrinter = NULL; - - if (UseNetworkDefault) - { - /* - * Find the first network default printer and use it... - */ - - cupsd_printer_t *dp; /* New default printer */ + char filename[1024]; /* Script/PPD filename */ + /* + * Remove any old PPD or script files... + */ - 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; - } - } - } + snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, p->name); + unlink(filename); + snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd.O", ServerRoot, p->name); + unlink(filename); - /* - * Remove this printer from any classes... - */ + snprintf(filename, sizeof(filename), "%s/%s.png", CacheDir, p->name); + unlink(filename); - if (!(p->type & CUPS_PRINTER_IMPLICIT)) - { - changed = cupsdDeletePrinterFromClasses(p); + snprintf(filename, sizeof(filename), "%s/%s.data", CacheDir, p->name); + unlink(filename); /* - * Deregister from any browse protocols... + * Unregister color profiles... */ - cupsdDeregisterPrinter(p, 1); + cupsdUnregisterColor(p); } /* @@ -829,6 +832,7 @@ cupsdDeletePrinter( cupsdClearString(&p->hostname); cupsdClearString(&p->name); cupsdClearString(&p->location); + cupsdClearString(&p->geo_location); cupsdClearString(&p->make_model); cupsdClearString(&p->info); cupsdClearString(&p->job_sheets[0]); @@ -838,19 +842,18 @@ cupsdDeletePrinter( cupsdClearString(&p->port_monitor); cupsdClearString(&p->op_policy); cupsdClearString(&p->error_policy); + cupsdClearString(&p->strings); cupsdClearString(&p->alert); cupsdClearString(&p->alert_description); -#ifdef HAVE_DNSSD +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) cupsdClearString(&p->pdl); -#endif /* HAVE_DNSSD */ + cupsdClearString(&p->reg_name); +#endif /* HAVE_DNSSD || HAVE_AVAHI */ cupsArrayDelete(p->filetypes); - if (p->browse_attrs) - free(p->browse_attrs); - cupsFreeOptions(p->num_options, p->options); free(p); @@ -865,6 +868,32 @@ cupsdDeletePrinter( } +/* + * 'cupsdDeleteTemporaryPrinters()' - Delete unneeded temporary printers. + */ + +void +cupsdDeleteTemporaryPrinters(int force) /* I - Force deletion instead of auto? */ +{ + cupsd_printer_t *p; /* Current printer */ + time_t unused_time; /* Last time for printer state change */ + + + /* + * Allow temporary printers to stick around for 60 seconds after the last job + * completes. + */ + + unused_time = time(NULL) - 60; + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) + { + if (p->temporary && (force || p->state_time < unused_time)) + cupsdDeletePrinter(p, 0); + } +} + + /* * 'cupsdFindDest()' - Find a destination in the list. */ @@ -918,13 +947,8 @@ cupsdLoadAllPrinters(void) */ 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)); + if ((fp = cupsdOpenConfFile(line)) == NULL) return; - } /* * Read printer configurations until we hit EOF... @@ -939,8 +963,14 @@ cupsdLoadAllPrinters(void) * Decode the directive... */ - if (!strcasecmp(line, " 0) + NextPrinterId = i; + else + cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); + } + else if (!_cups_strcasecmp(line, " or @@ -962,14 +992,14 @@ cupsdLoadAllPrinters(void) * Set the default printer as needed... */ - if (!strcasecmp(line, "")) + else if (!_cups_strcasecmp(line, "") || !_cups_strcasecmp(line, "")) { if (p != NULL) { @@ -977,17 +1007,21 @@ cupsdLoadAllPrinters(void) * Close out the current printer... */ + if (!p->printer_id) + { + p->printer_id = NextPrinterId ++; + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); + } + cupsdSetPrinterAttrs(p); - if (strncmp(p->device_uri, "file:", 5) && - p->state != IPP_PRINTER_STOPPED) + 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); + 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 */ @@ -999,8 +1033,7 @@ cupsdLoadAllPrinters(void) */ p->state = IPP_PRINTER_STOPPED; - snprintf(p->state_message, sizeof(p->state_message), - "Backend %s does not exist!", line); + snprintf(p->state_message, sizeof(p->state_message), "Backend %s does not exist!", line); } } @@ -1015,29 +1048,59 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "AuthInfoRequired")) + else if (!_cups_strcasecmp(line, "PrinterId")) + { + if (value && (i = atoi(value)) > 0) + p->printer_id = i; + else + cupsdLogMessage(CUPSD_LOG_ERROR, "Bad PrinterId on line %d of printers.conf.", linenum); + } + else if (!_cups_strcasecmp(line, "UUID")) + { + if (value && !strncmp(value, "urn:uuid:", 9)) + cupsdSetString(&(p->uuid), value); + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad UUID on line %d of printers.conf.", linenum); + } + else if (!_cups_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")) + else if (!_cups_strcasecmp(line, "Info")) { if (value) cupsdSetString(&p->info, value); } - else if (!strcasecmp(line, "MakeModel")) + else if (!_cups_strcasecmp(line, "MakeModel")) { if (value) cupsdSetString(&p->make_model, value); } - else if (!strcasecmp(line, "Location")) + else if (!_cups_strcasecmp(line, "Location")) { if (value) cupsdSetString(&p->location, value); } - else if (!strcasecmp(line, "DeviceURI")) + else if (!_cups_strcasecmp(line, "GeoLocation")) + { + if (value) + cupsdSetString(&p->geo_location, value); + } + else if (!_cups_strcasecmp(line, "Organization")) + { + if (value) + cupsdSetString(&p->organization, value); + } + else if (!_cups_strcasecmp(line, "OrganizationalUnit")) + { + if (value) + cupsdSetString(&p->organizational_unit, value); + } + else if (!_cups_strcasecmp(line, "DeviceURI")) { if (value) cupsdSetDeviceURI(p, value); @@ -1045,7 +1108,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "Option") && value) + else if (!_cups_strcasecmp(line, "Option") && value) { /* * Option name value @@ -1064,7 +1127,7 @@ cupsdLoadAllPrinters(void) &(p->options)); } } - else if (!strcasecmp(line, "PortMonitor")) + else if (!_cups_strcasecmp(line, "PortMonitor")) { if (value && strcmp(value, "none")) cupsdSetString(&p->port_monitor, value); @@ -1074,7 +1137,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "Reason")) + else if (!_cups_strcasecmp(line, "Reason")) { if (value && strcmp(value, "connecting-to-device") && @@ -1096,15 +1159,15 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "State")) + else if (!_cups_strcasecmp(line, "State")) { /* * Set the initial queue state... */ - if (value && !strcasecmp(value, "idle")) + if (value && !_cups_strcasecmp(value, "idle")) p->state = IPP_PRINTER_IDLE; - else if (value && !strcasecmp(value, "stopped")) + else if (value && !_cups_strcasecmp(value, "stopped")) { p->state = IPP_PRINTER_STOPPED; @@ -1123,7 +1186,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "StateMessage")) + else if (!_cups_strcasecmp(line, "StateMessage")) { /* * Set the initial queue state message... @@ -1132,7 +1195,7 @@ cupsdLoadAllPrinters(void) if (value) strlcpy(p->state_message, value, sizeof(p->state_message)); } - else if (!strcasecmp(line, "StateTime")) + else if (!_cups_strcasecmp(line, "StateTime")) { /* * Set the state time... @@ -1141,55 +1204,64 @@ cupsdLoadAllPrinters(void) if (value) p->state_time = atoi(value); } - else if (!strcasecmp(line, "Accepting")) + else if (!_cups_strcasecmp(line, "ConfigTime")) + { + /* + * Set the config time... + */ + + if (value) + p->config_time = atoi(value); + } + else if (!_cups_strcasecmp(line, "Accepting")) { /* * Set the initial accepting state... */ if (value && - (!strcasecmp(value, "yes") || - !strcasecmp(value, "on") || - !strcasecmp(value, "true"))) + (!_cups_strcasecmp(value, "yes") || + !_cups_strcasecmp(value, "on") || + !_cups_strcasecmp(value, "true"))) p->accepting = 1; else if (value && - (!strcasecmp(value, "no") || - !strcasecmp(value, "off") || - !strcasecmp(value, "false"))) + (!_cups_strcasecmp(value, "no") || + !_cups_strcasecmp(value, "off") || + !_cups_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")) + else if (!_cups_strcasecmp(line, "Type")) { if (value) - p->type = atoi(value); + p->type = (cups_ptype_t)atoi(value); else cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "Shared")) + else if (!_cups_strcasecmp(line, "Shared")) { /* * Set the initial shared state... */ if (value && - (!strcasecmp(value, "yes") || - !strcasecmp(value, "on") || - !strcasecmp(value, "true"))) + (!_cups_strcasecmp(value, "yes") || + !_cups_strcasecmp(value, "on") || + !_cups_strcasecmp(value, "true"))) p->shared = 1; else if (value && - (!strcasecmp(value, "no") || - !strcasecmp(value, "off") || - !strcasecmp(value, "false"))) + (!_cups_strcasecmp(value, "no") || + !_cups_strcasecmp(value, "off") || + !_cups_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")) + else if (!_cups_strcasecmp(line, "JobSheets")) { /* * Set the initial job sheets... @@ -1221,7 +1293,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "AllowUser")) + else if (!_cups_strcasecmp(line, "AllowUser")) { if (value) { @@ -1232,7 +1304,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "DenyUser")) + else if (!_cups_strcasecmp(line, "DenyUser")) { if (value) { @@ -1243,7 +1315,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "QuotaPeriod")) + else if (!_cups_strcasecmp(line, "QuotaPeriod")) { if (value) p->quota_period = atoi(value); @@ -1251,7 +1323,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "PageLimit")) + else if (!_cups_strcasecmp(line, "PageLimit")) { if (value) p->page_limit = atoi(value); @@ -1259,7 +1331,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "KLimit")) + else if (!_cups_strcasecmp(line, "KLimit")) { if (value) p->k_limit = atoi(value); @@ -1267,7 +1339,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "OpPolicy")) + else if (!_cups_strcasecmp(line, "OpPolicy")) { if (value) { @@ -1288,15 +1360,22 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "ErrorPolicy")) + else if (!_cups_strcasecmp(line, "ErrorPolicy")) { if (value) - cupsdSetString(&p->error_policy, value); + { + if (strcmp(value, "retry-current-job") && + strcmp(value, "abort-job") && + strcmp(value, "retry-job") && + strcmp(value, "stop-printer")) + cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid ErrorPolicy \"%s\" on line %d or printers.conf.", ErrorPolicy, linenum); + else + cupsdSetString(&p->error_policy, value); + } else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "Attribute") && value) + else if (!_cups_strcasecmp(line, "Attribute") && value) { for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++); @@ -1316,15 +1395,18 @@ cupsdLoadAllPrinters(void) cupsdSetPrinterAttr(p, value, valueptr); } } - else + else if (_cups_strcasecmp(line, "Filter") && + _cups_strcasecmp(line, "Prefilter") && + _cups_strcasecmp(line, "Product")) { /* - * Something else we don't understand... + * Something else we don't understand (and that wasn't used in a prior + * release of CUPS... */ cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown configuration directive %s on line %d of printers.conf.", - line, linenum); + "Unknown configuration directive %s on line %d of " + "printers.conf.", line, linenum); } } @@ -1349,14 +1431,6 @@ cupsdRenamePrinter( "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... */ @@ -1364,8 +1438,11 @@ cupsdRenamePrinter( mimeDeleteType(MimeDatabase, p->filetype); p->filetype = mimeAddType(MimeDatabase, "printer", name); - mimeDeleteType(MimeDatabase, p->prefiltertype); - p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", name); + if (p->prefiltertype) + { + mimeDeleteType(MimeDatabase, p->prefiltertype); + p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", name); + } /* * Rename the printer... @@ -1386,14 +1463,6 @@ cupsdRenamePrinter( 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); - } } @@ -1407,8 +1476,8 @@ cupsdSaveAllPrinters(void) { int i; /* Looping var */ cups_file_t *fp; /* printers.conf file */ - char temp[1024], /* Temporary string */ - backup[1024], /* printers.conf.O file */ + char filename[1024], /* printers.conf filename */ + temp[1024], /* Temporary string */ value[2048], /* Value string */ *ptr, /* Pointer into value */ *name; /* Current user/group name */ @@ -1423,35 +1492,12 @@ cupsdSaveAllPrinters(void) * 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)); + snprintf(filename, sizeof(filename), "%s/printers.conf", ServerRoot); - if (rename(backup, temp)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to restore printers.conf - %s", strerror(errno)); + if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm & 0600)) == NULL) return; - } - else - cupsdLogMessage(CUPSD_LOG_INFO, "Saving printers.conf..."); - - /* - * Restrict access to the file... - */ - fchown(cupsFileNumber(fp), getuid(), Group); - fchmod(cupsFileNumber(fp), ConfigFilePerm & 0600); + cupsdLogMessage(CUPSD_LOG_INFO, "Saving printers.conf..."); /* * Write a small header to the file... @@ -1465,6 +1511,8 @@ cupsdSaveAllPrinters(void) cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); cupsFilePuts(fp, "# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING\n"); + cupsFilePrintf(fp, "NextPrinterId %d\n", NextPrinterId); + /* * Write each local printer known to the system... */ @@ -1474,12 +1522,10 @@ cupsdSaveAllPrinters(void) printer = (cupsd_printer_t *)cupsArrayNext(Printers)) { /* - * Skip remote destinations and printer classes... + * Skip printer classes and temporary queues... */ - if ((printer->type & CUPS_PRINTER_DISCOVERED) || - (printer->type & CUPS_PRINTER_CLASS) || - (printer->type & CUPS_PRINTER_IMPLICIT)) + if ((printer->type & CUPS_PRINTER_CLASS) || printer->temporary) continue; /* @@ -1491,6 +1537,11 @@ cupsdSaveAllPrinters(void) else cupsFilePrintf(fp, "\n", printer->name); + if (printer->printer_id) + cupsFilePrintf(fp, "PrinterId %d\n", printer->printer_id); + + cupsFilePrintf(fp, "UUID %s\n", printer->uuid); + if (printer->num_auth_info_required > 0) { switch (printer->num_auth_info_required) @@ -1523,9 +1574,18 @@ cupsdSaveAllPrinters(void) if (printer->location) cupsFilePutConf(fp, "Location", printer->location); + if (printer->geo_location) + cupsFilePutConf(fp, "GeoLocation", printer->geo_location); + if (printer->make_model) cupsFilePutConf(fp, "MakeModel", printer->make_model); + if (printer->organization) + cupsFilePutConf(fp, "Organization", printer->organization); + + if (printer->organizational_unit) + cupsFilePutConf(fp, "OrganizationalUnit", printer->organizational_unit); + cupsFilePutConf(fp, "DeviceURI", printer->device_uri); if (printer->port_monitor) @@ -1535,13 +1595,14 @@ cupsdSaveAllPrinters(void) { cupsFilePuts(fp, "State Stopped\n"); - if (printer->state_message) + if (printer->state_message[0]) cupsFilePutConf(fp, "StateMessage", printer->state_message); } else cupsFilePuts(fp, "State Idle\n"); cupsFilePrintf(fp, "StateTime %d\n", (int)printer->state_time); + cupsFilePrintf(fp, "ConfigTime %d\n", (int)printer->config_time); for (i = 0; i < printer->num_reasons; i ++) if (strcmp(printer->reasons[i], "connecting-to-device") && @@ -1599,8 +1660,7 @@ cupsdSaveAllPrinters(void) if (i) *ptr++ = ','; - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); + strlcpy(ptr, marker->values[i].string.text, (size_t)(value + sizeof(value) - ptr)); ptr += strlen(ptr); } @@ -1659,8 +1719,7 @@ cupsdSaveAllPrinters(void) if (i) *ptr++ = ','; - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); + strlcpy(ptr, marker->values[i].string.text, (size_t)(value + sizeof(value) - ptr)); ptr += strlen(ptr); } @@ -1680,8 +1739,7 @@ cupsdSaveAllPrinters(void) if (i) *ptr++ = ','; - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); + strlcpy(ptr, marker->values[i].string.text, (size_t)(value + sizeof(value) - ptr)); ptr += strlen(ptr); } @@ -1693,18 +1751,13 @@ cupsdSaveAllPrinters(void) cupsFilePrintf(fp, "Attribute marker-change-time %ld\n", (long)printer->marker_time); - cupsFilePuts(fp, "\n"); - -#ifdef __sgi - /* - * Make IRIX desktop & printer status happy - */ - - write_irix_state(printer); -#endif /* __sgi */ + if (printer == DefaultPrinter) + cupsFilePuts(fp, "\n"); + else + cupsFilePuts(fp, "\n"); } - cupsFileClose(fp); + cupsdCloseCreatedConfFile(fp, filename); } @@ -1758,6 +1811,16 @@ cupsdSetAuthInfoRequired( p->auth_info_required[p->num_auth_info_required] = "negotiate"; p->num_auth_info_required ++; + + /* + * Don't allow sharing of queues that require Kerberos authentication. + */ + + if (p->shared) + { + cupsdDeregisterPrinter(p, 1); + p->shared = 0; + } } else if ((end - values) == 6 && !strncmp(values, "domain", 6)) { @@ -1794,7 +1857,7 @@ cupsdSetAuthInfoRequired( strcmp(p->auth_info_required[0], "none")) p->type |= CUPS_PRINTER_AUTHENTICATED; else - p->type &= ~CUPS_PRINTER_AUTHENTICATED; + p->type &= (cups_ptype_t)~CUPS_PRINTER_AUTHENTICATED; return (1); } @@ -1806,16 +1869,6 @@ cupsdSetAuthInfoRequired( 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")) @@ -1836,6 +1889,16 @@ cupsdSetAuthInfoRequired( p->auth_info_required[p->num_auth_info_required] = "negotiate"; p->num_auth_info_required ++; + /* + * Don't allow sharing of queues that require Kerberos authentication. + */ + + if (p->shared) + { + cupsdDeregisterPrinter(p, 1); + p->shared = 0; + } + return (1); } else if (!strcmp(attr->values[i].string.text, "domain")) @@ -1937,12 +2000,15 @@ void cupsdSetPrinterAttr( cupsd_printer_t *p, /* I - Printer */ const char *name, /* I - Attribute name */ - char *value) /* I - Attribute value string */ + const char *value) /* I - Attribute value string */ { ipp_attribute_t *attr; /* Attribute */ int i, /* Looping var */ count; /* Number of values */ - char *ptr; /* Pointer into value */ + char *temp, /* Temporary copy of value string */ + *ptr, /* Pointer into value */ + *start, /* Start of value */ + quote; /* Quote character */ ipp_tag_t value_tag; /* Value tag for this attribute */ @@ -1956,13 +2022,36 @@ cupsdSetPrinterAttr( return; } + /* + * Copy the value string so we can do what we want with it... + */ + + if ((temp = strdup(value)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to duplicate value for \"%s\" attribute.", name); + return; + } + /* * Count the number of values... */ - for (count = 1, ptr = value; - (ptr = strchr(ptr, ',')) != NULL; - ptr ++, count ++); + for (count = 1, quote = '\0', ptr = temp; + *ptr; + ptr ++) + { + if (*ptr == quote) + quote = '\0'; + else if (quote) + continue; + else if (*ptr == '\\' && ptr[1]) + ptr ++; + else if (*ptr == '\'' || *ptr == '\"') + quote = *ptr; + else if (*ptr == ',') + count ++; + } /* * Then add or update the attribute as needed... @@ -1990,21 +2079,22 @@ cupsdSetPrinterAttr( if (!attr) { + free(temp); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for printer attribute " "(%d values)", count); return; } - for (i = 0; i < count; i ++) + for (i = 0, start = temp; i < count; i ++) { - if ((ptr = strchr(value, ',')) != NULL) + if ((ptr = strchr(start, ',')) != NULL) *ptr++ = '\0'; - attr->values[i].integer = strtol(value, NULL, 10); + attr->values[i].integer = strtol(start, NULL, 10); if (ptr) - value = ptr; + start = ptr; } } else @@ -2040,21 +2130,113 @@ cupsdSetPrinterAttr( if (!attr) { + free(temp); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for printer attribute " "(%d values)", count); return; } + for (i = 0, quote = '\0', ptr = temp; i < count; i ++) + { + for (start = ptr; *ptr; ptr ++) + { + if (*ptr == quote) + *ptr = quote = '\0'; + else if (quote) + continue; + else if (*ptr == '\\' && ptr[1]) + _cups_strcpy(ptr, ptr + 1); + else if (*ptr == '\'' || *ptr == '\"') + { + quote = *ptr; + + if (ptr == start) + start ++; + else + _cups_strcpy(ptr, ptr + 1); + } + else if (*ptr == ',') + { + *ptr++ = '\0'; + break; + } + } + + attr->values[i].string.text = _cupsStrAlloc(start); + } + } + + free(temp); + + /* + * Update the printer-supply and printer-supply-description, as needed... + */ + + if (!strcmp(name, "marker-names")) + { + ipp_attribute_t *supply_desc = ippFindAttribute(p->attrs, "printer-supply-description", IPP_TAG_TEXT); + /* printer-supply-description attribute */ + + if (supply_desc != NULL) + ippDeleteAttribute(p->attrs, supply_desc); + + supply_desc = ippCopyAttribute(p->attrs, attr, 0); + ippSetName(p->attrs, &supply_desc, "printer-supply-description"); + ippSetValueTag(p->attrs, &supply_desc, IPP_TAG_TEXT); + } + else if (!strcmp(name, "marker-colors") || !strcmp(name, "marker-levels") || !strcmp(name, "marker-types")) + { + char buffer[256], /* printer-supply values */ + pstype[64], /* printer-supply type value */ + *psptr; /* Pointer into type */ + const char *color, /* marker-colors value */ + *type; /* marker-types value */ + int level; /* marker-levels value */ + ipp_attribute_t *colors = ippFindAttribute(p->attrs, "marker-colors", IPP_TAG_NAME); + /* marker-colors attribute */ + ipp_attribute_t *levels = ippFindAttribute(p->attrs, "marker-levels", IPP_TAG_INTEGER); + /* marker-levels attribute */ + ipp_attribute_t *types = ippFindAttribute(p->attrs, "marker-types", IPP_TAG_KEYWORD); + /* marker-types attribute */ + ipp_attribute_t *supply = ippFindAttribute(p->attrs, "printer-supply", IPP_TAG_STRING); + /* printer-supply attribute */ + + if (supply != NULL) + { + ippDeleteAttribute(p->attrs, supply); + supply = NULL; + } + + if (!colors || !levels || !types) + return; + + count = ippGetCount(colors); + if (count != ippGetCount(levels) || count != ippGetCount(types)) + return; + for (i = 0; i < count; i ++) { - if ((ptr = strchr(value, ',')) != NULL) - *ptr++ = '\0'; + color = ippGetString(colors, i, NULL); + level = ippGetInteger(levels, i); + type = ippGetString(types, i, NULL); + + for (psptr = pstype; *type && psptr < (pstype + sizeof(pstype) - 1); type ++) + if (*type == '-') + { + type ++; + *psptr++ = (char)toupper(*type & 255); + } + else + *psptr++ = *type; + *psptr = '\0'; - attr->values[i].string.text = _cupsStrAlloc(value); + snprintf(buffer, sizeof(buffer), "index=%d;class=%s;type=%s;unit=percent;maxcapacity=100;level=%d;colorantname=%s;", i + 1, strncmp(pstype, "waste", 5) ? "supplyThatIsConsumed" : "receptacleThatIsFilled", pstype, level, color); - if (ptr) - value = ptr; + if (!i) + supply = ippAddOctetString(p->attrs, IPP_TAG_PRINTER, "printer-supply", buffer, (int)strlen(buffer)); + else + ippSetOctetString(p->attrs, &supply, i, buffer, (int)strlen(buffer)); } } } @@ -2067,31 +2249,15 @@ cupsdSetPrinterAttr( void cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { - int i, /* Looping var */ - length; /* Length of browse attributes */ + int i; /* Looping var */ 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 *name, /* Current user/group name */ *filter; /* Current filter */ - static const char * const air_none[] = - { /* No authentication */ - "none" - }; - static const char * const air_userpass[] = - { /* Basic/Digest authentication */ - "username", - "password" - }; - - DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name, - p->type)); /* * Make sure that we have the common attributes defined... @@ -2100,6 +2266,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ if (!CommonData) cupsdCreateCommonData(); + _cupsRWLockWrite(&p->lock); + /* * Clear out old filters, if any... */ @@ -2111,20 +2279,6 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ */ 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); @@ -2141,27 +2295,22 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT) - auth_type = DefaultAuthType; + auth_type = cupsdDefaultAuthType(); - if (auth_type == CUPSD_AUTH_BASIC || auth_type == CUPSD_AUTH_BASICDIGEST) + if (auth_type == CUPSD_AUTH_BASIC) 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; - } + if (auth_type != CUPSD_AUTH_NONE) + p->type |= CUPS_PRINTER_AUTHENTICATED; + else + p->type &= (cups_ptype_t)~CUPS_PRINTER_AUTHENTICATED; } - else if (!(p->type & CUPS_PRINTER_DISCOVERED)) - p->type &= ~CUPS_PRINTER_AUTHENTICATED; + else + p->type &= (cups_ptype_t)~CUPS_PRINTER_AUTHENTICATED; /* * Create the required IPP attributes for a printer... @@ -2174,12 +2323,21 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ "uri-authentication-supported", NULL, auth_supported); ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "uri-security-supported", NULL, "none"); + if (p->printer_id) + ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-id", p->printer_id); 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 : ""); + if (p->geo_location) + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-geo-location", NULL, p->geo_location); + else + ippAddOutOfBand(p->attrs, IPP_TAG_PRINTER, IPP_TAG_UNKNOWN, "printer-geo-location"); ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL, p->info ? p->info : ""); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organization", NULL, p->organization ? p->organization : ""); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organizational-unit", NULL, p->organizational_unit ? p->organizational_unit : ""); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uuid", NULL, p->uuid); if (cupsArrayCount(p->users) > 0) { @@ -2195,7 +2353,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ for (i = 0, name = (char *)cupsArrayFirst(p->users); name; i ++, name = (char *)cupsArrayNext(p->users)) - attr->values[i].string.text = _cupsStrRetain(name); + attr->values[i].string.text = _cupsStrAlloc(name); } ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -2204,10 +2362,12 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ "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 (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none")) + ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "auth-info-required", p->num_auth_info_required, NULL, + p->auth_info_required); - if (cupsArrayCount(Banners) > 0 && !(p->type & CUPS_PRINTER_DISCOVERED)) + if (cupsArrayCount(Banners) > 0) { /* * Setup the job-sheets-default attribute... @@ -2228,163 +2388,99 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ p->raw = 0; p->remote = 0; - if (p->type & CUPS_PRINTER_DISCOVERED) + /* + * Assign additional attributes depending on whether this is a printer + * or class... + */ + + if (p->type & CUPS_PRINTER_CLASS) { + p->raw = 1; + p->type &= (cups_ptype_t)~CUPS_PRINTER_OPTIONS; + /* - * Tell the client this is a remote printer of some type... + * Add class-specific attributes... */ - if (strchr(p->uri, '?')) + 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) { /* - * Strip trailing "?options" from URI... + * Add a list of member names; URIs are added in copy_printer_attrs... */ - char *ptr; /* Pointer into URI */ + attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, + "member-names", p->num_printers, NULL, NULL); + p->type |= CUPS_PRINTER_OPTIONS; - strlcpy(resource, p->uri, sizeof(resource)); - if ((ptr = strchr(resource, '?')) != NULL) - *ptr = '\0'; + for (i = 0; i < p->num_printers; i ++) + { + if (attr != NULL) + attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->name); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, - "printer-uri-supported", NULL, resource); + p->type &= (cups_ptype_t)~CUPS_PRINTER_OPTIONS | p->printers[i]->type; + } } - else - 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... + * Add printer-specific attributes... */ - 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, + p->sanitized_device_uri); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, - "file:///dev/null"); + /* + * Assign additional attributes from the PPD file (if any)... + */ - if (p->num_printers > 0) - { - /* - * Add a list of member names; URIs are added in copy_printer_attrs... - */ + load_ppd(p); - attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "member-names", p->num_printers, NULL, NULL); - p->type |= CUPS_PRINTER_OPTIONS; + /* + * Add filters for printer... + */ - for (i = 0; i < p->num_printers; i ++) - { - if (attr != NULL) - attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name); + cupsdSetPrinterReasons(p, "-cups-missing-filter-warning," + "cups-insecure-filter-warning"); - p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type; - } - } + if (p->pc && p->pc->filters) + { + for (filter = (char *)cupsArrayFirst(p->pc->filters); + filter; + filter = (char *)cupsArrayNext(p->pc->filters)) + add_printer_filter(p, p->filetype, filter); } - else + else if (!(p->type & CUPS_PRINTER_REMOTE)) { /* - * Add printer-specific attributes... + * Add a filter from application/vnd.cups-raw to printer/name to + * handle "raw" printing by users. */ - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, - p->sanitized_device_uri); + add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -"); /* - * Assign additional attributes from the PPD file (if any)... + * Add a PostScript filter, since this is still possibly PS printer. */ - load_ppd(p); - - /* - * Add filters for printer... - */ - - cupsdSetPrinterReasons(p, "-cups-missing-filter-warning," - "cups-insecure-filter-warning"); - - if (p->pc && p->pc->filters) - { - for (filter = (char *)cupsArrayFirst(p->pc->filters); - filter; - filter = (char *)cupsArrayNext(p->pc->filters)) - add_printer_filter(p, p->filetype, filter); - } - else if (!(p->type & CUPS_PRINTER_REMOTE)) - { - char interface[1024]; /* Interface script */ - - - snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot, - p->name); - if (!access(interface, X_OK)) - { - /* - * Yes, we have a System V style interface script; use it! - */ - - snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s", - ServerRoot, p->name); - add_printer_filter(p, p->filetype, interface); - } - else - { - /* - * Add a filter from application/vnd.cups-raw to printer/name to - * handle "raw" printing by users. - */ - - add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -"); - - /* - * Add a PostScript filter, since this is still possibly PS printer. - */ - - add_printer_filter(p, p->filetype, - "application/vnd.cups-postscript 0 -"); - } - } + add_printer_filter(p, p->filetype, + "application/vnd.cups-postscript 0 -"); + } - if (p->pc && p->pc->prefilters) - { - p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name); + if (p->pc && p->pc->prefilters) + { + if (!p->prefiltertype) + p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name); - for (filter = (char *)cupsArrayFirst(p->pc->prefilters); - filter; - filter = (char *)cupsArrayNext(p->pc->prefilters)) - add_printer_filter(p, p->prefiltertype, filter); - } + for (filter = (char *)cupsArrayFirst(p->pc->prefilters); + filter; + filter = (char *)cupsArrayNext(p->pc->prefilters)) + add_printer_filter(p, p->prefiltertype, filter); } } @@ -2406,7 +2502,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { for (i = 0; i < oldattr->num_values; i ++) attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); + _cupsStrAlloc(oldattr->values[i].string.text); } } @@ -2460,7 +2556,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { for (i = 0; i < oldattr->num_values; i ++) attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); + _cupsStrAlloc(oldattr->values[i].string.text); } } @@ -2473,7 +2569,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { for (i = 0; i < oldattr->num_values; i ++) attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); + _cupsStrAlloc(oldattr->values[i].string.text); } } @@ -2484,98 +2580,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ * Force sharing off for remote queues... */ - if (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) + if (p->type & CUPS_PRINTER_REMOTE) 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... @@ -2583,23 +2589,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ 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 */ + _cupsRWUnlock(&p->lock); /* * Let the browse protocols reflect the change @@ -2696,14 +2692,17 @@ cupsdSetPrinterReasons( _cupsStrFree(p->reasons[i]); if (i < p->num_reasons) - memmove(p->reasons + i, p->reasons + i + 1, - (p->num_reasons - i) * sizeof(char *)); + memmove(p->reasons + i, p->reasons + i + 1, (size_t)(p->num_reasons - i) * sizeof(char *)); if (!strcmp(reason, "paused") && p->state == IPP_PRINTER_STOPPED) cupsdSetPrinterState(p, IPP_PRINTER_IDLE, 1); + if (!strcmp(reason, "cups-waiting-for-job-completed") && p->job) + p->job->completed = 0; + if (strcmp(reason, "connecting-to-device")) dirty_printer(p); + break; } } @@ -2734,6 +2733,9 @@ cupsdSetPrinterReasons( if (!strcmp(reason, "paused") && p->state != IPP_PRINTER_STOPPED) cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, 1); + if (!strcmp(reason, "cups-waiting-for-job-completed") && p->job) + p->job->completed = 1; + if (strcmp(reason, "connecting-to-device")) dirty_printer(p); } @@ -2754,6 +2756,7 @@ cupsdSetPrinterState( ipp_pstate_t s, /* I - New state */ int update) /* I - Update printers.conf? */ { + cupsd_job_t *job; /* Current job */ ipp_pstate_t old_state; /* Old printer state */ static const char * const printer_states[] = { /* State strings */ @@ -2763,13 +2766,6 @@ cupsdSetPrinterState( }; - /* - * Can't set status of remote printers... - */ - - if (p->type & CUPS_PRINTER_DISCOVERED) - return; - /* * Set the new state... */ @@ -2789,13 +2785,7 @@ cupsdSetPrinterState( * 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 */ + p->state_time = time(NULL); } /* @@ -2807,6 +2797,17 @@ cupsdSetPrinterState( else cupsdSetPrinterReasons(p, "-paused"); + if (old_state != s) + { + for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); + job; + job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) + if (job->reasons && job->state_value == IPP_JOB_PENDING && + !_cups_strcasecmp(job->dest, p->name)) + ippSetString(job->attrs, &job->reasons, 0, + s == IPP_PRINTER_STOPPED ? "printer-stopped" : "none"); + } + /* * Clear the message for the queue when going to processing... */ @@ -2989,22 +2990,6 @@ cupsdUpdatePrinters(void) 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... */ @@ -3013,11 +2998,10 @@ cupsdUpdatePrinters(void) p->op_policy_ptr = DefaultPolicyPtr; /* - * Update printer attributes as needed... + * Update printer attributes... */ - if (!(p->type & CUPS_PRINTER_DISCOVERED)) - cupsdSetPrinterAttrs(p); + cupsdSetPrinterAttrs(p); } } @@ -3046,9 +3030,6 @@ cupsdValidateDest( int port; /* Port portion of URI */ - DEBUG_printf(("cupsdValidateDest(uri=\"%s\", dtype=%p, printer=%p)\n", uri, - dtype, printer)); - /* * Initialize return values... */ @@ -3110,8 +3091,7 @@ cupsdValidateDest( *printer = p; if (dtype) - *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED); + *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); return (p->name); } @@ -3120,12 +3100,12 @@ cupsdValidateDest( * Change localhost to the server name... */ - if (!strcasecmp(hostname, "localhost")) + if (!_cups_strcasecmp(hostname, "localhost")) strlcpy(hostname, ServerName, sizeof(hostname)); strlcpy(localname, hostname, sizeof(localname)); - if (!strcasecmp(hostname, ServerName)) + if (!_cups_strcasecmp(hostname, ServerName)) { /* * Localize the hostname... @@ -3142,7 +3122,7 @@ cupsdValidateDest( while (lptr != NULL) { - if (!strcasecmp(lptr, sptr)) + if (!_cups_strcasecmp(lptr, sptr)) { *lptr = '\0'; break; @@ -3153,8 +3133,6 @@ cupsdValidateDest( } } - DEBUG_printf(("localized hostname is \"%s\"...\n", localname)); - /* * Find a matching printer or class... */ @@ -3162,15 +3140,14 @@ cupsdValidateDest( for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!strcasecmp(p->hostname, localname) && - !strcasecmp(p->name, rptr)) + if (!_cups_strcasecmp(p->hostname, localname) && + !_cups_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); + *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); return (p->name); } @@ -3192,16 +3169,6 @@ cupsdWritePrintcap(void) 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. */ @@ -3395,13 +3362,18 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("copies-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("document-format-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("finishings-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-account-id-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-accounting-user-id-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-cancel-after-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("notify-lease-duration-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("notify-events-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("number-up-default")); - cupsArrayAdd(CommonDefaults, - _cupsStrAlloc("orientation-requested-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("orientation-requested-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("print-quality-default")); } /* @@ -3443,6 +3415,10 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, "document-format-default", NULL, "application/octet-stream"); + if (!cupsGetOption("job-cancel-after", p->num_options, p->options)) + ippAddInteger(p->attrs, IPP_TAG_PRINTER, MaxJobTime > 0 ? IPP_TAG_INTEGER : IPP_TAG_NOVALUE, + "job-cancel-after-default", MaxJobTime); + 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"); @@ -3491,11 +3467,11 @@ add_printer_filter( /* Destination super/type */ program[1024]; /* Program/filter name */ int cost; /* Cost of filter */ + size_t maxsize = 0; /* Maximum supported file size */ mime_type_t *temptype, /* MIME type looping var */ *desttype; /* Destination MIME type */ - char filename[1024], /* Full filter filename */ - *dirsep; /* Pointer to directory separator */ - struct stat fileinfo; /* File information */ + mime_filter_t *filterptr; /* MIME filter */ + char filename[1024]; /* Full filter filename */ cupsdLogMessage(CUPSD_LOG_DEBUG2, @@ -3507,7 +3483,9 @@ add_printer_filter( * Parse the filter string; it should be in one of the following formats: * * source/type cost program + * source/type cost maxsize(nnnn) program * source/type dest/type cost program + * source/type dest/type cost maxsize(nnnn) program */ if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]", @@ -3540,9 +3518,28 @@ add_printer_filter( } } + if (!strncmp(program, "maxsize(", 8)) + { + char *ptr; /* Pointer into maxsize(nnnn) program */ + + maxsize = (size_t)strtoll(program + 8, &ptr, 10); + + if (*ptr != ')') + { + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: invalid filter string \"%s\"!", + p->name, filter); + return; + } + + ptr ++; + while (_cups_isspace(*ptr)) + ptr ++; + + _cups_strcpy(program, ptr); + } + /* - * See if the filter program exists; if not, stop the printer and flag - * the error! + * Check permissions on the filter and its containing directory... */ if (strcmp(program, "-")) @@ -3552,65 +3549,8 @@ add_printer_filter( else snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program); - if (stat(filename, &fileinfo)) - { - memset(&fileinfo, 0, sizeof(fileinfo)); - - snprintf(p->state_message, sizeof(p->state_message), - "Printer driver \"%s\" not available: %s", filename, - strerror(errno)); - cupsdSetPrinterReasons(p, "+cups-missing-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message); - } - - /* - * When running as root, do additional security checks... - */ - - else 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_IWGRP | S_IWOTH)) != 0) - { - snprintf(p->state_message, sizeof(p->state_message), - "Printer driver \"%s\" has insecure permissions (%d/0%o).", - filename, (int)fileinfo.st_uid, fileinfo.st_mode); - - cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, 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)) - { - snprintf(p->state_message, sizeof(p->state_message), - "Printer driver directory \"%s\" has insecure permissions " - "(%d/0%o).", filename, (int)fileinfo.st_uid, - fileinfo.st_mode); - - cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"); - - cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, p->state_message); - } - } - } + _cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !RunUser, + cupsdLogFCMessage, p); } /* @@ -3620,9 +3560,9 @@ add_printer_filter( 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))) + if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) || + !_cups_strcasecmp(temptype->super, super)) && + (type[0] == '*' || !_cups_strcasecmp(temptype->type, type))) { if (desttype != filtertype) { @@ -3631,7 +3571,8 @@ add_printer_filter( "%s", p->name, temptype->super, temptype->type, desttype->super, desttype->type, cost, program); - mimeAddFilter(MimeDatabase, temptype, desttype, cost, program); + filterptr = mimeAddFilter(MimeDatabase, temptype, desttype, cost, + program); if (!mimeFilterLookup(MimeDatabase, desttype, filtertype)) { @@ -3639,7 +3580,7 @@ add_printer_filter( "add_printer_filter: %s: adding filter %s/%s %s/%s " "0 -", p->name, desttype->super, desttype->type, filtertype->super, filtertype->type); - mimeAddFilter(MimeDatabase, desttype, filtertype, cost, "-"); + mimeAddFilter(MimeDatabase, desttype, filtertype, 0, "-"); } } else @@ -3649,8 +3590,12 @@ add_printer_filter( "%s", p->name, temptype->super, temptype->type, filtertype->super, filtertype->type, cost, program); - mimeAddFilter(MimeDatabase, temptype, filtertype, cost, program); + filterptr = mimeAddFilter(MimeDatabase, temptype, filtertype, cost, + program); } + + if (filterptr) + filterptr->maxsize = maxsize; } } @@ -3700,7 +3645,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */ type; type = mimeNextType(MimeDatabase)) { - if (!strcasecmp(type->super, "printer")) + if (!_cups_strcasecmp(type->super, "printer")) continue; snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type); @@ -3750,7 +3695,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */ attr->values[i].string.text = _cupsStrAlloc(mimetype); } -#ifdef HAVE_DNSSD +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) { char pdl[1024]; /* Buffer to build pdl list */ mime_filter_t *filter; /* MIME filter looping var */ @@ -3765,8 +3710,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */ filter; filter = (mime_filter_t *)cupsArrayNext(MimeDatabase->filters)) { - if (filter->dst == p->filetype && filter->filter && - strstr(filter->filter, "PrintJobMgr")) + if (filter->dst == p->filetype && strstr(filter->filter, "PrintJobMgr")) break; } @@ -3783,20 +3727,20 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */ type; type = (mime_type_t *)cupsArrayNext(p->filetypes)) { - if (!strcasecmp(type->super, "application")) + if (!_cups_strcasecmp(type->super, "application")) { - if (!strcasecmp(type->type, "pdf")) + if (!_cups_strcasecmp(type->type, "pdf")) strlcat(pdl, "application/pdf,", sizeof(pdl)); - else if (!strcasecmp(type->type, "postscript")) + else if (!_cups_strcasecmp(type->type, "postscript")) strlcat(pdl, "application/postscript,", sizeof(pdl)); } - else if (!strcasecmp(type->super, "image")) + else if (!_cups_strcasecmp(type->super, "image")) { - if (!strcasecmp(type->type, "jpeg")) + if (!_cups_strcasecmp(type->type, "jpeg")) strlcat(pdl, "image/jpeg,", sizeof(pdl)); - else if (!strcasecmp(type->type, "png")) + else if (!_cups_strcasecmp(type->type, "png")) strlcat(pdl, "image/png,", sizeof(pdl)); - else if (!strcasecmp(type->type, "pwg-raster")) + else if (!_cups_strcasecmp(type->type, "pwg-raster")) strlcat(pdl, "image/pwg-raster,", sizeof(pdl)); } } @@ -3806,7 +3750,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */ cupsdSetString(&p->pdl, pdl); } -#endif /* HAVE_DNSSD */ +#endif /* HAVE_DNSSD || HAVE_AVAHI */ } @@ -3819,7 +3763,9 @@ 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, + (void)data; + + return (_cups_strcasecmp(((cupsd_printer_t *)first)->name, ((cupsd_printer_t *)second)->name)); } @@ -3882,9 +3828,7 @@ delete_printer_filters( static void dirty_printer(cupsd_printer_t *p) /* I - Printer */ { - if (p->type & CUPS_PRINTER_DISCOVERED) - cupsdMarkDirty(CUPSD_DIRTY_REMOTE); - else if (p->type & CUPS_PRINTER_CLASS) + if (p->type & CUPS_PRINTER_CLASS) cupsdMarkDirty(CUPSD_DIRTY_CLASSES); else cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); @@ -3901,37 +3845,43 @@ dirty_printer(cupsd_printer_t *p) /* I - Printer */ static void load_ppd(cupsd_printer_t *p) /* I - Printer */ { - int i, j, k; /* Looping vars */ + int i, j; /* Looping vars */ char cache_name[1024]; /* Cache filename */ struct stat cache_info; /* Cache file info */ ppd_file_t *ppd; /* PPD file */ char ppd_name[1024]; /* PPD filename */ struct stat ppd_info; /* PPD file info */ - int num_media; /* Number of media options */ + char strings_name[1024]; /* Strings filename */ + int num_media; /* Number of media values */ 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_choice_t *choice; /* Current PPD choice */ 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 */ + 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 */ + _ipp_value_t *val; /* Attribute value */ int num_finishings, /* Number of finishings */ - finishings[5]; /* finishings-supported values */ + finishings[100]; /* 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 */ - const char *filter; /* Current filter */ + const char *filter, /* Current filter */ + *mandatory; /* Current mandatory attribute */ + static const char * const pwg_raster_document_types[] = + { + "black_1", + "sgray_8", + "srgb_8" + }; static const char * const sides[3] = /* sides-supported values */ { "one-sided", @@ -3958,8 +3908,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ if (stat(ppd_name, &ppd_info)) ppd_info.st_mtime = 1; + snprintf(strings_name, sizeof(strings_name), "%s/%s.strings", CacheDir, p->name); + ippDelete(p->ppd_attrs); - p->ppd_attrs = ippNew(); + p->ppd_attrs = NULL; _ppdCacheDestroy(p->pc); p->pc = NULL; @@ -3987,13 +3939,17 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", ppd_name); - p->type &= ~CUPS_PRINTER_OPTIONS; + cupsdClearString(&(p->make_model)); + + p->type &= (cups_ptype_t)~CUPS_PRINTER_OPTIONS; p->type |= CUPS_PRINTER_BW; finishings[0] = IPP_FINISHINGS_NONE; num_finishings = 1; - if ((ppd = ppdOpenFile(ppd_name)) != NULL) + p->ppd_attrs = ippNew(); + + if ((ppd = _ppdOpenFile(ppd_name, _PPD_LOCALIZATION_NONE)) != NULL) { /* * Add make/model and other various attributes... @@ -4001,6 +3957,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ p->pc = _ppdCacheCreateWithPPD(ppd); + if (!p->pc) + cupsdLogMessage(CUPSD_LOG_WARN, "Unable to create cache of \"%s\": %s", + ppd_name, cupsLastErrorString()); + ppdMarkDefaults(ppd); if (ppd->color_device) @@ -4010,11 +3970,31 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ 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")) + if (ppd_attr->value && !_cups_strcasecmp(ppd_attr->value, "true")) p->type |= CUPS_PRINTER_FAX; - ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "color-supported", - ppd->color_device); + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "color-supported", (char)ppd->color_device); + + if (p->pc && p->pc->charge_info_uri) + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_URI, + "printer-charge-info-uri", NULL, p->pc->charge_info_uri); + + if (p->pc && p->pc->account_id) + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "job-account-id-supported", + 1); + + if (p->pc && p->pc->accounting_user_id) + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, + "job-accounting-user-id-supported", 1); + + if (p->pc && p->pc->password) + { + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "job-password-encryption-supported", NULL, "none"); + ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "job-password-supported", (int)strlen(p->pc->password)); + } + if (ppd->throughput) { ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -4036,6 +4016,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ "pages-per-minute-color", 1); } + if ((ppd_attr = ppdFindAttr(ppd, "1284DeviceId", NULL)) != NULL) + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-device-id", NULL, ppd_attr->value); + num_qualities = 0; if ((output_mode = ppdFindOption(ppd, "OutputMode")) != NULL) @@ -4098,16 +4081,24 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, p->make_model); + if (p->pc && p->pc->strings) + _cupsMessageSave(strings_name, _CUPS_MESSAGE_STRINGS, p->pc->strings); + + if (!access(strings_name, R_OK)) + cupsdSetString(&p->strings, strings_name); + else + cupsdClearString(&p->strings); + /* * Add media options from the PPD file... */ if (ppd->num_sizes == 0 || !p->pc) { - if (!ppdFindAttr(ppd, "APScannerOnly", NULL)) + if (!ppdFindAttr(ppd, "APScannerOnly", NULL) && !ppdFindAttr(ppd, "cups3D", NULL)) cupsdLogMessage(CUPSD_LOG_CRIT, "The PPD file for printer %s contains no media " - "options and is therefore invalid!", p->name); + "options and is therefore invalid.", p->name); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", NULL, "unknown"); @@ -4137,20 +4128,8 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ { ipp_t *col; /* Collection value */ - input_slot = ppdFindMarkedChoice(ppd, "InputSlot"); - media_type = ppdFindMarkedChoice(ppd, "MediaType"); - col = new_media_col(pwgsize, - input_slot ? - _ppdCacheGetSource(p->pc, - input_slot->choice) : - NULL, - media_type ? - _ppdCacheGetType(p->pc, - media_type->choice) : - NULL); - - ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-default", - col); + col = new_media_col(pwgsize); + ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-default", col); ippDelete(col); } @@ -4171,13 +4150,48 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes; i > 0; i --, pwgsize ++, val ++) - val->string.text = _cupsStrRetain(pwgsize->map.pwg); + val->string.text = _cupsStrAlloc(pwgsize->map.pwg); if (p->pc->custom_min_keyword) { - val->string.text = _cupsStrRetain(p->pc->custom_min_keyword); + val->string.text = _cupsStrAlloc(p->pc->custom_min_keyword); val ++; - val->string.text = _cupsStrRetain(p->pc->custom_max_keyword); + val->string.text = _cupsStrAlloc(p->pc->custom_max_keyword); + } + } + + /* + * media-size-supported + */ + + num_media = p->pc->num_sizes; + if (p->pc->custom_min_keyword) + num_media ++; + + if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, + "media-size-supported", num_media, + NULL)) != NULL) + { + val = attr->values; + + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes; + i > 0; + i --, pwgsize ++, val ++) + { + val->collection = ippNew(); + ippAddInteger(val->collection, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "x-dimension", pwgsize->width); + ippAddInteger(val->collection, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "y-dimension", pwgsize->length); + } + + if (p->pc->custom_min_keyword) + { + val->collection = ippNew(); + ippAddRange(val->collection, IPP_TAG_PRINTER, "x-dimension", + p->pc->custom_min_width, p->pc->custom_max_width); + ippAddRange(val->collection, IPP_TAG_PRINTER, "y-dimension", + p->pc->custom_min_length, p->pc->custom_max_length); } } @@ -4194,7 +4208,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ val = attr->values; i > 0; i --, pwgsource ++, val ++) - val->string.text = _cupsStrRetain(pwgsource->pwg); + val->string.text = _cupsStrAlloc(pwgsource->pwg); } /* @@ -4210,7 +4224,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ val = attr->values; i > 0; i --, pwgtype ++, val ++) - val->string.text = _cupsStrRetain(pwgtype->pwg); + val->string.text = _cupsStrAlloc(pwgtype->pwg); } /* @@ -4309,89 +4323,19 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * media-col-database */ - num_media = p->pc->num_sizes; - if (p->pc->num_sources) + if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-database", p->pc->num_sizes, NULL)) != NULL) { - if (p->pc->num_types > 0) - num_media += p->pc->num_sizes * p->pc->num_sources * - p->pc->num_types; - else - num_media += p->pc->num_sizes * p->pc->num_sources; - } - else if (p->pc->num_types) - num_media += p->pc->num_sizes * p->pc->num_types; + /* + * Add each page size without source or type... + */ - if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, - "media-col-database", num_media, - NULL)) != NULL) - { - for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, val = attr->values; - i > 0; - i --, pwgsize ++) + for (i = 0, pwgsize = p->pc->sizes; i < p->pc->num_sizes; 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 ++; + ipp_t *col = new_media_col(pwgsize); - /* - * Then add the specific, supported combinations of size, source, and - * type... - */ - - if (p->pc->num_sources > 0) - { - for (j = p->pc->num_sources, pwgsource = p->pc->sources; - j > 0; - j --, pwgsource ++) - { - ppdMarkOption(ppd, "InputSlot", pwgsource->ppd); - - if (p->pc->num_types > 0) - { - for (k = p->pc->num_types, pwgtype = p->pc->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->pc->num_types > 0) - { - for (j = p->pc->num_types, pwgtype = p->pc->types; - j > 0; - j --, pwgtype ++) - { - if (!ppdMarkOption(ppd, "MediaType", pwgtype->ppd)) - { - val->collection = new_media_col(pwgsize, NULL, pwgtype->pwg); - val ++; - } - } - } + ippSetCollection(p->ppd_attrs, &attr, i, col); + ippDelete(col); } - - /* - * Update the number of media-col-database values... - */ - - attr->num_values = val - attr->values; } } @@ -4431,10 +4375,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } else if (((ppd_attr = ppdFindAttr(ppd, "DefaultOutputOrder", NULL)) != NULL && - !strcasecmp(ppd_attr->value, "Reverse")) || + !_cups_strcasecmp(ppd_attr->value, "Reverse")) || (!ppd_attr && ppd->manufacturer && /* "Compatibility heuristic" */ - (!strcasecmp(ppd->manufacturer, "epson") || - !strcasecmp(ppd->manufacturer, "lexmark")))) + (!_cups_strcasecmp(ppd->manufacturer, "epson") || + !_cups_strcasecmp(ppd->manufacturer, "lexmark")))) { /* * Report that this printer has a single output bin that leaves pages face @@ -4455,38 +4399,50 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } /* - * output-mode and print-color-mode... + * print-color-mode... */ if (ppd->color_device) { - static const char * const output_modes[] = + static const char * const color_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"); - - ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "print-color-mode-supported", 2, NULL, output_modes); + "print-color-mode-supported", 2, NULL, color_modes); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-default", NULL, "color"); + ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "pwg-raster-document-type-supported", 3, NULL, pwg_raster_document_types); } 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"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-supported", NULL, "monochrome"); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-default", NULL, "monochrome"); + ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "pwg-raster-document-type-supported", 2, NULL, pwg_raster_document_types); + } + + /* + * Mandatory job attributes, if any... + */ + + if (p->pc && cupsArrayCount(p->pc->mandatory) > 0) + { + int count = cupsArrayCount(p->pc->mandatory); + /* Number of mandatory attributes */ + + attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "printer-mandatory-job-attributes", count, NULL, + NULL); + + for (val = attr->values, + mandatory = (char *)cupsArrayFirst(p->pc->mandatory); + mandatory; + val ++, mandatory = (char *)cupsArrayNext(p->pc->mandatory)) + val->string.text = _cupsStrAlloc(mandatory); } /* @@ -4504,10 +4460,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * Report all supported resolutions... */ - attr = ippAddResolutions(p->ppd_attrs, IPP_TAG_PRINTER, - "printer-resolution-supported", - resolution->num_choices, IPP_RES_PER_INCH, - NULL, NULL); + 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; @@ -4530,9 +4483,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ 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); + ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, "printer-resolution-default", IPP_RES_PER_INCH, xdpi, ydpi); + + if (i == 0) + ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, "pwg-raster-document-resolution-supported", IPP_RES_PER_INCH, xdpi, ydpi); } } else if ((ppd_attr = ppdFindAttr(ppd, "DefaultResolution", NULL)) != NULL && @@ -4565,6 +4519,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, "printer-resolution-supported", IPP_RES_PER_INCH, xdpi, ydpi); + ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, "pwg-raster-document-resolution-supported", IPP_RES_PER_INCH, xdpi, ydpi); } else { @@ -4578,6 +4533,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, "printer-resolution-supported", IPP_RES_PER_INCH, 300, 300); + ippAddResolution(p->ppd_attrs, IPP_TAG_PRINTER, "pwg-raster-document-resolution-supported", IPP_RES_PER_INCH, 300, 300); } /* @@ -4597,13 +4553,15 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ { p->type |= CUPS_PRINTER_DUPLEX; + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "pwg-raster-document-sheet-back", NULL, "normal"); + ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-supported", 3, NULL, sides); - if (!strcasecmp(duplex->defchoice, "DuplexTumble")) + if (!_cups_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")) + else if (!_cups_strcasecmp(duplex->defchoice, "DuplexNoTumble")) ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-default", NULL, "two-sided-long-edge"); else @@ -4621,16 +4579,90 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ if (ppdFindOption(ppd, "Collate") != NULL) p->type |= CUPS_PRINTER_COLLATE; - if (ppdFindOption(ppd, "StapleLocation") != NULL) + if (p->pc && p->pc->finishings) { - p->type |= CUPS_PRINTER_STAPLE; - finishings[num_finishings++] = IPP_FINISHINGS_STAPLE; + _pwg_finishings_t *fin; /* Current finishing value */ + + for (fin = (_pwg_finishings_t *)cupsArrayFirst(p->pc->finishings); fin; fin = (_pwg_finishings_t *)cupsArrayNext(p->pc->finishings)) + { + if (num_finishings < (int)(sizeof(finishings) / sizeof(finishings[0]))) + finishings[num_finishings++] = fin->value; + + switch (fin->value) + { + case IPP_FINISHINGS_BIND : + case IPP_FINISHINGS_BIND_LEFT : + case IPP_FINISHINGS_BIND_TOP : + case IPP_FINISHINGS_BIND_RIGHT : + case IPP_FINISHINGS_BIND_BOTTOM : + case IPP_FINISHINGS_EDGE_STITCH : + case IPP_FINISHINGS_EDGE_STITCH_LEFT : + case IPP_FINISHINGS_EDGE_STITCH_TOP : + case IPP_FINISHINGS_EDGE_STITCH_RIGHT : + case IPP_FINISHINGS_EDGE_STITCH_BOTTOM : + p->type |= CUPS_PRINTER_BIND; + break; + + case IPP_FINISHINGS_COVER : + p->type |= CUPS_PRINTER_COVER; + break; + + case IPP_FINISHINGS_PUNCH : + case IPP_FINISHINGS_PUNCH_TOP_LEFT : + case IPP_FINISHINGS_PUNCH_BOTTOM_LEFT : + case IPP_FINISHINGS_PUNCH_TOP_RIGHT : + case IPP_FINISHINGS_PUNCH_BOTTOM_RIGHT : + case IPP_FINISHINGS_PUNCH_DUAL_LEFT : + case IPP_FINISHINGS_PUNCH_DUAL_TOP : + case IPP_FINISHINGS_PUNCH_DUAL_RIGHT : + case IPP_FINISHINGS_PUNCH_DUAL_BOTTOM : + case IPP_FINISHINGS_PUNCH_TRIPLE_LEFT : + case IPP_FINISHINGS_PUNCH_TRIPLE_TOP : + case IPP_FINISHINGS_PUNCH_TRIPLE_RIGHT : + case IPP_FINISHINGS_PUNCH_TRIPLE_BOTTOM : + case IPP_FINISHINGS_PUNCH_QUAD_LEFT : + case IPP_FINISHINGS_PUNCH_QUAD_TOP : + case IPP_FINISHINGS_PUNCH_QUAD_RIGHT : + case IPP_FINISHINGS_PUNCH_QUAD_BOTTOM : + p->type |= CUPS_PRINTER_PUNCH; + break; + + case IPP_FINISHINGS_STAPLE : + case IPP_FINISHINGS_STAPLE_TOP_LEFT : + case IPP_FINISHINGS_STAPLE_BOTTOM_LEFT : + case IPP_FINISHINGS_STAPLE_TOP_RIGHT : + case IPP_FINISHINGS_STAPLE_BOTTOM_RIGHT : + case IPP_FINISHINGS_STAPLE_DUAL_LEFT : + case IPP_FINISHINGS_STAPLE_DUAL_TOP : + case IPP_FINISHINGS_STAPLE_DUAL_RIGHT : + case IPP_FINISHINGS_STAPLE_DUAL_BOTTOM : + case IPP_FINISHINGS_STAPLE_TRIPLE_LEFT : + case IPP_FINISHINGS_STAPLE_TRIPLE_TOP : + case IPP_FINISHINGS_STAPLE_TRIPLE_RIGHT : + case IPP_FINISHINGS_STAPLE_TRIPLE_BOTTOM : + p->type |= CUPS_PRINTER_STAPLE; + break; + + default : + break; + } + } } - if (ppdFindOption(ppd, "BindEdge") != NULL) + if (p->pc && p->pc->templates) { - p->type |= CUPS_PRINTER_BIND; - finishings[num_finishings++] = IPP_FINISHINGS_BIND; + const char *template; /* Finishing template */ + ipp_attribute_t *fin_col_db; /* finishings-col-database attribute */ + ipp_t *fin_col; /* finishings-col value */ + + fin_col_db = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, "finishings-col-database", cupsArrayCount(p->pc->templates), NULL); + for (i = 0, template = (const char *)cupsArrayFirst(p->pc->templates); template; i ++, template = (const char *)cupsArrayNext(p->pc->templates)) + { + fin_col = ippNew(); + ippAddString(fin_col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "finishing-template", NULL, template); + ippSetCollection(p->ppd_attrs, &fin_col_db, i, fin_col); + ippDelete(fin_col); + } } for (i = 0; i < ppd->num_sizes; i ++) @@ -4642,10 +4674,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ p->type |= CUPS_PRINTER_SMALL; if ((ppd_attr = ppdFindAttr(ppd, "APICADriver", NULL)) != NULL && - ppd_attr->value && !strcasecmp(ppd_attr->value, "true")) + ppd_attr->value && !_cups_strcasecmp(ppd_attr->value, "true")) { if ((ppd_attr = ppdFindAttr(ppd, "APScannerOnly", NULL)) != NULL && - ppd_attr->value && !strcasecmp(ppd_attr->value, "true")) + ppd_attr->value && !_cups_strcasecmp(ppd_attr->value, "true")) p->type |= CUPS_PRINTER_SCANNER; else p->type |= CUPS_PRINTER_MFP; @@ -4661,7 +4693,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ filter; filter = (const char *)cupsArrayNext(p->pc->filters)) { - if (!strncasecmp(filter, "application/vnd.cups-command", 28) && + if (!_cups_strncasecmp(filter, "application/vnd.cups-command", 28) && _cups_isspace(filter[28])) { p->type |= CUPS_PRINTER_COMMANDS; @@ -4798,7 +4830,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ */ if ((ppd_attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL)) != NULL && - ppd_attr->value) + ppd_attr->value && + !_cupsFileCheck(ppd_attr->value, _CUPS_FILE_CHECK_FILE, !RunUser, + cupsdLogFCMessage, p)) { CGImageRef imageRef = NULL;/* Current icon image */ CGImageRef biggestIconRef = NULL; @@ -4815,22 +4849,16 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ 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); + outUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)outPath, (CFIndex)strlen(outPath), FALSE); + icnsFileUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)ppd_attr->value, (CFIndex)strlen(ppd_attr->value), FALSE); if (outUrl && icnsFileUrl) { sourceRef = CGImageSourceCreateWithURL(icnsFileUrl, NULL); if (sourceRef) { - for (i = 0; i < CGImageSourceGetCount(sourceRef); i ++) + for (i = 0; i < (int)CGImageSourceGetCount(sourceRef); i ++) { - imageRef = CGImageSourceCreateImageAtIndex(sourceRef, i, NULL); + imageRef = CGImageSourceCreateImageAtIndex(sourceRef, (size_t)i, NULL); if (!imageRef) continue; @@ -4934,14 +4962,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ pstatus = ppdLastError(&pline); - cupsdLogMessage(CUPSD_LOG_ERROR, "PPD file for %s cannot be loaded!", - p->name); + cupsdLogMessage(CUPSD_LOG_ERROR, "PPD file for %s cannot be loaded.", p->name); if (pstatus <= PPD_ALLOC_ERROR) - cupsdLogMessage(CUPSD_LOG_ERROR, "%s", strerror(errno)); + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", ppd_name, strerror(errno)); else - cupsdLogMessage(CUPSD_LOG_ERROR, "%s on line %d.", - ppdErrorString(pstatus), pline); + cupsdLogMessage(CUPSD_LOG_ERROR, "%s on line %d of %s.", ppdErrorString(pstatus), pline, ppd_name); cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.", @@ -4949,31 +4975,13 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } 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"); - } - 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")))) + if (((!strncmp(p->device_uri, "ipp://", 6) || + !strncmp(p->device_uri, "ipps://", 7)) && + (strstr(p->device_uri, "/printers/") != NULL || + strstr(p->device_uri, "/classes/") != NULL)) || + ((strstr(p->device_uri, "._ipp.") != NULL || + strstr(p->device_uri, "._ipps.") != NULL) && + !strcmp(p->device_uri + strlen(p->device_uri) - 5, "/cups"))) { /* * Tell the client this is really a hard-wired remote printer. @@ -4981,31 +4989,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ p->type |= CUPS_PRINTER_REMOTE; - /* - * Point the printer-uri-supported attribute to the - * remote printer... - */ - - if (strchr(p->device_uri, '?')) - { - /* - * Strip trailing "?options" from URI... - */ - - char resource[HTTP_MAX_URI], /* New URI */ - *ptr; /* Pointer into URI */ - - strlcpy(resource, p->device_uri, sizeof(resource)); - if ((ptr = strchr(resource, '?')) != NULL) - *ptr = '\0'; - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, - "printer-uri-supported", NULL, resource); - } - else - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, - "printer-uri-supported", NULL, p->device_uri); - /* * Then set the make-and-model accordingly... */ @@ -5066,9 +5049,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ */ 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 */ +new_media_col(pwg_size_t *size) /* I - media-size/margin values */ { ipp_t *media_col, /* Collection value */ *media_size; /* media-size value */ @@ -5077,289 +5058,20 @@ new_media_col(_pwg_size_t *size, /* I - media-size/margin values */ 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); + 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); + 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); 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. */ @@ -5379,7 +5091,7 @@ write_xml_string(cups_file_t *fp, /* I - File to write to */ if (*s == '&') { if (s > start) - cupsFileWrite(fp, start, s - start); + cupsFileWrite(fp, start, (size_t)(s - start)); cupsFilePuts(fp, "&"); start = s + 1; @@ -5387,7 +5099,7 @@ write_xml_string(cups_file_t *fp, /* I - File to write to */ else if (*s == '<') { if (s > start) - cupsFileWrite(fp, start, s - start); + cupsFileWrite(fp, start, (size_t)(s - start)); cupsFilePuts(fp, "<"); start = s + 1; @@ -5397,8 +5109,3 @@ write_xml_string(cups_file_t *fp, /* I - File to write to */ if (s > start) cupsFilePuts(fp, start); } - - -/* - * End of "$Id: printers.c 7968 2008-09-19 23:03:01Z mike $". - */