浏览代码

Add setting to decode query strings

See discussion in #1018
bel2125 3 年之前
父节点
当前提交
cb479ff645
共有 3 个文件被更改,包括 35 次插入2 次删除
  1. 12 2
      docs/UserManual.md
  2. 21 0
      src/civetweb.c
  3. 2 0
      unittest/private.c

+ 12 - 2
docs/UserManual.md

@@ -260,9 +260,19 @@ Maximum allowed runtime for CGI scripts.  CGI processes are terminated by
 the server after this time.  The default is "no timeout", so scripts may
 the server after this time.  The default is "no timeout", so scripts may
 run or block for undefined time.
 run or block for undefined time.
 
 
+### decode\_query\_string `no`
+URL decode all query strings in the server. 
+If you set this option to `yes`, all callbacks and scripts will only see the already
+decoded query string. If this option is set to `no`, all callbacks and scripts have to decode
+the query strings on their own, if they need to. Note that setting this option to `yes` is not
+compatible with submitting form data using "GET" requests (but it is compatible with submitting
+form data using the "POST" method; using "POST" is recommended for most use cases).
+
 ### decode\_url `yes`
 ### decode\_url `yes`
-URL encoded request strings are decoded in the server, unless it is disabled
-by setting this option to `no`.
+The server should decode the URL, according to the HTTP standard.
+This means, `http://mydomain.com/this%20file.txt` will be decoded to `this file.txt` 
+(%20 corresponds to the URL encoding of the space character).
+Set this option to `no` only if you are using callbacks exclusively and need access to the encoded URLs.
 
 
 ### document\_root `.`
 ### document\_root `.`
 A directory to serve. By default, the current working directory is served.
 A directory to serve. By default, the current working directory is served.

+ 21 - 0
src/civetweb.c

@@ -1929,6 +1929,7 @@ enum {
 	ENABLE_WEBSOCKET_PING_PONG,
 	ENABLE_WEBSOCKET_PING_PONG,
 #endif
 #endif
 	DECODE_URL,
 	DECODE_URL,
+	DECODE_QUERY_STRING,
 #if defined(USE_LUA)
 #if defined(USE_LUA)
 	LUA_BACKGROUND_SCRIPT,
 	LUA_BACKGROUND_SCRIPT,
 	LUA_BACKGROUND_SCRIPT_PARAMS,
 	LUA_BACKGROUND_SCRIPT_PARAMS,
@@ -2067,6 +2068,7 @@ static const struct mg_option config_options[] = {
     {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"},
     {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"},
 #endif
 #endif
     {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"},
     {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"},
+    {"decode_query_string", MG_CONFIG_TYPE_BOOLEAN, "no"},
 #if defined(USE_LUA)
 #if defined(USE_LUA)
     {"lua_background_script", MG_CONFIG_TYPE_FILE, NULL},
     {"lua_background_script", MG_CONFIG_TYPE_FILE, NULL},
     {"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL},
     {"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL},
@@ -4036,6 +4038,18 @@ should_decode_url(const struct mg_connection *conn)
 }
 }
 
 
 
 
+static int
+should_decode_query_string(const struct mg_connection *conn)
+{
+	if (!conn || !conn->dom_ctx) {
+		return 0;
+	}
+
+	return (mg_strcasecmp(conn->dom_ctx->config[DECODE_QUERY_STRING], "yes")
+	        == 0);
+}
+
+
 static const char *
 static const char *
 suggest_connection_header(const struct mg_connection *conn)
 suggest_connection_header(const struct mg_connection *conn)
 {
 {
@@ -14040,6 +14054,13 @@ handle_request(struct mg_connection *conn)
 		    ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
 		    ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
 	}
 	}
 
 
+	/* URL decode the query-string only if explicity set in the configuration */
+	if (conn->request_info.query_string) {
+		if (should_decode_query_string(conn)) {
+			url_decode_in_place((char *)conn->request_info.query_string);
+		}
+	}
+
 	/* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is not
 	/* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is not
 	 * possible. The fact that we cleaned the URI is stored in that the
 	 * possible. The fact that we cleaned the URI is stored in that the
 	 * pointer to ri->local_ur and ri->local_uri_raw are now different.
 	 * pointer to ri->local_ur and ri->local_uri_raw are now different.

+ 2 - 0
unittest/private.c

@@ -1340,6 +1340,8 @@ START_TEST(test_config_options)
 #endif
 #endif
 
 
 	ck_assert_str_eq("decode_url", config_options[DECODE_URL].name);
 	ck_assert_str_eq("decode_url", config_options[DECODE_URL].name);
+	ck_assert_str_eq("decode_query_string",
+	                 config_options[DECODE_QUERY_STRING].name);
 
 
 #if defined(USE_LUA)
 #if defined(USE_LUA)
 	ck_assert_str_eq("lua_preload_file", config_options[LUA_PRELOAD_FILE].name);
 	ck_assert_str_eq("lua_preload_file", config_options[LUA_PRELOAD_FILE].name);