]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Support many new attributes and fix some IPP conformance issues (STR #4630)
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Mon, 25 May 2015 19:38:09 +0000 (19:38 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Mon, 25 May 2015 19:38:09 +0000 (19:38 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@12666 a1ca3aef-8c08-0410-bb20-df032aa958be

CHANGES.txt
cups/encode.c
cups/ipp-support.c
cups/ipp.h
cups/ppd-private.h
scheduler/ipp.c
scheduler/job.c
scheduler/printers.c
scheduler/printers.h

index 36108c53535ec3a9dc67a106d9f478be10b2ec29..ca16db13150575e77f4718dff65c5bea5ee687ec 100644 (file)
@@ -1,4 +1,4 @@
-CHANGES.txt - 2.1b1 - 2015-05-19
+CHANGES.txt - 2.1b1 - 2015-05-25
 --------------------------------
 
 CHANGES IN CUPS V2.1b1
@@ -33,3 +33,5 @@ CHANGES IN CUPS V2.1b1
        - Long cookies caused the web interface to stop working (STR #4619)
        - Added SSLOptions values to allow Diffie-Hellman key exchange and
          disable TLS/1.0 support.
+       - Updated the scheduler to support more IPP Everywhere attributes
+         (STR #4630)
index 64f8ce3f971bdc6ed690b44043c47470dc245404..7640ec1055eb9444b99e6fe6eee4246acb226d63 100644 (file)
@@ -274,6 +274,7 @@ static const _ipp_option_t ipp_options[] =
   { 0, "print-quality-default",        IPP_TAG_ENUM,           IPP_TAG_PRINTER },
   { 1, "printer-commands",     IPP_TAG_KEYWORD,        IPP_TAG_PRINTER },
   { 0, "printer-error-policy", IPP_TAG_NAME,           IPP_TAG_PRINTER },
+  { 0, "printer-geo-location", IPP_TAG_URI,            IPP_TAG_PRINTER },
   { 0, "printer-info",         IPP_TAG_TEXT,           IPP_TAG_PRINTER },
   { 0, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN,   IPP_TAG_PRINTER },
   { 0, "printer-is-shared",    IPP_TAG_BOOLEAN,        IPP_TAG_PRINTER },
index 1964ad00b8bc0148733f1f04a74436be4411f110..c5f84de86ebf364760ccbdc28029e4002cb979b1 100644 (file)
@@ -195,7 +195,7 @@ static const char * const ipp_std_ops[] =
                  "Suspend-Current-Job",
                  "Resume-Job",
 
-                 /* 0x0030 - 0x003e */
+                 /* 0x0030 - 0x003f */
                  "Promote-Job",
                  "Schedule-Job-After",
                  "0x0032",
@@ -210,7 +210,21 @@ static const char * const ipp_std_ops[] =
                  "Close-Job",
                  "Identify-Printer",
                  "Validate-Document",
-                 "Send-Hardcopy-Document"
+                 "Send-Hardcopy-Document",
+                 "Acknowledge-Document",
+
+                 /* 0x0040 - 0x004a */
+                 "Acknowledge-Identify-Printer",
+                 "Acknowledge-Job",
+                 "Fetch-Document",
+                 "Fetch-Job",
+                 "Get-Output-Device-Attributes",
+                 "Update-Active-Jobs",
+                 "Deregister-Output-Device",
+                 "Update-Document-Status",
+                 "Update-Job-Status",
+                 "Update-Output-Device-Attributes",
+                 "Get-Next-Document-Data"
                },
                * const ipp_cups_ops[] =
                {
index 6b3964e5fe0bfdf15daa8a91278e4a4dddd892ff..3432478f1b9bd541fd182951d84495b9b2f23077 100644 (file)
@@ -246,11 +246,11 @@ typedef enum ipp_op_e                     /**** IPP operations ****/
   IPP_OP_CUPS_INVALID = -1,            /* Invalid operation name for @link ippOpValue@ */
   IPP_OP_CUPS_NONE = 0,                        /* No operation @private@ */
   IPP_OP_PRINT_JOB = 0x0002,           /* Print a single file */
-  IPP_OP_PRINT_URI,                    /* Print a single URL @private@ */
+  IPP_OP_PRINT_URI,                    /* Print a single URL */
   IPP_OP_VALIDATE_JOB,                 /* Validate job options */
   IPP_OP_CREATE_JOB,                   /* Create an empty print job */
   IPP_OP_SEND_DOCUMENT,                        /* Add a file to a job */
-  IPP_OP_SEND_URI,                     /* Add a URL to a job @private@ */
+  IPP_OP_SEND_URI,                     /* Add a URL to a job */
   IPP_OP_CANCEL_JOB,                   /* Cancel a job */
   IPP_OP_GET_JOB_ATTRIBUTES,           /* Get job attributes */
   IPP_OP_GET_JOBS,                     /* Get a list of jobs */
@@ -261,7 +261,7 @@ typedef enum ipp_op_e                       /**** IPP operations ****/
   IPP_OP_PAUSE_PRINTER = 0x0010,       /* Stop a printer */
   IPP_OP_RESUME_PRINTER,               /* Start a printer */
   IPP_OP_PURGE_JOBS,                   /* Cancel all jobs */
-  IPP_OP_SET_PRINTER_ATTRIBUTES,       /* Set printer attributes @private@ */
+  IPP_OP_SET_PRINTER_ATTRIBUTES,       /* Set printer attributes */
   IPP_OP_SET_JOB_ATTRIBUTES,           /* Set job attributes */
   IPP_OP_GET_PRINTER_SUPPORTED_VALUES, /* Get supported attribute values */
   IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS, /* Create one or more printer subscriptions @since CUPS 1.2/OS X 10.5@ */
@@ -279,32 +279,45 @@ typedef enum ipp_op_e                     /**** IPP operations ****/
   IPP_OP_ENABLE_PRINTER,               /* Start a printer */
   IPP_OP_DISABLE_PRINTER,              /* Stop a printer */
   IPP_OP_PAUSE_PRINTER_AFTER_CURRENT_JOB,
-                                       /* Stop printer after the current job @private@ */
-  IPP_OP_HOLD_NEW_JOBS,                        /* Hold new jobs @private@ */
-  IPP_OP_RELEASE_HELD_NEW_JOBS,                /* Release new jobs @private@ */
-  IPP_OP_DEACTIVATE_PRINTER,           /* Stop a printer @private@ */
-  IPP_OP_ACTIVATE_PRINTER,             /* Start a printer @private@ */
-  IPP_OP_RESTART_PRINTER,              /* Restart a printer @private@ */
-  IPP_OP_SHUTDOWN_PRINTER,             /* Turn a printer off @private@ */
-  IPP_OP_STARTUP_PRINTER,              /* Turn a printer on @private@ */
-  IPP_OP_REPROCESS_JOB,                        /* Reprint a job @private@ */
-  IPP_OP_CANCEL_CURRENT_JOB,           /* Cancel the current job @private@ */
-  IPP_OP_SUSPEND_CURRENT_JOB,          /* Suspend the current job @private@ */
-  IPP_OP_RESUME_JOB,                   /* Resume the current job @private@ */
-  IPP_OP_PROMOTE_JOB,                  /* Promote a job to print sooner @private@ */
-  IPP_OP_SCHEDULE_JOB_AFTER,           /* Schedule a job to print after another @private@ */
-  IPP_OP_CANCEL_DOCUMENT = 0x0033,     /* Cancel-Document @private@ */
-  IPP_OP_GET_DOCUMENT_ATTRIBUTES,      /* Get-Document-Attributes @private@ */
-  IPP_OP_GET_DOCUMENTS,                        /* Get-Documents @private@ */
-  IPP_OP_DELETE_DOCUMENT,              /* Delete-Document @private@ */
-  IPP_OP_SET_DOCUMENT_ATTRIBUTES,      /* Set-Document-Attributes @private@ */
+                                       /* Stop printer after the current job */
+  IPP_OP_HOLD_NEW_JOBS,                        /* Hold new jobs */
+  IPP_OP_RELEASE_HELD_NEW_JOBS,                /* Release new jobs */
+  IPP_OP_DEACTIVATE_PRINTER,           /* Stop a printer */
+  IPP_OP_ACTIVATE_PRINTER,             /* Start a printer */
+  IPP_OP_RESTART_PRINTER,              /* Restart a printer */
+  IPP_OP_SHUTDOWN_PRINTER,             /* Turn a printer off */
+  IPP_OP_STARTUP_PRINTER,              /* Turn a printer on */
+  IPP_OP_REPROCESS_JOB,                        /* Reprint a job */
+  IPP_OP_CANCEL_CURRENT_JOB,           /* Cancel the current job */
+  IPP_OP_SUSPEND_CURRENT_JOB,          /* Suspend the current job */
+  IPP_OP_RESUME_JOB,                   /* Resume the current job */
+  IPP_OP_PROMOTE_JOB,                  /* Promote a job to print sooner */
+  IPP_OP_SCHEDULE_JOB_AFTER,           /* Schedule a job to print after another */
+  IPP_OP_CANCEL_DOCUMENT = 0x0033,     /* Cancel-Document */
+  IPP_OP_GET_DOCUMENT_ATTRIBUTES,      /* Get-Document-Attributes */
+  IPP_OP_GET_DOCUMENTS,                        /* Get-Documents */
+  IPP_OP_DELETE_DOCUMENT,              /* Delete-Document */
+  IPP_OP_SET_DOCUMENT_ATTRIBUTES,      /* Set-Document-Attributes */
   IPP_OP_CANCEL_JOBS,                  /* Cancel-Jobs */
   IPP_OP_CANCEL_MY_JOBS,               /* Cancel-My-Jobs */
   IPP_OP_RESUBMIT_JOB,                 /* Resubmit-Job */
   IPP_OP_CLOSE_JOB,                    /* Close-Job */
-  IPP_OP_IDENTIFY_PRINTER,             /* Identify-Printer @private@ */
-  IPP_OP_VALIDATE_DOCUMENT,            /* Validate-Document @private@ */
-  IPP_OP_SEND_HARDCOPY_DOCUMENT,       /* Send-Hardcopy-Document @private@ */
+  IPP_OP_IDENTIFY_PRINTER,             /* Identify-Printer */
+  IPP_OP_VALIDATE_DOCUMENT,            /* Validate-Document */
+  IPP_OP_SEND_HARDCOPY_DOCUMENT,       /* Send-Hardcopy-Document */
+  IPP_OP_ACKNOWLEDGE_DOCUMENT,         /* Acknowledge-Document */
+  IPP_OP_ACKNOWLEDGE_IDENTIFY_PRINTER, /* Acknowledge-Identify-Printer */
+  IPP_OP_ACKNOWLEDGE_JOB,              /* Acknowledge-Job */
+  IPP_OP_FETCH_DOCUMENT,               /* Fetch-Document */
+  IPP_OP_FETCH_JOB,                    /* Fetch-Job */
+  IPP_OP_GET_OUTPUT_DEVICE_ATTRIBUTES, /* Get-Output-Device-Attributes */
+  IPP_OP_UPDATE_ACTIVE_JOBS,           /* Update-Active-Jobs */
+  IPP_OP_DEREGISTER_OUTPUT_DEVICE,     /* Deregister-Output-Device */
+  IPP_OP_UPDATE_DOCUMENT_STATUS,       /* Update-Document-Status */
+  IPP_OP_UPDATE_JOB_STATUS,            /* Update-Job-Status */
+  IPP_OP_UPDATE_OUTPUT_DEVICE_ATTRIBUTES,
+                                       /* Update-Output-Device-Attributes */
+  IPP_OP_GET_NEXT_DOCUMENT_DATA,       /* Get-Next-Document-Data */
 
   IPP_OP_PRIVATE = 0x4000,             /* Reserved @private@ */
   IPP_OP_CUPS_GET_DEFAULT,             /* Get the default printer */
index 0fa17d97f4f7faef296750c42940d8c2a49af1d1..4360746ac0e207aab444605c479f2c494aa727d2 100644 (file)
@@ -49,7 +49,7 @@ extern "C" {
  * Constants...
  */
 
-#  define _PPD_CACHE_VERSION   6       /* Version number in cache file */
+#  define _PPD_CACHE_VERSION   7       /* Version number in cache file */
 
 
 /*
index 5b68a494eded3eff0f27ee81b0e0e43e4b132253..5cd3bbc2372c5b2ff39eb2c149516b1e53f8647b 100644 (file)
@@ -946,10 +946,18 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
 
   need_restart_job = 0;
 
-  if ((attr = ippFindAttribute(con->request, "printer-location",
-                               IPP_TAG_TEXT)) != NULL)
+  if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL)
     cupsdSetString(&pclass->location, attr->values[0].string.text);
 
+  if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4))
+    cupsdSetString(&pclass->geo_location, attr->values[0].string.text);
+
+  if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL)
+    cupsdSetString(&pclass->organization, attr->values[0].string.text);
+
+  if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL)
+    cupsdSetString(&pclass->organizational_unit, attr->values[0].string.text);
+
   if ((attr = ippFindAttribute(con->request, "printer-info",
                                IPP_TAG_TEXT)) != NULL)
     cupsdSetString(&pclass->info, attr->values[0].string.text);
@@ -1069,6 +1077,8 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
                                IPP_TAG_KEYWORD)) != NULL)
     cupsdSetAuthInfoRequired(pclass, NULL, attr);
 
+  pclass->config_time = time(NULL);
+
  /*
   * Update the printer class attributes and return...
   */
@@ -1204,6 +1214,9 @@ add_job(cupsd_client_t  *con,             /* I - Client connection */
   ipp_t                *unsup_col;             /* media-col in unsupported response */
   static const char * const readonly[] =/* List of read-only attributes */
   {
+    "date-time-at-completed",
+    "date-time-at-creation",
+    "date-time-at-processing",
     "job-id",
     "job-k-octets-completed",
     "job-impressions-completed",
@@ -1664,14 +1677,12 @@ add_job(cupsd_client_t  *con,           /* I - Client connection */
                 "job-originating-host-name", NULL, con->http->hostname);
   }
 
-  ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation",
-                time(NULL));
-  attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
-                       "time-at-processing", 0);
-  attr->value_tag = IPP_TAG_NOVALUE;
-  attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
-                       "time-at-completed", 0);
-  attr->value_tag = IPP_TAG_NOVALUE;
+  ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-completed");
+  ippAddDate(job->attrs, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(time(NULL)));
+  ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-processing");
+  ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "time-at-completed");
+  ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", time(NULL));
+  ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "time-at-processing");
 
  /*
   * Add remaining job attributes...
@@ -1898,6 +1909,7 @@ add_job(cupsd_client_t  *con,             /* I - Client connection */
 
   ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state",
                 job->state_value);
+  ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_TEXT, "job-state-message", NULL, "");
   ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons",
                NULL, job->reasons->values[0].string.text);
 
@@ -2309,6 +2321,15 @@ add_printer(cupsd_client_t  *con,        /* I - Client connection */
                                IPP_TAG_TEXT)) != NULL)
     cupsdSetString(&printer->location, attr->values[0].string.text);
 
+  if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4))
+    cupsdSetString(&printer->geo_location, attr->values[0].string.text);
+
+  if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL)
+    cupsdSetString(&printer->organization, attr->values[0].string.text);
+
+  if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL)
+    cupsdSetString(&printer->organizational_unit, attr->values[0].string.text);
+
   if ((attr = ippFindAttribute(con->request, "printer-info",
                                IPP_TAG_TEXT)) != NULL)
     cupsdSetString(&printer->info, attr->values[0].string.text);
@@ -2782,6 +2803,8 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
     }
   }
 
+  printer->config_time = time(NULL);
+
  /*
   * Update the printer attributes and return...
   */
@@ -4762,6 +4785,12 @@ copy_job_attrs(cupsd_client_t *con,      /* I - Client connection */
     * Generate attributes from the job structure...
     */
 
+    if (job->completed_time && (!ra || cupsArrayFind(ra, "date-time-at-completed")))
+      ippAddDate(con->response, IPP_TAG_JOB, "date-time-at-completed", ippTimeToDate(job->completed_time));
+
+    if (job->creation_time && (!ra || cupsArrayFind(ra, "date-time-at-creation")))
+      ippAddDate(con->response, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(job->creation_time));
+
     if (!ra || cupsArrayFind(ra, "job-id"))
       ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
 
@@ -4798,7 +4827,7 @@ copy_job_attrs(cupsd_client_t *con,       /* I - Client connection */
     if (job->completed_time && (!ra || cupsArrayFind(ra, "time-at-completed")))
       ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-completed", (int)job->completed_time);
 
-    if (job->completed_time && (!ra || cupsArrayFind(ra, "time-at-creation")))
+    if (job->creation_time && (!ra || cupsArrayFind(ra, "time-at-creation")))
       ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)job->creation_time);
   }
 }
@@ -4877,6 +4906,13 @@ copy_printer_attrs(
                  "printer-alert-description", NULL,
                 printer->alert_description);
 
+  if (!ra || cupsArrayFind(ra, "printer-config-change-date-time"))
+    ippAddDate(con->response, IPP_TAG_PRINTER, "printer-config-change-date-time", ippTimeToDate(printer->config_time));
+
+  if (!ra || cupsArrayFind(ra, "printer-config-change-time"))
+    ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+                  "printer-config-change-time", printer->config_time);
+
   if (!ra || cupsArrayFind(ra, "printer-current-time"))
     ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
                ippTimeToDate(curtime));
@@ -4950,6 +4986,9 @@ copy_printer_attrs(
     ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
                   printer->state);
 
+  if (!ra || cupsArrayFind(ra, "printer-state-change-date-time"))
+    ippAddDate(con->response, IPP_TAG_PRINTER, "printer-state-change-date-time", ippTimeToDate(printer->state_time));
+
   if (!ra || cupsArrayFind(ra, "printer-state-change-time"))
     ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                   "printer-state-change-time", printer->state_time);
@@ -7096,10 +7135,16 @@ get_printer_supported(
   * Return a list of attributes that can be set via Set-Printer-Attributes.
   */
 
+  ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
+                "printer-geo-location", 0);
   ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
                 "printer-info", 0);
   ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
                 "printer-location", 0);
+  ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
+                "printer-organization", 0);
+  ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
+                "printer-organizational-unit", 0);
 
   con->response->request.status.status_code = IPP_OK;
 }
@@ -10232,6 +10277,24 @@ set_printer_attrs(cupsd_client_t  *con,        /* I - Client connection */
     changed = 1;
   }
 
+  if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4))
+  {
+    cupsdSetString(&printer->geo_location, attr->values[0].string.text);
+    changed = 1;
+  }
+
+  if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL)
+  {
+    cupsdSetString(&printer->organization, attr->values[0].string.text);
+    changed = 1;
+  }
+
+  if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL)
+  {
+    cupsdSetString(&printer->organizational_unit, attr->values[0].string.text);
+    changed = 1;
+  }
+
   if ((attr = ippFindAttribute(con->request, "printer-info",
                                IPP_TAG_TEXT)) != NULL)
   {
@@ -10245,6 +10308,8 @@ set_printer_attrs(cupsd_client_t  *con, /* I - Client connection */
 
   if (changed)
   {
+    printer->config_time = time(NULL);
+
     cupsdSetPrinterAttrs(printer);
     cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
 
index 6605b656de59812cb3774754b7bda5d063a0ab88..1edf585e1caf62d1f1365d78adb979d145393dec 100644 (file)
@@ -4513,6 +4513,7 @@ static void
 set_time(cupsd_job_t *job,             /* I - Job to update */
          const char  *name)            /* I - Name of attribute */
 {
+  char                 date_name[128]; /* date-time-at-xxx */
   ipp_attribute_t      *attr;          /* Time attribute */
   time_t               curtime;        /* Current time */
 
@@ -4527,6 +4528,14 @@ set_time(cupsd_job_t *job,               /* I - Job to update */
     attr->values[0].integer = curtime;
   }
 
+  snprintf(date_name, sizeof(date_name), "date-%s", name);
+
+  if ((attr = ippFindAttribute(job->attrs, date_name, IPP_TAG_ZERO)) != NULL)
+  {
+    attr->value_tag = IPP_TAG_DATE;
+    ippSetDate(job->attrs, &attr, 0, ippTimeToDate(curtime));
+  }
+
   if (!strcmp(name, "time-at-completed"))
   {
     job->completed_time = curtime;
index 88391af83046a7545464b47b895b1948bacff284..86b3e5939cb06e2aca715aa83d6467099759605f 100644 (file)
@@ -95,11 +95,12 @@ cupsdAddPrinter(const char *name)   /* I - Name of printer */
                                             uuid, sizeof(uuid)));
   cupsdSetDeviceURI(p, "file:///dev/null");
 
-  p->state      = IPP_PRINTER_STOPPED;
-  p->state_time = time(NULL);
-  p->accepting  = 0;
-  p->shared     = DefaultShared;
-  p->filetype   = mimeAddType(MimeDatabase, "printer", name);
+  p->config_time = time(NULL);
+  p->state       = IPP_PRINTER_STOPPED;
+  p->state_time  = time(NULL);
+  p->accepting   = 0;
+  p->shared      = DefaultShared;
+  p->filetype    = mimeAddType(MimeDatabase, "printer", name);
 
   cupsdSetString(&p->job_sheets[0], "none");
   cupsdSetString(&p->job_sheets[1], "none");
@@ -171,6 +172,10 @@ cupsdCreateCommonData(void)
                  "third-shift",
                  "weekend"
                };
+  static const char * const features[] =/* ipp-features-supported values */
+               {
+                 "subscription-object"
+               };
   static const char * const versions[] =/* ipp-versions-supported values */
                {
                  "1.0",
@@ -339,8 +344,11 @@ cupsdCreateCommonData(void)
                };
   static const char * const printer_settable[] =
                {                       /* printer-settable-attributes-supported */
+                 "printer-geo-location",
                  "printer-info",
-                 "printer-location"
+                 "printer-location",
+                 "printer-organization",
+                 "printer-organizational-unit"
                };
   static const char * const which_jobs[] =
                {                       /* which-jobs-supported values */
@@ -420,6 +428,9 @@ cupsdCreateCommonData(void)
   ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
                "generated-natural-language-supported", NULL, DefaultLanguage);
 
+  /* ipp-features-supported */
+  ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-features-supported", sizeof(features) / sizeof(features[0]), NULL, features);
+
   /* ipp-versions-supported */
   ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY,
                 "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]),
@@ -533,6 +544,9 @@ cupsdCreateCommonData(void)
   ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                 "multiple-operation-time-out", MultipleOperationTimeout);
 
+  /* multiple-operation-time-out-action */
+  ippAddString(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-operation-time-out-action", NULL, "process-job");
+
   /* natural-language-configured (no IPP_TAG_COPY) */
   ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
                "natural-language-configured", NULL, DefaultLanguage);
@@ -618,6 +632,9 @@ cupsdCreateCommonData(void)
   ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY,
                "pdl-override-supported", NULL, "attempted");
 
+  /* printer-get-attributes-supported */
+  ippAddString(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-get-attributes-supported", NULL, "document-format");
+
   /* printer-op-policy-supported */
   attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY,
                        "printer-op-policy-supported", cupsArrayCount(Policies),
@@ -751,6 +768,7 @@ cupsdDeletePrinter(
   cupsdClearString(&p->hostname);
   cupsdClearString(&p->name);
   cupsdClearString(&p->location);
+  cupsdClearString(&p->geo_location);
   cupsdClearString(&p->make_model);
   cupsdClearString(&p->info);
   cupsdClearString(&p->job_sheets[0]);
@@ -960,6 +978,21 @@ cupsdLoadAllPrinters(void)
       if (value)
        cupsdSetString(&p->location, value);
     }
+    else if (!_cups_strcasecmp(line, "GeoLocation"))
+    {
+      if (value)
+        cupsdSetString(&p->geo_location, value);
+    }
+    else if (!_cups_strcasecmp(line, "Organization"))
+    {
+      if (value)
+       cupsdSetString(&p->organization, value);
+    }
+    else if (!_cups_strcasecmp(line, "OrganizationalUnit"))
+    {
+      if (value)
+       cupsdSetString(&p->organizational_unit, value);
+    }
     else if (!_cups_strcasecmp(line, "DeviceURI"))
     {
       if (value)
@@ -1064,6 +1097,15 @@ cupsdLoadAllPrinters(void)
       if (value)
         p->state_time = atoi(value);
     }
+    else if (!_cups_strcasecmp(line, "ConfigTime"))
+    {
+     /*
+      * Set the config time...
+      */
+
+      if (value)
+        p->config_time = atoi(value);
+    }
     else if (!_cups_strcasecmp(line, "Accepting"))
     {
      /*
@@ -1420,9 +1462,18 @@ cupsdSaveAllPrinters(void)
     if (printer->location)
       cupsFilePutConf(fp, "Location", printer->location);
 
+    if (printer->geo_location)
+      cupsFilePutConf(fp, "GeoLocation", printer->geo_location);
+
     if (printer->make_model)
       cupsFilePutConf(fp, "MakeModel", printer->make_model);
 
+    if (printer->organization)
+      cupsFilePutConf(fp, "Organization", printer->organization);
+
+    if (printer->organizational_unit)
+      cupsFilePutConf(fp, "OrganizationalUnit", printer->organizational_unit);
+
     cupsFilePutConf(fp, "DeviceURI", printer->device_uri);
 
     if (printer->port_monitor)
@@ -1439,6 +1490,7 @@ cupsdSaveAllPrinters(void)
       cupsFilePuts(fp, "State Idle\n");
 
     cupsFilePrintf(fp, "StateTime %d\n", (int)printer->state_time);
+    cupsFilePrintf(fp, "ConfigTime %d\n", (int)printer->config_time);
 
     for (i = 0; i < printer->num_reasons; i ++)
       if (strcmp(printer->reasons[i], "connecting-to-device") &&
@@ -2004,6 +2056,77 @@ cupsdSetPrinterAttr(
   }
 
   free(temp);
+
+ /*
+  * Update the printer-supply and printer-supply-description, as needed...
+  */
+
+  if (!strcmp(name, "marker-names"))
+  {
+    ipp_attribute_t *supply_desc = ippFindAttribute(p->attrs, "printer-supply-description", IPP_TAG_TEXT);
+                                       /* printer-supply-description attribute */
+
+    if (supply_desc != NULL)
+      ippDeleteAttribute(p->attrs, supply_desc);
+
+    supply_desc = ippCopyAttribute(p->attrs, attr, 0);
+    ippSetName(p->attrs, &supply_desc, "printer-supply-description");
+    ippSetValueTag(p->attrs, &supply_desc, IPP_TAG_TEXT);
+  }
+  else if (!strcmp(name, "marker-colors") || !strcmp(name, "marker-levels") || !strcmp(name, "marker-types"))
+  {
+    char       buffer[256],            /* printer-supply values */
+               pstype[64],             /* printer-supply type value */
+               *psptr;                 /* Pointer into type */
+    const char *color,                 /* marker-colors value */
+               *type;                  /* marker-types value */
+    int                level;                  /* marker-levels value */
+    ipp_attribute_t *colors = ippFindAttribute(p->attrs, "marker-colors", IPP_TAG_NAME);
+                                       /* marker-colors attribute */
+    ipp_attribute_t *levels = ippFindAttribute(p->attrs, "marker-levels", IPP_TAG_INTEGER);
+                                       /* marker-levels attribute */
+    ipp_attribute_t *types = ippFindAttribute(p->attrs, "marker-types", IPP_TAG_KEYWORD);
+                                       /* marker-types attribute */
+    ipp_attribute_t *supply = ippFindAttribute(p->attrs, "printer-supply", IPP_TAG_STRING);
+                                       /* printer-supply attribute */
+
+    if (supply != NULL)
+    {
+      ippDeleteAttribute(p->attrs, supply);
+      supply = NULL;
+    }
+
+    if (!colors || !levels || !types)
+      return;
+
+    count = ippGetCount(colors);
+    if (count != ippGetCount(levels) || count != ippGetCount(types))
+      return;
+
+    for (i = 0; i < count; i ++)
+    {
+      color = ippGetString(colors, i, NULL);
+      level = ippGetInteger(levels, i);
+      type  = ippGetString(types, i, NULL);
+
+      for (psptr = pstype; *type && psptr < (pstype + sizeof(pstype) - 1); type ++)
+        if (*type == '-')
+       {
+         type ++;
+         *psptr++ = (char)toupper(*type & 255);
+       }
+       else
+         *psptr++ = *type;
+      *psptr = '\0';
+
+      snprintf(buffer, sizeof(buffer), "index=%d;class=%s;type=%s;unit=percent;maxcapacity=100;level=%d;colorantname=%s;", i + 1, strncmp(pstype, "waste", 5) ? "supplyThatIsConsumed" : "receptacleThatIsFilled", pstype, level, color);
+
+      if (!i)
+        supply = ippAddOctetString(p->attrs, IPP_TAG_PRINTER, "printer-supply", buffer, (int)strlen(buffer));
+      else
+        ippSetOctetString(p->attrs, &supply, i, buffer, (int)strlen(buffer));
+    }
+  }
 }
 
 
@@ -2093,10 +2216,15 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
                p->name);
   ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
                NULL, p->location ? p->location : "");
+  if (p->geo_location)
+    ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-geo-location", NULL, p->geo_location);
+  else
+    ippAddOutOfBand(p->attrs, IPP_TAG_PRINTER, IPP_TAG_UNKNOWN, "printer-geo-location");
   ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
                NULL, p->info ? p->info : "");
-  ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uuid", NULL,
-              p->uuid);
+  ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organization", NULL, p->organization ? p->organization : "");
+  ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organizational-unit", NULL, p->organizational_unit ? p->organizational_unit : "");
+  ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uuid", NULL, p->uuid);
 
   if (cupsArrayCount(p->users) > 0)
   {
@@ -3791,6 +3919,9 @@ load_ppd(cupsd_printer_t *p)              /* I - Printer */
                      "pages-per-minute-color", 1);
     }
 
+    if ((ppd_attr = ppdFindAttr(ppd, "1284DeviceId", NULL)) != NULL)
+      ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-device-id", NULL, ppd_attr->value);
+
     num_qualities = 0;
 
     if ((output_mode = ppdFindOption(ppd, "OutputMode")) != NULL)
index fd5e47bd0a05d1f8516ea77a1a002d11d3e9dad9..26f1a6537e5b5df35c5fda9f52ae5faba51b8acd 100644 (file)
@@ -63,9 +63,12 @@ struct cupsd_printer_s
                *uuid,                  /* Printer UUID */
                *hostname,              /* Host printer resides on */
                *name,                  /* Printer name */
-               *location,              /* Location code */
+               *location,              /* Location string */
+               *geo_location,          /* Geographic location URI */
                *make_model,            /* Make and model */
                *info,                  /* Description */
+               *organization,          /* Organization name */
+               *organizational_unit,   /* Organizational unit (department, etc.) */
                *op_policy,             /* Operation policy name */
                *error_policy;          /* Error policy */
   cupsd_policy_t *op_policy_ptr;       /* Pointer to operation policy */
@@ -77,7 +80,8 @@ struct cupsd_printer_s
   char         state_message[1024];    /* Printer state message */
   int          num_reasons;            /* Number of printer-state-reasons */
   char         *reasons[64];           /* printer-state-reasons strings */
-  time_t       state_time;             /* Time at this state */
+  time_t       config_time,            /* Time at this configuration */
+               state_time;             /* Time at this state */
   char         *job_sheets[2];         /* Banners/job sheets */
   cups_ptype_t type;                   /* Printer type (color, small, etc.) */
   char         *device_uri;            /* Device URI */