From: Michael R Sweet Date: Tue, 28 May 2019 18:54:01 +0000 (-0400) Subject: Back-port more compatibility fixes from CUPS 2.3.x - IPP/1.1 compatibility with X-Git-Tag: v2.2.12~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b48d16c1d5b4102bd8cbfdd053f7c9f5d3a8b5d;p=thirdparty%2Fcups.git Back-port more compatibility fixes from CUPS 2.3.x - IPP/1.1 compatibility with old versions of CUPS... (Issue #5587) --- diff --git a/CHANGES.md b/CHANGES.md index 6ddae30828..9ac73bd83e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -CHANGES - 2.2.12 - 2019-05-24 +CHANGES - 2.2.12 - 2019-05-28 ============================= @@ -19,6 +19,7 @@ Changes in CUPS v2.2.12 (Issue #5574) - The libusb-based USB backend now enforces read limits, improving print speed in many cases (Issue #5583) +- Fixed some compatibility issues with old releases of CUPS (Issue #5587) - Fixed a command ordering issue in the Zebra ZPL driver. diff --git a/cups/cups-private.h b/cups/cups-private.h index 6fd66a9ced..4ec4e6864b 100644 --- a/cups/cups-private.h +++ b/cups/cups-private.h @@ -239,8 +239,7 @@ extern http_t *_cupsConnect(void); extern char *_cupsCreateDest(const char *name, const char *info, const char *device_id, const char *device_uri, char *uri, size_t urisize); extern int _cupsGet1284Values(const char *device_id, cups_option_t **values); -extern const char *_cupsGetDestResource(cups_dest_t *dest, char *resource, - size_t resourcesize); +extern const char *_cupsGetDestResource(cups_dest_t *dest, unsigned flags, char *resource, size_t resourcesize); extern int _cupsGetDests(http_t *http, ipp_op_t op, const char *name, cups_dest_t **dests, cups_ptype_t type, cups_ptype_t mask); diff --git a/cups/dest-options.c b/cups/dest-options.c index cddc2f9550..e9361adf78 100644 --- a/cups/dest-options.c +++ b/cups/dest-options.c @@ -129,10 +129,10 @@ cupsCheckDestSupported( */ pwg_media_t *pwg; /* Current PWG media size info */ - int min_width, /* Minimum width */ - min_length, /* Minimum length */ - max_width, /* Maximum width */ - max_length; /* Maximum length */ + int min_width, /* Minimum width */ + min_length, /* Minimum length */ + max_width, /* Maximum width */ + max_length; /* Maximum length */ /* * Get the minimum and maximum size... @@ -581,6 +581,7 @@ cupsCopyDestInfo( cups_dest_t *dest) /* I - Destination */ { cups_dinfo_t *dinfo; /* Destination information */ + unsigned dflags; /* Destination flags */ ipp_t *request, /* Get-Printer-Attributes request */ *response; /* Supported attributes */ int tries, /* Number of tries so far */ @@ -590,6 +591,7 @@ cupsCopyDestInfo( char resource[1024]; /* Resource path */ int version; /* IPP version */ ipp_status_t status; /* Status of request */ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ static const char * const requested_attrs[] = { /* Requested attributes */ "job-template", @@ -598,14 +600,35 @@ cupsCopyDestInfo( }; - DEBUG_printf(("cupsCopyDestSupported(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : "")); + DEBUG_printf(("cupsCopyDestInfo(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : "")); /* * Get the default connection as needed... */ if (!http) - http = _cupsConnect(); + { + DEBUG_puts("1cupsCopyDestInfo: Default server connection."); + http = _cupsConnect(); + dflags = CUPS_DEST_FLAGS_NONE; + } +#ifdef AF_LOCAL + else if (httpAddrFamily(http->hostaddr) == AF_LOCAL) + { + DEBUG_puts("1cupsCopyDestInfo: Connection to server (domain socket)."); + dflags = CUPS_DEST_FLAGS_NONE; + } +#endif /* AF_LOCAL */ + else if ((strcmp(http->hostname, cg->server) && cg->server[0] != '/') || cg->ipp_port != httpAddrPort(http->hostaddr)) + { + DEBUG_printf(("1cupsCopyDestInfo: Connection to device (%s).", http->hostname)); + dflags = CUPS_DEST_FLAGS_DEVICE; + } + else + { + DEBUG_printf(("1cupsCopyDestInfo: Connection to server (%s).", http->hostname)); + dflags = CUPS_DEST_FLAGS_NONE; + } /* * Range check input... @@ -618,8 +641,11 @@ cupsCopyDestInfo( * Get the printer URI and resource path... */ - if ((uri = _cupsGetDestResource(dest, resource, sizeof(resource))) == NULL) + if ((uri = _cupsGetDestResource(dest, dflags, resource, sizeof(resource))) == NULL) + { + DEBUG_puts("1cupsCopyDestInfo: Unable to get resource."); return (NULL); + } /* * Get the supported attributes... @@ -637,28 +663,25 @@ cupsCopyDestInfo( */ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, - uri); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requesting-user-name", NULL, cupsUser()); - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, - "requested-attributes", - (int)(sizeof(requested_attrs) / sizeof(requested_attrs[0])), - NULL, requested_attrs); + + ippSetVersion(request, version / 10, version % 10); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested_attrs) / sizeof(requested_attrs[0])), NULL, requested_attrs); response = cupsDoRequest(http, request, resource); status = cupsLastError(); if (status > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) { - DEBUG_printf(("cupsCopyDestSupported: Get-Printer-Attributes for '%s' " - "returned %s (%s)", dest->name, ippErrorString(status), - cupsLastErrorString())); + DEBUG_printf(("1cupsCopyDestInfo: Get-Printer-Attributes for '%s' returned %s (%s)", dest->name, ippErrorString(status), cupsLastErrorString())); ippDelete(response); response = NULL; - if (status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED && version > 11) + if ((status == IPP_STATUS_ERROR_BAD_REQUEST || status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) && version > 11) + { version = 11; + } else if (status == IPP_STATUS_ERROR_BUSY) { sleep((unsigned)delay); @@ -674,7 +697,10 @@ cupsCopyDestInfo( while (!response && tries < 10); if (!response) + { + DEBUG_puts("1cupsCopyDestInfo: Unable to get printer attributes."); return (NULL); + } /* * Allocate a cups_dinfo_t structure and return it... @@ -687,6 +713,8 @@ cupsCopyDestInfo( return (NULL); } + DEBUG_printf(("1cupsCopyDestInfo: version=%d, uri=\"%s\", resource=\"%s\".", version, uri, resource)); + dinfo->version = version; dinfo->uri = uri; dinfo->resource = _cupsStrAlloc(resource); @@ -947,10 +975,10 @@ cupsGetDestMediaByIndex( return (0); } - if (nsize->size_name) - strlcpy(size->media, nsize->size_name, sizeof(size->media)); - else if (nsize->key) + if (nsize->key) strlcpy(size->media, nsize->key, sizeof(size->media)); + else if (nsize->size_name) + strlcpy(size->media, nsize->size_name, sizeof(size->media)); else if ((pwg = pwgMediaForSize(nsize->width, nsize->length)) != NULL) strlcpy(size->media, pwg->pwg, sizeof(size->media)); else @@ -1211,25 +1239,19 @@ cupsGetDestMediaDefault( * Get the default media size, if any... */ - if ((media = cupsGetOption("media", dest->num_options, - dest->options)) == NULL) + if ((media = cupsGetOption("media", dest->num_options, dest->options)) == NULL) media = "na_letter_8.5x11in"; if (cupsGetDestMediaByName(http, dest, dinfo, media, flags, size)) return (1); - if (strcmp(media, "na_letter_8.5x11in") && - cupsGetDestMediaByName(http, dest, dinfo, "iso_a4_210x297mm", flags, - size)) + if (strcmp(media, "na_letter_8.5x11in") && cupsGetDestMediaByName(http, dest, dinfo, "iso_a4_210x297mm", flags, size)) return (1); - if (strcmp(media, "iso_a4_210x297mm") && - cupsGetDestMediaByName(http, dest, dinfo, "na_letter_8.5x11in", flags, - size)) + if (strcmp(media, "iso_a4_210x297mm") && cupsGetDestMediaByName(http, dest, dinfo, "na_letter_8.5x11in", flags, size)) return (1); - if ((flags & CUPS_MEDIA_FLAGS_BORDERLESS) && - cupsGetDestMediaByName(http, dest, dinfo, "na_index_4x6in", flags, size)) + if ((flags & CUPS_MEDIA_FLAGS_BORDERLESS) && cupsGetDestMediaByName(http, dest, dinfo, "na_index_4x6in", flags, size)) return (1); /* @@ -1522,6 +1544,7 @@ cups_create_media_db( pwg_media_t *pwg; /* PWG media info */ cups_array_t *db; /* New media database array */ _cups_media_db_t mdb; /* Media entry */ + char media_key[256]; /* Synthesized media-key value */ db = cupsArrayNew3((cups_array_func_t)cups_compare_media_db, @@ -1622,61 +1645,92 @@ cups_create_media_db( } } - if ((media_attr = ippFindAttribute(val->collection, "media-color", - IPP_TAG_ZERO)) != NULL && - (media_attr->value_tag == IPP_TAG_NAME || - media_attr->value_tag == IPP_TAG_NAMELANG || - media_attr->value_tag == IPP_TAG_KEYWORD)) + if ((media_attr = ippFindAttribute(val->collection, "media-color", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD)) mdb.color = media_attr->values[0].string.text; - if ((media_attr = ippFindAttribute(val->collection, "media-info", - IPP_TAG_TEXT)) != NULL) + if ((media_attr = ippFindAttribute(val->collection, "media-info", IPP_TAG_TEXT)) != NULL) mdb.info = media_attr->values[0].string.text; - if ((media_attr = ippFindAttribute(val->collection, "media-key", - IPP_TAG_ZERO)) != NULL && - (media_attr->value_tag == IPP_TAG_NAME || - media_attr->value_tag == IPP_TAG_NAMELANG || - media_attr->value_tag == IPP_TAG_KEYWORD)) + if ((media_attr = ippFindAttribute(val->collection, "media-key", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD)) mdb.key = media_attr->values[0].string.text; - if ((media_attr = ippFindAttribute(val->collection, "media-size-name", - IPP_TAG_ZERO)) != NULL && - (media_attr->value_tag == IPP_TAG_NAME || - media_attr->value_tag == IPP_TAG_NAMELANG || - media_attr->value_tag == IPP_TAG_KEYWORD)) + if ((media_attr = ippFindAttribute(val->collection, "media-size-name", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD)) mdb.size_name = media_attr->values[0].string.text; - if ((media_attr = ippFindAttribute(val->collection, "media-source", - IPP_TAG_ZERO)) != NULL && - (media_attr->value_tag == IPP_TAG_NAME || - media_attr->value_tag == IPP_TAG_NAMELANG || - media_attr->value_tag == IPP_TAG_KEYWORD)) + if ((media_attr = ippFindAttribute(val->collection, "media-source", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD)) mdb.source = media_attr->values[0].string.text; - if ((media_attr = ippFindAttribute(val->collection, "media-type", - IPP_TAG_ZERO)) != NULL && - (media_attr->value_tag == IPP_TAG_NAME || - media_attr->value_tag == IPP_TAG_NAMELANG || - media_attr->value_tag == IPP_TAG_KEYWORD)) + if ((media_attr = ippFindAttribute(val->collection, "media-type", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD)) mdb.type = media_attr->values[0].string.text; - if ((media_attr = ippFindAttribute(val->collection, "media-bottom-margin", - IPP_TAG_INTEGER)) != NULL) + if ((media_attr = ippFindAttribute(val->collection, "media-bottom-margin", IPP_TAG_INTEGER)) != NULL) mdb.bottom = media_attr->values[0].integer; - if ((media_attr = ippFindAttribute(val->collection, "media-left-margin", - IPP_TAG_INTEGER)) != NULL) + if ((media_attr = ippFindAttribute(val->collection, "media-left-margin", IPP_TAG_INTEGER)) != NULL) mdb.left = media_attr->values[0].integer; - if ((media_attr = ippFindAttribute(val->collection, "media-right-margin", - IPP_TAG_INTEGER)) != NULL) + if ((media_attr = ippFindAttribute(val->collection, "media-right-margin", IPP_TAG_INTEGER)) != NULL) mdb.right = media_attr->values[0].integer; - if ((media_attr = ippFindAttribute(val->collection, "media-top-margin", - IPP_TAG_INTEGER)) != NULL) + if ((media_attr = ippFindAttribute(val->collection, "media-top-margin", IPP_TAG_INTEGER)) != NULL) mdb.top = media_attr->values[0].integer; + if (!mdb.key) + { + if (!mdb.size_name && (pwg = pwgMediaForSize(mdb.width, mdb.length)) != NULL) + mdb.size_name = (char *)pwg->pwg; + + if (!mdb.size_name) + { + /* + * Use a CUPS-specific identifier if we don't have a size name... + */ + + if (flags & CUPS_MEDIA_FLAGS_READY) + snprintf(media_key, sizeof(media_key), "cups-media-ready-%d", i + 1); + else + snprintf(media_key, sizeof(media_key), "cups-media-%d", i + 1); + } + else if (mdb.source) + { + /* + * Generate key using size name, source, and type (if set)... + */ + + if (mdb.type) + snprintf(media_key, sizeof(media_key), "%s_%s_%s", mdb.size_name, mdb.source, mdb.type); + else + snprintf(media_key, sizeof(media_key), "%s_%s", mdb.size_name, mdb.source); + } + else if (mdb.type) + { + /* + * Generate key using size name and type... + */ + + snprintf(media_key, sizeof(media_key), "%s_%s", mdb.size_name, mdb.type); + } + else + { + /* + * Key is just the size name... + */ + + strlcpy(media_key, mdb.size_name, sizeof(media_key)); + } + + /* + * Append "_borderless" for borderless media... + */ + + if (!mdb.bottom && !mdb.left && !mdb.right && !mdb.top) + strlcat(media_key, "_borderless", sizeof(media_key)); + + mdb.key = media_key; + } + + DEBUG_printf(("1cups_create_media_db: Adding media: key=\"%s\", width=%d, length=%d, source=\"%s\", type=\"%s\".", mdb.key, mdb.width, mdb.length, mdb.source, mdb.type)); + cupsArrayAdd(db, &mdb); } @@ -2036,12 +2090,14 @@ cups_get_media_db(http_t *http, /* I - Connection to destination */ * Return the matching size... */ - if (best->size_name) - strlcpy(size->media, best->size_name, sizeof(size->media)); - else if (best->key) + if (best->key) strlcpy(size->media, best->key, sizeof(size->media)); - else + else if (best->size_name) + strlcpy(size->media, best->size_name, sizeof(size->media)); + else if (pwg && pwg->pwg) strlcpy(size->media, pwg->pwg, sizeof(size->media)); + else + strlcpy(size->media, "unknown", sizeof(size->media)); size->width = best->width; size->length = best->length; diff --git a/cups/dest.c b/cups/dest.c index 7ef85a1b91..fd635b1111 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -79,7 +79,6 @@ typedef enum _cups_dnssd_state_e /* Enumerated device state */ _CUPS_DNSSD_QUERY, _CUPS_DNSSD_PENDING, _CUPS_DNSSD_ACTIVE, - _CUPS_DNSSD_LOCAL, _CUPS_DNSSD_INCOMPATIBLE, _CUPS_DNSSD_ERROR } _cups_dnssd_state_t; @@ -99,6 +98,10 @@ typedef struct _cups_dnssd_data_s /* Enumeration data */ cups_ptype_t type, /* Printer type filter */ mask; /* Printer type mask */ cups_array_t *devices; /* Devices found so far */ + int num_dests; /* Number of lpoptions destinations */ + cups_dest_t *dests; /* lpoptions destinations */ + char def_name[1024], /* Default printer name, if any */ + *def_instance; /* Default printer instance, if any */ } _cups_dnssd_data_t; typedef struct _cups_dnssd_device_s /* Enumerated device */ @@ -125,8 +128,10 @@ typedef struct _cups_dnssd_resolve_s /* Data for resolving URI */ typedef struct _cups_getdata_s { - int num_dests; /* Number of destinations */ - cups_dest_t *dests; /* Destinations */ + int num_dests; /* Number of destinations */ + cups_dest_t *dests; /* Destinations */ + char def_name[1024], /* Default printer name, if any */ + *def_instance; /* Default printer instance, if any */ } _cups_getdata_t; typedef struct _cups_namedata_s @@ -192,14 +197,6 @@ static _cups_dnssd_device_t * const char *regtype, const char *replyDomain); # ifdef HAVE_DNSSD -static void cups_dnssd_local_cb(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, - void *context); static void cups_dnssd_query_cb(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, @@ -237,9 +234,7 @@ static int cups_find_dest(const char *name, const char *instance, static int cups_get_cb(_cups_getdata_t *data, unsigned flags, cups_dest_t *dest); static char *cups_get_default(const char *filename, char *namebuf, size_t namesize, const char **instance); -static int cups_get_dests(const char *filename, const char *match_name, - const char *match_inst, int user_default_set, - int num_dests, cups_dest_t **dests); +static int cups_get_dests(const char *filename, const char *match_name, const char *match_inst, int load_all, int user_default_set, int num_dests, cups_dest_t **dests); static char *cups_make_string(ipp_attribute_t *attr, char *buffer, size_t bufsize); static int cups_name_cb(_cups_namedata_t *data, unsigned flags, cups_dest_t *dest); @@ -574,7 +569,7 @@ _cupsAppleSetUseLastPrinter( /* - * 'cupsConnectDest()' - Open a conection to the destination. + * 'cupsConnectDest()' - Open a connection to the destination. * * Connect to the destination, returning a new @code http_t@ connection object * and optionally the resource path to use for the destination. These calls @@ -583,7 +578,7 @@ _cupsAppleSetUseLastPrinter( * returns 0. The caller is responsible for calling @link httpClose@ on the * returned connection. * - * Starting with CUPS 2.2.4, the caller can pass @code CUPS_DEST_FLAGS_DEVICE@ + * Starting with CUPS 2.2.4, the caller can pass @code CUPS_DEST_FLAGS_DEVICE@ * for the "flags" argument to connect directly to the device associated with * the destination. Otherwise, the connection is made to the CUPS scheduler * associated with the destination. @@ -851,6 +846,8 @@ cupsCopyDest(cups_dest_t *dest, /* I - Destination to copy */ if (new_dest) { + new_dest->is_default = dest->is_default; + if ((new_dest->options = calloc(sizeof(cups_option_t), (size_t)dest->num_options)) == NULL) return (cupsRemoveDest(dest->name, dest->instance, num_dests, dests)); @@ -1103,20 +1100,23 @@ cupsGetDest(const char *name, /* I - Destination name or @code NULL@ for the d * '_cupsGetDestResource()' - Get the resource path and URI for a destination. */ -const char * /* O - Printer URI */ +const char * /* O - URI */ _cupsGetDestResource( cups_dest_t *dest, /* I - Destination */ + unsigned flags, /* I - Destination flags */ char *resource, /* I - Resource buffer */ size_t resourcesize) /* I - Size of resource buffer */ { - const char *uri; /* Printer URI */ + const char *uri, /* URI */ + *device_uri, /* Device URI */ + *printer_uri; /* Printer URI */ char scheme[32], /* URI scheme */ userpass[256], /* Username and password (unused) */ hostname[256]; /* Hostname */ int port; /* Port number */ - DEBUG_printf(("_cupsGetDestResource(dest=%p(%s), resource=%p, resourcesize=%d)", (void *)dest, dest->name, (void *)resource, (int)resourcesize)); + DEBUG_printf(("_cupsGetDestResource(dest=%p(%s), flags=%u, resource=%p, resourcesize=%d)", (void *)dest, dest->name, flags, (void *)resource, (int)resourcesize)); /* * Range check input... @@ -1132,25 +1132,46 @@ _cupsGetDestResource( } /* - * Grab the printer URI... + * Grab the printer and device URIs... */ - if ((uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options)) == NULL) + device_uri = cupsGetOption("device-uri", dest->num_options, dest->options); + printer_uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options); + + DEBUG_printf(("1_cupsGetDestResource: device-uri=\"%s\", printer-uri-supported=\"%s\".", device_uri, printer_uri)); + +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + if (((flags & CUPS_DEST_FLAGS_DEVICE) || !printer_uri) && strstr(device_uri, "._tcp")) { - if ((uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL) + if ((device_uri = cups_dnssd_resolve(dest, device_uri, 5000, NULL, NULL, NULL)) != NULL) { -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - if (strstr(uri, "._tcp")) - uri = cups_dnssd_resolve(dest, uri, 5000, NULL, NULL, NULL); -#endif /* HAVE_DNSSD || HAVE_AVAHI */ + DEBUG_printf(("1_cupsGetDestResource: Resolved device-uri=\"%s\".", device_uri)); } - - if (uri) + else { - DEBUG_printf(("1_cupsGetDestResource: Resolved printer-uri-supported=\"%s\"", uri)); + DEBUG_puts("1_cupsGetDestResource: Unable to resolve device."); - uri = _cupsCreateDest(dest->name, cupsGetOption("printer-info", dest->num_options, dest->options), NULL, uri, resource, resourcesize); + if (resource) + *resource = '\0'; + + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0); + + return (NULL); } + } +#endif /* HAVE_DNSSD || HAVE_AVAHI */ + + if (flags & CUPS_DEST_FLAGS_DEVICE) + { + uri = device_uri; + } + else if (printer_uri) + { + uri = printer_uri; + } + else + { + uri = _cupsCreateDest(dest->name, cupsGetOption("printer-info", dest->num_options, dest->options), NULL, device_uri, resource, resourcesize); if (uri) { @@ -1160,30 +1181,24 @@ _cupsGetDestResource( uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options); } - else - { - DEBUG_puts("1_cupsGetDestResource: No printer-uri-supported found."); + } - if (resource) - *resource = '\0'; + if (!uri) + { + DEBUG_puts("1_cupsGetDestResource: No printer-uri-supported or device-uri found."); - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0); + if (resource) + *resource = '\0'; - return (NULL); - } + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0); + + return (NULL); } - else + else if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, (int)resourcesize) < HTTP_URI_STATUS_OK) { - DEBUG_printf(("1_cupsGetDestResource: printer-uri-supported=\"%s\"", uri)); - - if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), - userpass, sizeof(userpass), hostname, sizeof(hostname), - &port, resource, (int)resourcesize) < HTTP_URI_STATUS_OK) - { - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad printer-uri."), 1); + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad URI."), 1); - return (NULL); - } + return (NULL); } DEBUG_printf(("1_cupsGetDestResource: resource=\"%s\"", resource)); @@ -1271,6 +1286,12 @@ cupsGetDestWithURI(const char *name, /* I - Desired printer name or @code NULL@ name = resource + 10; info = temp; } + else if (!strncmp(resource, "/ipp/print/", 11)) + { + snprintf(temp, sizeof(temp), "%s @ %s", resource + 11, hostname); + name = resource + 11; + info = temp; + } else { name = hostname; @@ -1631,16 +1652,6 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ cups_dest_t **dests) /* O - Destinations */ { _cups_getdata_t data; /* Enumeration data */ - cups_dest_t *dest; /* Current destination */ - const char *home; /* HOME environment variable */ - char filename[1024]; /* Local ~/.cups/lpoptions file */ - const char *defprinter; /* Default printer */ - char name[1024], /* Copy of printer name */ - *instance, /* Pointer to instance name */ - *user_default; /* User default printer */ - int num_reals; /* Number of real queues */ - cups_dest_t *reals; /* Real queues */ - _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ DEBUG_printf(("cupsGetDests2(http=%p, dests=%p)", (void *)http, (void *)dests)); @@ -1696,107 +1707,6 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ cups_enum_dests(http, 0, _CUPS_DNSSD_GET_DESTS, NULL, 0, 0, (cups_dest_cb_t)cups_get_cb, &data); } - /* - * Make a copy of the "real" queues for a later sanity check... - */ - - if (data.num_dests > 0) - { - num_reals = data.num_dests; - reals = calloc((size_t)num_reals, sizeof(cups_dest_t)); - - if (reals) - memcpy(reals, data.dests, (size_t)num_reals * sizeof(cups_dest_t)); - else - num_reals = 0; - } - else - { - num_reals = 0; - reals = NULL; - } - - /* - * Grab the default destination... - */ - - if ((user_default = _cupsUserDefault(name, sizeof(name))) != NULL) - defprinter = name; - else if ((defprinter = cupsGetDefault2(http)) != NULL) - { - strlcpy(name, defprinter, sizeof(name)); - defprinter = name; - } - - if (defprinter) - { - /* - * Separate printer and instance name... - */ - - if ((instance = strchr(name, '/')) != NULL) - *instance++ = '\0'; - - /* - * Lookup the printer and instance and make it the default... - */ - - if ((dest = cupsGetDest(name, instance, data.num_dests, data.dests)) != NULL) - dest->is_default = 1; - } - else - instance = NULL; - - /* - * Load the /etc/cups/lpoptions and ~/.cups/lpoptions files... - */ - - snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); - data.num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, data.num_dests, &data.dests); - - if ((home = getenv("HOME")) != NULL) - { - snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home); - - data.num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, data.num_dests, &data.dests); - } - - /* - * Validate the current default destination - this prevents old - * Default lines in /etc/cups/lpoptions and ~/.cups/lpoptions from - * pointing to a non-existent printer or class... - */ - - if (num_reals) - { - /* - * See if we have a default printer... - */ - - if ((dest = cupsGetDest(NULL, NULL, data.num_dests, data.dests)) != NULL) - { - /* - * Have a default; see if it is real... - */ - - if (!cupsGetDest(dest->name, NULL, num_reals, reals)) - { - /* - * Remove the non-real printer from the list, since we don't want jobs - * going to an unexpected printer... () - */ - - data.num_dests = cupsRemoveDest(dest->name, dest->instance, data.num_dests, &data.dests); - } - } - - /* - * Free memory... - */ - - free(reals); - } - /* * Return the number of destinations... */ @@ -1883,6 +1793,9 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home); dest_name = cups_get_default(filename, defname, sizeof(defname), &instance); + + if (dest_name) + set_as_default = 2; } if (!dest_name) @@ -1893,6 +1806,9 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); dest_name = cups_get_default(filename, defname, sizeof(defname), &instance); + + if (dest_name) + set_as_default = 3; } if (!dest_name) @@ -1901,7 +1817,8 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT * No locally-set default destination, ask the server... */ - op = IPP_OP_CUPS_GET_DEFAULT; + op = IPP_OP_CUPS_GET_DEFAULT; + set_as_default = 4; DEBUG_puts("1cupsGetNamedDest: Asking server for default printer..."); } @@ -1932,7 +1849,36 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT dest = data.dest; } else + { + switch (set_as_default) + { + default : + break; + + case 1 : /* Set from env vars */ + if (getenv("LPDEST")) + _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, _("LPDEST environment variable names default destination that does not exist."), 1); + else if (getenv("PRINTER")) + _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, _("PRINTER environment variable names default destination that does not exist."), 1); + else + _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, _("No default destination."), 1); + break; + + case 2 : /* Set from ~/.cups/lpoptions */ + _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, _("~/.cups/lpoptions file names default destination that does not exist."), 1); + break; + + case 3 : /* Set from /etc/cups/lpoptions */ + _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, _("/etc/cups/lpoptions file names default destination that does not exist."), 1); + break; + + case 4 : /* Set from server */ + _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, _("No default destination."), 1); + break; + } + return (NULL); + } } DEBUG_printf(("1cupsGetNamedDest: Got dest=%p", (void *)dest)); @@ -1948,13 +1894,13 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT */ snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); - cups_get_dests(filename, dest_name, instance, 1, 1, &dest); + cups_get_dests(filename, dest_name, instance, 0, 1, 1, &dest); if (home) { snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home); - cups_get_dests(filename, dest_name, instance, 1, 1, &dest); + cups_get_dests(filename, dest_name, instance, 0, 1, 1, &dest); } /* @@ -2129,12 +2075,6 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ #ifndef _WIN32 if (getuid()) { - /* - * Merge in server defaults... - */ - - num_temps = cups_get_dests(filename, NULL, NULL, 0, num_temps, &temps); - /* * Point to user defaults... */ @@ -2195,8 +2135,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ else wrote = 0; - if ((temp = cupsGetDest(dest->name, dest->instance, num_temps, temps)) == NULL) - temp = cupsGetDest(dest->name, NULL, num_temps, temps); + temp = cupsGetDest(dest->name, NULL, num_temps, temps); for (j = dest->num_options, option = dest->options; j > 0; j --, option ++) { @@ -2204,19 +2143,14 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ * See if this option is a printer attribute; if so, skip it... */ - if ((match = _ippFindOption(option->name)) != NULL && - match->group_tag == IPP_TAG_PRINTER) + if ((match = _ippFindOption(option->name)) != NULL && match->group_tag == IPP_TAG_PRINTER) continue; /* - * See if the server/global options match these; if so, don't - * write 'em. + * See if the server options match these; if so, don't write 'em. */ - if (temp && - (val = cupsGetOption(option->name, temp->num_options, - temp->options)) != NULL && - !_cups_strcasecmp(val, option->value)) + if (temp && (val = cupsGetOption(option->name, temp->num_options, temp->options)) != NULL && !_cups_strcasecmp(val, option->value)) continue; /* @@ -2233,10 +2167,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ if (option->value[0]) { - if (strchr(option->value, ' ') || - strchr(option->value, '\\') || - strchr(option->value, '\"') || - strchr(option->value, '\'')) + if (strchr(option->value, ' ') || strchr(option->value, '\\') || strchr(option->value, '\"') || strchr(option->value, '\'')) { /* * Quote the value... @@ -2287,9 +2218,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL) { - CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, - dest->name, - kCFStringEncodingUTF8); + CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, dest->name, kCFStringEncodingUTF8); /* Default printer name */ if (name) @@ -2720,22 +2649,7 @@ cups_dnssd_browse_cb( * This object is new on the network. */ - if (flags & AVAHI_LOOKUP_RESULT_LOCAL) - { - /* - * This comes from the local machine so ignore it. - */ - - DEBUG_printf(("cups_dnssd_browse_cb: Ignoring local service \"%s\".", name)); - } - else - { - /* - * Create a device entry for it if it doesn't yet exist. - */ - - cups_dnssd_get_device(data, name, type, domain); - } + cups_dnssd_get_device(data, name, type, domain); break; case AVAHI_BROWSER_REMOVE : @@ -2956,66 +2870,6 @@ cups_dnssd_get_device( } -# ifdef HAVE_DNSSD -/* - * 'cups_dnssd_local_cb()' - Browse for local printers. - */ - -static void -cups_dnssd_local_cb( - DNSServiceRef sdRef, /* I - Service reference */ - DNSServiceFlags flags, /* I - Option flags */ - uint32_t interfaceIndex, /* I - Interface number */ - DNSServiceErrorType errorCode, /* I - Error, if any */ - const char *serviceName, /* I - Name of service/device */ - const char *regtype, /* I - Type of service */ - const char *replyDomain, /* I - Service domain */ - void *context) /* I - Devices array */ -{ - _cups_dnssd_data_t *data = (_cups_dnssd_data_t *)context; - /* Enumeration data */ - _cups_dnssd_device_t *device; /* Device */ - - - DEBUG_printf(("5cups_dnssd_local_cb(sdRef=%p, flags=%x, interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", regtype=\"%s\", replyDomain=\"%s\", context=%p)", (void *)sdRef, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain, context)); - - /* - * Only process "add" data... - */ - - if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd)) - return; - - /* - * Get the device... - */ - - device = cups_dnssd_get_device(data, serviceName, regtype, replyDomain); - - /* - * Hide locally-registered devices... - */ - - DEBUG_printf(("6cups_dnssd_local_cb: Hiding local printer '%s'.", - serviceName)); - - if (device->ref) - { - DNSServiceRefDeallocate(device->ref); - device->ref = 0; - } - - if (device->state == _CUPS_DNSSD_ACTIVE) - { - DEBUG_printf(("6cups_dnssd_local_cb: Remove callback for \"%s\".", device->dest.name)); - (*data->cb)(data->user_data, CUPS_DEST_FLAGS_REMOVED, &device->dest); - } - - device->state = _CUPS_DNSSD_LOCAL; -} -# endif /* HAVE_DNSSD */ - - # ifdef HAVE_AVAHI /* * 'cups_dnssd_poll_cb()' - Wait for input on the specified file descriptors. @@ -3065,9 +2919,9 @@ cups_dnssd_poll_cb( * 'cups_dnssd_query_cb()' - Process query data. */ -# ifdef HAVE_DNSSD static void cups_dnssd_query_cb( +# ifdef HAVE_DNSSD DNSServiceRef sdRef, /* I - Service reference */ DNSServiceFlags flags, /* I - Data flags */ uint32_t interfaceIndex, /* I - Interface */ @@ -3078,11 +2932,7 @@ cups_dnssd_query_cb( uint16_t rdlen, /* I - Length of record data */ const void *rdata, /* I - Record data */ uint32_t ttl, /* I - Time-to-live */ - void *context) /* I - Enumeration data */ -{ # else /* HAVE_AVAHI */ -static void -cups_dnssd_query_cb( AvahiRecordBrowser *browser, /* I - Record browser */ AvahiIfIndex interfaceIndex, /* I - Interface index (unused) */ @@ -3094,13 +2944,13 @@ cups_dnssd_query_cb( const void *rdata, /* I - TXT record */ size_t rdlen, /* I - Length of TXT record */ AvahiLookupResultFlags flags, /* I - Flags */ - void *context) /* I - Enumeration data */ +# endif /* HAVE_DNSSD */ + void *context) /* I - Enumeration data */ { -# ifdef DEBUG +# if defined(DEBUG) && defined(HAVE_AVAHI) AvahiClient *client = avahi_record_browser_get_client(browser); /* Client information */ -# endif /* DEBUG */ -# endif /* HAVE_DNSSD */ +# endif /* DEBUG && HAVE_AVAHI */ _cups_dnssd_data_t *data = (_cups_dnssd_data_t *)context; /* Enumeration data */ char serviceName[256],/* Service name */ @@ -3543,29 +3393,26 @@ cups_enum_dests( cups_dest_cb_t cb, /* I - Callback function */ void *user_data) /* I - User data */ { - int i, /* Looping var */ + int i, j, /* Looping vars */ num_dests; /* Number of destinations */ cups_dest_t *dests = NULL, /* Destinations */ - *dest; /* Current destination */ - const char *defprinter; /* Default printer */ - char name[1024], /* Copy of printer name */ - *instance, /* Pointer to instance name */ - *user_default; /* User default printer */ + *dest, /* Current destination */ + *user_dest; /* User destination */ + cups_option_t *option; /* Current option */ + char *user_default; /* User default printer */ #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) int count, /* Number of queries started */ completed, /* Number of completed queries */ remaining; /* Remainder of timeout */ struct timeval curtime; /* Current time */ - _cups_dnssd_data_t data; /* Data for callback */ + _cups_dnssd_data_t data; /* Data for callback */ _cups_dnssd_device_t *device; /* Current device */ # ifdef HAVE_DNSSD int nfds, /* Number of files responded */ main_fd; /* File descriptor for lookups */ - DNSServiceRef ipp_ref = NULL, /* IPP browser */ - local_ipp_ref = NULL; /* Local IPP browser */ + DNSServiceRef ipp_ref = NULL; /* IPP browser */ # ifdef HAVE_SSL - DNSServiceRef ipps_ref = NULL, /* IPPS browser */ - local_ipps_ref = NULL; /* Local IPPS browser */ + DNSServiceRef ipps_ref = NULL; /* IPPS browser */ # endif /* HAVE_SSL */ # ifdef HAVE_POLL struct pollfd pfd; /* Polling data */ @@ -3580,7 +3427,12 @@ cups_enum_dests( AvahiServiceBrowser *ipps_ref = NULL; /* IPPS browser */ # endif /* HAVE_SSL */ # endif /* HAVE_DNSSD */ +#else + _cups_getdata_t data; /* Data for callback */ #endif /* HAVE_DNSSD || HAVE_AVAHI */ + const char *home; /* HOME environment variable */ + char filename[1024]; /* Local lpoptions file */ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ DEBUG_printf(("cups_enum_dests(flags=%x, msec=%d, cancel=%p, type=%x, mask=%x, cb=%p, user_data=%p)", flags, msec, (void *)cancel, type, mask, (void *)cb, (void *)user_data)); @@ -3598,12 +3450,47 @@ cups_enum_dests( } /* - * Get ready to enumerate... + * Load the /etc/cups/lpoptions and ~/.cups/lpoptions files... */ -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) memset(&data, 0, sizeof(data)); + if ((user_default = _cupsUserDefault(data.def_name, sizeof(data.def_name))) == NULL) + { + const char *defprinter = cupsGetDefault2(http); + /* Server default, if any */ + + if (defprinter) + strlcpy(data.def_name, defprinter, sizeof(data.def_name)); + } + + if (data.def_name[0]) + { + /* + * Separate printer and instance name... + */ + + if ((data.def_instance = strchr(data.def_name, '/')) != NULL) + *data.def_instance++ = '\0'; + } + + DEBUG_printf(("1cups_enum_dests: def_name=\"%s\", def_instance=\"%s\"", data.def_name, data.def_instance)); + + snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); + data.num_dests = cups_get_dests(filename, NULL, NULL, 1, user_default != NULL, data.num_dests, &data.dests); + + if ((home = getenv("HOME")) != NULL) + { + snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home); + + data.num_dests = cups_get_dests(filename, NULL, NULL, 1, user_default != NULL, data.num_dests, &data.dests); + } + + /* + * Get ready to enumerate... + */ + +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) data.type = type; data.mask = mask; data.cb = cb; @@ -3619,29 +3506,17 @@ cups_enum_dests( num_dests = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, &dests, type, mask); - if ((user_default = _cupsUserDefault(name, sizeof(name))) != NULL) - defprinter = name; - else if ((defprinter = cupsGetDefault2(http)) != NULL) - { - strlcpy(name, defprinter, sizeof(name)); - defprinter = name; - } - - if (defprinter) + if (data.def_name[0]) { /* - * Separate printer and instance name... + * Lookup the named default printer and instance and make it the default... */ - if ((instance = strchr(name, '/')) != NULL) - *instance++ = '\0'; - - /* - * Lookup the printer and instance and make it the default... - */ - - if ((dest = cupsGetDest(name, instance, num_dests, dests)) != NULL) + if ((dest = cupsGetDest(data.def_name, data.def_instance, num_dests, dests)) != NULL) + { + DEBUG_printf(("1cups_enum_dests: Setting is_default on \"%s/%s\".", dest->name, dest->instance)); dest->is_default = 1; + } } for (i = num_dests, dest = dests; @@ -3652,6 +3527,16 @@ cups_enum_dests( const char *device_uri; /* Device URI */ #endif /* HAVE_DNSSD || HAVE_AVAHI */ + if ((user_dest = cupsGetDest(dest->name, dest->instance, data.num_dests, data.dests)) != NULL) + { + /* + * Apply user defaults to this destination... + */ + + for (j = user_dest->num_options, option = user_dest->options; j > 0; j --, option ++) + dest->num_options = cupsAddOption(option->name, option->value, dest->num_options, &dest->options); + } + if (!(*cb)(user_data, i > 1 ? CUPS_DEST_FLAGS_MORE : CUPS_DEST_FLAGS_NONE, dest)) break; @@ -3714,6 +3599,9 @@ cups_enum_dests( if (DNSServiceCreateConnection(&data.main_ref) != kDNSServiceErr_NoError) { DEBUG_puts("1cups_enum_dests: Unable to create service browser, returning 0."); + + cupsFreeDests(data.num_dests, data.dests); + return (0); } @@ -3724,14 +3612,9 @@ cups_enum_dests( { DEBUG_puts("1cups_enum_dests: Unable to create IPP browser, returning 0."); DNSServiceRefDeallocate(data.main_ref); - return (0); - } - local_ipp_ref = data.main_ref; - if (DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipp._tcp", NULL, (DNSServiceBrowseReply)cups_dnssd_local_cb, &data) != kDNSServiceErr_NoError) - { - DEBUG_puts("1cups_enum_dests: Unable to create local IPP browser, returning 0."); - DNSServiceRefDeallocate(data.main_ref); + cupsFreeDests(data.num_dests, data.dests); + return (0); } @@ -3741,14 +3624,9 @@ cups_enum_dests( { DEBUG_puts("1cups_enum_dests: Unable to create IPPS browser, returning 0."); DNSServiceRefDeallocate(data.main_ref); - return (0); - } - local_ipps_ref = data.main_ref; - if (DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipps._tcp", NULL, (DNSServiceBrowseReply)cups_dnssd_local_cb, &data) != kDNSServiceErr_NoError) - { - DEBUG_puts("1cups_enum_dests: Unable to create local IPPS browser, returning 0."); - DNSServiceRefDeallocate(data.main_ref); + cupsFreeDests(data.num_dests, data.dests); + return (0); } # endif /* HAVE_SSL */ @@ -3757,6 +3635,9 @@ cups_enum_dests( if ((data.simple_poll = avahi_simple_poll_new()) == NULL) { DEBUG_puts("1cups_enum_dests: Unable to create Avahi poll, returning 0."); + + cupsFreeDests(data.num_dests, data.dests); + return (0); } @@ -3769,6 +3650,9 @@ cups_enum_dests( { DEBUG_puts("1cups_enum_dests: Unable to create Avahi client, returning 0."); avahi_simple_poll_free(data.simple_poll); + + cupsFreeDests(data.num_dests, data.dests); + return (0); } @@ -3779,6 +3663,9 @@ cups_enum_dests( avahi_client_free(data.client); avahi_simple_poll_free(data.simple_poll); + + cupsFreeDests(data.num_dests, data.dests); + return (0); } @@ -3791,6 +3678,9 @@ cups_enum_dests( avahi_service_browser_free(ipp_ref); avahi_client_free(data.client); avahi_simple_poll_free(data.simple_poll); + + cupsFreeDests(data.num_dests, data.dests); + return (0); } # endif /* HAVE_SSL */ @@ -3903,8 +3793,26 @@ cups_enum_dests( if ((device->type & mask) == type) { + dest = &device->dest; + + if ((user_dest = cupsGetDest(dest->name, dest->instance, data.num_dests, data.dests)) != NULL) + { + /* + * Apply user defaults to this destination... + */ + + for (j = user_dest->num_options, option = user_dest->options; j > 0; j --, option ++) + dest->num_options = cupsAddOption(option->name, option->value, dest->num_options, &dest->options); + } + + if (!strcasecmp(dest->name, data.def_name) && !data.def_instance) + { + DEBUG_printf(("1cups_enum_dests: Setting is_default on discovered \"%s\".", dest->name)); + dest->is_default = 1; + } + DEBUG_printf(("1cups_enum_dests: Add callback for \"%s\".", device->dest.name)); - if (!(*cb)(user_data, CUPS_DEST_FLAGS_NONE, &device->dest)) + if (!(*cb)(user_data, CUPS_DEST_FLAGS_NONE, dest)) { remaining = -1; break; @@ -3935,20 +3843,18 @@ cups_enum_dests( enum_finished: + cupsFreeDests(data.num_dests, data.dests); + #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) cupsArrayDelete(data.devices); # ifdef HAVE_DNSSD if (ipp_ref) DNSServiceRefDeallocate(ipp_ref); - if (local_ipp_ref) - DNSServiceRefDeallocate(local_ipp_ref); # ifdef HAVE_SSL if (ipps_ref) DNSServiceRefDeallocate(ipps_ref); - if (local_ipps_ref) - DNSServiceRefDeallocate(local_ipps_ref); # endif /* HAVE_SSL */ if (data.main_ref) @@ -4166,6 +4072,7 @@ cups_get_dests( const char *filename, /* I - File to read from */ const char *match_name, /* I - Destination name we want */ const char *match_inst, /* I - Instance name we want */ + int load_all, /* I - Load all saved destinations? */ int user_default_set, /* I - User default printer set? */ int num_dests, /* I - Number of destinations */ cups_dest_t **dests) /* IO - Destinations */ @@ -4180,7 +4087,7 @@ cups_get_dests( int linenum; /* Current line number */ - DEBUG_printf(("7cups_get_dests(filename=\"%s\", match_name=\"%s\", match_inst=\"%s\", user_default_set=%d, num_dests=%d, dests=%p)", filename, match_name, match_inst, user_default_set, num_dests, (void *)dests)); + DEBUG_printf(("7cups_get_dests(filename=\"%s\", match_name=\"%s\", match_inst=\"%s\", load_all=%d, user_default_set=%d, num_dests=%d, dests=%p)", filename, match_name, match_inst, load_all, user_default_set, num_dests, (void *)dests)); /* * Try to open the file... @@ -4248,8 +4155,7 @@ cups_get_dests( instance)); /* - * See if the primary instance of the destination exists; if not, - * ignore this entry and move on... + * Match and/or ignore missing destinations... */ if (match_name) @@ -4262,7 +4168,7 @@ cups_get_dests( dest = *dests; } - else if (cupsGetDest(name, NULL, num_dests, *dests) == NULL) + else if (!load_all && cupsGetDest(name, NULL, num_dests, *dests) == NULL) { DEBUG_puts("9cups_get_dests: Not found!"); continue; @@ -4290,8 +4196,7 @@ cups_get_dests( * Add options until we hit the end of the line... */ - dest->num_options = cupsParseOptions(lineptr, dest->num_options, - &(dest->options)); + dest->num_options = cupsParseOptions(lineptr, dest->num_options, &(dest->options)); /* * If we found what we were looking for, stop now... diff --git a/cups/testdest.c b/cups/testdest.c index 9eab8d2eff..a65e09960d 100644 --- a/cups/testdest.c +++ b/cups/testdest.c @@ -1,15 +1,9 @@ /* * CUPS destination API test program for CUPS. * - * Copyright 2012-2018 by Apple Inc. + * Copyright © 2012-2018 by Apple Inc. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * missing or damaged, see the license at "http://www.cups.org/". - * - * This file is subject to the Apple OS-Developed Software exception. + * Licensed under Apache License v2.0. See the file "LICENSE" for more information. */ /* @@ -43,17 +37,31 @@ int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { + int i; /* Looping var */ http_t *http; /* Connection to destination */ cups_dest_t *dest = NULL; /* Destination */ cups_dinfo_t *dinfo; /* Destination info */ + unsigned dflags = CUPS_DEST_FLAGS_NONE; + /* Destination flags */ if (argc < 2) - usage(NULL); + return (0); - if (!strcmp(argv[1], "--enum")) + if (!strcmp(argv[1], "--get")) + { + cups_dest_t *dests; /* Destinations */ + int num_dests = cupsGetDests2(CUPS_HTTP_DEFAULT, &dests); + /* Number of destinations */ + + for (i = 0; i < num_dests; i ++) + enum_cb(NULL, 0, dests + i); + + cupsFreeDests(num_dests, dests); + return (0); + } + else if (!strcmp(argv[1], "--enum")) { - int i; /* Looping var */ cups_ptype_t type = 0, /* Printer type filter */ mask = 0; /* Printer type mask */ @@ -103,78 +111,91 @@ main(int argc, /* I - Number of command-line arguments */ return (0); } - else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7)) - dest = cupsGetDestWithURI(NULL, argv[1]); - else if (!strcmp(argv[1], "default")) + + i = 1; + if (!strcmp(argv[i], "--device")) + { + dflags = CUPS_DEST_FLAGS_DEVICE; + i ++; + } + + if (!strncmp(argv[i], "ipp://", 6) || !strncmp(argv[i], "ipps://", 7)) + dest = cupsGetDestWithURI(NULL, argv[i]); + else if (!strcmp(argv[i], "default")) { dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL); if (dest && dest->instance) printf("default is \"%s/%s\".\n", dest->name, dest->instance); - else + else if (dest) printf("default is \"%s\".\n", dest->name); + else + puts("no default destination."); } else - dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[1], NULL); + dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[i], NULL); if (!dest) { - printf("testdest: Unable to get destination \"%s\": %s\n", argv[1], cupsLastErrorString()); + printf("testdest: Unable to get destination \"%s\": %s\n", argv[i], cupsLastErrorString()); return (1); } - if ((http = cupsConnectDest(dest, CUPS_DEST_FLAGS_NONE, 30000, NULL, NULL, 0, NULL, NULL)) == NULL) + i ++; + + if ((http = cupsConnectDest(dest, dflags, 30000, NULL, NULL, 0, NULL, NULL)) == NULL) { - printf("testdest: Unable to connect to destination \"%s\": %s\n", argv[1], cupsLastErrorString()); + printf("testdest: Unable to connect to destination \"%s\": %s\n", dest->name, cupsLastErrorString()); return (1); } if ((dinfo = cupsCopyDestInfo(http, dest)) == NULL) { - printf("testdest: Unable to get information for destination \"%s\": %s\n", argv[1], cupsLastErrorString()); + printf("testdest: Unable to get information for destination \"%s\": %s\n", dest->name, cupsLastErrorString()); return (1); } - if (argc == 2 || (!strcmp(argv[2], "supported") && argc < 6)) + if (i == argc || !strcmp(argv[i], "supported")) { - if (argc > 3) - show_supported(http, dest, dinfo, argv[3], argv[4]); + i ++; + + if ((i + 1) < argc) + show_supported(http, dest, dinfo, argv[i], argv[i + 1]); else if (argc > 2) - show_supported(http, dest, dinfo, argv[3], NULL); + show_supported(http, dest, dinfo, argv[i], NULL); else show_supported(http, dest, dinfo, NULL, NULL); } - else if (!strcmp(argv[2], "conflicts") && argc > 3) + else if (!strcmp(argv[i], "conflicts") && (i + 1) < argc) { - int i, /* Looping var */ - num_options = 0;/* Number of options */ + int num_options = 0;/* Number of options */ cups_option_t *options = NULL;/* Options */ - for (i = 3; i < argc; i ++) + for (i ++; i < argc; i ++) num_options = cupsParseOptions(argv[i], num_options, &options); show_conflicts(http, dest, dinfo, num_options, options); } - else if (!strcmp(argv[2], "default") && argc == 4) + else if (!strcmp(argv[i], "default") && (i + 1) < argc) { - show_default(http, dest, dinfo, argv[3]); + show_default(http, dest, dinfo, argv[i + 1]); } - else if (!strcmp(argv[2], "localize") && argc < 6) + else if (!strcmp(argv[i], "localize")) { - if (argc > 3) - localize(http, dest, dinfo, argv[3], argv[4]); + i ++; + if ((i + 1) < argc) + localize(http, dest, dinfo, argv[i], argv[i + 1]); else if (argc > 2) - localize(http, dest, dinfo, argv[3], NULL); + localize(http, dest, dinfo, argv[i], NULL); else localize(http, dest, dinfo, NULL, NULL); } - else if (!strcmp(argv[2], "media")) + else if (!strcmp(argv[i], "media")) { - int i; /* Looping var */ const char *name = NULL; /* Media name, if any */ unsigned flags = CUPS_MEDIA_FLAGS_DEFAULT; /* Media selection flags */ - for (i = 3; i < argc; i ++) + for (i ++; i < argc; i ++) { if (!strcmp(argv[i], "borderless")) flags = CUPS_MEDIA_FLAGS_BORDERLESS; @@ -192,19 +213,19 @@ main(int argc, /* I - Number of command-line arguments */ show_media(http, dest, dinfo, flags, name); } - else if (!strcmp(argv[2], "print") && argc > 3) + else if (!strcmp(argv[i], "print") && (i + 1) < argc) { - int i, /* Looping var */ - num_options = 0;/* Number of options */ + int num_options = 0;/* Number of options */ cups_option_t *options = NULL;/* Options */ + const char *filename = argv[i + 1]; - for (i = 4; i < argc; i ++) + for (i += 2; i < argc; i ++) num_options = cupsParseOptions(argv[i], num_options, &options); - print_file(http, dest, dinfo, argv[3], num_options, options); + print_file(http, dest, dinfo, filename, num_options, options); } else - usage(argv[2]); + usage(argv[i]); return (0); } @@ -226,13 +247,15 @@ enum_cb(void *user_data, /* I - User data (unused) */ (void)flags; if (dest->instance) - printf("%s%s/%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->instance); + printf("%s%s/%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->instance, dest->is_default ? " (Default)" : ""); else - printf("%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name); + printf("%s%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->is_default ? " (Default)" : ""); for (i = 0; i < dest->num_options; i ++) printf(" %s=\"%s\"\n", dest->options[i].name, dest->options[i].value); + puts(""); + return (1); } @@ -740,9 +763,10 @@ usage(const char *arg) /* I - Argument for usage message */ printf("testdest: Unknown option \"%s\".\n", arg); puts("Usage:"); - puts(" ./testdest name [operation ...]"); - puts(" ./testdest ipp://... [operation ...]"); - puts(" ./testdest ipps://... [operation ...]"); + puts(" ./testdest [--device] name [operation ...]"); + puts(" ./testdest [--device] ipp://... [operation ...]"); + puts(" ./testdest [--device] ipps://... [operation ...]"); + puts(" ./testdest --get"); puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n" " [medium] [large]"); puts("");