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