/*
- * "$Id: ipp.c 7682 2008-06-21 00:06:02Z 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);
*/
cupsdLogMessage(con->response->request.status.status_code
- >= IPP_BAD_REQUEST ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG,
+ >= 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),
/*
- * 'add_job_subscriptions()' - Add any subcriptions for a job.
+ * 'add_job_subscriptions()' - Add any subscriptions for a job.
*/
static void
* 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)
{
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,
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);
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
*/
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...
"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...
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.
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);
uri ? uri->values[0].string.text : "no URI",
con->http.hostname);
- 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)
+ if (printer)
{
- char resource[HTTP_MAX_URI]; /* Resource portion of URI */
- cupsd_location_t *auth; /* Pointer to authentication element */
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);
}
/*
- * End of "$Id: ipp.c 7682 2008-06-21 00:06:02Z mike $".
+ * End of "$Id: ipp.c 7944 2008-09-16 22:32:42Z mike $".
*/