]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Add function to split HTTP query arguments.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 11 Aug 2015 14:04:57 +0000 (15:04 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 11 Aug 2015 14:04:57 +0000 (15:04 +0100)
src/libutil/http.c
src/libutil/http.h

index 3e4e4a7c468ca8c4bc19ba4c676783938bee13e3..82ffdc19fc6530f29a273bf928d955f484e1f1d4 100644 (file)
@@ -2325,3 +2325,108 @@ rspamd_http_connection_make_peer_key (const gchar *key)
 
        return kp;
 }
+
+GHashTable *
+rspamd_http_message_parse_query (struct rspamd_http_message *msg)
+{
+       GHashTable *res;
+       GString *key = NULL, *value = NULL;
+       const gchar *p, *c, *end;
+       struct http_parser_url u;
+       enum {
+               parse_key,
+               parse_eqsign,
+               parse_value,
+               parse_ampersand
+       } state = parse_key;
+
+       res = g_hash_table_new_full (rspamd_gstring_icase_hash,
+                       rspamd_gstring_icase_equal, rspamd_gstring_free_hard,
+                       rspamd_gstring_free_hard);
+
+       if (msg->url && msg->url->len > 0) {
+               http_parser_parse_url (msg->url->str, msg->url->len, TRUE, &u);
+
+               if (u.field_set & (1 << UF_QUERY)) {
+                       p = msg->url->str + u.field_data[UF_QUERY].off;
+                       c = p;
+                       end = p + u.field_data[UF_QUERY].len;
+
+                       while (p <= end) {
+                               switch (state) {
+                               case parse_key:
+                                       if ((*p == '&' || p == end) && p > c) {
+                                               /* We have a single parameter without a value */
+                                               key = g_string_sized_new (p - c);
+                                               g_string_append_len (key, c, p - c);
+                                               key->len = rspamd_decode_url (key->str, key->str,
+                                                               key->len);
+                                               value = g_string_new ("");
+                                               g_hash_table_insert (res, key, value);
+                                               state = parse_ampersand;
+                                       }
+                                       else if (*p == '=' && p > c) {
+                                               /* We have something like key=value */
+                                               key = g_string_sized_new (p - c);
+                                               g_string_append_len (key, c, p - c);
+                                               key->len = rspamd_decode_url (key->str, key->str,
+                                                               key->len);
+                                               state = parse_eqsign;
+                                       }
+                                       else {
+                                               p ++;
+                                       }
+                                       break;
+
+                               case parse_eqsign:
+                                       if (*p != '=') {
+                                               c = p;
+                                               state = parse_value;
+                                       }
+                                       else {
+                                               p ++;
+                                       }
+                                       break;
+
+                               case parse_value:
+                                       if ((*p == '&' || p == end) && p >= c) {
+                                               g_assert (key != NULL);
+                                               if (p > c) {
+                                                       value = g_string_sized_new (p - c);
+                                                       g_string_append_len (key, c, p - c);
+                                                       value->len = rspamd_decode_url (value->str, value->str,
+                                                                       value->len);
+                                               }
+                                               else {
+                                                       value = g_string_new ("");
+                                               }
+
+                                               g_hash_table_insert (res, key, value);
+                                               key = value = NULL;
+                                               state = parse_ampersand;
+                                       }
+                                       else {
+                                               p ++;
+                                       }
+                                       break;
+
+                               case parse_ampersand:
+                                       if (*p != '&') {
+                                               c = p;
+                                               state = parse_key;
+                                       }
+                                       else {
+                                               p ++;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+
+               if (state != parse_ampersand && key != NULL) {
+                       g_string_free (key, TRUE);
+               }
+       }
+
+       return res;
+}
index 46c79ebb43584013e36c7c27170685399fc4152b..efd6d1e17ac78160abf994c112ea8eeb8d4a392f 100644 (file)
@@ -398,4 +398,12 @@ void rspamd_http_router_handle_socket (
  */
 void rspamd_http_router_free (struct rspamd_http_connection_router *router);
 
+/**
+ * Extract arguments from a messsage's URI contained inside query string decoding
+ * them if needed
+ * @param msg HTTP request message
+ * @return new GHashTable which maps GString * to GString * (table must be freed by a caller)
+ */
+GHashTable* rspamd_http_message_parse_query (struct rspamd_http_message *msg);
+
 #endif /* HTTP_H_ */