Przeglądaj źródła

Alternative to mg_upload (Step 17/?)

bel 9 lat temu
rodzic
commit
0d433b9f23
2 zmienionych plików z 85 dodań i 27 usunięć
  1. 34 6
      examples/embedded_c/embedded_c.c
  2. 51 21
      src/handle_form.inl

+ 34 - 6
examples/embedded_c/embedded_c.c

@@ -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 {
 	int (*field_found)(const char *key,
 	                   size_t keylen,
 	                   const char *filename,
-	                   int *disposition,
 	                   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;
 };
 
@@ -169,16 +183,30 @@ int
 field_found(const char *key,
             size_t keylen,
             const char *filename,
-            int *disposition,
             void *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_printf(conn, " = ");
-	// mg_write(conn, value, vallen);
-	// TODO: disposition = skip/store/read/abort
-	mg_printf(conn, "\r\n");
+	mg_write(conn, value, valuelen);
+	mg_printf(conn, "\r\n\r\n");
 
 	return 0;
 }
@@ -190,7 +218,7 @@ FormHandler(struct mg_connection *conn, void *cbdata)
 	/* Handler may access the request info using mg_get_request_info */
 	const struct mg_request_info *req_info = mg_get_request_info(conn);
 	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 ? */
 	(void)req_info;

+ 51 - 21
src/handle_form.inl

@@ -51,8 +51,13 @@ struct mg_form_data_handler {
 	int (*field_found)(const char *key,
 	                   size_t keylen,
 	                   const char *filename,
-	                   int *disposition,
 	                   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;
 };
 
@@ -61,7 +66,6 @@ static int
 url_encoded_field_found(const char *key,
                         size_t keylen,
                         const char *filename,
-                        int *disposition,
                         struct mg_form_data_handler *fdh)
 {
 	/* Call callback */
@@ -69,14 +73,13 @@ url_encoded_field_found(const char *key,
 	int ret =
 	    mg_url_decode(key, (size_t)keylen, key_dec, (int)sizeof(key_dec), 1);
 	if ((ret < sizeof(key_dec)) && (ret >= 0)) {
-		return fdh->field_found(
-		    key, keylen, filename, disposition, fdh->user_data);
+		return fdh->field_found(key, keylen, filename, fdh->user_data);
 	}
 	return FORM_DISPOSITION_SKIP;
 }
 
 
-void
+int
 url_encoded_field_get(const char *key,
                       size_t keylen,
                       const char *filename,
@@ -88,16 +91,14 @@ url_encoded_field_get(const char *key,
 	char *value_dec = mg_malloc(valuelen + 1);
 	if (!value_dec) {
 		/* TODO: oom */
-		return;
+		return FORM_DISPOSITION_ABORT;
 	}
 
 	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);
 
-
-	/* TODO: Form decode */
-	fdh->field_get(
-	    key, keylen, filename, value, strlen(value_dec), fdh->user_data);
+	return fdh->field_get(
+	    key, keylen, filename, value_dec, strlen(value_dec), fdh->user_data);
 }
 
 
@@ -106,8 +107,9 @@ mg_handle_form_data(struct mg_connection *conn,
                     struct mg_form_data_handler *fdh)
 {
 	const char *content_type;
-	const char *boundary;
+	char buf[1024];
 	int disposition;
+	int buf_fill = 0;
 
 	int has_body_data =
 	    (conn->request_info.content_length > 0) || (conn->is_chunked);
@@ -150,8 +152,8 @@ mg_handle_form_data(struct mg_connection *conn,
 			}
 			keylen = val - data;
 
-			url_encoded_field_found(
-			    data, (size_t)keylen, NULL, &disposition, fdh);
+			disposition =
+			    url_encoded_field_found(data, (size_t)keylen, NULL, fdh);
 
 			val++;
 			next = strchr(val, '&');
@@ -166,7 +168,7 @@ mg_handle_form_data(struct mg_connection *conn,
 			if (disposition == FORM_DISPOSITION_GET) {
 				/* Call callback */
 				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 */
@@ -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 ... */
 		/* The encoding is like in the "GET" case above, but here we read data
 		 * on the fly */
-		char buf[1024];
-		int buf_fill = 0;
-
 		for (;;) {
 			/* TODO(high): Handle (text) fields with data > sizeof(buf). */
 			const char *val;
@@ -229,8 +228,8 @@ mg_handle_form_data(struct mg_connection *conn,
 			}
 
 			/* Call callback */
-			fdh->field_found(
-			    buf, (size_t)keylen, NULL, &disposition, fdh->user_data);
+			disposition =
+			    fdh->field_found(buf, (size_t)keylen, NULL, fdh->user_data);
 
 			/* Proceed to next entry */
 			used = next - buf;
@@ -241,14 +240,45 @@ mg_handle_form_data(struct mg_connection *conn,
 		return 0;
 	}
 
-	mirror_body___dev_helper(conn);
+	// mirror_body___dev_helper(conn);
 
 	if (!mg_strncasecmp(content_type, "MULTIPART/FORM-DATA;", 20)) {
 		/* The form data is in the request body data, encoded as multipart
 		 * content. */
+		const char *boundary;
+		size_t bl;
+		int r;
 
 		/* 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 */
 			return 0;
 		}