nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* profile.c |
2 | * Dialog box for profiles editing |
||
3 | * Stig Bjorlykke <stig@bjorlykke.org>, 2008 |
||
4 | * |
||
5 | * Wireshark - Network traffic analyzer |
||
6 | * By Gerald Combs <gerald@wireshark.org> |
||
7 | * Copyright 1998 Gerald Combs |
||
8 | * |
||
9 | * This program is free software; you can redistribute it and/or |
||
10 | * modify it under the terms of the GNU General Public License |
||
11 | * as published by the Free Software Foundation; either version 2 |
||
12 | * of the License, or (at your option) any later version. |
||
13 | * |
||
14 | * This program is distributed in the hope that it will be useful, |
||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
17 | * GNU General Public License for more details. |
||
18 | * |
||
19 | * You should have received a copy of the GNU General Public License |
||
20 | * along with this program; if not, write to the Free Software |
||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
22 | */ |
||
23 | |||
24 | #include "config.h" |
||
25 | |||
26 | #include <string.h> |
||
27 | #include <errno.h> |
||
28 | |||
29 | #include <glib.h> |
||
30 | |||
31 | #include <wsutil/filesystem.h> |
||
32 | |||
33 | #include "profile.h" |
||
34 | |||
35 | #include "ui/simple_dialog.h" |
||
36 | |||
37 | #include <wsutil/file_util.h> |
||
38 | |||
39 | static GList *current_profiles = NULL; |
||
40 | static GList *edited_profiles = NULL; |
||
41 | |||
42 | #define PROF_OPERATION_NEW 1 |
||
43 | #define PROF_OPERATION_EDIT 2 |
||
44 | |||
45 | GList * current_profile_list(void) { |
||
46 | return g_list_first(current_profiles); |
||
47 | } |
||
48 | |||
49 | GList * edited_profile_list(void) { |
||
50 | return g_list_first(edited_profiles); |
||
51 | } |
||
52 | |||
53 | static GList * |
||
54 | add_profile_entry(GList *fl, const char *profilename, const char *reference, int status, |
||
55 | gboolean is_global, gboolean from_global) |
||
56 | { |
||
57 | profile_def *profile; |
||
58 | |||
59 | profile = (profile_def *) g_malloc0(sizeof(profile_def)); |
||
60 | profile->name = g_strdup(profilename); |
||
61 | profile->reference = g_strdup(reference); |
||
62 | profile->status = status; |
||
63 | profile->is_global = is_global; |
||
64 | profile->from_global = from_global; |
||
65 | return g_list_append(fl, profile); |
||
66 | } |
||
67 | |||
68 | static GList * |
||
69 | remove_profile_entry(GList *fl, GList *fl_entry) |
||
70 | { |
||
71 | profile_def *profile; |
||
72 | |||
73 | profile = (profile_def *) fl_entry->data; |
||
74 | g_free(profile->name); |
||
75 | g_free(profile->reference); |
||
76 | g_free(profile); |
||
77 | return g_list_remove_link(fl, fl_entry); |
||
78 | } |
||
79 | |||
80 | const gchar * |
||
81 | get_profile_parent (const gchar *profilename) |
||
82 | { |
||
83 | GList *fl_entry = g_list_first(edited_profiles); |
||
84 | guint no_edited = g_list_length(edited_profiles); |
||
85 | profile_def *profile; |
||
86 | guint i; |
||
87 | |||
88 | if (fl_entry) { |
||
89 | /* We have edited profiles, find parent */ |
||
90 | for (i = 0; i < no_edited; i++) { |
||
91 | while (fl_entry) { |
||
92 | profile = (profile_def *) fl_entry->data; |
||
93 | if (strcmp (profile->name, profilename) == 0) { |
||
94 | if ((profile->status == PROF_STAT_NEW) || |
||
95 | (profile->reference == NULL)) { |
||
96 | /* Copy from a new profile */ |
||
97 | return NULL; |
||
98 | } else { |
||
99 | /* Found a parent, use this */ |
||
100 | profilename = profile->reference; |
||
101 | } |
||
102 | } |
||
103 | fl_entry = g_list_next(fl_entry); |
||
104 | } |
||
105 | fl_entry = g_list_first(edited_profiles); |
||
106 | } |
||
107 | } |
||
108 | |||
109 | return profilename; |
||
110 | } |
||
111 | |||
112 | const gchar *apply_profile_changes(void) { |
||
113 | char *pf_dir_path, *pf_dir_path2, *pf_filename; |
||
114 | GList *fl1, *fl2; |
||
115 | profile_def *profile1, *profile2; |
||
116 | gboolean found; |
||
117 | const gchar *err_msg; |
||
118 | |||
119 | /* First validate all profile names */ |
||
120 | fl1 = edited_profile_list(); |
||
121 | while (fl1) { |
||
122 | profile1 = (profile_def *) fl1->data; |
||
123 | g_strstrip(profile1->name); |
||
124 | if ((err_msg = profile_name_is_valid(profile1->name)) != NULL) { |
||
125 | return err_msg; |
||
126 | } |
||
127 | fl1 = g_list_next(fl1); |
||
128 | } |
||
129 | |||
130 | /* Then do all copy profiles */ |
||
131 | fl1 = edited_profile_list(); |
||
132 | while (fl1) { |
||
133 | profile1 = (profile_def *) fl1->data; |
||
134 | g_strstrip(profile1->name); |
||
135 | if (profile1->status == PROF_STAT_COPY) { |
||
136 | if (create_persconffile_profile(profile1->name, &pf_dir_path) == -1) { |
||
137 | err_msg = g_strdup_printf("Can't create directory\n\"%s\":\n%s.", |
||
138 | pf_dir_path, g_strerror(errno)); |
||
139 | |||
140 | g_free(pf_dir_path); |
||
141 | return err_msg; |
||
142 | } |
||
143 | profile1->status = PROF_STAT_EXISTS; |
||
144 | |||
145 | if (profile1->reference) { |
||
146 | if (copy_persconffile_profile(profile1->name, profile1->reference, profile1->from_global, |
||
147 | &pf_filename, &pf_dir_path, &pf_dir_path2) == -1) { |
||
148 | simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, |
||
149 | "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.", |
||
150 | pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno)); |
||
151 | |||
152 | g_free(pf_filename); |
||
153 | g_free(pf_dir_path); |
||
154 | g_free(pf_dir_path2); |
||
155 | } |
||
156 | } |
||
157 | |||
158 | g_free (profile1->reference); |
||
159 | profile1->reference = g_strdup(profile1->name); |
||
160 | } |
||
161 | fl1 = g_list_next(fl1); |
||
162 | } |
||
163 | |||
164 | |||
165 | /* Then create new and rename changed */ |
||
166 | fl1 = edited_profile_list(); |
||
167 | while (fl1) { |
||
168 | profile1 = (profile_def *) fl1->data; |
||
169 | g_strstrip(profile1->name); |
||
170 | if (profile1->status == PROF_STAT_NEW) { |
||
171 | /* We do not create a directory for the default profile */ |
||
172 | if (strcmp(profile1->name, DEFAULT_PROFILE)!=0) { |
||
173 | if (create_persconffile_profile(profile1->name, &pf_dir_path) == -1) { |
||
174 | simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, |
||
175 | "Can't create directory\n\"%s\":\n%s.", |
||
176 | pf_dir_path, g_strerror(errno)); |
||
177 | |||
178 | g_free(pf_dir_path); |
||
179 | } |
||
180 | profile1->status = PROF_STAT_EXISTS; |
||
181 | |||
182 | g_free (profile1->reference); |
||
183 | profile1->reference = g_strdup(profile1->name); |
||
184 | } |
||
185 | } else if (profile1->status == PROF_STAT_CHANGED) { |
||
186 | if (strcmp(profile1->reference, profile1->name)!=0) { |
||
187 | /* Rename old profile directory to new */ |
||
188 | if (rename_persconffile_profile(profile1->reference, profile1->name, |
||
189 | &pf_dir_path, &pf_dir_path2) == -1) { |
||
190 | simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, |
||
191 | "Can't rename directory\n\"%s\" to\n\"%s\":\n%s.", |
||
192 | pf_dir_path, pf_dir_path2, g_strerror(errno)); |
||
193 | |||
194 | g_free(pf_dir_path); |
||
195 | g_free(pf_dir_path2); |
||
196 | } |
||
197 | profile1->status = PROF_STAT_EXISTS; |
||
198 | g_free (profile1->reference); |
||
199 | profile1->reference = g_strdup(profile1->name); |
||
200 | } |
||
201 | } |
||
202 | fl1 = g_list_next(fl1); |
||
203 | } |
||
204 | |||
205 | /* Last remove deleted */ |
||
206 | fl1 = current_profile_list(); |
||
207 | while (fl1) { |
||
208 | found = FALSE; |
||
209 | profile1 = (profile_def *) fl1->data; |
||
210 | fl2 = edited_profile_list(); |
||
211 | while (fl2) { |
||
212 | profile2 = (profile_def *) fl2->data; |
||
213 | if (!profile2->is_global) { |
||
214 | if (strcmp(profile1->name, profile2->name)==0) { |
||
215 | /* Profile exists in both lists */ |
||
216 | found = TRUE; |
||
217 | } else if (strcmp(profile1->name, profile2->reference)==0) { |
||
218 | /* Profile has been renamed */ |
||
219 | found = TRUE; |
||
220 | } |
||
221 | } |
||
222 | fl2 = g_list_next(fl2); |
||
223 | } |
||
224 | if (!found) { |
||
225 | /* Exists in existing list and not in edited, this is a deleted profile */ |
||
226 | if (delete_persconffile_profile(profile1->name, &pf_dir_path) == -1) { |
||
227 | simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, |
||
228 | "Can't delete profile directory\n\"%s\":\n%s.", |
||
229 | pf_dir_path, g_strerror(errno)); |
||
230 | |||
231 | g_free(pf_dir_path); |
||
232 | } |
||
233 | } |
||
234 | fl1 = g_list_next(fl1); |
||
235 | } |
||
236 | |||
237 | copy_profile_list(); |
||
238 | return NULL; |
||
239 | } |
||
240 | |||
241 | GList * |
||
242 | add_to_profile_list(const char *name, const char *expression, int status, |
||
243 | gboolean is_global, gboolean from_global) |
||
244 | { |
||
245 | edited_profiles = add_profile_entry(edited_profiles, name, expression, status, |
||
246 | is_global, from_global); |
||
247 | |||
248 | return g_list_last(edited_profiles); |
||
249 | } |
||
250 | |||
251 | void |
||
252 | remove_from_profile_list(GList *fl_entry) |
||
253 | { |
||
254 | edited_profiles = remove_profile_entry(edited_profiles, fl_entry); |
||
255 | } |
||
256 | |||
257 | void |
||
258 | empty_profile_list(gboolean edit_list) |
||
259 | { |
||
260 | GList **flpp; |
||
261 | |||
262 | if (edit_list) { |
||
263 | flpp = &edited_profiles; |
||
264 | |||
265 | while(*flpp) { |
||
266 | *flpp = remove_profile_entry(*flpp, g_list_first(*flpp)); |
||
267 | } |
||
268 | |||
269 | g_assert(g_list_length(*flpp) == 0); |
||
270 | } |
||
271 | |||
272 | flpp = ¤t_profiles; |
||
273 | |||
274 | while(*flpp) { |
||
275 | *flpp = remove_profile_entry(*flpp, g_list_first(*flpp)); |
||
276 | } |
||
277 | |||
278 | g_assert(g_list_length(*flpp) == 0); |
||
279 | } |
||
280 | |||
281 | void |
||
282 | copy_profile_list(void) |
||
283 | { |
||
284 | GList *flp_src; |
||
285 | profile_def *profile; |
||
286 | |||
287 | flp_src = edited_profiles; |
||
288 | |||
289 | /* throw away the "old" destination list - a NULL list is ok here */ |
||
290 | empty_profile_list(FALSE); |
||
291 | |||
292 | /* copy the list entries */ |
||
293 | while(flp_src) { |
||
294 | profile = (profile_def *)(flp_src)->data; |
||
295 | |||
296 | current_profiles = add_profile_entry(current_profiles, profile->name, |
||
297 | profile->reference, profile->status, |
||
298 | profile->is_global, profile->from_global); |
||
299 | flp_src = g_list_next(flp_src); |
||
300 | } |
||
301 | } |
||
302 | |||
303 | void |
||
304 | init_profile_list(void) |
||
305 | { |
||
306 | WS_DIR *dir; /* scanned directory */ |
||
307 | WS_DIRENT *file; /* current file */ |
||
308 | const gchar *profiles_dir, *name; |
||
309 | gchar *filename; |
||
310 | |||
311 | empty_profile_list(TRUE); |
||
312 | |||
313 | /* Default entry */ |
||
314 | add_to_profile_list(DEFAULT_PROFILE, DEFAULT_PROFILE, PROF_STAT_DEFAULT, FALSE, FALSE); |
||
315 | |||
316 | /* Local (user) profiles */ |
||
317 | profiles_dir = get_profiles_dir(); |
||
318 | if ((dir = ws_dir_open(profiles_dir, 0, NULL)) != NULL) { |
||
319 | while ((file = ws_dir_read_name(dir)) != NULL) { |
||
320 | name = ws_dir_get_name(file); |
||
321 | filename = g_strdup_printf ("%s%s%s", profiles_dir, G_DIR_SEPARATOR_S, name); |
||
322 | |||
323 | if (test_for_directory(filename) == EISDIR) { |
||
324 | /*fl_entry =*/ add_to_profile_list(name, name, PROF_STAT_EXISTS, FALSE, FALSE); |
||
325 | } |
||
326 | g_free (filename); |
||
327 | } |
||
328 | ws_dir_close (dir); |
||
329 | } |
||
330 | |||
331 | /* Global profiles */ |
||
332 | profiles_dir = get_global_profiles_dir(); |
||
333 | if ((dir = ws_dir_open(profiles_dir, 0, NULL)) != NULL) { |
||
334 | while ((file = ws_dir_read_name(dir)) != NULL) { |
||
335 | name = ws_dir_get_name(file); |
||
336 | filename = g_strdup_printf ("%s%s%s", profiles_dir, G_DIR_SEPARATOR_S, name); |
||
337 | |||
338 | if (test_for_directory(filename) == EISDIR) { |
||
339 | /*fl_entry =*/ add_to_profile_list(name, name, PROF_STAT_EXISTS, TRUE, TRUE); |
||
340 | /*profile = (profile_def *) fl_entry->data;*/ |
||
341 | } |
||
342 | g_free (filename); |
||
343 | } |
||
344 | ws_dir_close (dir); |
||
345 | } |
||
346 | |||
347 | /* Make the current list and the edited list equal */ |
||
348 | copy_profile_list (); |
||
349 | } |
||
350 | |||
351 | gchar * |
||
352 | profile_name_is_valid(const gchar *name) |
||
353 | { |
||
354 | gchar *reason = NULL; |
||
355 | gchar *message; |
||
356 | |||
357 | #ifdef _WIN32 |
||
358 | char *invalid_dir_char = "\\/:*?\"<>|"; |
||
359 | gboolean invalid = FALSE; |
||
360 | int i; |
||
361 | |||
362 | for (i = 0; i < 9; i++) { |
||
363 | if (strchr(name, invalid_dir_char[i])) { |
||
364 | /* Invalid character in directory */ |
||
365 | invalid = TRUE; |
||
366 | } |
||
367 | } |
||
368 | if (name[0] == '.' || name[strlen(name)-1] == '.') { |
||
369 | /* Profile name cannot start or end with period */ |
||
370 | invalid = TRUE; |
||
371 | } |
||
372 | if (invalid) { |
||
373 | reason = g_strdup_printf("start or end with period (.), or contain any of the following characters:\n" |
||
374 | " \\ / : * ? \" < > |"); |
||
375 | } |
||
376 | #else |
||
377 | if (strchr(name, '/')) { |
||
378 | /* Invalid character in directory */ |
||
379 | reason = g_strdup_printf("contain the '/' character."); |
||
380 | } |
||
381 | #endif |
||
382 | |||
383 | if (reason) { |
||
384 | message = g_strdup_printf("A profile name cannot %s\nProfiles unchanged.", reason); |
||
385 | g_free(reason); |
||
386 | return message; |
||
387 | } |
||
388 | |||
389 | return NULL; |
||
390 | } |
||
391 | |||
392 | gboolean delete_current_profile(void) { |
||
393 | const gchar *name = get_profile_name(); |
||
394 | char *pf_dir_path; |
||
395 | |||
396 | if (profile_exists(name, FALSE) && strcmp (name, DEFAULT_PROFILE) != 0) { |
||
397 | if (delete_persconffile_profile(name, &pf_dir_path) == -1) { |
||
398 | simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, |
||
399 | "Can't delete profile directory\n\"%s\":\n%s.", |
||
400 | pf_dir_path, g_strerror(errno)); |
||
401 | |||
402 | g_free(pf_dir_path); |
||
403 | } else { |
||
404 | return TRUE; |
||
405 | } |
||
406 | } |
||
407 | return FALSE; |
||
408 | } |
||
409 | |||
410 | /* |
||
411 | * Editor modelines |
||
412 | * |
||
413 | * Local Variables: |
||
414 | * c-basic-offset: 4 |
||
415 | * tab-width: 8 |
||
416 | * indent-tabs-mode: nil |
||
417 | * End: |
||
418 | * |
||
419 | * ex: set shiftwidth=4 tabstop=8 expandtab: |
||
420 | * :indentSize=4:tabSize=8:noTabs=true: |
||
421 | */ |