sec_vt_header: dissect cont_id + opnum
[wireshark-wip.git] / ui / profile.c
blob60326646bef63a6179b868aa10318af2e245d771
1 /* profile.c
2 * Dialog box for profiles editing
3 * Stig Bjorlykke <stig@bjorlykke.org>, 2008
5 * $Id$
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.
26 #include "config.h"
28 #include <string.h>
29 #include <errno.h>
31 #include <glib.h>
33 #include <epan/emem.h>
34 #include <epan/filesystem.h>
35 #include <epan/prefs.h>
37 #include "profile.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);
58 static GList *
59 add_profile_entry(GList *fl, const char *profilename, const char *reference, int status,
60 gboolean is_global, gboolean from_global)
62 profile_def *profile;
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);
73 static GList *
74 remove_profile_entry(GList *fl, GList *fl_entry)
76 profile_def *profile;
78 profile = (profile_def *) fl_entry->data;
79 g_free(profile->name);
80 g_free(profile->reference);
81 g_free(profile);
82 return g_list_remove_link(fl, fl_entry);
85 const gchar *
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);
90 profile_def *profile;
91 guint i;
93 if (fl_entry) {
94 /* We have edited profiles, find parent */
95 for (i = 0; i < no_edited; i++) {
96 while (fl_entry) {
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 */
102 return NULL;
103 } else {
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);
114 return profilename;
117 const gchar *apply_profile_changes(void) {
118 char *pf_dir_path, *pf_dir_path2, *pf_filename;
119 GList *fl1, *fl2;
120 profile_def *profile1, *profile2;
121 gboolean found;
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();
127 while (fl1) {
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);
132 return message->str;
134 fl1 = g_list_next(fl1);
137 /* Then do all copy profiles */
138 fl1 = edited_profile_list();
139 while (fl1) {
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));
148 g_free(pf_dir_path);
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));
159 g_free(pf_filename);
160 g_free(pf_dir_path);
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();
174 while (fl1) {
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));
185 g_free(pf_dir_path);
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));
201 g_free(pf_dir_path);
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();
214 while (fl1) {
215 found = FALSE;
216 profile1 = (profile_def *) fl1->data;
217 fl2 = edited_profile_list();
218 while (fl2) {
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 */
223 found = TRUE;
224 } else if (strcmp(profile1->name, profile2->reference)==0) {
225 /* Profile has been renamed */
226 found = TRUE;
229 fl2 = g_list_next(fl2);
231 if (!found) {
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));
238 g_free(pf_dir_path);
241 fl1 = g_list_next(fl1);
244 copy_profile_list();
245 return NULL;
248 GList *
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);
258 void
259 remove_from_profile_list(GList *fl_entry)
261 edited_profiles = remove_profile_entry(edited_profiles, fl_entry);
264 void
265 empty_profile_list(gboolean edit_list)
267 GList **flpp;
269 if (edit_list) {
270 flpp = &edited_profiles;
272 while(*flpp) {
273 *flpp = remove_profile_entry(*flpp, g_list_first(*flpp));
276 g_assert(g_list_length(*flpp) == 0);
279 flpp = &current_profiles;
281 while(*flpp) {
282 *flpp = remove_profile_entry(*flpp, g_list_first(*flpp));
285 g_assert(g_list_length(*flpp) == 0);
288 void
289 copy_profile_list(void)
291 GList *flp_src;
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 */
300 while(flp_src) {
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);
310 void
311 init_profile_list(void)
313 WS_DIR *dir; /* scanned directory */
314 WS_DIRENT *file; /* current file */
315 const gchar *profiles_dir, *name;
316 gchar *filename;
318 empty_profile_list(TRUE);
320 /* Default entry */
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);
333 g_free (filename);
335 ws_dir_close (dir);
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;*/
349 g_free (filename);
351 ws_dir_close (dir);
354 /* Make the current list and the edited list equal */
355 copy_profile_list ();
358 const gchar *
359 profile_name_is_valid(const gchar *name)
361 gchar *reason = NULL;
362 emem_strbuf_t *message = ep_strbuf_new(NULL);
364 #ifdef _WIN32
365 char *invalid_dir_char = "\\/:*?\"<>|";
366 gboolean invalid = FALSE;
367 int i;
369 for (i = 0; i < 9; i++) {
370 if (strchr(name, invalid_dir_char[i])) {
371 /* Invalid character in directory */
372 invalid = TRUE;
375 if (name[0] == '.' || name[strlen(name)-1] == '.') {
376 /* Profile name cannot start or end with period */
377 invalid = TRUE;
379 if (invalid) {
380 reason = g_strdup_printf("start or end with period (.), or contain any of the following characters:\n"
381 " \\ / : * ? \" &lt; &gt; |");
383 #else
384 if (strchr(name, '/')) {
385 /* Invalid character in directory */
386 reason = g_strdup_printf("contain the '/' character.");
388 #endif
390 if (reason) {
391 ep_strbuf_printf(message, "A profile name cannot %s\nProfiles unchanged.", reason);
392 g_free(reason);
393 return message->str;
396 return NULL;
399 gboolean delete_current_profile(void) {
400 const gchar *name = get_profile_name();
401 char *pf_dir_path;
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));
409 g_free(pf_dir_path);
410 } else {
411 return TRUE;
414 return FALSE;
418 * Editor modelines
420 * Local Variables:
421 * c-basic-offset: 4
422 * tab-width: 8
423 * indent-tabs-mode: nil
424 * End:
426 * ex: set shiftwidth=4 tabstop=8 expandtab:
427 * :indentSize=4:tabSize=8:noTabs=true: