Wireshark-dev: [Wireshark-dev] [Patch] Add "Copy as Filter" menu item

Date Prev · Date Next · Thread Prev · Thread Next
From: Sake Blok <sake@xxxxxxxxxx>
Date: Thu, 1 Mar 2007 00:00:39 +0100
Hi,

OK, third and final version. I did some extensive testing and now the 
patch does exacly what I wanted it to :)  Sorry for the first two try's
and the "noise" it created...

This patch adds the menu-item "Copy as Filter" to the menu-bar, the
context-menu of the packet-list-pane and the context-menu of the
packet-detail-pane. 

The motivation for this extra menu-item is that I often use "Prepare
as Filter", just to be able to copy the filter-expression from the
filter-strip (with the annoying side-effect that the original filter
in the strip gets lost).

I did not replicate the options with and/or/not, since I want to keep 
the copy-action as simple as possible and I personally do not see
a need to combine it with the filter in the filter strip. I used the
same code as the "Apply/Prepare as Filter" menu-items, so adding 
all the "and/or/not" options is not that hard to do later if people
start asking for it.

I also did not add the "Copy to Filter" option to the other 4 places
where "Apply/Prepare as Filter" options are found ("Expert info
Composite", "Endpoint list", "Conversation list" and "Service 
response Time"). If people would find that useful too, or if we
want to keep things simular across menu's, I will spend some
time on implementing it there as well.

Last but not least, I changed the documentation to reflect these
changes in the menu's.

Can someone review my patch and commit it to the trunk?

Cheers,


Sake
Index: doc/wireshark.pod
===================================================================
--- doc/wireshark.pod	(revision 20948)
+++ doc/wireshark.pod	(working copy)
@@ -970,30 +970,34 @@
 Edit the saved list of display filters, allowing filters to be added,
 changed, or deleted.
 
-=item Analyze:Apply as Filter
+=item Analyze:Copy as Filter
 
-Create a display filter, or add to the display filter strip at the
-bottom, a display filter based on the data currently highlighted in the
-packe details, and apply the filter.
+Create a display filter based on the data currently highlighted in the
+packet details and copy that filter to the clipboard.
 
 If that data is a field that can be tested in a display filter
 expression, the display filter will test that field; otherwise, the
-display filter will be based on absolute offset within the packet, and
-so could be unreliable if the packet contains protocols with
+display filter will be based on the absolute offset within the packet.
+Therefore it could be unreliable if the packet contains protocols with
 variable-length headers, such as a source-routed token-ring packet.
 
+=item Analyze:Apply as Filter
+
+Create a display filter based on the data currently highlighted in the
+packet details and apply the filter.
+
 The B<Selected> option creates a display filter that tests for a match
 of the data; the B<Not Selected> option creates a display filter that
 tests for a non-match of the data.  The B<And Selected>, B<Or Selected>,
 B<And Not Selected>, and B<Or Not Selected> options add to the end of
-the display filter in the strip at the bottom an AND or OR operator
-followed by the new display filter expression.
+the display filter in the strip at the top (or bottom) an AND or OR
+operator followed by the new display filter expression.
 
 =item Analyze:Prepare a Filter
 
-Create a display filter, or add to the display filter strip at the
-bottom, a display filter based on the data currently highlighted in the
-packet details, but don't apply the filter.
+Create a display filter based on the data currently highlighted in the
+packet details. The filter strip at the top (or bottom) is updated but 
+it is not yet applied.
 
 =item Analyze:Enabled Protocols
 
Index: docbook/wsug_src/WSUG_chapter_work.xml
===================================================================
--- docbook/wsug_src/WSUG_chapter_work.xml	(revision 20948)
+++ docbook/wsug_src/WSUG_chapter_work.xml	(working copy)
@@ -101,6 +101,16 @@
 		<entry></entry>
 	      </row>
 	      <row>
+		<entry><command>Copy as Filter</command></entry>
+		<entry>Analyze</entry>
+		<entry>
+	    <para>
+		  Prepare a display filter based on the currently selected item
+		  but copy it to the clipboard.
+	    </para>
+		</entry>
+	      </row>
+	      <row>
 		<entry><command>Apply as Filter</command></entry>
 		<entry>Analyze</entry>
 		<entry>
@@ -430,6 +440,16 @@
 		<entry></entry>
 	      </row>
 	      <row>
+		<entry><command>Copy as Filter</command></entry>
+		<entry>Analyze</entry>
+		<entry>
+	    <para>
+		  Prepare a display filter based on the currently selected item
+		  but copy it to the clipboard.
+	    </para>
+		</entry>
+	      </row>
+	      <row>
 		<entry><command>Apply as Filter</command></entry>
 		<entry>Analyze</entry>
 		<entry>
Index: docbook/wsug_src/WSUG_chapter_use.xml
===================================================================
--- docbook/wsug_src/WSUG_chapter_use.xml	(revision 20948)
+++ docbook/wsug_src/WSUG_chapter_use.xml	(working copy)
@@ -1229,6 +1229,15 @@
 		  </para></entry>
 	      </row>
 	      <row>
+		<entry><command>Copy as Filter</command></entry>
+		<entry></entry>
+		<entry><para>
+			This menu item will use the selected item in the detail view to
+			create a display filter. This display filter is then copied to
+			the clipboard.
+		  </para></entry>
+	      </row>
+	      <row>
 		<entry><command>Apply as Filter > ...</command></entry>
 		<entry></entry>
 		<entry><para>
Index: gtk/menu.c
===================================================================
--- gtk/menu.c	(revision 20948)
+++ gtk/menu.c	(working copy)
@@ -568,6 +568,8 @@
     ITEM_FACTORY_ENTRY("/_Analyze", NULL, NULL, 0, "<Branch>", NULL),
     ITEM_FACTORY_STOCK_ENTRY("/Analyze/_Display Filters...", NULL, dfilter_dialog_cb,
                        0, WIRESHARK_STOCK_DISPLAY_FILTER),
+    ITEM_FACTORY_ENTRY("/Analyze/_Copy as Filter", NULL, match_selected_ptree_cb,
+                       MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL),
     ITEM_FACTORY_ENTRY("/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL),
     ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
@@ -656,6 +658,8 @@
 
     ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
 
+    ITEM_FACTORY_ENTRY("/Copy as Filter", NULL, match_selected_plist_cb,
+                       MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL),
     ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
     ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_plist_cb,
                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
@@ -762,6 +766,9 @@
 
     ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
 
+    ITEM_FACTORY_ENTRY("/Copy as Filter", NULL, match_selected_ptree_cb,
+                       MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL),
+
     ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
     ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
@@ -2399,6 +2406,8 @@
       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
   set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
+  set_menu_sensitivity(packet_list_menu_factory, "/Copy as Filter",
+      cf->current_frame != NULL);
   set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
       cf->current_frame != NULL);
   set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
@@ -2486,6 +2495,10 @@
 	  "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
 	set_menu_sensitivity(tree_view_menu_factory,
 	  "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
+	set_menu_sensitivity(main_menu_factory, "/Analyze/Copy as Filter",
+	  proto_can_match_selected(cf->finfo_selected, cf->edt));
+	set_menu_sensitivity(tree_view_menu_factory, "/Copy as Filter",
+	  proto_can_match_selected(cf->finfo_selected, cf->edt));
 	set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
 	  proto_can_match_selected(cf->finfo_selected, cf->edt));
 	set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
@@ -2507,6 +2520,8 @@
 	    "/Go/Go to Corresponding Packet", FALSE);
 	set_menu_sensitivity(tree_view_menu_factory,
 	    "/Go to Corresponding Packet", FALSE);
+	set_menu_sensitivity(main_menu_factory, "/Analyze/Copy as Filter", FALSE);
+	set_menu_sensitivity(tree_view_menu_factory, "/Copy as Filter", FALSE);
 	set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
 	set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
 	set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
Index: gtk/main.c
===================================================================
--- gtk/main.c	(revision 20948)
+++ gtk/main.c	(working copy)
@@ -247,8 +247,11 @@
     GtkWidget		*filter_te;
     char		*cur_filter, *new_filter;
 
-    if (!text)
+    if (strlen(text)==0) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
 	return;
+    }
+
     g_assert(data);
     filter_te = OBJECT_GET_DATA(data, E_DFILTER_TE_KEY);
     g_assert(filter_te);
@@ -302,12 +305,20 @@
     /* Free up the copy we got of the old filter text. */
     g_free(cur_filter);
 
-    /* create a new one and set the display filter entry accordingly */
-    gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
+    /* Don't change the current display filter if we only want to copy the filter */
+    if (action&MATCH_SELECTED_COPY_ONLY) {
+	GString *gtk_text_str = g_string_new("");
+	g_string_sprintfa(gtk_text_str, "%s", new_filter);
+	copy_to_clipboard(gtk_text_str);
+	g_string_free(gtk_text_str, TRUE);
+    } else {
+	/* create a new one and set the display filter entry accordingly */
+	gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
 
-    /* Run the display filter so it goes in effect. */
-    if (action&MATCH_SELECTED_APPLY_NOW)
-	main_filter_packets(&cfile, new_filter, FALSE);
+	/* Run the display filter so it goes in effect. */
+	if (action&MATCH_SELECTED_APPLY_NOW)
+	    main_filter_packets(&cfile, new_filter, FALSE);
+    }
 
     /* Free up the new filter text. */
     g_free(new_filter);
@@ -321,8 +332,7 @@
     if (cfile.finfo_selected) {
         filter = proto_construct_match_selected_string(cfile.finfo_selected,
                                                        cfile.edt);
-        if (filter != NULL)
-            match_selected_cb_do((data ? data : w), action, filter);
+        match_selected_cb_do((data ? data : w), action, filter);
     }
 }
 
@@ -4644,6 +4654,8 @@
                          filter_te);
     set_menu_object_data("/Analyze/Follow SSL Stream", E_DFILTER_TE_KEY,
                          filter_te);
+    set_menu_object_data("/Analyze/Copy as Filter", E_DFILTER_TE_KEY,
+                         filter_te);
     set_menu_object_data("/Analyze/Apply as Filter/Selected", E_DFILTER_TE_KEY,
                          filter_te);
     set_menu_object_data("/Analyze/Apply as Filter/Not Selected", E_DFILTER_TE_KEY,
Index: gtk/main.h
===================================================================
--- gtk/main.h	(revision 20948)
+++ gtk/main.h	(working copy)
@@ -126,6 +126,9 @@
 /** "bitwise or" this with MATCH_SELECTED_E value for instant apply instead of prepare only */
 #define MATCH_SELECTED_APPLY_NOW    0x100
 
+/** "bitwise or" this with MATCH_SELECTED_E value for copy to clipboard instead of prepare only */
+#define MATCH_SELECTED_COPY_ONLY    0x200
+
 /** User highlited item in details window and then right clicked and selected the copy option 
  *
  * @param widget parent widget