1 /* main_filter_toolbar.c
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
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.
26 * This file implements the "filter" toolbar for Wireshark.
37 #include "gtk/old-gtk-compat.h"
39 #include "filter_dlg.h"
40 #include "filter_autocomplete.h"
42 #include "epan/prefs.h"
45 #include "gtkglobals.h"
46 #include "stock_icons.h"
51 #include "main_toolbar.h"
52 #include "main_filter_toolbar.h"
54 #ifdef MAIN_MENU_USE_UIMANAGER
55 # define MENU_BAR_PATH_FILE_OPEN "/Menubar/FileMenu/Open"
56 # define MENU_BAR_PATH_EDIT_COPY_AS_FLT "/Menubar/EditMenu/Copy/AsFilter"
57 # define MENU_BAR_PATH_ANALYZE_DISPLAY_FLT "/Menubar/AnalyzeMenu/DisplayFilters"
58 # define MENU_BAR_PATH_ANALYZE_FOLLOW_TCP_STREAM "/Menubar/AnalyzeMenu/FollowTCPStream"
59 # define MENU_BAR_PATH_ANALYZE_FOLLOW_UDP_STREAM "/Menubar/AnalyzeMenu/FollowUDPStream"
60 # define MENU_BAR_PATH_ANALYZE_FOLLOW_SSL_STREAM "/Menubar/AnalyzeMenu/FollowSSLStream"
61 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/Selected"
62 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_NOT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/NotSelected"
63 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/AndSelected"
64 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/OrSelected"
65 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_NOT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/AndNotSelected"
66 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_NOT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/OrNotSelected"
68 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/Selected"
69 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_NOT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/NotSelected"
70 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/AndSelected"
71 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/OrSelected"
72 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_NOT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/AndNotSelected"
73 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_NOT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/OrNotSelected"
75 # define MENU_BAR_PATH_FILE_OPEN "/File/Open..."
76 # define MENU_BAR_PATH_EDIT_COPY_AS_FLT "/Edit/Copy/As Filter"
77 # define MENU_BAR_PATH_ANALYZE_DISPLAY_FLT "/Analyze/Display Filters..."
78 # define MENU_BAR_PATH_ANALYZE_FOLLOW_TCP_STREAM "/Analyze/Follow TCP Stream"
79 # define MENU_BAR_PATH_ANALYZE_FOLLOW_UDP_STREAM "/Analyze/Follow UDP Stream"
80 # define MENU_BAR_PATH_ANALYZE_FOLLOW_SSL_STREAM "/Analyze/Follow SSL Stream"
81 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_SEL "/Analyze/Apply as Filter/Selected"
82 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_NOT_SEL "/Analyze/Apply as Filter/Not Selected"
83 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_SEL "/Analyze/Apply as Filter/... and Selected"
84 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_SEL "/Analyze/Apply as Filter/... or Selected"
85 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_NOT_SEL "/Analyze/Apply as Filter/... and not Selected"
86 # define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_NOT_SEL "/Analyze/Apply as Filter/... or not Selected"
88 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_SEL "/Analyze/Prepare a Filter/Selected"
89 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_NOT_SEL "/Analyze/Prepare a Filter/Not Selected"
90 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_SEL "/Analyze/Prepare a Filter/... and Selected"
91 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_SEL "/Analyze/Prepare a Filter/... or Selected"
92 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_NOT_SEL "/Analyze/Prepare a Filter/... and not Selected"
93 # define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_NOT_SEL "/Analyze/Prepare a Filter/... or not Selected"
94 # endif /* MAIN_MENU_USE_UIMANAGER */
97 # define PACKET_LIST_POPUP_PATH_ANALYZE_FOLLOW_TCP_STREAM "/PacketListMenuPopup/FollowTCPStream"
98 # define PACKET_LIST_POPUP_PATH_ANALYZE_FOLLOW_UDP_STREAM "/PacketListMenuPopup/FollowUDPStream"
99 # define PACKET_LIST_POPUP_PATH_ANALYZE_FOLLOW_SSL_STREAM "/PacketListMenuPopup/FollowSSLStream"
100 # define PACKET_LIST_POPUP_PATH_CONV_FLT_ETH "/PacketListMenuPopup/ConversationFilter/Ethernet"
101 # define PACKET_LIST_POPUP_PATH_CONV_FLT_IP "/PacketListMenuPopup/ConversationFilter/IP"
102 # define PACKET_LIST_POPUP_PATH_CONV_FLT_TCP "/PacketListMenuPopup/ConversationFilter/TCP"
103 # define PACKET_LIST_POPUP_PATH_CONV_FLT_UDP "/PacketListMenuPopup/ConversationFilter/UDP"
104 # define PACKET_LIST_POPUP_PATH_CONV_FLT_PN_CBA_SERV "/PacketListMenuPopup/ConversationFilter/PN-CBA"
107 GtkWidget *main_display_filter_widget=NULL;
109 /* Run the current display filter on the current packet set, and
112 filter_activate_cb(GtkWidget *w _U_, gpointer data)
116 s = gtk_entry_get_text(GTK_ENTRY(data));
117 main_filter_packets(&cfile, s, FALSE);
120 /* Enable both Clear and Apply button when filter is changed */
122 filter_changed_cb(GtkWidget *w _U_, gpointer data)
124 gtk_widget_set_sensitive (g_object_get_data (G_OBJECT(data), E_DFILTER_APPLY_KEY), TRUE);
125 gtk_widget_set_sensitive (g_object_get_data (G_OBJECT(data), E_DFILTER_CLEAR_KEY), TRUE);
128 /* redisplay with no display filter */
130 filter_reset_cb(GtkWidget *w, gpointer data _U_)
132 GtkWidget *filter_te = NULL;
134 if ((filter_te = g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY))) {
135 gtk_entry_set_text(GTK_ENTRY(filter_te), "");
137 main_filter_packets(&cfile, NULL, FALSE);
140 GtkWidget *filter_toolbar_new(void)
142 GtkWidget *filter_cm;
143 GtkWidget *filter_te;
144 GtkWidget *filter_tb;
145 GtkToolItem *filter_bt, *filter_add_expr_bt, *filter_reset;
146 GtkToolItem *filter_apply, *item;
149 /* Display filter construct dialog has an Apply button, and "OK" not
150 only sets our text widget, it activates it (i.e., it causes us to
151 filter the capture). */
152 static construct_args_t args = {
153 "Wireshark: Display Filter",
160 filter_tb = gtk_toolbar_new();
161 gtk_orientable_set_orientation(GTK_ORIENTABLE(filter_tb),
162 GTK_ORIENTATION_HORIZONTAL);
164 g_object_set_data(G_OBJECT(top_level), E_TB_FILTER_KEY, filter_tb);
165 gtk_widget_show(filter_tb);
167 /* Create the "Filter:" button */
168 filter_bt = gtk_tool_button_new_from_stock (WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
169 g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &args);
170 gtk_widget_show(GTK_WIDGET (filter_bt));
171 g_object_set_data(G_OBJECT(top_level), E_FILT_BT_PTR_KEY, filter_bt);
173 gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
176 gtk_widget_set_tooltip_text( GTK_WIDGET(filter_bt), "Open the \"Display Filter\" dialog, to edit/apply filters");
178 /* Create the filter combobox */
179 filter_cm = gtk_combo_box_text_new_with_entry ();
180 filter_te = gtk_bin_get_child(GTK_BIN(filter_cm));
181 main_display_filter_widget=filter_te;
182 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
183 g_object_set_data(G_OBJECT(filter_te), E_DFILTER_CM_KEY, filter_cm);
184 g_object_set_data(G_OBJECT(top_level), E_DFILTER_CM_KEY, filter_cm);
185 g_signal_connect(filter_te, "activate", G_CALLBACK(filter_activate_cb), filter_te);
186 g_signal_connect(filter_te, "changed", G_CALLBACK(filter_changed_cb), filter_cm);
187 g_signal_connect(filter_te, "changed", G_CALLBACK(filter_te_syntax_check_cb), NULL);
188 g_object_set_data(G_OBJECT(filter_tb), E_FILT_AUTOCOMP_PTR_KEY, NULL);
189 g_object_set_data(G_OBJECT(filter_te), E_FILT_FIELD_USE_STATUSBAR_KEY, "");
190 g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
191 g_signal_connect(filter_tb, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
193 gtk_widget_set_size_request(filter_cm, 400, -1);
194 gtk_widget_show(filter_cm);
195 item = gtk_tool_item_new ();
196 gtk_container_add (GTK_CONTAINER (item), filter_cm);
197 gtk_widget_show (GTK_WIDGET (item));
199 gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
203 /* setting a tooltip for a combobox will do nothing, so add it to the corresponding text entry */
204 gtk_widget_set_tooltip_text(filter_cm,
205 "Enter a display filter, or choose one of your recently used filters. "
206 "The background color of this field is changed by a continuous syntax check "
207 "(green is valid, red is invalid, yellow may have unexpected results).");
209 /* Create the "Add Expression..." button, to pop up a dialog
210 for constructing filter comparison expressions. */
211 filter_add_expr_bt = gtk_tool_button_new_from_stock(WIRESHARK_STOCK_ADD_EXPRESSION);
212 g_object_set_data(G_OBJECT(filter_tb), E_FILT_FILTER_TE_KEY, filter_te);
213 g_signal_connect(filter_add_expr_bt, "clicked", G_CALLBACK(filter_add_expr_bt_cb), filter_tb);
214 gtk_widget_show(GTK_WIDGET(filter_add_expr_bt));
216 gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
220 gtk_widget_set_tooltip_text(GTK_WIDGET(filter_add_expr_bt), "Add an expression to this filter string");
222 /* Create the "Clear" button */
223 filter_reset = gtk_tool_button_new_from_stock(WIRESHARK_STOCK_CLEAR_EXPRESSION);
224 g_object_set_data(G_OBJECT(filter_reset), E_DFILTER_TE_KEY, filter_te);
225 g_object_set_data (G_OBJECT(filter_cm), E_DFILTER_CLEAR_KEY, filter_reset);
226 g_signal_connect(filter_reset, "clicked", G_CALLBACK(filter_reset_cb), NULL);
227 gtk_widget_set_sensitive (GTK_WIDGET(filter_reset), FALSE);
228 gtk_widget_show(GTK_WIDGET(filter_reset));
229 gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
233 gtk_widget_set_tooltip_text(GTK_WIDGET(filter_reset), "Clear this filter string and update the display");
235 /* Create the "Apply" button */
236 filter_apply = gtk_tool_button_new_from_stock(WIRESHARK_STOCK_APPLY_EXPRESSION);
237 g_object_set_data(G_OBJECT(filter_apply), E_DFILTER_CM_KEY, filter_cm);
238 g_object_set_data (G_OBJECT(filter_cm), E_DFILTER_APPLY_KEY, filter_apply);
239 g_signal_connect(filter_apply, "clicked", G_CALLBACK(filter_activate_cb), filter_te);
240 gtk_widget_set_sensitive (GTK_WIDGET(filter_apply), FALSE);
241 gtk_widget_show(GTK_WIDGET(filter_apply));
243 gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
247 gtk_widget_set_tooltip_text(GTK_WIDGET(filter_apply), "Apply this filter string to the display");
249 /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
250 * of any widget that ends up calling a callback which needs
251 * that text entry pointer */
252 set_menu_object_data(MENU_BAR_PATH_FILE_OPEN, E_DFILTER_TE_KEY, filter_te);
253 set_menu_object_data(MENU_BAR_PATH_EDIT_COPY_AS_FLT, E_DFILTER_TE_KEY,
255 set_menu_object_data(MENU_BAR_PATH_ANALYZE_DISPLAY_FLT, E_FILT_TE_PTR_KEY,
257 set_menu_object_data(MENU_BAR_PATH_ANALYZE_FOLLOW_TCP_STREAM, E_DFILTER_TE_KEY,
259 set_menu_object_data(MENU_BAR_PATH_ANALYZE_FOLLOW_UDP_STREAM, E_DFILTER_TE_KEY,
261 set_menu_object_data(MENU_BAR_PATH_ANALYZE_FOLLOW_SSL_STREAM, E_DFILTER_TE_KEY,
263 set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_SEL, E_DFILTER_TE_KEY,
265 set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_NOT_SEL, E_DFILTER_TE_KEY,
267 set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_SEL, E_DFILTER_TE_KEY,
269 set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_SEL, E_DFILTER_TE_KEY,
271 set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_NOT_SEL, E_DFILTER_TE_KEY,
273 set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_NOT_SEL, E_DFILTER_TE_KEY,
275 set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_SEL, E_DFILTER_TE_KEY,
277 set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_NOT_SEL, E_DFILTER_TE_KEY,
279 set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_SEL, E_DFILTER_TE_KEY,
281 set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_SEL, E_DFILTER_TE_KEY,
283 set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_NOT_SEL, E_DFILTER_TE_KEY,
285 set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_NOT_SEL, E_DFILTER_TE_KEY,
288 set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
289 g_object_set_data(G_OBJECT(popup_menu_object), E_DFILTER_TE_KEY, filter_te);
291 /* make current preferences effective */
292 toolbar_redraw_all();
298 dfilter_entry_match(GtkWidget *filter_cm, char *s, int *index)
300 GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(filter_cm));
302 GValue value = { 0, {{0}}};
303 const char *filter_str;
307 if (!gtk_tree_model_get_iter_first (model, &iter)){
313 gtk_tree_model_get_value (model, &iter, 0, &value);
314 filter_str = g_value_get_string (&value);
316 if(strcmp(s, filter_str) == 0){
317 g_value_unset (&value);
322 g_value_unset (&value);
323 }while (gtk_tree_model_iter_next (model, &iter));
329 /* add a display filter to the combo box */
330 /* Note: a new filter string will not replace an old identical one */
332 dfilter_combo_add(GtkWidget *filter_cm, char *s) {
335 if(!dfilter_entry_match(filter_cm,s, &index))
336 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(filter_cm), s);
343 /* write all non empty display filters (until maximum count)
344 * of the combo box GList to the user's recent file */
346 dfilter_recent_combo_write_all(FILE *rf) {
347 GtkWidget *filter_cm = g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
348 GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(filter_cm));
350 GValue value = { 0, {{0}}};
351 const char *filter_str;
354 if (!gtk_tree_model_get_iter_first (model, &iter))
357 gtk_tree_model_get_value (model, &iter, 0, &value);
358 filter_str = g_value_get_string (&value);
360 fprintf (rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", filter_str);
361 g_value_unset (&value);
363 }while (gtk_tree_model_iter_next (model, &iter)&& (max_count++ < prefs.gui_recent_df_entries_max));
367 /* add a display filter coming from the user's recent file to the dfilter combo box */
369 dfilter_combo_add_recent(gchar *s) {
370 GtkWidget *filter_cm = g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
375 return dfilter_combo_add(filter_cm, dup);
378 /* call cf_filter_packets() and add this filter string to the recent filter list */
380 main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
382 GtkWidget *filter_cm = g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
383 gboolean free_filter = TRUE;
385 cf_status_t cf_status;
387 s = g_strdup(dftext);
389 cf_status = cf_filter_packets(cf, s, force);
391 if (cf_status == CF_OK) {
392 gtk_widget_set_sensitive (g_object_get_data (G_OBJECT(filter_cm), E_DFILTER_APPLY_KEY), FALSE);
393 if (!s || strlen (s) == 0) {
394 gtk_widget_set_sensitive (g_object_get_data (G_OBJECT(filter_cm), E_DFILTER_CLEAR_KEY), FALSE);
399 return (cf_status == CF_OK);
401 /* GtkCombos don't let us get at their list contents easily, so we maintain
402 our own filter list, and feed it to gtk_combo_set_popdown_strings when
403 a new filter is added. */
404 if (cf_status == CF_OK && strlen(s) > 0) {
407 if(!dfilter_entry_match(filter_cm,s, &index)){
408 gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), s);
411 while ((guint)index >= prefs.gui_recent_df_entries_max){
412 gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(filter_cm), index);
419 return (cf_status == CF_OK);