From c585706d00357dec95a60ce9e3e258775189ed6c Mon Sep 17 00:00:00 2001 From: msweet Date: Thu, 18 Feb 2016 20:32:13 +0000 Subject: Implement more of testdest unit test. Fix mapping of CUPS-Create-Local-Printer operation code. Add logging to background thread. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@13105 a1ca3aef-8c08-0410-bb20-df032aa958be --- cups/dest.c | 39 +++++++++-- cups/ipp-support.c | 4 +- cups/testdest.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++---- scheduler/ipp.c | 26 ++++++- 4 files changed, 242 insertions(+), 26 deletions(-) diff --git a/cups/dest.c b/cups/dest.c index bc9d71141..1682346b4 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -826,11 +826,10 @@ _cupsCreateDest(const char *name, /* I - Printer name */ ipp_t *request, /* CUPS-Create-Local-Printer request */ *response; /* CUPS-Create-Local-Printer response */ ipp_attribute_t *attr; /* printer-uri-supported attribute */ + ipp_pstate_t state = IPP_PSTATE_STOPPED; + /* printer-state value */ - (void)info; - (void)device_id; - if (!name || !device_uri || !uri || urisize < 32) return (NULL); @@ -851,14 +850,40 @@ _cupsCreateDest(const char *name, /* I - Printer name */ response = cupsDoRequest(http, request, "/"); - httpClose(http); - if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) strlcpy(uri, ippGetString(attr, 0, NULL), urisize); + else + { + ippDelete(response); + httpClose(http); + return (NULL); + } + + if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) + state = (ipp_pstate_t)ippGetInteger(attr, 0); + + while (state == IPP_PSTATE_STOPPED && cupsLastError() == IPP_STATUS_OK) + { + sleep(1); + ippDelete(response); + + 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()); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "printer-state"); + + response = cupsDoRequest(http, request, "/"); + + if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) + state = (ipp_pstate_t)ippGetInteger(attr, 0); + } ippDelete(response); - return (attr ? uri : NULL); + httpClose(http); + + return (uri); } @@ -3498,7 +3523,7 @@ cups_dnssd_resolve( if (cb) (*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_DEFAULT, cups_dnssd_resolve_cb, &resolve)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to resolve printer-uri."), 1); diff --git a/cups/ipp-support.c b/cups/ipp-support.c index 9928a91d4..40c01eb60 100644 --- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -2051,8 +2051,8 @@ ippOpString(ipp_op_t op) /* I - Operation ID */ return ("windows-ext"); else if (op >= IPP_OP_CUPS_GET_DEFAULT && op <= IPP_OP_CUPS_GET_PPD) return (ipp_cups_ops[op - IPP_OP_CUPS_GET_DEFAULT]); - else if (op == IPP_OP_CUPS_GET_DOCUMENT) - return (ipp_cups_ops2[0]); + else if (op >= IPP_OP_CUPS_GET_DOCUMENT && op <= IPP_OP_CUPS_CREATE_LOCAL_PRINTER) + return (ipp_cups_ops2[op - IPP_OP_CUPS_GET_DOCUMENT]); /* * No, build an "0xxxxx" operation string... diff --git a/cups/testdest.c b/cups/testdest.c index 74cdd6555..50835eceb 100644 --- a/cups/testdest.c +++ b/cups/testdest.c @@ -1,7 +1,7 @@ /* * CUPS destination API test program for CUPS. * - * Copyright 2016 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 @@ -17,6 +17,7 @@ */ #include +#include #include "cups.h" @@ -149,9 +150,14 @@ main(int argc, /* I - Number of command-line arguments */ { show_default(http, dest, dinfo, argv[3]); } - else if (!strcmp(argv[2], "localize") && argc > 3 && argc < 6) + else if (!strcmp(argv[2], "localize") && argc < 6) { - localize(http, dest, dinfo, argv[3], argv[4]); + if (argc > 3) + localize(http, dest, dinfo, argv[3], argv[4]); + else if (argc > 2) + localize(http, dest, dinfo, argv[3], NULL); + else + localize(http, dest, dinfo, NULL, NULL); } else if (!strcmp(argv[2], "media")) { @@ -234,11 +240,128 @@ localize(http_t *http, /* I - Connection to destination */ const char *option, /* I - Option */ const char *value) /* I - Value, if any */ { - (void)http; - (void)dest; - (void)dinfo; - (void)option; - (void)value; + ipp_attribute_t *attr; /* Attribute */ + int i, /* Looping var */ + count; /* Number of values */ + + + if (!option) + { + attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes"); + if (attr) + { + count = ippGetCount(attr); + for (i = 0; i < count; i ++) + localize(http, dest, dinfo, ippGetString(attr, i, NULL), NULL); + } + else + { + static const char * const options[] = + { /* List of standard options */ + CUPS_COPIES, + CUPS_FINISHINGS, + CUPS_MEDIA, + CUPS_NUMBER_UP, + CUPS_ORIENTATION, + CUPS_PRINT_COLOR_MODE, + CUPS_PRINT_QUALITY, + CUPS_SIDES + }; + + puts("No job-creation-attributes-supported attribute, probing instead."); + + for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++) + if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL)) + localize(http, dest, dinfo, options[i], NULL); + } + } + else if (!value) + { + printf("%s (%s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option)); + + if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL) + { + count = ippGetCount(attr); + + switch (ippGetValueTag(attr)) + { + case IPP_TAG_INTEGER : + for (i = 0; i < count; i ++) + printf(" %d\n", ippGetInteger(attr, i)); + break; + + case IPP_TAG_ENUM : + for (i = 0; i < count; i ++) + printf(" %s\n", ippEnumString(option, ippGetInteger(attr, i))); + break; + + case IPP_TAG_RANGE : + for (i = 0; i < count; i ++) + { + int upper, lower = ippGetRange(attr, i, &upper); + + printf(" %d-%d\n", lower, upper); + } + break; + + case IPP_TAG_RESOLUTION : + for (i = 0; i < count; i ++) + { + int xres, yres; + ipp_res_t units; + xres = ippGetResolution(attr, i, &yres, &units); + + if (xres == yres) + printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); + else + printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); + } + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + for (i = 0; i < count; i ++) + printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL))); + break; + + case IPP_TAG_STRING : + for (i = 0; i < count; i ++) + { + int j, len; + unsigned char *data = ippGetOctetString(attr, i, &len); + + fputs(" ", stdout); + for (j = 0; j < len; j ++) + { + if (data[j] < ' ' || data[j] >= 0x7f) + printf("<%02X>", data[j]); + else + putchar(data[j]); + } + putchar('\n'); + } + break; + + case IPP_TAG_BOOLEAN : + break; + + default : + printf(" %s\n", ippTagString(ippGetValueTag(attr))); + break; + } + } + + } + else + puts(cupsLocalizeDestValue(http, dest, dinfo, option, value)); } @@ -254,12 +377,59 @@ print_file(http_t *http, /* I - Connection to destination */ int num_options, /* I - Number of options */ cups_option_t *options) /* I - Options */ { - (void)http; - (void)dest; - (void)dinfo; - (void)filename; - (void)num_options; - (void)options; + cups_file_t *fp; /* File to print */ + int job_id; /* Job ID */ + ipp_status_t status; /* Submission status */ + const char *title; /* Title of job */ + char buffer[32768]; /* File buffer */ + ssize_t bytes; /* Bytes read/to write */ + + + if ((fp = cupsFileOpen(filename, "r")) == NULL) + { + printf("Unable to open \"%s\": %s\n", filename, strerror(errno)); + return; + } + + if ((title = strrchr(filename, '/')) != NULL) + title ++; + else + title = filename; + + if ((status = cupsCreateDestJob(http, dest, dinfo, &job_id, title, num_options, options)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) + { + printf("Unable to create job: %s\n", cupsLastErrorString()); + cupsFileClose(fp); + return; + } + + printf("Created job ID: %d\n", job_id); + + if (cupsStartDestDocument(http, dest, dinfo, job_id, title, CUPS_FORMAT_AUTO, 0, NULL, 1) != HTTP_STATUS_CONTINUE) + { + printf("Unable to send document: %s\n", cupsLastErrorString()); + cupsFileClose(fp); + return; + } + + while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) + { + if (cupsWriteRequestData(http, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE) + { + printf("Unable to write document data: %s\n", cupsLastErrorString()); + break; + } + } + + cupsFileClose(fp); + + if ((status = cupsFinishDestDocument(http, dest, dinfo)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) + { + printf("Unable to send document: %s\n", cupsLastErrorString()); + return; + } + + puts("Job queued."); } @@ -510,7 +680,6 @@ show_supported(http_t *http, /* I - Connection to destination */ puts("YES"); else puts("NO"); - } diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 8c266c7c9..6ccdc6889 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -5229,8 +5229,13 @@ create_local_bg_thread( * Try connecting to the printer... */ + cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Generating PPD file from \"%s\"...", printer->name, printer->device_uri); + if (httpSeparateURI(HTTP_URI_CODING_ALL, printer->device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Bad device URI \"%s\".", printer->name, printer->device_uri); return (NULL); + } if (!strcmp(scheme, "ipps") || port == 443) encryption = HTTP_ENCRYPTION_ALWAYS; @@ -5238,18 +5243,25 @@ create_local_bg_thread( encryption = HTTP_ENCRYPTION_IF_REQUESTED; if ((http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to connect to %s:%d: %s", printer->name, host, port, cupsLastErrorString()); return (NULL); + } /* * Query the printer for its capabilities... */ + cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Connected to %s:%d, sending Get-Printer-Attributes request...", printer->name, host, port); + request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer->device_uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "all"); response = cupsDoRequest(http, request, resource); + cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Get-Printer-Attributes returned %s", printer->name, ippErrorString(cupsLastError())); + // TODO: Grab printer icon file... httpClose(http); @@ -5269,11 +5281,15 @@ create_local_bg_thread( cupsdSetString(&printer->geo_location, ippGetString(attr, 0, NULL)); if ((from = cupsFileOpen(fromppd, "r")) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to read generated PPD: %s", printer->name, strerror(errno)); return (NULL); + } snprintf(toppd, sizeof(toppd), "%s/ppd/%s.ppd", ServerRoot, printer->name); if ((to = cupsdCreateConfFile(toppd, ConfigFilePerm)) == NULL) { + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to create PPD for printer: %s", printer->name, strerror(errno)); cupsFileClose(from); return (NULL); } @@ -5284,12 +5300,18 @@ create_local_bg_thread( cupsFileClose(from); if (!cupsdCloseCreatedConfFile(to, toppd)) { - printer->state = IPP_PSTATE_IDLE; - printer->accepting = 1; + printer->config_time = time(NULL); + printer->state = IPP_PSTATE_IDLE; + printer->accepting = 1; cupsdSetPrinterAttrs(printer); + + cupsdAddEvent(CUPSD_EVENT_PRINTER_CONFIG, printer, NULL, "Printer \"%s\" is now available.", printer->name); + cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" is now available.", printer->name); } } + else + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: PPD creation failed.", printer->name); return (NULL); } -- cgit v1.2.3