diff -Naurp cups-1.3.10/scheduler/client.c cups-1.3.10.oden/scheduler/client.c --- cups-1.3.10/scheduler/client.c 2010-04-14 04:33:04.000000000 -0400 +++ cups-1.3.10.oden/scheduler/client.c 2010-04-14 04:33:16.000000000 -0400 @@ -2250,7 +2250,7 @@ cupsdSendCommand( con->sent_header = 0; con->file_ready = 0; con->got_fields = 0; - con->field_col = 0; + con->header_used = 0; return (1); } @@ -2644,9 +2644,10 @@ cupsdUpdateCGI(void) void cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ { - int bytes; /* Number of bytes written */ - char buf[16385]; /* Data buffer */ - char *bufptr; /* Pointer into buffer */ + int bytes, /* Number of bytes written */ + field_col; /* Current column */ + char *bufptr, /* Pointer into buffer */ + *bufend; /* Pointer to end of buffer */ ipp_state_t ipp_state; /* IPP state value */ @@ -2660,7 +2661,15 @@ cupsdWriteClient(cupsd_client_t *con) /* if (con->http.state != HTTP_GET_SEND && con->http.state != HTTP_POST_SEND) + { + /* + * If we get called in the wrong state, then something went wrong with the + * connection and we need to shut it down... + */ + + cupsdCloseClient(con); return; + } if (con->pipe_pid) { @@ -2689,11 +2698,10 @@ cupsdWriteClient(cupsd_client_t *con) /* bytes = ipp_state != IPP_ERROR && (con->file >= 0 || ipp_state != IPP_DATA); } - else if ((bytes = read(con->file, buf, sizeof(buf) - 1)) > 0) + else if ((bytes = read(con->file, con->header, + sizeof(con->header) - con->header_used)) > 0) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdWriteClient: Read %d bytes from file %d...", - bytes, con->file); + con->header_used += bytes; if (con->pipe_pid && !con->got_fields) { @@ -2701,9 +2709,10 @@ cupsdWriteClient(cupsd_client_t *con) /* * Inspect the data for Content-Type and other fields. */ - buf[bytes] = '\0'; - - for (bufptr = buf; !con->got_fields && *bufptr; bufptr ++) + for (bufptr = con->header, bufend = con->header + con->header_used, + field_col = 0; + !con->got_fields && bufptr < bufend; + bufptr ++) { if (*bufptr == '\n') { @@ -2711,11 +2720,11 @@ cupsdWriteClient(cupsd_client_t *con) /* * Send line to client... */ - if (bufptr > buf && bufptr[-1] == '\r') + if (bufptr > con->header && bufptr[-1] == '\r') bufptr[-1] = '\0'; *bufptr++ = '\0'; - cupsdLogMessage(CUPSD_LOG_DEBUG, "Script header: %s", buf); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Script header: %s", con->header); if (!con->sent_header) { @@ -2723,7 +2732,7 @@ cupsdWriteClient(cupsd_client_t *con) /* * Handle redirection and CGI status codes... */ - if (!strncasecmp(buf, "Location:", 9)) + if (!strncasecmp(con->header, "Location:", 9)) { cupsdSendHeader(con, HTTP_SEE_OTHER, NULL, CUPSD_AUTH_NONE); con->sent_header = 2; @@ -2731,9 +2740,10 @@ cupsdWriteClient(cupsd_client_t *con) /* if (httpPrintf(HTTP(con), "Content-Length: 0\r\n") < 0) return; } - else if (!strncasecmp(buf, "Status:", 7)) + else if (!strncasecmp(con->header, "Status:", 7)) { - cupsdSendError(con, (http_status_t)atoi(buf + 7), CUPSD_AUTH_NONE); + cupsdSendError(con, (http_status_t)atoi(con->header + 7), + CUPSD_AUTH_NONE); con->sent_header = 2; } else @@ -2749,30 +2759,25 @@ cupsdWriteClient(cupsd_client_t *con) /* } } - if (strncasecmp(buf, "Status:", 7)) - httpPrintf(HTTP(con), "%s\r\n", buf); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdWriteClient: %d %s", - con->http.fd, buf); + if (strncasecmp(con->header, "Status:", 7)) + httpPrintf(HTTP(con), "%s\r\n", con->header); /* * Update buffer... */ - bytes -= (bufptr - buf); + con->header_used -= bufptr - con->header; - if (bytes > 0) - memmove(buf, bufptr, bytes + 1); - else - buf[0] = '\0'; + if (con->header_used > 0) + memmove(con->header, bufptr, con->header_used); - bufptr = buf - 1; + bufptr = con->header - 1; /* * See if the line was empty... */ - if (con->field_col == 0) + if (field_col == 0) { con->got_fields = 1; @@ -2786,34 +2791,22 @@ cupsdWriteClient(cupsd_client_t *con) /* con->http.data_encoding = HTTP_ENCODE_CHUNKED; } else - con->field_col = 0; + field_col = 0; } else if (*bufptr != '\r') - con->field_col ++; + field_col ++; } - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdWriteClient: %d bytes=%d, got_fields=%d", - con->http.fd, bytes, con->got_fields); - - if (bytes > 0 && !con->got_fields) + if (!con->got_fields) { - /* - * Remaining text needs to go out... - */ - - httpPrintf(HTTP(con), "%s", buf); - con->http.activity = time(NULL); return; } - else if (bytes == 0) - con->http.activity = time(NULL); } - if (bytes > 0) + if (con->header_used > 0) { - if (httpWrite2(HTTP(con), buf, bytes) < 0) + if (httpWrite2(HTTP(con), con->header, con->header_used) < 0) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdWriteClient: %d Write of %d bytes failed!", @@ -2823,14 +2816,22 @@ cupsdWriteClient(cupsd_client_t *con) /* return; } - con->bytes += bytes; + if (con->http.data_encoding == HTTP_ENCODE_CHUNKED) + httpFlushWrite(HTTP(con)); + + con->bytes += con->header_used; if (con->http.state == HTTP_WAITING) bytes = 0; + else + bytes = con->header_used; + + con->header_used = 0; } } - if (bytes <= 0) + if (bytes <= 0 || + (con->http.state != HTTP_GET_SEND && con->http.state != HTTP_POST_SEND)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdWriteClient: %d bytes < 0", con->http.fd); diff -Naurp cups-1.3.10/scheduler/client.h cups-1.3.10.oden/scheduler/client.h --- cups-1.3.10/scheduler/client.h 2009-01-15 14:12:15.000000000 -0500 +++ cups-1.3.10.oden/scheduler/client.h 2010-04-14 04:33:16.000000000 -0400 @@ -44,7 +44,8 @@ struct cupsd_client_s int pipe_pid; /* Pipe process ID (or 0 if not a pipe) */ int sent_header, /* Non-zero if sent HTTP header */ got_fields, /* Non-zero if all fields seen */ - field_col; /* Column within line */ + header_used; /* Number of header bytes used */ + char header[2048]; /* Header from CGI program */ cups_lang_t *language; /* Language to use */ #ifdef HAVE_SSL int auto_ssl; /* Automatic test for SSL/TLS */