Document the possible presence of multiple variables with the
authorLuigi Rizzo <rizzo@icir.org>
Tue, 20 May 2008 17:48:43 +0000 (17:48 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Tue, 20 May 2008 17:48:43 +0000 (17:48 +0000)
same name in http queries, which might confuse the manager.

Replace calls to ast_uri_decode() with a local function that also
replaces '+' with ' ', as this is the normal encoding for
spaces in http requests.
This allows passing cli commands to the manager through the
http interface.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@117295 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/http.c

index 7dc46a3..5ab4d27 100644 (file)
@@ -370,6 +370,20 @@ void ast_http_uri_unlink_all_with_key(const char *key)
        AST_RWLIST_TRAVERSE_SAFE_END
 }
 
+/*
+ * Decode special characters in http uri.
+ * We have ast_uri_decode to handle %XX sequences, but spaces
+ * are encoded as a '+' so we need to replace them beforehand.
+ */
+static void http_decode(char *s)
+{
+       for (;*s; s++) {
+               if (*s == '+')
+                       *s = ' ';
+       }
+       ast_uri_decode(s);
+}
+
 static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method,
                                  int *status, char **title, int *contentlength, struct ast_variable **cookies, struct ast_variable *headers, 
                                  unsigned int *static_content)
@@ -387,18 +401,22 @@ static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char
        if (method == AST_HTTP_GET) {
                strsep(&params, "?");
                
-               /* Extract arguments from the request and store them in variables. */
+               /* Extract arguments from the request and store them in variables.
+                * Note that a request can have multiple arguments with the same
+                * name, and we store them all in the list of variables.
+                * It is up to the application to handle multiple values.
+                */
                if (params) {
                        char *var, *val;
                        
                        while ((val = strsep(&params, "&"))) {
                                var = strsep(&val, "=");
                                if (val) {
-                                       ast_uri_decode(val);
+                                       http_decode(val);
                                } else {
                                        val = "";
                                }
-                               ast_uri_decode(var);
+                               http_decode(var);
                                if ((v = ast_variable_new(var, val, ""))) {
                                        if (vars) {
                                                prev->next = v;
@@ -412,9 +430,11 @@ static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char
        }
 
        /*
-        * Append the cookies to the variables (the only reason to have them
-        * at the end is to avoid another pass of the cookies list to find
-        * the tail).
+        * Append the cookies to the list of variables.
+        * This saves a pass in the cookies list, but has the side effect
+        * that a variable might mask a cookie with the same name if the
+        * application stops at the first match.
+        * Note that this is the same behaviour as $_REQUEST variables in PHP.
         */
        if (prev) {
                prev->next = *cookies;
@@ -423,7 +443,7 @@ static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char
        }
        *cookies = NULL;
 
-       ast_uri_decode(uri);
+       http_decode(uri);
 
        AST_RWLIST_RDLOCK(&uri_redirects);
        AST_RWLIST_TRAVERSE(&uri_redirects, redirect, entry) {