/*
* IPP backend for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * "LICENSE" which should have been included with this file. If this
- * file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * This file is subject to the Apple OS-Developed Software exception.
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
#define _CUPS_JSR_ACCOUNT_LIMIT_REACHED 0x08
#define _CUPS_JSR_JOB_PASSWORD_WAIT 0x10
#define _CUPS_JSR_JOB_RELEASE_WAIT 0x20
+#define _CUPS_JSR_DOCUMENT_FORMAT_ERROR 0x40
+#define _CUPS_JSR_DOCUMENT_UNPRINTABLE 0x80
/*
http_encryption_t encryption; /* Use encryption? */
ipp_jstate_t job_state; /* Current job state */
ipp_pstate_t printer_state; /* Current printer state */
+ int retryable; /* Is this a job that should be retried? */
} _cups_monitor_t;
* that way.
*/
- if (!getuid() && (value = getenv("AUTH_UID")) != NULL &&
- !getenv("AUTH_PASSWORD"))
+ if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
{
uid_t uid = (uid_t)atoi(value);
/* User ID */
fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
- if (errno == ECONNREFUSED || errno == EHOSTDOWN ||
- errno == EHOSTUNREACH)
+ if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH || errno == ETIMEDOUT || errno == ENOTCONN)
{
if (contimeout && (time(NULL) - start_time) > contimeout)
{
break;
case EHOSTUNREACH :
+ default :
_cupsLangPrintFilter(stderr, "WARNING",
_("The printer is unreachable at this "
"time."));
break;
case ECONNREFUSED :
- default :
_cupsLangPrintFilter(stderr, "WARNING",
_("The printer is in use."));
break;
monitor.encryption = cupsEncryption();
monitor.job_state = IPP_JOB_PENDING;
monitor.printer_state = IPP_PRINTER_IDLE;
+ monitor.retryable = argc == 6 && document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf");
if (create_job)
{
while (!job_canceled && validate_job)
{
- request = new_request(IPP_VALIDATE_JOB, version, uri, argv[2],
+ request = new_request(IPP_OP_VALIDATE_JOB, version, uri, argv[2],
monitor.job_name, num_options, options, compression,
copies_sup ? copies : 1, document_format, pc, ppd,
media_col_sup, doc_handling_sup, print_color_mode_sup);
else if (ipp_status < IPP_REDIRECTION_OTHER_SITE ||
ipp_status == IPP_BAD_REQUEST)
break;
+ else if (job_auth == NULL && ipp_status > IPP_BAD_REQUEST)
+ goto cleanup;
}
/*
return (CUPS_BACKEND_HOLD);
else if (ipp_status == IPP_INTERNAL_ERROR)
return (CUPS_BACKEND_STOP);
- else if (ipp_status == IPP_CONFLICT)
+ else if (ipp_status == IPP_CONFLICT || ipp_status == IPP_STATUS_ERROR_REQUEST_ENTITY || ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
return (CUPS_BACKEND_FAILED);
else if (ipp_status == IPP_REQUEST_VALUE ||
ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
while (monitor->job_state < IPP_JOB_CANCELED && !job_canceled)
{
/*
- * Reconnect to the printer...
+ * Reconnect to the printer as needed...
*/
- if (!httpReconnect(http))
+ if (httpGetFd(http) < 0)
+ httpReconnect(http);
+
+ if (httpGetFd(http) >= 0)
{
/*
* Connected, so check on the printer state...
* No job-id yet, so continue...
*/
- goto monitor_disconnect;
+ goto monitor_sleep;
}
/*
for (i = 0; i < attr->num_values; i ++)
{
- if (!strcmp(attr->values[i].string.text,
- "account-authorization-failed"))
+ if (!strcmp(attr->values[i].string.text, "account-authorization-failed"))
new_reasons |= _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED;
else if (!strcmp(attr->values[i].string.text, "account-closed"))
new_reasons |= _CUPS_JSR_ACCOUNT_CLOSED;
else if (!strcmp(attr->values[i].string.text, "account-info-needed"))
new_reasons |= _CUPS_JSR_ACCOUNT_INFO_NEEDED;
- else if (!strcmp(attr->values[i].string.text,
- "account-limit-reached"))
+ else if (!strcmp(attr->values[i].string.text, "account-limit-reached"))
new_reasons |= _CUPS_JSR_ACCOUNT_LIMIT_REACHED;
else if (!strcmp(attr->values[i].string.text, "job-password-wait"))
new_reasons |= _CUPS_JSR_JOB_PASSWORD_WAIT;
else if (!strcmp(attr->values[i].string.text, "job-release-wait"))
new_reasons |= _CUPS_JSR_JOB_RELEASE_WAIT;
- if (!job_canceled &&
- (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
+ else if (!strcmp(attr->values[i].string.text, "document-format-error"))
+ new_reasons |= _CUPS_JSR_DOCUMENT_FORMAT_ERROR;
+ else if (!strcmp(attr->values[i].string.text, "document-unprintable"))
+ new_reasons |= _CUPS_JSR_DOCUMENT_UNPRINTABLE;
+
+ if (!job_canceled && (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
job_canceled = 1;
}
fputs("JOBSTATE: job-password-wait\n", stderr);
else if (new_reasons & _CUPS_JSR_JOB_RELEASE_WAIT)
fputs("JOBSTATE: job-release-wait\n", stderr);
+ else if (new_reasons & (_CUPS_JSR_DOCUMENT_FORMAT_ERROR | _CUPS_JSR_DOCUMENT_UNPRINTABLE))
+ {
+ if (monitor->retryable)
+ {
+ /*
+ * Can't print this, so retry as raster...
+ */
+
+ job_canceled = 1;
+ fputs("JOBSTATE: cups-retry-as-raster\n", stderr);
+ }
+ else if (new_reasons & _CUPS_JSR_DOCUMENT_FORMAT_ERROR)
+ {
+ fputs("JOBSTATE: document-format-error\n", stderr);
+ }
+ else
+ {
+ fputs("JOBSTATE: document-unprintable\n", stderr);
+ }
+ }
else
fputs("JOBSTATE: job-printing\n", stderr);
(monitor->job_state == IPP_JOB_CANCELED ||
monitor->job_state == IPP_JOB_ABORTED))
job_canceled = -1;
-
- /*
- * Disconnect from the printer - we'll reconnect on the next poll...
- */
-
- monitor_disconnect:
-
- _httpDisconnect(http);
}
/*
* Sleep for N seconds...
*/
+ monitor_sleep:
+
sleep((unsigned)delay);
delay = _cupsNextDelay(delay, &prev_delay);
if (job_canceled > 0 && monitor->job_id > 0)
{
- if (!httpReconnect(http))
+ if (httpGetFd(http) < 0)
+ httpReconnect(http);
+
+ if (httpGetFd(http) >= 0)
{
cancel_job(http, monitor->uri, monitor->job_id, monitor->resource,
monitor->user, monitor->version);