From 68506acf467b79f1fde053b85edbfe1ec30b2f85 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Wed, 23 Jun 2021 17:45:40 -0400 Subject: [PATCH] Support the 'everywhere' model in cupsd (Issue #201) --- CHANGES.md | 1 + cgi-bin/admin.c | 87 ++---------------------------------- scheduler/ipp.c | 20 ++++++++- systemv/lpadmin.c | 111 +--------------------------------------------- 4 files changed, 24 insertions(+), 195 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5b67d81713..f7aef3c69d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -48,6 +48,7 @@ CUPS v2.4rc1 (Pending) and values are retained on an error (Issue #195) - Hardened `ippReadIO` to prevent invalid IPP messages from being propagated (Issue #195, Issue #196) +- The scheduler now supports the "everywhere" model directly (Issue #201) - Documentation fixes (Issue #92, Issue #163, Issue #177, Issue #184) - Localization updates (Issue #123, Issue #129, Issue #134, Issue #146, Issue #164) diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index c6489389f5..63b956e628 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -1,7 +1,8 @@ /* * Administration CGI for CUPS. * - * Copyright © 2007-2019 by Apple Inc. + * Copyright © 2021 by OpenPrinting + * Copyright © 2007-2021 by Apple Inc. * Copyright © 1997-2007 by Easy Software Products. * * Licensed under Apache License v2.0. See the file "LICENSE" for more @@ -50,7 +51,6 @@ static void do_set_sharing(http_t *http); static char *get_option_value(ppd_file_t *ppd, const char *name, char *buffer, size_t bufsize); static double get_points(double number, const char *uval); -static char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize); /* @@ -1125,9 +1125,7 @@ do_am_printer(http_t *http, /* I - HTTP connection */ if (!file) { var = cgiGetVariable("PPD_NAME"); - if (!strcmp(var, "everywhere")) - get_printer_ppd(cgiGetVariable("DEVICE_URI"), evefile, sizeof(evefile)); - else if (strcmp(var, "__no_change__")) + if (strcmp(var, "__no_change__")) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name", NULL, var); } @@ -3735,82 +3733,3 @@ get_points(double number, /* I - Original number */ else /* Points */ return (number); } - - -/* - * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI. - */ - -static char * /* O - Filename or NULL */ -get_printer_ppd(const char *uri, /* I - Printer URI */ - char *buffer, /* I - Filename buffer */ - size_t bufsize) /* I - Size of filename buffer */ -{ - http_t *http; /* Connection to printer */ - ipp_t *request, /* Get-Printer-Attributes request */ - *response; /* Get-Printer-Attributes response */ - char resolved[1024], /* Resolved URI */ - scheme[32], /* URI scheme */ - userpass[256], /* Username:password */ - host[256], /* Hostname */ - resource[256]; /* Resource path */ - int port; /* Port number */ - static const char * const pattrs[] = /* Printer attributes we need */ - { - "all", - "media-col-database" - }; - - - /* - * Connect to the printer... - */ - - if (strstr(uri, "._tcp")) - { - /* - * Resolve URI... - */ - - if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL)) - { - fprintf(stderr, "ERROR: Unable to resolve \"%s\".\n", uri); - return (NULL); - } - - uri = resolved; - } - - if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) - { - fprintf(stderr, "ERROR: Bad printer URI \"%s\".\n", uri); - return (NULL); - } - - http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); - if (!http) - { - fprintf(stderr, "ERROR: Unable to connect to \"%s:%d\": %s\n", host, port, cupsLastErrorString()); - return (NULL); - } - - /* - * Send a Get-Printer-Attributes request... - */ - - request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs); - response = cupsDoRequest(http, request, resource); - - if (!_ppdCreateFromIPP(buffer, bufsize, response)) - fprintf(stderr, "ERROR: Unable to create PPD file: %s\n", strerror(errno)); - - ippDelete(response); - httpClose(http); - - if (buffer[0]) - return (buffer); - else - return (NULL); -} diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 2104d46bbc..dd5172c668 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -2,7 +2,7 @@ * IPP routines for the CUPS scheduler. * * Copyright © 2020-2021 by OpenPrinting - * Copyright © 2007-2019 by Apple Inc. + * Copyright © 2007-2021 by Apple Inc. * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -73,6 +73,7 @@ static void copy_subscription_attrs(cupsd_client_t *con, cups_array_t *ra, cups_array_t *exclude); static void create_job(cupsd_client_t *con, ipp_attribute_t *uri); +static void *create_local_bg_thread(cupsd_printer_t *printer); static void create_local_printer(cupsd_client_t *con); static cups_array_t *create_requested_array(ipp_t *request); static void create_subscriptions(cupsd_client_t *con, ipp_attribute_t *uri); @@ -2692,7 +2693,22 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ need_restart_job = 1; changed_driver = 1; - if (!strcmp(ppd_name, "raw")) + if (!strcmp(ppd_name, "everywhere")) + { + // Create IPP Everywhere PPD... + if (!printer->device_uri || (strncmp(printer->device_uri, "dnssd://", 8) && strncmp(printer->device_uri, "ipp://", 6) && strncmp(printer->device_uri, "ipps://", 7) && strncmp(printer->device_uri, "ippusb://", 9))) + { + send_ipp_status(con, IPP_INTERNAL_ERROR, _("IPP Everywhere driver requires an IPP connection.")); + if (!modify) + cupsdDeletePrinter(printer, 0); + + return; + } + + // Run a background thread to create the PPD... + _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, printer); + } + else if (!strcmp(ppd_name, "raw")) { /* * Raw driver, remove any existing PPD file. diff --git a/systemv/lpadmin.c b/systemv/lpadmin.c index 00d0fc7c72..355dc8391c 100644 --- a/systemv/lpadmin.c +++ b/systemv/lpadmin.c @@ -2,7 +2,7 @@ * "lpadmin" command for CUPS. * * Copyright © 2021 by OpenPrinting. - * Copyright © 2007-2019 by Apple Inc. + * Copyright © 2007-2021 by Apple Inc. * Copyright © 1997-2006 by Easy Software Products. * * Licensed under Apache License v2.0. See the file "LICENSE" for more @@ -29,7 +29,6 @@ static int delete_printer_from_class(http_t *http, char *printer, static int delete_printer_option(http_t *http, char *printer, char *option); static int enable_printer(http_t *http, char *printer); -static char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize, int *num_options, cups_option_t **options); static cups_ptype_t get_printer_type(http_t *http, char *printer, char *uri, size_t urisize); static int set_printer_options(http_t *http, char *printer, @@ -626,14 +625,7 @@ main(int argc, /* I - Number of command-line arguments */ return (1); #endif /* __APPLE__ */ } - else if (ppd_name && !strcmp(ppd_name, "everywhere") && device_uri) - { - if ((file = get_printer_ppd(device_uri, evefile, sizeof(evefile), &num_options, &options)) == NULL) - return (1); - - num_options = cupsRemoveOption("ppd-name", num_options, &options); - } - else if (ppd_name || file) + else if ((ppd_name && strcmp(ppd_name, "everywhere")) || file) { _cupsLangPuts(stderr, _("lpadmin: Printer drivers are deprecated and will stop working in a future version of CUPS.")); } @@ -1157,105 +1149,6 @@ enable_printer(http_t *http, /* I - Server connection */ } -/* - * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI. - */ - -static char * /* O - Filename or NULL */ -get_printer_ppd( - const char *uri, /* I - Printer URI */ - char *buffer, /* I - Filename buffer */ - size_t bufsize, /* I - Size of filename buffer */ - int *num_options, /* IO - Number of options */ - cups_option_t **options) /* IO - Options */ -{ - http_t *http; /* Connection to printer */ - ipp_t *request, /* Get-Printer-Attributes request */ - *response; /* Get-Printer-Attributes response */ - ipp_attribute_t *attr; /* Attribute from response */ - char resolved[1024], /* Resolved URI */ - scheme[32], /* URI scheme */ - userpass[256], /* Username:password */ - host[256], /* Hostname */ - resource[256]; /* Resource path */ - int port; /* Port number */ - static const char * const pattrs[] = /* Attributes to use */ - { - "all", - "media-col-database" - }; - - - /* - * Connect to the printer... - */ - - if (strstr(uri, "._tcp")) - { - /* - * Resolve URI... - */ - - if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL)) - { - _cupsLangPrintf(stderr, _("%s: Unable to resolve \"%s\"."), "lpadmin", uri); - return (NULL); - } - - uri = resolved; - } - - if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) - { - _cupsLangPrintf(stderr, _("%s: Bad printer URI \"%s\"."), "lpadmin", uri); - return (NULL); - } - - http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); - if (!http) - { - _cupsLangPrintf(stderr, _("%s: Unable to connect to \"%s:%d\": %s"), "lpadmin", host, port, cupsLastErrorString()); - return (NULL); - } - - /* - * Send a Get-Printer-Attributes request... - */ - - request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs); - response = cupsDoRequest(http, request, resource); - - if (cupsLastError() >= IPP_STATUS_REDIRECTION_OTHER_SITE) - { - _cupsLangPrintf(stderr, _("%s: Unable to query printer: %s"), "lpadmin", cupsLastErrorString()); - buffer[0] = '\0'; - } - else if (_ppdCreateFromIPP(buffer, bufsize, response)) - { - if (!cupsGetOption("printer-geo-location", *num_options, *options) && (attr = ippFindAttribute(response, "printer-geo-location", IPP_TAG_URI)) != NULL) - *num_options = cupsAddOption("printer-geo-location", ippGetString(attr, 0, NULL), *num_options, options); - - if (!cupsGetOption("printer-info", *num_options, *options) && (attr = ippFindAttribute(response, "printer-info", IPP_TAG_TEXT)) != NULL) - *num_options = cupsAddOption("printer-info", ippGetString(attr, 0, NULL), *num_options, options); - - if (!cupsGetOption("printer-location", *num_options, *options) && (attr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT)) != NULL) - *num_options = cupsAddOption("printer-location", ippGetString(attr, 0, NULL), *num_options, options); - } - else - _cupsLangPrintf(stderr, _("%s: Unable to create PPD file: %s"), "lpadmin", strerror(errno)); - - ippDelete(response); - httpClose(http); - - if (buffer[0]) - return (buffer); - else - return (NULL); -} - - /* * 'get_printer_type()' - Determine the printer type and URI. */