GSM A DTAP: add UMTS EVS to supported codecs list IE
[metze/wireshark/wip.git] / epan / dissectors / packet-http-urlencoded.c
1 /* packet-http-urlencoded.c
2  * Routines for dissection of HTTP urlecncoded form, based on packet-text-media.c (C) Olivier Biot, 2004.
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #define NEW_PROTO_TREE_API
12
13 #include "config.h"
14
15 #include <epan/packet.h>
16 #include <wsutil/str_util.h>
17
18 #include "packet-http.h"
19
20 void proto_register_http_urlencoded(void);
21 void proto_reg_handoff_http_urlencoded(void);
22
23 static dissector_handle_t form_urlencoded_handle;
24
25 static header_field_info *hfi_urlencoded = NULL;
26
27 #define URLENCODED_HFI_INIT HFI_INIT(proto_urlencoded)
28
29 static header_field_info hfi_form_key URLENCODED_HFI_INIT =
30         { "Key", "urlencoded-form.key", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL };
31
32 static header_field_info hfi_form_value URLENCODED_HFI_INIT =
33         { "Value", "urlencoded-form.value", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL };
34
35 static gint ett_form_urlencoded = -1;
36 static gint ett_form_keyvalue = -1;
37
38 static int
39 get_form_key_value(tvbuff_t *tvb, char **ptr, int offset, char stop)
40 {
41         const int orig_offset = offset;
42         char *tmp;
43         int len;
44
45         len = 0;
46         while (tvb_reported_length_remaining(tvb, offset) > 0) {
47                 guint8 ch;
48
49                 ch = tvb_get_guint8(tvb, offset);
50                 if (!ch)
51                         return -1;
52                 if (ch == stop)
53                         break;
54                 if (ch == '%') {
55                         offset++;
56                         ch = tvb_get_guint8(tvb, offset);
57                         if (ws_xton(ch) == -1)
58                                 return -1;
59
60                         offset++;
61                         ch = tvb_get_guint8(tvb, offset);
62                         if (ws_xton(ch) == -1)
63                                 return -1;
64                 }
65
66                 len++;
67                 offset++;
68         }
69
70         *ptr = tmp = (char*)wmem_alloc(wmem_packet_scope(), len + 1);
71         tmp[len] = '\0';
72
73         len = 0;
74         offset = orig_offset;
75         while (tvb_reported_length_remaining(tvb, offset) > 0) {
76                 guint8 ch;
77
78                 ch = tvb_get_guint8(tvb, offset);
79                 if (!ch)
80                         return -1;
81                 if (ch == stop)
82                         break;
83
84                 if (ch == '%') {
85                         guint8 ch1, ch2;
86
87                         offset++;
88                         ch1 = tvb_get_guint8(tvb, offset);
89
90                         offset++;
91                         ch2 = tvb_get_guint8(tvb, offset);
92
93                         tmp[len] = ws_xton(ch1) << 4 | ws_xton(ch2);
94
95                 } else if (ch == '+')
96                         tmp[len] = ' ';
97                 else
98                         tmp[len] = ch;
99
100                 len++;
101                 offset++;
102         }
103
104         return offset;
105 }
106
107
108 static int
109 dissect_form_urlencoded(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
110 {
111         proto_tree      *url_tree;
112         proto_tree      *sub;
113         proto_item      *ti;
114         gint            offset = 0, next_offset;
115         const char      *data_name;
116         http_message_info_t *message_info;
117
118         data_name = pinfo->match_string;
119         if (! (data_name && data_name[0])) {
120                 /*
121                  * No information from "match_string"
122                  */
123                 message_info = (http_message_info_t *)data;
124                 if (message_info == NULL) {
125                         /*
126                          * No information from dissector data
127                          */
128                         data_name = NULL;
129                 } else {
130                         data_name = message_info->media_str;
131                         if (! (data_name && data_name[0])) {
132                                 /*
133                                  * No information from dissector data
134                                  */
135                                 data_name = NULL;
136                         }
137                 }
138         }
139
140         if (data_name)
141                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name);
142
143         ti = proto_tree_add_item(tree, hfi_urlencoded, tvb, 0, -1, ENC_NA);
144         if (data_name)
145                 proto_item_append_text(ti, ": %s", data_name);
146         url_tree = proto_item_add_subtree(ti, ett_form_urlencoded);
147
148         while (tvb_reported_length_remaining(tvb, offset) > 0) {
149                 const int start_offset = offset;
150                 char *key, *value;
151
152                 sub = proto_tree_add_subtree(url_tree, tvb, offset, 0, ett_form_keyvalue, &ti, "Form item");
153
154                 next_offset = get_form_key_value(tvb, &key, offset, '=');
155                 if (next_offset == -1)
156                         break;
157                 proto_tree_add_string(sub, &hfi_form_key, tvb, offset, next_offset - offset, key);
158                 proto_item_append_text(sub, ": \"%s\"", key);
159
160                 offset = next_offset+1;
161
162                 next_offset = get_form_key_value(tvb, &value, offset, '&');
163                 if (next_offset == -1)
164                         break;
165                 proto_tree_add_string(sub, &hfi_form_value, tvb, offset, next_offset - offset, value);
166                 proto_item_append_text(sub, " = \"%s\"", value);
167
168                 offset = next_offset+1;
169
170                 proto_item_set_len(ti, offset - start_offset);
171         }
172
173         return tvb_captured_length(tvb);
174 }
175
176 void
177 proto_register_http_urlencoded(void)
178 {
179 #ifndef HAVE_HFI_SECTION_INIT
180         static header_field_info *hfi[] = {
181                 &hfi_form_key,
182                 &hfi_form_value,
183         };
184 #endif
185
186         static gint *ett[] = {
187                 &ett_form_urlencoded,
188                 &ett_form_keyvalue
189         };
190
191         int proto_urlencoded;
192
193         proto_urlencoded = proto_register_protocol("HTML Form URL Encoded", "URL Encoded Form Data", "urlencoded-form");
194         hfi_urlencoded = proto_registrar_get_nth(proto_urlencoded);
195
196         form_urlencoded_handle = register_dissector("urlencoded-form", dissect_form_urlencoded, proto_urlencoded);
197
198         proto_register_fields(proto_urlencoded, hfi, array_length(hfi));
199         proto_register_subtree_array(ett, array_length(ett));
200 }
201
202 void
203 proto_reg_handoff_http_urlencoded(void)
204 {
205         dissector_add_string("media_type", "application/x-www-form-urlencoded", form_urlencoded_handle);
206 }
207
208 /*
209  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
210  *
211  * Local variables:
212  * c-basic-offset: 8
213  * tab-width: 8
214  * indent-tabs-mode: t
215  * End:
216  *
217  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
218  * :indentSize=8:tabSize=8:noTabs=false:
219  */