This patch adds support for configuration profiles, which can be used to
authorstig <stig@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 14 Jan 2008 16:40:23 +0000 (16:40 +0000)
committerstig <stig@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 14 Jan 2008 16:40:23 +0000 (16:40 +0000)
configure and use more than one set of preferences and configuration files.

This can be found in the "Configuration Profiles..." menu item from the Edit
menu, or by pressing Shift-Ctrl-A.  It's also possible to start wireshark
and tshark with a named profile by using the "-C ProfileName" option.
A new status pane in the main window will show the current profile.

The configuration files currently stored in the Profiles are:
- Preferences
- Capture Filters
- Display Filters
- Coloring Rules
- Disabled Protocols
- User Accessible Tables

The recent data are by design not added to the profile.

Planned future enhancements:
- make a more convenient function to switch between profiles
- add a "clone profile" button to copy an existing profile
- make the profiles list active and accept return as OK
- save users "Decode as" in the profile
- make new, clone and deletion of profiles more secure
- make some of the recent values available in the profile

This patch also fixes:
- setting default status pane sizes
- a bug setting status pane for packets when not having main lower pane.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@24089 f5534014-38df-0310-8fa8-9805f1628bb7

37 files changed:
color_filters.c
color_filters.h
disabled_protos.c
docbook/user-guide.xml
docbook/wsug_graphics/ws-gui-config-profiles.png [new file with mode: 0644]
docbook/wsug_src/WSUG_chapter_customize.xml
epan/addr_resolv.c
epan/dissectors/packet-radius.c
epan/dissectors/packet-xml.c
epan/filesystem.c
epan/filesystem.h
epan/libwireshark.def
epan/oids.c
epan/plugins.c
epan/prefs.c
epan/prefs.h
epan/proto.c
epan/proto.h
epan/uat.c
epan/uat.h
epan/wslua/init_wslua.c
epan/wslua/wslua_util.c
filters.c
gtk/Makefile.am
gtk/Makefile.common
gtk/about_dlg.c
gtk/help_dlg.c
gtk/help_dlg.h
gtk/main.c
gtk/main.h
gtk/menu.c
gtk/profile_dlg.c [new file with mode: 0644]
gtk/profile_dlg.h [new file with mode: 0644]
gtk/recent.c
gtk/recent.h
tshark.c
update.c

index 239823ce0bfe6c285bf748c59121bfbd9b73a832..652dcb19a6c385c1b8280bc4d1c22ad5f12d54a4 100644 (file)
@@ -298,6 +298,23 @@ color_filters_init(void)
                color_filters_read_globals(&color_filter_list);
 }
 
+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)
 {
@@ -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.",
index df7846e6362079c303a685b50c4c18d4050553ed..a38e17c90613c3c88cc0c03a71f11f43a14f3d46 100644 (file)
@@ -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);
 
index 8c08ea3714810287122ea9b16280ffb4dfb0070d..7fd7775b5ac60526939bd0ca827bb8a221957c5e 100644 (file)
@@ -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
index 508e78700a8f155f524c0c3266bd5d14ffe9f54f..288e2a45791a834a7979d9ba93b40fac00d88253 100644 (file)
@@ -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 (file)
index 0000000..5619682
Binary files /dev/null and b/docbook/wsug_graphics/ws-gui-config-profiles.png differ
index cb7da8125b85db0117851db907570aa83683d8b4..101e271e03072f277a128efa867cb334fbde9ca8 100644 (file)
@@ -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
index f38ae2b5ed12c4f8f8a6ba214e4dfa7e4d11a89f..1fc7c45fc6cb0210d4245579343c4cfaed9abeeb 100644 (file)
@@ -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);
   }
index df590fe13aaec3d8b9d01ebb9cd0c88fc8cadb3e..5a149d970f2ad54b20efdc85babf649f6ad4cc20 100644 (file)
@@ -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 */
index f204b5ec1538c38353d1a3c6e70f7bb92534eb16..13ec0c58adb77fa311244eb5e8370548ed2b9a1b 100644 (file)
@@ -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 */
index f58e1e32f1b3f0296ab40910e579f145bf0a97ca..cbb9695aca83b404112f2019a58028e8a97b7629 100644 (file)
 #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) {
index d667ea4b68b3ade9a5b01c56b9de90d8960ad2a4..9a762c18fc101fd5266501aaf8c5b3d94e42bbfb 100644 (file)
@@ -70,6 +70,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
@@ -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.
index 6af119b5b3b8624e8078cd1df9d0112bcb275cd0..0fd22c734280a9047bdf4fe4bdf940e21ccc7091 100644 (file)
@@ -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
index a8354e91d3d1a1b76607e28e387c52cec174d97a..9951eda752f132aebb338bff02ff60638b6fb11d 100644 (file)
@@ -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"
index 68031b5be2a285cdd76726cf933d2779369863a5..9e7cc17edc11db7a5f4e3619ba7deb0cb6c39cb6 100644 (file)
@@ -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);
 }
 
 /*
index b070f0a65efa4e14864f67fe31e088010d4fa479..c9485885874891c3b7c95d3a2d16c48ddba16d35 100644 (file)
@@ -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;
index c67b4fe07a371f6ca55f2a752b39fce39e7ffb93..c01c714015f69f33f30fb6a3d27b83c43c393b24 100644 (file)
@@ -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);
 
index e04807e533ade3c8ecb138448655beab01662bfd..ca109808e8336a502703091877728b5cda5367e7 100644 (file)
@@ -3730,6 +3730,23 @@ proto_set_decoding(int proto_id, gboolean enabled)
        protocol->is_enabled = 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)
 {
index 0af704c2a572be40d2cb80e7ca76525dd02658f7..2be5a3a05590fd6c2af6c0a3975c873ff3451725 100644 (file)
@@ -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);
index b745c759d9f871b6819186a71674d649183d91f9..49c59dd873cb1090eb3085d3db29b8fcdb2f83a6 100644 (file)
@@ -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);
index 6f095d80a68ab829b6cf1f800ca02c58038a09cb..15d5796ad0ff0c2a91bcd70ddbb6dd8542a1a73c 100644 (file)
@@ -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);
index ebf4cf22c215ed5f4c11ebeffa428b68095fe64d..a0cba1cb5d477f6ce623fea6a5fb9957ad6a72a6 100644 (file)
@@ -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);
index 4d28c0044e4bdcabb3dbc220d00824c9e2e19f40..b870b001c87634441b4909ea321ca9f1e97fcb89 100644 (file)
@@ -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 */
index e8c22d1c3a9de7ead1b999f9481383f15a651e2c..71d177135b6efec77570cb0b35602c5b1de7049a 100644 (file)
--- 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
index f9e2c878a0a4199f63d8cf22731cfc8d8353ac79..8d997dc2552ce08a9fe4a594859a1f86d4e4b182 100644 (file)
@@ -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  \
index 4f7abf58ec9edf574f8c91cd1dd72b4a63156275..7f3aeb19ac4e0e36f9777b26f892c7a1902d2edd 100644 (file)
@@ -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    \
index 1ef9c0ac7d725b1d5ae9affea7fce64a521c3f24..9bb1e890f1a84d5258f6ace5d8f42904e56dc604 100644 (file)
@@ -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);
index ecf1009108747ddbac40a86e96b28b240b603345..223aaa5c3c109458ef23b7bcba2668993f5a6cad 100644 (file)
@@ -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;
index e19ed45db9f6c1415648ec8fc83b92543cad2ca7..fd9ef88ae7b7d54f5ceb7c3aedd8171604ee7cf6 100644 (file)
@@ -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,
index e6e81130260d009d2cae185bce4ca5dbbf8fcfe8..3b4fba71092c20645b4696de008efb3ef24e4aa1 100644 (file)
@@ -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();
+}
index fdb9b8540f773faba234db1c00fc9b6d91f5710b..acb6ca1bd1fc97aff5474813e2222bc85d879ab6 100644 (file)
@@ -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__ */
index 6df8c26ace7a4cbe1e0548462792472b20522f11..0962d6686e9e488a2bed1a135795b63c6e4b67cd 100644 (file)
@@ -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 (file)
index 0000000..a08b607
--- /dev/null
@@ -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 (file)
index 0000000..df6fcb3
--- /dev/null
@@ -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 */
index 913812094d81b20f7e9c66bd212608ab1ac4a596..7f0dfe46eab02bf951b1d3d4703951b11facd1eb 100644 (file)
@@ -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;
index 0a2fa6c0bbb8acc07825342b9a4bb1eb6ca9a805..ff3aba914232394cd03e701067cfab40719d8463 100644 (file)
@@ -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;
index 1af614457db3e9d2f9dc439812ee2ab9a528452c..1e1e077bca8ab294272503a12d1bee08e339c8dc 100644 (file)
--- 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);
index 4296d4c35350da7bfdca2ab9e52fa1a6692d081b..05f8dbefeeeeedb254ccc9164db562867aa4cc6f 100644 (file)
--- a/update.c
+++ b/update.c
@@ -312,7 +312,7 @@ update_check(gboolean interactive)
 \r
     /* build update file name */\r
     /* XXX - using the personal path, use temp dir instead? */\r
-    local_file = get_persconffile_path("wsupdate", TRUE /*for_writing*/);\r
+    local_file = get_persconffile_path("wsupdate", FALSE, TRUE /*for_writing*/);\r
     if(local_file == NULL) {\r
         g_warning("Couldn't create output path!");\r
         return;\r