PageRenderTime 59ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/ui/gtk/main_filter_toolbar.c

https://github.com/labx-technologies-llc/wireshark
C | 434 lines | 295 code | 72 blank | 67 comment | 26 complexity | 98458cf64d1378b07b81aedc8580c1b5 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* main_filter_toolbar.c
  2. * The filter toolbar
  3. *
  4. * $Id$
  5. *
  6. * Wireshark - Network traffic analyzer
  7. * By Gerald Combs <gerald@wireshark.org>
  8. * Copyright 1998 Gerald Combs
  9. *
  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.
  14. *
  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.
  19. *
  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  23. */
  24. /*
  25. * This file implements the "filter" toolbar for Wireshark.
  26. */
  27. #include "config.h"
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <gtk/gtk.h>
  31. #include "ui/recent.h"
  32. #include "ui/recent_utils.h"
  33. #include "ui/gtk/old-gtk-compat.h"
  34. #include "filter_dlg.h"
  35. #include "filter_autocomplete.h"
  36. #include "epan/prefs.h"
  37. #include "keys.h"
  38. #include "gtkglobals.h"
  39. #include "stock_icons.h"
  40. #include "main.h"
  41. #include "menus.h"
  42. #include "main_toolbar.h"
  43. #include "main_filter_toolbar.h"
  44. #include "filter_expression_save_dlg.h"
  45. #define MENU_BAR_PATH_FILE_OPEN "/Menubar/FileMenu/Open"
  46. #define MENU_BAR_PATH_EDIT_COPY_AS_FLT "/Menubar/EditMenu/Copy/AsFilter"
  47. #define MENU_BAR_PATH_ANALYZE_DISPLAY_FLT "/Menubar/AnalyzeMenu/DisplayFilters"
  48. #define MENU_BAR_PATH_ANALYZE_FOLLOW_TCP_STREAM "/Menubar/AnalyzeMenu/FollowTCPStream"
  49. #define MENU_BAR_PATH_ANALYZE_FOLLOW_UDP_STREAM "/Menubar/AnalyzeMenu/FollowUDPStream"
  50. #define MENU_BAR_PATH_ANALYZE_FOLLOW_SSL_STREAM "/Menubar/AnalyzeMenu/FollowSSLStream"
  51. #define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/Selected"
  52. #define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_NOT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/NotSelected"
  53. #define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/AndSelected"
  54. #define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/OrSelected"
  55. #define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_NOT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/AndNotSelected"
  56. #define MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_NOT_SEL "/Menubar/AnalyzeMenu/ApplyAsFilter/OrNotSelected"
  57. #define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/Selected"
  58. #define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_NOT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/NotSelected"
  59. #define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/AndSelected"
  60. #define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/OrSelected"
  61. #define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_NOT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/AndNotSelected"
  62. #define MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_NOT_SEL "/Menubar/AnalyzeMenu/PrepareaFilter/OrNotSelected"
  63. GtkWidget *main_display_filter_widget=NULL;
  64. /* Run the current display filter on the current packet set, and
  65. redisplay. */
  66. static void
  67. filter_activate_cb(GtkWidget *w _U_, gpointer data)
  68. {
  69. const char *s;
  70. s = gtk_entry_get_text(GTK_ENTRY(data));
  71. main_filter_packets(&cfile, s, FALSE);
  72. }
  73. /* Enable both Clear and Apply button when filter is changed */
  74. static void
  75. filter_changed_cb(GtkWidget *w _U_, gpointer data)
  76. {
  77. gtk_widget_set_sensitive ((GtkWidget *)g_object_get_data (G_OBJECT(data), E_DFILTER_APPLY_KEY), TRUE);
  78. gtk_widget_set_sensitive ((GtkWidget *)g_object_get_data (G_OBJECT(data), E_DFILTER_CLEAR_KEY), TRUE);
  79. gtk_widget_set_sensitive ((GtkWidget *)g_object_get_data (G_OBJECT(data), E_DFILTER_SAVE_KEY), TRUE);
  80. }
  81. /* redisplay with no display filter */
  82. static void
  83. filter_reset_cb(GtkWidget *w, gpointer data _U_)
  84. {
  85. GtkWidget *filter_te = NULL;
  86. if ((filter_te = (GtkWidget *)g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY))) {
  87. gtk_entry_set_text(GTK_ENTRY(filter_te), "");
  88. }
  89. main_filter_packets(&cfile, NULL, FALSE);
  90. }
  91. static void
  92. filter_save_cb(GtkWidget *w _U_, GtkWindow *parent_w)
  93. {
  94. filter_expression_save_dlg(parent_w);
  95. }
  96. GtkWidget *
  97. filter_toolbar_new(void)
  98. {
  99. GtkWidget *filter_cm;
  100. GtkWidget *filter_te;
  101. GtkWidget *filter_tb;
  102. GtkToolItem *filter_bt, *filter_add_expr_bt, *filter_reset;
  103. GtkToolItem *filter_apply, *filter_save, *item;
  104. /* Display filter construct dialog has an Apply button, and "OK" not
  105. only sets our text widget, it activates it (i.e., it causes us to
  106. filter the capture). */
  107. static construct_args_t args = {
  108. "Wireshark: Display Filter",
  109. TRUE,
  110. TRUE,
  111. FALSE
  112. };
  113. /* filter toolbar */
  114. filter_tb = gtk_toolbar_new();
  115. gtk_orientable_set_orientation(GTK_ORIENTABLE(filter_tb),
  116. GTK_ORIENTATION_HORIZONTAL);
  117. g_object_set_data(G_OBJECT(top_level), E_TB_FILTER_KEY, filter_tb);
  118. gtk_widget_show(filter_tb);
  119. /* Create the "Filter:" button */
  120. filter_bt = gtk_tool_button_new_from_stock (WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
  121. g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &args);
  122. gtk_widget_show(GTK_WIDGET (filter_bt));
  123. g_object_set_data(G_OBJECT(top_level), E_FILT_BT_PTR_KEY, filter_bt);
  124. gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
  125. filter_bt,
  126. -1);
  127. gtk_widget_set_tooltip_text(GTK_WIDGET(filter_bt), "Open the \"Display Filter\" dialog, to edit/apply filters");
  128. /* Create the filter combobox */
  129. filter_cm = gtk_combo_box_text_new_with_entry ();
  130. filter_te = gtk_bin_get_child(GTK_BIN(filter_cm));
  131. main_display_filter_widget=filter_te;
  132. g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
  133. g_object_set_data(G_OBJECT(filter_te), E_DFILTER_CM_KEY, filter_cm);
  134. g_object_set_data(G_OBJECT(top_level), E_DFILTER_CM_KEY, filter_cm);
  135. g_signal_connect(filter_te, "activate", G_CALLBACK(filter_activate_cb), filter_te);
  136. g_signal_connect(filter_te, "changed", G_CALLBACK(filter_changed_cb), filter_cm);
  137. g_signal_connect(filter_te, "changed", G_CALLBACK(filter_te_syntax_check_cb), NULL);
  138. g_object_set_data(G_OBJECT(filter_tb), E_FILT_AUTOCOMP_PTR_KEY, NULL);
  139. g_object_set_data(G_OBJECT(filter_te), E_FILT_FIELD_USE_STATUSBAR_KEY, (gpointer)"");
  140. g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
  141. g_signal_connect(filter_tb, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
  142. gtk_widget_set_size_request(filter_cm, 400, -1);
  143. gtk_widget_show(filter_cm);
  144. item = gtk_tool_item_new ();
  145. gtk_container_add (GTK_CONTAINER (item), filter_cm);
  146. gtk_widget_show (GTK_WIDGET (item));
  147. gtk_toolbar_insert(GTK_TOOLBAR(filter_tb), item, -1);
  148. /* setting a tooltip for a combobox will do nothing, so add it to the corresponding text entry */
  149. gtk_widget_set_tooltip_text(filter_cm,
  150. "Enter a display filter, or choose one of your recently used filters. "
  151. "The background color of this field is changed by a continuous syntax check "
  152. "(green is valid, red is invalid, yellow may have unexpected results).");
  153. /* Create the "Add Expression..." button, to pop up a dialog
  154. for constructing filter comparison expressions. */
  155. filter_add_expr_bt = gtk_tool_button_new_from_stock(WIRESHARK_STOCK_ADD_EXPRESSION);
  156. g_object_set_data(G_OBJECT(filter_tb), E_FILT_FILTER_TE_KEY, filter_te);
  157. g_signal_connect(filter_add_expr_bt, "clicked", G_CALLBACK(filter_add_expr_bt_cb), filter_tb);
  158. gtk_widget_show(GTK_WIDGET(filter_add_expr_bt));
  159. gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
  160. filter_add_expr_bt,
  161. -1);
  162. gtk_widget_set_tooltip_text(GTK_WIDGET(filter_add_expr_bt), "Add an expression to this filter string");
  163. /* Create the "Clear" button */
  164. filter_reset = gtk_tool_button_new_from_stock(WIRESHARK_STOCK_CLEAR_EXPRESSION);
  165. g_object_set_data(G_OBJECT(filter_reset), E_DFILTER_TE_KEY, filter_te);
  166. g_object_set_data (G_OBJECT(filter_cm), E_DFILTER_CLEAR_KEY, filter_reset);
  167. g_signal_connect(filter_reset, "clicked", G_CALLBACK(filter_reset_cb), NULL);
  168. gtk_widget_set_sensitive (GTK_WIDGET(filter_reset), FALSE);
  169. gtk_widget_show(GTK_WIDGET(filter_reset));
  170. gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
  171. filter_reset,
  172. -1);
  173. gtk_widget_set_tooltip_text(GTK_WIDGET(filter_reset), "Clear this filter string and update the display");
  174. /* Create the "Apply" button */
  175. filter_apply = gtk_tool_button_new_from_stock(WIRESHARK_STOCK_APPLY_EXPRESSION);
  176. g_object_set_data(G_OBJECT(filter_apply), E_DFILTER_CM_KEY, filter_cm);
  177. g_object_set_data (G_OBJECT(filter_cm), E_DFILTER_APPLY_KEY, filter_apply);
  178. g_signal_connect(filter_apply, "clicked", G_CALLBACK(filter_activate_cb), filter_te);
  179. gtk_widget_set_sensitive (GTK_WIDGET(filter_apply), FALSE);
  180. gtk_widget_show(GTK_WIDGET(filter_apply));
  181. gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
  182. filter_apply,
  183. -1);
  184. gtk_widget_set_tooltip_text(GTK_WIDGET(filter_apply), "Apply this filter string to the display");
  185. /* Create the "Save" button */
  186. filter_save = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
  187. g_object_set_data(G_OBJECT(filter_save), E_DFILTER_CM_KEY, filter_cm);
  188. g_object_set_data(G_OBJECT(filter_cm), E_DFILTER_SAVE_KEY, filter_save);
  189. g_signal_connect(filter_save, "clicked", G_CALLBACK(filter_save_cb), filter_te);
  190. gtk_widget_set_sensitive (GTK_WIDGET(filter_save), FALSE);
  191. gtk_widget_show(GTK_WIDGET(filter_save));
  192. gtk_toolbar_insert(GTK_TOOLBAR(filter_tb),
  193. filter_save,
  194. -1);
  195. gtk_widget_set_tooltip_text(GTK_WIDGET(filter_save), "Create a button based on the current display filter");
  196. /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
  197. * of any widget that ends up calling a callback which needs
  198. * that text entry pointer */
  199. set_menu_object_data(MENU_BAR_PATH_FILE_OPEN, E_DFILTER_TE_KEY, filter_te);
  200. set_menu_object_data(MENU_BAR_PATH_EDIT_COPY_AS_FLT, E_DFILTER_TE_KEY,
  201. filter_te);
  202. set_menu_object_data(MENU_BAR_PATH_ANALYZE_DISPLAY_FLT, E_FILT_TE_PTR_KEY,
  203. filter_te);
  204. set_menu_object_data(MENU_BAR_PATH_ANALYZE_FOLLOW_TCP_STREAM, E_DFILTER_TE_KEY,
  205. filter_te);
  206. set_menu_object_data(MENU_BAR_PATH_ANALYZE_FOLLOW_UDP_STREAM, E_DFILTER_TE_KEY,
  207. filter_te);
  208. set_menu_object_data(MENU_BAR_PATH_ANALYZE_FOLLOW_SSL_STREAM, E_DFILTER_TE_KEY,
  209. filter_te);
  210. set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_SEL, E_DFILTER_TE_KEY,
  211. filter_te);
  212. set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_NOT_SEL, E_DFILTER_TE_KEY,
  213. filter_te);
  214. set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_SEL, E_DFILTER_TE_KEY,
  215. filter_te);
  216. set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_SEL, E_DFILTER_TE_KEY,
  217. filter_te);
  218. set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_AND_NOT_SEL, E_DFILTER_TE_KEY,
  219. filter_te);
  220. set_menu_object_data(MENU_BAR_PATH_ANALYZE_APL_AS_FLT_OR_NOT_SEL, E_DFILTER_TE_KEY,
  221. filter_te);
  222. set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_SEL, E_DFILTER_TE_KEY,
  223. filter_te);
  224. set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_NOT_SEL, E_DFILTER_TE_KEY,
  225. filter_te);
  226. set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_SEL, E_DFILTER_TE_KEY,
  227. filter_te);
  228. set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_SEL, E_DFILTER_TE_KEY,
  229. filter_te);
  230. set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_AND_NOT_SEL, E_DFILTER_TE_KEY,
  231. filter_te);
  232. set_menu_object_data(MENU_BAR_PATH_ANALYZE_PREP_A_FLT_OR_NOT_SEL, E_DFILTER_TE_KEY,
  233. filter_te);
  234. set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
  235. g_object_set_data(G_OBJECT(popup_menu_object), E_DFILTER_TE_KEY, filter_te);
  236. filter_expression_save_dlg_init(filter_tb, filter_te);
  237. /* make current preferences effective */
  238. toolbar_redraw_all();
  239. return filter_tb;
  240. }
  241. static gboolean
  242. dfilter_entry_match(GtkWidget *filter_cm, char *s, int *indx)
  243. {
  244. GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(filter_cm));
  245. GtkTreeIter iter;
  246. GValue value = { 0, {{0}}};
  247. const char *filter_str;
  248. int i;
  249. i = -1;
  250. if (!gtk_tree_model_get_iter_first (model, &iter)) {
  251. *indx = i;
  252. return FALSE;
  253. }
  254. do {
  255. i++;
  256. gtk_tree_model_get_value (model, &iter, 0, &value);
  257. filter_str = g_value_get_string (&value);
  258. if(filter_str) {
  259. if(strcmp(s, filter_str) == 0) {
  260. g_value_unset (&value);
  261. *indx = i;
  262. return TRUE;
  263. }
  264. }
  265. g_value_unset (&value);
  266. } while (gtk_tree_model_iter_next (model, &iter));
  267. *indx = -1;
  268. return FALSE;
  269. }
  270. /* add a display filter to the combo box */
  271. /* Note: a new filter string will not replace an old identical one */
  272. static gboolean
  273. dfilter_combo_add(GtkWidget *filter_cm, char *s) {
  274. int indx;
  275. if(!dfilter_entry_match(filter_cm,s, &indx))
  276. gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(filter_cm), s);
  277. g_free(s);
  278. return TRUE;
  279. }
  280. /* write all non empty display filters (until maximum count)
  281. * of the combo box GList to the user's recent file */
  282. void
  283. dfilter_recent_combo_write_all(FILE *rf) {
  284. GtkWidget *filter_cm = (GtkWidget *)g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
  285. GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(filter_cm));
  286. GtkTreeIter iter;
  287. GValue value = { 0, {{0}}};
  288. const char *filter_str;
  289. guint max_count = 0;
  290. if (!gtk_tree_model_get_iter_first (model, &iter))
  291. return;
  292. do {
  293. gtk_tree_model_get_value (model, &iter, 0, &value);
  294. filter_str = g_value_get_string (&value);
  295. if(filter_str)
  296. fprintf (rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", filter_str);
  297. g_value_unset (&value);
  298. } while (gtk_tree_model_iter_next (model, &iter)&& (max_count++ < prefs.gui_recent_df_entries_max));
  299. }
  300. /* add a display filter coming from the user's recent file to the dfilter combo box */
  301. gboolean
  302. dfilter_combo_add_recent(const gchar *s) {
  303. GtkWidget *filter_cm = (GtkWidget *)g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
  304. char *dupstr;
  305. dupstr = g_strdup(s);
  306. return dfilter_combo_add(filter_cm, dupstr);
  307. }
  308. /* call cf_filter_packets() and add this filter string to the recent filter list */
  309. gboolean
  310. main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
  311. {
  312. GtkWidget *filter_cm = (GtkWidget *)g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
  313. gboolean free_filter = TRUE;
  314. char *s;
  315. cf_status_t cf_status;
  316. gint filter_count;
  317. s = g_strdup(dftext);
  318. cf_status = cf_filter_packets(cf, s, force);
  319. if (cf_status == CF_OK) {
  320. gtk_widget_set_sensitive ((GtkWidget *)g_object_get_data (G_OBJECT(filter_cm), E_DFILTER_APPLY_KEY), FALSE);
  321. if (!s || strlen (s) == 0) {
  322. gtk_widget_set_sensitive ((GtkWidget *)g_object_get_data (G_OBJECT(filter_cm), E_DFILTER_CLEAR_KEY), FALSE);
  323. gtk_widget_set_sensitive ((GtkWidget *)g_object_get_data (G_OBJECT(filter_cm), E_DFILTER_SAVE_KEY), FALSE);
  324. }
  325. }
  326. if (!s)
  327. return (cf_status == CF_OK);
  328. if (cf_status == CF_OK && strlen(s) > 0) {
  329. int indx;
  330. if(!dfilter_entry_match(filter_cm,s, &indx) || indx > -1) {
  331. /* If the filter is already there but not the first entry, remove it */
  332. if (indx > -1) {
  333. gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(filter_cm), indx);
  334. indx--;
  335. }
  336. /* Add the filter (at the head of the list) */
  337. gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), s);
  338. indx++;
  339. }
  340. }
  341. if (free_filter)
  342. g_free(s);
  343. /* If we have too many entries, remove some */
  344. filter_count = gtk_tree_model_iter_n_children(gtk_combo_box_get_model(GTK_COMBO_BOX(filter_cm)), NULL);
  345. while (filter_count >= (gint)prefs.gui_recent_df_entries_max) {
  346. filter_count--;
  347. gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(filter_cm), filter_count);
  348. }
  349. return (cf_status == CF_OK);
  350. }
  351. /*
  352. * Editor modelines
  353. *
  354. * Local Variables:
  355. * c-basic-offset: 4
  356. * tab-width: 8
  357. * indent-tabs-mode: nil
  358. * End:
  359. *
  360. * ex: set shiftwidth=4 tabstop=8 expandtab:
  361. * :indentSize=4:tabSize=8:noTabs=true:
  362. */