Skip to content

Commit

Permalink
Support the 'everywhere' model in cupsd (Issue #201)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed Jun 23, 2021
1 parent 540b657 commit 68506ac
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 195 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
87 changes: 3 additions & 84 deletions cgi-bin/admin.c
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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);


/*
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
20 changes: 18 additions & 2 deletions scheduler/ipp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down
111 changes: 2 additions & 109 deletions systemv/lpadmin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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."));
}
Expand Down Expand Up @@ -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.
*/
Expand Down

0 comments on commit 68506ac

Please sign in to comment.