diff --git a/CHANGES.md b/CHANGES.md index 0c968cbc81..eb1a5ad687 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -153,6 +153,8 @@ Changes in CUPS v2.5b1 (YYYY-MM-DD) - Fixed job cleanup after daemon restart (Issue #1315) - Fixed unreachable block in IPP backend (Issue #1351) - Fixed memory leak in _cupsConvertOptions (Issue #1354) +- Added OAuth Bearer auth-info support and OAuth metadata for shared queues + (Issue #1233) - Fixed missing write check in `cupsFileOpen/Fd` (Issue #1360) - Removed hash support for SHA2-512-224 and SHA2-512-256. - Removed `mantohtml` script for generating html pages (use diff --git a/backend/ipp.c b/backend/ipp.c index 8311a1cf97..95862ff0f9 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -88,6 +88,7 @@ static char device_username[256] = "", /* Password for device URI */ static const char * const pattrs[] = /* Printer attributes we want */ { + "auth-info-required", "compression-supported", "copies-supported", "cups-version", @@ -102,6 +103,8 @@ static const char * const pattrs[] = /* Printer attributes we want */ "marker-types", "media-col-supported", "multiple-document-handling-supported", + "oauth-authorization-scopes", + "oauth-authorization-server-uri", "operations-supported", "print-color-mode-supported", "print-scaling-supported", @@ -254,7 +257,8 @@ main(int argc, /* I - Number of command-line args */ copies, /* Number of copies for job */ copies_remaining; /* Number of copies remaining */ const char *auth_info_required, /* New auth-info-required value */ - *content_type, /* CONTENT_TYPE environment variable */ + *auth_bearer, /* AUTH_BEARER env variable */ + *content_type, /* CONTENT_TYPE environment variable */ *final_content_type, /* FINAL_CONTENT_TYPE environment var */ *document_format; /* document-format value */ int fd; /* File descriptor */ @@ -392,6 +396,8 @@ main(int argc, /* I - Number of command-line args */ final_content_type = "application/vnd.cups-raw"; } + auth_bearer = getenv("AUTH_BEARER"); + /* * Extract the hostname and printer name from the URI... */ @@ -661,6 +667,9 @@ main(int argc, /* I - Number of command-line args */ 0, NULL); httpSetTimeout(http, 30.0, timeout_cb, NULL); + if (auth_bearer) + httpSetAuthString(http, "Bearer", auth_bearer); + /* * See if the printer supports SNMP... */ @@ -1000,6 +1009,8 @@ main(int argc, /* I - Number of command-line args */ if (!strncmp(www_auth, "Negotiate", 9)) auth_info_required = "negotiate"; + else if (!strncmp(www_auth, "Bearer", 6)) + auth_info_required = "bearer"; else if (www_auth[0]) auth_info_required = "username,password"; @@ -1567,6 +1578,8 @@ main(int argc, /* I - Number of command-line args */ if (!strncmp(www_auth, "Negotiate", 9)) auth_info_required = "negotiate"; + else if (!strncmp(www_auth, "Bearer", 6)) + auth_info_required = "bearer"; else if (www_auth[0]) auth_info_required = "username,password"; @@ -1766,6 +1779,8 @@ main(int argc, /* I - Number of command-line args */ if (!strncmp(www_auth, "Negotiate", 9)) auth_info_required = "negotiate"; + else if (!strncmp(www_auth, "Bearer", 6)) + auth_info_required = "bearer"; else if (www_auth[0]) auth_info_required = "username,password"; } diff --git a/cups/cupspm.md b/cups/cupspm.md index 127bd2bf4e..e62d71e709 100644 --- a/cups/cupspm.md +++ b/cups/cupspm.md @@ -135,6 +135,25 @@ Historically destinations have been manually maintained by the administrator of a system or network, but CUPS also supports dynamic discovery of destinations on the current network. +### Authentication Attributes + +Destinations that proxy jobs to remote printers sometimes need additional +authentication information. In addition to the standard options, CUPS can expose +the following authentication-related attributes in `cups_dest_t.options`: + +- `"auth-info-required"`: Lists the authentication fields that are required for + the destination. Values include `"none"`, `"username,password"`, + `"domain,username,password"`, `"bearer"` (OAuth/OpenID HTTP Bearer token), and + `"negotiate"` (Kerberos). +- `"oauth-authorization-server-uri"`: Provides the OAuth/OpenID authorization + server URI that clients should use when obtaining Bearer tokens. +- `"oauth-authorization-scopes"`: Lists the OAuth/OpenID scopes that should be + requested when obtaining Bearer tokens. + +Applications that present destination details to users SHOULD display these +attributes so that clients know when additional credentials or tokens are +required. + ## Finding Available Destinations diff --git a/cups/dest.c b/cups/dest.c index eafb241558..8f12d9b041 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -1293,6 +1293,8 @@ _cupsGetDests(http_t *http, /* I - Connection to server or #ifdef __APPLE__ "media-supported", #endif // __APPLE__ + "oauth-authorization-scopes", + "oauth-authorization-server-uri", "printer-commands", "printer-defaults", "printer-info", @@ -1395,7 +1397,7 @@ _cupsGetDests(http_t *http, /* I - Connection to server or attr->value_tag != IPP_TAG_URI) continue; - if (!strcmp(attr->name, "auth-info-required") || + if (!strcmp(attr->name, "auth-info-required") || !strcmp(attr->name, "device-uri") || !strcmp(attr->name, "marker-change-time") || !strcmp(attr->name, "marker-colors") || @@ -1405,6 +1407,8 @@ _cupsGetDests(http_t *http, /* I - Connection to server or !strcmp(attr->name, "marker-message") || !strcmp(attr->name, "marker-names") || !strcmp(attr->name, "marker-types") || + !strcmp(attr->name, "oauth-authorization-scopes") || + !strcmp(attr->name, "oauth-authorization-server-uri") || !strcmp(attr->name, "printer-commands") || !strcmp(attr->name, "printer-info") || !strcmp(attr->name, "printer-is-shared") || diff --git a/cups/ipp-support.c b/cups/ipp-support.c index 5d575b5b52..41c9d27906 100644 --- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -1607,6 +1607,8 @@ ippCreateRequestedArray(ipp_t *request) // I - IPP request static const char * const printer_description[] = { // printer-description group "auth-info-required", // CUPS extension + "oauth-authorization-scopes", // CUPS extension + "oauth-authorization-server-uri", // CUPS extension "chamber-humidity-current", // IPP 3D "chamber-temperature-current", // IPP 3D "charset-configured", diff --git a/doc/help/cupspm.html b/doc/help/cupspm.html index f92c13980b..b0112173f0 100644 --- a/doc/help/cupspm.html +++ b/doc/help/cupspm.html @@ -1180,7 +1180,9 @@

Finding Available Destinat

Basic Destination Information

The num_options and options members of the cups_dest_t structure provide basic attributes about the destination in addition to the user default options and values for that destination. The following names are predefined for various destination attributes:

+

Extensionoauth-authorization-server-uri (uri)

+

The "oauth-authorization-server-uri" attribute specifies the OAuth 2.0/OpenID Connect authorization server URI that clients SHOULD use when retrieving Bearer tokens for this destination.

+ +

Extensionoauth-authorization-scopes (1setOf name(MAX))

+

The "oauth-authorization-scopes" attribute specifies the OAuth/OpenID scopes that MUST be requested when obtaining Bearer tokens for this destination.

+

Deprecatedjob-k-limit (integer)

The "job-k-limit" attribute specifies the maximum number of kilobytes that may be printed by a user, including banner files. The default value of 0 specifies that there is no limit. diff --git a/man/filter.7 b/man/filter.7 index 3d165954e4..5ff8426635 100644 --- a/man/filter.7 +++ b/man/filter.7 @@ -99,6 +99,7 @@ Sets the "printer-state-message" attribute and adds the specified message to the Sets the named job or printer attribute(s). The following job attributes can be set: "job-media-progress". The following printer attributes can be set: "auth-info-required", "marker-colors", "marker-high-levels", "marker-levels", "marker-low-levels", "marker-message", "marker-names", "marker-types", +"oauth-authorization-scopes", "oauth-authorization-server-uri", "printer-alert", and "printer-alert-description". .TP 5 \fBCRIT: \fImessage\fR diff --git a/scheduler/conf.c b/scheduler/conf.c index da5fd54a2f..74e09d2eed 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -3589,6 +3589,7 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */ static const char * const prohibited_env[] = { /* Prohibited environment variables */ "APPLE_LANGUAGE", + "AUTH_BEARER", "AUTH_DOMAIN", "AUTH_INFO_REQUIRED", "AUTH_NEGOTIATE", diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index 0dbc1d050f..9f8b75722e 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -259,7 +259,8 @@ dnssdBuildTxtRecord( *ptr; /* Pointer in string */ cupsd_listener_t *lis; /* Current listener */ const char *admin_scheme = "http"; /* Admin page URL scheme */ - ipp_attribute_t *urf_supported; /* urf-supported attribute */ + ipp_attribute_t *urf_supported, /* urf-supported attribute */ + *attr; /* Generic attribute */ /* @@ -330,6 +331,32 @@ dnssdBuildTxtRecord( if (get_auth_info_required(p, value, sizeof(value))) num_txt = cupsAddOption("air", value, num_txt, txt); + if ((attr = ippFindAttribute(p->attrs, "oauth-authorization-server-uri", + IPP_TAG_URI)) != NULL) + num_txt = cupsAddOption("oauth-uri", attr->values[0].string.text, + num_txt, txt); + + if ((attr = ippFindAttribute(p->attrs, "oauth-authorization-scopes", + IPP_TAG_NAME)) != NULL) + { + value[0] = '\0'; + for (i = 0, ptr = value; i < attr->num_values; i ++) + { + const char *scope = attr->values[i].string.text; + + if (ptr > value && ptr < (value + sizeof(value) - 1)) + *ptr++ = ' '; + + cupsCopyString(ptr, scope, sizeof(value) - (size_t)(ptr - value)); + ptr += strlen(ptr); + + if (ptr >= (value + sizeof(value) - 1)) + break; + } + + num_txt = cupsAddOption("oauth-scope", value, num_txt, txt); + } + num_txt = cupsAddOption("UUID", p->uuid + 9, num_txt, txt); num_txt = cupsAddOption("TLS", "1.3", num_txt, txt); diff --git a/scheduler/ipp.c b/scheduler/ipp.c index fa822603b0..ac27e97164 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -9495,6 +9495,9 @@ save_auth_info( else if (!strcmp(dest->auth_info_required[i], "negotiate")) cupsdSetStringf(job->auth_env + i, "AUTH_NEGOTIATE=%s", auth_info->values[i].string.text); + else if (!strcmp(dest->auth_info_required[i], "bearer")) + cupsdSetStringf(job->auth_env + i, "AUTH_BEARER=%s", + auth_info->values[i].string.text); else i --; } diff --git a/scheduler/job.c b/scheduler/job.c index 047e5dfc94..723482499e 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -2051,6 +2051,8 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ cupsdSetStringf(job->auth_env + i, "AUTH_PASSWORD=%s", data); else if (!strcmp(line, "negotiate")) cupsdSetStringf(job->auth_env + i, "AUTH_NEGOTIATE=%s", value); + else if (!strcmp(line, "bearer")) + cupsdSetStringf(job->auth_env + i, "AUTH_BEARER=%s", data); else continue; @@ -5414,6 +5416,22 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); } + if ((attr = cupsGetOption("oauth-authorization-server-uri", num_attrs, + attrs)) != NULL) + { + cupsdSetPrinterAttr(job->printer, "oauth-authorization-server-uri", + (char *)attr); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); + } + + if ((attr = cupsGetOption("oauth-authorization-scopes", num_attrs, + attrs)) != NULL) + { + cupsdSetPrinterAttr(job->printer, "oauth-authorization-scopes", + (char *)attr); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); + } + cupsFreeOptions(num_attrs, attrs); } else if (loglevel == CUPSD_LOG_PPD) diff --git a/scheduler/printers.c b/scheduler/printers.c index 0469734c26..aab04768a7 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -34,6 +34,7 @@ * Local functions... */ +static void add_ppd_defaults_to_ipp(cupsd_printer_t *p, ppd_file_t *ppd); static void add_printer_defaults(cupsd_printer_t *p); static void add_printer_filter(cupsd_printer_t *p, mime_type_t *type, const char *filter); @@ -1366,10 +1367,10 @@ cupsdLoadAllPrinters(void) } if (found_raw) - cupsdLogMessage(CUPSD_LOG_WARN, "Raw queues are deprecated and will stop working in a future version of CUPS. See https://github.com/OpenPrinting/cups/issues/103"); + cupsdLogMessage(CUPSD_LOG_WARN, "Raw queues are deprecated and will stop working in a future version of CUPS. Use IPP Everywhere drivers (\"-m everywhere\") or Printer Applications instead. See https://github.com/OpenPrinting/cups/issues/103"); if (found_driver) - cupsdLogMessage(CUPSD_LOG_WARN, "Printer drivers are deprecated and will stop working in a future version of CUPS. See https://github.com/OpenPrinting/cups/issues/103"); + cupsdLogMessage(CUPSD_LOG_WARN, "Printer drivers are deprecated and will stop working in a future version of CUPS. Use IPP Everywhere drivers (\"-m everywhere\") or Printer Applications instead. See https://github.com/OpenPrinting/cups/issues/103"); cupsFileClose(fp); } @@ -1710,6 +1711,37 @@ cupsdSaveAllPrinters(void) cupsFilePutConf(fp, "Attribute", value); } + if ((marker = ippFindAttribute(printer->attrs, + "oauth-authorization-server-uri", + IPP_TAG_URI)) != NULL) + { + snprintf(value, sizeof(value), "%s %s", marker->name, + marker->values[0].string.text); + cupsFilePutConf(fp, "Attribute", value); + } + + if ((marker = ippFindAttribute(printer->attrs, + "oauth-authorization-scopes", + IPP_TAG_NAME)) != NULL) + { + snprintf(value, sizeof(value), "%s ", marker->name); + + for (j = 0, ptr = value + strlen(value); + j < marker->num_values && ptr < (value + sizeof(value) - 1); + j ++) + { + if (j) + *ptr++ = ','; + + cupsCopyString(ptr, marker->values[j].string.text, + (size_t)(value + sizeof(value) - ptr)); + ptr += strlen(ptr); + } + + *ptr = '\0'; + cupsFilePutConf(fp, "Attribute", value); + } + if (printer->marker_time) cupsFilePrintf(fp, "Attribute marker-change-time %ld\n", (long)printer->marker_time); @@ -1792,6 +1824,14 @@ cupsdSetAuthInfoRequired( p->auth_info_required[p->num_auth_info_required] = "domain"; p->num_auth_info_required ++; } + else if ((end - values) == 6 && !strncmp(values, "bearer", 6)) + { + if (p->num_auth_info_required != 0 || *end) + return (0); + + p->auth_info_required[p->num_auth_info_required] = "bearer"; + p->num_auth_info_required ++; + } else if ((end - values) == 8 && !strncmp(values, "password", 8)) { p->auth_info_required[p->num_auth_info_required] = "password"; @@ -1871,6 +1911,16 @@ cupsdSetAuthInfoRequired( p->auth_info_required[p->num_auth_info_required] = "domain"; p->num_auth_info_required ++; } + else if (!strcmp(attr->values[i].string.text, "bearer")) + { + if (p->num_auth_info_required != 0 || attr->num_values != 1) + return (0); + + p->auth_info_required[p->num_auth_info_required] = "bearer"; + p->num_auth_info_required ++; + + return (1); + } else if (!strcmp(attr->values[i].string.text, "password")) { p->auth_info_required[p->num_auth_info_required] = "password"; @@ -2069,6 +2119,8 @@ cupsdSetPrinterAttr( value_tag = IPP_TAG_KEYWORD; else if (!strcmp(name, "marker-message")) value_tag = IPP_TAG_TEXT; + else if (!strcmp(name, "oauth-authorization-server-uri")) + value_tag = IPP_TAG_URI; else value_tag = IPP_TAG_NAME; @@ -2532,6 +2584,29 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ } } + if ((oldattr = ippFindAttribute(oldattrs, + "oauth-authorization-server-uri", + IPP_TAG_URI)) != NULL) + { + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, + "oauth-authorization-server-uri", NULL, + oldattr->values[0].string.text); + } + + if ((oldattr = ippFindAttribute(oldattrs, + "oauth-authorization-scopes", + IPP_TAG_NAME)) != NULL) + { + if ((attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, + "oauth-authorization-scopes", + oldattr->num_values, NULL, NULL)) != NULL) + { + for (i = 0; i < oldattr->num_values; i ++) + attr->values[i].string.text = + _cupsStrAlloc(oldattr->values[i].string.text); + } + } + ippDelete(oldattrs); } @@ -3376,6 +3451,185 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */ } +/* + * 'add_ppd_defaults_to_ipp()' - Map PPD option defaults to IPP "-default" attributes. + */ + +static void +add_ppd_defaults_to_ipp(cupsd_printer_t *p, /* I - Printer */ + ppd_file_t *ppd) /* I - PPD file */ +{ + ppd_option_t *option; /* Current PPD option */ + ppd_group_t *group; /* Current PPD group */ + const char *ipp_name; /* IPP attribute name */ + const char *ipp_value; /* IPP attribute value */ + const char *mapped_value; /* Mapped IPP attribute value */ + char attr_name[256]; /* Attribute name buffer */ + int i; /* Looping var */ + + + /* + * Skip if no PPD or PPD cache... + */ + + if (!ppd || !p->pc) + return; + + /* + * Loop through all PPD options and map their defaults to IPP attributes... + */ + + for (group = ppd->groups; group; group = group->next) + { + for (option = (ppd_option_t *)cupsArrayFirst(group->options); + option; + option = (ppd_option_t *)cupsArrayNext(group->options)) + { + /* + * Skip if no default choice... + */ + + if (!option->defchoice || !option->defchoice[0]) + continue; + + /* + * Skip options that are already explicitly handled... + */ + + if (!strcmp(option->keyword, "PageSize") || + !strcmp(option->keyword, "PageRegion") || + !strcmp(option->keyword, "ColorModel") || + !strcmp(option->keyword, "HPColorMode") || + !strcmp(option->keyword, "BRMonoColor") || + !strcmp(option->keyword, "CNIJSGrayScale") || + !strcmp(option->keyword, "HPColorAsGray") || + !strcmp(option->keyword, "Resolution") || + !strcmp(option->keyword, "JCLResolution") || + !strcmp(option->keyword, "SetResolution") || + !strcmp(option->keyword, "CNRes_PGP") || + !strcmp(option->keyword, "Duplex") || + !strcmp(option->keyword, "EFDuplex") || + !strcmp(option->keyword, "EFDuplexing") || + !strcmp(option->keyword, "KD03Duplex") || + !strcmp(option->keyword, "JCLDuplex") || + !strcmp(option->keyword, "OutputBin") || + !strcmp(option->keyword, "InputSlot") || + !strcmp(option->keyword, "HPPaperSource") || + !strcmp(option->keyword, "MediaType") || + !strcmp(option->keyword, "DefaultMediaType") || + !strcmp(option->keyword, "DefaultInputSlot")) + continue; + + /* + * Map PPD option names to IPP attribute names... + */ + + ipp_name = NULL; + ipp_value = option->defchoice; + mapped_value = ipp_value; + + if (!strcmp(option->keyword, "OutputOrder")) + ipp_name = "output-order"; + else if (!strcmp(option->keyword, "Collate")) + { + ipp_name = "multiple-document-handling"; + /* + * Map Collate values to IPP multiple-document-handling values... + */ + if (!_cups_strcasecmp(ipp_value, "True") || + !_cups_strcasecmp(ipp_value, "On") || + !_cups_strcasecmp(ipp_value, "Yes")) + { + mapped_value = "separate-documents-collated-copies"; + } + else + { + mapped_value = "separate-documents-uncollated-copies"; + } + } + else if (!strcmp(option->keyword, "cupsPrintQuality") || + !strcmp(option->keyword, "OutputMode")) + { + ipp_name = "print-quality"; + /* + * Map quality names to IPP enum values... + */ + if (!_cups_strcasecmp(ipp_value, "draft") || + !_cups_strcasecmp(ipp_value, "fast")) + { + if (!ippFindAttribute(p->attrs, "print-quality-default", IPP_TAG_ZERO)) + ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-default", IPP_QUALITY_DRAFT); + } + else if (!_cups_strcasecmp(ipp_value, "best") || + !_cups_strcasecmp(ipp_value, "high")) + { + if (!ippFindAttribute(p->attrs, "print-quality-default", IPP_TAG_ZERO)) + ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-default", IPP_QUALITY_HIGH); + } + else + { + if (!ippFindAttribute(p->attrs, "print-quality-default", IPP_TAG_ZERO)) + ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-default", IPP_QUALITY_NORMAL); + } + continue; + } + else + { + /* + * For other options, convert the option name to lowercase with dashes + * and append "-default"... + */ + + snprintf(attr_name, sizeof(attr_name), "%s-default", option->keyword); + for (i = 0; attr_name[i]; i ++) + { + if (attr_name[i] >= 'A' && attr_name[i] <= 'Z') + attr_name[i] = (char)(attr_name[i] | 32); /* tolower */ + else if (attr_name[i] == '_') + attr_name[i] = '-'; + } + + ipp_name = attr_name; + } + + /* + * Skip if we already have this attribute... + */ + + if (ippFindAttribute(p->attrs, ipp_name, IPP_TAG_ZERO)) + continue; + + /* + * Add the IPP "-default" attribute... + */ + + if (ipp_name && mapped_value) + { + /* + * For boolean options, convert to boolean... + */ + + if (option->ui == PPD_UI_BOOLEAN) + { + ippAddBoolean(p->attrs, IPP_TAG_PRINTER, ipp_name, + !_cups_strcasecmp(mapped_value, "True") || + !_cups_strcasecmp(mapped_value, "On") || + !_cups_strcasecmp(mapped_value, "Yes")); + } + else + { + /* + * For other options, add as string/keyword... + */ + + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, ipp_name, NULL, mapped_value); + } + } + } + } +} + + /* * 'add_printer_filter()' - Add a MIME filter for a printer. */ @@ -5271,6 +5525,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } #endif /* HAVE_APPLICATIONSERVICES_H */ + /* + * Map PPD defaults to IPP "-default" attributes... + */ + + add_ppd_defaults_to_ipp(p, ppd); + /* * Close the PPD and set the type... */ diff --git a/systemv/lpadmin.c b/systemv/lpadmin.c index 29332c15aa..ad9afb124e 100644 --- a/systemv/lpadmin.c +++ b/systemv/lpadmin.c @@ -611,7 +611,7 @@ main(int argc, /* I - Number of command-line arguments */ #ifdef __APPLE__ _cupsLangPuts(stderr, _("lpadmin: Raw queues are no longer supported on macOS.")); #else - _cupsLangPuts(stderr, _("lpadmin: Raw queues are deprecated and will stop working in a future version of CUPS.")); + _cupsLangPuts(stderr, _("lpadmin: Raw queues are deprecated and will stop working in a future version of CUPS. Use IPP Everywhere drivers (\"-m everywhere\") or Printer Applications instead.")); #endif /* __APPLE__ */ if (device_uri && (!strncmp(device_uri, "ipp://", 6) || !strncmp(device_uri, "ipps://", 7)) && strstr(device_uri, "/printers/")) @@ -623,7 +623,7 @@ main(int argc, /* I - Number of command-line arguments */ } else if ((ppd_name && strcmp(ppd_name, "everywhere") && strncmp(ppd_name, "driverless:", 11)) || file) { - _cupsLangPuts(stderr, _("lpadmin: Printer drivers are deprecated and will stop working in a future version of CUPS.")); + _cupsLangPuts(stderr, _("lpadmin: Printer drivers are deprecated and will stop working in a future version of CUPS. Use IPP Everywhere drivers (\"-m everywhere\") or Printer Applications instead.")); } if (num_options || file) diff --git a/templates/printer-added.tmpl b/templates/printer-added.tmpl index e3d36e185c..c5e4b64c74 100644 --- a/templates/printer-added.tmpl +++ b/templates/printer-added.tmpl @@ -4,7 +4,7 @@ successfully.

-Note: Printer drivers and raw queues are deprecated and will stop working in a future version of CUPS. +Note: Printer drivers and raw queues are deprecated and will stop working in a future version of CUPS. Use IPP Everywhere drivers (select "everywhere" as the model) or Printer Applications instead. See issue #103 for more information.