2 * Dialog box for profiles editing
3 * Stig Bjorlykke <stig@bjorlykke.org>, 2008
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
19 #include <wsutil/filesystem.h>
23 #include "ui/simple_dialog.h"
24 #include "ui/recent.h"
26 #include <wsutil/file_util.h>
28 static GList *current_profiles = NULL;
29 static GList *edited_profiles = NULL;
31 #define PROF_OPERATION_NEW 1
32 #define PROF_OPERATION_EDIT 2
34 GList * current_profile_list(void) {
35 return g_list_first(current_profiles);
38 GList * edited_profile_list(void) {
39 return g_list_first(edited_profiles);
43 add_profile_entry(GList *fl, const char *profilename, const char *reference, int status,
44 gboolean is_global, gboolean from_global)
48 profile = (profile_def *) g_malloc0(sizeof(profile_def));
49 profile->name = g_strdup(profilename);
50 profile->reference = g_strdup(reference);
51 profile->status = status;
52 profile->is_global = is_global;
53 profile->from_global = from_global;
54 return g_list_append(fl, profile);
58 remove_profile_entry(GList *fl, GList *fl_entry)
62 profile = (profile_def *) fl_entry->data;
63 g_free(profile->name);
64 g_free(profile->reference);
66 return g_list_remove_link(fl, fl_entry);
70 get_profile_parent (const gchar *profilename)
72 GList *fl_entry = g_list_first(edited_profiles);
73 guint no_edited = g_list_length(edited_profiles);
78 /* We have edited profiles, find parent */
79 for (i = 0; i < no_edited; i++) {
81 profile = (profile_def *) fl_entry->data;
82 if (strcmp (profile->name, profilename) == 0) {
83 if ((profile->status == PROF_STAT_NEW) ||
84 (profile->reference == NULL)) {
85 /* Copy from a new profile */
88 /* Found a parent, use this */
89 profilename = profile->reference;
92 fl_entry = g_list_next(fl_entry);
94 fl_entry = g_list_first(edited_profiles);
101 gchar *apply_profile_changes(void)
103 char *pf_dir_path, *pf_dir_path2, *pf_filename;
105 profile_def *profile1, *profile2;
109 /* First validate all profile names */
110 fl1 = edited_profile_list();
112 profile1 = (profile_def *) fl1->data;
113 g_strstrip(profile1->name);
114 if ((err_msg = profile_name_is_valid(profile1->name)) != NULL) {
115 gchar *message = g_strdup_printf("%s\nProfiles unchanged.", err_msg);
119 fl1 = g_list_next(fl1);
122 /* Write recent file for current profile before copying or renaming */
123 write_profile_recent();
125 /* Then do all copy profiles */
126 fl1 = edited_profile_list();
128 profile1 = (profile_def *) fl1->data;
129 g_strstrip(profile1->name);
130 if (profile1->status == PROF_STAT_COPY) {
131 if (create_persconffile_profile(profile1->name, &pf_dir_path) == -1) {
132 err_msg = g_strdup_printf("Can't create directory\n\"%s\":\n%s.",
133 pf_dir_path, g_strerror(errno));
138 profile1->status = PROF_STAT_EXISTS;
140 if (profile1->reference) {
141 if (copy_persconffile_profile(profile1->name, profile1->reference, profile1->from_global,
142 &pf_filename, &pf_dir_path, &pf_dir_path2) == -1) {
143 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
144 "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
145 pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
149 g_free(pf_dir_path2);
153 g_free (profile1->reference);
154 profile1->reference = g_strdup(profile1->name);
156 fl1 = g_list_next(fl1);
160 /* Then create new and rename changed */
161 fl1 = edited_profile_list();
163 profile1 = (profile_def *) fl1->data;
164 g_strstrip(profile1->name);
165 if (profile1->status == PROF_STAT_NEW) {
166 /* We do not create a directory for the default profile */
167 if (strcmp(profile1->name, DEFAULT_PROFILE)!=0) {
168 if (create_persconffile_profile(profile1->name, &pf_dir_path) == -1) {
169 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
170 "Can't create directory\n\"%s\":\n%s.",
171 pf_dir_path, g_strerror(errno));
175 profile1->status = PROF_STAT_EXISTS;
177 g_free (profile1->reference);
178 profile1->reference = g_strdup(profile1->name);
180 } else if (profile1->status == PROF_STAT_CHANGED) {
181 if (strcmp(profile1->reference, profile1->name)!=0) {
182 /* Rename old profile directory to new */
183 if (rename_persconffile_profile(profile1->reference, profile1->name,
184 &pf_dir_path, &pf_dir_path2) == -1) {
185 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
186 "Can't rename directory\n\"%s\" to\n\"%s\":\n%s.",
187 pf_dir_path, pf_dir_path2, g_strerror(errno));
190 g_free(pf_dir_path2);
192 profile1->status = PROF_STAT_EXISTS;
195 fl1 = g_list_next(fl1);
198 /* Last remove deleted */
199 fl1 = current_profile_list();
202 profile1 = (profile_def *) fl1->data;
203 fl2 = edited_profile_list();
205 profile2 = (profile_def *) fl2->data;
206 if (!profile2->is_global) {
207 if (strcmp(profile1->name, profile2->name)==0) {
208 /* Profile exists in both lists */
210 } else if (strcmp(profile1->name, profile2->reference)==0) {
211 /* Profile has been renamed, update reference to the new name */
212 g_free (profile2->reference);
213 profile2->reference = g_strdup(profile2->name);
217 fl2 = g_list_next(fl2);
220 /* Exists in existing list and not in edited, this is a deleted profile */
221 if (delete_persconffile_profile(profile1->name, &pf_dir_path) == -1) {
222 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
223 "Can't delete profile directory\n\"%s\":\n%s.",
224 pf_dir_path, g_strerror(errno));
229 fl1 = g_list_next(fl1);
237 add_to_profile_list(const char *name, const char *expression, int status,
238 gboolean is_global, gboolean from_global)
240 edited_profiles = add_profile_entry(edited_profiles, name, expression, status,
241 is_global, from_global);
243 return g_list_last(edited_profiles);
247 remove_from_profile_list(GList *fl_entry)
249 edited_profiles = remove_profile_entry(edited_profiles, fl_entry);
253 empty_profile_list(gboolean edit_list)
258 flpp = &edited_profiles;
261 *flpp = remove_profile_entry(*flpp, g_list_first(*flpp));
264 g_assert(g_list_length(*flpp) == 0);
267 flpp = ¤t_profiles;
270 *flpp = remove_profile_entry(*flpp, g_list_first(*flpp));
273 g_assert(g_list_length(*flpp) == 0);
277 copy_profile_list(void)
280 profile_def *profile;
282 flp_src = edited_profiles;
284 /* throw away the "old" destination list - a NULL list is ok here */
285 empty_profile_list(FALSE);
287 /* copy the list entries */
289 profile = (profile_def *)(flp_src)->data;
291 current_profiles = add_profile_entry(current_profiles, profile->name,
292 profile->reference, profile->status,
293 profile->is_global, profile->from_global);
294 flp_src = g_list_next(flp_src);
299 init_profile_list(void)
301 WS_DIR *dir; /* scanned directory */
302 WS_DIRENT *file; /* current file */
304 GList *local_profiles = NULL;
305 GList *global_profiles = NULL;
307 gchar *profiles_dir, *filename;
309 empty_profile_list(TRUE);
312 add_to_profile_list(DEFAULT_PROFILE, DEFAULT_PROFILE, PROF_STAT_DEFAULT, FALSE, FALSE);
314 /* Local (user) profiles */
315 profiles_dir = get_profiles_dir();
316 if ((dir = ws_dir_open(profiles_dir, 0, NULL)) != NULL) {
317 while ((file = ws_dir_read_name(dir)) != NULL) {
318 name = ws_dir_get_name(file);
319 filename = g_strdup_printf ("%s%s%s", profiles_dir, G_DIR_SEPARATOR_S, name);
321 if (test_for_directory(filename) == EISDIR) {
322 local_profiles = g_list_prepend(local_profiles, g_strdup(name));
328 g_free(profiles_dir);
330 local_profiles = g_list_sort(local_profiles, (GCompareFunc)g_ascii_strcasecmp);
331 for (iter = g_list_first(local_profiles); iter; iter = g_list_next(iter)) {
332 name = (gchar *)iter->data;
333 add_to_profile_list(name, name, PROF_STAT_EXISTS, FALSE, FALSE);
335 g_list_free_full(local_profiles, g_free);
337 /* Global profiles */
338 profiles_dir = get_global_profiles_dir();
339 if ((dir = ws_dir_open(profiles_dir, 0, NULL)) != NULL) {
340 while ((file = ws_dir_read_name(dir)) != NULL) {
341 name = ws_dir_get_name(file);
342 filename = g_strdup_printf ("%s%s%s", profiles_dir, G_DIR_SEPARATOR_S, name);
344 if (test_for_directory(filename) == EISDIR) {
345 global_profiles = g_list_prepend(global_profiles, g_strdup(name));
351 g_free(profiles_dir);
353 global_profiles = g_list_sort(global_profiles, (GCompareFunc)g_ascii_strcasecmp);
354 for (iter = g_list_first(global_profiles); iter; iter = g_list_next(iter)) {
355 name = (gchar *)iter->data;
356 add_to_profile_list(name, name, PROF_STAT_EXISTS, TRUE, TRUE);
358 g_list_free_full(global_profiles, g_free);
360 /* Make the current list and the edited list equal */
361 copy_profile_list ();
365 profile_name_is_valid(const gchar *name)
367 gchar *reason = NULL;
371 char *invalid_dir_char = "\\/:*?\"<>|";
372 gboolean invalid = FALSE;
375 for (i = 0; i < 9; i++) {
376 if (strchr(name, invalid_dir_char[i])) {
377 /* Invalid character in directory */
381 if (name[0] == '.' || name[strlen(name)-1] == '.') {
382 /* Profile name cannot start or end with period */
386 reason = g_strdup_printf("start or end with period (.), or contain any of the following characters:\n"
387 " \\ / : * ? \" < > |");
390 if (strchr(name, '/')) {
391 /* Invalid character in directory */
392 reason = g_strdup_printf("contain the '/' character.");
397 message = g_strdup_printf("A profile name cannot %s", reason);
405 gboolean delete_current_profile(void) {
406 const gchar *name = get_profile_name();
409 if (profile_exists(name, FALSE) && strcmp (name, DEFAULT_PROFILE) != 0) {
410 if (delete_persconffile_profile(name, &pf_dir_path) == -1) {
411 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
412 "Can't delete profile directory\n\"%s\":\n%s.",
413 pf_dir_path, g_strerror(errno));
429 * indent-tabs-mode: nil
432 * ex: set shiftwidth=4 tabstop=8 expandtab:
433 * :indentSize=4:tabSize=8:noTabs=true: