Index: docbook/wsug_src/WSUG_app_files.xml
===================================================================
--- docbook/wsug_src/WSUG_app_files.xml (revision 32935)
+++ docbook/wsug_src/WSUG_app_files.xml (working copy)
@@ -527,8 +527,134 @@
+
+ Protocol help configuration
+
+ Wireshark can use configuration files to create context-sensitive menu
+ items for protocol detail items which will load help URLs in your web
+ browser.
+
+
+ To create a protocol help file, create a folder named "protocol_help"
+ in either the personal or global configuration folders. Create a text
+ file with the extension ".ini" in the "protocol_help" folder. The file
+ must contain key-value pairs with the following sections:
+
+
+ General
+
+
+ Mandatory. This contains initialization information for the
+ help file. The following keys must be defined:
+
+
+ source
+ Source name, e.g. "HyperGlobalMegaMart".
+
+
+ version
+ Must be "1".
+
+
+ url_template
+
+
+ General URL for help items. Variables can be substituted using
+ the URL Data section below.
+
+
+
+
+
+
+
+
+
+ URL Data
+
+
+ Optional. Contains keys that will be used for variable
+ substitution in the url_template value. For example, if
+ the General section contains
+
+url_template = http://www.example.com/proto?cookie=${cookie}&path=${PATH}
+
+ then setting
+
+cookie = anonymous-user-1138
+
+ will result in the URL
+ "http://www.example.com/proto?cookie=anonymous-user-1138&path=${PATH}".
+ PATH is used for help path substitution, and shouldn't be defined in this section.
+
+
+
+
+
+ Map
+
+
+ Maps Wireshark protocol names to section names below. Each key
+ MUST match a valid protocol name such as "ip". Each value MUST
+ have a matching section defined in the configuration file.
+
+
+
+
+
+
+ Each protocol section must contain an "_OVERVIEW" key which will be used
+ as the first menu item for the help source. Subsequent keys must match
+ descriptions in the protocol detail. Values will be used as the ${PATH}
+ variable in the URL template.
+
+
+
+ Suppose the file
+ C:\Users\sam.clemens\AppData\Roaming\Wireshark\protocol_help\wikipedia.ini
+ contains the following:
+
+
+# Wikipedia (en) protocol help file.
+
+# Help file initialization
+# source: The source of the help information, e.g. "Inacon" or "Wikipedia"
+# version: Currently unused. Must be "1".
+# url_template: Template for generated URLs. See "URL Data" below.
+[General]
+source=Wikipedia
+version=1
+url_template=http://en.wikipedia.org/wiki/${PATH}
+
+# Substitution data for the URL template.
+# Each occurence of the keys below in the URL template will be substituted
+# with their corresponding values. For example, "${license}" in the URL
+# template above will be replaced with the value of "license" below.
+#
+# PATH is reserved for the help paths below; do not specify it here.
+[URL Data]
+
+# Maps Wireshark protocol names to section names below. Each key MUST match
+# a valid protocol name. Each value MUST have a matching section below.
+[Map]
+tcp=TCP
+
+# Mapped protocol sections.
+# Keys must match protocol detail items descriptions.
+[TCP]
+_OVERVIEW=Transmission_Control_Protocol
+Destination port=Transmission_Control_Protocol#TCP_ports
+Source port=Transmission_Control_Protocol#TCP_ports
+
+ Right-clicking on a TCP protocol detail item will display a help menu
+ item that displays the Wikipedia page for TCP. Right-clicking on the
+ TCP destination or source ports will display additional help menu items that
+ take you to the "TCP ports" section of the page.
+
+
+
Windows folders
Here you will find some details about the folders used in Wireshark
Index: gtk/proto_help.c
===================================================================
--- gtk/proto_help.c (revision 0)
+++ gtk/proto_help.c (revision 0)
@@ -0,0 +1,652 @@
+/* proto_help.c
+ * Routines for dynamic protocol help menus
+ *
+ * $Id: capture_dlg.c 32829 2010-05-16 08:14:29Z guy $
+ *
+ * Edgar Gladkich
+ * Gerald Combs
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include
+
+#include
+#include
+
+#include "../file.h"
+
+#include
+#include
+#include
+#include
+
+#define PH_MENU_TOP "/Protocol Help"
+
+#define PH_FILE_LOG "ph.log"
+#define PH_INI_SUFFIX ".ini"
+#define PH_PATH_SEARCH_STR "${PATH}"
+
+/* .ini Section names */
+#define PH_INI_GROUP_GENERAL "General"
+#define PH_INI_GROUP_URL_DATA "URL Data"
+#define PH_INI_GROUP_MAP "Map"
+
+/* .ini General section keys */
+#define PH_INI_KEY_LICENSE "license"
+#define PH_INI_KEY_SOURCE "source"
+#define PH_INI_KEY_URL_TEMPLATE "url_template"
+
+/* .ini Path sections */
+#define PH_INI_KEY_OVERVIEW "_OVERVIEW"
+
+/* Where to look for .ini files */
+#define PH_CONFFILE_SUBDIR "protocol_help"
+
+#ifdef PH_DEBUG_LOG
+const gchar *ph_log_path;
+#endif
+
+typedef struct proto_help_key_file_t {
+ GKeyFile *keyfile;
+ const gchar *source;
+ const gchar *url_template;
+} proto_help_key_file;
+
+GPtrArray *g_ph_key_files = NULL;
+
+GtkItemFactory *g_ph_menu_factory;
+
+static void ph_menu_reset(void);
+static void ph_menu_onclick(GtkWidget*, gpointer, guint);
+
+static int ph_capture_get_protocol_id(GtkTreeSelection*, capture_file*);
+static const gchar* ph_capture_get_protocol_name(GtkTreeSelection*, capture_file*);
+static const gchar* ph_capture_get_protocol_abbrev(GtkTreeSelection*, capture_file*);
+static gchar* ph_capture_get_description(capture_file*);
+
+static proto_help_key_file *ph_ini_load_file(const gchar*);
+static gchar* ph_ini_get_value(GKeyFile *, const gchar*, const gchar*, gchar *);
+static gchar* ph_ini_get_path(GKeyFile *, const gchar*, const gchar*);
+static gchar** ph_ini_get_keywords(GKeyFile *, const gchar*);
+
+static guint ph_parse_string(const gchar*, const gchar*);
+
+/* #define PH_DEBUG_LOG 1 */
+#ifdef PH_DEBUG_LOG
+static void ph_logging_handler(const gchar*, GLogLevelFlags, const gchar*, gpointer);
+#endif
+
+/** @file
+ * Protocol help routines. Adds web browser links to protocol menu items
+ * via configuration files.
+ */
+
+/** Initialization
+ *
+ * @param void
+ * @return void
+ */
+#define PH_CONF_DIRS 2
+void proto_help_init(void)
+{
+ gchar *search_dir[PH_CONF_DIRS];
+ const gchar *ini_name;
+ gchar *ini_path;
+ GDir *conf_dir;
+ proto_help_key_file *phkf;
+ int i;
+
+ search_dir[0] = g_strdup_printf("%s" G_DIR_SEPARATOR_S PH_CONFFILE_SUBDIR, get_datafile_dir());
+ /* XXX - Use profiles? */
+ search_dir[1] = get_persconffile_path(PH_CONFFILE_SUBDIR, FALSE, FALSE);
+
+#ifdef PH_DEBUG_LOG
+ g_log_set_handler(NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, ph_logging_handler, NULL);
+#endif
+
+ if (g_ph_key_files)
+ return;
+
+ g_ph_key_files = g_ptr_array_new();
+
+ /* Start loop */
+
+#ifdef PH_DEBUG_LOG
+ ph_log_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", g_get_tmp_dir(), PH_FILE_LOG);
+#endif
+
+ for (i = 0; i < PH_CONF_DIRS; i++) {
+ g_log(NULL, G_LOG_LEVEL_INFO, "Looking for protocol help files in '%s'", search_dir[i]);
+ conf_dir = g_dir_open(search_dir[i], 0, NULL);
+ if (!conf_dir) {
+ continue;
+ }
+
+ while ((ini_name = g_dir_read_name(conf_dir)) != NULL) {
+ if (! g_str_has_suffix(ini_name, PH_INI_SUFFIX)) {
+ continue;
+ }
+ g_log(NULL, G_LOG_LEVEL_INFO, "-- Found '%s'", ini_name);
+ ini_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", search_dir[i], ini_name);
+ phkf = ph_ini_load_file(ini_path);
+ g_free(ini_path);
+ }
+ g_dir_close(conf_dir);
+ }
+}
+
+/** Initialize the menu
+ *
+ * @param widget Context menu root
+ * @return void
+ */
+void proto_help_menu_init(GtkWidget *widget)
+{
+ g_ph_menu_factory = gtk_item_factory_from_widget(widget);
+ ph_menu_reset();
+}
+
+/** Clear the menu
+ *
+ * @param void
+ * @return void
+ */
+static void ph_menu_reset(void)
+{
+ GtkWidget *menu_item = NULL;
+ GList *menu_entries = NULL;
+ GList *menu_entry = NULL;
+
+ if(!g_ph_menu_factory) return;
+
+ menu_item = gtk_item_factory_get_widget(g_ph_menu_factory, PH_MENU_TOP);
+ menu_entries = gtk_container_children(GTK_CONTAINER(menu_item));
+
+ for(menu_entry = g_list_first(menu_entries); menu_entry != NULL; menu_entry = g_list_next(menu_entry))
+ {
+ gtk_container_remove(GTK_CONTAINER(menu_item), menu_entry->data);
+ }
+
+ menu_item = gtk_item_factory_get_item(g_ph_menu_factory, PH_MENU_TOP);
+ gtk_widget_set_sensitive(menu_item, FALSE);
+}
+
+/* Callback to free URLs */
+static void
+url_destroy_cb(GtkWidget *w _U_, gpointer url) {
+ g_free(url);
+}
+
+/** Fill in the protocol help menu
+ *
+ * @param selection Currently-selected packet
+ * @param cf Capture file
+ * @return void
+ */
+void proto_help_menu_modify(GtkTreeSelection *selection, capture_file *cf)
+{
+ gchar *description;
+ const gchar *proto_abbrev, *proto_name;
+ gchar *value;
+ gchar **keys;
+ GHashTable *table;
+ guint i = 0, cur_kf;
+ GtkWidget *menu_item = NULL;
+ GtkItemFactoryEntry *menu_entry = NULL;
+ proto_help_key_file* phkf;
+ gchar *url;
+ gboolean add_separator = FALSE;
+ gboolean found = FALSE;
+
+ if(!g_ph_menu_factory) return;
+ ph_menu_reset();
+
+ proto_abbrev = ph_capture_get_protocol_abbrev(selection, cf);
+ if(!proto_abbrev) return;
+
+ proto_name = ph_capture_get_protocol_name(selection, cf);
+ if(!proto_name) return;
+
+ description = ph_capture_get_description(cf);
+
+ for (cur_kf = 0; cur_kf < g_ph_key_files->len; cur_kf++) {
+ phkf = (proto_help_key_file *) g_ptr_array_index(g_ph_key_files, cur_kf);
+ g_assert(phkf);
+
+ value = ph_ini_get_path(phkf->keyfile, proto_abbrev, PH_INI_KEY_OVERVIEW);
+
+ if(!value)
+ {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Overview page of the protocol '%s' is not defined", proto_abbrev);
+ continue;
+ }
+
+ /*
+ * XXX - We could save some memory here if we stored the URL template
+ * and search value as separate items. However, that makes freeing them
+ * a bit messy.
+ */
+ url = string_replace(phkf->url_template, PH_PATH_SEARCH_STR, value);
+ g_free(value);
+ if (!url || !strlen(url)) continue;
+
+ if (add_separator) {
+ menu_entry = g_malloc0(sizeof(GtkItemFactoryEntry));
+ menu_entry->path = g_strdup_printf("%s/", PH_MENU_TOP);
+ menu_entry->item_type = "";
+ gtk_item_factory_create_item(g_ph_menu_factory, menu_entry, NULL, 2);
+ }
+ add_separator = TRUE;
+
+ menu_entry = g_malloc0(sizeof(GtkItemFactoryEntry));
+ menu_entry->path = g_strdup_printf("%s/%s %s Overview", PH_MENU_TOP, phkf->source, proto_name);
+ menu_entry->callback = ph_menu_onclick;
+ gtk_item_factory_create_item(g_ph_menu_factory, menu_entry, url, 2);
+ menu_item = gtk_item_factory_get_widget(g_ph_menu_factory, menu_entry->path);
+ g_assert(menu_item);
+ g_signal_connect(menu_item, "destroy", G_CALLBACK(url_destroy_cb), url);
+
+ found = TRUE;
+
+ if(description)
+ {
+ keys = ph_ini_get_keywords(phkf->keyfile, proto_abbrev);
+ table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+ for(i = 0; keys[i] != NULL; i++)
+ {
+ if(!strcmp(keys[i], PH_INI_KEY_OVERVIEW)) continue; /* We already added the overview */
+ if(!ph_parse_string(description, keys[i])) continue; /* Bad format */
+ if(g_hash_table_lookup(table, g_ascii_strup(keys[i], -1)) != NULL) continue; /* Duplicate */
+
+ value = ph_ini_get_path(phkf->keyfile, proto_abbrev, keys[i]);
+ if(!value || !strlen(value)) continue;
+
+ url = string_replace(phkf->url_template, PH_PATH_SEARCH_STR, value);
+ g_free(value);
+ if (!url || !strlen(url)) continue;
+
+ g_hash_table_insert(table, g_ascii_strup(keys[i], -1), NULL);
+
+ menu_entry = g_malloc0(sizeof(GtkItemFactoryEntry));
+ menu_entry->path = g_strdup_printf("%s/%s", PH_MENU_TOP, keys[i]);
+ menu_entry->callback = ph_menu_onclick;
+ gtk_item_factory_create_item(g_ph_menu_factory, menu_entry, url, 2);
+ menu_item = gtk_item_factory_get_widget(g_ph_menu_factory, menu_entry->path);
+ g_assert(menu_item);
+ g_signal_connect(menu_item, "destroy", G_CALLBACK(url_destroy_cb), url);
+ }
+
+ g_hash_table_destroy(table);
+ }
+ }
+
+ g_free(description);
+ menu_item = gtk_item_factory_get_item(g_ph_menu_factory, PH_MENU_TOP);
+ gtk_widget_set_sensitive(menu_item, found);
+}
+
+/**
+* Function ph_menu_onclick
+*
+* @param GtkWidget *widget Description
+* @param gpointer data Description
+* @param guint action Description
+* @return void
+*/
+static void ph_menu_onclick(GtkWidget *widget _U_, gpointer data, guint action _U_)
+{
+ gchar *url = (gchar *) data;
+
+ if (! url) {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Protocol help ended up with a NULL URL.");
+ return;
+ }
+
+ /* XXX - Should we do any RFC 3986 escaping first? */
+ if (! browser_open_url(url)) {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Couldn't get protocol help for %s", url);
+ }
+}
+
+/** Get the field ID for a selected tree item.
+ *
+ * @param selection Tree selection
+ * @param cfile Capture file
+ * @return Field ID or 0
+ */
+static int
+ph_capture_get_protocol_id(GtkTreeSelection *selection, capture_file *cf)
+{
+ GtkTreeModel *model = NULL;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+ field_info *finfo = NULL;
+ int proto_id = 0;
+
+ if(!cf->finfo_selected) return 0;
+ proto_id = cf->finfo_selected->hfinfo->id;
+
+ if(!proto_id)
+ {
+ if(!gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter)) return 0;
+
+ while(gtk_tree_model_iter_parent(model, &parent, &iter))
+ {
+ gtk_tree_model_get(model, &parent, 1, &finfo, -1);
+ iter = parent;
+
+ if(finfo->hfinfo->id > 0)
+ {
+ proto_id = finfo->hfinfo->id;
+ break;
+ }
+ }
+ }
+
+ while(proto_id && !proto_registrar_is_protocol(proto_id))
+ {
+ proto_id = proto_registrar_get_parent(proto_id);
+ }
+
+ return proto_id;
+}
+
+/** Get the protocol name for a selected tree item.
+ *
+ * @param selection Tree selection
+ * @param cfile Capture file
+ * @return Name for a protocol or NULL
+ */
+static const gchar*
+ph_capture_get_protocol_name(GtkTreeSelection *selection, capture_file *cf)
+{
+ int proto_id = ph_capture_get_protocol_id(selection, cf);
+
+ return (!proto_id) ? NULL : proto_get_protocol_short_name(find_protocol_by_id(proto_id));
+}
+
+/** Get the abbreviated protocol name for a selected tree item.
+ *
+ * @param selection Tree selection
+ * @param cfile Capture file
+ * @return Abbreviated (lower-case) name for a protocol or NULL
+ */
+static const gchar*
+ph_capture_get_protocol_abbrev(GtkTreeSelection *selection, capture_file *cf)
+{
+ int proto_id = ph_capture_get_protocol_id(selection, cf);
+
+ return (!proto_id) ? NULL : proto_registrar_get_abbrev(proto_id);
+}
+
+/** Return the selected item description
+ * @param cf capture file pointer
+ * @return Description of the selected item. MUST be freed with g_free().
+ */
+static gchar* ph_capture_get_description(capture_file *cf)
+{
+ gchar *buffer = NULL;
+
+ if(cf->finfo_selected->rep->representation != 0)
+ {
+ buffer = g_strdup(cf->finfo_selected->rep->representation);
+ }
+ else
+ {
+ buffer = g_malloc(ITEM_LABEL_LENGTH);
+ proto_item_fill_label(cf->finfo_selected, buffer);
+ }
+
+ return buffer;
+}
+
+/** Load a protocol help key file and add it to the global array.
+ *
+ * @param filename Full path to the key file.
+ * @return Newly-created key file entry or NULL.
+ */
+static proto_help_key_file *
+ph_ini_load_file(const gchar *filename)
+{
+ GKeyFile *kf;
+ GError *error = NULL;
+ proto_help_key_file *phkf = NULL;
+ gchar *old_template, *url_template;
+ gchar **url_data, *url_repl, *url_search;
+ gsize i, len;
+
+ if(!g_file_test(filename, G_FILE_TEST_EXISTS))
+ {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Configuration file %s does not exists", filename);
+ return NULL;
+ }
+
+ kf = g_key_file_new();
+
+ if(!g_key_file_load_from_file(kf, filename, G_KEY_FILE_NONE, &error))
+ {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Configuration file '%s' could not be loaded (%s)", filename, error->message);
+ g_error_free(error);
+ g_key_file_free(kf);
+
+ return NULL;
+ }
+
+ url_template = ph_ini_get_value(kf, PH_INI_GROUP_GENERAL, PH_INI_KEY_URL_TEMPLATE, NULL);
+ if (!url_template) {
+ g_key_file_free(kf);
+ return NULL;
+ }
+
+ url_data = g_key_file_get_keys(kf, PH_INI_GROUP_URL_DATA, &len, NULL);
+ for (i = 0; i < len; i++) {
+ url_repl = ph_ini_get_value(kf, PH_INI_GROUP_URL_DATA, url_data[i], NULL);
+ old_template = url_template;
+ url_search = g_strdup_printf("${%s}", url_data[i]);
+ url_template = string_replace(url_template, url_search, url_repl);
+ g_free(url_repl);
+ g_free(url_search);
+ g_free(old_template);
+ }
+
+ phkf = g_malloc(sizeof(proto_help_key_file));
+ phkf->keyfile = kf;
+ phkf->source = ph_ini_get_value(kf, PH_INI_GROUP_GENERAL, PH_INI_KEY_SOURCE, "Unknown source");
+ phkf->url_template = url_template;
+
+ g_ptr_array_add(g_ph_key_files, phkf);
+
+ return phkf;
+}
+
+/** Fetch a value for a key from a key file with an optional default value.
+ *
+ * @param keyfile The key file to search
+ * @param group Key file group
+ * @param key Key file value to fetch
+ * @param alt Alternate string to return. May be NULL.
+ * @return const gchar* A newly-allocated key value, or a copy of alt if not found.
+ */
+static gchar*
+ph_ini_get_value(GKeyFile *keyfile, const gchar *group, const gchar *key, gchar *alt)
+{
+ gchar *value = NULL;
+
+ if (keyfile) {
+ value = g_key_file_get_string(keyfile, group, key, NULL);
+ }
+
+ if (!value) {
+ value = g_strdup(alt);
+ }
+
+ return value;
+}
+
+/** Given a protocol name and a key, map the protocol name to a section in the
+ * keyfile, then look up the value for that key.
+ *
+ * @param keyfile The key file to search
+ * @param protocol Wireshark protocol name to map, e.g. "tcp".
+ * @param keyword The key to fetch from the mapped section.
+ * @return
+ */
+static gchar*
+ph_ini_get_path(GKeyFile *keyfile, const gchar *protocol, const gchar *keyword)
+{
+ GError *error = NULL;
+ gchar *map;
+ gchar *value;
+
+ if(!keyfile || !protocol || !keyword) return NULL;
+
+ map = g_key_file_get_string(keyfile, PH_INI_GROUP_MAP, protocol, &error);
+
+ if(!map)
+ {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Protocol '%s' is not defined (%s)", protocol, error->message);
+ g_error_free(error);
+ return NULL;
+ }
+
+ value = g_key_file_get_string(keyfile, map, keyword, NULL);
+ g_free(map);
+ return value;
+}
+
+/** Given a protocol name, map it to a section in the keyfile, then
+ * return the keys in that section.
+ *
+ * @param keyfile The key file to search
+ * @param protocol Wireshark protocol name to map, e.g. "tcp".
+ * @return An array of keys in the mapped section. Must be freed with g_strfreev().
+ */
+static gchar**
+ph_ini_get_keywords(GKeyFile *keyfile, const gchar *protocol)
+{
+ GError *error = NULL;
+ gchar *map;
+ gchar **keys;
+ gsize length = 0;
+
+ if(!keyfile) return NULL;
+
+ map = g_key_file_get_string(keyfile, PH_INI_GROUP_MAP, protocol, &error);
+
+ if(!map)
+ {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Protocol '%s' is not defined (%s)", protocol, error->message);
+ g_error_free(error);
+ return NULL;
+ }
+
+ error = NULL;
+ keys = g_key_file_get_keys(keyfile, map, &length, &error);
+ g_free(map);
+
+ if(!keys)
+ {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "Display titles are not defined (%s)", protocol);
+ g_error_free(error);
+ }
+
+ return keys;
+}
+
+/**
+* Function ph_parse_string
+*
+* @param const gchar *description Description
+* @param const gchar *value Description
+* @return guint Description
+*/
+static guint ph_parse_string(const gchar *description, const gchar *value)
+{
+ GRegex *regex = NULL;
+ GMatchInfo *match_info = NULL;
+ gchar *pattern = NULL;
+ guint result = 0;
+
+ pattern = g_strdup_printf("(?tm_year + 1900, timestamp->tm_mon + 1, timestamp->tm_mday, timestamp->tm_hour, timestamp->tm_min, timestamp->tm_sec, type, message);
+ fputs(log, file);
+ fclose(file);
+ }
+}
+#endif
\ No newline at end of file
Index: gtk/proto_help.h
===================================================================
--- gtk/proto_help.h (revision 0)
+++ gtk/proto_help.h (revision 0)
@@ -0,0 +1,46 @@
+/* proto_help.h
+ * Routines for dynamic protocol help menus
+ *
+ * $Id: capture_dlg.c 32829 2010-05-16 08:14:29Z guy $
+ *
+ * Edgar Gladkich
+ * Gerald Combs
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/** Search for and read configuration files
+ *
+ */
+extern void proto_help_init(void);
+
+/** Initialize the menu
+ *
+ * @param widget Context menu root
+ * @return void
+ */
+extern void proto_help_menu_init(GtkWidget *);
+
+/** Fill in the protocol help menu
+ *
+ * @param selection Currently-selected packet
+ * @param cf Capture file
+ * @return void
+ */
+extern void proto_help_menu_modify(GtkTreeSelection*, capture_file *cfile);
Index: gtk/menus.c
===================================================================
--- gtk/menus.c (revision 32935)
+++ gtk/menus.c (working copy)
@@ -94,6 +94,7 @@
#include "gtk/uat_gui.h"
#include "gtk/gui_utils.h"
#include "gtk/manual_addr_resolv.h"
+#include "gtk/proto_help.h"
#ifdef NEW_PACKET_LIST
#include "gtk/new_packet_list.h"
@@ -1136,6 +1137,7 @@
0, "", WIRESHARK_STOCK_WIKI,},
{"/Filter Field Reference", NULL, GTK_MENU_FUNC(selected_ptree_ref_cb),
0, "", WIRESHARK_STOCK_INTERNET,},
+ {"/Protocol Help", NULL, NULL, 0, "", NULL,},
{"/Protocol Preferences", NULL, NULL, 0, NULL, NULL,},
{"/", NULL, NULL, 0, "", NULL,},
{"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "", WIRESHARK_STOCK_DECODE_AS,},
@@ -1328,9 +1330,11 @@
set_menus_for_capture_in_progress(FALSE);
set_menus_for_file_set(/* dialog */TRUE, /* previous file */ FALSE, /* next_file */ FALSE);
- /* init with an empty recent files list */
+ /* Init with an empty recent files list */
clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
+ /* Protocol help links */
+ proto_help_menu_init(tree_view_menu_factory->widget);
}
}
Index: gtk/Makefile.common
===================================================================
--- gtk/Makefile.common (revision 32935)
+++ gtk/Makefile.common (working copy)
@@ -108,6 +108,7 @@
profile_dlg.c \
progress_dlg.c \
proto_dlg.c \
+ proto_help.c \
proto_hier_stats_dlg.c \
range_utils.c \
recent.c \
@@ -296,6 +297,7 @@
prefs_stream.h \
profile_dlg.h \
proto_dlg.h \
+ proto_help.h \
proto_hier_stats_dlg.h \
range_utils.h \
recent.h \
Index: gtk/main.c
===================================================================
--- gtk/main.c (revision 32935)
+++ gtk/main.c (working copy)
@@ -157,6 +157,7 @@
#include "gtk/tap_dfilter_dlg.h"
#include "gtk/prefs_column.h"
#include "gtk/prefs_dlg.h"
+#include "gtk/proto_help.h"
#ifdef HAVE_LIBPCAP
#include "../image/wsicon16.xpm"
@@ -805,6 +806,7 @@
cf_unselect_field(&cfile);
packet_hex_print(byte_view, byte_data,
cfile.current_frame, NULL, byte_len);
+ proto_help_menu_modify(sel, &cfile);
return;
}
gtk_tree_model_get(model, &iter, 1, &finfo, -1);
@@ -868,6 +870,7 @@
}
packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
byte_len);
+ proto_help_menu_modify(sel, &cfile);
}
void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
@@ -2401,6 +2404,8 @@
rf_path, strerror(rf_open_errno));
}
+ proto_help_init();
+
cap_file_init(&cfile);
/* Fill in capture options with values from the preferences */
Index: epan/strutil.c
===================================================================
--- epan/strutil.c (revision 32935)
+++ epan/strutil.c (working copy)
@@ -1090,3 +1090,19 @@
return new_str;
}
+
+/* Create a newly-allocated string with replacement values. */
+gchar *string_replace(const gchar* str, const gchar *old_val, const gchar *new_val) {
+ gchar **str_parts;
+ gchar *new_str;
+
+ if (!str || !old_val) {
+ return NULL;
+ }
+
+ str_parts = g_strsplit(str, old_val, 0);
+ new_str = g_strjoinv(new_val, str_parts);
+ g_strfreev(str_parts);
+
+ return new_str;
+}
Index: epan/strutil.h
===================================================================
--- epan/strutil.h (revision 32935)
+++ epan/strutil.h (working copy)
@@ -244,4 +244,15 @@
*/
gchar* ws_strdup_unescape_underscore (const gchar *str);
+/** Replace values in a string
+ *
+ * @param str String containing 0 or more values to be replaced.
+ * @param old_val Old value.
+ * @param new_val New value. May be NULL, in which case occurences of
+ * old_value will be removed.
+ * @return A newly-allocated version of str with replacement values or
+ * NULL on failure.
+ */
+gchar *string_replace(const gchar* str, const gchar *old_val, const gchar *new_val);
+
#endif /* __STRUTIL_H__ */