diff --git a/cups-str2913.patch b/cups-str2913.patch new file mode 100644 index 0000000..9576f60 --- /dev/null +++ b/cups-str2913.patch @@ -0,0 +1,400 @@ +diff -up cups-1.6.4/scheduler/ipp.c.str2913 cups-1.6.4/scheduler/ipp.c +--- cups-1.6.4/scheduler/ipp.c.str2913 2014-08-21 11:32:28.833339773 +0100 ++++ cups-1.6.4/scheduler/ipp.c 2014-08-21 11:34:37.689179809 +0100 +@@ -1575,8 +1575,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) +@@ -1700,6 +1699,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) + { +@@ -1794,8 +1796,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); +@@ -4433,8 +4434,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); +@@ -4856,7 +4858,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_JOB_ABORTED : ++ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-aborted-by-system"); ++ break; ++ case IPP_JOB_CANCELED : ++ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-canceled-by-user"); ++ break; ++ case IPP_JOB_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); ++ } + } + + +@@ -6422,9 +6472,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 */ +@@ -6590,8 +6644,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) + { +@@ -6603,11 +6656,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) + { +@@ -6619,15 +6681,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."), +@@ -6652,6 +6711,44 @@ get_jobs(cupsd_client_t *con, /* I - C + cupsArrayAdd(ra, "job-uri"); + } + ++ 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... + */ +@@ -6677,13 +6774,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) +@@ -6733,13 +6832,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)) +@@ -8473,8 +8578,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; + + /* +@@ -9709,8 +9815,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.6.4/scheduler/job.c.str2913 cups-1.6.4/scheduler/job.c +--- cups-1.6.4/scheduler/job.c.str2913 2014-08-21 11:32:28.834339779 +0100 ++++ cups-1.6.4/scheduler/job.c 2014-08-21 11:32:28.839339812 +0100 +@@ -1766,9 +1766,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; + +@@ -1920,6 +1921,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... + */ +@@ -1944,6 +1951,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) + { + /* +@@ -2256,14 +2266,18 @@ cupsdSaveAllJobs(void) + { + cupsFilePrintf(fp, "\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, +@@ -4166,7 +4180,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); +@@ -4189,6 +4203,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); +@@ -4213,6 +4235,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.6.4/scheduler/job.h.str2913 cups-1.6.4/scheduler/job.h +--- cups-1.6.4/scheduler/job.h.str2913 2014-08-21 11:32:28.834339779 +0100 ++++ cups-1.6.4/scheduler/job.h 2014-08-21 11:32:28.839339812 +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 */ diff --git a/cups-str4396.patch b/cups-str4396.patch new file mode 100644 index 0000000..ffb33c5 --- /dev/null +++ b/cups-str4396.patch @@ -0,0 +1,270 @@ +diff -up cups-1.6.4/scheduler/ipp.c.str4396 cups-1.6.4/scheduler/ipp.c +--- cups-1.6.4/scheduler/ipp.c.str4396 2014-08-21 11:31:08.764817790 +0100 ++++ cups-1.6.4/scheduler/ipp.c 2014-08-21 11:31:08.835818252 +0100 +@@ -6429,6 +6429,7 @@ get_jobs(cupsd_client_t *con, /* I - C + cupsd_job_t *job; /* Current job pointer */ + cupsd_printer_t *printer; /* Printer */ + cups_array_t *list; /* Which job list... */ ++ int delete_list = 0; /* Delete the list afterwards? */ + cups_array_t *ra, /* Requested attributes array */ + *exclude; /* Private attributes array */ + cupsd_policy_t *policy; /* Current policy */ +@@ -6528,13 +6529,15 @@ get_jobs(cupsd_client_t *con, /* I - C + { + job_comparison = 1; + job_state = IPP_JOB_CANCELED; +- list = Jobs; ++ list = cupsdGetCompletedJobs(printer); ++ delete_list = 1; + } + else if (!strcmp(attr->values[0].string.text, "aborted")) + { + job_comparison = 0; + job_state = IPP_JOB_ABORTED; +- list = Jobs; ++ list = cupsdGetCompletedJobs(printer); ++ delete_list = 1; + } + else if (!strcmp(attr->values[0].string.text, "all")) + { +@@ -6546,7 +6549,8 @@ get_jobs(cupsd_client_t *con, /* I - C + { + job_comparison = 0; + job_state = IPP_JOB_CANCELED; +- list = Jobs; ++ list = cupsdGetCompletedJobs(printer); ++ delete_list = 1; + } + else if (!strcmp(attr->values[0].string.text, "pending")) + { +@@ -6759,6 +6763,9 @@ get_jobs(cupsd_client_t *con, /* I - C + + cupsArrayDelete(ra); + ++ if (delete_list) ++ cupsArrayDelete(list); ++ + con->response->request.status.status_code = IPP_OK; + } + +diff -up cups-1.6.4/scheduler/job.c.str4396 cups-1.6.4/scheduler/job.c +--- cups-1.6.4/scheduler/job.c.str4396 2014-08-21 11:31:08.816818129 +0100 ++++ cups-1.6.4/scheduler/job.c 2014-08-21 11:31:08.836818259 +0100 +@@ -174,6 +174,7 @@ static mime_filter_t gziptoany_filter = + */ + + static int compare_active_jobs(void *first, void *second, void *data); ++static int compare_completed_jobs(void *first, void *second, void *data); + static int compare_jobs(void *first, void *second, void *data); + static void dump_job_history(cupsd_job_t *job); + static void finalize_job(cupsd_job_t *job, int set_job_state); +@@ -1544,6 +1545,30 @@ cupsdFindJob(int id) /* I - Job ID */ + + + /* ++ * 'cupsdGetCompletedJobs()'- Generate a completed jobs list. ++ */ ++ ++cups_array_t * /* O - Array of jobs */ ++cupsdGetCompletedJobs( ++ cupsd_printer_t *p) /* I - Printer */ ++{ ++ cups_array_t *list; /* Array of jobs */ ++ cupsd_job_t *job; /* Current job */ ++ ++ ++ list = cupsArrayNew(compare_completed_jobs, NULL); ++ ++ for (job = (cupsd_job_t *)cupsArrayFirst(Jobs); ++ job; ++ job = (cupsd_job_t *)cupsArrayNext(Jobs)) ++ if ((!p || !_cups_strcasecmp(p->name, job->dest)) && job->state_value >= IPP_JOB_STOPPED && job->completed_time) ++ cupsArrayAdd(list, job); ++ ++ return (list); ++} ++ ++ ++/* + * 'cupsdGetPrinterJobCount()' - Get the number of pending, processing, + * or held jobs in a printer or class. + */ +@@ -1745,6 +1770,8 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J + (attr = ippFindAttribute(job->attrs, "time-at-completed", + IPP_TAG_INTEGER)) != NULL) + { ++ job->completed_time = attr->values[0].integer; ++ + if (JobHistory < INT_MAX) + job->history_time = attr->values[0].integer + JobHistory; + else +@@ -2229,8 +2256,11 @@ cupsdSaveAllJobs(void) + { + cupsFilePrintf(fp, "\n", job->id); + cupsFilePrintf(fp, "State %d\n", job->state_value); ++ if (job->completed_time) ++ cupsFilePrintf(fp, "Completed %ld\n", (long)job->completed_time); + cupsFilePrintf(fp, "Priority %d\n", job->priority); +- cupsFilePrintf(fp, "HoldUntil %d\n", (int)job->hold_until); ++ if (job->hold_until) ++ cupsFilePrintf(fp, "HoldUntil %ld\n", (long)job->hold_until); + cupsFilePrintf(fp, "Username %s\n", job->username); + cupsFilePrintf(fp, "Destination %s\n", job->dest); + cupsFilePrintf(fp, "DestType %d\n", job->dtype); +@@ -2888,6 +2918,28 @@ compare_active_jobs(void *first, /* I - + + + /* ++ * 'compare_completed_jobs()' - Compare the job IDs and completion times of two jobs. ++ */ ++ ++static int /* O - Difference */ ++compare_completed_jobs(void *first, /* I - First job */ ++ void *second, /* I - Second job */ ++ void *data) /* I - App data (not used) */ ++{ ++ int diff; /* Difference */ ++ ++ ++ (void)data; ++ ++ if ((diff = ((cupsd_job_t *)second)->completed_time - ++ ((cupsd_job_t *)first)->completed_time) != 0) ++ return (diff); ++ else ++ return (((cupsd_job_t *)first)->id - ((cupsd_job_t *)second)->id); ++} ++ ++ ++/* + * 'compare_jobs()' - Compare the job IDs of two jobs. + */ + +@@ -4112,6 +4164,14 @@ load_job_cache(const char *filename) /* + + if (job->state_value <= IPP_JOB_STOPPED && cupsdLoadJob(job)) + cupsArrayAdd(ActiveJobs, job); ++ else if (job->state_value > IPP_JOB_STOPPED) ++ { ++ if (!job->completed_time) ++ { ++ cupsdLoadJob(job); ++ unload_job(job); ++ } ++ } + + job = NULL; + } +@@ -4129,9 +4189,13 @@ 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, "Completed")) ++ { ++ job->completed_time = strtol(value, NULL, 10); ++ } + else if (!_cups_strcasecmp(line, "HoldUntil")) + { +- job->hold_until = atoi(value); ++ job->hold_until = strtol(value, NULL, 10); + } + else if (!_cups_strcasecmp(line, "Priority")) + { +@@ -4469,6 +4533,8 @@ set_time(cupsd_job_t *job, /* I - Job t + + if (!strcmp(name, "time-at-completed")) + { ++ job->completed_time = curtime; ++ + if (JobHistory < INT_MAX && attr) + job->history_time = attr->values[0].integer + JobHistory; + else +diff -up cups-1.6.4/scheduler/job.h.str4396 cups-1.6.4/scheduler/job.h +--- cups-1.6.4/scheduler/job.h.str4396 2013-07-23 13:31:34.000000000 +0100 ++++ cups-1.6.4/scheduler/job.h 2014-08-21 11:31:08.836818259 +0100 +@@ -47,6 +47,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 */ ++ completed_time, /* When job was completed (0 if not) */ + file_time, /* Job file retain time */ + history_time, /* Job history retain time */ + hold_until, /* Hold expiration date/time */ +@@ -145,6 +146,7 @@ extern void cupsdDeleteJob(cupsd_job_t + cupsd_jobaction_t action); + extern cupsd_job_t *cupsdFindJob(int id); + extern void cupsdFreeAllJobs(void); ++extern cups_array_t *cupsdGetCompletedJobs(cupsd_printer_t *p); + extern int cupsdGetPrinterJobCount(const char *dest); + extern int cupsdGetUserJobCount(const char *username); + extern void cupsdLoadAllJobs(void); +diff -up cups-1.6.4/systemv/lpstat.c.str4396 cups-1.6.4/systemv/lpstat.c +--- cups-1.6.4/systemv/lpstat.c.str4396 2013-07-23 13:31:34.000000000 +0100 ++++ cups-1.6.4/systemv/lpstat.c 2014-08-21 11:31:08.837818265 +0100 +@@ -1374,7 +1374,8 @@ show_jobs(const char *dests, /* I - Des + const char *dest, /* Pointer into job-printer-uri */ + *username, /* Pointer to job-originating-user-name */ + *title, /* Pointer to job-name */ +- *message; /* Pointer to job-printer-state-message */ ++ *message, /* Pointer to job-printer-state-message */ ++ *time_at; /* time-at-xxx attribute name to use */ + int rank, /* Rank in queue */ + jobid, /* job-id */ + size; /* job-k-octets */ +@@ -1391,7 +1392,8 @@ show_jobs(const char *dests, /* I - Des + "job-printer-state-message", + "job-printer-uri", + "job-state-reasons", +- "time-at-creation" ++ "time-at-creation", ++ "time-at-completed" + }; + + +@@ -1457,6 +1459,13 @@ show_jobs(const char *dests, /* I - Des + * Loop through the job list and display them... + */ + ++ if (!strcmp(which, "aborted") || ++ !strcmp(which, "canceled") || ++ !strcmp(which, "completed")) ++ time_at = "time-at-completed"; ++ else ++ time_at = "time-at-creation"; ++ + rank = -1; + + for (attr = response->attrs; attr != NULL; attr = attr->next) +@@ -1492,8 +1501,7 @@ show_jobs(const char *dests, /* I - Des + else if (!strcmp(attr->name, "job-k-octets") && + attr->value_tag == IPP_TAG_INTEGER) + size = attr->values[0].integer; +- else if (!strcmp(attr->name, "time-at-creation") && +- attr->value_tag == IPP_TAG_INTEGER) ++ else if (!strcmp(attr->name, time_at) && attr->value_tag == IPP_TAG_INTEGER) + jobtime = attr->values[0].integer; + else if (!strcmp(attr->name, "job-printer-state-message") && + attr->value_tag == IPP_TAG_TEXT) +diff -up cups-1.6.4/test/5.5-lp.sh.str4396 cups-1.6.4/test/5.5-lp.sh +--- cups-1.6.4/test/5.5-lp.sh.str4396 2014-08-21 11:31:08.837818265 +0100 ++++ cups-1.6.4/test/5.5-lp.sh 2014-08-21 11:32:05.791189556 +0100 +@@ -79,6 +79,19 @@ echo "" + + ./waitjobs.sh + ++echo "LPSTAT Completed Jobs Order Test" ++echo "" ++echo " lpstat -W completed -o" ++$VALGRIND ../systemv/lpstat -W completed -o | tee $BASE/lpstat-completed.txt ++if test "`uniq -d $BASE/lpstat-completed.txt`" != ""; then ++ echo " FAILED" ++ exit 1 ++else ++ echo " PASSED" ++fi ++echo "" ++ ++ + # + # End of "$Id: 5.5-lp.sh 7415 2008-03-31 22:33:20Z mike $". + # diff --git a/cups.spec b/cups.spec index 523cd00..b13c4d1 100644 --- a/cups.spec +++ b/cups.spec @@ -11,7 +11,7 @@ Summary: CUPS printing system Name: cups Epoch: 1 Version: 1.6.4 -Release: 8%{?dist} +Release: 9%{?dist} License: GPLv2 Group: System Environment/Daemons Url: http://www.cups.org/ @@ -77,6 +77,8 @@ Patch46: cups-str4356.patch Patch47: cups-CVE-2014-3537.patch Patch48: cups-CVE-2014-5029-5030-5031.patch Patch49: cups-str4461.patch +Patch50: cups-str4396.patch +Patch51: cups-str2913.patch Patch100: cups-lspp.patch @@ -291,6 +293,11 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch48 -p1 -b .CVE-2014-5029-5030-5031 # Fix conf/log file reading for authenticated users (STR #4461). %patch49 -p1 -b .str4461 +# Upstream patch for STR #4396, pre-requisite for STR #2913 patch. +%patch50 -p1 -b .str4396 +# Upstream patch for STR #2913 to limit Get-Jobs replies to 500 jobs +# (bug #421671). +%patch51 -p1 -b .str2913 %if %lspp # LSPP support. @@ -679,6 +686,11 @@ rm -f %{cups_serverbin}/backend/smb %{_mandir}/man5/ipptoolfile.5.gz %changelog +* Thu Aug 21 2014 Tim Waugh - 1:1.6.4-9 +- Upstream patch for STR #4396, pre-requisite for STR #2913 patch. +- Upstream patch for STR #2913 to limit Get-Jobs replies to 500 jobs + (bug #421671). + * Mon Aug 11 2014 Tim Waugh - 1:1.6.4-8 - Fix conf/log file reading for authenticated users (STR #4461).