Explorar o código

Add setting to decode query strings

See discussion in #1018
bel2125 %!s(int64=3) %!d(string=hai) anos
pai
achega
cb479ff645
Modificáronse 3 ficheiros con 35 adicións e 2 borrados
  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
 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`
-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 `.`
 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,
 #endif
 	DECODE_URL,
+	DECODE_QUERY_STRING,
 #if defined(USE_LUA)
 	LUA_BACKGROUND_SCRIPT,
 	LUA_BACKGROUND_SCRIPT_PARAMS,
@@ -2067,6 +2068,7 @@ static const struct mg_option config_options[] = {
     {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"},
 #endif
     {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"},
+    {"decode_query_string", MG_CONFIG_TYPE_BOOLEAN, "no"},
 #if defined(USE_LUA)
     {"lua_background_script", MG_CONFIG_TYPE_FILE, 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 *
 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);
 	}
 
+	/* 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
 	 * 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.

+ 2 - 0
unittest/private.c

@@ -1340,6 +1340,8 @@ START_TEST(test_config_options)
 #endif
 
 	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)
 	ck_assert_str_eq("lua_preload_file", config_options[LUA_PRELOAD_FILE].name);