Index: cups/http.c =================================================================== --- cups/http.c (revision 9499) +++ cups/http.c (working copy) @@ -3,7 +3,7 @@ * * HTTP routines for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -67,6 +67,7 @@ * httpSetField() - Set the value of an HTTP header. * httpSetLength() - Set the content-length and content-encoding. * httpTrace() - Send an TRACE request to the server. + * _httpUpdate() - Update the current HTTP status for incoming data. * httpUpdate() - Update the current HTTP state for incoming data. * _httpWait() - Wait for data available on a connection (no flush). * httpWait() - Wait for data available on a connection. @@ -2012,163 +2013,202 @@ /* - * 'httpUpdate()' - Update the current HTTP state for incoming data. + * '_httpUpdate()' - Update the current HTTP status for incoming data. + * + * Note: Unlike httpUpdate(), this function does not flush pending write data + * and only retrieves a single status line from the HTTP connection. */ -http_status_t /* O - HTTP status */ -httpUpdate(http_t *http) /* I - Connection to server */ +int /* O - 1 to continue, 0 to stop */ +_httpUpdate(http_t *http, /* I - Connection to server */ + http_status_t *status) /* O - Current HTTP status */ { char line[32768], /* Line from connection... */ *value; /* Pointer to value on line */ http_field_t field; /* Field index */ - int major, minor, /* HTTP version numbers */ - status; /* Request status */ + int major, minor; /* HTTP version numbers */ - DEBUG_printf(("httpUpdate(http=%p), state=%s", http, + DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", http, status, http_states[http->state])); /* - * Flush pending data, if any... + * Grab a single line from the connection... */ - if (http->wused) + if (!httpGets(line, sizeof(line), http)) { - DEBUG_puts("2httpUpdate: flushing buffer..."); - - if (httpFlushWrite(http) < 0) - return (HTTP_ERROR); + *status = HTTP_ERROR; + return (0); } - /* - * If we haven't issued any commands, then there is nothing to "update"... - */ + DEBUG_printf(("2_httpUpdate: Got \"%s\"", line)); - if (http->state == HTTP_WAITING) - return (HTTP_CONTINUE); - - /* - * Grab all of the lines we can from the connection... - */ - - while (httpGets(line, sizeof(line), http) != NULL) + if (line[0] == '\0') { - DEBUG_printf(("2httpUpdate: Got \"%s\"", line)); + /* + * Blank line means the start of the data section (if any). Return + * the result code, too... + * + * If we get status 100 (HTTP_CONTINUE), then we *don't* change states. + * Instead, we just return HTTP_CONTINUE to the caller and keep on + * tryin'... + */ - if (line[0] == '\0') + if (http->status == HTTP_CONTINUE) { - /* - * Blank line means the start of the data section (if any). Return - * the result code, too... - * - * If we get status 100 (HTTP_CONTINUE), then we *don't* change states. - * Instead, we just return HTTP_CONTINUE to the caller and keep on - * tryin'... - */ + *status = http->status; + return (0); + } - if (http->status == HTTP_CONTINUE) - return (http->status); + if (http->status < HTTP_BAD_REQUEST) + http->digest_tries = 0; - if (http->status < HTTP_BAD_REQUEST) - http->digest_tries = 0; - #ifdef HAVE_SSL - if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls) + if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls) + { + if (http_setup_ssl(http) != 0) { - if (http_setup_ssl(http) != 0) - { # ifdef WIN32 - closesocket(http->fd); + closesocket(http->fd); # else - close(http->fd); + close(http->fd); # endif /* WIN32 */ - return (HTTP_ERROR); - } + *status = http->status = HTTP_ERROR; + return (0); + } - return (HTTP_CONTINUE); - } + *status = HTTP_CONTINUE; + return (0); + } #endif /* HAVE_SSL */ - httpGetLength2(http); + httpGetLength2(http); - switch (http->state) - { - case HTTP_GET : - case HTTP_POST : - case HTTP_POST_RECV : - case HTTP_PUT : - http->state ++; - case HTTP_POST_SEND : - case HTTP_HEAD : - break; + switch (http->state) + { + case HTTP_GET : + case HTTP_POST : + case HTTP_POST_RECV : + case HTTP_PUT : + http->state ++; + case HTTP_POST_SEND : + case HTTP_HEAD : + break; - default : - http->state = HTTP_WAITING; - break; - } + default : + http->state = HTTP_WAITING; + break; + } - return (http->status); + *status = http->status; + return (0); + } + else if (!strncmp(line, "HTTP/", 5)) + { + /* + * Got the beginning of a response... + */ + + int intstatus; /* Status value as an integer */ + + if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3) + { + *status = http->status = HTTP_ERROR; + return (0); } - else if (!strncmp(line, "HTTP/", 5)) + + http->version = (http_version_t)(major * 100 + minor); + *status = http->status = (http_status_t)intstatus; + } + else if ((value = strchr(line, ':')) != NULL) + { + /* + * Got a value... + */ + + *value++ = '\0'; + while (_cups_isspace(*value)) + value ++; + + /* + * Be tolerants of servers that send unknown attribute fields... + */ + + if (!strcasecmp(line, "expect")) { /* - * Got the beginning of a response... + * "Expect: 100-continue" or similar... */ - if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3) - return (HTTP_ERROR); - - http->version = (http_version_t)(major * 100 + minor); - http->status = (http_status_t)status; + http->expect = (http_status_t)atoi(value); } - else if ((value = strchr(line, ':')) != NULL) + else if (!strcasecmp(line, "cookie")) { /* - * Got a value... + * "Cookie: name=value[; name=value ...]" - replaces previous cookies... */ - *value++ = '\0'; - while (_cups_isspace(*value)) - value ++; + httpSetCookie(http, value); + } + else if ((field = http_field(line)) != HTTP_FIELD_UNKNOWN) + httpSetField(http, field, value); +#ifdef DEBUG + else + DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line)); +#endif /* DEBUG */ + } + else + { + DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line)); + *status = http->status = HTTP_ERROR; + return (0); + } - /* - * Be tolerants of servers that send unknown attribute fields... - */ + return (1); +} - if (!strcasecmp(line, "expect")) - { - /* - * "Expect: 100-continue" or similar... - */ - http->expect = (http_status_t)atoi(value); - } - else if (!strcasecmp(line, "cookie")) - { - /* - * "Cookie: name=value[; name=value ...]" - replaces previous cookies... - */ +/* + * 'httpUpdate()' - Update the current HTTP state for incoming data. + */ - httpSetCookie(http, value); - } - else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN) - { - DEBUG_printf(("1httpUpdate: unknown field %s seen!", line)); - continue; - } - else - httpSetField(http, field, value); - } - else - { - DEBUG_printf(("1httpUpdate: Bad response line \"%s\"!", line)); - http->status = HTTP_ERROR; +http_status_t /* O - HTTP status */ +httpUpdate(http_t *http) /* I - Connection to server */ +{ + http_status_t status; /* Request status */ + + + DEBUG_printf(("httpUpdate(http=%p), state=%s", http, + http_states[http->state])); + + /* + * Flush pending data, if any... + */ + + if (http->wused) + { + DEBUG_puts("2httpUpdate: flushing buffer..."); + + if (httpFlushWrite(http) < 0) return (HTTP_ERROR); - } } /* + * If we haven't issued any commands, then there is nothing to "update"... + */ + + if (http->state == HTTP_WAITING) + return (HTTP_CONTINUE); + + /* + * Grab all of the lines we can from the connection... + */ + + while (_httpUpdate(http, &status)); + + /* * See if there was an error... */ @@ -2187,10 +2227,10 @@ } /* - * If we haven't already returned, then there is nothing new... + * Return the current status... */ - return (HTTP_CONTINUE); + return (status); } Index: cups/request.c =================================================================== --- cups/request.c (revision 9499) +++ cups/request.c (working copy) @@ -1,9 +1,9 @@ /* * "$Id$" * - * IPP utilities for the Common UNIX Printing System (CUPS). + * IPP utilities for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -668,7 +668,8 @@ { got_status = 1; - if ((status = httpUpdate(http)) != HTTP_CONTINUE) + _httpUpdate(http, &status); + if (status >= HTTP_MULTIPLE_CHOICES) break; } @@ -676,15 +677,18 @@ * Wait up to 1 second to get the 100-continue response as needed... */ - if (!got_status && expect == HTTP_CONTINUE) + if (!got_status) { - DEBUG_puts("2cupsSendRequest: Waiting for 100-continue..."); + if (expect == HTTP_CONTINUE) + { + DEBUG_puts("2cupsSendRequest: Waiting for 100-continue..."); - if (httpWait(http, 1000)) - status = httpUpdate(http); + if (httpWait(http, 1000)) + _httpUpdate(http, &status); + } + else if (httpCheck(http)) + _httpUpdate(http, &status); } - else if (httpCheck(http)) - status = httpUpdate(http); DEBUG_printf(("2cupsSendRequest: status=%d", status)); @@ -692,7 +696,7 @@ * Process the current HTTP status... */ - if (status >= HTTP_BAD_REQUEST) + if (status >= HTTP_MULTIPLE_CHOICES) httpFlush(http); switch (status) @@ -819,9 +823,10 @@ if (_httpWait(http, 0, 1)) { - http_status_t status; /* Status from httpUpdate */ + http_status_t status; /* Status from _httpUpdate */ - if ((status = httpUpdate(http)) >= HTTP_BAD_REQUEST) + _httpUpdate(http, &status); + if (status >= HTTP_MULTIPLE_CHOICES) httpFlush(http); return (status); Index: cups/http-private.h =================================================================== --- cups/http-private.h (revision 9499) +++ cups/http-private.h (working copy) @@ -1,9 +1,9 @@ /* * "$Id$" * - * Private HTTP definitions for the Common UNIX Printing System (CUPS). + * Private HTTP definitions for CUPS. * - * Copyright 2007-2008 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -269,6 +269,7 @@ size_t dstsize); extern const char *_httpResolveURI(const char *uri, char *resolved_uri, size_t resolved_size, int log); +extern int _httpUpdate(http_t *http, http_status_t *status); extern int _httpWait(http_t *http, int msec, int usessl); #endif /* !_CUPS_HTTP_PRIVATE_H_ */