Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-http-urlencoded.c
blob22cdd02b7b7e92c045f263adc1efd5bb4e804282
1 /* packet-http-urlencoded.c
2 * Routines for dissection of HTTP urlecncoded form, based on packet-text-media.c (C) Olivier Biot, 2004.
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 #include "config.h"
12 #include <epan/packet.h>
13 #include <epan/charsets.h>
14 #include <epan/strutil.h>
15 #include <wsutil/str_util.h>
17 #include "packet-media-type.h"
19 void proto_register_http_urlencoded(void);
20 void proto_reg_handoff_http_urlencoded(void);
22 static dissector_handle_t form_urlencoded_handle;
24 static int proto_urlencoded;
26 static int hf_form_key;
27 static int hf_form_value;
29 static int ett_form_urlencoded;
30 static int ett_form_keyvalue;
32 static ws_mempbrk_pattern pbrk_key;
33 static ws_mempbrk_pattern pbrk_value;
35 static int
36 get_form_key_value(wmem_allocator_t *pool, tvbuff_t *tvb, char **ptr, int offset, const ws_mempbrk_pattern *pbrk)
38 const int orig_offset = offset;
39 int found_offset;
40 uint8_t ch;
41 char *tmp;
42 int len;
44 len = 0;
45 while (tvb_reported_length_remaining(tvb, offset) > 0) {
46 found_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset, -1, pbrk, &ch);
47 if (found_offset == -1) {
48 len += tvb_reported_length_remaining(tvb, offset);
49 break;
51 len += (found_offset - offset);
52 offset = found_offset;
53 if (ch == '%') {
54 if (tvb_reported_length_remaining(tvb, offset) < 2) {
55 return -1;
57 offset++;
58 ch = tvb_get_uint8(tvb, offset);
59 if (ws_xton(ch) == -1)
60 return -1;
62 offset++;
63 ch = tvb_get_uint8(tvb, offset);
64 if (ws_xton(ch) == -1)
65 return -1;
66 } else if (ch != '+') {
67 /* Key, matched '=', stop. */
68 break;
71 len++;
72 offset++;
75 *ptr = tmp = (char*)wmem_alloc(pool, len + 1);
76 tmp[len] = '\0';
78 len = 0;
79 offset = orig_offset;
80 while (tvb_reported_length_remaining(tvb, offset)) {
81 found_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset, -1, pbrk, &ch);
82 if (found_offset == -1) {
83 tvb_memcpy(tvb, &tmp[len], offset, tvb_reported_length_remaining(tvb, offset));
84 offset = tvb_reported_length(tvb);
85 break;
87 tvb_memcpy(tvb, &tmp[len], offset, found_offset - offset);
88 len += (found_offset - offset);
89 offset = found_offset;
90 if (ch == '%') {
91 uint8_t ch1, ch2;
93 offset++;
94 ch1 = tvb_get_uint8(tvb, offset);
96 offset++;
97 ch2 = tvb_get_uint8(tvb, offset);
99 tmp[len] = ws_xton(ch1) << 4 | ws_xton(ch2);
101 } else if (ch == '+') {
102 tmp[len] = ' ';
103 } else {
104 /* Key, matched '=', stop */
105 break;
108 len++;
109 offset++;
112 return offset;
116 static int
117 dissect_form_urlencoded(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
119 proto_tree *url_tree;
120 proto_tree *sub;
121 proto_item *ti;
122 int offset = 0, next_offset, end_offset;
123 const char *data_name;
124 media_content_info_t *content_info;
125 tvbuff_t *sequence_tvb;
127 data_name = pinfo->match_string;
128 if (! (data_name && data_name[0])) {
130 * No information from "match_string"
132 content_info = (media_content_info_t *)data;
133 if (content_info == NULL) {
135 * No information from dissector data
137 data_name = NULL;
138 } else {
139 data_name = content_info->media_str;
140 if (! (data_name && data_name[0])) {
142 * No information from dissector data
144 data_name = NULL;
149 if (data_name)
150 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name);
152 ti = proto_tree_add_item(tree, proto_urlencoded, tvb, 0, -1, ENC_NA);
153 if (data_name)
154 proto_item_append_text(ti, ": %s", data_name);
155 url_tree = proto_item_add_subtree(ti, ett_form_urlencoded);
157 while (tvb_reported_length_remaining(tvb, offset) > 0) {
158 char *key, *value;
159 char *key_decoded, *value_decoded;
161 end_offset = tvb_find_uint8(tvb, offset, -1, '&');
162 if (end_offset == -1) {
163 end_offset = (int)tvb_reported_length(tvb);
165 sub = proto_tree_add_subtree(url_tree, tvb, offset, end_offset - offset, ett_form_keyvalue, NULL, "Form item");
167 sequence_tvb = tvb_new_subset_length(tvb, 0, end_offset);
168 next_offset = get_form_key_value(pinfo->pool, sequence_tvb, &key, offset, &pbrk_key);
169 if (next_offset == -1)
170 break;
171 /* XXX: Only UTF-8 is conforming according to WHATWG, though we
172 * ought to look for a "charset" parameter in media_str
173 * to handle other encodings.
174 * Our charset functions should probably return a boolean
175 * indicating that replacement characters had to be used,
176 * and that the string was not the expected encoding.
178 key_decoded = get_utf_8_string(pinfo->pool, key, (int)strlen(key));
179 proto_tree_add_string(sub, hf_form_key, tvb, offset, next_offset - offset, key_decoded);
180 proto_item_append_text(sub, ": \"%s\"", format_text(pinfo->pool, key, strlen(key)));
182 offset = next_offset+1;
184 next_offset = get_form_key_value(pinfo->pool, sequence_tvb, &value, offset, &pbrk_value);
185 if (next_offset == -1)
186 break;
187 value_decoded = get_utf_8_string(pinfo->pool, value, (int)strlen(value));
188 proto_tree_add_string(sub, hf_form_value, tvb, offset, next_offset - offset, value_decoded);
189 proto_item_append_text(sub, " = \"%s\"", format_text(pinfo->pool, value, strlen(value)));
191 offset = next_offset+1;
194 return tvb_captured_length(tvb);
197 void
198 proto_register_http_urlencoded(void)
200 static hf_register_info hf[] = {
201 { &hf_form_key,
202 { "Key", "urlencoded-form.key",
203 FT_STRINGZ, BASE_NONE, NULL, 0x0,
204 NULL, HFILL }
206 { &hf_form_value,
207 { "Value", "urlencoded-form.value",
208 FT_STRINGZ, BASE_NONE, NULL, 0x0,
209 NULL, HFILL }
213 static int *ett[] = {
214 &ett_form_urlencoded,
215 &ett_form_keyvalue
218 proto_urlencoded = proto_register_protocol("HTML Form URL Encoded", "URL Encoded Form Data", "urlencoded-form");
220 form_urlencoded_handle = register_dissector("urlencoded-form", dissect_form_urlencoded, proto_urlencoded);
222 proto_register_field_array(proto_urlencoded, hf, array_length(hf));
223 proto_register_subtree_array(ett, array_length(ett));
225 ws_mempbrk_compile(&pbrk_key, "%+=");
226 ws_mempbrk_compile(&pbrk_value, "%+");
229 void
230 proto_reg_handoff_http_urlencoded(void)
232 dissector_add_string("media_type", "application/x-www-form-urlencoded", form_urlencoded_handle);
236 * Editor modelines - https://www.wireshark.org/tools/modelines.html
238 * Local variables:
239 * c-basic-offset: 8
240 * tab-width: 8
241 * indent-tabs-mode: t
242 * End:
244 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
245 * :indentSize=8:tabSize=8:noTabs=false: