mirror of
https://github.com/lammertb/libhttp.git
synced 2025-07-29 21:01:13 +03:00
Alternative to mg_upload (Step 17/?)
This commit is contained in:
@ -155,12 +155,26 @@ FileHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FORM_DISPOSITION_SKIP = 0x0,
|
||||||
|
FORM_DISPOSITION_GET = 0x1,
|
||||||
|
FORM_DISPOSITION_STORE = 0x2,
|
||||||
|
FORM_DISPOSITION_READ = 0x4,
|
||||||
|
FORM_DISPOSITION_ABORT = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct mg_form_data_handler {
|
struct mg_form_data_handler {
|
||||||
int (*field_found)(const char *key,
|
int (*field_found)(const char *key,
|
||||||
size_t keylen,
|
size_t keylen,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
int *disposition,
|
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
int (*field_get)(const char *key,
|
||||||
|
size_t keylen,
|
||||||
|
const char *filename,
|
||||||
|
const char *value,
|
||||||
|
size_t valuelen,
|
||||||
|
void *user_data);
|
||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -169,16 +183,30 @@ int
|
|||||||
field_found(const char *key,
|
field_found(const char *key,
|
||||||
size_t keylen,
|
size_t keylen,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
int *disposition,
|
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn = (struct mg_connection *)user_data;
|
struct mg_connection *conn = (struct mg_connection *)user_data;
|
||||||
|
|
||||||
|
mg_write(conn, key, keylen);
|
||||||
|
mg_printf(conn, ":\r\n");
|
||||||
|
return FORM_DISPOSITION_GET;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
field_get(const char *key,
|
||||||
|
size_t keylen,
|
||||||
|
const char *filename,
|
||||||
|
const char *value,
|
||||||
|
size_t valuelen,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct mg_connection *conn = (struct mg_connection *)user_data;
|
||||||
|
|
||||||
mg_write(conn, key, keylen);
|
mg_write(conn, key, keylen);
|
||||||
mg_printf(conn, " = ");
|
mg_printf(conn, " = ");
|
||||||
// mg_write(conn, value, vallen);
|
mg_write(conn, value, valuelen);
|
||||||
// TODO: disposition = skip/store/read/abort
|
mg_printf(conn, "\r\n\r\n");
|
||||||
mg_printf(conn, "\r\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -190,7 +218,7 @@ FormHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
/* Handler may access the request info using mg_get_request_info */
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
int ret;
|
int ret;
|
||||||
struct mg_form_data_handler fdh = {field_found, 0};
|
struct mg_form_data_handler fdh = {field_found, field_get, 0};
|
||||||
|
|
||||||
/* TODO: Checks before calling handle_form_data ? */
|
/* TODO: Checks before calling handle_form_data ? */
|
||||||
(void)req_info;
|
(void)req_info;
|
||||||
|
@ -51,8 +51,13 @@ struct mg_form_data_handler {
|
|||||||
int (*field_found)(const char *key,
|
int (*field_found)(const char *key,
|
||||||
size_t keylen,
|
size_t keylen,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
int *disposition,
|
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
int (*field_get)(const char *key,
|
||||||
|
size_t keylen,
|
||||||
|
const char *filename,
|
||||||
|
const char *value,
|
||||||
|
size_t valuelen,
|
||||||
|
void *user_data);
|
||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,7 +66,6 @@ static int
|
|||||||
url_encoded_field_found(const char *key,
|
url_encoded_field_found(const char *key,
|
||||||
size_t keylen,
|
size_t keylen,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
int *disposition,
|
|
||||||
struct mg_form_data_handler *fdh)
|
struct mg_form_data_handler *fdh)
|
||||||
{
|
{
|
||||||
/* Call callback */
|
/* Call callback */
|
||||||
@ -69,14 +73,13 @@ url_encoded_field_found(const char *key,
|
|||||||
int ret =
|
int ret =
|
||||||
mg_url_decode(key, (size_t)keylen, key_dec, (int)sizeof(key_dec), 1);
|
mg_url_decode(key, (size_t)keylen, key_dec, (int)sizeof(key_dec), 1);
|
||||||
if ((ret < sizeof(key_dec)) && (ret >= 0)) {
|
if ((ret < sizeof(key_dec)) && (ret >= 0)) {
|
||||||
return fdh->field_found(
|
return fdh->field_found(key, keylen, filename, fdh->user_data);
|
||||||
key, keylen, filename, disposition, fdh->user_data);
|
|
||||||
}
|
}
|
||||||
return FORM_DISPOSITION_SKIP;
|
return FORM_DISPOSITION_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
int
|
||||||
url_encoded_field_get(const char *key,
|
url_encoded_field_get(const char *key,
|
||||||
size_t keylen,
|
size_t keylen,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
@ -88,16 +91,14 @@ url_encoded_field_get(const char *key,
|
|||||||
char *value_dec = mg_malloc(valuelen + 1);
|
char *value_dec = mg_malloc(valuelen + 1);
|
||||||
if (!value_dec) {
|
if (!value_dec) {
|
||||||
/* TODO: oom */
|
/* TODO: oom */
|
||||||
return;
|
return FORM_DISPOSITION_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_url_decode(key, (size_t)keylen, key_dec, (int)sizeof(key_dec), 1);
|
mg_url_decode(key, (size_t)keylen, key_dec, (int)sizeof(key_dec), 1);
|
||||||
mg_url_decode(value, (size_t)valuelen, value_dec, (int)valuelen + 1, 1);
|
mg_url_decode(value, (size_t)valuelen, value_dec, (int)valuelen + 1, 1);
|
||||||
|
|
||||||
|
return fdh->field_get(
|
||||||
/* TODO: Form decode */
|
key, keylen, filename, value_dec, strlen(value_dec), fdh->user_data);
|
||||||
fdh->field_get(
|
|
||||||
key, keylen, filename, value, strlen(value_dec), fdh->user_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -106,8 +107,9 @@ mg_handle_form_data(struct mg_connection *conn,
|
|||||||
struct mg_form_data_handler *fdh)
|
struct mg_form_data_handler *fdh)
|
||||||
{
|
{
|
||||||
const char *content_type;
|
const char *content_type;
|
||||||
const char *boundary;
|
char buf[1024];
|
||||||
int disposition;
|
int disposition;
|
||||||
|
int buf_fill = 0;
|
||||||
|
|
||||||
int has_body_data =
|
int has_body_data =
|
||||||
(conn->request_info.content_length > 0) || (conn->is_chunked);
|
(conn->request_info.content_length > 0) || (conn->is_chunked);
|
||||||
@ -150,8 +152,8 @@ mg_handle_form_data(struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
keylen = val - data;
|
keylen = val - data;
|
||||||
|
|
||||||
url_encoded_field_found(
|
disposition =
|
||||||
data, (size_t)keylen, NULL, &disposition, fdh);
|
url_encoded_field_found(data, (size_t)keylen, NULL, fdh);
|
||||||
|
|
||||||
val++;
|
val++;
|
||||||
next = strchr(val, '&');
|
next = strchr(val, '&');
|
||||||
@ -166,7 +168,7 @@ mg_handle_form_data(struct mg_connection *conn,
|
|||||||
if (disposition == FORM_DISPOSITION_GET) {
|
if (disposition == FORM_DISPOSITION_GET) {
|
||||||
/* Call callback */
|
/* Call callback */
|
||||||
url_encoded_field_get(
|
url_encoded_field_get(
|
||||||
data, (size_t)keylen, val, (size_t)vallen, fdh);
|
data, (size_t)keylen, NULL, val, (size_t)vallen, fdh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Proceed to next entry */
|
/* Proceed to next entry */
|
||||||
@ -186,9 +188,6 @@ mg_handle_form_data(struct mg_connection *conn,
|
|||||||
/* Read body data and split it in a=1&b&c=3&c=4 ... */
|
/* Read body data and split it in a=1&b&c=3&c=4 ... */
|
||||||
/* The encoding is like in the "GET" case above, but here we read data
|
/* The encoding is like in the "GET" case above, but here we read data
|
||||||
* on the fly */
|
* on the fly */
|
||||||
char buf[1024];
|
|
||||||
int buf_fill = 0;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* TODO(high): Handle (text) fields with data > sizeof(buf). */
|
/* TODO(high): Handle (text) fields with data > sizeof(buf). */
|
||||||
const char *val;
|
const char *val;
|
||||||
@ -229,8 +228,8 @@ mg_handle_form_data(struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Call callback */
|
/* Call callback */
|
||||||
fdh->field_found(
|
disposition =
|
||||||
buf, (size_t)keylen, NULL, &disposition, fdh->user_data);
|
fdh->field_found(buf, (size_t)keylen, NULL, fdh->user_data);
|
||||||
|
|
||||||
/* Proceed to next entry */
|
/* Proceed to next entry */
|
||||||
used = next - buf;
|
used = next - buf;
|
||||||
@ -241,14 +240,45 @@ mg_handle_form_data(struct mg_connection *conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mirror_body___dev_helper(conn);
|
// mirror_body___dev_helper(conn);
|
||||||
|
|
||||||
if (!mg_strncasecmp(content_type, "MULTIPART/FORM-DATA;", 20)) {
|
if (!mg_strncasecmp(content_type, "MULTIPART/FORM-DATA;", 20)) {
|
||||||
/* The form data is in the request body data, encoded as multipart
|
/* The form data is in the request body data, encoded as multipart
|
||||||
* content. */
|
* content. */
|
||||||
|
const char *boundary;
|
||||||
|
size_t bl;
|
||||||
|
int r;
|
||||||
|
|
||||||
/* There has to be a BOUNDARY definition in the Content-Type header */
|
/* There has to be a BOUNDARY definition in the Content-Type header */
|
||||||
if (!mg_strncasecmp(content_type + 20, "BOUNDARY=", 9)) {
|
if (mg_strncasecmp(content_type + 21, "BOUNDARY=", 9)) {
|
||||||
|
/* Malformed request */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boundary = content_type + 30;
|
||||||
|
bl = strlen(boundary);
|
||||||
|
|
||||||
|
r = mg_read(conn, buf + buf_fill, sizeof(buf) - 1 - buf_fill);
|
||||||
|
if (r < 0) {
|
||||||
|
/* read error */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buf_fill += r;
|
||||||
|
buf[buf_fill] = 0;
|
||||||
|
if (buf_fill < 1) {
|
||||||
|
/* No data */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf[0] != '-' || buf[1] != '-') {
|
||||||
|
/* Malformed request */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strncmp(buf + 2, boundary, bl)) {
|
||||||
|
/* Malformed request */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (buf[bl + 2] != '\r' || buf[bl + 3] != '\n') {
|
||||||
/* Malformed request */
|
/* Malformed request */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user