diff -up cups-1.3.7/scheduler/client.c.str3194 cups-1.3.7/scheduler/client.c --- cups-1.3.7/scheduler/client.c.str3194 2009-10-22 11:55:44.000000000 +0200 +++ cups-1.3.7/scheduler/client.c 2009-10-22 13:59:04.000000000 +0200 @@ -2338,7 +2338,7 @@ cupsdSendCommand( con->sent_header = 0; con->file_ready = 0; con->got_fields = 0; - con->field_col = 0; + con->header_used = 0; return (1); } @@ -2732,9 +2732,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 */ @@ -2748,7 +2749,16 @@ 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) { @@ -2777,32 +2787,31 @@ 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) { /* * 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') { /* * 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_DEBUG2, "Script header: %s", buf); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Script header: %s", con->header); if (!con->sent_header) { @@ -2810,7 +2819,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; @@ -2818,9 +2827,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 @@ -2836,25 +2846,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); - memmove(buf, bufptr, bytes + 1); - bufptr = buf - 1; + con->header_used -= bufptr - con->header; + + if (con->header_used > 0) + memmove(con->header, bufptr, con->header_used); + + bufptr = con->header - 1; /* * See if the line was empty... */ - if (con->field_col == 0) + if (field_col == 0) { con->got_fields = 1; @@ -2868,33 +2878,21 @@ 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 ++; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdWriteClient: %d bytes=%d, got_fields=%d", - con->http.fd, bytes, con->got_fields); + field_col ++; - 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!", @@ -2904,14 +2902,21 @@ 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 -up cups-1.3.7/scheduler/client.h.str3194 cups-1.3.7/scheduler/client.h --- cups-1.3.7/scheduler/client.h.str3194 2009-10-22 11:55:44.000000000 +0200 +++ cups-1.3.7/scheduler/client.h 2009-10-22 13:31:14.000000000 +0200 @@ -51,7 +51,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 */