Changelog
Daniel (14 January 2007)
+- David McCreedy provided libcurl changes for doing HTTP communication on
+ non-ASCII platforms. It does add some complexity, most notably with more
+ #ifdefs, but I want to see this supported added and I can't see how we can
+ add it without the extra stuff added.
+
- Setting CURLOPT_COOKIELIST to "ALL" when no cookies at all was present,
libcurl would crash when trying to read a NULL pointer.
Available command line options: 112
Available curl_easy_setopt() options: 133
Number of public functions in libcurl: 54
- Amount of public web site mirrors: 38
+ Amount of public web site mirrors: 39
Number of known libcurl bindings: 35
Number of contributors: 524
This release includes the following changes:
- o Support for SCP and SFTP were added
+ o Support for SCP and SFTP were added (powered by libssh2)
o CURLOPT_CLOSEPOLICY is now deprecated
o --ftp-ssl-ccc and CURLOPT_FTP_SSL_CCC were added
+ o HTTP support for non-ASCII platforms
This release includes the following bugfixes:
/*
Debug the form generator stand-alone by compiling this source file with:
- gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -o formdata -I../include formdata.c strequal.c
+ gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -DCURLDEBUG -o formdata -I../include formdata.c strequal.c memdebug.c mprintf.c strerror.c
run the 'formdata' executable the output should end with:
All Tests seem to have worked ...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
-Content-Disposition: attachment; filename="Makefile.b32.resp"
+Content-Disposition: attachment; filename="Makefile.b32"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
-Content-Disposition: attachment; filename="Makefile.b32.resp"
+Content-Disposition: attachment; filename="Makefile.b32"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
-Content-Disposition: attachment; filename="Makefile.b32.resp"
+Content-Disposition: attachment; filename="Makefile.b32"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
#endif
+#include "urldata.h" /* for struct SessionHandle */
+#include "easyif.h" /* for Curl_convert_... prototypes */
#include "formdata.h"
#include "strequal.h"
#include "memory.h"
* Set the Name property.
*/
case CURLFORM_PTRNAME:
+#ifdef CURL_DOES_CONVERSIONS
+ /* treat CURLFORM_PTR like CURLFORM_COPYNAME so we'll
+ have safe memory for the eventual conversion */
+#else
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
+#endif
case CURLFORM_COPYNAME:
if (current_form->name)
return_value = CURL_FORMADD_OPTION_TWICE;
*formp = newform;
if (size) {
- if(type == FORM_DATA)
+ if((type == FORM_DATA) || (type == FORM_CONTENT))
*size += length;
else {
/* Since this is a file to be uploaded here, add the size of the actual
* Curl_formclean() is used from http.c, this cleans a built FormData linked
* list
*/
-void Curl_formclean(struct FormData *form)
+void Curl_formclean(struct FormData **form_ptr)
{
- struct FormData *next;
+ struct FormData *next, *form;
+ form = *form_ptr;
if(!form)
return;
free(form); /* free the struct */
} while ((form = next) != NULL); /* continue */
+
+ *form_ptr = NULL;
}
+#ifdef CURL_DOES_CONVERSIONS
+/*
+ * Curl_formcovert() is used from http.c, this converts any
+ form items that need to be sent in the network encoding.
+ Returns CURLE_OK on success.
+ */
+CURLcode Curl_formconvert(struct SessionHandle *data, struct FormData *form)
+{
+ struct FormData *next;
+ CURLcode rc;
+
+ if(!form)
+ return CURLE_OK;
+
+ if(!data)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ do {
+ next=form->next; /* the following form line */
+ if (form->type == FORM_DATA) {
+ rc = Curl_convert_to_network(data, form->line, form->length);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if (rc != CURLE_OK)
+ return rc;
+ }
+ } while ((form = next) != NULL); /* continue */
+ return CURLE_OK;
+}
+#endif /* CURL_DOES_CONVERSIONS */
+
/*
* curl_formget()
* Serialize a curl_httppost struct.
if (temp.fp) {
fclose(temp.fp);
}
- Curl_formclean(data);
+ Curl_formclean(&data);
return -1;
}
} while (read == sizeof(buffer));
} else {
if (ptr->length != append(arg, ptr->line, ptr->length)) {
- Curl_formclean(data);
+ Curl_formclean(&data);
return -1;
}
}
}
- Curl_formclean(data);
+ Curl_formclean(&data);
return 0;
}
curList = curList->next;
}
if (result) {
- Curl_formclean(firstform);
+ Curl_formclean(&firstform);
free(boundary);
return result;
}
if(file->contenttype &&
!checkprefix("text/", file->contenttype)) {
/* this is not a text content, mention our binary encoding */
- size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
+ result = AddFormDataf(&form, &size,
+ "\r\nContent-Transfer-Encoding: binary");
+ if (result)
+ break;
}
#endif
size_t nread;
char buffer[512];
while ((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
- result = AddFormData(&form, FORM_DATA, buffer, nread, &size);
+ result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
if (result)
break;
}
}
if (result) {
- Curl_formclean(firstform);
+ Curl_formclean(&firstform);
free(boundary);
return result;
}
}
else {
- Curl_formclean(firstform);
+#ifdef _FORM_DEBUG
+ fprintf(stderr,
+ "\n==> Curl_getFormData couldn't open/read \"%s\"\n",
+ file->contents);
+#endif
+ Curl_formclean(&firstform);
free(boundary);
*finalform = NULL;
return CURLE_READ_ERROR;
}
else if (post->flags & HTTPPOST_BUFFER) {
/* include contents of buffer */
- result = AddFormData(&form, FORM_DATA, post->buffer,
+ result = AddFormData(&form, FORM_CONTENT, post->buffer,
post->bufferlength, &size);
if (result)
break;
else {
/* include the contents we got */
- result = AddFormData(&form, FORM_DATA, post->contents,
+ result = AddFormData(&form, FORM_CONTENT, post->contents,
post->contentslength, &size);
if (result)
break;
}
} while ((file = file->more) != NULL); /* for each specified file for this field */
if (result) {
- Curl_formclean(firstform);
+ Curl_formclean(&firstform);
free(boundary);
return result;
}
} while ((post = post->next) != NULL); /* for each field */
if (result) {
- Curl_formclean(firstform);
+ Curl_formclean(&firstform);
free(boundary);
return result;
}
"\r\n--%s--\r\n",
boundary);
if (result) {
- Curl_formclean(firstform);
+ Curl_formclean(&firstform);
free(boundary);
return result;
}
form->data = form->data->next; /* advance */
- } while(form->data && (form->data->type == FORM_DATA));
+ } while(form->data && (form->data->type != FORM_FILE));
/* If we got an empty line and we have more data, we proceed to the next
line immediately to avoid returning zero before we've reached the end.
This is the bug reported November 22 1999 on curl 6.3. (Daniel) */
char value5[] = "value for PTRCONTENTS + CONTENTSLENGTH";
char value6[] = "value for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE";
char value7[] = "inet_ntoa_r.h";
- char value8[] = "Makefile.b32.resp";
+ char value8[] = "Makefile.b32";
char type2[] = "image/gif";
char type6[] = "text/plain";
char type7[] = "text/html";
int value5length = strlen(value4);
int value6length = strlen(value5);
int errors = 0;
- int size;
+ CURLcode rc;
+ size_t size;
size_t nread;
char buffer[4096];
struct curl_httppost *httppost=NULL;
CURLFORM_END))
++errors;
- form=Curl_getFormData(httppost, &size);
+ rc = Curl_getFormData(&form, httppost, NULL, &size);
+ if(rc != CURLE_OK) {
+ if(rc != CURLE_READ_ERROR) {
+ const char *errortext = curl_easy_strerror(rc);
+ fprintf(stdout, "\n==> Curl_getFormData error: %s\n", errortext);
+ }
+ return 0;
+ }
Curl_FormInit(&formread, form);
nread = Curl_FormReader(buffer, 1, sizeof(buffer),
(FILE *)&formread);
- if(-1 == nread)
+ if(nread < 1)
break;
fwrite(buffer, nread, 1, stdout);
} while(1);
***************************************************************************/
enum formtype {
- FORM_DATA, /* regular data */
- FORM_FILE /* 'line' points to a file name we should read from */
+ FORM_DATA, /* form metadata (convert to network encoding if necessary) */
+ FORM_CONTENT, /* form content (never convert) */
+ FORM_FILE /* 'line' points to a file name we should read from
+ to create the form data (never convert) */
};
/* plain and simple linked list with lines to send */
char *Curl_FormBoundary(void);
-void Curl_formclean(struct FormData *);
+void Curl_formclean(struct FormData **);
+
+CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *);
#endif
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
+#include "easyif.h" /* for Curl_convert_... prototypes */
#include "formdata.h"
#include "progress.h"
#include "base64.h"
&authorization) > 0) {
if(*userp)
free(*userp);
- *userp = aprintf( "%sAuthorization: Basic %s\015\012",
+ *userp = aprintf( "%sAuthorization: Basic %s\r\n",
proxy?"Proxy-":"",
authorization);
free(authorization);
ptr = in->buffer;
size = in->size_used;
+#ifdef CURL_DOES_CONVERSIONS
+ if(size - included_body_bytes > 0) {
+ res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(res != CURLE_OK) {
+ /* conversion failed, free memory and return to the caller */
+ if(in->buffer)
+ free(in->buffer);
+ free(in);
+ return res;
+ }
+ }
+#endif /* CURL_DOES_CONVERSIONS */
+
if(conn->protocol & PROT_HTTPS) {
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
when we speak HTTPS, as if only a fraction of it is sent now, this data
if(HTTPREQ_POST_FORM == data->set.httpreq) {
k->bytecount = http->readbytecount + http->writebytecount;
- Curl_formclean(http->sendit); /* Now free that whole lot */
+ Curl_formclean(&http->sendit); /* Now free that whole lot */
if(http->form.fp) {
/* a file being uploaded was left opened, close it! */
fclose(http->form.fp);
Curl_safefree(conn->allocptr.ref);
if(data->change.referer && !checkheaders(data, "Referer:"))
- conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer);
+ conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
conn->allocptr.ref = NULL;
data->set.encoding) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
- aprintf("Accept-Encoding: %s\015\012", data->set.encoding);
+ aprintf("Accept-Encoding: %s\r\n", data->set.encoding);
if(!conn->allocptr.accept_encoding)
return CURLE_OUT_OF_MEMORY;
}
&http->readbytecount,
FIRSTSOCKET,
&http->writebytecount);
+
+ if(result) {
+ Curl_formclean(&http->sendit); /* free that whole lot */
+ return result;
+ }
+#ifdef CURL_DOES_CONVERSIONS
+/* time to convert the form data... */
+ result = Curl_formconvert(data, http->sendit);
if(result) {
- Curl_formclean(http->sendit); /* free that whole lot */
+ Curl_formclean(&http->sendit); /* free that whole lot */
return result;
}
+#endif /* CURL_DOES_CONVERSIONS */
break;
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
(size_t)postsize);
if(CURLE_OK == result)
result = add_buffer(req_buffer,
- "\r\n0\r\n\r\n", 7); /* end of a chunked
- transfer stream */
+ "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
+ /* CR LF 0 CR LF CR LF */
included_body = postsize + 7;
}
if(result)
#include "content_encoding.h"
#include "http.h"
#include "memory.h"
+#include "easyif.h" /* for Curl_convert_to_network prototype */
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
* client (for byte-counting and whatever).
*
* The states and the state-machine is further explained in the header file.
+ *
+ * This function always uses ASCII hex values to accommodate non-ASCII hosts.
+ * For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
*/
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
char *datap,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(ISXDIGIT(*datap)) {
+ /* Check for an ASCII hex digit.
+ We avoid the use of isxdigit to accommodate non-ASCII hosts. */
+ if((*datap >= 0x30 && *datap <= 0x39) /* 0-9 */
+ || (*datap >= 0x41 && *datap <= 0x46) /* A-F */
+ || (*datap >= 0x61 && *datap <= 0x66)) { /* a-f */
if(ch->hexindex < MAXNUM_SIZE) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
}
/* length and datap are unmodified */
ch->hexbuffer[ch->hexindex]=0;
+#ifdef CURL_DOES_CONVERSIONS
+ /* convert to host encoding before calling strtoul */
+ result = Curl_convert_from_network(conn->data,
+ ch->hexbuffer,
+ ch->hexindex);
+ if(result != CURLE_OK) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* Treat it as a bad hex character */
+ return(CHUNKE_ILLEGAL_HEX);
+ }
+#endif /* CURL_DOES_CONVERSIONS */
ch->datasize=strtoul(ch->hexbuffer, NULL, 16);
ch->state = CHUNK_POSTHEX;
}
/* In this state, we're waiting for CRLF to arrive. We support
this to allow so called chunk-extensions to show up here
before the CRLF comes. */
- if(*datap == '\r')
+ if(*datap == 0x0d)
ch->state = CHUNK_CR;
length--;
datap++;
case CHUNK_CR:
/* waiting for the LF */
- if(*datap == '\n') {
+ if(*datap == 0x0a) {
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
if (conn->bits.trailerHdrPresent!=TRUE) {
break;
case CHUNK_POSTCR:
- if(*datap == '\r') {
+ if(*datap == 0x0d) {
ch->state = CHUNK_POSTLF;
datap++;
length--;
break;
case CHUNK_POSTLF:
- if(*datap == '\n') {
+ if(*datap == 0x0a) {
/*
* The last one before we go back to hex state and start all
* over.
}
conn->trailer[conn->trlPos++]=*datap;
- if(*datap == '\r')
+ if(*datap == 0x0d)
ch->state = CHUNK_TRAILER_CR;
else {
datap++;
break;
case CHUNK_TRAILER_CR:
- if(*datap == '\r') {
+ if(*datap == 0x0d) {
ch->state = CHUNK_TRAILER_POSTCR;
datap++;
length--;
break;
case CHUNK_TRAILER_POSTCR:
- if (*datap == '\n') {
- conn->trailer[conn->trlPos++]='\n';
+ if (*datap == 0x0a) {
+ conn->trailer[conn->trlPos++]=0x0a;
conn->trailer[conn->trlPos]=0;
if (conn->trlPos==2) {
ch->state = CHUNK_STOP;
return CHUNKE_STOP;
}
else {
+#ifdef CURL_DOES_CONVERSIONS
+ /* Convert to host encoding before calling Curl_client_write */
+ result = Curl_convert_from_network(conn->data,
+ ch->hexbuffer,
+ ch->hexindex);
+ if(result != CURLE_OK) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* Treat it as a bad chunk */
+ return(CHUNKE_BAD_CHUNK);
+ }
+#endif /* CURL_DOES_CONVERSIONS */
Curl_client_write(conn, CLIENTWRITE_HEADER,
conn->trailer, conn->trlPos);
}
#include "strtok.h"
#include "url.h" /* for Curl_safefree() */
#include "memory.h"
+#include "easyif.h" /* included for Curl_convert_... prototypes */
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
struct SessionHandle *data = conn->data;
struct digestdata *d;
+#ifdef CURL_DOES_CONVERSIONS
+ CURLcode rc;
+/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
+ It converts digest text to ASCII so the MD5 will be correct for
+ what ultimately goes over the network.
+*/
+#define CURL_OUTPUT_DIGEST_CONV(a, b) \
+ rc = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
+ if (rc != CURLE_OK) { \
+ free(b); \
+ return rc; \
+ }
+#else
+#define CURL_OUTPUT_DIGEST_CONV(a, b)
+#endif /* CURL_DOES_CONVERSIONS */
if(proxy) {
d = &data->state.proxydigest;
aprintf("%s:%s:%s", userp, d->realm, passwdp);
if(!md5this)
return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
tmp = aprintf("%s:%s:%s", ha1, d->nonce, d->cnonce);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
+ CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */
Curl_md5it(md5buf, (unsigned char *)tmp);
free(tmp); /* free this again */
md5_to_ascii(md5buf, ha1);
entity-body here */
/* TODO: Append H(entity-body)*/
}
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, ha2);
if(!md5this)
return CURLE_OUT_OF_MEMORY;
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, request_digest);
return CURLE_OK;
}
+#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
/*
* Internal read-from-socket function. This is meant to deal with plain
#ifdef CURL_DOES_CONVERSIONS
char buf[BUFSIZE+1];
+ int conv_size;
switch(type) {
case CURLINFO_HEADER_OUT:
size = BUFSIZE; /* truncate if necessary */
buf[BUFSIZE] = '\0';
}
+ conv_size = size;
memcpy(buf, ptr, size);
- Curl_convert_from_network(data, buf, size);
+ /* Special processing is needed for this block if it
+ * contains both headers and data (separated by CRLFCRLF).
+ * We want to convert just the headers, leaving the data as-is.
+ */
+ if(size > 4) {
+ int i;
+ for(i = 0; i < size-4; i++) {
+ if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
+ /* convert everthing through this CRLFCRLF but no further */
+ conv_size = i + 4;
+ break;
+ }
+ }
+ }
+
+ Curl_convert_from_network(data, buf, conv_size);
/* Curl_convert_from_network calls failf if unsuccessful */
/* we might as well continue even if it fails... */
ptr = buf; /* switch pointer to use my buffer instead */
case CURLINFO_HEADER_IN:
fwrite(s_infotype[type], 2, 1, data->set.err);
fwrite(ptr, size, 1, data->set.err);
+#ifdef CURL_DOES_CONVERSIONS
+ if(size != conv_size) {
+ /* we had untranslated data so we need an explicit newline */
+ fwrite("\n", 1, 1, data->set.err);
+ }
+#endif
break;
default: /* nada */
break;
const char *s)
{
struct curl_slist *head = data->set.http200aliases;
+ bool rc = FALSE;
+#ifdef CURL_DOES_CONVERSIONS
+ /* convert from the network encoding using a scratch area */
+ char *scratch = calloc(1, strlen(s)+1);
+ if (NULL == scratch) {
+ failf (data, "Failed to calloc memory for conversion!");
+ return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
+ }
+ strcpy(scratch, s);
+ if (CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(scratch);
+ return FALSE; /* can't return CURLE_foobar so return FALSE */
+ }
+ s = scratch;
+#endif /* CURL_DOES_CONVERSIONS */
while (head) {
- if (checkprefix(head->data, s))
- return TRUE;
+ if (checkprefix(head->data, s)) {
+ rc = TRUE;
+ break;
+ }
head = head->next;
}
- if(checkprefix("HTTP/", s))
- return TRUE;
+ if ((rc != TRUE) && (checkprefix("HTTP/", s))) {
+ rc = TRUE;
+ }
- return FALSE;
+#ifdef CURL_DOES_CONVERSIONS
+ free(scratch);
+#endif /* CURL_DOES_CONVERSIONS */
+ return rc;
}
/*
/* str_start is start of line within buf */
k->str_start = k->str;
- k->end_ptr = memchr(k->str_start, '\n', nread);
+ /* data is in network encoding so use 0x0a instead of '\n' */
+ k->end_ptr = memchr(k->str_start, 0x0a, nread);
if (!k->end_ptr) {
/* Not a complete header line within buffer, append the data to
}
}
- if (('\n' == *k->p) || ('\r' == *k->p)) {
+ /* headers are in network encoding so
+ use 0x0a and 0x0d instead of '\n' and '\r' */
+ if ((0x0a == *k->p) || (0x0d == *k->p)) {
size_t headerlen;
/* Zero-length header line means end of headers! */
+#ifdef CURL_DOES_CONVERSIONS
+ if (0x0d == *k->p) {
+ *k->p = '\r'; /* replace with CR in host encoding */
+ k->p++; /* pass the CR byte */
+ }
+ if (0x0a == *k->p) {
+ *k->p = '\n'; /* replace with LF in host encoding */
+ k->p++; /* pass the LF byte */
+ }
+#else
if ('\r' == *k->p)
k->p++; /* pass the \r byte */
if ('\n' == *k->p)
k->p++; /* pass the \n byte */
+#endif /* CURL_DOES_CONVERSIONS */
if(100 == k->httpcode) {
/*
if (!k->headerline++) {
/* This is the first header, it MUST be the error code line
- or else we consiser this to be the body right away! */
+ or else we consider this to be the body right away! */
int httpversion_major;
- int nc=sscanf(k->p, " HTTP/%d.%d %3d",
- &httpversion_major,
- &k->httpversion,
- &k->httpcode);
+ int nc;
+#ifdef CURL_DOES_CONVERSIONS
+#define HEADER1 scratch
+#define SCRATCHSIZE 21
+ CURLcode res;
+ char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
+ /* We can't really convert this yet because we
+ don't know if it's the 1st header line or the body.
+ So we do a partial conversion into a scratch area,
+ leaving the data at k->p as-is.
+ */
+ strncpy(&scratch[0], k->p, SCRATCHSIZE);
+ scratch[SCRATCHSIZE] = 0; /* null terminate */
+ res = Curl_convert_from_network(data,
+ &scratch[0],
+ SCRATCHSIZE);
+ if (CURLE_OK != res) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ return res;
+ }
+#else
+#define HEADER1 k->p /* no conversion needed, just use k->p */
+#endif /* CURL_DOES_CONVERSIONS */
+
+ nc = sscanf(HEADER1,
+ " HTTP/%d.%d %3d",
+ &httpversion_major,
+ &k->httpversion,
+ &k->httpcode);
if (nc==3) {
k->httpversion += 10 * httpversion_major;
}
/* this is the real world, not a Nirvana
NCSA 1.5.x returns this crap when asked for HTTP/1.1
*/
- nc=sscanf(k->p, " HTTP %3d", &k->httpcode);
+ nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
k->httpversion = 10;
/* If user has set option HTTP200ALIASES,
}
}
+#ifdef CURL_DOES_CONVERSIONS
+ /* convert from the network encoding */
+ result = Curl_convert_from_network(data, k->p, strlen(k->p));
+ if (CURLE_OK != result) {
+ return(result);
+ }
+ /* Curl_convert_from_network calls failf if unsuccessful */
+#endif /* CURL_DOES_CONVERSIONS */
+
/* Check for Content-Length: header lines to get size. Ignore
the header completely if we get a 416 response as then we're
resuming a document that we don't get, and this header contains
start++)
; /* empty loop */
+ /* data is now in the host encoding so
+ use '\r' and '\n' instead of 0x0d and 0x0a */
end = strchr(start, '\r');
if(!end)
end = strchr(start, '\n');
if(data->set.useragent) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent =
- aprintf("User-Agent: %s\015\012", data->set.useragent);
+ aprintf("User-Agent: %s\r\n", data->set.useragent);
if(!conn->allocptr.uagent)
return CURLE_OUT_OF_MEMORY;
}