aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--color_filters.c21
-rw-r--r--color_filters.h3
-rw-r--r--disabled_protos.c7
-rw-r--r--docbook/user-guide.xml1
-rw-r--r--docbook/wsug_graphics/ws-gui-config-profiles.pngbin0 -> 28516 bytes
-rw-r--r--docbook/wsug_src/WSUG_chapter_customize.xml151
-rw-r--r--epan/addr_resolv.c8
-rw-r--r--epan/dissectors/packet-radius.c2
-rw-r--r--epan/dissectors/packet-xml.c2
-rw-r--r--epan/filesystem.c176
-rw-r--r--epan/filesystem.h55
-rw-r--r--epan/libwireshark.def10
-rw-r--r--epan/oids.c2
-rw-r--r--epan/plugins.c2
-rw-r--r--epan/prefs.c11
-rw-r--r--epan/prefs.h3
-rw-r--r--epan/proto.c17
-rw-r--r--epan/proto.h3
-rw-r--r--epan/uat.c14
-rw-r--r--epan/uat.h1
-rw-r--r--epan/wslua/init_wslua.c2
-rw-r--r--epan/wslua/wslua_util.c4
-rw-r--r--filters.c6
-rw-r--r--gtk/Makefile.am1
-rw-r--r--gtk/Makefile.common1
-rw-r--r--gtk/about_dlg.c2
-rw-r--r--gtk/help_dlg.c3
-rw-r--r--gtk/help_dlg.h1
-rw-r--r--gtk/main.c334
-rw-r--r--gtk/main.h11
-rw-r--r--gtk/menu.c4
-rw-r--r--gtk/profile_dlg.c791
-rw-r--r--gtk/profile_dlg.h41
-rw-r--r--gtk/recent.c37
-rw-r--r--gtk/recent.h3
-rw-r--r--tshark.c14
-rw-r--r--update.c2
37 files changed, 1587 insertions, 159 deletions
diff --git a/color_filters.c b/color_filters.c
index 239823ce0b..652dcb19a6 100644
--- a/color_filters.c
+++ b/color_filters.c
@@ -299,6 +299,23 @@ color_filters_init(void)
}
void
+color_filters_reload(void)
+{
+ /* "move" old entries to the deleted list
+ * we must keep them until the dissection no longer needs them */
+ color_filter_deleted_list = g_slist_concat(color_filter_deleted_list, color_filter_list);
+ color_filter_list = NULL;
+
+ /* start the list with the temporary colorizing rules */
+ color_filters_add_tmp(&color_filter_list);
+
+ /* try to read the users filters */
+ if (!read_users_filters(&color_filter_list))
+ /* if that failed, try to read the global filters */
+ color_filters_read_globals(&color_filter_list);
+}
+
+void
color_filters_cleanup(void)
{
/* delete the previously deleted filters */
@@ -612,7 +629,7 @@ read_users_filters(GSList **cfl)
gboolean ret;
/* decide what file to open (from dfilter code) */
- path = get_persconffile_path("colorfilters", FALSE);
+ path = get_persconffile_path("colorfilters", TRUE, FALSE);
if ((f = eth_fopen(path, "r")) == NULL) {
if (errno != ENOENT) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
@@ -737,7 +754,7 @@ color_filters_write(GSList *cfl)
return FALSE;
}
- path = get_persconffile_path("colorfilters", TRUE);
+ path = get_persconffile_path("colorfilters", TRUE, TRUE);
if ((f = eth_fopen(path, "w+")) == NULL) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Could not open\n%s\nfor writing: %s.",
diff --git a/color_filters.h b/color_filters.h
index df7846e636..a38e17c906 100644
--- a/color_filters.h
+++ b/color_filters.h
@@ -50,6 +50,9 @@ typedef struct _color_filter {
/** Init the color filters (incl. initial read from file). */
void color_filters_init(void);
+/** Reload the color filters */
+void color_filters_reload(void);
+
/** Cleanup remaining color filter zombies */
void color_filters_cleanup(void);
diff --git a/disabled_protos.c b/disabled_protos.c
index 8c08ea3714..7fd7775b5a 100644
--- a/disabled_protos.c
+++ b/disabled_protos.c
@@ -108,7 +108,7 @@ read_disabled_protos_list(char **gpath_return, int *gopen_errno_return,
}
/* Construct the pathname of the user's disabled protocols file. */
- ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, FALSE);
+ ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, FALSE);
/* Read the user's disabled protocols file, if it exists. */
*path_return = NULL;
@@ -319,7 +319,6 @@ void
save_disabled_protos_list(char **pref_path_return, int *errno_return)
{
gchar *ff_path, *ff_path_new;
- const gchar *ff_name;
FILE *ff;
gint i;
protocol_t *protocol;
@@ -327,9 +326,7 @@ save_disabled_protos_list(char **pref_path_return, int *errno_return)
*pref_path_return = NULL; /* assume no error */
- ff_name = PROTOCOLS_FILE_NAME;
-
- ff_path = get_persconffile_path(ff_name, TRUE);
+ ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, TRUE);
/* Write to "XXX.new", and rename if that succeeds.
That means we don't trash the file if we fail to write it out
diff --git a/docbook/user-guide.xml b/docbook/user-guide.xml
index 508e78700a..288e2a4579 100644
--- a/docbook/user-guide.xml
+++ b/docbook/user-guide.xml
@@ -178,6 +178,7 @@ FILE SECTION
<!ENTITY WiresharkGUIColumnsPreferences SYSTEM "./wsug_graphics/ws-gui-columns-preferences.png" NDATA PNG>
<!ENTITY WiresharkGUIFontPreferences SYSTEM "./wsug_graphics/ws-gui-font-preferences.png" NDATA PNG>
<!ENTITY WiresharkGUIColorsPreferences SYSTEM "./wsug_graphics/ws-gui-colors-preferences.png" NDATA PNG>
+ <!ENTITY WiresharkGUIConfigProfiles SYSTEM "./wsug_graphics/ws-gui-config-profiles.png" NDATA PNG>
<!ENTITY WiresharkCapturePreferences SYSTEM "./wsug_graphics/ws-capture-preferences.png" NDATA PNG>
<!ENTITY WiresharkPrintingPreferences SYSTEM "./wsug_graphics/ws-printing-preferences.png" NDATA PNG>
<!ENTITY WiresharkNameResolutionPreferences SYSTEM "./wsug_graphics/ws-nameresolution-preferences.png" NDATA PNG>
diff --git a/docbook/wsug_graphics/ws-gui-config-profiles.png b/docbook/wsug_graphics/ws-gui-config-profiles.png
new file mode 100644
index 0000000000..5619682866
--- /dev/null
+++ b/docbook/wsug_graphics/ws-gui-config-profiles.png
Binary files differ
diff --git a/docbook/wsug_src/WSUG_chapter_customize.xml b/docbook/wsug_src/WSUG_chapter_customize.xml
index cb7da8125b..101e271e03 100644
--- a/docbook/wsug_src/WSUG_chapter_customize.xml
+++ b/docbook/wsug_src/WSUG_chapter_customize.xml
@@ -929,6 +929,157 @@ standard libpcap format.
<graphic entityref="WiresharkGUIPreferences" format="PNG"/>
</figure>
</section>
+ <section id="ChCustConfigProfilesSection"><title>Configuration Profiles</title>
+ <para>
+ Configuration Profiles can be used to configure and use more than one set of preferences
+ and configurations. Select the <command>Configuration Profiles...</command> menu item from
+ the <command>Edit</command> menu, or simply press Shift-Ctrl-A; and Wireshark will pop up the
+ Configuration Profiles dialog box as shown in <xref linked="ChCustGUIConfigProfilesPage"/>.
+ </para>
+ <para>
+ Configuration files stored in the Profiles:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Preferences (preferences)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Capture Filters (cfilters)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Display Filters (dfilters)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Coloring Rules (colorfilters)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Disabled Protocols (disabled_protos)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ User Accessible Tables:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Display Filter Macros (dfilter_macros)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ K12 Protocols (k12_protos)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ SCCP Users Table (sccp_users)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ SMI Modules (smi_modules)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ SMI Paths (smi_paths)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ SNMP Users (snmp_users)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ User DLTs Table (user_dlts)
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <note><title>Note!</title>
+ <para>
+ All other configurations are stored in the personal configuration folder,
+ and are common to all profiles.
+ </para>
+ </note>
+ </para>
+ <figure id="ChCustGUIConfigProfilesPage">
+ <title>The configuration profiles dialog box</title>
+ <graphic entityref="WiresharkGUIConfigProfiles" format="PNG"/>
+ </figure>
+ <para>
+ <variablelist>
+ <varlistentry><term><command>New</command></term>
+ <listitem>
+ <para>
+ This button adds a new profile to the profiles list.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><command>Delete</command></term>
+ <listitem>
+ <para>
+ This button deletes the selected profile.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><command>Configuration Profiles</command></term>
+ <listitem>
+ <para>
+ You can select a configuration profile from this list (which will fill
+ in the profile name in the fields down at the bottom of the dialog box).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><command>Profile name:</command></term>
+ <listitem>
+ <para>
+ You can change the name of the currently selected profile here.
+ </para>
+ <note><title>Note!</title>
+ <para>
+ The profile name will be used as a folder name in the configured
+ "Personal configurations" folder. If adding multiple profiles with the
+ same name, only one profile will be created.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><command>OK</command></term>
+ <listitem>
+ <para>
+ This button saves all changes, applies the selected profile and closes the dialog.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><command>Apply</command></term>
+ <listitem>
+ <para>
+ This button saves all changes, applies the selected profile and keeps the dialog open.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><command>Cancel</command></term>
+ <listitem>
+ <para>
+ Close this dialog. This will discard unsaved settings.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </section>
<section id="ChUserTable"><title>User Table</title>
<para>
The User Table editor is used for managing various tables in wireshark. Its main dialog works
diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c
index f38ae2b5ed..1fc7c45fc6 100644
--- a/epan/addr_resolv.c
+++ b/epan/addr_resolv.c
@@ -444,7 +444,7 @@ static void initialize_services(void)
/* set personal services path */
if (g_pservices_path == NULL)
- g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE);
+ g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE, FALSE);
parse_services_file(g_pservices_path);
@@ -1194,7 +1194,7 @@ static void initialize_ethers(void)
* with it. It's used in get_ethbyname() and get_ethbyaddr()
*/
if (g_pethers_path == NULL)
- g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
+ g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE, FALSE);
/* manuf hash table initialization */
@@ -1587,7 +1587,7 @@ static void initialize_ipxnets(void)
* with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
*/
if (g_pipxnets_path == NULL)
- g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
+ g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE, FALSE);
} /* initialize_ipxnets */
@@ -1784,7 +1784,7 @@ host_name_lookup_init(void) {
/*
* Load the user's hosts file, if they have one.
*/
- hostspath = get_persconffile_path(ENAME_HOSTS, FALSE);
+ hostspath = get_persconffile_path(ENAME_HOSTS, FALSE, FALSE);
if (!read_hosts_file(hostspath) && errno != ENOENT) {
report_open_failure(hostspath, errno, FALSE);
}
diff --git a/epan/dissectors/packet-radius.c b/epan/dissectors/packet-radius.c
index df590fe13a..5a149d970f 100644
--- a/epan/dissectors/packet-radius.c
+++ b/epan/dissectors/packet-radius.c
@@ -1527,7 +1527,7 @@ proto_register_radius(void)
g_array_append_vals(ri.hf, base_hf, array_length(base_hf));
g_array_append_vals(ri.ett, base_ett, array_length(base_ett));
- dir = get_persconffile_path("radius", FALSE);
+ dir = get_persconffile_path("radius", FALSE, FALSE);
if (test_for_directory(dir) != EISDIR) {
/* Although dir isn't a directory it may still use memory */
diff --git a/epan/dissectors/packet-xml.c b/epan/dissectors/packet-xml.c
index f204b5ec15..13ec0c58ad 100644
--- a/epan/dissectors/packet-xml.c
+++ b/epan/dissectors/packet-xml.c
@@ -1139,7 +1139,7 @@ static void init_xml_names(void) {
xmlpi_xml_ns->elements = NULL;
- dirname = get_persconffile_path("dtds", FALSE);
+ dirname = get_persconffile_path("dtds", FALSE, FALSE);
if (test_for_directory(dirname) != EISDIR) {
/* Although dir isn't a directory it may still use memory */
diff --git a/epan/filesystem.c b/epan/filesystem.c
index f58e1e32f1..cbb9695aca 100644
--- a/epan/filesystem.c
+++ b/epan/filesystem.c
@@ -55,10 +55,12 @@
#include "privileges.h"
#include <wiretap/file_util.h>
+#define PROFILES_DIR "profiles"
#define U3_MY_CAPTURES "\\My Captures"
char *persconffile_dir = NULL;
char *persdatafile_dir = NULL;
+char *persconfprofile = NULL;
/*
* Given a pathname, return a pointer to the last pathname separator
@@ -780,6 +782,27 @@ char *getenv_utf8(const char *varname)
}
#endif
+void
+set_profile_name(const gchar *profilename)
+{
+ if (persconfprofile) {
+ g_free (persconfprofile);
+ }
+
+ if (profilename && strlen(profilename) > 0) {
+ persconfprofile = g_strdup (profilename);
+ } else {
+ /* Default Profile */
+ persconfprofile = NULL;
+ }
+}
+
+const char *
+get_profile_name(void)
+{
+ return persconfprofile;
+}
+
/*
* Get the directory in which personal configuration files reside;
* in UNIX-compatible systems, it's ".wireshark", under the user's home
@@ -788,7 +811,7 @@ char *getenv_utf8(const char *varname)
* (which is what %APPDATA% normally is on Windows 2000).
*/
static const char *
-get_persconffile_dir(void)
+get_persconffile_dir_no_profile(void)
{
#ifdef _WIN32
char *appdatadir;
@@ -828,7 +851,7 @@ get_persconffile_dir(void)
* Concatenate %APPDATA% with "\Wireshark".
*/
persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
- appdatadir, PF_DIR);
+ appdatadir, PF_DIR);
} else {
/*
* OK, %APPDATA% wasn't set, so use
@@ -874,6 +897,119 @@ get_persconffile_dir(void)
return persconffile_dir;
}
+const char *
+get_profiles_dir(void)
+{
+ static char *profiles_dir = NULL;
+
+ if (profiles_dir) {
+ g_free (profiles_dir);
+ }
+
+ profiles_dir = g_strdup_printf ("%s%s%s", get_persconffile_dir_no_profile (),
+ G_DIR_SEPARATOR_S, PROFILES_DIR);
+
+ return profiles_dir;
+}
+
+static const char *
+get_persconffile_dir(const gchar *profilename)
+{
+ static char *persconffile_profile_dir = NULL;
+
+ if (persconffile_profile_dir) {
+ g_free (persconffile_profile_dir);
+ }
+
+ if (profilename) {
+ persconffile_profile_dir = g_strdup_printf ("%s%s%s", get_profiles_dir (), G_DIR_SEPARATOR_S,
+ profilename);
+ } else {
+ persconffile_profile_dir = g_strdup_printf (get_persconffile_dir_no_profile ());
+ }
+
+ return persconffile_profile_dir;
+}
+
+gboolean
+profile_exists(const gchar *profilename)
+{
+ if (test_for_directory (get_persconffile_dir (profilename)) == EISDIR) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int
+delete_directory (const char *directory, char **pf_dir_path_return)
+{
+ ETH_DIR *dir;
+ ETH_DIRENT *file;
+ gchar *filename;
+ int ret = 0;
+
+ if ((dir = eth_dir_open(directory, 0, NULL)) != NULL) {
+ while ((file = eth_dir_read_name(dir)) != NULL) {
+ filename = g_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S, eth_dir_get_name(file));
+ if (test_for_directory(filename) != EISDIR) {
+ ret = eth_remove(filename);
+#if 0
+ } else {
+ /* The user has manually created a directory in the profile directory */
+ /* I do not want to delete the directory recursively yet */
+ ret = delete_directory (filename, pf_dir_path_return);
+#endif
+ }
+ if (ret != 0) {
+ *pf_dir_path_return = filename;
+ break;
+ }
+ g_free (filename);
+ }
+ eth_dir_close(dir);
+ }
+
+ if (ret == 0 && (ret = eth_remove(directory)) != 0) {
+ *pf_dir_path_return = g_strdup (directory);
+ }
+
+ return ret;
+}
+
+int
+delete_persconffile_profile(const char *profilename, char **pf_dir_path_return)
+{
+ const char *profile_dir = get_persconffile_dir(profilename);
+ int ret = 0;
+
+ if (test_for_directory (profile_dir) == EISDIR) {
+ ret = delete_directory (profile_dir, pf_dir_path_return);
+ }
+
+ return ret;
+}
+
+int
+rename_persconffile_profile(const char *fromname, const char *toname,
+ char **pf_from_dir_path_return, char **pf_to_dir_path_return)
+{
+ char *from_dir = g_strdup (get_persconffile_dir(fromname));
+ char *to_dir = g_strdup (get_persconffile_dir(toname));
+ int ret = 0;
+
+ ret = eth_rename (from_dir, to_dir);
+ if (ret != 0) {
+ *pf_from_dir_path_return = g_strdup (from_dir);
+ *pf_to_dir_path_return = g_strdup (to_dir);
+ }
+
+ g_free (from_dir);
+ g_free (to_dir);
+
+ return ret;
+}
+
/*
* Create the directory that holds personal configuration files, if
* necessary. If we attempted to create it, and failed, return -1 and
@@ -882,7 +1018,7 @@ get_persconffile_dir(void)
* return 0.
*/
int
-create_persconffile_dir(char **pf_dir_path_return)
+create_persconffile_profile(const char *profilename, char **pf_dir_path_return)
{
const char *pf_dir_path;
#ifdef _WIN32
@@ -891,8 +1027,23 @@ create_persconffile_dir(char **pf_dir_path_return)
#endif
struct stat s_buf;
int ret;
+
+ if (profilename) {
+ /*
+ * Check if profiles directory exists.
+ * If not then create it.
+ */
+ pf_dir_path = get_profiles_dir ();
+ if (eth_stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
+ ret = eth_mkdir(pf_dir_path, 0755);
+ if (ret == -1) {
+ *pf_dir_path_return = g_strdup(pf_dir_path);
+ return ret;
+ }
+ }
+ }
- pf_dir_path = get_persconffile_dir();
+ pf_dir_path = get_persconffile_dir(profilename);
if (eth_stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
#ifdef _WIN32
/*
@@ -940,6 +1091,12 @@ create_persconffile_dir(char **pf_dir_path_return)
return ret;
}
+int
+create_persconffile_dir(char **pf_dir_path_return)
+{
+ return create_persconffile_profile(get_profile_name(), pf_dir_path_return);
+}
+
/*
* Get the (default) directory in which personal data is stored.
*
@@ -1065,7 +1222,7 @@ get_home_dir(void)
* from earlier versions can be read.
*/
char *
-get_persconffile_path(const char *filename, gboolean for_writing
+get_persconffile_path(const char *filename, gboolean from_profile, gboolean for_writing
#ifndef _WIN32
_U_
#endif
@@ -1077,8 +1234,13 @@ get_persconffile_path(const char *filename, gboolean for_writing
char *old_path;
#endif
- path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", get_persconffile_dir(),
- filename);
+ if (from_profile) {
+ path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ get_persconffile_dir(get_profile_name()), filename);
+ } else {
+ path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ get_persconffile_dir(NULL), filename);
+ }
#ifdef _WIN32
if (!for_writing) {
if (eth_stat(path, &s_buf) != 0 && errno == ENOENT) {
diff --git a/epan/filesystem.h b/epan/filesystem.h
index d667ea4b68..9a762c18fc 100644
--- a/epan/filesystem.h
+++ b/epan/filesystem.h
@@ -71,6 +71,55 @@ extern char *get_datafile_path(const char *filename);
extern const char *get_systemfile_dir(void);
/*
+ * Set the configuration profile name to be used for storing
+ * personal configuration files.
+ */
+extern void set_profile_name(const gchar *profilename);
+
+/*
+ * Get the current configuration profile name used for storing
+ * personal configuration files.
+ */
+extern const char *get_profile_name(void);
+
+/*
+ * Get the directory used to store configuration profile directories.
+ */
+extern const char *get_profiles_dir(void);
+
+/*
+ * Check if given configuration profile exists.
+ */
+extern gboolean profile_exists(const gchar *profilename);
+
+/*
+ * Create a directory for the given configuration profile.
+ * If we attempted to create it, and failed, return -1 and
+ * set "*pf_dir_path_return" to the pathname of the directory we failed
+ * to create (it's g_mallocated, so our caller should free it); otherwise,
+ * return 0.
+ */
+extern int create_persconffile_profile(const char *profilename,
+ char **pf_dir_path_return);
+
+/*
+ * Delete the directory for the given configuration profile.
+ * If we attempted to delete it, and failed, return -1 and
+ * set "*pf_dir_path_return" to the pathname of the directory we failed
+ * to delete (it's g_mallocated, so our caller should free it); otherwise,
+ * return 0.
+ */
+extern int delete_persconffile_profile(const char *profilename,
+ char **pf_dir_path_return);
+
+/*
+ * Rename the directory for the given confinguration profile.
+ */
+extern int rename_persconffile_profile(const char *fromname, const char *toname,
+ char **pf_from_dir_path_return,
+ char **pf_to_dir_path_return);
+
+/*
* Create the directory that holds personal configuration files, if
* necessary. If we attempted to create it, and failed, return -1 and
* set "*pf_dir_path_return" to the pathname of the directory we failed
@@ -81,7 +130,8 @@ extern int create_persconffile_dir(char **pf_dir_path_return);
/*
* Construct the path name of a personal configuration file, given the
- * file name.
+ * file name. If using configuration profiles this directory will be
+ * used if "from_profile" is TRUE.
*
* On Win32, if "for_writing" is FALSE, we check whether the file exists
* and, if not, construct a path name relative to the ".wireshark"
@@ -89,7 +139,8 @@ extern int create_persconffile_dir(char **pf_dir_path_return);
* exists; if it does, we return that, so that configuration files
* from earlier versions can be read.
*/
-extern char *get_persconffile_path(const char *filename, gboolean for_writing);
+extern char *get_persconffile_path(const char *filename, gboolean from_profile,
+ gboolean for_writing);
/*
* Get the (default) directory in which personal data is stored.
diff --git a/epan/libwireshark.def b/epan/libwireshark.def
index 6af119b5b3..0fd22c7342 100644
--- a/epan/libwireshark.def
+++ b/epan/libwireshark.def
@@ -99,6 +99,7 @@ copy_prefs
crc16_ccitt_tvb
create_dissector_handle
create_persconffile_dir
+create_persconffile_profile
data_out_file DATA
dcerpc_add_conv_to_bind_table
dcerpc_get_proto_hf_opnum
@@ -117,6 +118,7 @@ decode_boolean_bitfield
decode_enumerated_bitfield_shifted
decode_enumerated_bitfield
decode_numeric_bitfield
+delete_persconffile_profile
deletefile
dfilter_apply_edt
dfilter_compile
@@ -437,6 +439,8 @@ get_persconffile_path
get_persdatafile_dir
get_plugin_dir
get_plugins_pers_dir
+get_profile_name
+get_profiles_dir
get_progfile_dir
get_rose_ctx
get_systemfile_dir
@@ -572,14 +576,17 @@ prefs_register_static_text_preference
prefs_register_string_preference
prefs_register_uat_preference
prefs_register_uint_preference
+prefs_reset
prefs_set_pref
process_reassembled_data
process_stat_cmd_arg
+profile_exists
proto_all_finfos
proto_can_match_selected
proto_can_toggle_protocol
proto_construct_match_selected_string
proto_data DATA
+proto_enable_all
proto_find_field_from_offset
proto_find_finfo
proto_frame DATA
@@ -730,6 +737,7 @@ rel_time_to_secs_str
rel_time_to_str
relinquish_special_privs_perm
remove_tap_listener
+rename_persconffile_profile
report_failure
report_open_failure
report_read_failure
@@ -770,6 +778,7 @@ se_strndup
se_tree_create
se_tree_create_non_persistent
set_actual_length
+set_profile_name
show_fragment_seq_tree
show_fragment_tree
sid_name_snooping DATA
@@ -923,6 +932,7 @@ uat_fld_chk_str_isxdigit
uat_foreach_table
uat_load
uat_new
+uat_reload_all
uat_remove_record_idx
uat_save
uat_swap
diff --git a/epan/oids.c b/epan/oids.c
index a8354e91d3..9951eda752 100644
--- a/epan/oids.c
+++ b/epan/oids.c
@@ -454,7 +454,7 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
#ifdef WIN32
#define PATH_SEPARATOR ";"
#define DEFAULT_PATH_FMT "%s;%s"
-#define DEFAULT_PATH_ARGS get_datafile_path("snmp\\mibs"), get_persconffile_path("snmp\\mibs", FALSE)
+#define DEFAULT_PATH_ARGS get_datafile_path("snmp\\mibs"), get_persconffile_path("snmp\\mibs", FALSE, FALSE)
#else
#define PATH_SEPARATOR ":"
#define DEFAULT_PATH_FMT "%s"
diff --git a/epan/plugins.c b/epan/plugins.c
index 68031b5be2..9e7cc17edc 100644
--- a/epan/plugins.c
+++ b/epan/plugins.c
@@ -371,7 +371,7 @@ plugins_scan_dir(const char *dirname)
/* Return value is malloced so the caller should g_free() it. */
char *get_plugins_pers_dir(void)
{
- return get_persconffile_path(PLUGINS_DIR_NAME, FALSE);
+ return get_persconffile_path(PLUGINS_DIR_NAME, FALSE, FALSE);
}
/*
diff --git a/epan/prefs.c b/epan/prefs.c
index b070f0a65e..c948588587 100644
--- a/epan/prefs.c
+++ b/epan/prefs.c
@@ -1221,6 +1221,13 @@ init_prefs(void) {
prefs_initialized = TRUE;
}
+/* Reset preferences */
+void
+prefs_reset(void)
+{
+ prefs_initialized = FALSE;
+ init_prefs();
+}
/* Read the preferences file, fill in "prefs", and return a pointer to it.
@@ -1305,7 +1312,7 @@ read_prefs(int *gpf_errno_return, int *gpf_read_errno_return,
}
/* Construct the pathname of the user's preferences file. */
- pf_path = get_persconffile_path(PF_NAME, FALSE);
+ pf_path = get_persconffile_path(PF_NAME, TRUE, FALSE);
/* Read the user's preferences file, if it exists. */
*pf_path_return = NULL;
@@ -2440,7 +2447,7 @@ write_prefs(char **pf_path_return)
*/
if (pf_path_return != NULL) {
- pf_path = get_persconffile_path(PF_NAME, TRUE);
+ pf_path = get_persconffile_path(PF_NAME, TRUE, TRUE);
if ((pf = eth_fopen(pf_path, "w")) == NULL) {
*pf_path_return = pf_path;
return errno;
diff --git a/epan/prefs.h b/epan/prefs.h
index c67b4fe07a..c01c714015 100644
--- a/epan/prefs.h
+++ b/epan/prefs.h
@@ -169,6 +169,9 @@ typedef struct pref_module module_t;
/** Sets up memory used by proto routines. Called at program startup */
extern void prefs_init(void);
+/** Reset preferences to default values. Called at profile change */
+extern void prefs_reset(void);
+
/** Frees memory used by proto routines. Called at program shutdown */
extern void prefs_cleanup(void);
diff --git a/epan/proto.c b/epan/proto.c
index e04807e533..ca109808e8 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -3731,6 +3731,23 @@ proto_set_decoding(int proto_id, gboolean enabled)
}
void
+proto_enable_all(void)
+{
+ protocol_t *protocol;
+ GList *list_item = protocols;
+
+ if (protocols == NULL)
+ return;
+
+ while (list_item) {
+ protocol = list_item->data;
+ if (protocol->can_toggle)
+ protocol->is_enabled = TRUE;
+ list_item = g_list_next(list_item);
+ }
+}
+
+void
proto_set_cant_toggle(int proto_id)
{
protocol_t *protocol;
diff --git a/epan/proto.h b/epan/proto.h
index 0af704c2a5..2be5a3a055 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -1507,6 +1507,9 @@ extern const char *proto_get_protocol_filter_name(int proto_id);
@param enabled enable / disable the protocol */
extern void proto_set_decoding(int proto_id, gboolean enabled);
+/** Enable all protocols */
+extern void proto_enable_all(void);
+
/** Disable disabling/enabling of protocol of the given item number.
@param proto_id protocol id (0-indexed) */
extern void proto_set_cant_toggle(int proto_id);
diff --git a/epan/uat.c b/epan/uat.c
index b745c759d9..49c59dd873 100644
--- a/epan/uat.c
+++ b/epan/uat.c
@@ -155,7 +155,7 @@ void uat_remove_record_idx(uat_t* uat, guint idx) {
}
gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
- gchar* pers_fname = get_persconffile_path(uat->filename,for_writing);
+ gchar* pers_fname = get_persconffile_path(uat->filename, TRUE, for_writing);
if (! for_writing ) {
gchar* data_fname = get_datafile_path(uat->filename);
@@ -285,6 +285,18 @@ void* uat_se_dup(uat_t* uat, guint* len_p) {
return size ? se_memdup(uat->user_data->data,size) : NULL ;
}
+void uat_reload_all(void) {
+ guint i;
+
+ for (i=0; i < all_uats->len; i++) {
+ uat_t* u = g_ptr_array_index(all_uats,i);
+ uat_clear(u);
+ u->loaded = FALSE;
+ }
+
+ uat_load_all();
+}
+
void uat_cleanup(void) {
while( all_uats->len ) {
uat_destroy((uat_t*)all_uats->pdata);
diff --git a/epan/uat.h b/epan/uat.h
index 6f095d80a6..15d5796ad0 100644
--- a/epan/uat.h
+++ b/epan/uat.h
@@ -269,6 +269,7 @@ gboolean uat_fld_chk_str_ ## what (void*, const char*, unsigned, void*, void*, c
typedef void (*uat_cb_t)(void* uat,void* user_data);
void uat_foreach_table(uat_cb_t cb,void* user_data);
+void uat_reload_all(void);
char* uat_undquote(const char* si, guint in_len, guint* len_p);
char* uat_unbinstring(const char* si, guint in_len, guint* len_p);
diff --git a/epan/wslua/init_wslua.c b/epan/wslua/init_wslua.c
index ebf4cf22c2..a0cba1cb5d 100644
--- a/epan/wslua/init_wslua.c
+++ b/epan/wslua/init_wslua.c
@@ -296,7 +296,7 @@ int wslua_init(lua_State* LS) {
/* if we are indeed superuser run user scripts only if told to do so */
if ( (!started_with_special_privs()) || run_anyway ) {
- filename = get_persconffile_path("init.lua", FALSE);
+ filename = get_persconffile_path("init.lua", FALSE, FALSE);
if (( file_exists(filename))) {
lua_load_script(filename);
diff --git a/epan/wslua/wslua_util.c b/epan/wslua/wslua_util.c
index 4d28c0044e..b870b001c8 100644
--- a/epan/wslua/wslua_util.c
+++ b/epan/wslua/wslua_util.c
@@ -165,7 +165,7 @@ const char* wslua_get_actual_filename(const char* fname) {
return fname_clean;
}
- filename = get_persconffile_path(fname_clean,FALSE);
+ filename = get_persconffile_path(fname_clean,FALSE,FALSE);
if ( file_exists(filename) ) {
return filename;
@@ -220,7 +220,7 @@ WSLUA_FUNCTION wslua_dofile(lua_State* L) {
WSLUA_FUNCTION wslua_persconffile_path(lua_State* L) {
#define WSLUA_OPTARG_persconffile_path_FILENAME 1 /* a filename */
const char *fname = luaL_optstring(L, WSLUA_OPTARG_persconffile_path_FILENAME,"");
- const char* filename = get_persconffile_path(fname,FALSE);
+ const char* filename = get_persconffile_path(fname,FALSE,FALSE);
lua_pushstring(L,filename);
WSLUA_RETURN(1); /* the full pathname for a file in the personal configuration directory */
diff --git a/filters.c b/filters.c
index e8c22d1c3a..71d177135b 100644
--- a/filters.c
+++ b/filters.c
@@ -145,7 +145,7 @@ read_filter_list(filter_list_type_t list_type, char **pref_path_return,
}
/* try to open personal "cfilters"/"dfilters" file */
- ff_path = get_persconffile_path(ff_name, FALSE);
+ ff_path = get_persconffile_path(ff_name, TRUE, FALSE);
if ((ff = eth_fopen(ff_path, "r")) == NULL) {
/*
* Did that fail because the file didn't exist?
@@ -168,7 +168,7 @@ read_filter_list(filter_list_type_t list_type, char **pref_path_return,
* a particular list.
*/
g_free(ff_path);
- ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE);
+ ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE, FALSE);
if ((ff = eth_fopen(ff_path, "r")) == NULL) {
/*
* Did that fail because the file didn't exist?
@@ -487,7 +487,7 @@ save_filter_list(filter_list_type_t list_type, char **pref_path_return,
return;
}
- ff_path = get_persconffile_path(ff_name, TRUE);
+ ff_path = get_persconffile_path(ff_name, TRUE, TRUE);
/* Write to "XXX.new", and rename if that succeeds.
That means we don't trash the file if we fail to write it out
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index f9e2c878a0..8d997dc255 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -98,6 +98,7 @@ noinst_HEADERS = \
plugins_dlg.h \
prefs_dlg.h \
print_prefs.h \
+ profile_dlg.h \
proto_dlg.h \
proto_draw.h \
proto_hier_stats_dlg.h \
diff --git a/gtk/Makefile.common b/gtk/Makefile.common
index 4f7abf58ec..7f3aeb19ac 100644
--- a/gtk/Makefile.common
+++ b/gtk/Makefile.common
@@ -96,6 +96,7 @@ WIRESHARK_GTK_SRC = \
prefs_dlg.c \
print_dlg.c \
print_prefs.c \
+ profile_dlg.c \
progress_dlg.c \
proto_dlg.c \
proto_draw.c \
diff --git a/gtk/about_dlg.c b/gtk/about_dlg.c
index 1ef9c0ac7d..9bb1e890f1 100644
--- a/gtk/about_dlg.c
+++ b/gtk/about_dlg.c
@@ -369,7 +369,7 @@ about_folders_page_new(void)
g_free((void *) path);
/* pers conf */
- path = get_persconffile_path("", FALSE);
+ path = get_persconffile_path("", FALSE, FALSE);
about_folders_row(table, "Personal configuration", path,
"\"dfilters\", \"preferences\", \"ethers\", ...");
g_free((void *) path);
diff --git a/gtk/help_dlg.c b/gtk/help_dlg.c
index ecf1009108..223aaa5c3c 100644
--- a/gtk/help_dlg.c
+++ b/gtk/help_dlg.c
@@ -410,6 +410,9 @@ topic_action(topic_action_e action)
case(HELP_COLORING_RULES_DIALOG):
help_topic_html("ChCustColorizationSection.html");
break;
+ case(HELP_CONFIG_PROFILES_DIALOG):
+ help_topic_html("ChCustConfigProfilesSection.html");
+ break;
case(HELP_PRINT_DIALOG):
help_topic_html("ChIOPrintSection.html");
break;
diff --git a/gtk/help_dlg.h b/gtk/help_dlg.h
index e19ed45db9..fd9ef88ae7 100644
--- a/gtk/help_dlg.h
+++ b/gtk/help_dlg.h
@@ -57,6 +57,7 @@ typedef enum {
HELP_CAPTURE_FILTERS_DIALOG,
HELP_DISPLAY_FILTERS_DIALOG,
HELP_COLORING_RULES_DIALOG,
+ HELP_CONFIG_PROFILES_DIALOG,
HELP_PRINT_DIALOG,
HELP_FIND_DIALOG,
HELP_FILESET_DIALOG,
diff --git a/gtk/main.c b/gtk/main.c
index e6e8113026..3b4fba7109 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -98,6 +98,7 @@
#include "merge.h"
#include "u3.h"
#include "uat_gui.h"
+#include "epan/uat.h"
#ifdef HAVE_LIBPCAP
@@ -210,7 +211,7 @@ GtkWidget *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
GtkWidget *pkt_scrollw;
static GtkWidget *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
static GtkWidget *main_first_pane, *main_second_pane;
-static GtkWidget *status_pane;
+static GtkWidget *status_pane_left, *status_pane_right;
static GtkWidget *menubar, *main_vbox, *main_tb, *stat_hbox, *filter_tb;
static GtkWidget *priv_warning_dialog;
@@ -222,10 +223,13 @@ static int airpcap_dll_ret_val = -1;
static GtkWidget *info_bar;
static GtkWidget *packets_bar = NULL;
+static GtkWidget *profile_bar = NULL;
static GtkWidget *welcome_pane;
static guint main_ctx, file_ctx, help_ctx;
static guint packets_ctx;
+static guint profile_ctx;
static gchar *packets_str = NULL;
+static gchar *profile_str = NULL;
GString *comp_info_str, *runtime_info_str;
gboolean have_capture_file = FALSE; /* XXX - is there an aquivalent in cfile? */
@@ -1033,6 +1037,29 @@ void packets_bar_update(void)
}
}
+/*
+ * update the packets statusbar to the current values
+ */
+void profile_bar_update(void)
+{
+ const char *profile_name;
+ if (profile_bar) {
+ /* remove old status */
+ if(profile_str) {
+ g_free(profile_str);
+ gtk_statusbar_pop(GTK_STATUSBAR(profile_bar), profile_ctx);
+ }
+
+ profile_name = get_profile_name ();
+ if (!profile_name) {
+ profile_name = DEFAULT_PROFILE;
+ }
+ profile_str = g_strdup_printf (" Profile: %s", profile_name);
+
+ gtk_statusbar_push(GTK_STATUSBAR(profile_bar), profile_ctx, profile_str);
+ }
+}
+
void
main_set_for_capture_file(gboolean have_capture_file_in)
{
@@ -1168,11 +1195,13 @@ main_load_window_geometry(GtkWidget *widget)
window_set_geometry(widget, &geom);
if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
- gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
+ gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane)
gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
- if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_status_pane)
- gtk_paned_set_position(GTK_PANED(status_pane), recent.gui_geometry_status_pane);
+ if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_left)
+ gtk_paned_set_position(GTK_PANED(status_pane_left), recent.gui_geometry_status_pane_left);
+ if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_right)
+ gtk_paned_set_position(GTK_PANED(status_pane_right), recent.gui_geometry_status_pane_right);
}
@@ -1200,7 +1229,8 @@ main_save_window_geometry(GtkWidget *widget)
recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
- recent.gui_geometry_status_pane = gtk_paned_get_position(GTK_PANED(status_pane));
+ recent.gui_geometry_status_pane_left = gtk_paned_get_position(GTK_PANED(status_pane_left));
+ recent.gui_geometry_status_pane_right = gtk_paned_get_position(GTK_PANED(status_pane_right));
#endif
}
@@ -1303,6 +1333,7 @@ print_usage(gboolean print_ver) {
fprintf(output, "\n");
fprintf(output, "User interface:\n");
+ fprintf(output, " -C <config profile> start with specified configuration profile\n");
fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
fprintf(output, " -m <font> set the font name used for most text\n");
fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
@@ -2146,6 +2177,112 @@ get_gui_runtime_info(GString *str
}
+static e_prefs *
+read_configuration_files(char **gdp_path, char **dp_path)
+{
+ int gpf_open_errno, gpf_read_errno;
+ int cf_open_errno, df_open_errno;
+ int gdp_open_errno, gdp_read_errno;
+ int dp_open_errno, dp_read_errno;
+ char *gpf_path, *pf_path;
+ char *cf_path, *df_path;
+ int pf_open_errno, pf_read_errno;
+ e_prefs *prefs;
+
+ /* Read the preference files. */
+ prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
+ &pf_open_errno, &pf_read_errno, &pf_path);
+
+ if (gpf_path != NULL) {
+ if (gpf_open_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not open global preferences file\n\"%s\": %s.", gpf_path,
+ strerror(gpf_open_errno));
+ }
+ if (gpf_read_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
+ strerror(gpf_read_errno));
+ }
+ }
+ if (pf_path != NULL) {
+ if (pf_open_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not open your preferences file\n\"%s\": %s.", pf_path,
+ strerror(pf_open_errno));
+ }
+ if (pf_read_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
+ strerror(pf_read_errno));
+ }
+ g_free(pf_path);
+ pf_path = NULL;
+ }
+
+#ifdef _WIN32
+ /* if the user wants a console to be always there, well, we should open one for him */
+ if (prefs->gui_console_open == console_open_always) {
+ create_console();
+ }
+#endif
+
+ /* Fill in capture options with values from the preferences */
+ prefs_to_capture_opts();
+
+ /* Read the capture filter file. */
+ read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
+ if (cf_path != NULL) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not open your capture filter file\n\"%s\": %s.", cf_path,
+ strerror(cf_open_errno));
+ g_free(cf_path);
+ }
+
+ /* Read the display filter file. */
+ read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
+ if (df_path != NULL) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not open your display filter file\n\"%s\": %s.", df_path,
+ strerror(df_open_errno));
+ g_free(df_path);
+ }
+
+ /* Read the disabled protocols file. */
+ read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
+ dp_path, &dp_open_errno, &dp_read_errno);
+ if (*gdp_path != NULL) {
+ if (gdp_open_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not open global disabled protocols file\n\"%s\": %s.",
+ *gdp_path, strerror(gdp_open_errno));
+ }
+ if (gdp_read_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "I/O error reading global disabled protocols file\n\"%s\": %s.",
+ *gdp_path, strerror(gdp_read_errno));
+ }
+ g_free(*gdp_path);
+ *gdp_path = NULL;
+ }
+ if (*dp_path != NULL) {
+ if (dp_open_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
+ strerror(dp_open_errno));
+ }
+ if (dp_read_errno != 0) {
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
+ strerror(dp_read_errno));
+ }
+ g_free(*dp_path);
+ *dp_path = NULL;
+ }
+
+ return prefs;
+}
+
/* And now our feature presentation... [ fade to music ] */
int
main(int argc, char *argv[])
@@ -2162,14 +2299,7 @@ main(int argc, char *argv[])
char *rf_path;
int rf_open_errno;
- char *gpf_path, *pf_path;
- char *cf_path, *df_path;
char *gdp_path, *dp_path;
- int gpf_open_errno, gpf_read_errno;
- int pf_open_errno, pf_read_errno;
- int cf_open_errno, df_open_errno;
- int gdp_open_errno, gdp_read_errno;
- int dp_open_errno, dp_read_errno;
int err;
#ifdef HAVE_LIBPCAP
gboolean start_capture = FALSE;
@@ -2194,7 +2324,7 @@ main(int argc, char *argv[])
/*gchar *cant_get_if_list_errstr;*/
#endif
-#define OPTSTRING_INIT "a:b:c:Df:g:Hhi:klLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
+#define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:klLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
#if defined HAVE_LIBPCAP && defined _WIN32
#define OPTSTRING_WIN32 "B:"
@@ -2315,6 +2445,14 @@ main(int argc, char *argv[])
optind_initial = optind;
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
+ case 'C': /* Configuration Profile */
+ if (profile_exists (optarg)) {
+ set_profile_name (optarg);
+ } else {
+ cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
+ exit(1);
+ }
+ break;
case 'h': /* Print help and exit */
print_usage(TRUE);
exit(0);
@@ -2502,94 +2640,7 @@ main(int argc, char *argv[])
splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
- /* Read the preference files. */
- prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
- &pf_open_errno, &pf_read_errno, &pf_path);
-
- if (gpf_path != NULL) {
- if (gpf_open_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "Could not open global preferences file\n\"%s\": %s.", gpf_path,
- strerror(gpf_open_errno));
- }
- if (gpf_read_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
- strerror(gpf_read_errno));
- }
- }
- if (pf_path != NULL) {
- if (pf_open_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "Could not open your preferences file\n\"%s\": %s.", pf_path,
- strerror(pf_open_errno));
- }
- if (pf_read_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
- strerror(pf_read_errno));
- }
- g_free(pf_path);
- pf_path = NULL;
- }
-
-#ifdef _WIN32
- /* if the user wants a console to be always there, well, we should open one for him */
- if (prefs->gui_console_open == console_open_always) {
- create_console();
- }
-#endif
-
- /* Fill in capture options with values from the preferences */
- prefs_to_capture_opts();
-
- /* Read the capture filter file. */
- read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
- if (cf_path != NULL) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "Could not open your capture filter file\n\"%s\": %s.", cf_path,
- strerror(cf_open_errno));
- g_free(cf_path);
- }
-
- /* Read the display filter file. */
- read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
- if (df_path != NULL) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "Could not open your display filter file\n\"%s\": %s.", df_path,
- strerror(df_open_errno));
- g_free(df_path);
- }
-
- /* Read the disabled protocols file. */
- read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
- &dp_path, &dp_open_errno, &dp_read_errno);
- if (gdp_path != NULL) {
- if (gdp_open_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "Could not open global disabled protocols file\n\"%s\": %s.",
- gdp_path, strerror(gdp_open_errno));
- }
- if (gdp_read_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "I/O error reading global disabled protocols file\n\"%s\": %s.",
- gdp_path, strerror(gdp_read_errno));
- }
- g_free(gdp_path);
- }
- if (dp_path != NULL) {
- if (dp_open_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
- strerror(dp_open_errno));
- }
- if (dp_read_errno != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
- "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
- strerror(dp_read_errno));
- }
- g_free(dp_path);
- }
+ prefs = read_configuration_files (&gdp_path, &dp_path);
/* Read the (static part) of the recent file. Only the static part of it will be read, */
/* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
@@ -2630,6 +2681,9 @@ main(int argc, char *argv[])
break;
/*** all non capture option specific ***/
+ case 'C':
+ /* Configuration profile settings were already processed just ignore them this time*/
+ break;
case 'D': /* Print a list of capture devices and exit */
#ifdef HAVE_LIBPCAP
capture_opts_list_interfaces(FALSE);
@@ -2910,7 +2964,7 @@ main(int argc, char *argv[])
/* read in rc file from global and personal configuration paths. */
rc_file = get_datafile_path(RC_FILE);
gtk_rc_parse(rc_file);
- rc_file = get_persconffile_path(RC_FILE, FALSE);
+ rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
gtk_rc_parse(rc_file);
font_init();
@@ -3321,10 +3375,23 @@ static GtkWidget *packets_bar_new(void)
packets_bar = gtk_statusbar_new();
packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
packets_bar_update();
+#if GTK_MAJOR_VERSION >= 2
+ gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(packets_bar), FALSE);
+#endif
return packets_bar;
}
+static GtkWidget *profile_bar_new(void)
+{
+ /* tip: tooltips don't work on statusbars! */
+ profile_bar = gtk_statusbar_new();
+ profile_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(profile_bar), "profile");
+ profile_bar_update();
+
+ return profile_bar;
+}
+
/*
* Helper for main_widgets_rearrange()
@@ -3377,7 +3444,9 @@ void main_widgets_rearrange(void) {
gtk_widget_ref(stat_hbox);
gtk_widget_ref(info_bar);
gtk_widget_ref(packets_bar);
- gtk_widget_ref(status_pane);
+ gtk_widget_ref(profile_bar);
+ gtk_widget_ref(status_pane_left);
+ gtk_widget_ref(status_pane_right);
gtk_widget_ref(main_pane_v1);
gtk_widget_ref(main_pane_v2);
gtk_widget_ref(main_pane_h1);
@@ -3387,7 +3456,8 @@ void main_widgets_rearrange(void) {
/* empty all containers participating */
gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
gtk_container_foreach(GTK_CONTAINER(stat_hbox), foreach_remove_a_child, stat_hbox);
- gtk_container_foreach(GTK_CONTAINER(status_pane), foreach_remove_a_child, status_pane);
+ gtk_container_foreach(GTK_CONTAINER(status_pane_left), foreach_remove_a_child, status_pane_left);
+ gtk_container_foreach(GTK_CONTAINER(status_pane_right), foreach_remove_a_child, status_pane_right);
gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
@@ -3486,9 +3556,11 @@ void main_widgets_rearrange(void) {
#endif
/* statusbar */
- gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane, TRUE, TRUE, 0);
- gtk_paned_pack1(GTK_PANED(status_pane), info_bar, FALSE, FALSE);
- gtk_paned_pack2(GTK_PANED(status_pane), packets_bar, FALSE, FALSE);
+ gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane_left, TRUE, TRUE, 0);
+ gtk_paned_pack1(GTK_PANED(status_pane_left), info_bar, FALSE, FALSE);
+ gtk_paned_pack2(GTK_PANED(status_pane_left), status_pane_right, TRUE, FALSE);
+ gtk_paned_pack1(GTK_PANED(status_pane_right), packets_bar, TRUE, FALSE);
+ gtk_paned_pack2(GTK_PANED(status_pane_right), profile_bar, FALSE, FALSE);
/* hide widgets on users recent settings */
main_widgets_show_or_hide();
@@ -4067,9 +4139,9 @@ main_widgets_show_or_hide(void)
}
if (recent.statusbar_show) {
- gtk_widget_show(status_pane);
+ gtk_widget_show(status_pane_left);
} else {
- gtk_widget_hide(status_pane);
+ gtk_widget_hide(status_pane_left);
}
if (recent.filter_toolbar_show) {
@@ -4833,14 +4905,20 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
packets_bar = packets_bar_new();
gtk_widget_show(packets_bar);
+ /* profile statusbar */
+ profile_bar = profile_bar_new();
+ gtk_widget_show(profile_bar);
+
/* Filter/status hbox */
stat_hbox = gtk_hbox_new(FALSE, 1);
gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
gtk_widget_show(stat_hbox);
/* Pane for the statusbar */
- status_pane = gtk_hpaned_new();
- gtk_widget_show(status_pane);
+ status_pane_left = gtk_hpaned_new();
+ gtk_widget_show(status_pane_left);
+ status_pane_right = gtk_hpaned_new();
+ gtk_widget_show(status_pane_right);
/* Pane for the welcome screen */
welcome_pane = welcome_new();
@@ -4938,3 +5016,37 @@ prefs_to_capture_opts(void)
/* Set the name resolution code's flags from the preferences. */
g_resolv_flags = prefs.name_resolve;
}
+
+
+/* Change configuration profile */
+void change_configuration_profile (const gchar *profile_name)
+{
+ char *gdp_path, *dp_path;
+
+ /* First set profile name and update the status bar */
+ set_profile_name (profile_name);
+ profile_bar_update ();
+
+ /* Reset current preferences and apply the new */
+ prefs_reset();
+ (void) read_configuration_files (&gdp_path, &dp_path);
+ prefs_apply_all();
+ uat_reload_all();
+
+ /* Update window view and redraw the toolbar */
+ update_main_window_name();
+ toolbar_redraw_all();
+
+ /* Enable all protocols and disable from the disabled list */
+ proto_enable_all();
+ if (gdp_path == NULL && dp_path == NULL) {
+ set_disabled_protos_list();
+ }
+
+ /* Reload color filters */
+ color_filters_reload();
+
+ /* Recreate the packet list according to new preferences */
+ packet_list_recreate ();
+ user_font_apply();
+}
diff --git a/gtk/main.h b/gtk/main.h
index fdb9b8540f..acb6ca1bd1 100644
--- a/gtk/main.h
+++ b/gtk/main.h
@@ -333,14 +333,23 @@ extern void dnd_open_file_cmd(gchar *cf_names_freeme);
/** Update the packets statusbar to the current values. */
extern void packets_bar_update(void);
+/** Update the profile statusbar to the current values. */
+extern void profile_bar_update(void);
+
#ifdef _WIN32
/** Win32 only: Create a console. Beware: cannot be closed again. */
extern void create_console(void);
#endif
-/* Fill in capture options with values from the preferences */
+/** Fill in capture options with values from the preferences */
extern void prefs_to_capture_opts(void);
+/** Change configuration profile */
+extern void change_configuration_profile(const gchar *profile_name);
+
+#define DEFAULT_PROFILE "Default"
+
+
extern GtkWidget *pkt_scrollw;
#endif /* __MAIN_H__ */
diff --git a/gtk/menu.c b/gtk/menu.c
index 6df8c26ace..0962d6686e 100644
--- a/gtk/menu.c
+++ b/gtk/menu.c
@@ -46,6 +46,7 @@
#include "capture_dlg.h"
#include "color_dlg.h"
#include "filter_dlg.h"
+#include "profile_dlg.h"
#include "dlg_utils.h"
#include "capture_file_dlg.h"
#include "fileset_dlg.h"
@@ -520,6 +521,9 @@ static GtkItemFactoryEntry menu_items[] =
ITEM_FACTORY_ENTRY("/Edit/Find Next Reference", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
ITEM_FACTORY_ENTRY("/Edit/Find Previous Reference", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
+#if GTK_MAJOR_VERSION >= 2
+ ITEM_FACTORY_ENTRY("/Edit/_Configuration Profiles...", "<shift><control>A", profile_dialog_cb, 0, NULL, NULL),
+#endif
ITEM_FACTORY_STOCK_ENTRY("/Edit/_Preferences...", "<shift><control>P", prefs_cb,
0, GTK_STOCK_PREFERENCES),
ITEM_FACTORY_ENTRY("/_View", NULL, NULL, 0, "<Branch>", NULL),
diff --git a/gtk/profile_dlg.c b/gtk/profile_dlg.c
new file mode 100644
index 0000000000..a08b6077ef
--- /dev/null
+++ b/gtk/profile_dlg.c
@@ -0,0 +1,791 @@
+/* profile_dlg.c
+ * Dialog box for profiles editing
+ * Stig Bjørlykke <stig@bjorlykke.org>, 2008
+ *
+ * $Id$
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include <epan/filesystem.h>
+#include <wiretap/file_util.h>
+
+#include "gtk/main.h"
+#include "profile_dlg.h"
+#include "dlg_utils.h"
+#include "gui_utils.h"
+#include "simple_dialog.h"
+#include "compat_macros.h"
+#include "gtkglobals.h"
+#include "help_dlg.h"
+#include <epan/prefs.h>
+
+#if GTK_MAJOR_VERSION >= 2
+
+#define E_PROF_PROFILE_L_KEY "profile_profile_l"
+#define E_PROF_COPY_BT_KEY "profile_copy_bt"
+#define E_PROF_DEL_BT_KEY "profile_del_bt"
+#define E_PROF_NAME_TE_KEY "profile_name_te"
+#define E_PROF_SELFUNC_KEY "profile_selfunc"
+#define E_PROF_SELARG_KEY "profile_selarg"
+
+static GtkWidget *global_profile_w = NULL;
+static GList *current_profiles = NULL;
+static GList *edited_profiles = NULL;
+
+#define PROF_STAT_DEFAULT 1
+#define PROF_STAT_EXISTS 2
+#define PROF_STAT_NEW 3
+#define PROF_STAT_CHANGED 4
+#define PROF_STAT_COPY 5
+
+typedef struct {
+ char *name; /* profile name */
+ char *reference; /* profile reference */
+ int status;
+} profile_def;
+
+static GList *
+add_profile_entry(GList *fl, const char *profilename, const char *reference, int status)
+{
+ profile_def *profile;
+
+ profile = (profile_def *) g_malloc(sizeof(profile_def));
+ profile->name = g_strdup(profilename);
+ profile->reference = g_strdup(reference);
+ profile->status = status;
+ return g_list_append(fl, profile);
+}
+
+static GList *
+remove_profile_entry(GList *fl, GList *fl_entry)
+{
+ profile_def *profile;
+
+ profile = (profile_def *) fl_entry->data;
+ g_free(profile->name);
+ g_free(profile->reference);
+ g_free(profile);
+ return g_list_remove_link(fl, fl_entry);
+}
+
+static GList *
+add_to_profile_list(const char *name, const char *expression, int status)
+{
+ edited_profiles = add_profile_entry(edited_profiles, name, expression, status);
+
+ return g_list_last(edited_profiles);
+}
+
+static void
+remove_from_profile_list(GList *fl_entry)
+{
+ edited_profiles = remove_profile_entry(edited_profiles, fl_entry);
+}
+
+static void
+empty_profile_list(gboolean edit_list)
+{
+ GList **flpp;
+
+ if (edit_list) {
+ flpp = &edited_profiles;
+
+ while(*flpp) {
+ *flpp = remove_profile_entry(*flpp, g_list_first(*flpp));
+ }
+
+ g_assert(g_list_length(*flpp) == 0);
+ }
+
+ flpp = &current_profiles;
+
+ while(*flpp) {
+ *flpp = remove_profile_entry(*flpp, g_list_first(*flpp));
+ }
+
+ g_assert(g_list_length(*flpp) == 0);
+}
+
+static void
+copy_profile_list(void)
+{
+ GList *flp_src;
+ profile_def *profile;
+
+ flp_src = edited_profiles;
+
+ /* throw away the "old" destination list - a NULL list is ok here */
+ empty_profile_list(FALSE);
+
+ /* copy the list entries */
+ while(flp_src) {
+ profile = (flp_src)->data;
+
+ current_profiles = add_profile_entry(current_profiles, profile->name,
+ profile->reference, profile->status);
+ flp_src = g_list_next(flp_src);
+ }
+}
+
+
+static GtkTreeIter *
+fill_list(GtkWidget *main_w)
+{
+ ETH_DIR *dir; /* scanned directory */
+ ETH_DIRENT *file; /* current file */
+ GList *fl_entry;
+ profile_def *profile;
+ GtkTreeView *profile_l;
+ GtkListStore *store;
+ GtkTreeIter iter, *l_select = NULL;
+ const gchar *profile_name = get_profile_name ();
+ const gchar *profiles_dir, *name;
+ gchar *filename;
+
+ profile_l = GTK_TREE_VIEW(OBJECT_GET_DATA(main_w, E_PROF_PROFILE_L_KEY));
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(profile_l));
+
+ fl_entry = add_to_profile_list(DEFAULT_PROFILE, DEFAULT_PROFILE, PROF_STAT_DEFAULT);
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, DEFAULT_PROFILE, 1, fl_entry, -1);
+ if (profile_name == NULL || strlen(profile_name) == 0) {
+ l_select = g_memdup(&iter, sizeof(iter));
+ }
+
+ /* fill in data */
+ profiles_dir = get_profiles_dir();
+ if ((dir = eth_dir_open(profiles_dir, 0, NULL)) != NULL) {
+ while ((file = eth_dir_read_name(dir)) != NULL) {
+ name = eth_dir_get_name(file);
+ filename = g_strdup_printf ("%s%s%s", profiles_dir, G_DIR_SEPARATOR_S, name);
+
+ if (test_for_directory(filename) == EISDIR) {
+ fl_entry = add_to_profile_list(name, name, PROF_STAT_EXISTS);
+ profile = (profile_def *) fl_entry->data;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, profile->name, 1, fl_entry, -1);
+
+ if (profile_name && profile->name) {
+ if (strcmp(profile_name, profile->name) == 0) {
+ /*
+ * XXX - We're assuming that we can just copy a GtkTreeIter
+ * and use it later without any crashes. This may not be a
+ * valid assumption.
+ */
+ l_select = g_memdup(&iter, sizeof(iter));
+ }
+ }
+ }
+ g_free (filename);
+ }
+ eth_dir_close (dir);
+ }
+
+ /* Make the current list an the edited list equal */
+ copy_profile_list ();
+
+ return l_select;
+}
+
+static void
+profile_select(GtkWidget *main_w, GtkTreeView *profile_l, gboolean destroy)
+{
+ GList *fl_entry;
+ profile_def *profile;
+ GtkTreeSelection *sel;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(profile_l));
+
+ if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, 1, &fl_entry, -1);
+ if (fl_entry) {
+ profile = (profile_def *) fl_entry->data;
+ if (strcmp(profile->name, DEFAULT_PROFILE)!=0) {
+ change_configuration_profile (profile->name);
+ } else {
+ change_configuration_profile (NULL);
+ }
+ }
+ }
+
+ if (destroy) {
+ /*
+ * Destroy the profile dialog box.
+ */
+ empty_profile_list (TRUE);
+ window_destroy(main_w);
+ }
+}
+
+static void
+profile_dlg_select(GtkTreeView *profile_l, gpointer main_w_arg)
+{
+ GtkWidget *main_w = GTK_WIDGET(main_w_arg);
+
+ profile_select(main_w, profile_l, TRUE);
+}
+
+static void
+profile_apply(GtkWidget *main_w, gboolean destroy)
+{
+ GtkTreeView *profile_l = GTK_TREE_VIEW(OBJECT_GET_DATA(main_w, E_PROF_PROFILE_L_KEY));
+
+ profile_select(main_w, profile_l, destroy);
+}
+
+static void
+profile_dlg_save(void)
+{
+ char *pf_dir_path, *pf_dir_path2;
+ GList *fl1, *fl2;
+ profile_def *profile1, *profile2;
+ gboolean found;
+
+ fl1 = g_list_first(edited_profiles);
+ while (fl1) {
+ found = FALSE;
+ profile1 = (profile_def *) fl1->data;
+ if (profile1->status == PROF_STAT_NEW) {
+ /* We do not create a directory for the default profile */
+ if (strcmp(profile1->name, DEFAULT_PROFILE)!=0) {
+ if (create_persconffile_profile(profile1->name, &pf_dir_path) == -1) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't create directory\n\"%s\":\n%s.",
+ pf_dir_path, strerror(errno));
+
+ g_free(pf_dir_path);
+ }
+ profile1->status = PROF_STAT_EXISTS;
+ }
+ } else if (profile1->status == PROF_STAT_CHANGED) {
+ if (strcmp(profile1->reference, profile1->name)!=0) {
+ /* Rename old profile directory to new */
+ if (rename_persconffile_profile(profile1->reference, profile1->name,
+ &pf_dir_path, &pf_dir_path2) == -1) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't rename directory\n\"%s\" to\n\"%s\":\n%s.",
+ pf_dir_path, pf_dir_path2, strerror(errno));
+
+ g_free(pf_dir_path);
+ }
+ profile1->status = PROF_STAT_EXISTS;
+ }
+ }
+ fl1 = g_list_next(fl1);
+ }
+
+ fl1 = g_list_first(current_profiles);
+ while (fl1) {
+ found = FALSE;
+ profile1 = (profile_def *) fl1->data;
+ fl2 = g_list_first(edited_profiles);
+ while (fl2) {
+ profile2 = (profile_def *) fl2->data;
+ if (strcmp(profile1->name, profile2->name)==0) {
+ /* Profile exists in both lists */
+ found = TRUE;
+ } else if (strcmp(profile1->name, profile2->reference)==0) {
+ /* Profile has been renamed */
+ found = TRUE;
+ }
+ fl2 = fl2->next;
+ }
+ if (!found) {
+ /* Exists in existing list and not in edited, this is a deleted profile */
+ if (delete_persconffile_profile(profile1->name, &pf_dir_path) == -1) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't delete profile directory\n\"%s\":\n%s.",
+ pf_dir_path, strerror(errno));
+
+ g_free(pf_dir_path);
+ }
+ }
+ fl1 = g_list_next(fl1);
+ }
+
+ copy_profile_list();
+}
+
+static void
+profile_dlg_ok_cb(GtkWidget *ok_bt, gpointer data _U_)
+{
+ profile_dlg_save();
+
+ /*
+ * Destroy the dialog box and apply the profile.
+ */
+ profile_apply(gtk_widget_get_toplevel(ok_bt), TRUE);
+}
+
+static void
+profile_dlg_apply_cb(GtkWidget *apply_bt, gpointer data _U_)
+{
+ profile_dlg_save();
+
+ /*
+ * Apply the profile, but don't destroy the dialog box.
+ */
+ profile_apply(gtk_widget_get_toplevel(apply_bt), FALSE);
+}
+
+/* cancel button pressed, revert changes and exit dialog */
+static void
+profile_dlg_cancel_cb(GtkWidget *cancel_bt, gpointer data _U_)
+{
+ GtkWidget *main_w = gtk_widget_get_toplevel(cancel_bt);
+
+ empty_profile_list (TRUE);
+ window_destroy(GTK_WIDGET(main_w));
+}
+
+/* Treat this as a cancel, by calling "profile_dlg_cancel_cb()" */
+static gboolean
+profile_dlg_delete_event_cb(GtkWidget *main_w, GdkEvent *event _U_,
+ gpointer data)
+{
+ profile_dlg_cancel_cb(main_w, data);
+ return FALSE;
+}
+
+static void
+profile_dlg_destroy_cb(GtkWidget *w _U_, gpointer data _U_)
+{
+ global_profile_w = NULL;
+}
+
+
+static gint
+profile_sel_list_button_cb(GtkWidget *list, GdkEventButton *event,
+ gpointer data _U_)
+{
+ void (* func)(GtkWidget *, gpointer);
+ gpointer func_arg;
+
+ if (event->type == GDK_2BUTTON_PRESS) {
+ func = OBJECT_GET_DATA(list, E_PROF_SELFUNC_KEY);
+ func_arg = OBJECT_GET_DATA(list, E_PROF_SELARG_KEY);
+
+ if (func)
+ (*func)(list, func_arg);
+ }
+
+ return FALSE;
+}
+
+static void
+profile_sel_list_cb(GtkTreeSelection *sel, gpointer data _U_)
+{
+ GtkWidget *profile_l = GTK_WIDGET(gtk_tree_selection_get_tree_view(sel));
+ GtkWidget *main_w = gtk_widget_get_toplevel(profile_l);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *name_te = OBJECT_GET_DATA(main_w, E_PROF_NAME_TE_KEY);
+ GtkWidget *copy_bt = OBJECT_GET_DATA(main_w, E_PROF_COPY_BT_KEY);
+ GtkWidget *del_bt = OBJECT_GET_DATA(main_w, E_PROF_DEL_BT_KEY);
+ profile_def *profile;
+ gchar *name = NULL;
+ GList *fl_entry;
+ gint sensitivity = FALSE;
+
+ if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, 1, &fl_entry, -1);
+ if (fl_entry) {
+ profile= (profile_def *) fl_entry->data;
+ name = g_strdup(profile->name);
+ if (profile->status!=PROF_STAT_DEFAULT) {
+ sensitivity = TRUE;
+ }
+ }
+ }
+
+ /*
+ * Did you know that this function is called when the window is destroyed?
+ * Funny, that.
+ * This means that we have to:
+ *
+ * attach to the top-level window data items containing pointers to
+ * the widgets we affect here;
+ *
+ * give each of those widgets their own destroy callbacks;
+ *
+ * clear that pointer when the widget is destroyed;
+ *
+ * don't do anything to the widget if the pointer we get back is
+ * null;
+ *
+ * so that if we're called after any of the widgets we'd affect are
+ * destroyed, we know that we shouldn't do anything to those widgets.
+ */
+ if (name_te != NULL) {
+ gtk_entry_set_text(GTK_ENTRY(name_te), name ? name : "");
+ gtk_widget_set_sensitive(name_te, sensitivity);
+ }
+ if (copy_bt != NULL)
+ gtk_widget_set_sensitive(copy_bt, sensitivity);
+ if (del_bt != NULL)
+ gtk_widget_set_sensitive(del_bt, sensitivity);
+ if (name != NULL)
+ g_free(name);
+}
+
+static void
+profile_new_bt_clicked_cb(GtkWidget *w, gpointer data _U_)
+{
+ GtkWidget *main_w = gtk_widget_get_toplevel(w);
+ GtkTreeView *profile_l = GTK_TREE_VIEW(OBJECT_GET_DATA(main_w, E_PROF_PROFILE_L_KEY));
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GList *fl_entry;
+ const gchar *name = "New profile";
+
+ /* Add a new entry to the profile list. */
+ fl_entry = add_to_profile_list(name, "", PROF_STAT_NEW);
+
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(profile_l));
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, name, 1, fl_entry, -1);
+ /* Select the item. */
+ gtk_tree_selection_select_iter(gtk_tree_view_get_selection(profile_l), &iter);
+}
+
+#if 0
+static void
+profile_copy_bt_clicked_cb(GtkWidget *w, gpointer data _U_)
+{
+ GtkWidget *main_w = gtk_widget_get_toplevel(w);
+ GtkWidget *name_te = OBJECT_GET_DATA(main_w, E_PROF_NAME_TE_KEY);
+ GtkTreeView *profile_l = GTK_TREE_VIEW(OBJECT_GET_DATA(main_w, E_PROF_PROFILE_L_KEY));
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GList *fl_entry;
+ const gchar *name = gtk_entry_get_text(GTK_ENTRY(name_te));
+ gchar *new_name;
+
+ new_name = g_strdup_printf ("%s (copy)", name);
+
+ /* Add a new entry to the profile list. */
+ fl_entry = add_to_profile_list(new_name, name, PROF_STAT_COPY);
+
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(profile_l));
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, new_name, 1, fl_entry, -1);
+ /* Select the item. */
+ gtk_tree_selection_select_iter(gtk_tree_view_get_selection(profile_l), &iter);
+ g_free (new_name);
+}
+#endif
+
+static void
+profile_name_te_changed_cb(GtkWidget *w, gpointer data _U_)
+{
+ GtkWidget *main_w = gtk_widget_get_toplevel(w);
+ GtkWidget *name_te = OBJECT_GET_DATA(main_w, E_PROF_NAME_TE_KEY);
+ GtkWidget *profile_l = OBJECT_GET_DATA(main_w, E_PROF_PROFILE_L_KEY);
+ profile_def *profile;
+ GList *fl_entry;
+ const gchar *name = "";
+
+ GtkTreeSelection *sel;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(profile_l));
+ name = gtk_entry_get_text(GTK_ENTRY(name_te));
+
+ /* if something was selected */
+ if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, 1, &fl_entry, -1);
+ if (fl_entry != NULL) {
+ profile = (profile_def *) fl_entry->data;
+
+ if (strlen(name) > 0 && profile) {
+ if (profile->status != PROF_STAT_DEFAULT) {
+ g_free(profile->name);
+ profile->name = g_strdup(name);
+ if (profile->status != PROF_STAT_NEW) {
+ profile->status = PROF_STAT_CHANGED;
+ }
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, name, -1);
+ }
+ }
+ }
+ }
+}
+
+static void
+profile_del_bt_clicked_cb(GtkWidget *w, gpointer data _U_)
+{
+ GtkWidget *main_w = gtk_widget_get_toplevel(w);
+ GtkWidget *profile_l = OBJECT_GET_DATA(main_w, E_PROF_PROFILE_L_KEY);
+ GList *fl_entry;
+
+ GtkTreeSelection *sel;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(profile_l));
+ /* If something was selected */
+ if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, 1, &fl_entry, -1);
+
+ if (fl_entry != NULL) {
+ remove_from_profile_list (fl_entry);
+ gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+ }
+ }
+
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ gtk_tree_selection_select_iter(sel, &iter);
+ }
+}
+
+static GtkWidget *
+profile_dialog_new(void)
+{
+ GtkWidget *main_w, /* main window */
+ *main_vb, /* main container */
+ *bbox, /* button container */
+ *ok_bt, /* "OK" button */
+ *apply_bt, /* "Apply" button */
+ *cancel_bt, /* "Cancel" button */
+ *help_bt; /* "Help" button */
+ GtkWidget *profile_vb, /* profile settings box */
+ *props_vb;
+ GtkWidget *top_hb,
+ *list_bb,
+ *new_bt,
+#if 0
+ *copy_bt,
+#endif
+ *del_bt,
+ *profile_sc,
+ *profile_l,
+ *middle_hb,
+ *name_lb,
+ *name_te,
+ *profile_fr,
+ *edit_fr,
+ *props_fr;
+ GtkTooltips *tooltips;
+ GtkListStore *store;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *sel;
+ GtkTreeIter *l_select;
+
+ /* Get a pointer to a static variable holding the type of profile on
+ which we're working, so we can pass that pointer to callback
+ routines. */
+
+ tooltips = gtk_tooltips_new ();
+
+ main_w = dlg_window_new("Wireshark: Configuration Profiles");
+ gtk_window_set_default_size(GTK_WINDOW(main_w), 400, 400);
+
+ main_vb = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+ gtk_container_add(GTK_CONTAINER(main_w), main_vb);
+ gtk_widget_show(main_vb);
+
+ /* Container for each row of widgets */
+ profile_vb = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(profile_vb), 0);
+ gtk_container_add(GTK_CONTAINER(main_vb), profile_vb);
+ gtk_widget_show(profile_vb);
+
+ /* Top row: Buttons and profile list */
+ top_hb = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(profile_vb), top_hb);
+ gtk_widget_show(top_hb);
+
+ edit_fr = gtk_frame_new("Edit");
+ gtk_box_pack_start(GTK_BOX(top_hb), edit_fr, FALSE, FALSE, 0);
+ gtk_widget_show(edit_fr);
+
+ list_bb = gtk_vbox_new(TRUE, 0);
+ gtk_container_border_width(GTK_CONTAINER(list_bb), 5);
+ gtk_container_add(GTK_CONTAINER(edit_fr), list_bb);
+ gtk_widget_show(list_bb);
+
+ new_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_NEW);
+ SIGNAL_CONNECT(new_bt, "clicked", profile_new_bt_clicked_cb, NULL);
+ gtk_widget_show(new_bt);
+ gtk_box_pack_start (GTK_BOX (list_bb), new_bt, FALSE, FALSE, 0);
+ gtk_tooltips_set_tip (tooltips, new_bt,
+ "Create a new profile (with default properties)", NULL);
+
+#if 0
+ copy_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_COPY);
+ gtk_widget_set_sensitive(copy_bt, FALSE);
+ SIGNAL_CONNECT(copy_bt, "clicked", profile_copy_bt_clicked_cb, NULL);
+ OBJECT_SET_DATA(main_w, E_PROF_COPY_BT_KEY, copy_bt);
+ gtk_widget_show(copy_bt);
+ gtk_box_pack_start (GTK_BOX (list_bb), copy_bt, FALSE, FALSE, 0);
+ gtk_tooltips_set_tip (tooltips, copy_bt,
+ "Copy the selected profile", NULL);
+#endif
+
+ del_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_DELETE);
+ gtk_widget_set_sensitive(del_bt, FALSE);
+ SIGNAL_CONNECT(del_bt, "clicked", profile_del_bt_clicked_cb, NULL);
+ OBJECT_SET_DATA(main_w, E_PROF_DEL_BT_KEY, del_bt);
+ gtk_widget_show(del_bt);
+ gtk_box_pack_start (GTK_BOX (list_bb), del_bt, FALSE, FALSE, 0);
+ gtk_tooltips_set_tip (tooltips, del_bt, "Delete the selected profile", NULL);
+
+ profile_fr = gtk_frame_new("Configuration Profiles");
+ gtk_box_pack_start(GTK_BOX(top_hb), profile_fr, TRUE, TRUE, 0);
+ gtk_widget_show(profile_fr);
+
+ profile_sc = scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(profile_sc),
+ GTK_SHADOW_IN);
+
+ gtk_container_set_border_width (GTK_CONTAINER (profile_sc), 5);
+ gtk_container_add(GTK_CONTAINER(profile_fr), profile_sc);
+ gtk_widget_show(profile_sc);
+
+ store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
+ profile_l = tree_view_new(GTK_TREE_MODEL(store));
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(profile_l), FALSE);
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
+ gtk_tree_view_column_set_sort_column_id(column, 0);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(profile_l), column);
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(profile_l));
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+ SIGNAL_CONNECT(sel, "changed", profile_sel_list_cb, profile_vb);
+ SIGNAL_CONNECT(profile_l, "button_press_event", profile_sel_list_button_cb, NULL);
+ OBJECT_SET_DATA(main_w, E_PROF_PROFILE_L_KEY, profile_l);
+ gtk_container_add(GTK_CONTAINER(profile_sc), profile_l);
+ gtk_widget_show(profile_l);
+
+ OBJECT_SET_DATA(profile_l, E_PROF_SELFUNC_KEY, profile_dlg_select);
+ OBJECT_SET_DATA(profile_l, E_PROF_SELARG_KEY, main_w);
+
+ /* fill in data */
+ l_select = fill_list(main_w);
+
+ g_object_unref(G_OBJECT(store));
+
+ props_fr = gtk_frame_new("Properties");
+ gtk_box_pack_start(GTK_BOX(profile_vb), props_fr, FALSE, FALSE, 0);
+ gtk_widget_show(props_fr);
+
+ props_vb = gtk_vbox_new(FALSE, 3);
+ gtk_container_border_width(GTK_CONTAINER(props_vb), 5);
+ gtk_container_add(GTK_CONTAINER(props_fr), props_vb);
+ gtk_widget_show(props_vb);
+
+ /* row: Profile name entry */
+ middle_hb = gtk_hbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(props_vb), middle_hb);
+ gtk_widget_show(middle_hb);
+
+ name_lb = gtk_label_new("Profile name:");
+ gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 0);
+ gtk_widget_show(name_lb);
+
+ name_te = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 0);
+ OBJECT_SET_DATA(main_w, E_PROF_NAME_TE_KEY, name_te);
+ SIGNAL_CONNECT(name_te, "changed", profile_name_te_changed_cb, NULL);
+ gtk_widget_show(name_te);
+
+ /* button row (create all possible buttons and hide the unrequired later - it's a lot easier) */
+ bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
+ gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
+ gtk_widget_show(bbox);
+
+ ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
+ SIGNAL_CONNECT(ok_bt, "clicked", profile_dlg_ok_cb, NULL);
+ gtk_tooltips_set_tip (tooltips, ok_bt, "Apply the profiles and close this dialog", NULL);
+
+ /* Catch the "activate" signal on the profile name and profile
+ list entries, so that if the user types Return
+ there, we act as if the "OK" button had been selected, as
+ happens if Return is typed if some widget that *doesn't*
+ handle the Return key has the input focus. */
+ dlg_set_activate(name_te, ok_bt);
+
+ apply_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_APPLY);
+ SIGNAL_CONNECT(apply_bt, "clicked", profile_dlg_apply_cb, NULL);
+ gtk_tooltips_set_tip (tooltips, apply_bt, "Apply the profiles and keep this dialog open", NULL);
+
+ cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
+ gtk_tooltips_set_tip (tooltips, cancel_bt, "Cancel the changes", NULL);
+ SIGNAL_CONNECT(cancel_bt, "clicked", profile_dlg_cancel_cb, NULL);
+ window_set_cancel_button(main_w, cancel_bt, NULL);
+
+ help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
+ SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_CONFIG_PROFILES_DIALOG);
+ gtk_tooltips_set_tip (tooltips, help_bt, "Show topic specific help", NULL);
+
+ if(ok_bt) {
+ gtk_widget_grab_default(ok_bt);
+ }
+
+
+ /* DO SELECTION THINGS *AFTER* SHOWING THE DIALOG! */
+ /* otherwise the updatings can get confused */
+ if (l_select) {
+ gtk_tree_selection_select_iter(sel, l_select);
+ g_free(l_select);
+ }
+
+ SIGNAL_CONNECT(main_w, "delete_event", profile_dlg_delete_event_cb, NULL);
+ SIGNAL_CONNECT(main_w, "destroy", profile_dlg_destroy_cb, NULL);
+
+ gtk_widget_show(main_w);
+
+ window_present(main_w);
+
+ return main_w;
+}
+
+#endif
+
+
+/* Create a profile dialog for editing display profiles; this is to be used
+ as a callback for menu items, toolbars, etc.. */
+void
+profile_dialog_cb(GtkWidget *w _U_)
+{
+#if GTK_MAJOR_VERSION >= 2
+ /* Has a profiles dialog box already been opened */
+ if (global_profile_w != NULL) {
+ /* Yes. Just reactivate it. */
+ reactivate_window(global_profile_w);
+ } else {
+ global_profile_w = profile_dialog_new ();
+ }
+#endif
+}
+
diff --git a/gtk/profile_dlg.h b/gtk/profile_dlg.h
new file mode 100644
index 0000000000..df6fcb391b
--- /dev/null
+++ b/gtk/profile_dlg.h
@@ -0,0 +1,41 @@
+/* profile_dlg.h
+ * Definitions for dialog box for profiles editing.
+ * Stig Bjørlykke <stig@bjorlykke.org>, 2008
+ *
+ * $Id$
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PROFILE_DLG_H__
+#define __PROFILE_DLG_H__
+
+/** @file
+ * "Configuration Profiles" dialog box
+ * @ingroup dialog_group
+ */
+
+
+/** User requested the "Configuration Profiles" dialog box by menu or toolbar.
+ *
+ * @param widget parent widget
+ */
+void profile_dialog_cb(GtkWidget *widget);
+
+#endif /* profile_dlg.h */
diff --git a/gtk/recent.c b/gtk/recent.c
index 913812094d..7f0dfe46ea 100644
--- a/gtk/recent.c
+++ b/gtk/recent.c
@@ -72,7 +72,8 @@
#define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized"
#define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
#define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
-#define RECENT_GUI_GEOMETRY_STATUS_PANE "gui.geometry_status_pane"
+#define RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT "gui.geometry_status_pane"
+#define RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT "gui.geometry_status_pane_right"
#define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
#define RECENT_GUI_GEOMETRY "gui.geom."
#define RECENT_KEY_PRIVS_WARN_IF_ELEVATED "privs.warn_if_elevated"
@@ -133,7 +134,7 @@ write_recent(void)
return FALSE;
}
- rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
+ rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE, TRUE);
if ((rf = eth_fopen(rf_path, "w")) == NULL) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Can't open recent file\n\"%s\": %s.", rf_path,
@@ -259,9 +260,16 @@ write_recent(void)
fprintf(rf, "\n# Statusbar left pane size.\n");
fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
fprintf(rf, "# Decimal number.\n");
- if (recent.gui_geometry_status_pane != 0) {
- fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE ": %d\n",
- recent.gui_geometry_status_pane);
+ if (recent.gui_geometry_status_pane_left != 0) {
+ fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT ": %d\n",
+ recent.gui_geometry_status_pane_left);
+ }
+ fprintf(rf, "\n# Statusbar middle pane size.\n");
+ fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
+ fprintf(rf, "# Decimal number.\n");
+ if (recent.gui_geometry_status_pane_right != 0) {
+ fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT ": %d\n",
+ recent.gui_geometry_status_pane_right);
}
fprintf(rf, "\n# Warn if running with elevated permissions (e.g. as root).\n");
@@ -446,13 +454,21 @@ read_set_recent_pair_static(gchar *key, gchar *value, void *private_data _U_)
return PREFS_SET_SYNTAX_ERR; /* number must be positive */
recent.gui_geometry_main_lower_pane = num;
recent.has_gui_geometry_main_lower_pane = TRUE;
- } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE) == 0) {
+ } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT) == 0) {
+ num = strtol(value, &p, 0);
+ if (p == value || *p != '\0')
+ return PREFS_SET_SYNTAX_ERR; /* number was bad */
+ if (num <= 0)
+ return PREFS_SET_SYNTAX_ERR; /* number must be positive */
+ recent.gui_geometry_status_pane_right = num;
+ recent.has_gui_geometry_status_pane = TRUE;
+ } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT) == 0) {
num = strtol(value, &p, 0);
if (p == value || *p != '\0')
return PREFS_SET_SYNTAX_ERR; /* number was bad */
if (num <= 0)
return PREFS_SET_SYNTAX_ERR; /* number must be positive */
- recent.gui_geometry_status_pane = num;
+ recent.gui_geometry_status_pane_left = num;
recent.has_gui_geometry_status_pane = TRUE;
} else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
if(u3_active())
@@ -580,7 +596,8 @@ recent_read_static(char **rf_path_return, int *rf_errno_return)
/* pane size of zero will autodetect */
recent.gui_geometry_main_upper_pane = 0;
recent.gui_geometry_main_lower_pane = 0;
- recent.gui_geometry_status_pane = 0;
+ recent.gui_geometry_status_pane_left = (DEF_WIDTH/3);
+ recent.gui_geometry_status_pane_right = (DEF_WIDTH/3);
/* the following are only used if GTK2 is used (as GTK1 cannot read these geometry values) */
/* or if set through command line */
@@ -598,7 +615,7 @@ recent_read_static(char **rf_path_return, int *rf_errno_return)
recent.privs_warn_if_no_npf = TRUE;
/* Construct the pathname of the user's recent file. */
- rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
+ rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE, FALSE);
/* Read the user's recent file, if it exists. */
*rf_path_return = NULL;
@@ -630,7 +647,7 @@ recent_read_dynamic(char **rf_path_return, int *rf_errno_return)
/* Construct the pathname of the user's recent file. */
- rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
+ rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE, FALSE);
/* Read the user's recent file, if it exists. */
*rf_path_return = NULL;
diff --git a/gtk/recent.h b/gtk/recent.h
index 0a2fa6c0bb..ff3aba9142 100644
--- a/gtk/recent.h
+++ b/gtk/recent.h
@@ -66,7 +66,8 @@ typedef struct recent_settings_tag {
gboolean has_gui_geometry_main_lower_pane; /* gui_geometry_main_lower_pane is valid */
gint gui_geometry_main_lower_pane; /* this is autodetected in GTK2 only */
gboolean has_gui_geometry_status_pane; /* gui_geometry_status_pane is valid */
- gint gui_geometry_status_pane; /* this is autodetected in GTK2 only */
+ gint gui_geometry_status_pane_left; /* this is autodetected in GTK2 only */
+ gint gui_geometry_status_pane_right; /* this is autodetected in GTK2 only */
gboolean privs_warn_if_elevated;
gboolean privs_warn_if_no_npf;
} recent_settings_t;
diff --git a/tshark.c b/tshark.c
index 1af614457d..1e1e077bca 100644
--- a/tshark.c
+++ b/tshark.c
@@ -259,6 +259,7 @@ print_usage(gboolean print_ver)
/*fprintf(output, "\n");*/
fprintf(output, "Output:\n");
fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
+ fprintf(output, " -C <config profile> start with specified configuration profile\n");
fprintf(output, " -F <output file type> set the output file type, default is libpcap\n");
fprintf(output, " an empty \"-F\" option will list the file types\n");
fprintf(output, " -V add output of packet tree (Packet Details)\n");
@@ -725,7 +726,7 @@ main(int argc, char *argv[])
GLogLevelFlags log_flags;
int optind_initial;
-#define OPTSTRING_INIT "a:b:c:d:De:E:f:F:G:hi:lLnN:o:pqr:R:s:St:T:vVw:xX:y:z:"
+#define OPTSTRING_INIT "a:b:c:C:d:De:E:f:F:G:hi:lLnN:o:pqr:R:s:St:T:vVw:xX:y:z:"
#ifdef HAVE_LIBPCAP
#ifdef _WIN32
#define OPTSTRING_WIN32 "B:"
@@ -761,6 +762,14 @@ main(int argc, char *argv[])
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
+ case 'C': /* Configuration Profile */
+ if (profile_exists (optarg)) {
+ set_profile_name (optarg);
+ } else {
+ cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
+ exit(1);
+ }
+ break;
case 'X':
ex_opt_add(optarg);
break;
@@ -956,6 +965,9 @@ main(int argc, char *argv[])
arg_error = TRUE;
#endif
break;
+ case 'C':
+ /* Configuration profile settings were already processed just ignore them this time*/
+ break;
case 'd': /* Decode as rule */
if (!add_decode_as(optarg))
exit(1);
diff --git a/update.c b/update.c
index 4296d4c353..05f8dbefee 100644
--- a/update.c
+++ b/update.c
@@ -312,7 +312,7 @@ update_check(gboolean interactive)
/* build update file name */
/* XXX - using the personal path, use temp dir instead? */
- local_file = get_persconffile_path("wsupdate", TRUE /*for_writing*/);
+ local_file = get_persconffile_path("wsupdate", FALSE, TRUE /*for_writing*/);
if(local_file == NULL) {
g_warning("Couldn't create output path!");
return;