/*
- * "$Id: ipp.c 7014 2007-10-10 21:57:43Z mike $"
+ * "$Id: ipp.c 7944 2008-09-16 22:32:42Z mike $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
* add_job() - Add a job to a print queue.
* add_job_state_reasons() - Add the "job-state-reasons" attribute based
* upon the job and printer state...
- * add_job_subscriptions() - Add any subcriptions for a job.
+ * add_job_subscriptions() - Add any subscriptions for a job.
* add_job_uuid() - Add job-uuid attribute to a job.
* add_printer() - Add a printer to the system.
* add_printer_state_reasons() - Add the "printer-state-reasons" attribute
* move_job() - Move a job to a new destination.
* ppd_parse_line() - Parse a PPD default line.
* print_job() - Print a file to a printer or class.
- * read_ps_job_ticket() - Reads a job ticket embedded in a PS file.
+ * read_job_ticket() - Read a job ticket embedded in a print file.
* reject_jobs() - Reject print jobs to a printer.
* release_job() - Release a held print job.
* renew_subscription() - Renew an existing subscription...
static int ppd_parse_line(const char *line, char *option, int olen,
char *choice, int clen);
static void print_job(cupsd_client_t *con, ipp_attribute_t *uri);
-static void read_ps_job_ticket(cupsd_client_t *con);
+static void read_job_ticket(cupsd_client_t *con);
static void reject_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
static void release_job(cupsd_client_t *con, ipp_attribute_t *uri);
static void renew_subscription(cupsd_client_t *con, int sub_id);
ipp_attribute_t *attr; /* Current attribute */
ipp_attribute_t *charset; /* Character set attribute */
ipp_attribute_t *language; /* Language attribute */
- ipp_attribute_t *uri; /* Printer URI attribute */
+ ipp_attribute_t *uri = NULL; /* Printer or job URI attribute */
ipp_attribute_t *username; /* requesting-user-name attr */
int sub_id; /* Subscription ID */
* Sending data from the scheduler...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdProcessIPPRequest: %d status_code=%x (%s)",
- con->http.fd, con->response->request.status.status_code,
- ippErrorString(con->response->request.status.status_code));
+ cupsdLogMessage(con->response->request.status.status_code
+ >= IPP_BAD_REQUEST &&
+ con->response->request.status.status_code
+ != IPP_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG,
+ "Returning IPP %s for %s (%s) from %s",
+ ippErrorString(con->response->request.status.status_code),
+ ippOpString(con->request->request.op.operation_id),
+ uri ? uri->values[0].string.text : "no URI",
+ con->http.hostname);
if (cupsdSendHeader(con, HTTP_OK, "application/ipp", CUPSD_AUTH_NONE))
{
* Yes...
*/
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Adding end banner page \"%s\".",
- job->id, attr->values[1].string.text);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Adding end banner page \"%s\".",
+ attr->values[1].string.text);
if ((kbytes = copy_banner(NULL, job, attr->values[1].string.text)) < 0)
return (-1);
IPP_TAG_INTEGER)) != NULL)
attr->values[0].integer = 0;
else
- attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
- "job-k-octets", 0);
+ ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", 0);
if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
IPP_TAG_KEYWORD)) == NULL)
cupsdSetString(&attr->values[0].string.text, Classification);
- cupsdLogMessage(CUPSD_LOG_NOTICE, "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s,none\", "
- "job-originating-user-name=\"%s\"",
- job->id, Classification, job->username);
+ 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,
cupsdSetString(&attr->values[1].string.text, attr->values[0].string.text);
- cupsdLogMessage(CUPSD_LOG_NOTICE, "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s,%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text,
- attr->values[1].string.text, job->username);
+ 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") &&
strcmp(attr->values[1].string.text, "none"))))
{
if (attr->num_values == 1)
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION OVERRIDDEN "
- "job-sheets=\"%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE,
+ "CLASSIFICATION OVERRIDDEN "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ attr->values[0].string.text, job->username);
else
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION OVERRIDDEN "
- "job-sheets=\"%s,%s\",fffff "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text,
- attr->values[1].string.text, job->username);
+ 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) &&
}
if (attr->num_values > 1)
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s,%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text,
- attr->values[1].string.text, job->username);
+ 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
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, Classification, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE,
+ "CLASSIFICATION FORCED "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ Classification, job->username);
}
}
if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
{
- cupsdLogMessage(CUPSD_LOG_INFO,
- "[Job %d] Adding start banner page \"%s\".",
- job->id, attr->values[0].string.text);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Adding start banner page \"%s\".",
+ attr->values[0].string.text);
if ((kbytes = copy_banner(con, job, attr->values[0].string.text)) < 0)
{
/*
- * 'add_job_subscriptions()' - Add any subcriptions for a job.
+ * 'add_job_subscriptions()' - Add any subscriptions for a job.
*/
static void
* none...
*/
- for (attr = job->attrs->attrs, prev = NULL;
- attr;
- prev = attr, attr = attr->next)
+ for (attr = job->attrs->attrs; attr; attr = attr->next)
if (attr->group_tag == IPP_TAG_SUBSCRIPTION)
break;
/*
* Remove all of the subscription attributes from the job request...
+ *
+ * TODO: Optimize this since subscription groups have to come at the
+ * end of the request...
*/
for (attr = job->attrs->attrs, prev = NULL; attr; attr = next)
* Do we have a valid device URI?
*/
- http_uri_status_t uri_status; /* URI separation status */
+ http_uri_status_t uri_status; /* URI separation status */
+ char old_device_uri[1024];
+ /* Old device URI */
need_restart_job = 1;
* Could not find device in list!
*/
- send_ipp_status(con, IPP_NOT_POSSIBLE, _("Bad device-uri \"%s\"!"),
- attr->values[0].string.text);
+ send_ipp_status(con, IPP_NOT_POSSIBLE, _("Bad device-uri scheme \"%s\"!"),
+ scheme);
return;
}
}
+ if (printer->sanitized_device_uri)
+ strlcpy(old_device_uri, printer->sanitized_device_uri,
+ sizeof(old_device_uri));
+ else
+ old_device_uri[0] = '\0';
+
+ cupsdSetDeviceURI(printer, attr->values[0].string.text);
+
cupsdLogMessage(CUPSD_LOG_INFO,
"Setting %s device-uri to \"%s\" (was \"%s\".)",
- printer->name,
- cupsdSanitizeURI(attr->values[0].string.text, line,
- sizeof(line)),
- cupsdSanitizeURI(printer->device_uri, resource,
- sizeof(resource)));
+ printer->name, printer->sanitized_device_uri,
+ old_device_uri);
- cupsdSetString(&printer->device_uri, attr->values[0].string.text);
set_device_uri = 1;
}
cupsdAddPrinterHistory(printer);
}
+ if ((attr = ippFindAttribute(con->request, "printer-state-reasons",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ if (attr->num_values >
+ (int)(sizeof(printer->reasons) / sizeof(printer->reasons[0])))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("Too many printer-state-reasons values (%d > %d)!"),
+ attr->num_values,
+ (int)(sizeof(printer->reasons) /
+ sizeof(printer->reasons[0])));
+ return;
+ }
+
+ for (i = 0; i < printer->num_reasons; i ++)
+ _cupsStrFree(printer->reasons[i]);
+
+ printer->num_reasons = 0;
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (!strcmp(attr->values[i].string.text, "none"))
+ continue;
+
+ printer->reasons[printer->num_reasons] =
+ _cupsStrAlloc(attr->values[i].string.text);
+
+ if (!strcmp(printer->reasons[printer->num_reasons], "paused") &&
+ printer->state != IPP_PRINTER_STOPPED)
+ {
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Setting %s printer-state to %d (was %d.)",
+ printer->name, IPP_PRINTER_STOPPED, printer->state);
+ cupsdStopPrinter(printer, 0);
+ }
+
+ printer->num_reasons ++;
+ }
+
+ if (PrintcapFormat == PRINTCAP_PLIST)
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
+ }
+
set_printer_defaults(con, printer);
if ((attr = ippFindAttribute(con->request, "auth-info-required",
device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
- printer_name = CFStringCreateWithCString(kCFAllocatorDefault, p->name,
- kCFStringEncodingUTF8);
+ printer_name = CFStringCreateWithCString(kCFAllocatorDefault,
+ p->name, kCFStringEncodingUTF8);
if (device_name && printer_name)
{
* job object...
*/
- for (i = printer->num_options, num_options = 0, option = printer->options;
+ for (i = printer->num_options, num_options = 0, options = NULL,
+ option = printer->options;
i > 0;
i --, option ++)
if (!ippFindAttribute(job->attrs, option->name, IPP_TAG_ZERO))
cupsdReleaseJob(job);
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Authenticated by \"%s\".", jobid,
- con->username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Authenticated by \"%s\".", con->username);
}
if (purge)
cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Purged by \"%s\".", jobid,
- username);
+ username);
else
cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Canceled by \"%s\".", jobid,
- username);
+ username);
con->response->request.status.status_code = IPP_OK;
}
cups_option_t *defaults; /* Default options */
char cups_protocol[PPD_MAX_LINE];
/* cupsProtocol attribute */
- int have_letter, /* Have Letter size */
- have_a4; /* Have A4 size */
-#ifdef HAVE_LIBPAPER
- char *paper_result; /* Paper size name from libpaper */
- char system_paper[64]; /* Paper size name buffer */
-#endif /* HAVE_LIBPAPER */
cupsdLogMessage(CUPSD_LOG_DEBUG2,
* See if we have data ready...
*/
- bytes = 0;
-
FD_ZERO(&input);
FD_SET(temppipe[0], &input);
FD_SET(CGIPipes[0], &input);
return (-1);
}
- have_letter = ppdPageSize(ppd, "Letter") != NULL;
- have_a4 = ppdPageSize(ppd, "A4") != NULL;
-
/*
* Open the destination (if possible) and set the default options...
*/
cupsFileClose(dst);
}
-#ifdef HAVE_LIBPAPER
- else if ((paper_result = systempapername()) != NULL)
- {
- /*
- * Set the default media sizes from the systemwide default...
- */
-
- strlcpy(system_paper, paper_result, sizeof(system_paper));
- system_paper[0] = toupper(system_paper[0] & 255);
-
- if ((!strcmp(system_paper, "Letter") && have_letter) ||
- (!strcmp(system_paper, "A4") && have_a4))
- {
- num_defaults = cupsAddOption("PageSize", system_paper,
- num_defaults, &defaults);
- num_defaults = cupsAddOption("PageRegion", system_paper,
- num_defaults, &defaults);
- num_defaults = cupsAddOption("PaperDimension", system_paper,
- num_defaults, &defaults);
- num_defaults = cupsAddOption("ImageableArea", system_paper,
- num_defaults, &defaults);
- }
- }
-#endif /* HAVE_LIBPAPER */
- else
+ else if (ppdPageSize(ppd, DefaultPaperSize))
{
/*
* Add the default media sizes...
- *
- * Note: These values are generally not valid for large-format devices
- * like plotters, however it is probably safe to say that those
- * users will configure the media size after initially adding
- * the device anyways...
*/
- if (!DefaultLanguage ||
- !strcasecmp(DefaultLanguage, "C") ||
- !strcasecmp(DefaultLanguage, "POSIX") ||
- !strcasecmp(DefaultLanguage, "en") ||
- !strncasecmp(DefaultLanguage, "en.", 3) ||
- !strncasecmp(DefaultLanguage, "en_US", 5) ||
- !strncasecmp(DefaultLanguage, "en_CA", 5) ||
- !strncasecmp(DefaultLanguage, "fr_CA", 5))
- {
- /*
- * These are the only locales that will default to "letter" size...
- */
-
- if (have_letter)
- {
- num_defaults = cupsAddOption("PageSize", "Letter", num_defaults,
- &defaults);
- num_defaults = cupsAddOption("PageRegion", "Letter", num_defaults,
- &defaults);
- num_defaults = cupsAddOption("PaperDimension", "Letter", num_defaults,
- &defaults);
- num_defaults = cupsAddOption("ImageableArea", "Letter", num_defaults,
- &defaults);
- }
- }
- else if (have_a4)
- {
- /*
- * The rest default to "a4" size...
- */
-
- num_defaults = cupsAddOption("PageSize", "A4", num_defaults,
- &defaults);
- num_defaults = cupsAddOption("PageRegion", "A4", num_defaults,
- &defaults);
- num_defaults = cupsAddOption("PaperDimension", "A4", num_defaults,
- &defaults);
- num_defaults = cupsAddOption("ImageableArea", "A4", num_defaults,
- &defaults);
- }
+ num_defaults = cupsAddOption("PageSize", DefaultPaperSize,
+ num_defaults, &defaults);
+ num_defaults = cupsAddOption("PageRegion", DefaultPaperSize,
+ num_defaults, &defaults);
+ num_defaults = cupsAddOption("PaperDimension", DefaultPaperSize,
+ num_defaults, &defaults);
+ num_defaults = cupsAddOption("ImageableArea", DefaultPaperSize,
+ num_defaults, &defaults);
}
ppdClose(ppd);
ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
"document-count", job->num_files);
+ if (!ra || cupsArrayFind(ra, "job-media-progress"))
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-media-progress", job->progress);
+
if (!ra || cupsArrayFind(ra, "job-more-info"))
ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
"job-more-info", NULL, job_uri);
ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"marker-change-time", printer->marker_time);
+ if (printer->num_printers > 0 &&
+ (!ra || cupsArrayFind(ra, "member-uris")))
+ {
+ ipp_attribute_t *member_uris; /* member-uris attribute */
+ cupsd_printer_t *p2; /* Printer in class */
+ ipp_attribute_t *p2_uri; /* printer-uri-supported for class printer */
+
+
+ if ((member_uris = ippAddStrings(con->response, IPP_TAG_PRINTER,
+ IPP_TAG_URI, "member-uris",
+ printer->num_printers, NULL,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < printer->num_printers; i ++)
+ {
+ p2 = printer->printers[i];
+
+ if ((p2_uri = ippFindAttribute(p2->attrs, "printer-uri-supported",
+ IPP_TAG_URI)) != NULL)
+ member_uris->values[i].string.text =
+ _cupsStrAlloc(p2_uri->values[0].string.text);
+ else
+ {
+ httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri,
+ sizeof(printer_uri), "ipp", NULL, con->servername,
+ con->serverport,
+ (p2->type & CUPS_PRINTER_CLASS) ?
+ "/classes/%s" : "/printers/%s", p2->name);
+ member_uris->values[i].string.text = _cupsStrAlloc(printer_uri);
+ }
+ }
+ }
+ }
+
if (printer->alert && (!ra || cupsArrayFind(ra, "printer-alert")))
ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_STRING,
"printer-alert", NULL, printer->alert);
* Save and log the job...
*/
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Queued on \"%s\" by \"%s\".",
- job->id, job->dest, job->username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Queued on \"%s\" by \"%s\".",
+ job->dest, job->username);
}
cupsArrayAdd(ra, "job-impressions-completed");
cupsArrayAdd(ra, "job-k-octets");
cupsArrayAdd(ra, "job-k-octets-processed");
+ cupsArrayAdd(ra, "job-media-progress");
cupsArrayAdd(ra, "job-media-sheets");
cupsArrayAdd(ra, "job-media-sheets-completed");
cupsArrayAdd(ra, "job-message-from-operator");
cupsArrayAdd(ra, "job-impressions-supported");
cupsArrayAdd(ra, "job-k-octets-supported");
cupsArrayAdd(ra, "job-media-sheets-supported");
+ cupsArrayAdd(ra, "job-settable-attributes-supported");
cupsArrayAdd(ra, "multiple-document-jobs-supported");
cupsArrayAdd(ra, "multiple-operation-time-out");
cupsArrayAdd(ra, "natural-language-configured");
cupsArrayAdd(ra, "printer-state");
cupsArrayAdd(ra, "printer-state-message");
cupsArrayAdd(ra, "printer-state-reasons");
+ cupsArrayAdd(ra, "printer-settable-attributes-supported");
cupsArrayAdd(ra, "printer-type");
cupsArrayAdd(ra, "printer-up-time");
cupsArrayAdd(ra, "printer-uri-supported");
{
if ((!type || (printer->type & CUPS_PRINTER_CLASS) == type) &&
(printer->type & printer_mask) == printer_type &&
- (!location || !printer->location ||
- !strcasecmp(printer->location, location)))
+ (!location ||
+ (printer->location && !strcasecmp(printer->location, location))))
{
/*
* If HideImplicitMembers is enabled, see if this printer or class
* access...
*/
- if (printer->num_users && username && !user_allowed(printer, username))
+ if (!(printer->type & CUPS_PRINTER_AUTHENTICATED) &&
+ printer->num_users && username && !user_allowed(printer, username))
continue;
/*
"Job job-hold-until value changed by user.");
}
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Held by \"%s\".", jobid,
- username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Held by \"%s\".", username);
con->response->request.status.status_code = IPP_OK;
}
*/
if (!strcasecmp(filetype->super, "application") &&
- !strcasecmp(filetype->type, "postscript"))
- read_ps_job_ticket(con);
+ (!strcasecmp(filetype->type, "postscript") ||
+ !strcasecmp(filetype->type, "pdf")))
+ read_job_ticket(con);
/*
* Create the job object...
* Log and save the job...
*/
- cupsdLogMessage(CUPSD_LOG_INFO,
- "[Job %d] File of type %s/%s queued by \"%s\".", job->id,
- filetype->super, filetype->type, job->username);
- cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] hold_until=%d", job->id,
- (int)job->hold_until);
+ cupsdLogJob(job, CUPSD_LOG_INFO,
+ "File of type %s/%s queued by \"%s\".",
+ filetype->super, filetype->type, job->username);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "hold_until=%d", (int)job->hold_until);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Queued on \"%s\" by \"%s\".",
+ job->dest, job->username);
/*
* Start the job if possible...
/*
- * 'read_ps_job_ticket()' - Reads a job ticket embedded in a PS file.
+ * 'read_job_ticket()' - Read a job ticket embedded in a print file.
*
- * This function only gets called when printing a single PostScript
+ * This function only gets called when printing a single PDF or PostScript
* file using the Print-Job operation. It doesn't work for Create-Job +
* Send-File, since the job attributes need to be set at job creation
- * time for banners to work. The embedded PS job ticket stuff is here
- * only to allow the Windows printer driver for CUPS to pass in JCL
+ * time for banners to work. The embedded job ticket stuff is here
+ * primarily to allow the Windows printer driver for CUPS to pass in JCL
* options and IPP attributes which otherwise would be lost.
*
- * The format of a PS job ticket is simple:
+ * The format of a job ticket is simple:
*
* %cupsJobTicket: attr1=value1 attr2=value2 ... attrN=valueN
*
* %cupsJobTicket: attrN=valueN
*
* Job ticket lines must appear immediately after the first line that
- * specifies PostScript format (%!PS-Adobe-3.0), and CUPS will stop
- * looking for job ticket info when it finds a line that does not begin
+ * specifies PostScript (%!PS-Adobe-3.0) or PDF (%PDF) format, and CUPS
+ * stops looking for job ticket info when it finds a line that does not begin
* with "%cupsJobTicket:".
*
* The maximum length of a job ticket line, including the prefix, is
*/
static void
-read_ps_job_ticket(cupsd_client_t *con) /* I - Client connection */
+read_job_ticket(cupsd_client_t *con) /* I - Client connection */
{
cups_file_t *fp; /* File to read from */
char line[256]; /* Line data */
if ((fp = cupsFileOpen(con->filename, "rb")) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "read_ps_job_ticket: Unable to open PostScript print file "
- "- %s",
+ "Unable to open print file for job ticket - %s",
strerror(errno));
return;
}
if (cupsFileGets(fp, line, sizeof(line)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "read_ps_job_ticket: Unable to read from PostScript print "
- "file - %s",
+ "Unable to read from print file for job ticket - %s",
strerror(errno));
cupsFileClose(fp);
return;
}
- if (strncmp(line, "%!PS-Adobe-", 11))
+ if (strncmp(line, "%!PS-Adobe-", 11) && strncmp(line, "%PDF-", 5))
{
/*
* Not a DSC-compliant file, so no job ticket info will be available...
cupsdAddEvent(CUPSD_EVENT_JOB_STATE, cupsdFindDest(job->dest), job,
"Job released by user.");
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Released by \"%s\".", jobid,
- username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Released by \"%s\".", username);
con->response->request.status.status_code = IPP_OK;
+
+ cupsdCheckJobs();
}
cupsdRestartJob(job);
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Restarted by \"%s\".", jobid,
- username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Restarted by \"%s\".", username);
con->response->request.status.status_code = IPP_OK;
}
return;
# endif /* __APPLE__ */
+ if (!KerberosInitialized)
+ {
+ /*
+ * Setup a Kerberos context for the scheduler to use...
+ */
+
+ KerberosInitialized = 1;
+
+ if (krb5_init_context(&KerberosContext))
+ {
+ KerberosContext = NULL;
+
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context");
+ return;
+ }
+ }
+
/*
* We MUST create a file-based cache because memory-based caches are
* only valid for the current process/address space.
cupsdSetStringf(&(job->ccname), "KRB5CCNAME=FILE:%s",
krb5_cc_get_name(KerberosContext, job->ccache));
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] save_krb5_creds: %s", job->id,
- job->ccname);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "save_krb5_creds: %s", job->ccname);
# endif /* HAVE_KRB5_CC_NEW_UNIQUE || HAVE_HEIMDAL */
}
#endif /* HAVE_GSSAPI && HAVE_KRB5_H */
struct stat fileinfo; /* File information */
int kbytes; /* Size of file */
int compression; /* Type of compression */
+ int start_job; /* Start the job? */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", con,
ipp_attribute_t *doc_name; /* document-name attribute */
- cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Auto-typing file...", job->id);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Auto-typing file...");
doc_name = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME);
filetype = mimeFileType(MimeDatabase, con->filename,
if (!filetype)
filetype = mimeType(MimeDatabase, super, type);
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "[Job %d] Request file type is %s/%s.", job->id,
- filetype->super, filetype->type);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Request file type is %s/%s.",
+ filetype->super, filetype->type);
}
else
filetype = mimeType(MimeDatabase, super, type);
- jformat = ippFindAttribute(job->attrs, "document-format", IPP_TAG_MIMETYPE);
-
- if (filetype &&
- (!jformat ||
- (!strcmp(super, "application") && !strcmp(type, "octet-stream"))))
+ if (filetype)
{
/*
* Replace the document-format attribute value with the auto-typed or
snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
filetype->type);
- if (jformat)
+ if ((jformat = ippFindAttribute(job->attrs, "document-format",
+ IPP_TAG_MIMETYPE)) != NULL)
{
_cupsStrFree(jformat->values[0].string.text);
cupsdClearString(&con->filename);
- cupsdLogMessage(CUPSD_LOG_INFO,
- "[Job %d] File of type %s/%s queued by \"%s\".", job->id,
- filetype->super, filetype->type, job->username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "File of type %s/%s queued by \"%s\".",
+ filetype->super, filetype->type, job->username);
/*
* Start the job if this is the last document...
job->dirty = 1;
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
- /*
- * Start the job if possible... Since cupsdCheckJobs() can cancel a
- * job if it doesn't print, we need to re-find the job afterwards...
- */
-
- jobid = job->id;
-
- cupsdCheckJobs();
-
- job = cupsdFindJob(jobid);
+ start_job = 1;
}
else
{
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
+
+ start_job = 0;
}
/*
ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", jobid);
ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state",
- job ? job->state_value : IPP_JOB_CANCELED);
+ job->state_value);
add_job_state_reasons(con, job);
con->response->request.status.status_code = IPP_OK;
+
+ /*
+ * Start the job if necessary...
+ */
+
+ if (start_job)
+ cupsdCheckJobs();
}
http_status_t status, /* I - HTTP status code */
cupsd_printer_t *printer) /* I - Printer, if any */
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s",
- ippOpString(con->request->request.op.operation_id),
- httpStatus(status));
-
- if (status == HTTP_UNAUTHORIZED &&
- printer && printer->num_auth_info_required > 0 &&
- !strcmp(printer->auth_info_required[0], "negotiate"))
- cupsdSendError(con, status, CUPSD_AUTH_NEGOTIATE);
- else if (printer)
- {
- char resource[HTTP_MAX_URI]; /* Resource portion of URI */
- cupsd_location_t *auth; /* Pointer to authentication element */
+ ipp_attribute_t *uri; /* Request URI, if any */
+
+
+ if ((uri = ippFindAttribute(con->request, "printer-uri",
+ IPP_TAG_URI)) == NULL)
+ uri = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI);
+
+ cupsdLogMessage(status == HTTP_FORBIDDEN ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG,
+ "Returning HTTP %s for %s (%s) from %s",
+ httpStatus(status),
+ ippOpString(con->request->request.op.operation_id),
+ uri ? uri->values[0].string.text : "no URI",
+ con->http.hostname);
+
+ if (printer)
+ {
int auth_type; /* Type of authentication required */
- if (printer->type & CUPS_PRINTER_CLASS)
- snprintf(resource, sizeof(resource), "/classes/%s", printer->name);
- else
- snprintf(resource, sizeof(resource), "/printers/%s", printer->name);
-
- if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
- auth->type == CUPSD_AUTH_NONE)
- auth = cupsdFindPolicyOp(printer->op_policy_ptr,
- con->request ?
- con->request->request.op.operation_id :
- IPP_PRINT_JOB);
-
- if (!auth)
- auth_type = CUPSD_AUTH_NONE;
- else if (auth->type == CUPSD_AUTH_DEFAULT)
- auth_type = DefaultAuthType;
+ auth_type = CUPSD_AUTH_NONE;
+
+ if (status == HTTP_UNAUTHORIZED &&
+ printer->num_auth_info_required > 0 &&
+ !strcmp(printer->auth_info_required[0], "negotiate") &&
+ con->request &&
+ (con->request->request.op.operation_id == IPP_PRINT_JOB ||
+ con->request->request.op.operation_id == IPP_CREATE_JOB ||
+ con->request->request.op.operation_id == CUPS_AUTHENTICATE_JOB))
+ {
+ /*
+ * Creating and authenticating jobs requires Kerberos...
+ */
+
+ auth_type = CUPSD_AUTH_NEGOTIATE;
+ }
else
- auth_type = auth->type;
+ {
+ /*
+ * Use policy/location-defined authentication requirements...
+ */
+
+ char resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ cupsd_location_t *auth; /* Pointer to authentication element */
+
+
+ if (printer->type & CUPS_PRINTER_CLASS)
+ snprintf(resource, sizeof(resource), "/classes/%s", printer->name);
+ else
+ snprintf(resource, sizeof(resource), "/printers/%s", printer->name);
+
+ if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
+ auth->type == CUPSD_AUTH_NONE)
+ auth = cupsdFindPolicyOp(printer->op_policy_ptr,
+ con->request ?
+ con->request->request.op.operation_id :
+ IPP_PRINT_JOB);
+
+ if (auth)
+ {
+ if (auth->type == CUPSD_AUTH_DEFAULT)
+ auth_type = DefaultAuthType;
+ else
+ auth_type = auth->type;
+ }
+ }
cupsdSendError(con, status, auth_type);
}
static void
send_ipp_status(cupsd_client_t *con, /* I - Client connection */
- ipp_status_t status, /* I - IPP status code */
- const char *message, /* I - Status message */
- ...) /* I - Additional args as needed */
+ ipp_status_t status, /* I - IPP status code */
+ const char *message,/* I - Status message */
+ ...) /* I - Additional args as needed */
{
va_list ap; /* Pointer to additional args */
char formatted[1024]; /* Formatted errror message */
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer/class) */
- cupsd_printer_t *printer; /* Printer */
+ cupsd_printer_t *printer, /* Printer */
+ *oldprinter; /* Old default printer */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", con,
* Set it as the default...
*/
+ oldprinter = DefaultPrinter;
DefaultPrinter = printer;
+ if (oldprinter)
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, oldprinter, NULL,
+ "%s is no longer the default printer.", oldprinter->name);
+
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
+ "%s is now the default printer.", printer->name);
+
cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES |
CUPSD_DIRTY_REMOTE | CUPSD_DIRTY_PRINTCAP);
/* Resource portion of URI */
int port; /* Port portion of URI */
int event; /* Events? */
+ int check_jobs; /* Check jobs? */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", con,
cupsdLoadJob(job);
- event = 0;
+ check_jobs = 0;
+ event = 0;
for (attr = con->request->attrs; attr; attr = attr->next)
{
!strcmp(attr->name, "job-detailed-status-messages") ||
!strcmp(attr->name, "job-document-access-errors") ||
!strcmp(attr->name, "job-id") ||
+ !strcmp(attr->name, "job-impressions-completed") ||
!strcmp(attr->name, "job-k-octets") ||
!strcmp(attr->name, "job-originating-host-name") ||
!strcmp(attr->name, "job-originating-user-name") ||
!strcmp(attr->name, "number-of-intervening-jobs") ||
!strcmp(attr->name, "output-device-assigned") ||
!strncmp(attr->name, "date-time-at-", 13) ||
- !strncmp(attr->name, "job-impressions", 15) ||
!strncmp(attr->name, "job-k-octets", 12) ||
!strncmp(attr->name, "job-media-sheets", 16) ||
!strncmp(attr->name, "time-at-", 8))
}
else if (con->response->request.status.status_code == IPP_OK)
{
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-priority to %d",
+ attr->values[0].integer);
cupsdSetJobPriority(job, attr->values[0].integer);
- event |= CUPSD_EVENT_JOB_CONFIG_CHANGED |
- CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED;
+
+ check_jobs = 1;
+ event |= CUPSD_EVENT_JOB_CONFIG_CHANGED |
+ CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED;
}
}
else if (!strcmp(attr->name, "job-state"))
}
else if (con->response->request.status.status_code == IPP_OK)
{
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-state to %d",
+ attr->values[0].integer);
+
job->state->values[0].integer = attr->values[0].integer;
job->state_value = (ipp_jstate_t)attr->values[0].integer;
event |= CUPSD_EVENT_JOB_STATE;
+ check_jobs = 1;
}
break;
return;
}
else if (con->response->request.status.status_code == IPP_OK)
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-state to %d",
+ attr->values[0].integer);
cupsdCancelJob(job, 0, (ipp_jstate_t)attr->values[0].integer);
+
+ check_jobs = 1;
+ }
break;
}
}
if (!strcmp(attr->name, "job-hold-until"))
{
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-hold-until to %s",
+ attr->values[0].string.text);
cupsdSetJobHoldUntil(job, attr->values[0].string.text);
if (!strcmp(attr->values[0].string.text, "no-hold"))
else
cupsdHoldJob(job);
- event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_STATE;
+ check_jobs = 1;
+ event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_STATE;
}
}
else if (attr->value_tag == IPP_TAG_DELETEATTR)
* Start jobs if possible...
*/
- cupsdCheckJobs();
+ if (check_jobs)
+ cupsdCheckJobs();
}
continue;
if (strcmp(attr->values[0].string.text, "abort-job") &&
+ strcmp(attr->values[0].string.text, "retry-current-job") &&
strcmp(attr->values[0].string.text, "retry-job") &&
strcmp(attr->values[0].string.text, "stop-printer"))
{
if (cupsdCheckGroup(username, pw, p->users[i] + 1))
break;
}
+ else if (p->users[i][0] == '#')
+ {
+ /*
+ * Check UUID...
+ */
+
+ if (cupsdCheckGroup(username, pw, p->users[i]))
+ break;
+ }
else if (!strcasecmp(username, p->users[i]))
break;
}
/*
- * End of "$Id: ipp.c 7014 2007-10-10 21:57:43Z mike $".
+ * End of "$Id: ipp.c 7944 2008-09-16 22:32:42Z mike $".
*/