diff options
-rw-r--r-- | doc/README.plugins | 26 | ||||
-rw-r--r-- | epan/CMakeLists.txt | 2 | ||||
-rw-r--r-- | epan/Makefile.common | 4 | ||||
-rw-r--r-- | epan/plugin_if.c (renamed from epan/ext_menubar.c) | 89 | ||||
-rw-r--r-- | epan/plugin_if.h (renamed from epan/ext_menubar.h) | 42 | ||||
-rw-r--r-- | ui/gtk/main_filter_toolbar.c | 24 | ||||
-rw-r--r-- | ui/gtk/main_menubar.c | 2 | ||||
-rw-r--r-- | ui/gtk/packet_list.c | 24 | ||||
-rw-r--r-- | ui/preference_utils.c | 42 | ||||
-rw-r--r-- | ui/preference_utils.h | 10 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 44 | ||||
-rw-r--r-- | ui/qt/main_window.h | 2 |
12 files changed, 292 insertions, 19 deletions
diff --git a/doc/README.plugins b/doc/README.plugins index eca52da251..e8cac10246 100644 --- a/doc/README.plugins +++ b/doc/README.plugins @@ -321,12 +321,14 @@ is encouraged to update their plugins as outlined below: the DOCSIS plugin. -6 How to implement a plugin related menu +6 How to plugin related interface options + +6.1 Implement a plugin GUI menu A plugin (as well as built-in dissectors) may implement a menu within Wireshark to be used to trigger options, start tools, open Websites, ... -This menu structure is built using the ext_menubar.h interface and it's +This menu structure is built using the plugin_if.h interface and it's corresponding functions. The menu items all call a callback provided by the plugin, which takes @@ -365,7 +367,25 @@ Using the Gtk Version and a Mac OSX operating system, this will not work, and the Gtk interface is currently not supported on this plattform. The Qt interface on Mac provides the menu. -For a more detailed information, please refer to ext_menubar.h +For a more detailed information, please refer to plugin_if.h + +6.2 Implement interactions with the main interface + +Due to memory constraints on most plattforms, plugin functionality cannot be +called directly from a DLL context. Instead special functions will be used, which +will implement certain options for plugins to utilize. + +The following methods exist so far: + + /* Applies the given filter string as display filter */ + WS_DLL_PUBLIC void plugin_if_apply_filter + (const char * filter_string, gboolean force); + + /* Saves the given preference to the main preference storage */ + WS_DLL_PUBLIC void plugin_if_save_preference + (const char * pref_module, const char * pref_key, const char * pref_value); + + ---------------- diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index aa37191ddc..36d141bf0d 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -1600,7 +1600,7 @@ set(LIBWIRESHARK_FILES except.c expert.c exported_pdu.c - ext_menubar.c + plugin_if.c filter_expressions.c follow.c frame_data.c diff --git a/epan/Makefile.common b/epan/Makefile.common index a8c3bb5ad1..fe81b1c7ea 100644 --- a/epan/Makefile.common +++ b/epan/Makefile.common @@ -51,7 +51,7 @@ LIBWIRESHARK_SRC = \ except.c \ expert.c \ exported_pdu.c \ - ext_menubar.c \ + plugin_if.c \ filter_expressions.c \ follow.c \ frame_data.c \ @@ -192,7 +192,7 @@ LIBWIRESHARK_INCLUDES = \ exceptions.h \ expert.h \ exported_pdu.h \ - ext_menubar.h \ + plugin_if.h \ filter_expressions.h \ follow.h \ frame_data.h \ diff --git a/epan/ext_menubar.c b/epan/plugin_if.c index 25501520c7..62244dd4fd 100644 --- a/epan/ext_menubar.c +++ b/epan/plugin_if.c @@ -1,9 +1,12 @@ -/* ext_menubar.c - * A menubar API for Wireshark dissectors +/* plugin_if.c + * An API for Wireshark plugins * * This enables wireshark dissectors, especially those implemented by plugins * to register menubar entries, which then will call a pre-defined callback - * function for the dissector or plugin + * function for the dissector or plugin. + * + * Also it implements additional methods, which allow plugins to interoperate + * with the main GUI. * * Wireshark - Network traffic analyzer * By Gerald Combs <gerald@wireshark.org> @@ -30,7 +33,7 @@ #include <epan/epan.h> #include <epan/proto.h> -#include "ext_menubar.h" +#include "plugin_if.h" static GList * menubar_entries = NULL; static GList * menubar_menunames = NULL; @@ -158,6 +161,84 @@ extern void ext_menubar_add_separator(ext_menu_t *parent) ext_menubar_add_generic_entry ( EXT_MENUBAR_SEPARATOR, parent, g_strdup("-"), NULL, NULL, NULL ); } +/* Implementation of GUI callback methods follows. + * This is a necessity, as using modern UI systems, gui interfaces often operate + * in different threads then the calling application. Even more so, if the calling + * application is implemented using a separate plugin. Therefore the external menubars + * cannot call gui functionality directly, the gui has to perform the function within + * it' own scope. */ + +static GHashTable * plugin_if_callback_functions; + +static void +plugin_if_init_hashtable(void) +{ + if ( plugin_if_callback_functions == 0 ) + plugin_if_callback_functions = g_hash_table_new(g_int_hash, g_int_equal); +} + +static void plugin_if_call_gui_cb(plugin_if_callback_t actionType, GHashTable * dataSet) +{ + plugin_if_gui_cb action; + gint * key = 0; + + key = (gint *)g_malloc0(sizeof(gint)); + *key = (gint) actionType; + + plugin_if_init_hashtable(); + + if ( g_hash_table_size(plugin_if_callback_functions) != 0 ) + { + if ( g_hash_table_contains(plugin_if_callback_functions, key) ) + { + action = (plugin_if_gui_cb)g_hash_table_lookup(plugin_if_callback_functions, key); + if ( action != NULL ) + action(dataSet); + } + } +} + +extern void plugin_if_apply_filter(const char * filter_string, gboolean force) +{ + plugin_if_callback_t actionType; + GHashTable * dataSet = NULL; + + actionType = ( force == TRUE ) ? PLUGIN_IF_FILTER_ACTION_APPLY : PLUGIN_IF_FILTER_ACTION_PREPARE; + dataSet = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert( dataSet, g_strdup("action_type"), (gpointer) &actionType ); + g_hash_table_insert( dataSet, g_strdup("filter_string"), g_strdup(filter_string) ); + g_hash_table_insert( dataSet, g_strdup("force"), (gpointer) &force ); + + plugin_if_call_gui_cb(actionType, dataSet); +} + +extern void plugin_if_save_preference(const char * pref_module, const char * pref_key, const char * pref_value) +{ + GHashTable * dataSet = NULL; + + dataSet = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert( dataSet, g_strdup("pref_module"), g_strdup(pref_module) ); + g_hash_table_insert( dataSet, g_strdup("pref_key"), g_strdup(pref_key) ); + g_hash_table_insert( dataSet, g_strdup("pref_value"), g_strdup(pref_value) ); + + plugin_if_call_gui_cb(PLUGIN_IF_PREFERENCE_SAVE, dataSet); +} + +extern void plugin_if_register_gui_cb(plugin_if_callback_t actionType, plugin_if_gui_cb callback) +{ + gint * key = 0; + + key = (gint *)g_malloc0(sizeof(gint)); + *key = actionType; + + plugin_if_init_hashtable(); + + if ( ! g_hash_table_contains(plugin_if_callback_functions, key ) ) + g_hash_table_insert(plugin_if_callback_functions, key, callback); +} + /* * Editor modelines * diff --git a/epan/ext_menubar.h b/epan/plugin_if.h index acffa8f2e8..df9ea6e846 100644 --- a/epan/ext_menubar.h +++ b/epan/plugin_if.h @@ -1,9 +1,12 @@ -/* ext_menubar.h - * A menubar API for Wireshark dissectors +/* plugin_if.h + * An API for Wireshark plugins * * This enables wireshark dissectors, especially those implemented by plugins * to register menubar entries, which then will call a pre-defined callback - * function for the dissector or plugin + * function for the dissector or plugin. + * + * Also it implements additional methods, which allow plugins to interoperate + * with the main GUI. * * Wireshark - Network traffic analyzer * By Gerald Combs <gerald@wireshark.org> @@ -23,8 +26,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef EPAN_EXT_MENUBAR_H_ -#define EPAN_EXT_MENUBAR_H_ +#ifndef EPAN_PLUGIN_IF_H +#define EPAN_PLUGIN_IF_H #include <config.h> @@ -146,6 +149,33 @@ WS_DLL_PUBLIC void ext_menubar_add_separator(ext_menu_t *parent_menu); WS_DLL_PUBLIC void ext_menubar_add_website(ext_menu_t * parent, const gchar *label, const gchar *tooltip, const gchar *url); + +/* + * Enumeration of possible actions, which are registered in GUI interfaces + */ +typedef enum +{ + /* Applies a given string as filter */ + PLUGIN_IF_FILTER_ACTION_APPLY, + + /* Prepares the given string as filter */ + PLUGIN_IF_FILTER_ACTION_PREPARE, + + /* Saves a preference entry */ + PLUGIN_IF_PREFERENCE_SAVE +} plugin_if_callback_t; + + +typedef void (*plugin_if_gui_cb)(gconstpointer user_data); + +WS_DLL_PUBLIC void plugin_if_register_gui_cb(plugin_if_callback_t actionType, plugin_if_gui_cb callback); + +/* Applies the given filter string as display filter */ +WS_DLL_PUBLIC void plugin_if_apply_filter(const char * filter_string, gboolean force); + +/* Saves the given preference to the main preference storage */ +WS_DLL_PUBLIC void plugin_if_save_preference(const char * pref_module, const char * pref_key, const char * pref_value); + /* Private Method for retrieving the menubar entries * * Is only to be used by the UI interfaces to retrieve the menu entries @@ -156,7 +186,7 @@ WS_DLL_PUBLIC GList * ext_menubar_get_entries(void); } #endif /* __cplusplus */ -#endif /* EPAN_EXT_MENUBAR_H_ */ +#endif /* EPAN_PLUGIN_IF_H */ /* * Editor modelines diff --git a/ui/gtk/main_filter_toolbar.c b/ui/gtk/main_filter_toolbar.c index f47e7819dc..eed3ee3cc2 100644 --- a/ui/gtk/main_filter_toolbar.c +++ b/ui/gtk/main_filter_toolbar.c @@ -39,6 +39,7 @@ #include "filter_autocomplete.h" #include "epan/prefs.h" +#include "epan/plugin_if.h" #include "keys.h" #include "gtkglobals.h" @@ -109,6 +110,26 @@ filter_save_cb(GtkWidget *w _U_, GtkWindow *parent_w) filter_expression_save_dlg(parent_w); } +static void +plugin_if_filter_apply(gconstpointer filter_text) +{ + /* code is derived from voip_calls_dlg.c::voip_calls_on_filter */ + + int pos = 0; + size_t filter_length; + size_t max_filter_length = 2048; + gchar *filter_string; + + if ( main_display_filter_widget != 0 ) + { + filter_string = g_strndup((const char *)filter_text, max_filter_length); + filter_length = strlen(filter_string); + pos = (int)filter_length; + + if ( filter_length < max_filter_length ) + gtk_editable_insert_text(GTK_EDITABLE(main_display_filter_widget), filter_string, -1, &pos); + } +} GtkWidget * filter_toolbar_new(void) @@ -279,6 +300,9 @@ filter_toolbar_new(void) /* make current preferences effective */ toolbar_redraw_all(); + plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_APPLY, plugin_if_filter_apply ); + plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_PREPARE, plugin_if_filter_apply ); + return filter_tb; } diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c index b4c24d986a..50292d049e 100644 --- a/ui/gtk/main_menubar.c +++ b/ui/gtk/main_menubar.c @@ -36,7 +36,7 @@ #include <epan/epan_dissect.h> #include <epan/column.h> #include <epan/stats_tree_priv.h> -#include <epan/ext_menubar.h> +#include <epan/plugin_if.h> #include "globals.h" #include "color_filters.h" diff --git a/ui/gtk/packet_list.c b/ui/gtk/packet_list.c index f9a4f298e7..57ab4f95bb 100644 --- a/ui/gtk/packet_list.c +++ b/ui/gtk/packet_list.c @@ -34,6 +34,7 @@ #include <epan/packet.h> #include <epan/column.h> #include <epan/strutil.h> +#include <epan/plugin_if.h> #include "ui/main_statusbar.h" #include "ui/packet_list_utils.h" @@ -91,6 +92,7 @@ static void show_cell_data_func(GtkTreeViewColumn *col, static gint row_number_from_iter(GtkTreeIter *iter); static void scroll_to_current(void); static gboolean query_packet_list_tooltip_cb(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer data _U_); +static void plugin_if_pktlist_preference(gconstpointer user_data); GtkWidget * packet_list_create(void) @@ -105,6 +107,8 @@ packet_list_create(void) g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY, view); + plugin_if_register_gui_cb(PLUGIN_IF_PREFERENCE_SAVE, plugin_if_pktlist_preference); + return scrollwin; } @@ -1730,6 +1734,26 @@ query_packet_list_tooltip_cb(GtkWidget *widget, gint x, gint y, gboolean keyboar return result; } +void plugin_if_pktlist_preference(gconstpointer user_data) +{ + if ( packetlist != NULL && user_data != NULL ) + { + GHashTable * dataSet = (GHashTable *) user_data; + if ( g_hash_table_contains(dataSet, "pref_module" ) && + g_hash_table_contains(dataSet, "pref_value" ) && + g_hash_table_contains(dataSet, "pref_value" ) ) + { + const char * module_name = (const char *)g_hash_table_lookup(dataSet, "pref_module"); + const char * pref_name = (const char *)g_hash_table_lookup(dataSet, "pref_key"); + const char * pref_value = (const char *)g_hash_table_lookup(dataSet, "pref_value"); + + if ( prefs_store_ext(module_name, pref_name, pref_value) ) + packet_list_recreate(); + + } + } +} + /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * diff --git a/ui/preference_utils.c b/ui/preference_utils.c index 1e358bd7d0..0f80ef6742 100644 --- a/ui/preference_utils.c +++ b/ui/preference_utils.c @@ -273,6 +273,48 @@ prefs_main_write(void) } } +gboolean +prefs_store_ext(const char * module_name, const char *pref_name, const char *pref_value) +{ + module_t * module = NULL; + pref_t * pref = NULL; + gboolean pref_changed = TRUE; + + if ( ! prefs_is_registered_protocol(module_name)) + return FALSE; + + module = prefs_find_module(module_name); + if ( ! module ) + return FALSE; + + pref = prefs_find_preference(module, pref_name); + + if (!pref) + return FALSE; + + if ( pref->type == PREF_STRING ) + { + g_free((void *)pref->stashed_val.string); + pref->stashed_val.string = (gchar *) g_strdup(pref_value); + /* unstash - taken from preferences_util */ + if (strcmp(*pref->varp.string, pref->stashed_val.string) != 0) + { + pref_changed = TRUE; + g_free((void *)*pref->varp.string); + *pref->varp.string = g_strdup(pref->stashed_val.string); + } + } + + if ( pref_changed ) + { + prefs_main_write(); + prefs_apply_all(); + prefs_to_capture_opts(); + } + + return TRUE; +} + gint column_prefs_add_custom(gint fmt, const gchar *title, const gchar *custom_field, gint custom_occurrence) { diff --git a/ui/preference_utils.h b/ui/preference_utils.h index 882555d70a..a0b345d043 100644 --- a/ui/preference_utils.h +++ b/ui/preference_utils.h @@ -80,6 +80,16 @@ extern void prefs_to_capture_opts(void); */ extern void prefs_main_write(void); +/** Convenient function for plugin_if + * + * @param module the module for the preference + * @param key the key for the preference + * @param value the new value as string for the preference + * + * @return true if the value has been stored successfully + */ +extern gboolean prefs_store_ext(const char * module, const char * key, const char * value); + /** Add a custom column. * * @param fmt column format diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index abae150c71..35e110c39b 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -27,7 +27,7 @@ #include <wsutil/filesystem.h> #include <epan/prefs.h> #include <epan/stats_tree_priv.h> -#include <epan/ext_menubar.h> +#include <epan/plugin_if.h> #ifdef HAVE_LIBPCAP #include "ui/capture.h" @@ -42,6 +42,7 @@ #include "ui/main_statusbar.h" #include "ui/recent.h" #include "ui/util.h" +#include "ui/preference_utils.h" #include "byte_view_tab.h" #include "display_filter_edit.h" @@ -83,6 +84,42 @@ void pipe_input_set_handler(gint source, gpointer user_data, ws_process_id *chil gbl_cur_main_window_->setPipeInputHandler(source, user_data, child_process, input_cb); } +void plugin_if_mainwindow_apply_filter(gconstpointer user_data) +{ + if ( gbl_cur_main_window_ != NULL && user_data != NULL ) + { + GHashTable * dataSet = (GHashTable *) user_data; + + if ( g_hash_table_contains(dataSet, "filter_string" ) ) + { + QString filter((const char *)g_hash_table_lookup(dataSet, "filter_string")); + gbl_cur_main_window_->filterPackets(filter); + } + } +} + +void plugin_if_mainwindow_preference(gconstpointer user_data) +{ + if ( gbl_cur_main_window_ != NULL && user_data != NULL ) + { + GHashTable * dataSet = (GHashTable *) user_data; + if ( g_hash_table_contains(dataSet, "pref_module" ) && + g_hash_table_contains(dataSet, "pref_value" ) && + g_hash_table_contains(dataSet, "pref_value" ) ) + { + const char * module_name = (const char *)g_hash_table_lookup(dataSet, "pref_module"); + const char * pref_name = (const char *)g_hash_table_lookup(dataSet, "pref_key"); + const char * pref_value = (const char *)g_hash_table_lookup(dataSet, "pref_value"); + + if ( prefs_store_ext(module_name, pref_name, pref_value) ) + { + wsApp->emitAppSignal(WiresharkApplication::PacketDissectionChanged); + wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged); + } + } + } +} + gpointer simple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ...) { @@ -479,6 +516,11 @@ MainWindow::MainWindow(QWidget *parent) : this->main_welcome_->getInterfaceTree(), SLOT(interfaceListChanged())); #endif + /* Create plugin_if hooks */ + plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_APPLY, plugin_if_mainwindow_apply_filter ); + plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_PREPARE, plugin_if_mainwindow_apply_filter ); + plugin_if_register_gui_cb(PLUGIN_IF_PREFERENCE_SAVE, plugin_if_mainwindow_preference); + main_ui_->mainStack->setCurrentWidget(main_welcome_); } diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 220bc63ffe..dbb85847aa 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -33,7 +33,7 @@ #include "ui/ui_util.h" #include <epan/prefs.h> -#include <epan/ext_menubar.h> +#include <epan/plugin_if.h> #ifdef HAVE_LIBPCAP #include "capture_opts.h" |