|  | @@ -1773,6 +1773,7 @@ field_get(const char *key, const char *value, size_t valuelen, void *user_data)
 | 
											
												
													
														|  |  	return 0;
 |  |  	return 0;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +static const char *myfile_content = "Content of myfile.txt\r\n";
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  static int
 |  |  static int
 | 
											
												
													
														|  |  field_store(const char *path, long long file_size, void *user_data)
 |  |  field_store(const char *path, long long file_size, void *user_data)
 | 
											
										
											
												
													
														|  | @@ -1786,7 +1787,7 @@ field_store(const char *path, long long file_size, void *user_data)
 | 
											
												
													
														|  |  	case 101:
 |  |  	case 101:
 | 
											
												
													
														|  |  		ck_assert_str_eq(path, "storeme.txt");
 |  |  		ck_assert_str_eq(path, "storeme.txt");
 | 
											
												
													
														|  |  		ck_assert_int_eq(file_size, 9);
 |  |  		ck_assert_int_eq(file_size, 9);
 | 
											
												
													
														|  | -		f = fopen("storeme.txt", "r");
 |  | 
 | 
											
												
													
														|  | 
 |  | +		f = fopen(path, "r");
 | 
											
												
													
														|  |  		ck_assert_ptr_ne(f, NULL);
 |  |  		ck_assert_ptr_ne(f, NULL);
 | 
											
												
													
														|  |  		if (f) {
 |  |  		if (f) {
 | 
											
												
													
														|  |  			char buf[10] = {0};
 |  |  			char buf[10] = {0};
 | 
											
										
											
												
													
														|  | @@ -1797,7 +1798,22 @@ field_store(const char *path, long long file_size, void *user_data)
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  		break;
 |  |  		break;
 | 
											
												
													
														|  |  	case 102:
 |  |  	case 102:
 | 
											
												
													
														|  | -		/* TODO: A file upload is only possible with multipart/form-data */
 |  | 
 | 
											
												
													
														|  | 
 |  | +		ck_assert_str_eq(path, "file2store.txt");
 | 
											
												
													
														|  | 
 |  | +		ck_assert_int_eq(file_size, 23);
 | 
											
												
													
														|  | 
 |  | +		ck_assert_int_eq(23, strlen(myfile_content));
 | 
											
												
													
														|  | 
 |  | +#ifdef _WIN32
 | 
											
												
													
														|  | 
 |  | +		f = fopen(path, "rb");
 | 
											
												
													
														|  | 
 |  | +#else
 | 
											
												
													
														|  | 
 |  | +		f = fopen(path, "r");
 | 
											
												
													
														|  | 
 |  | +#endif
 | 
											
												
													
														|  | 
 |  | +		ck_assert_ptr_ne(f, NULL);
 | 
											
												
													
														|  | 
 |  | +		if (f) {
 | 
											
												
													
														|  | 
 |  | +			char buf[32] = {0};
 | 
											
												
													
														|  | 
 |  | +			int i = (int)fread(buf, 1, sizeof(buf) - 1, f);
 | 
											
												
													
														|  | 
 |  | +			ck_assert_int_eq(i, file_size);
 | 
											
												
													
														|  | 
 |  | +			fclose(f);
 | 
											
												
													
														|  | 
 |  | +			ck_assert_str_eq(buf, myfile_content);
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		break;
 |  |  		break;
 | 
											
												
													
														|  |  	default:
 |  |  	default:
 | 
											
												
													
														|  |  		ck_abort_msg("field_get called with g_field_step == %i",
 |  |  		ck_abort_msg("field_get called with g_field_step == %i",
 | 
											
										
											
												
													
														|  | @@ -1836,7 +1852,10 @@ FormGet(struct mg_connection *conn, void *cbdata)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  static int
 |  |  static int
 | 
											
												
													
														|  | -FormStore(struct mg_connection *conn, void *cbdata)
 |  | 
 | 
											
												
													
														|  | 
 |  | +FormStore(struct mg_connection *conn,
 | 
											
												
													
														|  | 
 |  | +          void *cbdata,
 | 
											
												
													
														|  | 
 |  | +          int ret_expected,
 | 
											
												
													
														|  | 
 |  | +          int field_step_expected)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	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;
 | 
											
										
											
												
													
														|  | @@ -1856,14 +1875,28 @@ FormStore(struct mg_connection *conn, void *cbdata)
 | 
											
												
													
														|  |  	g_field_step = 100;
 |  |  	g_field_step = 100;
 | 
											
												
													
														|  |  	g_field_found_return = FORM_FIELD_STORAGE_STORE;
 |  |  	g_field_found_return = FORM_FIELD_STORAGE_STORE;
 | 
											
												
													
														|  |  	ret = mg_handle_form_request(conn, &fdh);
 |  |  	ret = mg_handle_form_request(conn, &fdh);
 | 
											
												
													
														|  | -	ck_assert_int_eq(ret, 3);
 |  | 
 | 
											
												
													
														|  | -	ck_assert_int_eq(g_field_step, 101);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	ck_assert_int_eq(ret, ret_expected);
 | 
											
												
													
														|  | 
 |  | +	ck_assert_int_eq(g_field_step, field_step_expected);
 | 
											
												
													
														|  |  	mg_printf(conn, "%i\r\n", ret);
 |  |  	mg_printf(conn, "%i\r\n", ret);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	return 1;
 |  |  	return 1;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +static int
 | 
											
												
													
														|  | 
 |  | +FormStore1(struct mg_connection *conn, void *cbdata)
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +	return FormStore(conn, cbdata, 3, 101);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +static int
 | 
											
												
													
														|  | 
 |  | +FormStore2(struct mg_connection *conn, void *cbdata)
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +	return FormStore(conn, cbdata, 4, 102);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  static void
 |  |  static void
 | 
											
												
													
														|  |  send_chunk_string(struct mg_connection *conn, const char *txt)
 |  |  send_chunk_string(struct mg_connection *conn, const char *txt)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
										
											
												
													
														|  | @@ -1904,7 +1937,8 @@ START_TEST(test_handle_form)
 | 
											
												
													
														|  |  	ck_assert_str_eq(opt, "8884");
 |  |  	ck_assert_str_eq(opt, "8884");
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	mg_set_request_handler(ctx, "/handle_form", FormGet, (void *)0);
 |  |  	mg_set_request_handler(ctx, "/handle_form", FormGet, (void *)0);
 | 
											
												
													
														|  | -	mg_set_request_handler(ctx, "/handle_form_store", FormStore, (void *)0);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	mg_set_request_handler(ctx, "/handle_form_store", FormStore1, (void *)0);
 | 
											
												
													
														|  | 
 |  | +	mg_set_request_handler(ctx, "/handle_form_store2", FormStore2, (void *)0);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	test_sleep(1);
 |  |  	test_sleep(1);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -2285,7 +2319,7 @@ START_TEST(test_handle_form)
 | 
											
												
													
														|  |  	                ebuf,
 |  |  	                ebuf,
 | 
											
												
													
														|  |  	                sizeof(ebuf),
 |  |  	                sizeof(ebuf),
 | 
											
												
													
														|  |  	                "%s",
 |  |  	                "%s",
 | 
											
												
													
														|  | -	                "POST /handle_form_store HTTP/1.0\r\n"
 |  | 
 | 
											
												
													
														|  | 
 |  | +	                "POST /handle_form_store2 HTTP/1.0\r\n"
 | 
											
												
													
														|  |  	                "Host: localhost:8884\r\n"
 |  |  	                "Host: localhost:8884\r\n"
 | 
											
												
													
														|  |  	                "Connection: close\r\n"
 |  |  	                "Connection: close\r\n"
 | 
											
												
													
														|  |  	                "Content-Type: multipart/form-data; "
 |  |  	                "Content-Type: multipart/form-data; "
 | 
											
										
											
												
													
														|  | @@ -2329,6 +2363,18 @@ START_TEST(test_handle_form)
 | 
											
												
													
														|  |  	send_chunk_string(client_conn, "\r\n");
 |  |  	send_chunk_string(client_conn, "\r\n");
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	send_chunk_string(client_conn, boundary);
 |  |  	send_chunk_string(client_conn, boundary);
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "-see-RFC-2388\r\n");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "Content-Disposition: form-data; ");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "name=\"file2store\";");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "filename=\"myfile.txt\"\r\n");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "Content-Type: ");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "application/octet-stream\r\n");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "X-Ignored-Header: xyz\r\n");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "\r\n");
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, myfile_content);
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, "\r\n");
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	send_chunk_string(client_conn, boundary);
 | 
											
												
													
														|  |  	send_chunk_string(client_conn, "Content-Disposition: form-data; ");
 |  |  	send_chunk_string(client_conn, "Content-Disposition: form-data; ");
 | 
											
												
													
														|  |  	send_chunk_string(client_conn, "name=\"break_field_handler\"\r\n");
 |  |  	send_chunk_string(client_conn, "name=\"break_field_handler\"\r\n");
 | 
											
												
													
														|  |  	send_chunk_string(client_conn, "\r\n");
 |  |  	send_chunk_string(client_conn, "\r\n");
 | 
											
										
											
												
													
														|  | @@ -2345,7 +2391,7 @@ START_TEST(test_handle_form)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	for (sleep_cnt = 0; sleep_cnt < 30; sleep_cnt++) {
 |  |  	for (sleep_cnt = 0; sleep_cnt < 30; sleep_cnt++) {
 | 
											
												
													
														|  |  		test_sleep(1);
 |  |  		test_sleep(1);
 | 
											
												
													
														|  | -		if (g_field_step == 101) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if (g_field_step == 102) {
 | 
											
												
													
														|  |  			break;
 |  |  			break;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -2685,7 +2731,7 @@ make_public_server_suite(void)
 | 
											
												
													
														|  |  	suite_add_tcase(suite, tcase_serverrequests);
 |  |  	suite_add_tcase(suite, tcase_serverrequests);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	tcase_add_test(tcase_handle_form, test_handle_form);
 |  |  	tcase_add_test(tcase_handle_form, test_handle_form);
 | 
											
												
													
														|  | -	tcase_set_timeout(tcase_handle_form, 120);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	tcase_set_timeout(tcase_handle_form, 300);
 | 
											
												
													
														|  |  	suite_add_tcase(suite, tcase_handle_form);
 |  |  	suite_add_tcase(suite, tcase_handle_form);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	tcase_add_test(tcase_http_auth, test_http_auth);
 |  |  	tcase_add_test(tcase_http_auth, test_http_auth);
 |