From 89c51341b0132f406598e943c42c8152bd3a696c Mon Sep 17 00:00:00 2001
From: Your Name
Date: Tue, 4 Nov 2025 23:52:12 +0530
Subject: [PATCH 1/3] Map PPD defaults to IPP "-default" attributes (#1358)
---
scheduler/printers.c | 186 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 0469734c26..757a1be80f 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);
@@ -3376,6 +3377,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 +5451,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...
*/
From acb474d965ad2e75efc32c8c6632faac9e4b7d09 Mon Sep 17 00:00:00 2001
From: Your Name
Date: Sun, 16 Nov 2025 19:48:59 +0530
Subject: [PATCH 2/3] Improve deprecation warnings with IPP Everywhere guidance
(#1357)
---
scheduler/printers.c | 4 ++--
systemv/lpadmin.c | 4 ++--
templates/printer-added.tmpl | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 757a1be80f..8a09bc9864 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -1367,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);
}
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.
CRIT: message
diff --git a/doc/help/spec-ipp.html b/doc/help/spec-ipp.html
index 671b1e9356..6a3fe22822 100644
--- a/doc/help/spec-ipp.html
+++ b/doc/help/spec-ipp.html
@@ -1022,11 +1022,17 @@
Deprecatedauth-info-requir
'domain': A domain name is required.
'negotiate': Kerberos is required - this keyword can only appear by itself and causes cupsd to collect the UID of the printing user.
'none': No authentication is required - this keyword can only appear by itself.
- 'oauth': An OAuth/OpenID access token is required - this keyword can only appear by itself.
+ 'bearer': An OAuth/OpenID access token (HTTP "Bearer" token from RFC 6750) is required - this keyword can only appear by itself.
'password': A password is required.
'username': A username is required. Some protocols (like SMB) prefix the username with the domain, for example "DOMAIN\user".
+ 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 8a09bc9864..aab04768a7 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -1711,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);
@@ -1793,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";
@@ -1872,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";
@@ -2070,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;
@@ -2533,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);
}