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 = num; + 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_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;