/*
- * "$Id: ipp.c 9759 2011-05-11 03:24:33Z mike $"
+ * "$Id$"
*
* IPP backend for CUPS.
*
- * Copyright 2007-2012 by Apple Inc.
+ * Copyright 2007-2013 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
/* Username for device URI */
*password = NULL;
/* Password for device URI */
-static int password_tries = 0;
- /* Password tries */
static const char * const pattrs[] = /* Printer attributes we want */
{
#ifdef HAVE_LIBZ
int print_color_mode);
static const char *password_cb(const char *prompt, http_t *http,
const char *method, const char *resource,
- void *user_data);
+ int *user_data);
static const char *quote_string(const char *s, char *q, size_t qsize);
static void report_attr(ipp_attribute_t *attr);
static void report_printer_state(ipp_t *ipp);
*name, /* Name of option */
*value, /* Value of option */
sep; /* Separator character */
+ int password_tries = 0; /* Password tries */
http_addrlist_t *addrlist; /* Address of printer */
int snmp_enabled = 1; /* Is SNMP enabled? */
int snmp_fd, /* SNMP socket */
ipp_attribute_t *copies_sup; /* copies-supported */
ipp_attribute_t *cups_version; /* cups-version */
ipp_attribute_t *format_sup; /* document-format-supported */
+ ipp_attribute_t *job_auth; /* job-authorization-uri */
ipp_attribute_t *media_col_sup; /* media-col-supported */
ipp_attribute_t *operations_sup; /* operations-supported */
ipp_attribute_t *doc_handling_sup; /* multiple-document-handling-supported */
* that way.
*/
- if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
+ if (!getuid() && (value = getenv("AUTH_UID")) != NULL &&
+ !getenv("AUTH_PASSWORD"))
{
uid_t uid = (uid_t)atoi(value);
/* User ID */
if (!port)
port = IPP_PORT; /* Default to port 631 */
- if (!strcmp(scheme, "https"))
+ if (!strcmp(scheme, "https") || !strcmp(scheme, "ipps"))
cupsSetEncryption(HTTP_ENCRYPT_ALWAYS);
else
cupsSetEncryption(HTTP_ENCRYPT_IF_REQUESTED);
* Set the authentication info, if any...
*/
- cupsSetPasswordCB2(password_cb, NULL);
+ cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
if (username[0])
{
return (CUPS_BACKEND_OK);
}
- http = _httpCreate(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
- _HTTP_MODE_CLIENT);
+ http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
+ 0, NULL);
httpSetTimeout(http, 30.0, timeout_cb, NULL);
/*
}
else if (!compression)
{
- if (ippContainsString(compression_sup, "deflate"))
- compression = "deflate";
- else if (ippContainsString(compression_sup, "gzip"))
+ if (ippContainsString(compression_sup, "gzip"))
compression = "gzip";
+ else if (ippContainsString(compression_sup, "deflate"))
+ compression = "deflate";
if (compression)
fprintf(stderr, "DEBUG: Automatically using \"%s\" compression.\n",
/*
* If the printer only claims to support IPP/1.0, or if the user specifically
* included version=1.0 in the URI, then do not try to use Create-Job or
- * Send-Document. This is another dreaded compatibility hack, but unfortunately
- * there are enough broken printers out there that we need this for now...
+ * Send-Document. This is another dreaded compatibility hack, but
+ * unfortunately there are enough broken printers out there that we need
+ * this for now...
*/
if (version == 10)
copies_sup ? copies : 1, document_format, pc, ppd,
media_col_sup, doc_handling_sup, print_color_mode);
- ippDelete(cupsDoRequest(http, request, resource));
+ response = cupsDoRequest(http, request, resource);
ipp_status = cupsLastError();
fprintf(stderr, "DEBUG: Validate-Job: %s (%s)\n",
ippErrorString(ipp_status), cupsLastErrorString());
+ if ((job_auth = ippFindAttribute(response, "job-authorization-uri",
+ IPP_TAG_URI)) != NULL)
+ num_options = cupsAddOption("job-authorization-uri",
+ ippGetString(job_auth, 0, NULL), num_options,
+ &options);
+
+ ippDelete(response);
+
if (job_canceled)
break;
http_status = cupsSendRequest(http, request, resource, length);
if (http_status == HTTP_CONTINUE && request->state == IPP_DATA)
{
+ if (compression && strcmp(compression, "none"))
+ httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
+
if (num_files == 1)
{
if ((fd = open(files[0], O_RDONLY)) < 0)
{
fprintf(stderr, "DEBUG: Read %d bytes...\n", (int)bytes);
- if (cupsWriteRequestData(http, buffer, bytes) != HTTP_CONTINUE)
+ if ((http_status = cupsWriteRequestData(http, buffer, bytes))
+ != HTTP_CONTINUE)
break;
}
else if (bytes == 0 || (errno != EINTR && errno != EAGAIN))
}
}
+ if (http_status == HTTP_ERROR)
+ fprintf(stderr, "DEBUG: Error writing document data for "
+ "Print-Job: %s\n", strerror(httpError(http)));
+
if (num_files == 1)
close(fd);
}
}
else if (ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
+ ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
"requesting-user-name", NULL, argv[2]);
- if ((i + 1) >= num_files)
- ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "last-document",
+ (i + 1) >= num_files);
if (document_format)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
close(fd);
}
+ if (http_status == HTTP_ERROR)
+ fprintf(stderr, "DEBUG: Error writing document data for "
+ "Send-Document: %s\n", strerror(httpError(http)));
+
ippDelete(cupsGetResponse(http, resource));
ippDelete(request);
goto cleanup;
}
+ else if (ipp_status == IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED)
+ {
+ /*
+ * Server is configured incorrectly; the policy for Create-Job and
+ * Send-Document has to be the same (auth or no auth, encryption or
+ * no encryption). Force the queue to stop since printing will never
+ * work.
+ */
+
+ fputs("DEBUG: The server or printer is configured incorrectly.\n",
+ stderr);
+ fputs("DEBUG: The policy for Create-Job and Send-Document must have the "
+ "same authentication and encryption requirements.\n", stderr);
+
+ ipp_status = IPP_STATUS_ERROR_INTERNAL;
+
+ if (job_id > 0)
+ cancel_job(http, uri, job_id, resource, argv[2], version);
+
+ goto cleanup;
+ }
else if (ipp_status == IPP_NOT_FOUND)
{
/*
backendCheckSideChannel(snmp_fd, http->hostaddr);
+ /*
+ * Check printer state...
+ */
+
+ check_printer_state(http, uri, resource, argv[2], version);
+
+ if (cupsLastError() <= IPP_OK_CONFLICT)
+ password_tries = 0;
+
/*
* Build an IPP_GET_JOB_ATTRIBUTES request...
*/
check_printer_state(http, uri, resource, argv[2], version);
+ if (cupsLastError() <= IPP_OK_CONFLICT)
+ password_tries = 0;
+
/*
* Collect the final page count as needed...
*/
if (have_supplies &&
- !backendSNMPSupplies(snmp_fd, http->hostaddr, &page_count, NULL) &&
+ !backendSNMPSupplies(snmp_fd, &(http->addrlist->addr), &page_count,
+ NULL) &&
page_count > start_count)
fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
fputs("JOBSTATE: account-authorization-failed\n", stderr);
if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
- ipp_status == IPP_AUTHENTICATION_CANCELED ||
- ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
- ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
- ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
- ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
+ ipp_status == IPP_AUTHENTICATION_CANCELED)
return (CUPS_BACKEND_AUTH_REQUIRED);
+ else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
+ ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
+ ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
+ ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
+ return (CUPS_BACKEND_HOLD);
else if (ipp_status == IPP_INTERNAL_ERROR)
return (CUPS_BACKEND_STOP);
else if (ipp_status == IPP_CONFLICT)
return (CUPS_BACKEND_FAILED);
else if (ipp_status == IPP_REQUEST_VALUE ||
+ ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
ipp_status == IPP_DOCUMENT_FORMAT || job_canceled < 0)
{
if (ipp_status == IPP_REQUEST_VALUE)
else if (ipp_status == IPP_DOCUMENT_FORMAT)
_cupsLangPrintFilter(stderr, "ERROR",
_("Printer cannot print supplied content."));
+ else if (ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES)
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Printer cannot print with supplied options."));
else
_cupsLangPrintFilter(stderr, "ERROR", _("Print job canceled at printer."));
fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
ippErrorString(cupsLastError()), cupsLastErrorString());
- if (cupsLastError() <= IPP_OK_CONFLICT)
- password_tries = 0;
-
/*
* Return the printer-state value...
*/
const char *job_name; /* Job name */
ipp_jstate_t job_state; /* Job state */
const char *job_user; /* Job originating user name */
+ int password_tries = 0; /* Password tries */
/*
* Make a copy of the printer connection...
*/
- http = _httpCreate(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
- monitor->encryption, 1, _HTTP_MODE_CLIENT);
+ http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
+ monitor->encryption, 1, 0, NULL);
httpSetTimeout(http, 30.0, timeout_cb, NULL);
if (username[0])
cupsSetUser(username);
- cupsSetPasswordCB2(password_cb, NULL);
+
+ cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
/*
* Loop until the job is canceled, aborted, or completed.
monitor->resource,
monitor->user,
monitor->version);
+ if (cupsLastError() <= IPP_OK_CONFLICT)
+ password_tries = 0;
/*
* Check the status of the job itself...
"job-password-encryption", NULL, keyword);
}
- if (pc->account_id &&
- (keyword = cupsGetOption("job-account-id", num_options,
- options)) != NULL)
- ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-account-id",
- NULL, keyword);
+ if (pc->account_id)
+ {
+ if ((keyword = cupsGetOption("job-account-id", num_options,
+ options)) == NULL)
+ keyword = cupsGetOption("job-billing", num_options, options);
- if (pc->account_id &&
- (keyword = cupsGetOption("job-accounting-user-id", num_options,
- options)) != NULL)
- ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME,
- "job-accounting-user-id", NULL, keyword);
+ if (keyword)
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-account-id",
+ NULL, keyword);
+ }
+
+ if (pc->accounting_user_id)
+ {
+ if ((keyword = cupsGetOption("job-accounting-user-id", num_options,
+ options)) == NULL)
+ keyword = user;
+
+ if (keyword)
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME,
+ "job-accounting-user-id", NULL, keyword);
+ }
for (mandatory = (char *)cupsArrayFirst(pc->mandatory);
mandatory;
http_t *http, /* I - Connection */
const char *method, /* I - Request method (not used) */
const char *resource, /* I - Resource path (not used) */
- void *user_data) /* I - User data (not used) */
+ int *password_tries) /* I - Password tries */
{
char def_username[HTTP_MAX_VALUE]; /* Default username */
- fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\"), password=%p, "
- "password_tries=%d\n", prompt, password, password_tries);
+ fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\", http=%p, method=\"%s\", "
+ "resource=\"%s\", password_tries=%p(%d)), password=%p\n",
+ prompt, http, method, resource, password_tries, *password_tries,
+ password);
(void)prompt;
(void)method;
(void)resource;
- (void)user_data;
/*
* Remember that we need to authenticate...
quote_string(def_username, quoted, sizeof(quoted)));
}
- if (password && *password && password_tries < 3)
+ if (password && *password && *password_tries < 3)
{
- password_tries ++;
+ (*password_tries) ++;
return (password);
}
if (conn)
{
- xpc_connection_suspend(conn);
xpc_connection_cancel(conn);
xpc_release(conn);
}
}
/*
- * End of "$Id: ipp.c 9759 2011-05-11 03:24:33Z mike $".
+ * End of "$Id$".
*/