Переглянути джерело

Recognize both the CRLF sequence and single LF characters as line terminators.

master
Richard Nyberg 17 роки тому
джерело
коміт
1758597e3e
1 змінених файлів з 35 додано та 14 видалено
  1. +35
    -14
      misc/http_client.c

+ 35
- 14
misc/http_client.c Переглянути файл

@@ -132,11 +132,24 @@ http_error(struct http_req *req)
http_free(req);
}

static char *
strnl(char *str, int *nlsize)
{
char *nl = strchr(str, '\n');
if (nl != NULL && nl > str && *(nl - 1) == '\r') {
*nlsize = 2;
return nl - 1;
} else {
*nlsize = 1;
return nl;
}
}

static int
headers_parse(struct http_req *req, char *buf, char *end)
{
int code, majv, minv;
char *cur, *crlf;
int code, majv, minv, nlsize;
char *cur, *nl;
char name[128], value[872];
struct http_response res;

@@ -151,12 +164,12 @@ headers_parse(struct http_req *req, char *buf, char *end)
if (req->cancel)
return 1;

cur = strstr(buf, "\r\n") + 2;
crlf = strstr(cur, "\r\n");
cur = strchr(buf, '\n') + 1;
nl = strnl(cur, &nlsize);
while (cur < end) {
int i;
char *colon = strchr(cur, ':');
if (colon == NULL || colon > crlf)
if (colon == NULL || colon > nl)
return 0;
snprintf(name, sizeof(name), "%.*s", (int)(colon - cur), cur);

@@ -165,15 +178,15 @@ headers_parse(struct http_req *req, char *buf, char *end)
val_loop:
while (isblank(*cur))
cur++;
while (cur < crlf) {
while (cur < nl) {
if (i < sizeof(value) - 1) {
value[i] = *cur;
i++;
}
cur++;
}
cur += 2;
crlf = strstr(cur, "\r\n");
cur += nlsize;
nl = strnl(cur, &nlsize);
if (isblank(*cur)) {
if (i < sizeof(value) - 1) {
value[i] = ' ';
@@ -222,7 +235,11 @@ again:
case PS_HEAD:
if (len == 0)
goto error;
if ((end = evbuffer_find(req->buf, "\r\n\r\n", 4)) == NULL) {
if ((end = evbuffer_find(req->buf, "\r\n\r\n", 4)) != NULL)
dlen = 4;
else if ((end = evbuffer_find(req->buf, "\n\n", 2)) != NULL)
dlen = 2;
else {
if (req->buf->off < (1 << 15))
return 1;
else
@@ -235,13 +252,13 @@ again:
goto error;
if (req->cancel)
goto cancel;
evbuffer_drain(req->buf, end - (char *)req->buf->buffer + 4);
evbuffer_drain(req->buf, end - (char *)req->buf->buffer + dlen);
goto again;
case PS_CHUNK_SIZE:
assert(req->chunked);
if (len == 0)
goto error;
if ((end = evbuffer_find(req->buf, "\r\n", 2)) == NULL) {
if ((end = evbuffer_find(req->buf, "\n", 1)) == NULL) {
if (req->buf->off < 20)
return 1;
else
@@ -253,7 +270,7 @@ again:
goto error;
if (req->length == 0)
goto done;
evbuffer_drain(req->buf, end - (char *)req->buf->buffer + 2);
evbuffer_drain(req->buf, end - (char *)req->buf->buffer + 1);
req->pstate = PS_CHUNK_DATA;
goto again;
case PS_CHUNK_DATA:
@@ -282,9 +299,13 @@ again:
assert(req->length == 0);
if (req->buf->off < 2)
return 1;
if (bcmp(req->buf->buffer, "\r\n", 2) != 0)
if (req->buf->buffer[0] == '\r' && req->buf->buffer[1] == '\n')
dlen = 2;
else if (req->buf->buffer[0] == '\n')
dlen = 1;
else
goto error;
evbuffer_drain(req->buf, 2);
evbuffer_drain(req->buf, dlen);
req->pstate = PS_CHUNK_SIZE;
goto again;
case PS_ID_DATA:


Завантаження…
Відмінити
Зберегти