summaryrefslogtreecommitdiffstats
path: root/ui/profile.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /ui/profile.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ui/profile.c')
-rw-r--r--ui/profile.c436
1 files changed, 436 insertions, 0 deletions
diff --git a/ui/profile.c b/ui/profile.c
new file mode 100644
index 00000000..59687fac
--- /dev/null
+++ b/ui/profile.c
@@ -0,0 +1,436 @@
+/* profile.c
+ * Dialog box for profiles editing
+ * Stig Bjorlykke <stig@bjorlykke.org>, 2008
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <wsutil/filesystem.h>
+
+#include "profile.h"
+
+#include "ui/simple_dialog.h"
+#include "ui/recent.h"
+
+#include <wsutil/file_util.h>
+#include <wsutil/ws_assert.h>
+
+static GList *current_profiles = NULL;
+static GList *edited_profiles = NULL;
+
+#define PROF_OPERATION_NEW 1
+#define PROF_OPERATION_EDIT 2
+
+GList * current_profile_list(void) {
+ return g_list_first(current_profiles);
+}
+
+GList * edited_profile_list(void) {
+ return g_list_first(edited_profiles);
+}
+
+static GList *
+add_profile_entry(GList *fl, const char *profilename, const char *reference, int status,
+ gboolean is_global, gboolean from_global, gboolean is_import)
+{
+ profile_def *profile;
+
+ profile = g_new0(profile_def, 1);
+ profile->name = g_strdup(profilename);
+ profile->reference = g_strdup(reference);
+ profile->status = status;
+ profile->is_global = is_global;
+ profile->from_global = from_global;
+ profile->is_import = is_import;
+ return g_list_append(fl, profile);
+}
+
+static GList *
+remove_profile_entry(GList *fl, GList *fl_entry)
+{
+ GList *list;
+ profile_def *profile;
+
+ profile = (profile_def *) fl_entry->data;
+ g_free(profile->name);
+ g_free(profile->reference);
+ g_free(profile);
+ list = g_list_remove_link(fl, fl_entry);
+ g_list_free_1(fl_entry);
+ return list;
+}
+
+const gchar *
+get_profile_parent (const gchar *profilename)
+{
+ GList *fl_entry = g_list_first(edited_profiles);
+ guint no_edited = g_list_length(edited_profiles);
+ profile_def *profile;
+ guint i;
+
+ if (fl_entry) {
+ /* We have edited profiles, find parent */
+ for (i = 0; i < no_edited; i++) {
+ while (fl_entry) {
+ profile = (profile_def *) fl_entry->data;
+ if (strcmp (profile->name, profilename) == 0) {
+ if ((profile->status == PROF_STAT_NEW) ||
+ (profile->reference == NULL)) {
+ /* Copy from a new profile */
+ return NULL;
+ } else {
+ /* Found a parent, use this */
+ profilename = profile->reference;
+ }
+ }
+ fl_entry = g_list_next(fl_entry);
+ }
+ fl_entry = g_list_first(edited_profiles);
+ }
+ }
+
+ return profilename;
+}
+
+gchar *apply_profile_changes(void)
+{
+ char *pf_dir_path, *pf_dir_path2, *pf_filename;
+ GList *fl1, *fl2;
+ profile_def *profile1, *profile2;
+ gboolean found;
+ gchar *err_msg;
+
+ /* First validate all profile names */
+ fl1 = edited_profile_list();
+ while (fl1) {
+ profile1 = (profile_def *) fl1->data;
+ g_strstrip(profile1->name);
+ if ((err_msg = profile_name_is_valid(profile1->name)) != NULL) {
+ gchar *message = ws_strdup_printf("%s\nProfiles unchanged.", err_msg);
+ g_free(err_msg);
+ return message;
+ }
+ fl1 = g_list_next(fl1);
+ }
+
+ /* Write recent file for current profile before copying or renaming */
+ write_profile_recent();
+
+ /* Then do all copy profiles */
+ fl1 = edited_profile_list();
+ while (fl1) {
+ profile1 = (profile_def *) fl1->data;
+ g_strstrip(profile1->name);
+ if (profile1->status == PROF_STAT_COPY) {
+ if (create_persconffile_profile(profile1->name, &pf_dir_path) == -1) {
+ err_msg = ws_strdup_printf("Can't create directory\n\"%s\":\n%s.",
+ pf_dir_path, g_strerror(errno));
+
+ g_free(pf_dir_path);
+ return err_msg;
+ }
+ profile1->status = PROF_STAT_EXISTS;
+
+ if (profile1->reference) {
+ if (copy_persconffile_profile(profile1->name, profile1->reference, profile1->from_global,
+ &pf_filename, &pf_dir_path, &pf_dir_path2) == -1) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
+ pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
+
+ g_free(pf_filename);
+ g_free(pf_dir_path);
+ g_free(pf_dir_path2);
+ }
+ }
+
+ g_free (profile1->reference);
+ profile1->reference = g_strdup(profile1->name);
+ }
+ fl1 = g_list_next(fl1);
+ }
+
+
+ /* Then create new and rename changed */
+ fl1 = edited_profile_list();
+ while (fl1) {
+ profile1 = (profile_def *) fl1->data;
+ g_strstrip(profile1->name);
+ if (profile1->status == PROF_STAT_NEW) {
+ /* We do not create a directory for the default profile */
+ if (strcmp(profile1->name, DEFAULT_PROFILE)!=0 && ! profile1->is_import) {
+ 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, g_strerror(errno));
+
+ g_free(pf_dir_path);
+ }
+ profile1->status = PROF_STAT_EXISTS;
+
+ g_free (profile1->reference);
+ profile1->reference = g_strdup(profile1->name);
+ /* correctly apply imports as existing profiles */
+ } else if (profile1->is_import) {
+ profile1->status = PROF_STAT_EXISTS;
+ g_free (profile1->reference);
+ profile1->reference = g_strdup(profile1->name);
+ profile1->is_import = FALSE;
+ }
+ } 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, g_strerror(errno));
+
+ g_free(pf_dir_path);
+ g_free(pf_dir_path2);
+ }
+ profile1->status = PROF_STAT_EXISTS;
+ }
+ }
+ fl1 = g_list_next(fl1);
+ }
+
+ /* Last remove deleted */
+ fl1 = current_profile_list();
+ while (fl1) {
+ found = FALSE;
+ profile1 = (profile_def *) fl1->data;
+ fl2 = edited_profile_list();
+ while (fl2) {
+ profile2 = (profile_def *) fl2->data;
+ if (!profile2->is_global) {
+ 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, update reference to the new name */
+ g_free (profile2->reference);
+ profile2->reference = g_strdup(profile2->name);
+ found = TRUE;
+ }
+ }
+ fl2 = g_list_next(fl2);
+ }
+ 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, g_strerror(errno));
+
+ g_free(pf_dir_path);
+ }
+ }
+ fl1 = g_list_next(fl1);
+ }
+
+ copy_profile_list();
+ return NULL;
+}
+
+GList *
+add_to_profile_list(const char *name, const char *expression, int status,
+ gboolean is_global, gboolean from_global, gboolean is_imported)
+{
+ edited_profiles = add_profile_entry(edited_profiles, name, expression, status,
+ is_global, from_global, is_imported);
+
+ return g_list_last(edited_profiles);
+}
+
+void
+remove_from_profile_list(GList *fl_entry)
+{
+ edited_profiles = remove_profile_entry(edited_profiles, fl_entry);
+}
+
+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));
+ }
+
+ ws_assert(g_list_length(*flpp) == 0);
+ if ( ! edited_profiles )
+ edited_profiles = NULL;
+ }
+
+ flpp = &current_profiles;
+
+ while(*flpp) {
+ *flpp = remove_profile_entry(*flpp, g_list_first(*flpp));
+ }
+
+ ws_assert(g_list_length(*flpp) == 0);
+ if ( ! current_profiles )
+ current_profiles = NULL;
+}
+
+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 = (profile_def *)(flp_src)->data;
+
+ current_profiles = add_profile_entry(current_profiles, profile->name,
+ profile->reference, profile->status,
+ profile->is_global, profile->from_global, FALSE);
+ flp_src = g_list_next(flp_src);
+ }
+}
+
+void
+init_profile_list(void)
+{
+ WS_DIR *dir; /* scanned directory */
+ WS_DIRENT *file; /* current file */
+ const gchar *name;
+ GList *local_profiles = NULL;
+ GList *global_profiles = NULL;
+ GList *iter;
+ gchar *profiles_dir, *filename;
+
+ empty_profile_list(TRUE);
+
+ /* Default entry */
+ add_to_profile_list(DEFAULT_PROFILE, DEFAULT_PROFILE, PROF_STAT_DEFAULT, FALSE, FALSE, FALSE);
+
+ /* Local (user) profiles */
+ profiles_dir = get_profiles_dir();
+ if ((dir = ws_dir_open(profiles_dir, 0, NULL)) != NULL) {
+ while ((file = ws_dir_read_name(dir)) != NULL) {
+ name = ws_dir_get_name(file);
+ filename = ws_strdup_printf ("%s%s%s", profiles_dir, G_DIR_SEPARATOR_S, name);
+
+ if (test_for_directory(filename) == EISDIR) {
+ local_profiles = g_list_prepend(local_profiles, g_strdup(name));
+ }
+ g_free (filename);
+ }
+ ws_dir_close (dir);
+ }
+ g_free(profiles_dir);
+
+ local_profiles = g_list_sort(local_profiles, (GCompareFunc)g_ascii_strcasecmp);
+ for (iter = g_list_first(local_profiles); iter; iter = g_list_next(iter)) {
+ name = (gchar *)iter->data;
+ add_to_profile_list(name, name, PROF_STAT_EXISTS, FALSE, FALSE, FALSE);
+ }
+ g_list_free_full(local_profiles, g_free);
+
+ /* Global profiles */
+ profiles_dir = get_global_profiles_dir();
+ if ((dir = ws_dir_open(profiles_dir, 0, NULL)) != NULL) {
+ while ((file = ws_dir_read_name(dir)) != NULL) {
+ name = ws_dir_get_name(file);
+ filename = ws_strdup_printf ("%s%s%s", profiles_dir, G_DIR_SEPARATOR_S, name);
+
+ if (test_for_directory(filename) == EISDIR) {
+ global_profiles = g_list_prepend(global_profiles, g_strdup(name));
+ }
+ g_free (filename);
+ }
+ ws_dir_close (dir);
+ }
+ g_free(profiles_dir);
+
+ global_profiles = g_list_sort(global_profiles, (GCompareFunc)g_ascii_strcasecmp);
+ for (iter = g_list_first(global_profiles); iter; iter = g_list_next(iter)) {
+ name = (gchar *)iter->data;
+ add_to_profile_list(name, name, PROF_STAT_EXISTS, TRUE, TRUE, FALSE);
+ }
+ g_list_free_full(global_profiles, g_free);
+
+ /* Make the current list and the edited list equal */
+ copy_profile_list ();
+}
+
+gchar *
+profile_name_is_valid(const gchar *name)
+{
+ gchar *reason = NULL;
+ gchar *message;
+
+#ifdef _WIN32
+ char *invalid_dir_char = "\\/:*?\"<>|";
+ gboolean invalid = FALSE;
+ int i;
+
+ for (i = 0; i < 9; i++) {
+ if (strchr(name, invalid_dir_char[i])) {
+ /* Invalid character in directory */
+ invalid = TRUE;
+ }
+ }
+ if (name[0] == '.' || name[strlen(name)-1] == '.') {
+ /* Profile name cannot start or end with period */
+ invalid = TRUE;
+ }
+ if (invalid) {
+ reason = ws_strdup_printf("start or end with period (.), or contain any of the following characters:\n"
+ " \\ / : * ? \" &lt; &gt; |");
+ }
+#else
+ if (strchr(name, '/')) {
+ /* Invalid character in directory */
+ reason = ws_strdup_printf("contain the '/' character.");
+ }
+#endif
+
+ if (reason) {
+ message = ws_strdup_printf("A profile name cannot %s", reason);
+ g_free(reason);
+ return message;
+ }
+
+ return NULL;
+}
+
+gboolean delete_current_profile(void) {
+ const gchar *name = get_profile_name();
+ char *pf_dir_path;
+
+ if (profile_exists(name, FALSE) && strcmp (name, DEFAULT_PROFILE) != 0) {
+ if (delete_persconffile_profile(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, g_strerror(errno));
+
+ g_free(pf_dir_path);
+ } else {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}