wireshark/ui/gtk/about_dlg.c

629 lines
18 KiB
C
Raw Normal View History

/* about_dlg.c
*
* Ulf Lamping <ulf.lamping@web.de>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include <wsutil/filesystem.h>
#include <wsutil/copyright_info.h>
#include <ws_version_info.h>
#ifdef HAVE_LIBSMI
#include <epan/oids.h>
#endif
#ifdef HAVE_GEOIP
#include <epan/geoip_db.h>
#endif
#ifdef HAVE_LUA
#include <epan/wslua/init_wslua.h>
#endif
#ifdef HAVE_EXTCAP
#include "../../extcap.h"
#endif
#include "../../log.h"
#include "../../register.h"
#include "ui/last_open_dir.h"
#include "ui/gtk/about_dlg.h"
#include "ui/gtk/gui_utils.h"
#include "ui/gtk/dlg_utils.h"
#include "ui/gtk/file_dlg.h"
#include "ui/gtk/text_page_utils.h"
#include "ui/gtk/gtkglobals.h"
#include "ui/gtk/main.h"
#include "ui/gtk/plugins_dlg.h"
#include "ui/gtk/stock_icons.h"
#ifndef HAVE_GDK_GRESOURCE
#include "ui/gtk/pixbuf-csource.h"
#endif
#include "webbrowser.h"
/*
* Update frequence for the splash screen, given in milliseconds.
*/
int info_update_freq = 100;
static void about_wireshark_destroy_cb(GtkWidget *, gpointer);
/*
* Keep a static pointer to the current "About Wireshark" window, if any, so
* that if somebody tries to do "About Wireshark" while there's already an
* "About Wireshark" window up, we just pop up the existing one, rather than
* creating a new one.
*/
static GtkWidget *about_wireshark_w;
static void
about_wireshark(GtkWidget *parent _U_, GtkWidget *main_vb)
{
GtkWidget *msg_label, *icon;
gchar *message;
const char *title = "Network Protocol Analyzer";
/*icon = xpm_to_widget_from_parent(parent, wssplash_xpm);*/
#ifdef HAVE_GDK_GRESOURCE
icon = pixbuf_to_widget("/org/wireshark/image/wssplash_dev.png");
#else
icon = pixbuf_to_widget(wssplash_pb_data);
#endif
gtk_box_pack_start(GTK_BOX(main_vb), icon, TRUE, TRUE, 0);
msg_label = gtk_label_new(title);
message = g_strdup_printf("<span size=\"x-large\" weight=\"bold\">%s</span>", title);
gtk_label_set_markup(GTK_LABEL(msg_label), message);
g_free(message);
gtk_box_pack_start(GTK_BOX(main_vb), msg_label, TRUE, TRUE, 0);
}
static void
splash_update_label(GtkWidget *win, const char *message)
{
GtkWidget *main_lb;
if (win == NULL) return;
main_lb = (GtkWidget *)g_object_get_data(G_OBJECT(win), "splash_label");
gtk_label_set_text(GTK_LABEL(main_lb), message);
/* Process all pending GUI events before continuing, so that
the splash screen window gets updated. */
while (gtk_events_pending()) gtk_main_iteration();
}
GtkWidget*
splash_new(const char *message)
{
GtkWidget *win;
GtkWidget *main_lb;
GtkWidget *main_box;
GtkWidget *percentage_box;
GtkWidget *prog_bar;
GtkWidget *percentage_lb;
win = splash_window_new();
/* When calling about_wireshark(), we must realize the top-level
widget for the window, otherwise GTK will throw a warning
because we don't have a colormap associated with that window and
can't handle the pixmap. */
gtk_widget_realize(win);
main_box = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
gtk_container_set_border_width(GTK_CONTAINER(main_box), 24);
gtk_container_add(GTK_CONTAINER(win), main_box);
about_wireshark(win, main_box);
main_lb = gtk_label_new(message);
gtk_box_pack_start(GTK_BOX(main_box), main_lb, TRUE, TRUE, 0);
g_object_set_data(G_OBJECT(win), "splash_label", main_lb);
main_lb = gtk_label_new("");
gtk_box_pack_start(GTK_BOX(main_box), main_lb, TRUE, TRUE, 0);
g_object_set_data(G_OBJECT(win), "protocol_label", main_lb);
percentage_box = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1, FALSE);
gtk_box_pack_start(GTK_BOX(main_box), percentage_box, TRUE, TRUE, 3);
prog_bar = gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(percentage_box), prog_bar, TRUE, TRUE, 3);
g_object_set_data(G_OBJECT(win), "progress_bar", prog_bar);
percentage_lb = gtk_label_new(" 0%");
gtk_misc_set_alignment(GTK_MISC(percentage_lb), 0.0f, 0.0f);
gtk_box_pack_start(GTK_BOX(percentage_box), percentage_lb, FALSE, TRUE, 3);
g_object_set_data(G_OBJECT(win), "percentage_label", percentage_lb);
gtk_widget_show_all(win);
splash_update_label(win, message);
return win;
}
void
splash_update(register_action_e action, const char *message, gpointer client_data)
{
GtkWidget *win;
GtkWidget *main_lb;
GtkWidget *prog_bar;
GtkWidget *percentage_lb;
gfloat percentage;
gulong ul_percentage;
gchar tmp[100];
const char *action_msg;
static gulong ul_sofar = 0;
static gulong ul_count = 0;
static register_action_e last_action = RA_NONE;
static GTimeVal cur_tv;
static GTimeVal next_tv = {0, 0};
win = (GtkWidget *)client_data;
if (win == NULL) return;
g_get_current_time(&cur_tv);
if (last_action == action && cur_tv.tv_sec <= next_tv.tv_sec && cur_tv.tv_usec <= next_tv.tv_usec && ul_sofar < ul_count - 1) {
/* Only update every splash_register_freq milliseconds */
ul_sofar++;
return;
}
memcpy(&next_tv, &cur_tv, sizeof(next_tv));
next_tv.tv_usec += info_update_freq * 1000;
if (next_tv.tv_usec >= 1000000) {
next_tv.tv_sec++;
next_tv.tv_usec -= 1000000;
}
if(last_action != action) {
/* the action has changed */
switch(action) {
case RA_DISSECTORS:
action_msg = "Initializing dissectors ...";
break;
case RA_LISTENERS:
action_msg = "Initializing tap listeners ...";
break;
case RA_EXTCAP:
action_msg = "Initializing extcap ...";
break;
case RA_REGISTER:
action_msg = "Registering dissector ...";
break;
case RA_PLUGIN_REGISTER:
action_msg = "Registering plugins ...";
break;
case RA_HANDOFF:
action_msg = "Handing off dissector ...";
break;
case RA_PLUGIN_HANDOFF:
action_msg = "Handing off plugins ...";
break;
case RA_LUA_PLUGINS:
action_msg = "Loading Lua plugins ...";
break;
case RA_PREFERENCES:
action_msg = "Loading module preferences ...";
break;
case RA_INTERFACES:
action_msg = "Finding local interfaces ...";
break;
default:
action_msg = "(Unknown action)";
break;
}
splash_update_label(win, action_msg);
last_action = action;
}
if(ul_count == 0) { /* get the count of dissectors */
ul_count = register_count() + 6; /* additional 7 for:
dissectors, listeners,
registering plugins, handingoff plugins,
preferences, and interfaces */
#ifdef HAVE_LUA
ul_count += wslua_count_plugins (); /* get count of lua plugins */
#endif
#ifdef HAVE_EXTCAP
ul_count += extcap_count(); /* get count of extcap binaries */
#endif
}
main_lb = (GtkWidget *)g_object_get_data(G_OBJECT(win), "protocol_label");
/* make_dissector_reg.py changed -
so we need to strip off the leading elements to get back to the protocol */
if(message) {
if(!strncmp(message, "proto_register_", 15))
message += 15;
else if(!strncmp(message, "proto_reg_handoff_", 18))
message += 18;
}
gtk_label_set_text(GTK_LABEL(main_lb), message ? message : "");
ul_sofar++;
g_assert (ul_sofar <= ul_count);
percentage = (gfloat)ul_sofar/(gfloat)ul_count;
ul_percentage = (gulong)(percentage * 100);
/* update progress bar */
prog_bar = (GtkWidget *)g_object_get_data(G_OBJECT(win), "progress_bar");
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prog_bar), percentage);
percentage_lb = (GtkWidget *)g_object_get_data(G_OBJECT(win), "percentage_label");
g_snprintf(tmp, sizeof(tmp), "%lu%%", ul_percentage);
gtk_label_set_text((GtkLabel*)percentage_lb, tmp);
/* Process all pending GUI events before continuing, so that
the splash screen window gets updated. */
while (gtk_events_pending()) gtk_main_iteration();
}
gboolean
splash_destroy(GtkWidget *win)
{
if (win == NULL)
return FALSE;
gtk_widget_destroy(win);
return FALSE;
}
static GtkWidget *
about_wireshark_page_new(void)
{
GtkWidget *main_box, *msg_label /*, *icon*/;
gchar *message;
GString *comp_info_str, *runtime_info_str;
main_box = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
gtk_container_set_border_width(GTK_CONTAINER(main_box), 12);
g_object_set(gtk_widget_get_settings(main_box),
"gtk-label-select-on-focus", FALSE, NULL);
about_wireshark(top_level, main_box);
comp_info_str = get_compiled_version_info(get_wireshark_gtk_compiled_info,
get_gui_compiled_info);
runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
/* Construct the message string */
message = g_strdup_printf(
"Version %s\n"
"\n"
"%s"
"\n"
"%s"
"\n"
"%s"
"\n"
"Wireshark is Open Source Software released under the GNU General Public License.\n"
"\n"
"Check the man page and http://www.wireshark.org for more information.",
get_ws_vcs_version_info(), get_copyright_info(), comp_info_str->str,
runtime_info_str->str);
msg_label = gtk_label_new(message);
g_free(message);
gtk_label_set_justify(GTK_LABEL(msg_label), GTK_JUSTIFY_FILL);
gtk_label_set_selectable(GTK_LABEL(msg_label), TRUE);
gtk_box_pack_start(GTK_BOX (main_box), msg_label, TRUE, TRUE, 0);
return main_box;
}
static GtkWidget *
about_authors_page_new(void)
{
GtkWidget *page;
char *absolute_path;
absolute_path = get_datafile_path("AUTHORS-SHORT");
page = text_page_new(absolute_path);
return page;
}
static gboolean about_folders_callback(GtkWidget *widget, GdkEventButton *event, gint id _U_)
{
GtkTreeSelection *tree_selection;
GtkTreeModel *model;
GtkTreeIter iter;
gchar *path;
tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
if(gtk_tree_selection_count_selected_rows(tree_selection) == 0)
return FALSE;
if(event->type != GDK_2BUTTON_PRESS)
/* not a double click */
return FALSE;
if(gtk_tree_selection_get_selected (tree_selection, &model, &iter)) {
gtk_tree_model_get(model, &iter, 1, &path, -1);
filemanager_open_directory(path);
g_free(path);
}
return TRUE;
}
static void
about_folders_row(GtkWidget *table, const char *label, const char *dir, const char *tip)
{
simple_list_append(table, 0, label, 1, dir, 2, tip, -1);
}
static GtkWidget *
about_folders_page_new(void)
{
GtkWidget *table;
const char *constpath;
char *path;
static const gchar *titles[] = { "Name", "Folder", "Typical Files"};
GtkWidget *scrolledwindow;
#if defined(HAVE_LIBSMI) || defined(HAVE_GEOIP) || defined(HAVE_EXTCAP)
gint i;
gchar **resultArray;
#endif
#if 0
const gchar *const *dirs;
#endif
scrolledwindow = scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow),
GTK_SHADOW_IN);
/* Container for our data */
table = simple_list_new(3, titles);
/* connect a callback so we can spot a double-click */
g_signal_connect(table, "button_press_event",
G_CALLBACK(about_folders_callback), NULL);
simple_list_url_col(table, 1);
/* "file open" */
about_folders_row(table, "\"File\" dialogs", get_last_open_dir(),
"capture files");
/* temp */
about_folders_row(table, "Temp", g_get_tmp_dir(),
"untitled capture files");
/* pers conf */
path = get_persconffile_path("", FALSE);
about_folders_row(table, "Personal configuration", path,
"\"dfilters\", \"preferences\", \"ethers\", ...");
g_free(path);
/* global conf */
constpath = get_datafile_dir();
if (constpath != NULL) {
about_folders_row(table, "Global configuration", constpath,
"\"dfilters\", \"preferences\", \"manuf\", ...");
}
#if 0
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i]; i++){
g_warning("glibs data path %u %s",i+1,dirs[i]);
}
#endif
/* system */
constpath = get_systemfile_dir();
about_folders_row(table, "System", constpath,
"\"ethers\", \"ipxnets\"");
/* program */
constpath = get_progfile_dir();
about_folders_row(table, "Program", constpath,
"program files");
#if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
/* pers plugins */
path = get_plugins_pers_dir();
about_folders_row(table, "Personal Plugins", path,
"dissector plugins");
g_free(path);
/* global plugins */
about_folders_row(table, "Global Plugins", get_plugin_dir(),
"dissector plugins");
#endif
#ifdef HAVE_GEOIP
/* GeoIP */
path = geoip_db_get_paths();
resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10);
for(i = 0; resultArray[i]; i++)
about_folders_row(table, "GeoIP path", g_strstrip(resultArray[i]),
"GeoIP database search path");
g_strfreev(resultArray);
g_free(path);
#endif
#ifdef HAVE_LIBSMI
/* SMI MIBs/PIBs */
path = oid_get_default_mib_path();
resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10);
for(i = 0; resultArray[i]; i++)
about_folders_row(table, "MIB/PIB path", g_strstrip(resultArray[i]),
"SMI MIB/PIB search path");
g_strfreev(resultArray);
g_free(path);
#endif
Extcap Capture Interface Extcap is a plugin interface, which allows for the usage of external capture interfaces via pipes using a predefined configuration language which results in a graphical gui. This implementation seeks for a generic implementation, which results in a seamless integration with the current system, and does add all external interfaces as simple interfaces. Windows Note: Due to limitations with GTK and Windows, a gspawn-winXX-helper.exe, respective gspawn-winXX-helper-console.exe is needed, which is part of any GTK windows installation. The default installation directory from the build is an extcap subdirectory underneath the run directory. The folder used by extcap may be viewed in the folders tab of the about dialog. The default installation directory for extcap plugins with a pre-build or installer version of wireshark is the extcap subdirectory underneath the main wireshark directory. For more information see: http://youtu.be/Nn84T506SwU bug #9009 Also take a look in doc/extcap_example.py for a Python-example and in extcap.pod for the arguments grammer. Todo: - Integrate with Qt - currently no GUI is generated, but the interfaces are still usable Change-Id: I4f1239b2f1ebd8b2969f73af137915f5be1ce50f Signed-off-by: Mike Ryan <mikeryan+wireshark@lacklustre.net> Signed-off-by: Mike Kershaw <dragorn@kismetwireless.net> Signed-off-by: Roland Knall <rknall@gmail.com> Reviewed-on: https://code.wireshark.org/review/359 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
2014-02-25 13:05:11 +00:00
#ifdef HAVE_EXTCAP
/* extcap */
constpath = get_extcap_dir();
resultArray = g_strsplit(constpath, G_SEARCHPATH_SEPARATOR_S, 10);
for(i = 0; resultArray[i]; i++)
about_folders_row(table, "Extcap path", g_strstrip(resultArray[i]),
"Extcap Plugins search path");
Extcap Capture Interface Extcap is a plugin interface, which allows for the usage of external capture interfaces via pipes using a predefined configuration language which results in a graphical gui. This implementation seeks for a generic implementation, which results in a seamless integration with the current system, and does add all external interfaces as simple interfaces. Windows Note: Due to limitations with GTK and Windows, a gspawn-winXX-helper.exe, respective gspawn-winXX-helper-console.exe is needed, which is part of any GTK windows installation. The default installation directory from the build is an extcap subdirectory underneath the run directory. The folder used by extcap may be viewed in the folders tab of the about dialog. The default installation directory for extcap plugins with a pre-build or installer version of wireshark is the extcap subdirectory underneath the main wireshark directory. For more information see: http://youtu.be/Nn84T506SwU bug #9009 Also take a look in doc/extcap_example.py for a Python-example and in extcap.pod for the arguments grammer. Todo: - Integrate with Qt - currently no GUI is generated, but the interfaces are still usable Change-Id: I4f1239b2f1ebd8b2969f73af137915f5be1ce50f Signed-off-by: Mike Ryan <mikeryan+wireshark@lacklustre.net> Signed-off-by: Mike Kershaw <dragorn@kismetwireless.net> Signed-off-by: Roland Knall <rknall@gmail.com> Reviewed-on: https://code.wireshark.org/review/359 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
2014-02-25 13:05:11 +00:00
g_strfreev(resultArray);
#endif
gtk_container_add(GTK_CONTAINER(scrolledwindow), table);
return scrolledwindow;
}
static GtkWidget *
about_license_page_new(void)
{
GtkWidget *page;
char *absolute_path;
#if defined(_WIN32)
absolute_path = get_datafile_path("COPYING.txt");
#else
absolute_path = get_datafile_path("COPYING");
#endif
page = text_page_new(absolute_path);
return page;
}
void
about_wireshark_cb( GtkWidget *w _U_, gpointer data _U_ )
{
GtkWidget *main_box, *main_nb, *bbox, *ok_btn;
GtkWidget *page_lb, *about_page, *folders_page;
#if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
GtkWidget *plugins_page;
#endif
GtkWidget *authors_page, *license_page;
if (about_wireshark_w != NULL) {
/* There's already an "About Wireshark" dialog box; reactivate it. */
reactivate_window(about_wireshark_w);
return;
}
/*
* XXX - use GtkDialog? The GNOME 2.x GnomeAbout widget does.
* Should we use GtkDialog for simple_dialog() as well? Or
* is the GTK+ 2.x GtkDialog appropriate but the 1.2[.x] one
* not? (The GNOME 1.x GnomeAbout widget uses GnomeDialog.)
*/
about_wireshark_w = dlg_window_new("About Wireshark");
/* set the initial position (must be done, before show is called!) */
/* default position is not appropriate for the about dialog */
gtk_window_set_position(GTK_WINDOW(about_wireshark_w), GTK_WIN_POS_CENTER_ON_PARENT);
gtk_window_set_default_size(GTK_WINDOW(about_wireshark_w), 600, 400);
gtk_container_set_border_width(GTK_CONTAINER(about_wireshark_w), 6);
main_box = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 12, FALSE);
gtk_container_set_border_width(GTK_CONTAINER(main_box), 6);
gtk_container_add(GTK_CONTAINER(about_wireshark_w), main_box);
main_nb = gtk_notebook_new();
gtk_box_pack_start(GTK_BOX(main_box), main_nb, TRUE, TRUE, 0);
about_page = about_wireshark_page_new();
page_lb = gtk_label_new("Wireshark");
gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), about_page, page_lb);
authors_page = about_authors_page_new();
page_lb = gtk_label_new("Authors");
gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), authors_page, page_lb);
folders_page = about_folders_page_new();
page_lb = gtk_label_new("Folders");
gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), folders_page, page_lb);
#if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
plugins_page = about_plugins_page_new();
page_lb = gtk_label_new("Plugins");
gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), plugins_page, page_lb);
#endif
license_page = about_license_page_new();
page_lb = gtk_label_new("License");
/* set a minmum width to avoid a lot of line breaks at the wrong places */
gtk_widget_set_size_request(license_page, 600, -1);
gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), license_page, page_lb);
/* Button row */
bbox = dlg_button_row_new(GTK_STOCK_OK, NULL);
gtk_box_pack_start(GTK_BOX(main_box), bbox, FALSE, FALSE, 0);
ok_btn = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
gtk_widget_grab_focus(ok_btn);
gtk_widget_grab_default(ok_btn);
window_set_cancel_button(about_wireshark_w, ok_btn, window_cancel_button_cb);
g_signal_connect(about_wireshark_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
g_signal_connect(about_wireshark_w, "destroy", G_CALLBACK(about_wireshark_destroy_cb), NULL);
gtk_widget_show_all(about_wireshark_w);
window_present(about_wireshark_w);
}
static void
about_wireshark_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
{
/* Note that we no longer have an "About Wireshark" dialog box. */
about_wireshark_w = NULL;
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local Variables:
* c-basic-offset: 2
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=2 tabstop=8 expandtab:
* :indentSize=2:tabSize=8:noTabs=true:
*/