projects
/
project
/
uhttpd.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
7e44c75
)
fix chunked postdata parsing
author
Felix Fietkau
<nbd@openwrt.org>
Thu, 3 Jan 2013 01:49:36 +0000
(
02:49
+0100)
committer
Felix Fietkau
<nbd@openwrt.org>
Thu, 3 Jan 2013 01:49:36 +0000
(
02:49
+0100)
client.c
patch
|
blob
|
history
uhttpd.h
patch
|
blob
|
history
diff --git
a/client.c
b/client.c
index 6a0c4bf9cf4a0ab9b1ead291338151681c6316fe..408a8132b1645c03207faec7cf0fe5771be9463d 100644
(file)
--- a/
client.c
+++ b/
client.c
@@
-261,15
+261,16
@@
static bool client_data_cb(struct client *cl, char *buf, int len)
return false;
while (len) {
return false;
while (len) {
+ int offset = 0;
char *sep;
char *sep;
- r->content_length -= cur_len;
consumed += cur_len;
buf += cur_len;
len -= cur_len;
cur_len = min(r->content_length, len);
if (cur_len) {
consumed += cur_len;
buf += cur_len;
len -= cur_len;
cur_len = min(r->content_length, len);
if (cur_len) {
+ r->content_length -= cur_len;
if (d->data_send)
d->data_send(cl, buf, cur_len);
continue;
if (d->data_send)
d->data_send(cl, buf, cur_len);
continue;
@@
-278,28
+279,44
@@
static bool client_data_cb(struct client *cl, char *buf, int len)
if (!r->transfer_chunked)
break;
if (!r->transfer_chunked)
break;
- sep = strstr(buf, "\r\n");
+ if (r->transfer_chunked > 1)
+ offset = 2;
+
+ sep = strstr(buf + offset, "\r\n");
if (!sep)
break;
*sep = 0;
cur_len = sep + 2 - buf;
if (!sep)
break;
*sep = 0;
cur_len = sep + 2 - buf;
- r->content_length = strtoul(buf, &sep, 16);
+ r->content_length = strtoul(buf + offset, &sep, 16);
+ r->transfer_chunked++;
/* invalid chunk length */
if (sep && *sep)
/* invalid chunk length */
if (sep && *sep)
-
return false
;
+
goto abort
;
/* empty chunk == eof */
/* empty chunk == eof */
- if (!r->content_length)
{
+ if (!r->content_length)
r->transfer_chunked = false;
r->transfer_chunked = false;
- continue;
- }
+
+ continue;
+
+abort:
+ consumed = len;
+ r->content_length = 0;
+ r->transfer_chunked = 0;
+ break;
}
ustream_consume(cl->us, consumed);
}
ustream_consume(cl->us, consumed);
- return r->content_length || r->transfer_chunked;
+ if (!r->content_length && !r->transfer_chunked) {
+ if (cl->dispatch.data_done)
+ cl->dispatch.data_done(cl);
+
+ cl->state = CLIENT_STATE_DONE;
+ }
+ return false;
}
static bool client_header_cb(struct client *cl, char *buf, int len)
}
static bool client_header_cb(struct client *cl, char *buf, int len)
@@
-345,8
+362,6
@@
static void client_read_cb(struct client *cl)
if (!read_cbs[cl->state](cl, str, len)) {
if (len == us->r.buffer_len)
uh_header_error(cl, 413, "Request Entity Too Large");
if (!read_cbs[cl->state](cl, str, len)) {
if (len == us->r.buffer_len)
uh_header_error(cl, 413, "Request Entity Too Large");
- if (cl->dispatch.data_done)
- cl->dispatch.data_done(cl);
break;
}
} while(1);
break;
}
} while(1);
diff --git
a/uhttpd.h
b/uhttpd.h
index c36d3bba624ec76959b0b6fb81f4e0fb4a7fcf06..b2404f400efa5b238da4fd35e3d47dfffcc2b167 100644
(file)
--- a/
uhttpd.h
+++ b/
uhttpd.h
@@
-81,7
+81,7
@@
struct http_request {
int redirect_status;
int content_length;
bool expect_cont;
int redirect_status;
int content_length;
bool expect_cont;
-
bool
transfer_chunked;
+
uint8_t
transfer_chunked;
const char *url;
const struct auth_realm *realm;
};
const char *url;
const struct auth_realm *realm;
};