2 * Dialog box for profiles editing
3 * Stig Bjorlykke <stig@bjorlykke.org>, 2008
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <epan/emem.h>
34 #include <epan/filesystem.h>
35 #include <epan/prefs.h>
39 #include "ui/recent.h"
40 #include "ui/simple_dialog.h"
42 #include <wsutil/file_util.h>
44 static GList
*current_profiles
= NULL
;
45 static GList
*edited_profiles
= NULL
;
47 #define PROF_OPERATION_NEW 1
48 #define PROF_OPERATION_EDIT 2
50 GList
* current_profile_list(void) {
51 return g_list_first(current_profiles
);
54 GList
* edited_profile_list(void) {
55 return g_list_first(edited_profiles
);
59 add_profile_entry(GList
*fl
, const char *profilename
, const char *reference
, int status
,
60 gboolean is_global
, gboolean from_global
)
64 profile
= (profile_def
*) g_malloc0(sizeof(profile_def
));
65 profile
->name
= g_strdup(profilename
);
66 profile
->reference
= g_strdup(reference
);
67 profile
->status
= status
;
68 profile
->is_global
= is_global
;
69 profile
->from_global
= from_global
;
70 return g_list_append(fl
, profile
);
74 remove_profile_entry(GList
*fl
, GList
*fl_entry
)
78 profile
= (profile_def
*) fl_entry
->data
;
79 g_free(profile
->name
);
80 g_free(profile
->reference
);
82 return g_list_remove_link(fl
, fl_entry
);
86 get_profile_parent (const gchar
*profilename
)
88 GList
*fl_entry
= g_list_first(edited_profiles
);
89 guint no_edited
= g_list_length(edited_profiles
);
94 /* We have edited profiles, find parent */
95 for (i
= 0; i
< no_edited
; i
++) {
97 profile
= (profile_def
*) fl_entry
->data
;
98 if (strcmp (profile
->name
, profilename
) == 0) {
99 if ((profile
->status
== PROF_STAT_NEW
) ||
100 (profile
->reference
== NULL
)) {
101 /* Copy from a new profile */
104 /* Found a parent, use this */
105 profilename
= profile
->reference
;
108 fl_entry
= g_list_next(fl_entry
);
110 fl_entry
= g_list_first(edited_profiles
);
117 const gchar
*apply_profile_changes(void) {
118 char *pf_dir_path
, *pf_dir_path2
, *pf_filename
;
120 profile_def
*profile1
, *profile2
;
122 emem_strbuf_t
*message
= ep_strbuf_new(NULL
);
123 const gchar
*err_msg
;
125 /* First validate all profile names */
126 fl1
= edited_profile_list();
128 profile1
= (profile_def
*) fl1
->data
;
129 g_strstrip(profile1
->name
);
130 if ((err_msg
= profile_name_is_valid(profile1
->name
)) != NULL
) {
131 ep_strbuf_printf(message
, "%s", err_msg
);
134 fl1
= g_list_next(fl1
);
137 /* Then do all copy profiles */
138 fl1
= edited_profile_list();
140 profile1
= (profile_def
*) fl1
->data
;
141 g_strstrip(profile1
->name
);
142 if (profile1
->status
== PROF_STAT_COPY
) {
143 if (create_persconffile_profile(profile1
->name
, &pf_dir_path
) == -1) {
144 ep_strbuf_printf(message
,
145 "Can't create directory\n\"%s\":\n%s.",
146 pf_dir_path
, g_strerror(errno
));
150 profile1
->status
= PROF_STAT_EXISTS
;
152 if (profile1
->reference
) {
153 if (copy_persconffile_profile(profile1
->name
, profile1
->reference
, profile1
->from_global
,
154 &pf_filename
, &pf_dir_path
, &pf_dir_path2
) == -1) {
155 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
156 "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
157 pf_filename
, pf_dir_path2
, pf_dir_path
, g_strerror(errno
));
161 g_free(pf_dir_path2
);
165 g_free (profile1
->reference
);
166 profile1
->reference
= g_strdup(profile1
->name
);
168 fl1
= g_list_next(fl1
);
172 /* Then create new and rename changed */
173 fl1
= edited_profile_list();
175 profile1
= (profile_def
*) fl1
->data
;
176 g_strstrip(profile1
->name
);
177 if (profile1
->status
== PROF_STAT_NEW
) {
178 /* We do not create a directory for the default profile */
179 if (strcmp(profile1
->name
, DEFAULT_PROFILE
)!=0) {
180 if (create_persconffile_profile(profile1
->name
, &pf_dir_path
) == -1) {
181 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
182 "Can't create directory\n\"%s\":\n%s.",
183 pf_dir_path
, g_strerror(errno
));
187 profile1
->status
= PROF_STAT_EXISTS
;
189 g_free (profile1
->reference
);
190 profile1
->reference
= g_strdup(profile1
->name
);
192 } else if (profile1
->status
== PROF_STAT_CHANGED
) {
193 if (strcmp(profile1
->reference
, profile1
->name
)!=0) {
194 /* Rename old profile directory to new */
195 if (rename_persconffile_profile(profile1
->reference
, profile1
->name
,
196 &pf_dir_path
, &pf_dir_path2
) == -1) {
197 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
198 "Can't rename directory\n\"%s\" to\n\"%s\":\n%s.",
199 pf_dir_path
, pf_dir_path2
, g_strerror(errno
));
202 g_free(pf_dir_path2
);
204 profile1
->status
= PROF_STAT_EXISTS
;
205 g_free (profile1
->reference
);
206 profile1
->reference
= g_strdup(profile1
->name
);
209 fl1
= g_list_next(fl1
);
212 /* Last remove deleted */
213 fl1
= current_profile_list();
216 profile1
= (profile_def
*) fl1
->data
;
217 fl2
= edited_profile_list();
219 profile2
= (profile_def
*) fl2
->data
;
220 if (!profile2
->is_global
) {
221 if (strcmp(profile1
->name
, profile2
->name
)==0) {
222 /* Profile exists in both lists */
224 } else if (strcmp(profile1
->name
, profile2
->reference
)==0) {
225 /* Profile has been renamed */
229 fl2
= g_list_next(fl2
);
232 /* Exists in existing list and not in edited, this is a deleted profile */
233 if (delete_persconffile_profile(profile1
->name
, &pf_dir_path
) == -1) {
234 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
235 "Can't delete profile directory\n\"%s\":\n%s.",
236 pf_dir_path
, g_strerror(errno
));
241 fl1
= g_list_next(fl1
);
249 add_to_profile_list(const char *name
, const char *expression
, int status
,
250 gboolean is_global
, gboolean from_global
)
252 edited_profiles
= add_profile_entry(edited_profiles
, name
, expression
, status
,
253 is_global
, from_global
);
255 return g_list_last(edited_profiles
);
259 remove_from_profile_list(GList
*fl_entry
)
261 edited_profiles
= remove_profile_entry(edited_profiles
, fl_entry
);
265 empty_profile_list(gboolean edit_list
)
270 flpp
= &edited_profiles
;
273 *flpp
= remove_profile_entry(*flpp
, g_list_first(*flpp
));
276 g_assert(g_list_length(*flpp
) == 0);
279 flpp
= ¤t_profiles
;
282 *flpp
= remove_profile_entry(*flpp
, g_list_first(*flpp
));
285 g_assert(g_list_length(*flpp
) == 0);
289 copy_profile_list(void)
292 profile_def
*profile
;
294 flp_src
= edited_profiles
;
296 /* throw away the "old" destination list - a NULL list is ok here */
297 empty_profile_list(FALSE
);
299 /* copy the list entries */
301 profile
= (profile_def
*)(flp_src
)->data
;
303 current_profiles
= add_profile_entry(current_profiles
, profile
->name
,
304 profile
->reference
, profile
->status
,
305 profile
->is_global
, profile
->from_global
);
306 flp_src
= g_list_next(flp_src
);
311 init_profile_list(void)
313 WS_DIR
*dir
; /* scanned directory */
314 WS_DIRENT
*file
; /* current file */
315 const gchar
*profiles_dir
, *name
;
318 empty_profile_list(TRUE
);
321 add_to_profile_list(DEFAULT_PROFILE
, DEFAULT_PROFILE
, PROF_STAT_DEFAULT
, FALSE
, FALSE
);
323 /* Local (user) profiles */
324 profiles_dir
= get_profiles_dir();
325 if ((dir
= ws_dir_open(profiles_dir
, 0, NULL
)) != NULL
) {
326 while ((file
= ws_dir_read_name(dir
)) != NULL
) {
327 name
= ws_dir_get_name(file
);
328 filename
= g_strdup_printf ("%s%s%s", profiles_dir
, G_DIR_SEPARATOR_S
, name
);
330 if (test_for_directory(filename
) == EISDIR
) {
331 /*fl_entry =*/ add_to_profile_list(name
, name
, PROF_STAT_EXISTS
, FALSE
, FALSE
);
338 /* Global profiles */
339 profiles_dir
= get_global_profiles_dir();
340 if ((dir
= ws_dir_open(profiles_dir
, 0, NULL
)) != NULL
) {
341 while ((file
= ws_dir_read_name(dir
)) != NULL
) {
342 name
= ws_dir_get_name(file
);
343 filename
= g_strdup_printf ("%s%s%s", profiles_dir
, G_DIR_SEPARATOR_S
, name
);
345 if (test_for_directory(filename
) == EISDIR
) {
346 /*fl_entry =*/ add_to_profile_list(name
, name
, PROF_STAT_EXISTS
, TRUE
, TRUE
);
347 /*profile = (profile_def *) fl_entry->data;*/
354 /* Make the current list and the edited list equal */
355 copy_profile_list ();
359 profile_name_is_valid(const gchar
*name
)
361 gchar
*reason
= NULL
;
362 emem_strbuf_t
*message
= ep_strbuf_new(NULL
);
365 char *invalid_dir_char
= "\\/:*?\"<>|";
366 gboolean invalid
= FALSE
;
369 for (i
= 0; i
< 9; i
++) {
370 if (strchr(name
, invalid_dir_char
[i
])) {
371 /* Invalid character in directory */
375 if (name
[0] == '.' || name
[strlen(name
)-1] == '.') {
376 /* Profile name cannot start or end with period */
380 reason
= g_strdup_printf("start or end with period (.), or contain any of the following characters:\n"
381 " \\ / : * ? \" < > |");
384 if (strchr(name
, '/')) {
385 /* Invalid character in directory */
386 reason
= g_strdup_printf("contain the '/' character.");
391 ep_strbuf_printf(message
, "A profile name cannot %s\nProfiles unchanged.", reason
);
399 gboolean
delete_current_profile(void) {
400 const gchar
*name
= get_profile_name();
403 if (profile_exists(name
, FALSE
) && strcmp (name
, DEFAULT_PROFILE
) != 0) {
404 if (delete_persconffile_profile(name
, &pf_dir_path
) == -1) {
405 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
406 "Can't delete profile directory\n\"%s\":\n%s.",
407 pf_dir_path
, g_strerror(errno
));
423 * indent-tabs-mode: nil
426 * ex: set shiftwidth=4 tabstop=8 expandtab:
427 * :indentSize=4:tabSize=8:noTabs=true: