diff --git a/lib/ftp.c b/lib/ftp.c index 504af23ee..121b3de49 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -1591,8 +1591,8 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn) readthisamountnow = BUFSIZE; actuallyread = - data->set.fread(data->state.buffer, 1, readthisamountnow, - data->set.in); + conn->fread(data->state.buffer, 1, readthisamountnow, + conn->fread_in); passed += actuallyread; if(actuallyread != readthisamountnow) { @@ -1623,7 +1623,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn) } } - /* Send everything on data->set.in to the socket */ + /* Send everything on data->state.in to the socket */ if(data->set.ftp_append) { /* we append onto the file instead of rewriting it */ FTPSENDF(conn, "APPE %s", ftp->file); diff --git a/lib/http.c b/lib/http.c index 645d11200..82cd664ee 100644 --- a/lib/http.c +++ b/lib/http.c @@ -126,8 +126,11 @@ send_buffer *add_buffer_init(void) * add_buffer_send() sends a buffer and frees all associated memory. */ static -CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, - long *bytes_written) +CURLcode add_buffer_send(send_buffer *in, + int sockfd, + struct connectdata *conn, + long *bytes_written) /* add the number of sent + bytes to this counter */ { ssize_t amount; CURLcode res; @@ -149,6 +152,8 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount); + *bytes_written += amount; + if(amount != size) { size -= amount; ptr += amount; @@ -162,8 +167,6 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, free(in->buffer); free(in); - *bytes_written += amount; - return res; } @@ -517,8 +520,9 @@ CURLcode Curl_http_done(struct connectdata *conn) Curl_formclean(http->sendit); /* Now free that whole lot */ - data->set.fread = http->storefread; /* restore */ - data->set.in = http->in; /* restore */ + /* set the proper values */ + conn->fread = data->set.fread; /* restore */ + conn->fread_in = data->set.in; /* restore */ } else if(HTTPREQ_PUT == data->set.httpreq) conn->bytecount = http->readbytecount + http->writebytecount; @@ -923,13 +927,9 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_HTTP_POST_ERROR; } - http->storefread = data->set.fread; /* backup */ - http->in = data->set.in; /* backup */ - - data->set.fread = (curl_read_callback) - Curl_FormReader; /* set the read function to read from the - generated form data */ - data->set.in = (FILE *)&http->form; + /* set the read function to read from the generated form data */ + conn->fread = (curl_read_callback)Curl_FormReader; + conn->fread_in = &http->form; if(!conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ @@ -974,7 +974,7 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); /* fire away the whole request to the server */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) failf(data, "Failed sending POST request"); @@ -1004,10 +1004,10 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, data->set.infilesize); /* this sends the buffer and frees all the buffer resources */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) - failf(data, "Faied sending POST request"); + failf(data, "Failed sending POST request"); else /* prepare for transfer */ result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, @@ -1053,7 +1053,7 @@ CURLcode Curl_http(struct connectdata *conn) data->set.postfields ); /* issue the request */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) @@ -1070,7 +1070,7 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); /* issue the request */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) diff --git a/lib/ssluse.c b/lib/ssluse.c index ea1b69d02..5239cafd4 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -275,7 +275,8 @@ int cert_stuff(struct connectdata *conn, if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, key_file, file_type) != 1) { - failf(data, "unable to set private key file\n"); + failf(data, "unable to set private key file: '%s' type %s\n", + key_file, key_type?key_type:"PEM"); return 0; } break; diff --git a/lib/transfer.c b/lib/transfer.c index c991decd0..16c1a7b21 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -597,240 +597,240 @@ CURLcode Curl_readwrite(struct connectdata *conn, else if(checkprefix("Last-Modified:", k->p) && (data->set.timecondition || data->set.get_filetime) ) { time_t secs=time(NULL); -k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), - &secs); - if(data->set.get_filetime) - data->info.filetime = k->timeofdoc; - } - else if ((k->httpcode >= 300 && k->httpcode < 400) && - (data->set.http_follow_location) && - checkprefix("Location:", k->p)) { - /* this is the URL that the server advices us to get instead */ - char *ptr; - char *start=k->p; - char backup; - - start += 9; /* pass "Location:" */ - - /* Skip spaces and tabs. We do this to support multiple - white spaces after the "Location:" keyword. */ - while(*start && isspace((int)*start )) - start++; - ptr = start; /* start scanning here */ - - /* scan through the string to find the end */ - while(*ptr && !isspace((int)*ptr)) - ptr++; - backup = *ptr; /* store the ending letter */ - if(ptr != start) { - *ptr = '\0'; /* zero terminate */ - conn->newurl = strdup(start); /* clone string */ - *ptr = backup; /* restore ending letter */ + k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), + &secs); + if(data->set.get_filetime) + data->info.filetime = k->timeofdoc; } - } + else if ((k->httpcode >= 300 && k->httpcode < 400) && + (data->set.http_follow_location) && + checkprefix("Location:", k->p)) { + /* this is the URL that the server advices us to get instead */ + char *ptr; + char *start=k->p; + char backup; - /* - * End of header-checks. Write them to the client. - */ + start += 9; /* pass "Location:" */ - k->writetype = CLIENTWRITE_HEADER; - if (data->set.http_include_header) - k->writetype |= CLIENTWRITE_BODY; + /* Skip spaces and tabs. We do this to support multiple + white spaces after the "Location:" keyword. */ + while(*start && isspace((int)*start )) + start++; + ptr = start; /* start scanning here */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - k->p, k->hbuflen); + /* scan through the string to find the end */ + while(*ptr && !isspace((int)*ptr)) + ptr++; + backup = *ptr; /* store the ending letter */ + if(ptr != start) { + *ptr = '\0'; /* zero terminate */ + conn->newurl = strdup(start); /* clone string */ + *ptr = backup; /* restore ending letter */ + } + } - result = Curl_client_write(data, k->writetype, k->p, - k->hbuflen); - if(result) - return result; + /* + * End of header-checks. Write them to the client. + */ - data->info.header_size += k->hbuflen; - conn->headerbytecount += k->hbuflen; + k->writetype = CLIENTWRITE_HEADER; + if (data->set.http_include_header) + k->writetype |= CLIENTWRITE_BODY; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->p, k->hbuflen); + + result = Curl_client_write(data, k->writetype, k->p, + k->hbuflen); + if(result) + return result; + + data->info.header_size += k->hbuflen; + conn->headerbytecount += k->hbuflen; - /* reset hbufp pointer && hbuflen */ - k->hbufp = data->state.headerbuff; - k->hbuflen = 0; - } - while (!stop_reading && *k->str); /* header line within buffer */ + /* reset hbufp pointer && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + } + while (!stop_reading && *k->str); /* header line within buffer */ - if(stop_reading) - /* We've stopped dealing with input, get out of the do-while loop */ - break; + if(stop_reading) + /* We've stopped dealing with input, get out of the do-while loop */ + break; - /* We might have reached the end of the header part here, but - there might be a non-header part left in the end of the read - buffer. */ + /* We might have reached the end of the header part here, but + there might be a non-header part left in the end of the read + buffer. */ - } /* end if header mode */ + } /* end if header mode */ - /* This is not an 'else if' since it may be a rest from the header - parsing, where the beginning of the buffer is headers and the end - is non-headers. */ - if (k->str && !k->header && (nread > 0)) { + /* This is not an 'else if' since it may be a rest from the header + parsing, where the beginning of the buffer is headers and the end + is non-headers. */ + if (k->str && !k->header && (nread > 0)) { - if(0 == k->bodywrites) { - /* These checks are only made the first time we are about to - write a piece of the body */ - if(conn->protocol&PROT_HTTP) { - /* HTTP-only checks */ - if (conn->newurl) { - /* abort after the headers if "follow Location" is set */ - infof (data, "Follow to new URL: %s\n", conn->newurl); - k->keepon &= ~KEEP_READ; - FD_ZERO(&k->rkeepfd); - *done = TRUE; - return CURLE_OK; - } - else if (conn->resume_from && - !k->content_range && - (data->set.httpreq==HTTPREQ_GET)) { - /* we wanted to resume a download, although the server - doesn't seem to support this and we did this with a GET - (if it wasn't a GET we did a POST or PUT resume) */ - failf (data, "HTTP server doesn't seem to support " - "byte ranges. Cannot resume."); - return CURLE_HTTP_RANGE_ERROR; - } - else if(data->set.timecondition && !conn->range) { - /* A time condition has been set AND no ranges have been - requested. This seems to be what chapter 13.3.4 of - RFC 2616 defines to be the correct action for a - HTTP/1.1 client */ - if((k->timeofdoc > 0) && (data->set.timevalue > 0)) { - switch(data->set.timecondition) { - case TIMECOND_IFMODSINCE: - default: - if(k->timeofdoc < data->set.timevalue) { - infof(data, - "The requested document is not new enough\n"); - *done = TRUE; - return CURLE_OK; - } - break; - case TIMECOND_IFUNMODSINCE: - if(k->timeofdoc > data->set.timevalue) { - infof(data, - "The requested document is not old enough\n"); - *done = TRUE; - return CURLE_OK; - } - break; - } /* switch */ - } /* two valid time strings */ - } /* we have a time condition */ + if(0 == k->bodywrites) { + /* These checks are only made the first time we are about to + write a piece of the body */ + if(conn->protocol&PROT_HTTP) { + /* HTTP-only checks */ + if (conn->newurl) { + /* abort after the headers if "follow Location" is set */ + infof (data, "Follow to new URL: %s\n", conn->newurl); + k->keepon &= ~KEEP_READ; + FD_ZERO(&k->rkeepfd); + *done = TRUE; + return CURLE_OK; + } + else if (conn->resume_from && + !k->content_range && + (data->set.httpreq==HTTPREQ_GET)) { + /* we wanted to resume a download, although the server + doesn't seem to support this and we did this with a GET + (if it wasn't a GET we did a POST or PUT resume) */ + failf (data, "HTTP server doesn't seem to support " + "byte ranges. Cannot resume."); + return CURLE_HTTP_RANGE_ERROR; + } + else if(data->set.timecondition && !conn->range) { + /* A time condition has been set AND no ranges have been + requested. This seems to be what chapter 13.3.4 of + RFC 2616 defines to be the correct action for a + HTTP/1.1 client */ + if((k->timeofdoc > 0) && (data->set.timevalue > 0)) { + switch(data->set.timecondition) { + case TIMECOND_IFMODSINCE: + default: + if(k->timeofdoc < data->set.timevalue) { + infof(data, + "The requested document is not new enough\n"); + *done = TRUE; + return CURLE_OK; + } + break; + case TIMECOND_IFUNMODSINCE: + if(k->timeofdoc > data->set.timevalue) { + infof(data, + "The requested document is not old enough\n"); + *done = TRUE; + return CURLE_OK; + } + break; + } /* switch */ + } /* two valid time strings */ + } /* we have a time condition */ - } /* this is HTTP */ - } /* this is the first time we write a body part */ - k->bodywrites++; + } /* this is HTTP */ + } /* this is the first time we write a body part */ + k->bodywrites++; - /* pass data to the debug function before it gets "dechunked" */ - if(data->set.verbose) { - if(k->badheader) { - Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff, - k->hbuflen); - if(k->badheader == HEADER_PARTHEADER) + /* pass data to the debug function before it gets "dechunked" */ + if(data->set.verbose) { + if(k->badheader) { + Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff, + k->hbuflen); + if(k->badheader == HEADER_PARTHEADER) + Curl_debug(data, CURLINFO_DATA_IN, k->str, nread); + } + else Curl_debug(data, CURLINFO_DATA_IN, k->str, nread); } - else - Curl_debug(data, CURLINFO_DATA_IN, k->str, nread); - } - if(conn->bits.chunk) { - /* - * Bless me father for I have sinned. Here comes a chunked - * transfer flying and we need to decode this properly. While - * the name says read, this function both reads and writes away - * the data. The returned 'nread' holds the number of actual - * data it wrote to the client. */ - CHUNKcode res = - Curl_httpchunk_read(conn, k->str, nread, &nread); + if(conn->bits.chunk) { + /* + * Bless me father for I have sinned. Here comes a chunked + * transfer flying and we need to decode this properly. While + * the name says read, this function both reads and writes away + * the data. The returned 'nread' holds the number of actual + * data it wrote to the client. */ + CHUNKcode res = + Curl_httpchunk_read(conn, k->str, nread, &nread); - if(CHUNKE_OK < res) { - if(CHUNKE_WRITE_ERROR == res) { - failf(data, "Failed writing data"); - return CURLE_WRITE_ERROR; + if(CHUNKE_OK < res) { + if(CHUNKE_WRITE_ERROR == res) { + failf(data, "Failed writing data"); + return CURLE_WRITE_ERROR; + } + failf(data, "Received problem in the chunky parser"); + return CURLE_RECV_ERROR; } - failf(data, "Received problem in the chunky parser"); - return CURLE_RECV_ERROR; + else if(CHUNKE_STOP == res) { + /* we're done reading chunks! */ + k->keepon &= ~KEEP_READ; /* read no more */ + FD_ZERO(&k->rkeepfd); + + /* There are now possibly N number of bytes at the end of the + str buffer that weren't written to the client, but we don't + care about them right now. */ + } + /* If it returned OK, we just keep going */ } - else if(CHUNKE_STOP == res) { - /* we're done reading chunks! */ - k->keepon &= ~KEEP_READ; /* read no more */ + + if((-1 != conn->maxdownload) && + (k->bytecount + nread >= conn->maxdownload)) { + nread = conn->maxdownload - k->bytecount; + if(nread < 0 ) /* this should be unusual */ + nread = 0; + + k->keepon &= ~KEEP_READ; /* we're done reading */ FD_ZERO(&k->rkeepfd); - - /* There are now possibly N number of bytes at the end of the - str buffer that weren't written to the client, but we don't - care about them right now. */ } - /* If it returned OK, we just keep going */ - } - if((-1 != conn->maxdownload) && - (k->bytecount + nread >= conn->maxdownload)) { - nread = conn->maxdownload - k->bytecount; - if(nread < 0 ) /* this should be unusual */ - nread = 0; + k->bytecount += nread; - k->keepon &= ~KEEP_READ; /* we're done reading */ - FD_ZERO(&k->rkeepfd); - } - - k->bytecount += nread; - - Curl_pgrsSetDownloadCounter(data, (double)k->bytecount); + Curl_pgrsSetDownloadCounter(data, (double)k->bytecount); - if(!conn->bits.chunk && (nread || k->badheader)) { - /* If this is chunky transfer, it was already written */ + if(!conn->bits.chunk && (nread || k->badheader)) { + /* If this is chunky transfer, it was already written */ - if(k->badheader) { - /* we parsed a piece of data wrongly assuming it was a header - and now we output it as body instead */ - result = Curl_client_write(data, CLIENTWRITE_BODY, - data->state.headerbuff, - k->hbuflen); - } - if(k->badheader < HEADER_ALLBAD) { - /* This switch handles various content encodings. If there's an - error here, be sure to check over the almost identical code in - http_chunk.c. 08/29/02 jhrg */ -#ifdef HAVE_LIBZ - switch (k->content_encoding) { - case IDENTITY: -#endif - /* This is the default when the server sends no - Content-Encoding header. See Curl_readwrite_init; the - memset() call initializes k->content_encoding to zero. - 08/28/02 jhrg */ - result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, - nread); -#ifdef HAVE_LIBZ - break; - - case DEFLATE: - /* Assume CLIENTWRITE_BODY; headers are not encoded. */ - result = Curl_unencode_deflate_write(data, k, nread); - break; - - case GZIP: /* FIXME 08/27/02 jhrg */ - case COMPRESS: - default: - failf (data, "Unrecognized content encoding type. " - "libcurl understands `identity' and `deflate' " - "content encodings."); - result = CURLE_BAD_CONTENT_ENCODING; - break; + if(k->badheader) { + /* we parsed a piece of data wrongly assuming it was a header + and now we output it as body instead */ + result = Curl_client_write(data, CLIENTWRITE_BODY, + data->state.headerbuff, + k->hbuflen); } + if(k->badheader < HEADER_ALLBAD) { + /* This switch handles various content encodings. If there's an + error here, be sure to check over the almost identical code + in http_chunk.c. 08/29/02 jhrg */ +#ifdef HAVE_LIBZ + switch (k->content_encoding) { + case IDENTITY: #endif + /* This is the default when the server sends no + Content-Encoding header. See Curl_readwrite_init; the + memset() call initializes k->content_encoding to zero. + 08/28/02 jhrg */ + result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, + nread); +#ifdef HAVE_LIBZ + break; + + case DEFLATE: + /* Assume CLIENTWRITE_BODY; headers are not encoded. */ + result = Curl_unencode_deflate_write(data, k, nread); + break; + + case GZIP: /* FIXME 08/27/02 jhrg */ + case COMPRESS: + default: + failf (data, "Unrecognized content encoding type. " + "libcurl understands `identity' and `deflate' " + "content encodings."); + result = CURLE_BAD_CONTENT_ENCODING; + break; + } +#endif + } + k->badheader = HEADER_NORMAL; /* taken care of now */ + + if(result) + return result; } - k->badheader = HEADER_NORMAL; /* taken care of now */ - if(result) - return result; - } - - } /* if (! header and data to read ) */ + } /* if (! header and data to read ) */ } while(!readdone); @@ -874,8 +874,8 @@ k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), conn->upload_fromhere += 10; /* 32bit hex + CRLF */ } - nread = data->set.fread(conn->upload_fromhere, 1, - buffersize, data->set.in); + nread = conn->fread(conn->upload_fromhere, 1, + buffersize, conn->fread_in); if(conn->bits.upload_chunky) { /* if chunked Transfer-Encoding */ @@ -944,12 +944,12 @@ k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), that instead of reading more data */ } - /* write to socket */ + /* write to socket (send away data) */ result = Curl_write(conn, - conn->writesockfd, - conn->upload_fromhere, - conn->upload_present, - &bytes_written); + conn->writesockfd, /* socket to send to */ + conn->upload_fromhere, /* buffer pointer */ + conn->upload_present, /* buffer size */ + &bytes_written); /* actually send away */ if(result) return result; else if(conn->upload_present != bytes_written) { diff --git a/lib/url.c b/lib/url.c index f67ef7bcb..935507674 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1789,6 +1789,9 @@ static CURLcode CreateConnection(struct SessionHandle *data, /* else, no chunky upload */ FALSE; + conn->fread = data->set.fread; + conn->fread_in = data->set.in; + /*********************************************************** * We need to allocate memory to store the path in. We get the size of the * full URL to be sure, and we need to make it at least 256 bytes since diff --git a/lib/urldata.h b/lib/urldata.h index d53dc9cdc..2b51008bc 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -164,9 +164,6 @@ struct HTTP { /* For FORM posting */ struct Form form; - curl_read_callback storefread; - FILE *in; - struct Curl_chunker chunk; }; @@ -458,6 +455,9 @@ struct connectdata { and the 'upload_present' contains the number of bytes available at this position */ char *upload_fromhere; + + curl_read_callback fread; /* function that reads the input */ + void *fread_in; /* pointer to pass to the fread() above */ }; /* The end of connectdata. 08/27/02 jhrg */ @@ -633,7 +633,7 @@ struct UserDefined { bool free_referer; /* set TRUE if 'referer' points to a string we allocated */ char *useragent; /* User-Agent string */ - char *encoding; /* Accept-Encoding string 08/28/02 jhrg */ + char *encoding; /* Accept-Encoding string */ char *postfields; /* if POST, set the fields' values here */ size_t postfieldsize; /* if POST, this might have a size to use instead of strlen(), and then the data *may* be binary (contain