From 46385a1a1709ead60448003de218a288d7006a60 Mon Sep 17 00:00:00 2001 From: msweet Date: Wed, 17 Feb 2016 22:46:40 +0000 Subject: [PATCH] More work on temporary queues - implement support for them in the cupsDest APIs, add some duplicate printer checking code, and implement the --enum unit test. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@13099 a1ca3aef-8c08-0410-bb20-df032aa958be --- cups/dest-job.c | 39 +++++++++------ cups/dest-options.c | 6 +-- cups/dest.c | 111 ++++++++++++++++++++--------------------- cups/testdest.c | 80 +++++++++++++++++++++++++++-- doc/help/spec-ipp.html | 2 + scheduler/ipp.c | 12 +++++ 6 files changed, 170 insertions(+), 80 deletions(-) diff --git a/cups/dest-job.c b/cups/dest-job.c index 40f041237..759c5b354 100644 --- a/cups/dest-job.c +++ b/cups/dest-job.c @@ -1,9 +1,7 @@ /* - * "$Id$" - * * Destination job support for CUPS. * - * Copyright 2012-2014 by Apple Inc. + * Copyright 2012-2016 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -26,8 +24,9 @@ * * The "job_id" is the number returned by cupsCreateDestJob. * - * Returns IPP_STATUS_OK on success and IPP_NOT_AUTHORIZED or IPP_FORBIDDEN on - * failure. + * Returns @code IPP_STATUS_OK@ on success and + * @code IPP_STATUS_ERRPR_NOT_AUTHORIZED@ or + * @code IPP_STATUS_ERROR_FORBIDDEN@ on failure. * * @since CUPS 1.6/OS X 10.8@ */ @@ -37,13 +36,26 @@ cupsCancelDestJob(http_t *http, /* I - Connection to destination */ cups_dest_t *dest, /* I - Destination */ int job_id) /* I - Job ID */ { - /* TODO: Needs to be implemented! */ - /* Probably also needs to be revved to accept cups_dinfo_t... */ - (void)http; - (void)dest; - (void)job_id; + cups_dinfo_t *info; /* Destination information */ + + + if ((info = cupsCopyDestInfo(http, dest)) != NULL) + { + ipp_t *request; /* Cancel-Job request */ + + request = ippNewRequest(IPP_OP_CANCEL_JOB); + + ippSetVersion(request, info->version / 10, info->version % 10); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri); + ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); - return (IPP_STATUS_ERROR_NOT_FOUND); + ippDelete(cupsDoRequest(http, request, info->resource)); + cupsFreeDestInfo(info); + } + + return (cupsLastError()); } @@ -357,8 +369,3 @@ cupsStartDestDocument( return (status); } - - -/* - * End of "$Id$". - */ diff --git a/cups/dest-options.c b/cups/dest-options.c index 442ca5dc6..43d231b2b 100644 --- a/cups/dest-options.c +++ b/cups/dest-options.c @@ -1,9 +1,7 @@ /* - * "$Id$" - * * Destination option/media support for CUPS. * - * Copyright 2012-2014 by Apple Inc. + * Copyright 2012-2016 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -706,6 +704,7 @@ cupsFindDestDefault( return (ippFindAttribute(dinfo->attrs, name, IPP_TAG_ZERO)); } + /* * 'cupsFindDestReady()' - Find the default value(s) for the given option. * @@ -748,6 +747,7 @@ cupsFindDestReady( return (ippFindAttribute(dinfo->ready_attrs, name, IPP_TAG_ZERO)); } + /* * 'cupsFindDestSupported()' - Find the default value(s) for the given option. * diff --git a/cups/dest.c b/cups/dest.c index f54d5eec2..2dc88500d 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -589,26 +589,39 @@ cupsConnectDest( * Grab the printer URI... */ - if ((uri = cupsGetOption("printer-uri-supported", dest->num_options, - dest->options)) == NULL) + if ((uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options)) == NULL) { - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0); + if ((uri = cupsGetOption("resolved-device-uri", dest->num_options, dest->options)) == NULL) + { + if ((uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL) + { +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + if (strstr(uri, "._tcp")) + uri = cups_dnssd_resolve(dest, uri, msec, cancel, cb, user_data); + } +#endif /* HAVE_DNSSD || HAVE_AVAHI */ + } - if (cb) - (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, - dest); + if (uri) + uri = _cupsCreateDest(dest->name, cupsGetOption("printer-info", dest->num_options, dest->options), NULL, uri, tempresource, sizeof(tempresource)); - return (NULL); + if (uri) + { + dest->num_options = cupsAddOption("printer-uri-supported", uri, dest->num_options, &dest->options); + + uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options); + } } -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - if (strstr(uri, "._tcp")) + if (!uri) { - if ((uri = cups_dnssd_resolve(dest, uri, msec, cancel, cb, - user_data)) == NULL) - return (NULL); + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0); + + if (cb) + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, dest); + + return (NULL); } -#endif /* HAVE_DNSSD || HAVE_AVAHI */ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), @@ -628,16 +641,14 @@ cupsConnectDest( */ if (cb) - (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_RESOLVING, - dest); + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_RESOLVING, dest); snprintf(portstr, sizeof(portstr), "%d", port); if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portstr)) == NULL) { if (cb) - (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, - dest); + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, dest); return (NULL); } @@ -647,8 +658,7 @@ cupsConnectDest( httpAddrFreeList(addrlist); if (cb) - (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_CANCELED, - dest); + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_CANCELED, dest); return (NULL); } @@ -662,8 +672,7 @@ cupsConnectDest( else encryption = HTTP_ENCRYPTION_IF_REQUESTED; - http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, encryption, 1, 0, - NULL); + http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, encryption, 1, 0, NULL); httpAddrFreeList(addrlist); /* @@ -678,17 +687,14 @@ cupsConnectDest( else { if (cb) - (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_CONNECTING, - dest); + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_CONNECTING, dest); if (!httpReconnect2(http, msec, cancel) && cb) { if (cancel && *cancel) - (*cb)(user_data, - CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_CONNECTING, dest); + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_CONNECTING, dest); else - (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, - dest); + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, dest); } else if (cb) (*cb)(user_data, CUPS_DEST_FLAGS_NONE, dest); @@ -3327,22 +3333,28 @@ cups_dnssd_query_cb( */ const char *start, *next; /* Pointer into value */ - int have_pdf = 0; /* Have PDF? */ + int have_pdf = 0, /* Have PDF? */ + have_raster = 0;/* Have raster format support? */ for (start = value; start && *start; start = next) { - if (!_cups_strncasecmp(start, "application/pdf", 15) && - (!start[15] || start[15] == ',')) + if (!_cups_strncasecmp(start, "application/pdf", 15) && (!start[15] || start[15] == ',')) { have_pdf = 1; break; } + else if ((!_cups_strncasecmp(start, "image/pwg-raster", 16) && (!start[16] || start[16] == ',')) || + (!_cups_strncasecmp(start, "image/urf", 9) && (!start[9] || start[9] == ','))) + { + have_raster = 1; + break; + } if ((next = strchr(start, ',')) != NULL) next ++; } - if (!have_pdf) + if (!have_pdf && !have_raster) device->state = _CUPS_DNSSD_INCOMPATIBLE; } else if (!_cups_strcasecmp(key, "printer-type")) @@ -3408,31 +3420,21 @@ cups_dnssd_query_cb( * Save the printer-xxx values... */ - device->dest.num_options = cupsAddOption("printer-info", name, - device->dest.num_options, - &device->dest.options); + device->dest.num_options = cupsAddOption("printer-info", name, device->dest.num_options, &device->dest.options); if (make_and_model[0]) { strlcat(make_and_model, " ", sizeof(make_and_model)); strlcat(make_and_model, model, sizeof(make_and_model)); - device->dest.num_options = cupsAddOption("printer-make-and-model", - make_and_model, - device->dest.num_options, - &device->dest.options); + device->dest.num_options = cupsAddOption("printer-make-and-model", make_and_model, device->dest.num_options, &device->dest.options); } else - device->dest.num_options = cupsAddOption("printer-make-and-model", - model, - device->dest.num_options, - &device->dest.options); + device->dest.num_options = cupsAddOption("printer-make-and-model", model, device->dest.num_options, &device->dest.options); device->type = type; snprintf(value, sizeof(value), "%u", type); - device->dest.num_options = cupsAddOption("printer-type", value, - device->dest.num_options, - &device->dest.options); + device->dest.num_options = cupsAddOption("printer-type", value, device->dest.num_options, &device->dest.options); /* * Save the URI... @@ -3443,11 +3445,9 @@ cups_dnssd_query_cb( !strcmp(device->regtype, "_ipps._tcp") ? "ipps" : "ipp", NULL, uriname, 0, saw_printer_type ? "/cups" : "/"); - DEBUG_printf(("6cups_dnssd_query: printer-uri-supported=\"%s\"", uri)); + DEBUG_printf(("6cups_dnssd_query: device-uri=\"%s\"", uri)); - device->dest.num_options = cupsAddOption("printer-uri-supported", uri, - device->dest.num_options, - &device->dest.options); + device->dest.num_options = cupsAddOption("device-uri", uri, device->dest.num_options, &device->dest.options); } else DEBUG_printf(("6cups_dnssd_query: Ignoring TXT record for '%s'.", @@ -3496,15 +3496,12 @@ cups_dnssd_resolve( (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_RESOLVING, dest); - if ((uri = _httpResolveURI(uri, tempuri, sizeof(tempuri), - _HTTP_RESOLVE_FQDN, cups_dnssd_resolve_cb, - &resolve)) == NULL) + if ((uri = _httpResolveURI(uri, tempuri, sizeof(tempuri), _HTTP_RESOLVE_FQDN, cups_dnssd_resolve_cb, &resolve)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to resolve printer-uri."), 1); if (cb) - (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, - dest); + (*cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, dest); return (NULL); } @@ -3513,11 +3510,9 @@ cups_dnssd_resolve( * Save the resolved URI... */ - dest->num_options = cupsAddOption("printer-uri-supported", uri, - dest->num_options, &dest->options); + dest->num_options = cupsAddOption("resolved-device-uri", uri, dest->num_options, &dest->options); - return (cupsGetOption("printer-uri-supported", dest->num_options, - dest->options)); + return (cupsGetOption("resolved-device-uri", dest->num_options, dest->options)); } diff --git a/cups/testdest.c b/cups/testdest.c index aefe8818e..c940d3b1a 100644 --- a/cups/testdest.c +++ b/cups/testdest.c @@ -1,9 +1,7 @@ /* - * "$Id$" - * * CUPS destination API test program for CUPS. * - * Copyright 2014 by Apple Inc. + * Copyright 2016 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -26,6 +24,7 @@ * Local functions... */ +static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest); static void localize(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value); static void print_file(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *filename, int num_options, cups_option_t *options); static void show_conflicts(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, int num_options, cups_option_t *options); @@ -53,6 +52,54 @@ main(int argc, /* I - Number of command-line arguments */ if (!strcmp(argv[1], "--enum")) { + int i; /* Looping var */ + cups_ptype_t type = 0, /* Printer type filter */ + mask = 0; /* Printer type mask */ + + + for (i = 2; i < argc; i ++) + { + if (!strcmp(argv[i], "grayscale")) + { + type |= CUPS_PRINTER_BW; + mask |= CUPS_PRINTER_BW; + } + else if (!strcmp(argv[i], "color")) + { + type |= CUPS_PRINTER_COLOR; + mask |= CUPS_PRINTER_COLOR; + } + else if (!strcmp(argv[i], "duplex")) + { + type |= CUPS_PRINTER_DUPLEX; + mask |= CUPS_PRINTER_DUPLEX; + } + else if (!strcmp(argv[i], "staple")) + { + type |= CUPS_PRINTER_STAPLE; + mask |= CUPS_PRINTER_STAPLE; + } + else if (!strcmp(argv[i], "small")) + { + type |= CUPS_PRINTER_SMALL; + mask |= CUPS_PRINTER_SMALL; + } + else if (!strcmp(argv[i], "medium")) + { + type |= CUPS_PRINTER_MEDIUM; + mask |= CUPS_PRINTER_MEDIUM; + } + else if (!strcmp(argv[i], "large")) + { + type |= CUPS_PRINTER_LARGE; + mask |= CUPS_PRINTER_LARGE; + } + else + usage(argv[i]); + } + + cupsEnumDests(CUPS_DEST_FLAGS_NONE, 5000, NULL, type, mask, enum_cb, NULL); + return (0); } else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7)) @@ -149,6 +196,33 @@ main(int argc, /* I - Number of command-line arguments */ } +/* + * 'enum_cb()' - Print the results from the enumeration of destinations. + */ + +static int /* O - 1 to continue */ +enum_cb(void *user_data, /* I - User data (unused) */ + unsigned flags, /* I - Flags */ + cups_dest_t *dest) /* I - Destination */ +{ + int i; /* Looping var */ + + + (void)user_data; + (void)flags; + + if (dest->instance) + printf("%s/%s:\n", dest->name, dest->instance); + else + printf("%s:\n", dest->name); + + for (i = 0; i < dest->num_options; i ++) + printf(" %s=\"%s\"\n", dest->options[i].name, dest->options[i].value); + + return (1); +} + + /* * 'localize()' - Localize an option and value. */ diff --git a/doc/help/spec-ipp.html b/doc/help/spec-ipp.html index 7095443b5..16af6dfae 100644 --- a/doc/help/spec-ipp.html +++ b/doc/help/spec-ipp.html @@ -1334,6 +1334,8 @@ CUPS-Get-PPDs Response:

At a minimum, the scheduler requires a name and URI for the Printer to add. When successful, the local "printer-uri" values are returned and may be used by the Client to submit Job Creation Requests, monitor for state changes, and so forth.

+

If the named printer already exists, the scheduler will reject the request with the 'client-error-not-possible' status code.

+

Access Rights: The authenticated user performing this operation MUST be a Local User of the system, and the request MUST be made over a local (domain socket or loopback interface) address. Otherwise, the request will be rejected with the 'client-error-forbidden' status code.

CUPS-Create-Local-Printer Request

diff --git a/scheduler/ipp.c b/scheduler/ipp.c index bbd505859..8c266c7c9 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -5382,6 +5382,16 @@ create_local_printer( printer_info = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT); printer_location = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT); + /* + * See if the printer already exists... + */ + + if ((printer = cupsdFindDest(name)) != NULL) + { + send_ipp_status(con, IPP_STATUS_ERROR_NOT_POSSIBLE, _("Printer \"%s\" already exists."), name); + goto add_printer_attributes; + } + /* * Create the printer... */ @@ -5415,6 +5425,8 @@ create_local_printer( send_ipp_status(con, IPP_STATUS_OK, _("Local printer created.")); + add_printer_attributes: + ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting); ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", printer->state); add_printer_state_reasons(con, printer); -- 2.39.2