2 * Routines for "find frame" window
4 * $Id: find_dlg.c,v 1.53 2004/05/26 03:49:23 ulfl Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <epan/proto.h>
35 #include <epan/dfilter/dfilter.h>
40 #include "filter_prefs.h"
41 #include "alert_box.h"
42 #include "simple_dialog.h"
43 #include "dlg_utils.h"
44 #include "compat_macros.h"
46 #include "prefs_dlg.h"
49 /* Capture callback data keys */
50 #define E_FIND_FILT_KEY "find_filter_te"
51 #define E_FIND_BACKWARD_KEY "find_backward"
52 #define E_FIND_HEXDATA_KEY "find_hex"
53 #define E_FIND_STRINGDATA_KEY "find_string"
54 #define E_FIND_FILTERDATA_KEY "find_filter"
55 #define E_FIND_STRINGTYPE_KEY "find_string_type"
56 #define E_FIND_STRINGTYPE_LABEL_KEY "find_string_type_label"
57 #define E_CASE_SEARCH_KEY "case_insensitive_search"
58 #define E_SOURCE_HEX_KEY "hex_data_source"
59 #define E_SOURCE_DECODE_KEY "decode_data_source"
60 #define E_SOURCE_SUMMARY_KEY "summary_data_source"
61 #define E_FILT_TE_BUTTON_KEY "find_filter_button"
63 static gboolean case_type = TRUE;
64 static gboolean summary_data = FALSE;
65 static gboolean decode_data = FALSE;
68 find_filter_te_syntax_check_cb(GtkWidget *w, gpointer parent_w);
71 find_frame_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
74 find_frame_close_cb(GtkWidget *close_bt, gpointer parent_w);
77 find_frame_destroy_cb(GtkWidget *win, gpointer user_data);
80 hex_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
83 string_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
86 filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
89 convert_string_to_hex(const char *string, size_t *nbytes);
92 * Keep a static pointer to the current "Find Packet" window, if any, so
93 * that if somebody tries to do "Find Packet" while there's already a
94 * "Find Packet" window up, we just pop up the existing one, rather than
97 static GtkWidget *find_frame_w;
98 static GtkWidget *filter_text_box;
101 find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
103 GtkWidget *main_vb, *main_find_hb, *main_options_hb,
105 *find_type_frame, *find_type_vb,
106 *find_type_hb, *find_type_lb, *hex_rb, *string_rb, *filter_rb,
107 *filter_hb, *filter_bt,
109 *direction_frame, *direction_vb,
112 *data_frame, *data_vb,
113 *hex_data_rb, *decode_data_rb, *summary_data_rb,
115 *string_opt_frame, *string_opt_vb,
116 *case_cb, *combo_lb, *combo_cb,
118 *bbox, *ok_bt, *cancel_bt;
119 GtkTooltips *tooltips;
120 #if GTK_MAJOR_VERSION < 2
121 GtkAccelGroup *accel_group;
124 /* No Apply button, but "OK" not only sets our text widget, it
125 activates it (i.e., it causes us to do the search). */
126 static construct_args_t args = {
127 "Ethereal: Search Filter",
132 if (find_frame_w != NULL) {
133 /* There's already a "Find Packet" dialog box; reactivate it. */
134 reactivate_window(find_frame_w);
138 find_frame_w = dlg_window_new("Ethereal: Find Packet");
140 tooltips = gtk_tooltips_new ();
142 #if GTK_MAJOR_VERSION < 2
143 /* Accelerator group for the accelerators (or, as they're called in
144 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
145 Ctrl+<key> is an accelerator). */
146 accel_group = gtk_accel_group_new();
147 gtk_window_add_accel_group(GTK_WINDOW(find_frame_w), accel_group);
150 /* Container for each row of widgets */
151 main_vb = gtk_vbox_new(FALSE, 3);
152 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
153 gtk_container_add(GTK_CONTAINER(find_frame_w), main_vb);
154 gtk_widget_show(main_vb);
158 main_find_hb = gtk_hbox_new(FALSE, 3);
159 gtk_container_add(GTK_CONTAINER(main_vb), main_find_hb);
160 gtk_widget_show(main_find_hb);
164 find_type_frame = gtk_frame_new("Find");
165 gtk_box_pack_start(GTK_BOX(main_find_hb), find_type_frame, TRUE, TRUE, 0);
166 gtk_widget_show(find_type_frame);
168 find_type_vb = gtk_vbox_new(FALSE, 3);
169 gtk_container_border_width(GTK_CONTAINER(find_type_vb), 3);
170 gtk_container_add(GTK_CONTAINER(find_type_frame), find_type_vb);
171 gtk_widget_show(find_type_vb);
174 find_type_hb = gtk_hbox_new(FALSE, 3);
175 gtk_container_add(GTK_CONTAINER(find_type_vb), find_type_hb);
176 gtk_widget_show(find_type_hb);
178 find_type_lb = gtk_label_new("By:");
179 gtk_box_pack_start(GTK_BOX(find_type_hb), find_type_lb, FALSE, FALSE, 0);
180 gtk_widget_show(find_type_lb);
183 filter_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL,
184 "_Display filter", accel_group);
185 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_rb), !cfile.hex && !cfile.string);
186 gtk_box_pack_start(GTK_BOX(find_type_hb), filter_rb, FALSE, FALSE, 0);
187 gtk_tooltips_set_tip (tooltips, filter_rb, ("Search for data by display filter syntax.\ne.g. ip.addr==10.1.1.1"), NULL);
188 gtk_widget_show(filter_rb);
191 hex_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(filter_rb,
192 "_Hex value", accel_group);
193 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_rb), cfile.hex);
194 gtk_box_pack_start(GTK_BOX(find_type_hb), hex_rb, FALSE, FALSE, 0);
195 gtk_tooltips_set_tip (tooltips, hex_rb, ("Search for data by hex string.\ne.g. fffffda5"), NULL);
196 gtk_widget_show(hex_rb);
199 string_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(filter_rb,
200 "_String", accel_group);
201 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(string_rb), cfile.string);
202 gtk_box_pack_start(GTK_BOX(find_type_hb), string_rb, FALSE, FALSE, 0);
203 gtk_tooltips_set_tip (tooltips, string_rb, ("Search for data by string value.\ne.g. My String"), NULL);
204 gtk_widget_show(string_rb);
207 filter_hb = gtk_hbox_new(FALSE, 3);
208 gtk_box_pack_start(GTK_BOX(find_type_vb), filter_hb, FALSE, FALSE, 0);
209 gtk_widget_show(filter_hb);
211 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
212 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
213 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
214 OBJECT_SET_DATA(filter_bt, E_FILT_TE_BUTTON_KEY, filter_bt);
215 gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
216 gtk_tooltips_set_tip (tooltips, filter_bt, ("Click on the filter button to select a display filter,\nor enter your search criteria into the text box"), NULL);
217 gtk_widget_show(filter_bt);
219 filter_text_box = gtk_entry_new();
220 if (cfile.sfilter) gtk_entry_set_text(GTK_ENTRY(filter_text_box), cfile.sfilter);
221 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_text_box);
222 OBJECT_SET_DATA(find_frame_w, E_FILT_TE_PTR_KEY, filter_text_box);
223 gtk_box_pack_start(GTK_BOX(filter_hb), filter_text_box, TRUE, TRUE, 0);
224 SIGNAL_CONNECT(filter_text_box, "changed", find_filter_te_syntax_check_cb, find_frame_w);
225 gtk_widget_show(filter_text_box);
229 main_options_hb = gtk_hbox_new(FALSE, 3);
230 gtk_container_add(GTK_CONTAINER(main_vb), main_options_hb);
231 gtk_widget_show(main_options_hb);
234 /* search in frame */
235 data_frame = gtk_frame_new("Search In");
236 gtk_box_pack_start(GTK_BOX(main_options_hb), data_frame, TRUE, TRUE, 0);
237 gtk_widget_show(data_frame);
240 data_vb = gtk_vbox_new(TRUE, 0);
241 gtk_container_border_width(GTK_CONTAINER(data_vb), 3);
242 gtk_container_add(GTK_CONTAINER(data_frame), data_vb);
243 gtk_widget_show(data_vb);
246 summary_data_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL,
247 "Packet list", accel_group);
248 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(summary_data_rb), summary_data);
249 gtk_box_pack_start(GTK_BOX(data_vb), summary_data_rb, TRUE, TRUE, 0);
250 gtk_tooltips_set_tip (tooltips, summary_data_rb, ("Search for string in the Info column of the packet summary (top pane)"), NULL);
251 gtk_widget_show(summary_data_rb);
254 decode_data_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(summary_data_rb,
255 "Packet details", accel_group);
256 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(decode_data_rb), decode_data);
257 gtk_box_pack_start(GTK_BOX(data_vb), decode_data_rb, TRUE, TRUE, 0);
258 gtk_tooltips_set_tip (tooltips, decode_data_rb, ("Search for string in the decoded packet display (middle pane)"), NULL);
259 gtk_widget_show(decode_data_rb);
262 hex_data_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(summary_data_rb,
263 "Packet bytes", accel_group);
264 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_data_rb), !decode_data && !summary_data);
265 gtk_box_pack_start(GTK_BOX(data_vb), hex_data_rb, TRUE, TRUE, 0);
266 gtk_tooltips_set_tip (tooltips, hex_data_rb, ("Search for string in the packet data"), NULL);
267 gtk_widget_show(hex_data_rb);
269 /* string options frame */
270 string_opt_frame = gtk_frame_new("String Options");
271 gtk_box_pack_start(GTK_BOX(main_options_hb), string_opt_frame, TRUE, TRUE, 0);
272 gtk_widget_show(string_opt_frame);
274 string_opt_vb = gtk_vbox_new(FALSE, 0);
275 gtk_container_add(GTK_CONTAINER(string_opt_frame), string_opt_vb);
276 gtk_container_border_width(GTK_CONTAINER(string_opt_vb), 3);
277 gtk_widget_show(string_opt_vb);
279 case_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC(
280 "Case sensitive", accel_group);
281 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(case_cb), !case_type);
282 gtk_container_add(GTK_CONTAINER(string_opt_vb), case_cb);
283 gtk_tooltips_set_tip (tooltips, case_cb, ("Search by mixed upper/lower case?"), NULL);
284 gtk_widget_show(case_cb);
286 combo_lb = gtk_label_new("Character set:");
287 gtk_container_add(GTK_CONTAINER(string_opt_vb), combo_lb);
288 gtk_misc_set_alignment(GTK_MISC(combo_lb), 0.0, 0.5);
289 gtk_widget_show(combo_lb);
291 /* String Type Selection Dropdown Box
292 These only apply to the Hex Window search option */
293 /* Create Combo Box */
294 combo_cb = gtk_combo_new();
296 glist = g_list_append(glist, "ASCII Unicode & Non-Unicode");
297 glist = g_list_append(glist, "ASCII Non-Unicode");
298 glist = g_list_append(glist, "ASCII Unicode");
300 gtk_combo_set_popdown_strings(GTK_COMBO(combo_cb), glist);
301 /* You only get to choose from the options we offer */
302 gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(combo_cb)->entry), FALSE);
303 gtk_container_add(GTK_CONTAINER(string_opt_vb), combo_cb);
304 gtk_widget_show(combo_cb);
307 /* direction frame */
308 direction_frame = gtk_frame_new("Direction");
309 gtk_box_pack_start(GTK_BOX(main_options_hb), direction_frame, FALSE, FALSE, 0);
310 gtk_widget_show(direction_frame);
312 /* Direction row: Forward and reverse radio buttons */
313 direction_vb = gtk_vbox_new(FALSE, 0);
314 gtk_container_border_width(GTK_CONTAINER(direction_vb), 3);
315 gtk_container_add(GTK_CONTAINER(direction_frame), direction_vb);
316 gtk_widget_show(direction_vb);
318 up_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "_Up", accel_group);
319 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(up_rb), cfile.sbackward);
320 gtk_box_pack_start(GTK_BOX(direction_vb), up_rb, FALSE, FALSE, 0);
321 gtk_widget_show(up_rb);
323 down_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(up_rb, "_Down", accel_group);
324 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(down_rb), !cfile.sbackward);
325 gtk_box_pack_start(GTK_BOX(direction_vb), down_rb, FALSE, FALSE, 0);
326 gtk_widget_show(down_rb);
330 bbox = dlg_button_row_new(GTK_STOCK_FIND, GTK_STOCK_CANCEL, NULL);
331 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
332 gtk_widget_show(bbox);
334 ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_FIND);
335 SIGNAL_CONNECT(ok_bt, "clicked", find_frame_ok_cb, find_frame_w);
337 cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
338 SIGNAL_CONNECT(cancel_bt, "clicked", find_frame_close_cb, find_frame_w);
340 /* Attach pointers to needed widgets to the capture prefs window/object */
341 OBJECT_SET_DATA(find_frame_w, E_FIND_FILT_KEY, filter_text_box);
342 OBJECT_SET_DATA(find_frame_w, E_FIND_BACKWARD_KEY, up_rb);
343 OBJECT_SET_DATA(find_frame_w, E_FIND_FILTERDATA_KEY, filter_rb);
344 OBJECT_SET_DATA(find_frame_w, E_FIND_HEXDATA_KEY, hex_rb);
345 OBJECT_SET_DATA(find_frame_w, E_FIND_STRINGDATA_KEY, string_rb);
346 OBJECT_SET_DATA(find_frame_w, E_FIND_STRINGTYPE_LABEL_KEY, combo_lb);
347 OBJECT_SET_DATA(find_frame_w, E_FIND_STRINGTYPE_KEY, combo_cb);
348 OBJECT_SET_DATA(find_frame_w, E_CASE_SEARCH_KEY, case_cb);
349 OBJECT_SET_DATA(find_frame_w, E_SOURCE_HEX_KEY, hex_data_rb);
350 OBJECT_SET_DATA(find_frame_w, E_SOURCE_DECODE_KEY, decode_data_rb);
351 OBJECT_SET_DATA(find_frame_w, E_SOURCE_SUMMARY_KEY, summary_data_rb);
352 OBJECT_SET_DATA(find_frame_w, E_FILT_TE_BUTTON_KEY, filter_bt);
355 * Now that we've attached the pointers, connect the signals - if
356 * we do so before we've attached the pointers, the signals may
357 * be delivered before the pointers are attached; the signal
358 * handlers expect the pointers to be attached, and won't be happy.
360 SIGNAL_CONNECT(hex_rb, "clicked", hex_selected_cb, find_frame_w);
361 SIGNAL_CONNECT(string_rb, "clicked", string_selected_cb, find_frame_w);
362 SIGNAL_CONNECT(filter_rb, "clicked", filter_selected_cb, find_frame_w);
364 string_selected_cb(NULL, find_frame_w);
365 filter_selected_cb(NULL, find_frame_w);
367 window_set_cancel_button(find_frame_w, cancel_bt, window_cancel_button_cb);
369 gtk_widget_grab_default(ok_bt);
371 /* Catch the "activate" signal on the filter text entry, so that
372 if the user types Return there, we act as if the "OK" button
373 had been selected, as happens if Return is typed if some widget
374 that *doesn't* handle the Return key has the input focus. */
375 dlg_set_activate(filter_text_box, ok_bt);
377 /* Give the initial focus to the "Filter" entry box. */
378 gtk_widget_grab_focus(filter_text_box);
380 SIGNAL_CONNECT(find_frame_w, "delete_event", window_delete_event_cb, NULL);
381 SIGNAL_CONNECT(find_frame_w, "destroy", find_frame_destroy_cb, NULL);
383 gtk_widget_show(find_frame_w);
384 window_present(find_frame_w);
387 /* this function opens the find frame dialogue and sets the filter string */
389 find_frame_with_filter(char *filter)
391 find_frame_cb(NULL, NULL);
392 gtk_entry_set_text(GTK_ENTRY(filter_text_box), filter);
396 * Check the filter syntax based on the type of search we're doing.
399 find_filter_te_syntax_check_cb(GtkWidget *w, gpointer parent_w)
402 GtkWidget *hex_rb, *string_rb;
403 guint8 *bytes = NULL;
406 hex_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_HEXDATA_KEY);
407 string_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_STRINGDATA_KEY);
409 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb))) {
411 * Hex search - scan the search string to make sure it's valid hex.
413 strval = gtk_entry_get_text(GTK_ENTRY(w));
414 if (strval == NULL) {
415 /* XXX - can this happen? */
416 colorize_filter_te_as_invalid(w);
418 bytes = convert_string_to_hex(strval, &nbytes);
420 colorize_filter_te_as_invalid(w);
423 colorize_filter_te_as_valid(w);
426 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb))) {
428 * String search. Make sure the string isn't empty.
430 strval = gtk_entry_get_text(GTK_ENTRY(w));
431 if (strval == NULL) {
432 /* XXX - can this happen? */
433 colorize_filter_te_as_invalid(w);
435 if (strcmp(strval, "") == 0)
436 colorize_filter_te_as_invalid(w);
438 colorize_filter_te_as_valid(w);
442 * Display filter search; check it with "filter_te_syntax_check_cb()".
444 filter_te_syntax_check_cb(w);
449 * This function will re-check the search text syntax.
452 hex_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
454 GtkWidget *filter_text_box;
456 filter_text_box = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_FILT_TE_PTR_KEY);
458 /* Re-check the display filter. */
459 find_filter_te_syntax_check_cb(filter_text_box, parent_w);
464 * This function will disable the string options until
465 * the string search is selected.
468 string_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
470 GtkWidget *string_rb, *hex_data_rb, *decode_data_rb, *summary_data_rb,
471 *data_combo_lb, *data_combo_cb, *data_case_cb, *filter_text_box;
473 string_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_STRINGDATA_KEY);
474 hex_data_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_SOURCE_HEX_KEY);
475 decode_data_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_SOURCE_DECODE_KEY);
476 summary_data_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_SOURCE_SUMMARY_KEY);
478 data_combo_lb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_STRINGTYPE_LABEL_KEY);
479 data_combo_cb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_STRINGTYPE_KEY);
480 data_case_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CASE_SEARCH_KEY);
481 filter_text_box = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_FILT_TE_PTR_KEY);
483 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(string_rb))) {
484 gtk_widget_set_sensitive(GTK_WIDGET(hex_data_rb), TRUE);
485 gtk_widget_set_sensitive(GTK_WIDGET(decode_data_rb), TRUE);
486 gtk_widget_set_sensitive(GTK_WIDGET(summary_data_rb), TRUE);
487 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_lb), TRUE);
488 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_cb), TRUE);
489 gtk_widget_set_sensitive(GTK_WIDGET(data_case_cb), TRUE);
491 gtk_widget_set_sensitive(GTK_WIDGET(hex_data_rb), FALSE);
492 gtk_widget_set_sensitive(GTK_WIDGET(decode_data_rb), FALSE);
493 gtk_widget_set_sensitive(GTK_WIDGET(summary_data_rb), FALSE);
494 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_lb), FALSE);
495 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_cb), FALSE);
496 gtk_widget_set_sensitive(GTK_WIDGET(data_case_cb), FALSE);
498 /* Re-check the display filter. */
499 find_filter_te_syntax_check_cb(filter_text_box, parent_w);
504 * This function will disable the filter button until
505 * the filter search is selected.
508 filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
510 GtkWidget *filter_bt, *filter_rb;
512 filter_bt = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FILT_TE_BUTTON_KEY);
513 filter_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_FILTERDATA_KEY);
515 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filter_rb)))
517 gtk_widget_set_sensitive(GTK_WIDGET(filter_bt), TRUE);
521 gtk_widget_set_sensitive(GTK_WIDGET(filter_bt), FALSE);
527 convert_string_to_hex(const char *string, size_t *nbytes)
532 guint8 *bytes, *q, byte_val;
541 continue; /* allow white space */
542 if (c==':' || c=='.' || c=='-')
543 continue; /* skip any ':', '.', or '-' between bytes */
545 /* Not a valid hex digit - fail */
550 * We can only match bytes, not nibbles; we must have a valid
551 * hex digit immediately after that hex digit.
557 /* 2 hex digits = 1 byte */
562 * Were we given any hex digits?
570 * OK, it's valid, and it generates "n_bytes" bytes; generate the
573 bytes = g_malloc(n_bytes);
581 continue; /* allow white space */
582 if (c==':' || c=='.' || c=='-')
583 continue; /* skip any ':', '.', or '-' between bytes */
584 /* From the loop above, we know this is a hex digit */
588 byte_val = (c - 'a') + 10;
590 byte_val = (c - 'A') + 10;
593 /* We also know this is a hex digit */
598 byte_val |= (c - 'a') + 10;
600 byte_val |= (c - 'A') + 10;
609 convert_string_case(const char *string, gboolean case_insensitive)
617 * Copy if if it's a case-sensitive search; uppercase it if it's
618 * a case-insensitive search.
620 if (case_insensitive) {
621 out_string = g_malloc(strlen(string) + 1);
622 for (p = &string[0], q = &out_string[0]; (c = *p) != '\0'; p++, q++)
623 *q = toupper((unsigned char)*p);
626 out_string = g_strdup(string);
631 find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
633 GtkWidget *filter_te, *up_rb, *hex_rb, *string_rb, *combo_cb,
634 *case_cb, *decode_data_rb, *summary_data_rb;
635 const gchar *filter_text, *string_type;
636 search_charset_t scs_type = SCS_ASCII_AND_UNICODE;
637 guint8 *bytes = NULL;
641 gboolean found_packet;
643 filter_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_FILT_KEY);
644 up_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_BACKWARD_KEY);
645 hex_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_HEXDATA_KEY);
646 string_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_STRINGDATA_KEY);
647 combo_cb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_FIND_STRINGTYPE_KEY);
648 case_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CASE_SEARCH_KEY);
649 decode_data_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_SOURCE_DECODE_KEY);
650 summary_data_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_SOURCE_SUMMARY_KEY);
652 filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
653 string_type = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo_cb)->entry));
655 case_type = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(case_cb));
656 decode_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(decode_data_rb));
657 summary_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(summary_data_rb));
660 * Process the search criterion.
662 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb))) {
664 * Hex search - scan the search string to make sure it's valid hex
665 * and to find out how many bytes there are.
667 bytes = convert_string_to_hex(filter_text, &nbytes);
669 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
670 "You didn't specify a valid hex string.");
673 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb))) {
676 * Make sure we're searching for something, first.
678 if (strcmp(filter_text, "") == 0) {
679 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
680 "You didn't specify any text for which to search.");
685 * We are - get the character set type.
687 if (strcmp(string_type, "ASCII Unicode & Non-Unicode") == 0)
688 scs_type = SCS_ASCII_AND_UNICODE;
689 else if (strcmp(string_type, "ASCII Non-Unicode") == 0)
690 scs_type = SCS_ASCII;
691 else if (strcmp(string_type, "ASCII Unicode") == 0)
692 scs_type = SCS_UNICODE;
694 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "You didn't choose a valid character set.");
697 string = convert_string_case(filter_text, case_type);
700 * Display filter search - try to compile the filter.
702 if (!dfilter_compile(filter_text, &sfcode)) {
703 /* The attempt failed; report an error. */
704 bad_dfilter_alert_box(filter_text);
709 if (sfcode == NULL) {
710 /* Yes - complain. */
711 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
712 "You specified a filter that doesn't test anything.");
718 * Remember the search parameters.
721 g_free(cfile.sfilter);
722 cfile.sfilter = g_strdup(filter_text);
723 cfile.sbackward = GTK_TOGGLE_BUTTON (up_rb)->active;
724 cfile.hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb));
725 cfile.string = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb));
726 cfile.scs_type = scs_type;
727 cfile.case_type = case_type;
728 cfile.decode_data = decode_data;
729 cfile.summary_data = summary_data;
732 found_packet = find_packet_data(&cfile, bytes, nbytes);
735 /* We didn't find a packet */
736 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
737 "%sFound no match!%s\n\n"
738 "No packet contained those bytes.",
739 simple_dialog_primary_start(), simple_dialog_primary_end());
743 } else if (cfile.string) {
744 /* OK, what are we searching? */
745 if (cfile.decode_data) {
746 /* The text in the protocol tree */
747 found_packet = find_packet_protocol_tree(&cfile, string);
750 /* We didn't find the packet. */
751 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
752 "%sFound no match!%s\n\n"
753 "No packet contained that string in its dissected display.",
754 simple_dialog_primary_start(), simple_dialog_primary_end());
757 } else if (cfile.summary_data) {
758 /* The text in the summary line */
759 found_packet = find_packet_summary_line(&cfile, string);
762 /* We didn't find the packet. */
763 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
764 "%sFound no match!%s\n\n"
765 "No packet contained that string in its Info column.",
766 simple_dialog_primary_start(), simple_dialog_primary_end());
770 /* The raw packet data */
771 found_packet = find_packet_data(&cfile, string, strlen(string));
774 /* We didn't find the packet. */
775 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
776 "%sFound no match!%s\n\n"
777 "No packet contained that string in its data.",
778 simple_dialog_primary_start(), simple_dialog_primary_end());
783 found_packet = find_packet_dfilter(&cfile, sfcode);
784 dfilter_free(sfcode);
786 /* We didn't find a packet */
787 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
788 "%sFound no match!%s\n\n"
789 "No packet matched that filter.",
790 simple_dialog_primary_start(), simple_dialog_primary_end());
795 window_destroy(GTK_WIDGET(parent_w));
799 find_frame_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
801 gtk_grab_remove(GTK_WIDGET(parent_w));
802 window_destroy(GTK_WIDGET(parent_w));
806 find_frame_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
808 /* Note that we no longer have a "Find Packet" dialog box. */
813 find_previous_next(GtkWidget *w, gpointer d, gboolean sens)
821 cfile.sbackward = sens;
823 bytes = convert_string_to_hex(cfile.sfilter, &nbytes);
826 * XXX - this shouldn't happen, as we've already successfully
827 * translated the string once.
831 find_packet_data(&cfile, bytes, nbytes);
833 } else if (cfile.string) {
834 string = convert_string_case(cfile.sfilter, cfile.case_type);
835 /* OK, what are we searching? */
836 if (cfile.decode_data) {
837 /* The text in the protocol tree */
838 find_packet_protocol_tree(&cfile, string);
839 } else if (cfile.summary_data) {
840 /* The text in the summary line */
841 find_packet_summary_line(&cfile, string);
843 /* The raw packet data */
844 find_packet_data(&cfile, string, strlen(string));
848 if (!dfilter_compile(cfile.sfilter, &sfcode)) {
850 * XXX - this shouldn't happen, as we've already successfully
851 * translated the string once.
855 if (sfcode == NULL) {
857 * XXX - this shouldn't happen, as we've already found that the
858 * string wasn't null.
862 find_packet_dfilter(&cfile, sfcode);
863 dfilter_free(sfcode);
870 find_next_cb(GtkWidget *w , gpointer d)
872 find_previous_next(w, d, FALSE);
876 find_previous_cb(GtkWidget *w , gpointer d)
878 find_previous_next(w, d, TRUE);
881 /* this function jumps to the next packet matching the filter */
883 find_previous_next_frame_with_filter(char *filter, gboolean backwards)
886 gboolean sbackwards_saved;
888 /* temporarily set the direction we want to search */
889 sbackwards_saved=cfile.sbackward;
890 cfile.sbackward = backwards;
892 if (!dfilter_compile(filter, &sfcode)) {
894 * XXX - this shouldn't happen, as the filter string is machine
899 if (sfcode == NULL) {
901 * XXX - this shouldn't happen, as the filter string is machine
906 find_packet_dfilter(&cfile, sfcode);
907 dfilter_free(sfcode);
908 cfile.sbackward=sbackwards_saved;