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
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
;
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
;
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
);
51 len
+= (found_offset
- offset
);
52 offset
= found_offset
;
54 if (tvb_reported_length_remaining(tvb
, offset
) < 2) {
58 ch
= tvb_get_uint8(tvb
, offset
);
59 if (ws_xton(ch
) == -1)
63 ch
= tvb_get_uint8(tvb
, offset
);
64 if (ws_xton(ch
) == -1)
66 } else if (ch
!= '+') {
67 /* Key, matched '=', stop. */
75 *ptr
= tmp
= (char*)wmem_alloc(pool
, len
+ 1);
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
);
87 tvb_memcpy(tvb
, &tmp
[len
], offset
, found_offset
- offset
);
88 len
+= (found_offset
- offset
);
89 offset
= found_offset
;
94 ch1
= tvb_get_uint8(tvb
, offset
);
97 ch2
= tvb_get_uint8(tvb
, offset
);
99 tmp
[len
] = ws_xton(ch1
) << 4 | ws_xton(ch2
);
101 } else if (ch
== '+') {
104 /* Key, matched '=', stop */
117 dissect_form_urlencoded(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
119 proto_tree
*url_tree
;
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
139 data_name
= content_info
->media_str
;
140 if (! (data_name
&& data_name
[0])) {
142 * No information from dissector data
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
);
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) {
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)
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)
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
);
198 proto_register_http_urlencoded(void)
200 static hf_register_info hf
[] = {
202 { "Key", "urlencoded-form.key",
203 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
207 { "Value", "urlencoded-form.value",
208 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
213 static int *ett
[] = {
214 &ett_form_urlencoded
,
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
, "%+");
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
241 * indent-tabs-mode: t
244 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
245 * :indentSize=8:tabSize=8:noTabs=false: