Blob Blame Raw
diff -up cups-1.7.5/scheduler/ipp.c.str2913 cups-1.7.5/scheduler/ipp.c
--- cups-1.7.5/scheduler/ipp.c.str2913	2014-08-20 17:19:25.216908923 +0100
+++ cups-1.7.5/scheduler/ipp.c	2014-08-20 17:21:45.641812985 +0100
@@ -1531,8 +1531,7 @@ add_job(cupsd_client_t  *con,		/* I - Cl
   }
 
   if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_ZERO)) == NULL)
-    ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL,
-                 "Untitled");
+    ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled");
   else if ((attr->value_tag != IPP_TAG_NAME &&
             attr->value_tag != IPP_TAG_NAMELANG) ||
            attr->num_values != 1)
@@ -1612,6 +1611,9 @@ add_job(cupsd_client_t  *con,		/* I - Cl
       ippDeleteAttribute(job->attrs, auth_info);
   }
 
+  if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_NAME)) != NULL)
+    cupsdSetString(&(job->name), attr->values[0].string.text);
+
   if ((attr = ippFindAttribute(job->attrs, "job-originating-host-name",
                                IPP_TAG_ZERO)) != NULL)
   {
@@ -1706,8 +1708,7 @@ add_job(cupsd_client_t  *con,		/* I - Cl
   ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL,
                printer->uri);
 
-  if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
-                               IPP_TAG_INTEGER)) != NULL)
+  if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
     attr->values[0].integer = 0;
   else
     ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", 0);
@@ -4357,8 +4358,9 @@ copy_banner(cupsd_client_t *con,	/* I -
 
   kbytes = (cupsFileTell(out) + 1023) / 1024;
 
-  if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
-                               IPP_TAG_INTEGER)) != NULL)
+  job->koctets += kbytes;
+
+  if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
     attr->values[0].integer += kbytes;
 
   cupsFileClose(out);
@@ -4780,7 +4782,55 @@ copy_job_attrs(cupsd_client_t *con,	/* I
         	 "job-uri", NULL, job_uri);
   }
 
-  copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude);
+  if (job->attrs)
+  {
+    copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude);
+  }
+  else
+  {
+   /*
+    * Generate attributes from the job structure...
+    */
+
+    if (!ra || cupsArrayFind(ra, "job-id"))
+      ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
+
+    if (!ra || cupsArrayFind(ra, "job-k-octets"))
+      ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", job->koctets);
+
+    if (job->name && (!ra || cupsArrayFind(ra, "job-name")))
+      ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, job->name);
+
+    if (job->username && (!ra || cupsArrayFind(ra, "job-originating-user-name")))
+      ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-user-name", NULL, job->username);
+
+    if (!ra || cupsArrayFind(ra, "job-state"))
+      ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state_value);
+
+    if (!ra || cupsArrayFind(ra, "job-state-reasons"))
+    {
+      switch (job->state_value)
+      {
+        default : /* Should never get here for processing, pending, held, or stopped jobs since they don't get unloaded... */
+	    break;
+        case IPP_JSTATE_ABORTED :
+	    ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-aborted-by-system");
+	    break;
+        case IPP_JSTATE_CANCELED :
+	    ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-canceled-by-user");
+	    break;
+        case IPP_JSTATE_COMPLETED :
+	    ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-completed-successfully");
+	    break;
+      }
+    }
+
+    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")))
+      ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)job->creation_time);
+  }
 }
 
 
@@ -6133,9 +6183,13 @@ get_jobs(cupsd_client_t  *con,		/* I - C
   int		port;			/* Port portion of URI */
   int		job_comparison;		/* Job comparison */
   ipp_jstate_t	job_state;		/* job-state value */
-  int		first_job_id;		/* First job ID */
-  int		limit;			/* Maximum number of jobs to return */
+  int		first_job_id = 1,	/* First job ID */
+		first_index = 1,	/* First index */
+		current_index = 0;	/* Current index */
+  int		limit = 0;		/* Maximum number of jobs to return */
   int		count;			/* Number of jobs that match */
+  int		need_load_job = 0;	/* Do we need to load the job? */
+  const char	*job_attr;		/* Job attribute requested */
   ipp_attribute_t *job_ids;		/* job-ids attribute */
   cupsd_job_t	*job;			/* Current job pointer */
   cupsd_printer_t *printer;		/* Printer */
@@ -6301,8 +6355,7 @@ get_jobs(cupsd_client_t  *con,		/* I - C
   * See if they want to limit the number of jobs reported...
   */
 
-  if ((attr = ippFindAttribute(con->request, "limit",
-                               IPP_TAG_INTEGER)) != NULL)
+  if ((attr = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER)) != NULL)
   {
     if (job_ids)
     {
@@ -6314,11 +6367,20 @@ get_jobs(cupsd_client_t  *con,		/* I - C
 
     limit = attr->values[0].integer;
   }
-  else
-    limit = 0;
 
-  if ((attr = ippFindAttribute(con->request, "first-job-id",
-                               IPP_TAG_INTEGER)) != NULL)
+  if ((attr = ippFindAttribute(con->request, "first-index", IPP_TAG_INTEGER)) != NULL)
+  {
+    if (job_ids)
+    {
+      send_ipp_status(con, IPP_CONFLICT,
+		      _("The %s attribute cannot be provided with job-ids."),
+		      "first-index");
+      return;
+    }
+
+    first_index = attr->values[0].integer;
+  }
+  else if ((attr = ippFindAttribute(con->request, "first-job-id", IPP_TAG_INTEGER)) != NULL)
   {
     if (job_ids)
     {
@@ -6330,15 +6392,12 @@ get_jobs(cupsd_client_t  *con,		/* I - C
 
     first_job_id = attr->values[0].integer;
   }
-  else
-    first_job_id = 1;
 
  /*
   * See if we only want to see jobs for a specific user...
   */
 
-  if ((attr = ippFindAttribute(con->request, "my-jobs",
-                               IPP_TAG_BOOLEAN)) != NULL && job_ids)
+  if ((attr = ippFindAttribute(con->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL && job_ids)
   {
     send_ipp_status(con, IPP_CONFLICT,
                     _("The %s attribute cannot be provided with job-ids."),
@@ -6351,6 +6410,43 @@ get_jobs(cupsd_client_t  *con,		/* I - C
     username[0] = '\0';
 
   ra = create_requested_array(con->request);
+  for (job_attr = (char *)cupsArrayFirst(ra); job_attr; job_attr = (char *)cupsArrayNext(ra))
+    if (strcmp(job_attr, "job-id") &&
+	strcmp(job_attr, "job-k-octets") &&
+	strcmp(job_attr, "job-media-progress") &&
+	strcmp(job_attr, "job-more-info") &&
+	strcmp(job_attr, "job-name") &&
+	strcmp(job_attr, "job-originating-user-name") &&
+	strcmp(job_attr, "job-preserved") &&
+	strcmp(job_attr, "job-printer-up-time") &&
+        strcmp(job_attr, "job-printer-uri") &&
+	strcmp(job_attr, "job-state") &&
+	strcmp(job_attr, "job-state-reasons") &&
+	strcmp(job_attr, "job-uri") &&
+	strcmp(job_attr, "time-at-completed") &&
+	strcmp(job_attr, "time-at-creation") &&
+	strcmp(job_attr, "number-of-documents"))
+    {
+      need_load_job = 1;
+      break;
+    }
+
+  if (need_load_job && (limit == 0 || limit > 500) && (list == Jobs || delete_list))
+  {
+   /*
+    * Limit expensive Get-Jobs for job history to 500 jobs...
+    */
+
+    ippAddInteger(con->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "limit", 500);
+
+    if (limit)
+      ippAddInteger(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER, "limit", limit);
+
+    limit = 500;
+
+    cupsdLogMessage(CUPSD_LOG_INFO,
+		    "Limiting Get-Jobs response to %d jobs.", limit);
+  }
 
  /*
   * OK, build a list of jobs for this printer...
@@ -6377,13 +6473,15 @@ get_jobs(cupsd_client_t  *con,		/* I - C
     {
       job = cupsdFindJob(job_ids->values[i].integer);
 
-      cupsdLoadJob(job);
-
-      if (!job->attrs)
+      if (need_load_job && !job->attrs)
       {
-	cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d",
-			job->id);
-	continue;
+        cupsdLoadJob(job);
+
+	if (!job->attrs)
+	{
+	  cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id);
+	  continue;
+	}
       }
 
       if (i > 0)
@@ -6433,13 +6531,19 @@ get_jobs(cupsd_client_t  *con,		/* I - C
       if (job->id < first_job_id)
 	continue;
 
-      cupsdLoadJob(job);
+      current_index ++;
+      if (current_index < first_index)
+        continue;
 
-      if (!job->attrs)
+      if (need_load_job && !job->attrs)
       {
-	cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d",
-			job->id);
-	continue;
+        cupsdLoadJob(job);
+
+	if (!job->attrs)
+	{
+	  cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id);
+	  continue;
+	}
       }
 
       if (username[0] && _cups_strcasecmp(username, job->username))
@@ -8173,8 +8277,9 @@ print_job(cupsd_client_t  *con,		/* I -
 
   cupsdUpdateQuota(printer, job->username, 0, kbytes);
 
-  if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
-                               IPP_TAG_INTEGER)) != NULL)
+  job->koctets += kbytes;
+
+  if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
     attr->values[0].integer += kbytes;
 
  /*
@@ -9410,8 +9515,9 @@ send_document(cupsd_client_t  *con,	/* I
 
   cupsdUpdateQuota(printer, job->username, 0, kbytes);
 
-  if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
-                               IPP_TAG_INTEGER)) != NULL)
+  job->koctets += kbytes;
+
+  if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
     attr->values[0].integer += kbytes;
 
   snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id,
diff -up cups-1.7.5/scheduler/job.c.str2913 cups-1.7.5/scheduler/job.c
--- cups-1.7.5/scheduler/job.c.str2913	2014-08-20 17:19:25.261909213 +0100
+++ cups-1.7.5/scheduler/job.c	2014-08-20 17:19:25.272909284 +0100
@@ -1707,9 +1707,10 @@ cupsdLoadJob(cupsd_job_t *job)		/* I - J
   job->file_time    = 0;
   job->history_time = 0;
 
-  if (job->state_value >= IPP_JOB_CANCELED &&
-      (attr = ippFindAttribute(job->attrs, "time-at-completed",
-			       IPP_TAG_INTEGER)) != NULL)
+  if ((attr = ippFindAttribute(job->attrs, "time-at-creation", IPP_TAG_INTEGER)) != NULL)
+    job->creation_time = attr->values[0].integer;
+
+  if (job->state_value >= IPP_JOB_CANCELED && (attr = ippFindAttribute(job->attrs, "time-at-completed", IPP_TAG_INTEGER)) != NULL)
   {
     job->completed_time = attr->values[0].integer;
 
@@ -1858,6 +1859,12 @@ cupsdLoadJob(cupsd_job_t *job)		/* I - J
     cupsdSetString(&job->username, attr->values[0].string.text);
   }
 
+  if (!job->name)
+  {
+    if ((attr = ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME)) != NULL)
+      cupsdSetString(&job->name, attr->values[0].string.text);
+  }
+
  /*
   * Set the job hold-until time and state...
   */
@@ -1882,6 +1889,9 @@ cupsdLoadJob(cupsd_job_t *job)		/* I - J
     job->state_value              = IPP_JOB_PENDING;
   }
 
+  if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
+    job->koctets = attr->values[0].integer;
+
   if (!job->num_files)
   {
    /*
@@ -2190,14 +2200,18 @@ cupsdSaveAllJobs(void)
   {
     cupsFilePrintf(fp, "<Job %d>\n", job->id);
     cupsFilePrintf(fp, "State %d\n", job->state_value);
+    cupsFilePrintf(fp, "Created %ld\n", (long)job->creation_time);
     if (job->completed_time)
       cupsFilePrintf(fp, "Completed %ld\n", (long)job->completed_time);
     cupsFilePrintf(fp, "Priority %d\n", job->priority);
     if (job->hold_until)
       cupsFilePrintf(fp, "HoldUntil %ld\n", (long)job->hold_until);
     cupsFilePrintf(fp, "Username %s\n", job->username);
+    if (job->name)
+      cupsFilePutConf(fp, "Name", job->name);
     cupsFilePrintf(fp, "Destination %s\n", job->dest);
     cupsFilePrintf(fp, "DestType %d\n", job->dtype);
+    cupsFilePrintf(fp, "KOctets %d\n", job->koctets);
     cupsFilePrintf(fp, "NumFiles %d\n", job->num_files);
     for (i = 0; i < job->num_files; i ++)
       cupsFilePrintf(fp, "File %d %s/%s %d\n", i + 1, job->filetypes[i]->super,
@@ -4138,7 +4152,7 @@ load_job_cache(const char *filename)	/*
 	cupsArrayAdd(ActiveJobs, job);
       else if (job->state_value > IPP_JOB_STOPPED)
       {
-        if (!job->completed_time)
+        if (!job->completed_time || !job->creation_time || !job->name || !job->koctets)
 	{
 	  cupsdLoadJob(job);
 	  unload_job(job);
@@ -4161,6 +4175,14 @@ load_job_cache(const char *filename)	/*
       else if (job->state_value > IPP_JOB_COMPLETED)
         job->state_value = IPP_JOB_COMPLETED;
     }
+    else if (!_cups_strcasecmp(line, "Name"))
+    {
+      cupsdSetString(&(job->name), value);
+    }
+    else if (!_cups_strcasecmp(line, "Created"))
+    {
+      job->creation_time = strtol(value, NULL, 10);
+    }
     else if (!_cups_strcasecmp(line, "Completed"))
     {
       job->completed_time = strtol(value, NULL, 10);
@@ -4185,6 +4207,10 @@ load_job_cache(const char *filename)	/*
     {
       job->dtype = (cups_ptype_t)atoi(value);
     }
+    else if (!_cups_strcasecmp(line, "KOctets"))
+    {
+      job->koctets = atoi(value);
+    }
     else if (!_cups_strcasecmp(line, "NumFiles"))
     {
       job->num_files = atoi(value);
diff -up cups-1.7.5/scheduler/job.h.str2913 cups-1.7.5/scheduler/job.h
--- cups-1.7.5/scheduler/job.h.str2913	2014-08-20 17:19:25.196908795 +0100
+++ cups-1.7.5/scheduler/job.h	2014-08-20 17:19:25.273909291 +0100
@@ -39,6 +39,8 @@ struct cupsd_job_s			/**** Job request *
 					 * waiting on files */
   char			*username;	/* Printing user */
   char			*dest;		/* Destination printer or class */
+  char			*name;		/* Job name/title */
+  int			koctets;	/* job-k-octets */
   cups_ptype_t		dtype;		/* Destination type */
   cupsd_printer_t	*printer;	/* Printer this job is assigned to */
   int			num_files;	/* Number of files in job */
@@ -47,6 +49,7 @@ struct cupsd_job_s			/**** Job request *
   ipp_attribute_t	*sheets;	/* job-media-sheets-completed */
   time_t		access_time,	/* Last access time */
 			cancel_time,	/* When to cancel/send SIGTERM */
+			creation_time,	/* When job was created */
 			completed_time,	/* When job was completed (0 if not) */
 			file_time,	/* Job file retain time */
 			history_time,	/* Job history retain time */