]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add job-sheets-col support (Issue #138)
authorMichael R Sweet <msweet@msweet.org>
Thu, 25 Apr 2024 20:51:57 +0000 (16:51 -0400)
committerMichael R Sweet <msweet@msweet.org>
Thu, 25 Apr 2024 20:51:57 +0000 (16:51 -0400)
CHANGES.md
cups/encode.c
scheduler/ipp.c
scheduler/job.c
scheduler/printers.c

index 19dc38fd75bbb60c3955130ea38d134014a039a2..55653181a609bdfee0e95059b96205447b0422d4 100644 (file)
@@ -8,6 +8,7 @@ Changes in CUPS v2.5b1 (TBA)
 - Added `cupsConcatString`, `cupsCopyString`, and `cupsFormatString` string
   APIs.
 - Added new APIs for form, JSON, JWT, IPP, and raster setup.
+- Added "job-sheets-col" support (Issue #138)
 - Added support for wide-area DNS-SD with Avahi (Issue #319)
 - Added `cupsCopyDestInfo2` API (Issue #586)
 - Added OpenSSL support for `cupsHashData` (Issue #762)
index 7bd41a9089990f0641ed7fb3a1f5a777d836de44..d068b70c590319751baa0a888d5d95667bf1ea9b 100644 (file)
@@ -180,6 +180,8 @@ static const _ipp_option_t ipp_options[] =
   { 0, "job-priority-default", IPP_TAG_INTEGER,        IPP_TAG_PRINTER },
   { 0, "job-quota-period",     IPP_TAG_INTEGER,        IPP_TAG_PRINTER },
   { 1, "job-sheets",           IPP_TAG_NAME,           IPP_TAG_JOB },
+  { 0, "job-sheets-col",       IPP_TAG_BEGIN_COLLECTION, IPP_TAG_JOB },
+  { 0, "job-sheets-col-default",IPP_TAG_BEGIN_COLLECTION, IPP_TAG_PRINTER },
   { 1, "job-sheets-default",   IPP_TAG_NAME,           IPP_TAG_PRINTER },
   { 0, "job-state",            IPP_TAG_ENUM,           IPP_TAG_ZERO }, /* never send as option */
   { 0, "job-state-message",    IPP_TAG_TEXT,           IPP_TAG_ZERO }, /* never send as option */
index 84018f6b13010e7b025f3000106e38ce114d785f..d345f626d787b65620de59e3e652bb0f78fe9096 100644 (file)
@@ -1153,6 +1153,7 @@ add_job(cupsd_client_t  *con,             /* I - Client connection */
                *auth_info;             /* auth-info attribute */
   const char   *mandatory;             /* Current mandatory job attribute */
   const char   *val;                   /* Default option value */
+  const char   *job_sheets;            /* "job-sheets" value */
   int          priority;               /* Job priority */
   cupsd_job_t  *job;                   /* Current job */
   char         job_uri[HTTP_MAX_URI];  /* Job URI */
@@ -1697,126 +1698,60 @@ add_job(cupsd_client_t  *con,          /* I - Client connection */
     * Add job sheets options...
     */
 
-    if ((attr = ippFindAttribute(job->attrs, "job-sheets",
-                                 IPP_TAG_ZERO)) == NULL)
+    if ((attr = ippFindAttribute(job->attrs, "job-sheets-col", IPP_TAG_BEGIN_COLLECTION)) == NULL)
     {
-      cupsdLogMessage(CUPSD_LOG_DEBUG,
-                      "Adding default job-sheets values \"%s,%s\"...",
-                      printer->job_sheets[0], printer->job_sheets[1]);
+      if ((attr = ippFindAttribute(job->attrs, "job-sheets",
+                                  IPP_TAG_ZERO)) == NULL)
+      {
+       cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "Adding default job-sheets values \"%s,%s\"...",
+                       printer->job_sheets[0], printer->job_sheets[1]);
 
-      attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
-                           2, NULL, NULL);
-      ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]);
-      ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]);
+       attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
+                            2, NULL, NULL);
+       ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]);
+       ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]);
+      }
     }
 
     job->job_sheets = attr;
 
+    if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION)
+      job_sheets = ippGetString(ippFindAttribute(ippGetCollection(attr, 0), "job-sheets", IPP_TAG_ZERO), 0, NULL);
+    else
+      job_sheets = ippGetString(attr, 0, NULL);
+
+    if (!job_sheets)
+      job_sheets = "none";
+
    /*
     * Enforce classification level if set...
     */
 
     if (Classification)
     {
-      cupsdLogMessage(CUPSD_LOG_INFO,
-                      "Classification=\"%s\", ClassifyOverride=%d",
-                      Classification ? Classification : "(null)",
-                     ClassifyOverride);
-
-      if (ClassifyOverride)
-      {
-        if (!strcmp(attr->values[0].string.text, "none") &&
-           (attr->num_values == 1 ||
-            !strcmp(attr->values[1].string.text, "none")))
-        {
-        /*
-          * Force the leading banner to have the classification on it...
-         */
-
-          ippSetString(job->attrs, &attr, 0, Classification);
-
-         cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
-                                            "job-sheets=\"%s,none\", "
-                                            "job-originating-user-name=\"%s\"",
-                     Classification, job->username);
-       }
-       else if (attr->num_values == 2 &&
-                strcmp(attr->values[0].string.text,
-                       attr->values[1].string.text) &&
-                strcmp(attr->values[0].string.text, "none") &&
-                strcmp(attr->values[1].string.text, "none"))
-        {
-        /*
-         * Can't put two different security markings on the same document!
-         */
-
-          ippSetString(job->attrs, &attr, 1, attr->values[0].string.text);
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "Classification=\"%s\", ClassifyOverride=%d", Classification, ClassifyOverride);
 
-         cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
-                                            "job-sheets=\"%s,%s\", "
-                                            "job-originating-user-name=\"%s\"",
-                     attr->values[0].string.text,
-                     attr->values[1].string.text, job->username);
-       }
-       else if (strcmp(attr->values[0].string.text, Classification) &&
-                strcmp(attr->values[0].string.text, "none") &&
-                (attr->num_values == 1 ||
-                 (strcmp(attr->values[1].string.text, Classification) &&
-                  strcmp(attr->values[1].string.text, "none"))))
-        {
-         if (attr->num_values == 1)
-            cupsdLogJob(job, CUPSD_LOG_NOTICE,
-                       "CLASSIFICATION OVERRIDDEN "
-                       "job-sheets=\"%s\", "
-                       "job-originating-user-name=\"%s\"",
-                       attr->values[0].string.text, job->username);
-          else
-            cupsdLogJob(job, CUPSD_LOG_NOTICE,
-                       "CLASSIFICATION OVERRIDDEN "
-                       "job-sheets=\"%s,%s\",fffff "
-                       "job-originating-user-name=\"%s\"",
-                       attr->values[0].string.text,
-                       attr->values[1].string.text, job->username);
-        }
-      }
-      else if (strcmp(attr->values[0].string.text, Classification) &&
-               (attr->num_values == 1 ||
-              strcmp(attr->values[1].string.text, Classification)))
+      if (ClassifyOverride && strcmp(job_sheets, Classification))
       {
-       /*
-        * Force the banner to have the classification on it...
-       */
-
-        if (attr->num_values > 1 &&
-           !strcmp(attr->values[0].string.text, attr->values[1].string.text))
+        // Force the leading banner to have the classification on it...
+       if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION)
        {
-          ippSetString(job->attrs, &attr, 0, Classification);
-          ippSetString(job->attrs, &attr, 1, Classification);
+         ipp_t *col = ippGetCollection(attr, 0);
+         ipp_attribute_t *attr2 = ippFindAttribute(col, "job-sheets", IPP_TAG_ZERO);
+         if (attr2)
+           ippSetString(col, &attr2, 0, Classification);
+         else
+           ippAddString(col, IPP_TAG_ZERO, IPP_TAG_NAME, "job-sheets", NULL, Classification);
        }
-        else
+       else
        {
-          if (attr->num_values == 1 ||
-             strcmp(attr->values[0].string.text, "none"))
-            ippSetString(job->attrs, &attr, 0, Classification);
-
-          if (attr->num_values > 1 &&
-             strcmp(attr->values[1].string.text, "none"))
-           ippSetString(job->attrs, &attr, 1, Classification);
-        }
+         ippSetString(job->attrs, &attr, 0, Classification);
+         if (ippGetCount(attr) > 1)
+           ippDeleteValues(job->attrs, &attr, 1, ippGetCount(attr) - 1);
+       }
 
-        if (attr->num_values > 1)
-         cupsdLogJob(job, CUPSD_LOG_NOTICE,
-                     "CLASSIFICATION FORCED "
-                     "job-sheets=\"%s,%s\", "
-                     "job-originating-user-name=\"%s\"",
-                     attr->values[0].string.text,
-                     attr->values[1].string.text, job->username);
-        else
-         cupsdLogJob(job, CUPSD_LOG_NOTICE,
-                     "CLASSIFICATION FORCED "
-                     "job-sheets=\"%s\", "
-                     "job-originating-user-name=\"%s\"",
-                     Classification, job->username);
+       cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED: job-sheets=\"%s\", job-originating-user-name=\"%s\"", Classification, job->username);
       }
     }
 
index 925a7236ad42f4e442b0916f263ad0a8fd824784..7cd73da4bd026a31013023e4cbc8eecf3a7a6922 100644 (file)
@@ -829,11 +829,13 @@ cupsdContinueJob(cupsd_job_t *job)        /* I - Job */
   if (job->job_sheets == NULL)
   {
     cupsdLogJob(job, CUPSD_LOG_DEBUG, "No job-sheets attribute.");
-    if ((job->job_sheets =
-         ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
-      cupsdLogJob(job, CUPSD_LOG_DEBUG,
-                 "... but someone added one without setting job_sheets.");
+    if ((job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
+      cupsdLogJob(job, CUPSD_LOG_DEBUG, "... but someone added one without setting job_sheets.");
+    else if ((job->job_sheets = ippFindAttribute(job->attrs, "job-sheets-col", IPP_TAG_BEGIN_COLLECTION)) != NULL)
+      cupsdLogJob(job, CUPSD_LOG_DEBUG, "... but someone added one without setting job_sheets.");
   }
+  else if (ippGetValueTag(job->job_sheets) == IPP_TAG_BEGIN_COLLECTION)
+    cupsdLogJob(job, CUPSD_LOG_DEBUG, "job-sheets-col={job-sheets=%s ...}", ippGetString(ippFindAttribute(ippGetCollection(job->job_sheets, 0), "job-sheets", IPP_TAG_ZERO), 0, NULL));
   else if (job->job_sheets->num_values == 1)
     cupsdLogJob(job, CUPSD_LOG_DEBUG, "job-sheets=%s",
                job->job_sheets->values[0].string.text);
@@ -846,6 +848,8 @@ cupsdContinueJob(cupsd_job_t *job)  /* I - Job */
     banner_page = 0;
   else if (job->job_sheets == NULL)
     banner_page = 0;
+  else if (ippGetValueTag(job->job_sheets) == IPP_TAG_BEGIN_COLLECTION && job->current_file == 0)
+    banner_page = 1;
   else if (_cups_strcasecmp(job->job_sheets->values[0].string.text, "none") != 0 &&
           job->current_file == 0)
     banner_page = 1;
@@ -1843,7 +1847,9 @@ cupsdLoadJob(cupsd_job_t *job)            /* I - Job */
 
   job->impressions = ippFindAttribute(job->attrs, "job-impressions-completed", IPP_TAG_INTEGER);
   job->sheets      = ippFindAttribute(job->attrs, "job-media-sheets-completed", IPP_TAG_INTEGER);
-  job->job_sheets  = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
+
+  if ((job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME)) == NULL)
+    job->job_sheets = ippFindAttribute(job->attrs, "job-sheets-col", IPP_TAG_BEGIN_COLLECTION);
 
   if (!job->impressions)
     job->impressions = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", 0);
@@ -3764,6 +3770,9 @@ get_options(cupsd_job_t *job,             /* I - Job */
 
   if (pc)
   {
+    bool have_size, have_source, have_type;
+                                       /* Have media info? */
+
     if ((attr = ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ENUM)) != NULL)
     {
       int pq = ippGetInteger(attr, 0);
@@ -3777,33 +3786,57 @@ get_options(cupsd_job_t *job,           /* I - Job */
       }
     }
 
-    if (!ippFindAttribute(job->attrs, "InputSlot", IPP_TAG_ZERO) &&
-       !ippFindAttribute(job->attrs, "HPPaperSource", IPP_TAG_ZERO))
+    have_size   = ippFindAttribute(job->attrs, "PageRegion", IPP_TAG_ZERO) != NULL || ippFindAttribute(job->attrs, "PageSize", IPP_TAG_ZERO) != NULL;
+    have_source = ippFindAttribute(job->attrs, "InputSlot", IPP_TAG_ZERO) != NULL || ippFindAttribute(job->attrs, "HPPaperSource", IPP_TAG_ZERO) == NULL;
+    have_type   = ippFindAttribute(job->attrs, "MediaType", IPP_TAG_ZERO) != NULL;
+
+    if (banner_page && (attr = ippFindAttribute(job->attrs, "job-sheets-col", IPP_TAG_BEGIN_COLLECTION)) != NULL)
     {
-      if ((ppd = _ppdCacheGetInputSlot(pc, job->attrs, NULL)) != NULL)
-       num_pwgppds = cupsAddOption(pc->source_option, ppd, num_pwgppds,
-                                   &pwgppds);
+      ipp_t    *col;                   /* Collection value */
+
+      col = ippGetCollection(attr, 0);
+
+      if ((ppd = _ppdCacheGetInputSlot(pc, col, NULL)) != NULL)
+      {
+       cupsdLogJob(job, CUPSD_LOG_DEBUG, "Mapping media-source to %s=%s", pc->source_option, ppd);
+       num_pwgppds = cupsAddOption(pc->source_option, ppd, num_pwgppds, &pwgppds);
+       have_source = true;
+      }
+
+      if ((ppd = _ppdCacheGetMediaType(pc, col, NULL)) != NULL)
+      {
+       cupsdLogJob(job, CUPSD_LOG_DEBUG, "Mapping media-type to MediaType=%s", ppd);
+       num_pwgppds = cupsAddOption("MediaType", ppd, num_pwgppds, &pwgppds);
+       have_type   = true;
+      }
+
+      if ((ppd = _ppdCacheGetPageSize(pc, col, NULL, &exact)) != NULL)
+      {
+       cupsdLogJob(job, CUPSD_LOG_DEBUG, "Mapping media-source to InputSlot=%s", ppd);
+       num_pwgppds = cupsAddOption("PageSize", ppd, num_pwgppds, &pwgppds);
+       have_size   = true;
+      }
     }
-    if (!ippFindAttribute(job->attrs, "MediaType", IPP_TAG_ZERO) &&
-       (ppd = _ppdCacheGetMediaType(pc, job->attrs, NULL)) != NULL)
-    {
-      cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping media to MediaType=%s", ppd);
 
+    if (!have_source && (ppd = _ppdCacheGetInputSlot(pc, job->attrs, NULL)) != NULL)
+    {
+      cupsdLogJob(job, CUPSD_LOG_DEBUG, "Mapping media-source to %s=%s", pc->source_option, ppd);
+      num_pwgppds = cupsAddOption(pc->source_option, ppd, num_pwgppds, &pwgppds);
+    }
+    if (!have_type && (ppd = _ppdCacheGetMediaType(pc, job->attrs, NULL)) != NULL)
+    {
+      cupsdLogJob(job, CUPSD_LOG_DEBUG, "Mapping media-type to MediaType=%s", ppd);
       num_pwgppds = cupsAddOption("MediaType", ppd, num_pwgppds, &pwgppds);
     }
 
-    if (!ippFindAttribute(job->attrs, "PageRegion", IPP_TAG_ZERO) &&
-       !ippFindAttribute(job->attrs, "PageSize", IPP_TAG_ZERO) &&
-       (ppd = _ppdCacheGetPageSize(pc, job->attrs, NULL, &exact)) != NULL)
+    if (!have_size && (ppd = _ppdCacheGetPageSize(pc, job->attrs, NULL, &exact)) != NULL)
     {
-      cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping media to Pagesize=%s", ppd);
-
+      cupsdLogJob(job, CUPSD_LOG_DEBUG, "Mapping media-size to Pagesize=%s", ppd);
       num_pwgppds = cupsAddOption("PageSize", ppd, num_pwgppds, &pwgppds);
 
       if (!ippFindAttribute(job->attrs, "media", IPP_TAG_ZERO))
       {
-        cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Adding media=%s", ppd);
-
+        cupsdLogJob(job, CUPSD_LOG_DEBUG, "Adding media=%s", ppd);
         num_pwgppds = cupsAddOption("media", ppd, num_pwgppds, &pwgppds);
       }
     }
index 925e4b1189eed5377d45095fa1dc3a68ac71378e..fe93224d1f6ee29b1192f10dcd84eb3ffc3a4e26 100644 (file)
@@ -151,213 +151,226 @@ cupsdCreateCommonData(void)
   struct statfs                spoolinfo;      /* FS info for spool directory */
   double               spoolsize;      /* FS size */
 #endif /* HAVE_STATVFS */
+  static const char *const job_sheets_col[] =
+  {                                    /* job-sheets-col-supported values */
+    "job-sheets",
+    "media",
+    "media-col"
+  };
   static const char * const page_delivery[] =
-               {                       /* page-delivery-supported values */
-                 "reverse-order",
-                 "same-order"
-               };
+  {                                    /* page-delivery-supported values */
+    "reverse-order",
+    "same-order"
+  };
   static const char * const print_scaling[] =
-               {                       /* print-scaling-supported values */
-                 "auto",
-                 "auto-fit",
-                 "fill",
-                 "fit",
-                 "none"
-               };
-  static const int number_up[] =               /* number-up-supported values */
-               { 1, 2, 4, 6, 9, 16 };
+  {                                    /* print-scaling-supported values */
+    "auto",
+    "auto-fit",
+    "fill",
+    "fit",
+    "none"
+  };
+  static const int number_up[] =       /* number-up-supported values */
+  {
+    1,
+    2,
+    4,
+    6,
+    9,
+    16
+  };
   static const char * const number_up_layout[] =
-               {                       /* number-up-layout-supported values */
-                 "btlr",
-                 "btrl",
-                 "lrbt",
-                 "lrtb",
-                 "rlbt",
-                 "rltb",
-                 "tblr",
-                 "tbrl"
-               };
-  static const int orients[4] =/* orientation-requested-supported values */
-               {
-                 IPP_ORIENT_PORTRAIT,
-                 IPP_ORIENT_LANDSCAPE,
-                 IPP_ORIENT_REVERSE_LANDSCAPE,
-                 IPP_ORIENT_REVERSE_PORTRAIT
-               };
+  {                                    /* number-up-layout-supported values */
+    "btlr",
+    "btrl",
+    "lrbt",
+    "lrtb",
+    "rlbt",
+    "rltb",
+    "tblr",
+    "tbrl"
+  };
+  static const int orients[4] =                /* orientation-requested-supported values */
+  {
+    IPP_ORIENT_PORTRAIT,
+    IPP_ORIENT_LANDSCAPE,
+    IPP_ORIENT_REVERSE_LANDSCAPE,
+    IPP_ORIENT_REVERSE_PORTRAIT
+  };
   static const char * const holds[] =  /* job-hold-until-supported values */
-               {
-                 "no-hold",
-                 "indefinite",
-                 "day-time",
-                 "evening",
-                 "night",
-                 "second-shift",
-                 "third-shift",
-                 "weekend"
-               };
+  {
+    "no-hold",
+    "indefinite",
+    "day-time",
+    "evening",
+    "night",
+    "second-shift",
+    "third-shift",
+    "weekend"
+  };
   static const char * const versions[] =/* ipp-versions-supported values */
-               {
-                 "1.0",
-                 "1.1",
-                 "2.0",
-                 "2.1"
-               };
+  {
+    "1.0",
+    "1.1",
+    "2.0",
+    "2.1"
+  };
   static const int     ops[] =         /* operations-supported values */
-               {
-                 IPP_OP_PRINT_JOB,
-                 IPP_OP_VALIDATE_JOB,
-                 IPP_OP_CREATE_JOB,
-                 IPP_OP_SEND_DOCUMENT,
-                 IPP_OP_CANCEL_JOB,
-                 IPP_OP_GET_JOB_ATTRIBUTES,
-                 IPP_OP_GET_JOBS,
-                 IPP_OP_GET_PRINTER_ATTRIBUTES,
-                 IPP_OP_HOLD_JOB,
-                 IPP_OP_RELEASE_JOB,
-                 IPP_OP_PAUSE_PRINTER,
-                 IPP_OP_RESUME_PRINTER,
-                 IPP_OP_PURGE_JOBS,
-                 IPP_OP_SET_PRINTER_ATTRIBUTES,
-                 IPP_OP_SET_JOB_ATTRIBUTES,
-                 IPP_OP_GET_PRINTER_SUPPORTED_VALUES,
-                 IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS,
-                 IPP_OP_CREATE_JOB_SUBSCRIPTIONS,
-                 IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES,
-                 IPP_OP_GET_SUBSCRIPTIONS,
-                 IPP_OP_RENEW_SUBSCRIPTION,
-                 IPP_OP_CANCEL_SUBSCRIPTION,
-                 IPP_OP_GET_NOTIFICATIONS,
-                 IPP_OP_ENABLE_PRINTER,
-                 IPP_OP_DISABLE_PRINTER,
-                 IPP_OP_HOLD_NEW_JOBS,
-                 IPP_OP_RELEASE_HELD_NEW_JOBS,
-                 IPP_OP_CANCEL_JOBS,
-                 IPP_OP_CANCEL_MY_JOBS,
-                 IPP_OP_CLOSE_JOB,
-                 IPP_OP_CUPS_GET_DEFAULT,
-                 IPP_OP_CUPS_GET_PRINTERS,
-                 IPP_OP_CUPS_ADD_MODIFY_PRINTER,
-                 IPP_OP_CUPS_DELETE_PRINTER,
-                 IPP_OP_CUPS_GET_CLASSES,
-                 IPP_OP_CUPS_ADD_MODIFY_CLASS,
-                 IPP_OP_CUPS_DELETE_CLASS,
-                 IPP_OP_CUPS_ACCEPT_JOBS,
-                 IPP_OP_CUPS_REJECT_JOBS,
-                 IPP_OP_CUPS_SET_DEFAULT,
-                 IPP_OP_CUPS_GET_DEVICES,
-                 IPP_OP_CUPS_GET_PPDS,
-                 IPP_OP_CUPS_MOVE_JOB,
-                 IPP_OP_CUPS_AUTHENTICATE_JOB,
-                 IPP_OP_CUPS_GET_PPD,
-                 IPP_OP_CUPS_GET_DOCUMENT,
-                 IPP_OP_RESTART_JOB
-               };
+  {
+    IPP_OP_PRINT_JOB,
+    IPP_OP_VALIDATE_JOB,
+    IPP_OP_CREATE_JOB,
+    IPP_OP_SEND_DOCUMENT,
+    IPP_OP_CANCEL_JOB,
+    IPP_OP_GET_JOB_ATTRIBUTES,
+    IPP_OP_GET_JOBS,
+    IPP_OP_GET_PRINTER_ATTRIBUTES,
+    IPP_OP_HOLD_JOB,
+    IPP_OP_RELEASE_JOB,
+    IPP_OP_PAUSE_PRINTER,
+    IPP_OP_RESUME_PRINTER,
+    IPP_OP_PURGE_JOBS,
+    IPP_OP_SET_PRINTER_ATTRIBUTES,
+    IPP_OP_SET_JOB_ATTRIBUTES,
+    IPP_OP_GET_PRINTER_SUPPORTED_VALUES,
+    IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS,
+    IPP_OP_CREATE_JOB_SUBSCRIPTIONS,
+    IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES,
+    IPP_OP_GET_SUBSCRIPTIONS,
+    IPP_OP_RENEW_SUBSCRIPTION,
+    IPP_OP_CANCEL_SUBSCRIPTION,
+    IPP_OP_GET_NOTIFICATIONS,
+    IPP_OP_ENABLE_PRINTER,
+    IPP_OP_DISABLE_PRINTER,
+    IPP_OP_HOLD_NEW_JOBS,
+    IPP_OP_RELEASE_HELD_NEW_JOBS,
+    IPP_OP_CANCEL_JOBS,
+    IPP_OP_CANCEL_MY_JOBS,
+    IPP_OP_CLOSE_JOB,
+    IPP_OP_CUPS_GET_DEFAULT,
+    IPP_OP_CUPS_GET_PRINTERS,
+    IPP_OP_CUPS_ADD_MODIFY_PRINTER,
+    IPP_OP_CUPS_DELETE_PRINTER,
+    IPP_OP_CUPS_GET_CLASSES,
+    IPP_OP_CUPS_ADD_MODIFY_CLASS,
+    IPP_OP_CUPS_DELETE_CLASS,
+    IPP_OP_CUPS_ACCEPT_JOBS,
+    IPP_OP_CUPS_REJECT_JOBS,
+    IPP_OP_CUPS_SET_DEFAULT,
+    IPP_OP_CUPS_GET_DEVICES,
+    IPP_OP_CUPS_GET_PPDS,
+    IPP_OP_CUPS_MOVE_JOB,
+    IPP_OP_CUPS_AUTHENTICATE_JOB,
+    IPP_OP_CUPS_GET_PPD,
+    IPP_OP_CUPS_GET_DOCUMENT,
+    IPP_OP_RESTART_JOB
+  };
   static const char * const charsets[] =/* charset-supported values */
-               {
-                 "us-ascii",
-                 "utf-8"
-               };
+  {
+    "us-ascii",
+    "utf-8"
+  };
   static const char * const compressions[] =
-               {                       /* document-compression-supported values */
-                 "none",
-                 "gzip"
-               };
+  {                                    /* document-compression-supported values */
+    "none",
+    "gzip"
+  };
   static const char * const media_col_supported[] =
-               {                       /* media-col-supported values */
-                 "media-bottom-margin",
-                 "media-left-margin",
-                 "media-right-margin",
-                 "media-size",
-                 "media-source",
-                 "media-top-margin",
-                 "media-type"
-               };
+  {                                    /* media-col-supported values */
+    "media-bottom-margin",
+    "media-left-margin",
+    "media-right-margin",
+    "media-size",
+    "media-source",
+    "media-top-margin",
+    "media-type"
+  };
   static const char * const multiple_document_handling[] =
-               {                       /* multiple-document-handling-supported values */
-                 "separate-documents-uncollated-copies",
-                 "separate-documents-collated-copies"
-               };
+  {                                    /* multiple-document-handling-supported values */
+    "separate-documents-uncollated-copies",
+    "separate-documents-collated-copies"
+  };
   static const char * const notify_attrs[] =
-               {                       /* notify-attributes-supported values */
-                 "printer-state-change-time",
-                 "notify-lease-expiration-time",
-                 "notify-subscriber-user-name"
-               };
+  {                                    /* notify-attributes-supported values */
+    "printer-state-change-time",
+    "notify-lease-expiration-time",
+    "notify-subscriber-user-name"
+  };
   static const char * const notify_events[] =
-               {                       /* notify-events-supported values */
-                 "job-completed",
-                 "job-config-changed",
-                 "job-created",
-                 "job-progress",
-                 "job-state-changed",
-                 "job-stopped",
-                 "printer-added",
-                 "printer-changed",
-                 "printer-config-changed",
-                 "printer-deleted",
-                 "printer-finishings-changed",
-                 "printer-media-changed",
-                 "printer-modified",
-                 "printer-restarted",
-                 "printer-shutdown",
-                 "printer-state-changed",
-                 "printer-stopped",
-                 "server-audit",
-                 "server-restarted",
-                 "server-started",
-                 "server-stopped"
-               };
+  {                                    /* notify-events-supported values */
+    "job-completed",
+    "job-config-changed",
+    "job-created",
+    "job-progress",
+    "job-state-changed",
+    "job-stopped",
+    "printer-added",
+    "printer-changed",
+    "printer-config-changed",
+    "printer-deleted",
+    "printer-finishings-changed",
+    "printer-media-changed",
+    "printer-modified",
+    "printer-restarted",
+    "printer-shutdown",
+    "printer-state-changed",
+    "printer-stopped",
+    "server-audit",
+    "server-restarted",
+    "server-started",
+    "server-stopped"
+  };
   static const char * const job_settable[] =
-               {                       /* job-settable-attributes-supported */
-                 "copies",
-                 "finishings",
-                 "job-hold-until",
-                 "job-name",
-                 "job-priority",
-                 "media",
-                 "media-col",
-                 "multiple-document-handling",
-                 "number-up",
-                 "output-bin",
-                 "orientation-requested",
-                 "page-ranges",
-                 "print-color-mode",
-                 "print-quality",
-                 "printer-resolution",
-                 "sides"
-               };
+  {                                    /* job-settable-attributes-supported */
+    "copies",
+    "finishings",
+    "job-hold-until",
+    "job-name",
+    "job-priority",
+    "media",
+    "media-col",
+    "multiple-document-handling",
+    "number-up",
+    "output-bin",
+    "orientation-requested",
+    "page-ranges",
+    "print-color-mode",
+    "print-quality",
+    "printer-resolution",
+    "sides"
+  };
   static const char * const pdf_versions[] =
-               {                       /* pdf-versions-supported */
-                 "adobe-1.2",
-                 "adobe-1.3",
-                 "adobe-1.4",
-                 "adobe-1.5",
-                 "adobe-1.6",
-                 "adobe-1.7",
-                 "iso-19005-1_2005",
-                 "iso-32000-1_2008",
-                 "pwg-5102.3"
-               };
+  {                                    /* pdf-versions-supported */
+    "adobe-1.2",
+    "adobe-1.3",
+    "adobe-1.4",
+    "adobe-1.5",
+    "adobe-1.6",
+    "adobe-1.7",
+    "iso-19005-1_2005",
+    "iso-32000-1_2008",
+    "pwg-5102.3"
+  };
   static const char * const printer_settable[] =
-               {                       /* printer-settable-attributes-supported */
-                 "printer-geo-location",
-                 "printer-info",
-                 "printer-location",
-                 "printer-organization",
-                 "printer-organizational-unit"
-               };
+  {                                    /* printer-settable-attributes-supported */
+    "printer-geo-location",
+    "printer-info",
+    "printer-location",
+    "printer-organization",
+    "printer-organizational-unit"
+  };
   static const char * const which_jobs[] =
-               {                       /* which-jobs-supported values */
-                 "completed",
-                 "not-completed",
-                 "aborted",
-                 "all",
-                 "canceled",
-                 "pending",
-                 "pending-held",
-                 "processing",
-                 "processing-stopped"
-               };
+  {                                    /* which-jobs-supported values */
+    "completed",
+    "not-completed",
+    "aborted",
+    "all",
+    "canceled",
+    "pending",
+    "pending-held",
+    "processing",
+    "processing-stopped"
+  };
 
 
   if (CommonData)
@@ -435,6 +448,9 @@ cupsdCreateCommonData(void)
   /* job-settable-attributes-supported */
   ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-settable-attributes-supported", sizeof(job_settable) / sizeof(job_settable[0]), NULL, job_settable);
 
+  /* job-sheets-col-supported */
+  ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-sheets-col-supported", sizeof(job_sheets_col) / sizeof(job_sheets_col[0]), NULL, job_sheets_col);
+
   /* job-sheets-supported */
   if (cupsArrayCount(Banners) > 0)
   {