Ignore preferences for deleted protocols "etheric" and "isup_thin".
[metze/wireshark/wip.git] / epan / prefs.c
1 /* prefs.c
2  * Routines for handling preferences
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <errno.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <glib.h>
39
40 #include <stdio.h>
41 #include <epan/filesystem.h>
42 #include <epan/address.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/packet.h>
45 #include <epan/prefs.h>
46 #include <epan/proto.h>
47 #include "cfile.h"
48 #include <epan/column.h>
49 #include "print.h"
50 #include <wsutil/file_util.h>
51
52 #include <epan/prefs-int.h>
53 #include <epan/uat-int.h>
54
55 /* Internal functions */
56 static module_t *find_subtree(module_t *parent, const char *tilte);
57 static module_t *prefs_register_module_or_subtree(module_t *parent,
58     const char *name, const char *title, const char *description, gboolean is_subtree,
59     void (*apply_cb)(void));
60 static prefs_set_pref_e set_pref(gchar*, gchar*, void *);
61 static gchar *put_string_list(GList *);
62 static void   free_col_info(e_prefs *);
63
64 #define PF_NAME         "preferences"
65 #define OLD_GPF_NAME    "wireshark.conf"        /* old name for global preferences file */
66
67 static gboolean prefs_initialized = FALSE;
68 static gchar *gpf_path = NULL;
69
70 /*
71  * XXX - variables to allow us to attempt to interpret the first
72  * "mgcp.{tcp,udp}.port" in a preferences file as
73  * "mgcp.{tcp,udp}.gateway_port" and the second as
74  * "mgcp.{tcp,udp}.callagent_port".
75  */
76 static int mgcp_tcp_port_count;
77 static int mgcp_udp_port_count;
78
79 e_prefs prefs;
80
81 static const gchar      *gui_ptree_line_style_text[] =
82         { "NONE", "SOLID", "DOTTED", "TABBED", NULL };
83
84 static const gchar      *gui_ptree_expander_style_text[] =
85         { "NONE", "SQUARE", "TRIANGLE", "CIRCULAR", NULL };
86
87 static const gchar      *gui_hex_dump_highlight_style_text[] =
88         { "BOLD", "INVERSE", NULL };
89
90 static const gchar      *gui_console_open_text[] =
91         { "NEVER", "AUTOMATIC", "ALWAYS", NULL };
92
93 static const gchar      *gui_fileopen_style_text[] =
94         { "LAST_OPENED", "SPECIFIED", NULL };
95
96 /* GTK knows of two ways representing "both", vertical and horizontal aligned.
97  * as this may not work on other guis, we use only "both" in general here */
98 static const gchar      *gui_toolbar_style_text[] =
99         { "ICONS", "TEXT", "BOTH", NULL };
100
101 static const gchar      *gui_layout_content_text[] =
102         { "NONE", "PLIST", "PDETAILS", "PBYTES", NULL };
103
104 /*
105  * List of all modules with preference settings.
106  */
107 static emem_tree_t *prefs_modules = NULL;
108
109 /*
110  * List of all modules that should show up at the top level of the
111  * tree in the preference dialog box.
112  */
113 static emem_tree_t *prefs_top_level_modules = NULL;
114
115 /** Sets up memory used by proto routines. Called at program startup */
116 void prefs_init(void)
117 {
118   prefs_modules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_modules");
119   prefs_top_level_modules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_top_level_modules");
120 }
121
122 /** Frees memory used by proto routines. Called at program shutdown */
123 void prefs_cleanup(void)
124 {
125 }
126
127 /*
128  * Register a module that will have preferences.
129  * Specify the module under which to register it or NULL to register it
130  * at the top level, the name used for the module in the preferences file,
131  * the title used in the tab for it in a preferences dialog box, and a
132  * routine to call back when we apply the preferences.
133  */
134 module_t *
135 prefs_register_module(module_t *parent, const char *name, const char *title,
136     const char *description, void (*apply_cb)(void))
137 {
138         return prefs_register_module_or_subtree(parent, name, title, description,
139             FALSE, apply_cb);
140 }
141
142 /*
143  * Register a subtree that will have modules under it.
144  * Specify the module under which to register it or NULL to register it
145  * at the top level and the title used in the tab for it in a preferences
146  * dialog box.
147  */
148 module_t *
149 prefs_register_subtree(module_t *parent, const char *title, const char *description)
150 {
151         return prefs_register_module_or_subtree(parent, NULL, title, description, TRUE,
152             NULL);
153 }
154
155 static module_t *
156 prefs_register_module_or_subtree(module_t *parent, const char *name,
157     const char *title, const char *description, gboolean is_subtree, void (*apply_cb)(void))
158 {
159         module_t *module;
160         const char *p;
161         guchar c;
162
163         /* this module may have been created as a subtree item previously */
164         if((module = find_subtree(parent, title))) {
165           /* the module is currently a subtree */
166           module->name = name;
167           module->apply_cb = apply_cb;
168           module->description = description;
169
170           if (prefs_find_module(name) == NULL) {
171                 pe_tree_insert_string(prefs_modules, name, module, EMEM_TREE_STRING_NOCASE);
172           }
173
174           return module;
175         }
176
177         module = g_malloc(sizeof (module_t));
178         module->name = name;
179         module->title = title;
180         module->description = description;
181         module->apply_cb = apply_cb;
182         module->prefs = NULL;   /* no preferences, to start */
183         module->submodules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_submodules");
184         module->numprefs = 0;
185         module->prefs_changed = FALSE;
186         module->obsolete = FALSE;
187
188         /*
189          * Do we have a module name?
190          */
191         if (name != NULL) {
192                 /*
193                  * Yes.
194                  * Make sure that only lower-case ASCII letters, numbers,
195                  * underscores, hyphens, and dots appear in the name.
196                  *
197                  * Crash if there is, as that's an error in the code;
198                  * you can make the title a nice string with capitalization,
199                  * white space, punctuation, etc., but the name can be used
200                  * on the command line, and shouldn't require quoting,
201                  * shifting, etc.
202                  */
203                 for (p = name; (c = *p) != '\0'; p++)
204                         g_assert(isascii(c) &&
205                             (islower(c) || isdigit(c) || c == '_' ||
206                              c == '-' || c == '.'));
207
208                 /*
209                  * Make sure there's not already a module with that
210                  * name.  Crash if there is, as that's an error in the
211                  * code, and the code has to be fixed not to register
212                  * more than one module with the same name.
213                  *
214                  * We search the list of all modules; the subtree stuff
215                  * doesn't require preferences in subtrees to have names
216                  * that reflect the subtree they're in (that would require
217                  * protocol preferences to have a bogus "protocol.", or
218                  * something such as that, to be added to all their names).
219                  */
220                 g_assert(prefs_find_module(name) == NULL);
221
222                 /*
223                  * Insert this module in the list of all modules.
224                  */
225                 pe_tree_insert_string(prefs_modules, name, module, EMEM_TREE_STRING_NOCASE);
226         } else {
227                 /*
228                  * This has no name, just a title; check to make sure it's a
229                  * subtree, and crash if it's not.
230                  */
231                 g_assert(is_subtree);
232         }
233
234         /*
235          * Insert this module into the appropriate place in the display
236          * tree.
237          */
238         if (parent == NULL) {
239                 /*
240                  * It goes at the top.
241                  */
242                 pe_tree_insert_string(prefs_top_level_modules, title, module, EMEM_TREE_STRING_NOCASE);
243         } else {
244                 /*
245                  * It goes into the list for this module.
246                  */
247                 pe_tree_insert_string(parent->submodules, title, module, EMEM_TREE_STRING_NOCASE);
248         }
249
250         return module;
251 }
252
253 /*
254  * Register that a protocol has preferences.
255  */
256 module_t *protocols_module;
257
258 module_t *
259 prefs_register_protocol(int id, void (*apply_cb)(void))
260 {
261         protocol_t *protocol;
262
263         /*
264          * Have we yet created the "Protocols" subtree?
265          */
266         if (protocols_module == NULL) {
267                 /*
268                  * No.  Do so.
269                  */
270                 protocols_module = prefs_register_subtree(NULL, "Protocols", NULL);
271         }
272         protocol = find_protocol_by_id(id);
273         return prefs_register_module(protocols_module,
274             proto_get_protocol_filter_name(id),
275             proto_get_protocol_short_name(protocol),
276             proto_get_protocol_name(id), apply_cb);
277 }
278
279
280 module_t *
281 prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
282 {
283         protocol_t *protocol;
284         module_t   *subtree_module;
285         module_t   *new_module;
286         char       *sep = NULL, *ptr = NULL;
287         char       *csubtree = NULL;
288
289         /*
290          * Have we yet created the "Protocols" subtree?
291          */
292         if (protocols_module == NULL) {
293                 /*
294                  * No.  Do so.
295                  */
296                 protocols_module = prefs_register_subtree(NULL, "Protocols", NULL);
297         }
298
299         subtree_module = protocols_module;
300
301         if(subtree) {
302           /* take a copy of the buffer */
303           ptr = csubtree = g_strdup(subtree);
304
305           while(ptr && *ptr) {
306
307             if((sep = strchr(ptr, '/')))
308               *sep++ = '\0';
309
310             if(!(new_module = find_subtree(subtree_module, ptr))) {
311               /* create it */
312               new_module = prefs_register_subtree(subtree_module, ptr, NULL);
313             }
314
315             subtree_module = new_module;
316             ptr = sep;
317
318           }
319
320           /* g_free(csubtree); */
321
322         }
323
324         protocol = find_protocol_by_id(id);
325         return prefs_register_module(subtree_module,
326             proto_get_protocol_filter_name(id),
327             proto_get_protocol_short_name(protocol),
328             proto_get_protocol_name(id), apply_cb);
329 }
330
331
332 /*
333  * Register that a protocol used to have preferences but no longer does,
334  * by creating an "obsolete" module for it.
335  */
336 module_t *
337 prefs_register_protocol_obsolete(int id)
338 {
339         module_t *module;
340         protocol_t *protocol;
341
342         /*
343          * Have we yet created the "Protocols" subtree?
344          */
345         if (protocols_module == NULL) {
346                 /*
347                  * No.  Do so.
348                  */
349                 protocols_module = prefs_register_subtree(NULL, "Protocols", NULL);
350         }
351         protocol = find_protocol_by_id(id);
352         module = prefs_register_module(protocols_module,
353             proto_get_protocol_filter_name(id),
354             proto_get_protocol_short_name(protocol),
355             proto_get_protocol_name(id), NULL);
356         module->obsolete = TRUE;
357         return module;
358 }
359
360 module_t *
361 prefs_find_module(const char *name)
362 {
363         return pe_tree_lookup_string(prefs_modules, name, EMEM_TREE_STRING_NOCASE);
364 }
365
366 static module_t *
367 find_subtree(module_t *parent, const char *name)
368 {
369         return pe_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, EMEM_TREE_STRING_NOCASE);
370 }
371
372 /*
373  * Call a callback function, with a specified argument, for each module
374  * in a list of modules.  If the list is NULL, searches the top-level
375  * list in the display tree of modules.  If any callback returns a
376  * non-zero value, we stop and return that value, otherwise we
377  * return 0.
378  *
379  * Ignores "obsolete" modules; their sole purpose is to allow old
380  * preferences for dissectors that no longer have preferences to be
381  * silently ignored in preference files.  Does not ignore subtrees,
382  * as this can be used when walking the display tree of modules.
383  */
384
385 typedef struct {
386         module_cb callback;
387         gpointer user_data;
388         guint ret;
389 } call_foreach_t;
390
391 static gboolean
392 call_foreach_cb(void *value, void *data)
393 {
394         module_t *module = (module_t*)value;
395         call_foreach_t *call_data = (call_foreach_t*)data;
396
397         if (!module->obsolete) {
398                 call_data->ret = (*call_data->callback)(module, call_data->user_data);
399         }
400         return (call_data->ret != 0);
401 }
402
403 static guint
404 prefs_module_list_foreach(emem_tree_t *module_list, module_cb callback,
405     gpointer user_data)
406 {
407         call_foreach_t call_data;
408
409         if (module_list == NULL)
410                 module_list = prefs_top_level_modules;
411
412         call_data.callback = callback;
413         call_data.user_data = user_data;
414         call_data.ret = 0;
415         pe_tree_foreach(module_list, call_foreach_cb, &call_data);
416         return call_data.ret;
417 }
418
419 /*
420  * Returns TRUE if module has any submodules
421  */
422 gboolean prefs_module_has_submodules(module_t *module)
423 {
424         if (module->submodules == NULL) {
425                 return FALSE;
426         }
427
428         if (module->submodules->tree == NULL) {
429                 return FALSE;
430         }
431
432         return TRUE;
433 }
434
435 /*
436  * Call a callback function, with a specified argument, for each module
437  * in the list of all modules.  (This list does not include subtrees.)
438  *
439  * Ignores "obsolete" modules; their sole purpose is to allow old
440  * preferences for dissectors that no longer have preferences to be
441  * silently ignored in preference files.
442  */
443 guint
444 prefs_modules_foreach(module_cb callback, gpointer user_data)
445 {
446         return prefs_module_list_foreach(prefs_modules, callback, user_data);
447 }
448
449 /*
450  * Call a callback function, with a specified argument, for each submodule
451  * of specified modules.  If the module is NULL, goes through the top-level
452  * list in the display tree of modules.
453  *
454  * Ignores "obsolete" modules; their sole purpose is to allow old
455  * preferences for dissectors that no longer have preferences to be
456  * silently ignored in preference files.  Does not ignore subtrees,
457  * as this can be used when walking the display tree of modules.
458  */
459 guint
460 prefs_modules_foreach_submodules(module_t *module, module_cb callback, gpointer user_data)
461 {
462         return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data);
463 }
464
465 static gboolean
466 call_apply_cb(void *value, void *data _U_)
467 {
468         module_t *module = value;
469
470         if (module->obsolete)
471                 return FALSE;
472         if (module->prefs_changed) {
473                 if (module->apply_cb != NULL)
474                         (*module->apply_cb)();
475                 module->prefs_changed = FALSE;
476         }
477         return FALSE;
478 }
479
480 /*
481  * Call the "apply" callback function for each module if any of its
482  * preferences have changed, and then clear the flag saying its
483  * preferences have changed, as the module has been notified of that
484  * fact.
485  */
486 void
487 prefs_apply_all(void)
488 {
489         pe_tree_foreach(prefs_modules, call_apply_cb, NULL);
490 }
491
492 /*
493  * Call the "apply" callback function for a specific module if any of
494  * its preferences have changed, and then clear the flag saying its
495  * preferences have changed, as the module has been notified of that
496  * fact.
497  */
498 void
499 prefs_apply(module_t *module)
500 {
501         if (module && module->prefs_changed)
502                 call_apply_cb(module, NULL);
503 }
504
505 /*
506  * Register a preference in a module's list of preferences.
507  * If it has a title, give it an ordinal number; otherwise, it's a
508  * preference that won't show up in the UI, so it shouldn't get an
509  * ordinal number (the ordinal should be the ordinal in the set of
510  * *visible* preferences).
511  */
512 static pref_t *
513 register_preference(module_t *module, const char *name, const char *title,
514     const char *description, pref_type_t type)
515 {
516         pref_t *preference;
517         const gchar *p;
518
519         preference = g_malloc(sizeof (pref_t));
520         preference->name = name;
521         preference->title = title;
522         preference->description = description;
523         preference->type = type;
524         if (title != NULL)
525                 preference->ordinal = module->numprefs;
526         else
527                 preference->ordinal = -1;       /* no ordinal for you */
528
529         /*
530          * Make sure that only lower-case ASCII letters, numbers,
531          * underscores, and dots appear in the preference name.
532          *
533          * Crash if there is, as that's an error in the code;
534          * you can make the title and description nice strings
535          * with capitalization, white space, punctuation, etc.,
536          * but the name can be used on the command line,
537          * and shouldn't require quoting, shifting, etc.
538          */
539         for (p = name; *p != '\0'; p++)
540                 g_assert(isascii((guchar)*p) &&
541                     (islower((guchar)*p) || isdigit((guchar)*p) || *p == '_' || *p == '.'));
542
543         /*
544          * Make sure there's not already a preference with that
545          * name.  Crash if there is, as that's an error in the
546          * code, and the code has to be fixed not to register
547          * more than one preference with the same name.
548          */
549         g_assert(prefs_find_preference(module, name) == NULL);
550
551         if (type != PREF_OBSOLETE) {
552                 /*
553                  * Make sure the preference name doesn't begin with the
554                  * module name, as that's redundant and Just Silly.
555                  */
556                 g_assert((strncmp(name, module->name, strlen(module->name)) != 0) ||
557                         (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_')));
558         }
559
560         /*
561          * There isn't already one with that name, so add the
562          * preference.
563          */
564         module->prefs = g_list_append(module->prefs, preference);
565         if (title != NULL)
566                 module->numprefs++;
567
568         return preference;
569 }
570
571 /*
572  * Find a preference in a module's list of preferences, given the module
573  * and the preference's name.
574  */
575 static gint
576 preference_match(gconstpointer a, gconstpointer b)
577 {
578         const pref_t *pref = a;
579         const char *name = b;
580
581         return strcmp(name, pref->name);
582 }
583
584 struct preference *
585 prefs_find_preference(module_t *module, const char *name)
586 {
587         GList *list_entry;
588
589         list_entry = g_list_find_custom(module->prefs, name,
590             preference_match);
591
592         if (list_entry == NULL)
593                 return NULL;    /* no such preference */
594         return (struct preference *) list_entry->data;
595 }
596
597 /*
598  * Returns TRUE if the given protocol has registered preferences
599  */
600 gboolean
601 prefs_is_registered_protocol(const char *name)
602 {
603         module_t *m = prefs_find_module(name);
604
605         return (m != NULL && !m->obsolete);
606 }
607
608 /*
609  * Returns the module title of a registered protocol
610  */
611 const char *
612 prefs_get_title_by_name(const char *name)
613 {
614         module_t *m = prefs_find_module(name);
615
616         return (m != NULL && !m->obsolete) ? m->title : NULL;
617 }
618
619 /*
620  * Register a preference with an unsigned integral value.
621  */
622 void
623 prefs_register_uint_preference(module_t *module, const char *name,
624     const char *title, const char *description, guint base, guint *var)
625 {
626         pref_t *preference;
627
628         preference = register_preference(module, name, title, description,
629             PREF_UINT);
630         preference->varp.uint = var;
631         g_assert(base > 0 && base != 1 && base < 37);
632         preference->info.base = base;
633 }
634
635 /*
636  * Register a preference with an Boolean value.
637  */
638 void
639 prefs_register_bool_preference(module_t *module, const char *name,
640     const char *title, const char *description, gboolean *var)
641 {
642         pref_t *preference;
643
644         preference = register_preference(module, name, title, description,
645             PREF_BOOL);
646         preference->varp.boolp = var;
647 }
648
649 /*
650  * Register a preference with an enumerated value.
651  */
652 void
653 prefs_register_enum_preference(module_t *module, const char *name,
654     const char *title, const char *description, gint *var,
655     const enum_val_t *enumvals, gboolean radio_buttons)
656 {
657         pref_t *preference;
658
659         preference = register_preference(module, name, title, description,
660             PREF_ENUM);
661         preference->varp.enump = var;
662         preference->info.enum_info.enumvals = enumvals;
663         preference->info.enum_info.radio_buttons = radio_buttons;
664 }
665
666 /*
667  * Register a preference with a character-string value.
668  */
669 void
670 prefs_register_string_preference(module_t *module, const char *name,
671     const char *title, const char *description, const char **var)
672 {
673         pref_t *preference;
674
675         preference = register_preference(module, name, title, description,
676             PREF_STRING);
677
678         /*
679          * String preference values should be non-null (as you can't
680          * keep them null after using the preferences GUI, you can at best
681          * have them be null strings) and freeable (as we free them
682          * if we change them).
683          *
684          * If the value is a null pointer, make it a copy of a null
685          * string, otherwise make it a copy of the value.
686          */
687         if (*var == NULL)
688                 *var = g_strdup("");
689         else
690                 *var = g_strdup(*var);
691         preference->varp.string = var;
692         preference->saved_val.string = NULL;
693 }
694
695 /*
696  * Register a preference with a ranged value.
697  */
698 void
699 prefs_register_range_preference(module_t *module, const char *name,
700     const char *title, const char *description, range_t **var,
701     guint32 max_value)
702 {
703         pref_t *preference;
704
705         preference = register_preference(module, name, title, description,
706                                          PREF_RANGE);
707         preference->info.max_value = max_value;
708
709
710         /*
711          * Range preference values should be non-null (as you can't
712          * keep them null after using the preferences GUI, you can at best
713          * have them be empty ranges) and freeable (as we free them
714          * if we change them).
715          *
716          * If the value is a null pointer, make it an empty range.
717          */
718         if (*var == NULL)
719                 *var = range_empty();
720         preference->varp.range = var;
721         preference->saved_val.range = NULL;
722 }
723
724 /*
725  * Register a static text 'preference'.  It can be used to add explanatory
726  * text inline with other preferences in the GUI.
727  * Note: Static preferences are not saved to the preferences file.
728  */
729 void prefs_register_static_text_preference(module_t *module, const char *name,
730     const char *title, const char *description)
731 {
732         register_preference(module, name, title, description, PREF_STATIC_TEXT);
733 }
734
735 /*
736  * Register a uat 'preference'. It adds a button that opens the uat's window in the
737  * preferences tab of the module.
738  */
739 extern void prefs_register_uat_preference(module_t *module,
740                                                                                   const char *name,
741                                                                                   const char *title,
742                                                                                   const char *description,
743                                                                                   void* uat) {
744
745         pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
746
747         preference->varp.uat = uat;
748
749 }
750
751
752
753 /*
754  * Register a preference that used to be supported but no longer is.
755  */
756 void
757 prefs_register_obsolete_preference(module_t *module, const char *name)
758 {
759         register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
760 }
761
762 /*
763  * Call a callback function, with a specified argument, for each preference
764  * in a given module.
765  *
766  * If any of the callbacks return a non-zero value, stop and return that
767  * value, otherwise return 0.
768  */
769 guint
770 prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
771 {
772         GList *elem;
773         pref_t *pref;
774         guint ret;
775
776         for (elem = g_list_first(module->prefs); elem != NULL;
777             elem = g_list_next(elem)) {
778                 pref = elem->data;
779                 if (pref->type == PREF_OBSOLETE) {
780                         /*
781                          * This preference is no longer supported; it's
782                          * not a real preference, so we don't call the
783                          * callback for it (i.e., we treat it as if it
784                          * weren't found in the list of preferences,
785                          * and we weren't called in the first place).
786                          */
787                         continue;
788                 }
789
790                 ret = (*callback)(pref, user_data);
791                 if (ret != 0)
792                         return ret;
793         }
794         return 0;
795 }
796
797 /*
798  * Register all non-dissector modules' preferences.
799  */
800 void
801 prefs_register_modules(void)
802 {
803 }
804
805 /* Parse through a list of comma-separated, possibly quoted strings.
806    Return a list of the string data. */
807 GList *
808 prefs_get_string_list(gchar *str)
809 {
810   enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
811
812   gint      state = PRE_STRING, i = 0, j = 0;
813   gboolean  backslash = FALSE;
814   guchar    cur_c;
815   gchar    *slstr = NULL;
816   GList    *sl = NULL;
817
818   /* Allocate a buffer for the first string.   */
819   slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
820   j = 0;
821
822   for (;;) {
823     cur_c = str[i];
824     if (cur_c == '\0') {
825       /* It's the end of the input, so it's the end of the string we
826          were working on, and there's no more input. */
827       if (state == IN_QUOT || backslash) {
828         /* We were in the middle of a quoted string or backslash escape,
829            and ran out of characters; that's an error.  */
830         g_free(slstr);
831         prefs_clear_string_list(sl);
832         return NULL;
833       }
834       slstr[j] = '\0';
835       sl = g_list_append(sl, slstr);
836       break;
837     }
838     if (cur_c == '"' && ! backslash) {
839       switch (state) {
840         case PRE_STRING:
841           /* We hadn't yet started processing a string; this starts the
842              string, and we're now quoting.  */
843           state = IN_QUOT;
844           break;
845         case IN_QUOT:
846           /* We're in the middle of a quoted string, and we saw a quotation
847              mark; we're no longer quoting.   */
848           state = NOT_IN_QUOT;
849           break;
850         case NOT_IN_QUOT:
851           /* We're working on a string, but haven't seen a quote; we're
852              now quoting.  */
853           state = IN_QUOT;
854           break;
855         default:
856           break;
857       }
858     } else if (cur_c == '\\' && ! backslash) {
859       /* We saw a backslash, and the previous character wasn't a
860          backslash; escape the next character.
861
862          This also means we've started a new string. */
863       backslash = TRUE;
864       if (state == PRE_STRING)
865         state = NOT_IN_QUOT;
866     } else if (cur_c == ',' && state != IN_QUOT && ! backslash) {
867       /* We saw a comma, and we're not in the middle of a quoted string
868          and it wasn't preceded by a backslash; it's the end of
869          the string we were working on...  */
870       slstr[j] = '\0';
871       sl = g_list_append(sl, slstr);
872
873       /* ...and the beginning of a new string.  */
874       state = PRE_STRING;
875       slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
876       j = 0;
877     } else if (!isspace(cur_c) || state != PRE_STRING) {
878       /* Either this isn't a white-space character, or we've started a
879          string (i.e., already seen a non-white-space character for that
880          string and put it into the string).
881
882          The character is to be put into the string; do so if there's
883          room.  */
884       if (j < COL_MAX_LEN) {
885         slstr[j] = cur_c;
886         j++;
887       }
888
889       /* If it was backslash-escaped, we're done with the backslash escape.  */
890       backslash = FALSE;
891     }
892     i++;
893   }
894   return(sl);
895 }
896
897 #define MAX_FMT_PREF_LEN      1024
898 #define MAX_FMT_PREF_LINE_LEN   60
899 static gchar *
900 put_string_list(GList *sl)
901 {
902   static gchar  pref_str[MAX_FMT_PREF_LEN] = "";
903   GList        *clp = g_list_first(sl);
904   gchar        *str;
905   size_t        cur_pos = 0, cur_len = 0;
906   gchar        *quoted_str;
907   size_t        str_len;
908   gchar        *strp, *quoted_strp, c;
909   size_t        fmt_len;
910
911   while (clp) {
912     str = clp->data;
913
914     /* Allocate a buffer big enough to hold the entire string, with each
915        character quoted (that's the worst case).  */
916     str_len = strlen(str);
917     quoted_str = g_malloc(str_len*2 + 1);
918
919     /* Now quote any " or \ characters in it. */
920     strp = str;
921     quoted_strp = quoted_str;
922     while ((c = *strp++) != '\0') {
923       if (c == '"' || c == '\\') {
924         /* It has to be backslash-quoted.  */
925         *quoted_strp++ = '\\';
926       }
927       *quoted_strp++ = c;
928     }
929     *quoted_strp = '\0';
930
931     fmt_len = strlen(quoted_str) + 4;
932     if ((fmt_len + cur_len) < (MAX_FMT_PREF_LEN - 1)) {
933       if ((fmt_len + cur_pos) > MAX_FMT_PREF_LINE_LEN) {
934         /* Wrap the line.  */
935         cur_len--;
936         cur_pos = 0;
937         pref_str[cur_len] = '\n'; cur_len++;
938         pref_str[cur_len] = '\t'; cur_len++;
939       }
940       g_snprintf(&pref_str[cur_len], MAX_FMT_PREF_LEN - (gulong) cur_len, "\"%s\", ", quoted_str);
941       cur_pos += fmt_len;
942       cur_len += fmt_len;
943     }
944     g_free(quoted_str);
945     clp = clp->next;
946   }
947
948   /* If the string is at least two characters long, the last two characters
949      are ", ", and should be discarded, as there are no more items in the
950      string.  */
951   if (cur_len >= 2)
952     pref_str[cur_len - 2] = '\0';
953
954   return(pref_str);
955 }
956
957 void
958 prefs_clear_string_list(GList *sl)
959 {
960   GList *l = sl;
961
962   while (l) {
963     g_free(l->data);
964     l = g_list_remove_link(l, l);
965   }
966 }
967
968 /*
969  * Takes a string, a pointer to an array of "enum_val_t"s, and a default gint
970  * value.
971  * The array must be terminated by an entry with a null "name" string.
972  *
973  * If the string matches a "name" string in an entry, the value from that
974  * entry is returned.
975  *
976  * Otherwise, if a string matches a "desctiption" string in an entry, the
977  * value from that entry is returned; we do that for backwards compatibility,
978  * as we used to have only a "name" string that was used both for command-line
979  * and configuration-file values and in the GUI (which meant either that
980  * the GUI had what might be somewhat cryptic values to select from or that
981  * the "-o" flag took long strings, often with spaces in them).
982  *
983  * Otherwise, the default value that was passed as the third argument is
984  * returned.
985  */
986 gint
987 find_val_for_string(const char *needle, const enum_val_t *haystack,
988     gint default_value)
989 {
990         int i;
991
992         for (i = 0; haystack[i].name != NULL; i++) {
993                 if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
994                         return haystack[i].value;
995                 }
996         }
997         for (i = 0; haystack[i].name != NULL; i++) {
998                 if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
999                         return haystack[i].value;
1000                 }
1001         }
1002         return default_value;
1003 }
1004
1005 /* Takes an string and a pointer to an array of strings, and a default int value.
1006  * The array must be terminated by a NULL string. If the string is found in the array
1007  * of strings, the index of that string in the array is returned. Otherwise, the
1008  * default value that was passed as the third argument is returned.
1009  */
1010 static int
1011 find_index_from_string_array(char *needle, const char **haystack, int default_value)
1012 {
1013         int i = 0;
1014
1015         while (haystack[i] != NULL) {
1016                 if (strcmp(needle, haystack[i]) == 0) {
1017                         return i;
1018                 }
1019                 i++;
1020         }
1021         return default_value;
1022 }
1023
1024 /* Preferences file format:
1025  * - Configuration directives start at the beginning of the line, and
1026  *   are terminated with a colon.
1027  * - Directives can be continued on the next line by preceding them with
1028  *   whitespace.
1029  *
1030  * Example:
1031
1032 # This is a comment line
1033 print.command: lpr
1034 print.file: /a/very/long/path/
1035         to/wireshark-out.ps
1036  *
1037  */
1038
1039 #define DEF_NUM_COLS    6
1040
1041 /* Initialize preferences to wired-in default values.
1042  * They may be overridden by the global preferences file or the
1043  *  user's preferences file.
1044  */
1045 static void
1046 init_prefs(void) {
1047   int         i;
1048   fmt_data    *cfmt;
1049   const gchar *col_fmt[] = {"No.",      "%m", "Time",        "%t",
1050                            "Source",   "%s", "Destination", "%d",
1051                            "Protocol", "%p", "Info",        "%i"};
1052
1053   if (prefs_initialized)
1054     return;
1055
1056   uat_load_all();
1057
1058   prefs.pr_format  = PR_FMT_TEXT;
1059   prefs.pr_dest    = PR_DEST_CMD;
1060   prefs.pr_file    = g_strdup("wireshark.out");
1061   prefs.pr_cmd     = g_strdup("lpr");
1062   prefs.col_list = NULL;
1063   for (i = 0; i < DEF_NUM_COLS; i++) {
1064     cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1065     cfmt->title = g_strdup(col_fmt[i * 2]);
1066     cfmt->fmt   = g_strdup(col_fmt[(i * 2) + 1]);
1067     cfmt->custom_field = NULL;
1068     prefs.col_list = g_list_append(prefs.col_list, cfmt);
1069   }
1070   prefs.num_cols  = DEF_NUM_COLS;
1071   prefs.st_client_fg.pixel =     0;
1072   prefs.st_client_fg.red   = 32767;
1073   prefs.st_client_fg.green =     0;
1074   prefs.st_client_fg.blue  =     0;
1075   prefs.st_client_bg.pixel =     0;
1076   prefs.st_client_bg.red   = 64507;
1077   prefs.st_client_bg.green = 60909;
1078   prefs.st_client_bg.blue  = 60909;
1079   prefs.st_server_fg.pixel =     0;
1080   prefs.st_server_fg.red   =     0;
1081   prefs.st_server_fg.green =     0;
1082   prefs.st_server_fg.blue  = 32767;
1083   prefs.st_server_bg.pixel =     0;
1084   prefs.st_server_bg.red   = 60909;
1085   prefs.st_server_bg.green = 60909;
1086   prefs.st_server_bg.blue  = 64507;
1087   prefs.gui_scrollbar_on_right = TRUE;
1088   prefs.gui_plist_sel_browse = FALSE;
1089   prefs.gui_ptree_sel_browse = FALSE;
1090   prefs.gui_altern_colors = FALSE;
1091   prefs.gui_ptree_line_style = 0;
1092   prefs.gui_ptree_expander_style = 1;
1093   prefs.gui_hex_dump_highlight_style = 1;
1094   prefs.filter_toolbar_show_in_statusbar = FALSE;
1095   prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
1096 #ifdef _WIN32
1097   prefs.gui_font_name = g_strdup("Lucida Console 10");
1098 #else
1099   /*
1100    * XXX - for now, we make the initial font name a pattern that matches
1101    * only ISO 8859/1 fonts, so that we don't match 2-byte fonts such
1102    * as ISO 10646 fonts.
1103    *
1104    * Users in locales using other one-byte fonts will have to choose
1105    * a different font from the preferences dialog - or put the font
1106    * selection in the global preferences file to make that font the
1107    * default for all users who don't explicitly specify a different
1108    * font.
1109    *
1110    * Making this a font set rather than a font has two problems:
1111    *
1112    *    1) as far as I know, you can't select font sets with the
1113    *       font selection dialog;
1114    *
1115    *  2) if you use a font set, the text to be drawn must be a
1116    *       multi-byte string in the appropriate locale, but
1117    *       Wireshark does *NOT* guarantee that's the case - in
1118    *       the hex-dump window, each character in the text portion
1119    *       of the display must be a *single* byte, and in the
1120    *       packet-list and protocol-tree windows, text extracted
1121    *       from the packet is not necessarily in the right format.
1122    *
1123    * "Doing this right" may, for the packet-list and protocol-tree
1124    * windows, require that dissectors know what the locale is
1125    * *AND* know what locale and text representation is used in
1126    * the packets they're dissecting, and may be impossible in
1127    * the hex-dump window (except by punting and displaying only
1128    * ASCII characters).
1129    *
1130    * GTK+ 2.0 may simplify part of the problem, as it will, as I
1131    * understand it, use UTF-8-encoded Unicode as its internal
1132    * character set; however, we'd still have to know whatever
1133    * character set and encoding is used in the packet (which
1134    * may differ for different protocols, e.g. SMB might use
1135    * PC code pages for some strings and Unicode for others, whilst
1136    * NFS might use some UNIX character set encoding, e.g. ISO 8859/x,
1137    * or one of the EUC character sets for Asian languages, or one
1138    * of the other multi-byte character sets, or UTF-8, or...).
1139    *
1140    * I.e., as far as I can tell, "internationalizing" the packet-list,
1141    * protocol-tree, and hex-dump windows involves a lot more than, say,
1142    * just using font sets rather than fonts.
1143    */
1144   /* XXX - the above comment was about the GTK1 font stuff, just remove this comment now */
1145   /* XXX- is this the correct default font name for GTK2 none win32? */
1146   prefs.gui_font_name = g_strdup("Monospace 10");
1147 #endif
1148   prefs.gui_marked_fg.pixel        =     65535;
1149   prefs.gui_marked_fg.red          =     65535;
1150   prefs.gui_marked_fg.green        =     65535;
1151   prefs.gui_marked_fg.blue         =     65535;
1152   prefs.gui_marked_bg.pixel        =         0;
1153   prefs.gui_marked_bg.red          =         0;
1154   prefs.gui_marked_bg.green        =         0;
1155   prefs.gui_marked_bg.blue         =         0;
1156   prefs.gui_colorized_fg           = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
1157   prefs.gui_colorized_bg           = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
1158   prefs.gui_geometry_save_position =         FALSE;
1159   prefs.gui_geometry_save_size     =         TRUE;
1160   prefs.gui_geometry_save_maximized=         TRUE;
1161   prefs.gui_macosx_style           = TRUE;
1162   prefs.gui_console_open           = console_open_never;
1163   prefs.gui_fileopen_style         = FO_STYLE_LAST_OPENED;
1164   prefs.gui_recent_df_entries_max  = 10;
1165   prefs.gui_recent_files_count_max = 10;
1166   prefs.gui_fileopen_dir           = g_strdup(get_persdatafile_dir());
1167   prefs.gui_fileopen_preview       = 3;
1168   prefs.gui_ask_unsaved            = TRUE;
1169   prefs.gui_find_wrap              = TRUE;
1170   prefs.gui_use_pref_save          = FALSE;
1171   prefs.gui_webbrowser             = g_strdup(HTML_VIEWER " %s");
1172   prefs.gui_window_title           = g_strdup("");
1173   prefs.gui_start_title            = g_strdup("The World's Most Popular Network Protocol Analyzer");
1174   prefs.gui_version_in_start_page  = FALSE;
1175   prefs.gui_layout_type            = layout_type_5;
1176   prefs.gui_layout_content_1       = layout_pane_content_plist;
1177   prefs.gui_layout_content_2       = layout_pane_content_pdetails;
1178   prefs.gui_layout_content_3       = layout_pane_content_pbytes;
1179   prefs.console_log_level          =
1180       G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
1181
1182 /* set the default values for the capture dialog box */
1183   prefs.capture_device           = NULL;
1184   prefs.capture_devices_linktypes= NULL;
1185   prefs.capture_devices_descr    = NULL;
1186   prefs.capture_devices_hide     = NULL;
1187   prefs.capture_prom_mode        = TRUE;
1188   prefs.capture_pcap_ng          = FALSE;
1189   prefs.capture_real_time        = TRUE;
1190   prefs.capture_auto_scroll      = TRUE;
1191   prefs.capture_show_info        = FALSE;
1192
1193 /* set the default values for the name resolution dialog box */
1194   prefs.name_resolve             = RESOLV_ALL ^ RESOLV_NETWORK;
1195   prefs.name_resolve_concurrency = 500;
1196
1197 /* set the default values for the tap/statistics dialog box */
1198   prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
1199   prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
1200
1201   prefs.display_hidden_proto_items = FALSE;
1202
1203   prefs_initialized = TRUE;
1204 }
1205
1206 /* Reset preferences */
1207 void
1208 prefs_reset(void)
1209 {
1210   prefs_initialized = FALSE;
1211
1212   g_free(prefs.pr_file);
1213   g_free(prefs.pr_cmd);
1214   free_col_info(&prefs);
1215   g_free(prefs.gui_font_name);
1216   g_free(prefs.gui_colorized_fg);
1217   g_free(prefs.gui_colorized_bg);
1218   g_free(prefs.gui_fileopen_dir);
1219   g_free(prefs.gui_webbrowser);
1220   g_free(prefs.gui_window_title);
1221   g_free(prefs.gui_start_title);
1222   g_free(prefs.capture_device);
1223   g_free(prefs.capture_devices_linktypes);
1224   g_free(prefs.capture_devices_descr);
1225   g_free(prefs.capture_devices_hide);
1226
1227   uat_unload_all();
1228   init_prefs();
1229 }
1230
1231 /* Read the preferences file, fill in "prefs", and return a pointer to it.
1232
1233    If we got an error (other than "it doesn't exist") trying to read
1234    the global preferences file, stuff the errno into "*gpf_errno_return"
1235    and a pointer to the path of the file into "*gpf_path_return", and
1236    return NULL.
1237
1238    If we got an error (other than "it doesn't exist") trying to read
1239    the user's preferences file, stuff the errno into "*pf_errno_return"
1240    and a pointer to the path of the file into "*pf_path_return", and
1241    return NULL. */
1242 e_prefs *
1243 read_prefs(int *gpf_errno_return, int *gpf_read_errno_return,
1244            char **gpf_path_return, int *pf_errno_return,
1245            int *pf_read_errno_return, char **pf_path_return)
1246 {
1247   int         err;
1248   char        *pf_path;
1249   FILE        *pf;
1250
1251   init_prefs();
1252
1253   /*
1254    * If we don't already have the pathname of the global preferences
1255    * file, construct it.  Then, in either case, try to open the file.
1256    */
1257   if (gpf_path == NULL) {
1258     /*
1259      * We don't have the path; try the new path first, and, if that
1260      * file doesn't exist, try the old path.
1261      */
1262     gpf_path = get_datafile_path(PF_NAME);
1263     if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
1264       /*
1265        * It doesn't exist by the new name; try the old name.
1266        */
1267       g_free(gpf_path);
1268       gpf_path = get_datafile_path(OLD_GPF_NAME);
1269       pf = ws_fopen(gpf_path, "r");
1270     }
1271   } else {
1272     /*
1273      * We have the path; try it.
1274      */
1275     pf = ws_fopen(gpf_path, "r");
1276   }
1277
1278   /*
1279    * If we were able to open the file, read it.
1280    * XXX - if it failed for a reason other than "it doesn't exist",
1281    * report the error.
1282    */
1283   *gpf_path_return = NULL;
1284   if (pf != NULL) {
1285     /*
1286      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
1287      * seen.
1288      */
1289     mgcp_tcp_port_count = 0;
1290     mgcp_udp_port_count = 0;
1291
1292     /* We succeeded in opening it; read it. */
1293     err = read_prefs_file(gpf_path, pf, set_pref, NULL);
1294     if (err != 0) {
1295       /* We had an error reading the file; return the errno and the
1296          pathname, so our caller can report the error. */
1297       *gpf_errno_return = 0;
1298       *gpf_read_errno_return = err;
1299       *gpf_path_return = gpf_path;
1300     }
1301     fclose(pf);
1302   } else {
1303     /* We failed to open it.  If we failed for some reason other than
1304        "it doesn't exist", return the errno and the pathname, so our
1305        caller can report the error. */
1306     if (errno != ENOENT) {
1307       *gpf_errno_return = errno;
1308       *gpf_read_errno_return = 0;
1309       *gpf_path_return = gpf_path;
1310     }
1311   }
1312
1313   /* Construct the pathname of the user's preferences file. */
1314   pf_path = get_persconffile_path(PF_NAME, TRUE, FALSE);
1315
1316   /* Read the user's preferences file, if it exists. */
1317   *pf_path_return = NULL;
1318   if ((pf = ws_fopen(pf_path, "r")) != NULL) {
1319     /*
1320      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
1321      * seen.
1322      */
1323     mgcp_tcp_port_count = 0;
1324     mgcp_udp_port_count = 0;
1325
1326     /* We succeeded in opening it; read it. */
1327     err = read_prefs_file(pf_path, pf, set_pref, NULL);
1328     if (err != 0) {
1329       /* We had an error reading the file; return the errno and the
1330          pathname, so our caller can report the error. */
1331       *pf_errno_return = 0;
1332       *pf_read_errno_return = err;
1333       *pf_path_return = pf_path;
1334     } else
1335       g_free(pf_path);
1336     fclose(pf);
1337   } else {
1338     /* We failed to open it.  If we failed for some reason other than
1339        "it doesn't exist", return the errno and the pathname, so our
1340        caller can report the error. */
1341     if (errno != ENOENT) {
1342       *pf_errno_return = errno;
1343       *pf_read_errno_return = 0;
1344       *pf_path_return = pf_path;
1345     } else
1346       g_free(pf_path);
1347   }
1348
1349   return &prefs;
1350 }
1351
1352 /* read the preferences file (or similiar) and call the callback
1353  * function to set each key/value pair found */
1354 int
1355 read_prefs_file(const char *pf_path, FILE *pf, pref_set_pair_cb pref_set_pair_fct, void *private_data)
1356 {
1357   enum { START, IN_VAR, PRE_VAL, IN_VAL, IN_SKIP };
1358   int       got_c, state = START;
1359   GString  *cur_val;
1360   GString  *cur_var;
1361   gboolean  got_val = FALSE;
1362   gint      fline = 1, pline = 1;
1363   gchar     hint[] = "(applying your preferences once should remove this warning)";
1364
1365   cur_val = g_string_new("");
1366   cur_var = g_string_new("");
1367
1368   while ((got_c = getc(pf)) != EOF) {
1369     if (got_c == '\n') {
1370       state = START;
1371       fline++;
1372       continue;
1373     }
1374
1375     switch (state) {
1376       case START:
1377         if (isalnum(got_c)) {
1378           if (cur_var->len > 0) {
1379             if (got_val) {
1380               switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data)) {
1381
1382               case PREFS_SET_OK:
1383                 break;
1384
1385               case PREFS_SET_SYNTAX_ERR:
1386                 g_warning ("%s line %d: Syntax error %s", pf_path, pline, hint);
1387                 break;
1388
1389               case PREFS_SET_NO_SUCH_PREF:
1390                 g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
1391                                 pline, cur_var->str, hint);
1392                 break;
1393
1394               case PREFS_SET_OBSOLETE:
1395                 /* We silently ignore attempts to set these; it's
1396                    probably not the user's fault that it's in there -
1397                    they may have saved preferences with a release that
1398                    supported them. */
1399                 break;
1400               }
1401             } else {
1402               g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
1403             }
1404           }
1405           state      = IN_VAR;
1406           got_val    = FALSE;
1407           g_string_truncate(cur_var, 0);
1408           g_string_append_c(cur_var, (gchar) got_c);
1409           pline = fline;
1410         } else if (isspace(got_c) && cur_var->len > 0 && got_val) {
1411           state = PRE_VAL;
1412         } else if (got_c == '#') {
1413           state = IN_SKIP;
1414         } else {
1415           g_warning ("%s line %d: Malformed line %s", pf_path, fline, hint);
1416         }
1417         break;
1418       case IN_VAR:
1419         if (got_c != ':') {
1420           g_string_append_c(cur_var, (gchar) got_c);
1421         } else {
1422           state   = PRE_VAL;
1423           g_string_truncate(cur_val, 0);
1424           got_val = TRUE;
1425         }
1426         break;
1427       case PRE_VAL:
1428         if (!isspace(got_c)) {
1429           state = IN_VAL;
1430           g_string_append_c(cur_val, (gchar) got_c);
1431         }
1432         break;
1433       case IN_VAL:
1434         g_string_append_c(cur_val, (gchar) got_c);
1435         break;
1436     }
1437   }
1438   if (cur_var->len > 0) {
1439     if (got_val) {
1440       switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data)) {
1441
1442       case PREFS_SET_OK:
1443         break;
1444
1445       case PREFS_SET_SYNTAX_ERR:
1446         g_warning ("%s line %d: Syntax error %s", pf_path, pline, hint);
1447         break;
1448
1449       case PREFS_SET_NO_SUCH_PREF:
1450         g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
1451                         pline, cur_var->str, hint);
1452         break;
1453
1454       case PREFS_SET_OBSOLETE:
1455         /* We silently ignore attempts to set these; it's probably not
1456            the user's fault that it's in there - they may have saved
1457            preferences with a release that supported it. */
1458         break;
1459       }
1460     } else {
1461       g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
1462     }
1463   }
1464
1465   g_string_free(cur_val, TRUE);
1466   g_string_free(cur_var, TRUE);
1467
1468   if (ferror(pf))
1469     return errno;
1470   else
1471     return 0;
1472 }
1473
1474 /*
1475  * If we were handed a preference starting with "uat:", try to turn it into
1476  * a valid uat entry.
1477  */
1478 static gboolean
1479 prefs_set_uat_pref(char *uat_entry) {
1480         gchar *p, *colonp;
1481         uat_t *uat;
1482         gchar *err;
1483
1484         colonp = strchr(uat_entry, ':');
1485         if (colonp == NULL)
1486                 return FALSE;
1487
1488         p = colonp;
1489         *p++ = '\0';
1490
1491         /*
1492          * Skip over any white space (there probably won't be any, but
1493          * as we allow it in the preferences file, we might as well
1494          * allow it here).
1495          */
1496         while (isspace((guchar)*p))
1497                 p++;
1498         if (*p == '\0') {
1499                 /*
1500                  * Put the colon back, so if our caller uses, in an
1501                  * error message, the string they passed us, the message
1502                  * looks correct.
1503                  */
1504                 *colonp = ':';
1505                 return FALSE;
1506         }
1507
1508         uat = uat_find(uat_entry);
1509         *colonp = ':';
1510         if (uat == NULL) {
1511                 return FALSE;
1512         }
1513
1514         if (uat_load_str(uat, p, &err)) {
1515                 return TRUE;
1516         }
1517         return FALSE;
1518 }
1519
1520 /*
1521  * Given a string of the form "<pref name>:<pref value>", as might appear
1522  * as an argument to a "-o" option, parse it and set the preference in
1523  * question.  Return an indication of whether it succeeded or failed
1524  * in some fashion.
1525  */
1526 prefs_set_pref_e
1527 prefs_set_pref(char *prefarg)
1528 {
1529         gchar *p, *colonp;
1530         prefs_set_pref_e ret;
1531
1532         /*
1533          * Set the counters of "mgcp.{tcp,udp}.port" entries we've
1534          * seen to values that keep us from trying to interpret tham
1535          * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
1536          * as, from the command line, we have no way of guessing which
1537          * the user had in mind.
1538          */
1539         mgcp_tcp_port_count = -1;
1540         mgcp_udp_port_count = -1;
1541
1542         colonp = strchr(prefarg, ':');
1543         if (colonp == NULL)
1544                 return PREFS_SET_SYNTAX_ERR;
1545
1546         p = colonp;
1547         *p++ = '\0';
1548
1549         /*
1550          * Skip over any white space (there probably won't be any, but
1551          * as we allow it in the preferences file, we might as well
1552          * allow it here).
1553          */
1554         while (isspace((guchar)*p))
1555                 p++;
1556         if (*p == '\0') {
1557                 /*
1558                  * Put the colon back, so if our caller uses, in an
1559                  * error message, the string they passed us, the message
1560                  * looks correct.
1561                  */
1562                 *colonp = ':';
1563                 return PREFS_SET_SYNTAX_ERR;
1564         }
1565         if (strcmp(prefarg, "uat")) {
1566                 ret = set_pref(prefarg, p, NULL);
1567         } else {
1568                 ret = prefs_set_uat_pref(p) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
1569         }
1570         *colonp = ':';  /* put the colon back */
1571         return ret;
1572 }
1573
1574 /*
1575  * Returns TRUE if the given device is hidden
1576  */
1577 gboolean
1578 prefs_is_capture_device_hidden(const char *name)
1579 {
1580         gchar *tok, *devices;
1581         size_t len;
1582
1583         if (prefs.capture_devices_hide && name) {
1584                 devices = g_strdup (prefs.capture_devices_hide);
1585                 len = strlen (name);
1586                 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
1587                         if (strlen (tok) == len && strcmp (name, tok) == 0) {
1588                                 g_free (devices);
1589                                 return TRUE;
1590                         }
1591                 }
1592                 g_free (devices);
1593         }
1594
1595         return FALSE;
1596 }
1597
1598 #define PRS_PRINT_FMT                    "print.format"
1599 #define PRS_PRINT_DEST                   "print.destination"
1600 #define PRS_PRINT_FILE                   "print.file"
1601 #define PRS_PRINT_CMD                    "print.command"
1602 #define PRS_COL_FMT                      "column.format"
1603 #define PRS_STREAM_CL_FG                 "stream.client.fg"
1604 #define PRS_STREAM_CL_BG                 "stream.client.bg"
1605 #define PRS_STREAM_SR_FG                 "stream.server.fg"
1606 #define PRS_STREAM_SR_BG                 "stream.server.bg"
1607 #define PRS_GUI_SCROLLBAR_ON_RIGHT       "gui.scrollbar_on_right"
1608 #define PRS_GUI_PLIST_SEL_BROWSE         "gui.packet_list_sel_browse"
1609 #define PRS_GUI_PTREE_SEL_BROWSE         "gui.protocol_tree_sel_browse"
1610 #define PRS_GUI_ALTERN_COLORS            "gui.tree_view_altern_colors"
1611 #define PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR "gui.filter_toolbar_show_in_statusbar"
1612 #define PRS_GUI_PTREE_LINE_STYLE         "gui.protocol_tree_line_style"
1613 #define PRS_GUI_PTREE_EXPANDER_STYLE     "gui.protocol_tree_expander_style"
1614 #define PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE "gui.hex_dump_highlight_style"
1615 #define PRS_GUI_FONT_NAME_1              "gui.font_name"
1616 #define PRS_GUI_FONT_NAME_2              "gui.gtk2.font_name"
1617 #define PRS_GUI_MARKED_FG                "gui.marked_frame.fg"
1618 #define PRS_GUI_MARKED_BG                "gui.marked_frame.bg"
1619 #define PRS_GUI_COLORIZED_FG             "gui.colorized_frame.fg"
1620 #define PRS_GUI_COLORIZED_BG             "gui.colorized_frame.bg"
1621 #define PRS_GUI_CONSOLE_OPEN             "gui.console_open"
1622 #define PRS_GUI_FILEOPEN_STYLE           "gui.fileopen.style"
1623 #define PRS_GUI_RECENT_COUNT_MAX         "gui.recent_files_count.max"
1624 #define PRS_GUI_RECENT_DF_ENTRIES_MAX    "gui.recent_display_filter_entries.max"
1625 #define PRS_GUI_FILEOPEN_DIR             "gui.fileopen.dir"
1626 #define PRS_GUI_FILEOPEN_REMEMBERED_DIR  "gui.fileopen.remembered_dir"
1627 #define PRS_GUI_FILEOPEN_PREVIEW         "gui.fileopen.preview"
1628 #define PRS_GUI_ASK_UNSAVED              "gui.ask_unsaved"
1629 #define PRS_GUI_FIND_WRAP                "gui.find_wrap"
1630 #define PRS_GUI_USE_PREF_SAVE            "gui.use_pref_save"
1631 #define PRS_GUI_GEOMETRY_SAVE_POSITION   "gui.geometry.save.position"
1632 #define PRS_GUI_GEOMETRY_SAVE_SIZE       "gui.geometry.save.size"
1633 #define PRS_GUI_GEOMETRY_SAVE_MAXIMIZED  "gui.geometry.save.maximized"
1634 #define PRS_GUI_MACOSX_STYLE             "gui.macosx_style"
1635 #define PRS_GUI_GEOMETRY_MAIN_X          "gui.geometry.main.x"
1636 #define PRS_GUI_GEOMETRY_MAIN_Y          "gui.geometry.main.y"
1637 #define PRS_GUI_GEOMETRY_MAIN_WIDTH      "gui.geometry.main.width"
1638 #define PRS_GUI_GEOMETRY_MAIN_HEIGHT     "gui.geometry.main.height"
1639 #define PRS_GUI_TOOLBAR_MAIN_SHOW        "gui.toolbar_main_show"
1640 #define PRS_GUI_TOOLBAR_MAIN_STYLE       "gui.toolbar_main_style"
1641 #define PRS_GUI_WEBBROWSER               "gui.webbrowser"
1642 #define PRS_GUI_WINDOW_TITLE             "gui.window_title"
1643 #define PRS_GUI_START_TITLE              "gui.start_title"
1644 #define PRS_GUI_VERSION_IN_START_PAGE    "gui.version_in_start_page"
1645 #define PRS_GUI_LAYOUT_TYPE              "gui.layout_type"
1646 #define PRS_GUI_LAYOUT_CONTENT_1         "gui.layout_content_1"
1647 #define PRS_GUI_LAYOUT_CONTENT_2         "gui.layout_content_2"
1648 #define PRS_GUI_LAYOUT_CONTENT_3         "gui.layout_content_3"
1649 #define PRS_CONSOLE_LOG_LEVEL            "console.log.level"
1650
1651 /*
1652  * This applies to more than just captures, so it's not "capture.name_resolve";
1653  * "capture.name_resolve" is supported on input for backwards compatibility.
1654  *
1655  * It's not a preference for a particular part of Wireshark, it's used all
1656  * over the place, so its name doesn't have two components.
1657  */
1658 #define PRS_NAME_RESOLVE "name_resolve"
1659 #define PRS_NAME_RESOLVE_CONCURRENCY "name_resolve_concurrency"
1660 #define PRS_CAP_NAME_RESOLVE "capture.name_resolve"
1661
1662 /*  values for the capture dialog box */
1663 #define PRS_CAP_DEVICE        "capture.device"
1664 #define PRS_CAP_DEVICES_LINKTYPES "capture.devices_linktypes"
1665 #define PRS_CAP_DEVICES_DESCR "capture.devices_descr"
1666 #define PRS_CAP_DEVICES_HIDE  "capture.devices_hide"
1667 #define PRS_CAP_PROM_MODE     "capture.prom_mode"
1668 #define PRS_CAP_PCAP_NG       "capture.pcap_ng"
1669 #define PRS_CAP_REAL_TIME     "capture.real_time_update"
1670 #define PRS_CAP_AUTO_SCROLL   "capture.auto_scroll"
1671 #define PRS_CAP_SHOW_INFO     "capture.show_info"
1672
1673 #define RED_COMPONENT(x)   (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
1674 #define GREEN_COMPONENT(x) (guint16) (((((x) >>  8) & 0xff) * 65535 / 255))
1675 #define BLUE_COMPONENT(x)  (guint16) ( (((x)        & 0xff) * 65535 / 255))
1676
1677 /*  values for the rtp player preferences dialog box */
1678 #define PRS_TAP_UPDATE_INTERVAL           "taps.update_interval"
1679 #define PRS_RTP_PLAYER_MAX_VISIBLE        "taps.rtp_player_max_visible"
1680
1681 #define PRS_DISPLAY_HIDDEN_PROTO_ITEMS          "packet_list.display_hidden_proto_items"
1682
1683 static const gchar *pr_formats[] = { "text", "postscript" };
1684 static const gchar *pr_dests[]   = { "command", "file" };
1685
1686 typedef struct {
1687   char    letter;
1688   guint32 value;
1689 } name_resolve_opt_t;
1690
1691 static name_resolve_opt_t name_resolve_opt[] = {
1692   { 'm', RESOLV_MAC },
1693   { 'n', RESOLV_NETWORK },
1694   { 't', RESOLV_TRANSPORT },
1695   { 'C', RESOLV_CONCURRENT },
1696 };
1697
1698 #define N_NAME_RESOLVE_OPT      (sizeof name_resolve_opt / sizeof name_resolve_opt[0])
1699
1700 static const char *
1701 name_resolve_to_string(guint32 name_resolve)
1702 {
1703   static char string[N_NAME_RESOLVE_OPT+1];
1704   char *p;
1705   unsigned int i;
1706   gboolean all_opts_set = TRUE;
1707
1708   if (name_resolve == RESOLV_NONE)
1709     return "FALSE";
1710   p = &string[0];
1711   for (i = 0; i < N_NAME_RESOLVE_OPT; i++) {
1712     if (name_resolve & name_resolve_opt[i].value)
1713       *p++ =  name_resolve_opt[i].letter;
1714     else
1715       all_opts_set = FALSE;
1716   }
1717   *p = '\0';
1718   if (all_opts_set)
1719     return "TRUE";
1720   return string;
1721 }
1722
1723 char
1724 string_to_name_resolve(char *string, guint32 *name_resolve)
1725 {
1726   char c;
1727   unsigned int i;
1728
1729   *name_resolve = 0;
1730   while ((c = *string++) != '\0') {
1731     for (i = 0; i < N_NAME_RESOLVE_OPT; i++) {
1732       if (c == name_resolve_opt[i].letter) {
1733         *name_resolve |= name_resolve_opt[i].value;
1734         break;
1735       }
1736     }
1737     if (i == N_NAME_RESOLVE_OPT) {
1738       /*
1739        * Unrecognized letter.
1740        */
1741       return c;
1742     }
1743   }
1744   return '\0';
1745 }
1746
1747 static void
1748 try_convert_to_custom_column(gpointer *el_data)
1749 {
1750     /* Array of columns that have been migrated to custom columns */
1751     struct {
1752         gint el;
1753         gchar *col_expr;
1754     } migrated_columns[] = {
1755         { COL_COS_VALUE, "vlan.priority" },
1756         { COL_CIRCUIT_ID, "iax2.call" },
1757                 { COL_BSSGP_TLLI, "bssgp.tlli" },
1758         { COL_HPUX_SUBSYS, "nettl.subsys" },
1759         { COL_HPUX_DEVID, "nettl.devid" },
1760         { COL_DSCP_VALUE, "ip.dsfield" },
1761         { COL_FR_DLCI, "fr.dlci" },
1762         { COL_REL_CONV_TIME, "tcp.time_relative" },
1763         { COL_DELTA_CONV_TIME, "tcp.time_delta" }
1764     };
1765
1766     guint haystack_idx;
1767     const gchar *haystack_fmt;
1768
1769     gchar **fmt = (gchar **) el_data;
1770
1771     for (haystack_idx = 0;
1772          haystack_idx < G_N_ELEMENTS(migrated_columns);
1773          ++haystack_idx) {
1774
1775         haystack_fmt = col_format_to_string(migrated_columns[haystack_idx].el);
1776         if (strcmp(haystack_fmt, *fmt) == 0) {
1777             gchar *cust_col = g_strdup_printf("%%Cus:%s",
1778                                 migrated_columns[haystack_idx].col_expr);
1779
1780             g_free(*fmt);
1781             *fmt = cust_col;
1782         }
1783     }
1784 }
1785
1786 static prefs_set_pref_e
1787 set_pref(gchar *pref_name, gchar *value, void *private_data _U_)
1788 {
1789   GList    *col_l, *col_l_elt;
1790   gint      llen;
1791   fmt_data *cfmt;
1792   unsigned long int cval;
1793   guint    uval;
1794   gboolean bval;
1795   gint     enum_val;
1796   char     *p;
1797   gchar    *dotp, *last_dotp;
1798   module_t *module;
1799   pref_t   *pref;
1800   gboolean had_a_dot;
1801   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
1802   size_t cust_format_len = strlen(cust_format);
1803
1804   if (strcmp(pref_name, PRS_PRINT_FMT) == 0) {
1805     if (strcmp(value, pr_formats[PR_FMT_TEXT]) == 0) {
1806       prefs.pr_format = PR_FMT_TEXT;
1807     } else if (strcmp(value, pr_formats[PR_FMT_PS]) == 0) {
1808       prefs.pr_format = PR_FMT_PS;
1809     } else {
1810       return PREFS_SET_SYNTAX_ERR;
1811     }
1812   } else if (strcmp(pref_name, PRS_PRINT_DEST) == 0) {
1813     if (strcmp(value, pr_dests[PR_DEST_CMD]) == 0) {
1814       prefs.pr_dest = PR_DEST_CMD;
1815     } else if (strcmp(value, pr_dests[PR_DEST_FILE]) == 0) {
1816       prefs.pr_dest = PR_DEST_FILE;
1817     } else {
1818       return PREFS_SET_SYNTAX_ERR;
1819     }
1820   } else if (strcmp(pref_name, PRS_PRINT_FILE) == 0) {
1821     g_free(prefs.pr_file);
1822     prefs.pr_file = g_strdup(value);
1823   } else if (strcmp(pref_name, PRS_PRINT_CMD) == 0) {
1824     g_free(prefs.pr_cmd);
1825     prefs.pr_cmd = g_strdup(value);
1826   } else if (strcmp(pref_name, PRS_COL_FMT) == 0) {
1827     col_l = prefs_get_string_list(value);
1828     if (col_l == NULL)
1829       return PREFS_SET_SYNTAX_ERR;
1830     if ((g_list_length(col_l) % 2) != 0) {
1831       /* A title didn't have a matching format.  */
1832       prefs_clear_string_list(col_l);
1833       return PREFS_SET_SYNTAX_ERR;
1834     }
1835     /* Check to make sure all column formats are valid.  */
1836     col_l_elt = g_list_first(col_l);
1837     while(col_l_elt) {
1838       /* Make sure the title isn't empty.  */
1839       if (strcmp(col_l_elt->data, "") == 0) {
1840         /* It is.  */
1841         prefs_clear_string_list(col_l);
1842         return PREFS_SET_SYNTAX_ERR;
1843       }
1844
1845       /* Go past the title.  */
1846       col_l_elt = col_l_elt->next;
1847
1848       /* Check the format.  */
1849       if (strncmp(col_l_elt->data, cust_format, cust_format_len) != 0) {
1850         if (get_column_format_from_str(col_l_elt->data) == -1) {
1851           /* It's not a valid column format.  */
1852           prefs_clear_string_list(col_l);
1853           return PREFS_SET_SYNTAX_ERR;
1854         }
1855
1856         /* Some predefined columns have been migrated to use custom colums.
1857          * We'll convert these silently here */
1858         try_convert_to_custom_column(&col_l_elt->data);
1859       }
1860
1861       /* Go past the format.  */
1862       col_l_elt = col_l_elt->next;
1863     }
1864     free_col_info(&prefs);
1865     prefs.col_list = NULL;
1866     llen             = g_list_length(col_l);
1867     prefs.num_cols   = llen / 2;
1868     col_l_elt = g_list_first(col_l);
1869     while(col_l_elt) {
1870       cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1871       cfmt->title    = g_strdup(col_l_elt->data);
1872       col_l_elt      = col_l_elt->next;
1873       if (strncmp(col_l_elt->data, cust_format, cust_format_len) == 0) {
1874         gchar *fmt     = g_strdup(col_l_elt->data);
1875         cfmt->fmt      = g_strdup(cust_format);
1876         cfmt->custom_field = g_strdup(&fmt[cust_format_len+1]);  /* add 1 for ':' */
1877         g_free (fmt);
1878       } else {
1879         cfmt->fmt      = g_strdup(col_l_elt->data);
1880         cfmt->custom_field = NULL;
1881       }
1882       col_l_elt      = col_l_elt->next;
1883       prefs.col_list = g_list_append(prefs.col_list, cfmt);
1884     }
1885     prefs_clear_string_list(col_l);
1886   } else if (strcmp(pref_name, PRS_STREAM_CL_FG) == 0) {
1887     cval = strtoul(value, NULL, 16);
1888     prefs.st_client_fg.pixel = 0;
1889     prefs.st_client_fg.red   = RED_COMPONENT(cval);
1890     prefs.st_client_fg.green = GREEN_COMPONENT(cval);
1891     prefs.st_client_fg.blue  = BLUE_COMPONENT(cval);
1892   } else if (strcmp(pref_name, PRS_STREAM_CL_BG) == 0) {
1893     cval = strtoul(value, NULL, 16);
1894     prefs.st_client_bg.pixel = 0;
1895     prefs.st_client_bg.red   = RED_COMPONENT(cval);
1896     prefs.st_client_bg.green = GREEN_COMPONENT(cval);
1897     prefs.st_client_bg.blue  = BLUE_COMPONENT(cval);
1898   } else if (strcmp(pref_name, PRS_STREAM_SR_FG) == 0) {
1899     cval = strtoul(value, NULL, 16);
1900     prefs.st_server_fg.pixel = 0;
1901     prefs.st_server_fg.red   = RED_COMPONENT(cval);
1902     prefs.st_server_fg.green = GREEN_COMPONENT(cval);
1903     prefs.st_server_fg.blue  = BLUE_COMPONENT(cval);
1904   } else if (strcmp(pref_name, PRS_STREAM_SR_BG) == 0) {
1905     cval = strtoul(value, NULL, 16);
1906     prefs.st_server_bg.pixel = 0;
1907     prefs.st_server_bg.red   = RED_COMPONENT(cval);
1908     prefs.st_server_bg.green = GREEN_COMPONENT(cval);
1909     prefs.st_server_bg.blue  = BLUE_COMPONENT(cval);
1910   } else if (strcmp(pref_name, PRS_GUI_SCROLLBAR_ON_RIGHT) == 0) {
1911     if (g_ascii_strcasecmp(value, "true") == 0) {
1912             prefs.gui_scrollbar_on_right = TRUE;
1913     }
1914     else {
1915             prefs.gui_scrollbar_on_right = FALSE;
1916     }
1917   } else if (strcmp(pref_name, PRS_GUI_PLIST_SEL_BROWSE) == 0) {
1918     if (g_ascii_strcasecmp(value, "true") == 0) {
1919             prefs.gui_plist_sel_browse = TRUE;
1920     }
1921     else {
1922             prefs.gui_plist_sel_browse = FALSE;
1923     }
1924   } else if (strcmp(pref_name, PRS_GUI_PTREE_SEL_BROWSE) == 0) {
1925     if (g_ascii_strcasecmp(value, "true") == 0) {
1926             prefs.gui_ptree_sel_browse = TRUE;
1927     }
1928     else {
1929             prefs.gui_ptree_sel_browse = FALSE;
1930     }
1931   } else if (strcmp(pref_name, PRS_GUI_ALTERN_COLORS) == 0) {
1932     if (g_ascii_strcasecmp(value, "true") == 0) {
1933             prefs.gui_altern_colors = TRUE;
1934     }
1935     else {
1936             prefs.gui_altern_colors = FALSE;
1937     }
1938   } else if (strcmp(pref_name, PRS_GUI_PTREE_LINE_STYLE) == 0) {
1939     prefs.gui_ptree_line_style =
1940         find_index_from_string_array(value, gui_ptree_line_style_text, 0);
1941   } else if (strcmp(pref_name, PRS_GUI_PTREE_EXPANDER_STYLE) == 0) {
1942     prefs.gui_ptree_expander_style =
1943         find_index_from_string_array(value, gui_ptree_expander_style_text, 1);
1944   } else if (strcmp(pref_name, PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE) == 0) {
1945     prefs.gui_hex_dump_highlight_style =
1946         find_index_from_string_array(value, gui_hex_dump_highlight_style_text, 1);
1947   } else if (strcmp(pref_name, PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR) == 0) {
1948     if (g_ascii_strcasecmp(value, "true") == 0) {
1949             prefs.filter_toolbar_show_in_statusbar = TRUE;
1950     }
1951     else {
1952             prefs.filter_toolbar_show_in_statusbar = FALSE;
1953     }
1954   } else if (strcmp(pref_name, PRS_GUI_TOOLBAR_MAIN_SHOW) == 0) {
1955     /* obsoleted by recent setting */
1956   } else if (strcmp(pref_name, PRS_GUI_TOOLBAR_MAIN_STYLE) == 0) {
1957     /* see toolbar.c for details, "icons only" is default */
1958         prefs.gui_toolbar_main_style =
1959             find_index_from_string_array(value, gui_toolbar_style_text,
1960                                      TB_STYLE_ICONS);
1961   } else if (strcmp(pref_name, PRS_GUI_FONT_NAME_1) == 0) {
1962     /* GTK1 font name obsolete */
1963   } else if (strcmp(pref_name, PRS_GUI_FONT_NAME_2) == 0) {
1964     g_free(prefs.gui_font_name);
1965     prefs.gui_font_name = g_strdup(value);
1966   } else if (strcmp(pref_name, PRS_GUI_MARKED_FG) == 0) {
1967     cval = strtoul(value, NULL, 16);
1968     prefs.gui_marked_fg.pixel = 0;
1969     prefs.gui_marked_fg.red   = RED_COMPONENT(cval);
1970     prefs.gui_marked_fg.green = GREEN_COMPONENT(cval);
1971     prefs.gui_marked_fg.blue  = BLUE_COMPONENT(cval);
1972   } else if (strcmp(pref_name, PRS_GUI_MARKED_BG) == 0) {
1973     cval = strtoul(value, NULL, 16);
1974     prefs.gui_marked_bg.pixel = 0;
1975     prefs.gui_marked_bg.red   = RED_COMPONENT(cval);
1976     prefs.gui_marked_bg.green = GREEN_COMPONENT(cval);
1977     prefs.gui_marked_bg.blue  = BLUE_COMPONENT(cval);
1978   } else if (strcmp(pref_name, PRS_GUI_COLORIZED_FG) == 0) {
1979     g_free(prefs.gui_colorized_fg);
1980     prefs.gui_colorized_fg = g_strdup(value);
1981   } else if (strcmp(pref_name, PRS_GUI_COLORIZED_BG) == 0) {
1982     g_free(prefs.gui_colorized_bg);
1983     prefs.gui_colorized_bg = g_strdup(value);
1984   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_POSITION) == 0) {
1985     if (g_ascii_strcasecmp(value, "true") == 0) {
1986             prefs.gui_geometry_save_position = TRUE;
1987     }
1988     else {
1989             prefs.gui_geometry_save_position = FALSE;
1990     }
1991   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_SIZE) == 0) {
1992     if (g_ascii_strcasecmp(value, "true") == 0) {
1993             prefs.gui_geometry_save_size = TRUE;
1994     }
1995     else {
1996             prefs.gui_geometry_save_size = FALSE;
1997     }
1998   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_MAXIMIZED) == 0) {
1999     if (g_ascii_strcasecmp(value, "true") == 0) {
2000             prefs.gui_geometry_save_maximized = TRUE;
2001     }
2002     else {
2003             prefs.gui_geometry_save_maximized = FALSE;
2004     }
2005   } else if (strcmp(pref_name, PRS_GUI_MACOSX_STYLE) == 0) {
2006      if (g_ascii_strcasecmp(value, "true") == 0) {
2007             prefs.gui_macosx_style = TRUE;
2008     }
2009     else {
2010             prefs.gui_macosx_style = FALSE;
2011     }
2012   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_X) == 0) {         /* deprecated */
2013   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_Y) == 0) {         /* deprecated */
2014   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_WIDTH) == 0) {     /* deprecated */
2015   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {    /* deprecated */
2016   } else if (strcmp(pref_name, PRS_GUI_CONSOLE_OPEN) == 0) {
2017     prefs.gui_console_open =
2018         find_index_from_string_array(value, gui_console_open_text,
2019                                      console_open_never);
2020   } else if (strcmp(pref_name, PRS_GUI_RECENT_COUNT_MAX) == 0) {
2021     prefs.gui_recent_files_count_max = strtoul(value, NULL, 10);
2022     if (prefs.gui_recent_files_count_max == 0) {
2023       /* We really should put up a dialog box here ... */
2024       prefs.gui_recent_files_count_max = 10;
2025     }
2026   } else if (strcmp(pref_name, PRS_GUI_RECENT_DF_ENTRIES_MAX) == 0) {
2027     prefs.gui_recent_df_entries_max = strtoul(value, NULL, 10);
2028     if (prefs.gui_recent_df_entries_max == 0) {
2029       /* We really should put up a dialog box here ... */
2030       prefs.gui_recent_df_entries_max = 10;
2031     }
2032   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_STYLE) == 0) {
2033     prefs.gui_fileopen_style =
2034         find_index_from_string_array(value, gui_fileopen_style_text,
2035                                      FO_STYLE_LAST_OPENED);
2036   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_DIR) == 0) {
2037     g_free(prefs.gui_fileopen_dir);
2038     prefs.gui_fileopen_dir = g_strdup(value);
2039   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_REMEMBERED_DIR) == 0) { /* deprecated */
2040   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_PREVIEW) == 0) {
2041     prefs.gui_fileopen_preview = strtoul(value, NULL, 10);
2042   } else if (strcmp(pref_name, PRS_GUI_ASK_UNSAVED) == 0) {
2043     if (g_ascii_strcasecmp(value, "true") == 0) {
2044             prefs.gui_ask_unsaved = TRUE;
2045     }
2046     else {
2047             prefs.gui_ask_unsaved = FALSE;
2048     }
2049   } else if (strcmp(pref_name, PRS_GUI_FIND_WRAP) == 0) {
2050     if (g_ascii_strcasecmp(value, "true") == 0) {
2051             prefs.gui_find_wrap = TRUE;
2052     }
2053     else {
2054             prefs.gui_find_wrap = FALSE;
2055     }
2056   } else if (strcmp(pref_name, PRS_GUI_USE_PREF_SAVE) == 0) {
2057     if (g_ascii_strcasecmp(value, "true") == 0) {
2058             prefs.gui_use_pref_save = TRUE;
2059     }
2060     else {
2061             prefs.gui_use_pref_save = FALSE;
2062     }
2063   } else if (strcmp(pref_name, PRS_GUI_WEBBROWSER) == 0) {
2064     g_free(prefs.gui_webbrowser);
2065     prefs.gui_webbrowser = g_strdup(value);
2066   } else if (strcmp(pref_name, PRS_GUI_WINDOW_TITLE) == 0) {
2067     g_free(prefs.gui_window_title);
2068     prefs.gui_window_title = g_strdup(value);
2069   } else if (strcmp(pref_name, PRS_GUI_START_TITLE) == 0) {
2070     g_free(prefs.gui_start_title);
2071     prefs.gui_start_title = g_strdup(value);
2072   } else if (strcmp(pref_name, PRS_GUI_VERSION_IN_START_PAGE) == 0) {
2073     if (g_ascii_strcasecmp(value, "true") == 0) {
2074             prefs.gui_version_in_start_page = TRUE;
2075     } else {
2076             prefs.gui_version_in_start_page = FALSE;
2077     }
2078   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_TYPE) == 0) {
2079     prefs.gui_layout_type = strtoul(value, NULL, 10);
2080     if (prefs.gui_layout_type == layout_unused ||
2081         prefs.gui_layout_type >= layout_type_max) {
2082       /* XXX - report an error?  It's not a syntax error - we'd need to
2083          add a way of reporting a *semantic* error. */
2084       prefs.gui_layout_type = layout_type_5;
2085     }
2086   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_1) == 0) {
2087     prefs.gui_layout_content_1 =
2088         find_index_from_string_array(value, gui_layout_content_text, 0);
2089   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_2) == 0) {
2090     prefs.gui_layout_content_2 =
2091         find_index_from_string_array(value, gui_layout_content_text, 0);
2092   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_3) == 0) {
2093     prefs.gui_layout_content_3 =
2094         find_index_from_string_array(value, gui_layout_content_text, 0);
2095   } else if (strcmp(pref_name, PRS_CONSOLE_LOG_LEVEL) == 0) {
2096     prefs.console_log_level = strtoul(value, NULL, 10);
2097
2098 /* handle the capture options */
2099   } else if (strcmp(pref_name, PRS_CAP_DEVICE) == 0) {
2100     g_free(prefs.capture_device);
2101     prefs.capture_device = g_strdup(value);
2102   } else if (strcmp(pref_name, PRS_CAP_DEVICES_LINKTYPES) == 0) {
2103     g_free(prefs.capture_devices_linktypes);
2104     prefs.capture_devices_linktypes = g_strdup(value);
2105   } else if (strcmp(pref_name, PRS_CAP_DEVICES_DESCR) == 0) {
2106     g_free(prefs.capture_devices_descr);
2107     prefs.capture_devices_descr = g_strdup(value);
2108   } else if (strcmp(pref_name, PRS_CAP_DEVICES_HIDE) == 0) {
2109     g_free(prefs.capture_devices_hide);
2110     prefs.capture_devices_hide = g_strdup(value);
2111   } else if (strcmp(pref_name, PRS_CAP_PROM_MODE) == 0) {
2112     prefs.capture_prom_mode = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2113    } else if (strcmp(pref_name, PRS_CAP_PCAP_NG) == 0) {
2114     prefs.capture_pcap_ng = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2115  } else if (strcmp(pref_name, PRS_CAP_REAL_TIME) == 0) {
2116     prefs.capture_real_time = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2117   } else if (strcmp(pref_name, PRS_CAP_AUTO_SCROLL) == 0) {
2118     prefs.capture_auto_scroll = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2119   } else if (strcmp(pref_name, PRS_CAP_SHOW_INFO) == 0) {
2120     prefs.capture_show_info = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2121
2122 /* handle the global options */
2123   } else if (strcmp(pref_name, PRS_NAME_RESOLVE) == 0 ||
2124              strcmp(pref_name, PRS_CAP_NAME_RESOLVE) == 0) {
2125     /*
2126      * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
2127      * RESOLV_ALL and RESOLV_NONE.
2128      *
2129      * Otherwise, we treat it as a list of name types we want to resolve.
2130      */
2131     if (g_ascii_strcasecmp(value, "true") == 0)
2132       prefs.name_resolve = RESOLV_ALL;
2133     else if (g_ascii_strcasecmp(value, "false") == 0)
2134       prefs.name_resolve = RESOLV_NONE;
2135     else {
2136       prefs.name_resolve = RESOLV_NONE; /* start out with none set */
2137       if (string_to_name_resolve(value, &prefs.name_resolve) != '\0')
2138         return PREFS_SET_SYNTAX_ERR;
2139     }
2140   } else if (strcmp(pref_name, PRS_NAME_RESOLVE_CONCURRENCY) == 0) {
2141     prefs.name_resolve_concurrency = strtol(value, NULL, 10);
2142   } else if ((strcmp(pref_name, PRS_RTP_PLAYER_MAX_VISIBLE) == 0) ||
2143              (strcmp(pref_name, "rtp_player.max_visible") == 0)) {
2144     /* ... also accepting old name for this preference */
2145     prefs.rtp_player_max_visible = strtol(value, NULL, 10);
2146   } else if (strcmp(pref_name, PRS_TAP_UPDATE_INTERVAL) == 0) {
2147     prefs.tap_update_interval = strtol(value, NULL, 10);
2148   } else if (strcmp(pref_name, PRS_DISPLAY_HIDDEN_PROTO_ITEMS) == 0) {
2149     prefs.display_hidden_proto_items = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2150   } else {
2151     /* To which module does this preference belong? */
2152     module = NULL;
2153     last_dotp = pref_name;
2154     had_a_dot = FALSE;
2155     while (!module) {
2156         dotp = strchr(last_dotp, '.');
2157         if (dotp == NULL) {
2158             if (had_a_dot) {
2159               /* no such module */
2160               return PREFS_SET_NO_SUCH_PREF;
2161             }
2162             else {
2163               /* no ".", so no module/name separator */
2164               return PREFS_SET_SYNTAX_ERR;
2165             }
2166         }
2167         else {
2168             had_a_dot = TRUE;
2169         }
2170         *dotp = '\0';           /* separate module and preference name */
2171         module = prefs_find_module(pref_name);
2172
2173         /*
2174          * XXX - "Diameter" rather than "diameter" was used in earlier
2175          * versions of Wireshark; if we didn't find the module, and its name
2176          * was "Diameter", look for "diameter" instead.
2177          *
2178          * In addition, the BEEP protocol used to be the BXXP protocol,
2179          * so if we didn't find the module, and its name was "bxxp",
2180          * look for "beep" instead.
2181          *
2182          * Also, the preferences for GTP v0 and v1 were combined under
2183          * a single "gtp" heading, and the preferences for SMPP were
2184          * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
2185          * However, SMPP now has its own preferences, so we just map
2186          * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
2187          *
2188          * We also renamed "dcp" to "dccp" and "x.25" to "x25".
2189          */
2190         if (module == NULL) {
2191           if (strcmp(pref_name, "Diameter") == 0)
2192             module = prefs_find_module("diameter");
2193           else if (strcmp(pref_name, "bxxp") == 0)
2194             module = prefs_find_module("beep");
2195           else if (strcmp(pref_name, "gtpv0") == 0 ||
2196                    strcmp(pref_name, "gtpv1") == 0)
2197             module = prefs_find_module("gtp");
2198           else if (strcmp(pref_name, "smpp-gsm-sms") == 0)
2199             module = prefs_find_module("gsm-sms-ud");
2200           else if (strcmp(pref_name, "dcp") == 0)
2201             module = prefs_find_module("dccp");
2202           else if (strcmp(pref_name, "x.25") == 0)
2203             module = prefs_find_module("x25");
2204           else if (strcmp(pref_name, "etheric") == 0 ||
2205                    strcmp(pref_name, "isup_thin") == 0)
2206             /* This protocols was removed 7. July 2009 */
2207             return PREFS_SET_OBSOLETE;
2208         }
2209         *dotp = '.';            /* put the preference string back */
2210         dotp++;                 /* skip past separator to preference name */
2211         last_dotp = dotp;
2212     }
2213
2214     pref = prefs_find_preference(module, dotp);
2215
2216     if (pref == NULL) {
2217       if (strcmp(module->name, "mgcp") == 0) {
2218         /*
2219          * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
2220          * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
2221          * were used in earlier versions of Wireshark; if we didn't find the
2222          * preference, it was an MGCP preference, and its name was
2223          * "display raw text toggle" or "display dissect tree", look for
2224          * "display_raw_text" or "display_dissect_tree" instead.
2225          *
2226          * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
2227          * the gateway and callagent ports were given those names; we interpret
2228          * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
2229          * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
2230          * they were registered by the MCCP dissector and thus that's the
2231          * order in which they were written to the preferences file.  (If
2232          * we're not reading the preferences file, but are handling stuff
2233          * from a "-o" command-line option, we have no clue which the user
2234          * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
2235          * or "mgcp.{tcp,udp}.callagent_port" instead.)
2236          */
2237         if (strcmp(dotp, "display raw text toggle") == 0)
2238           pref = prefs_find_preference(module, "display_raw_text");
2239         else if (strcmp(dotp, "display dissect tree") == 0)
2240           pref = prefs_find_preference(module, "display_dissect_tree");
2241         else if (strcmp(dotp, "tcp.port") == 0) {
2242           mgcp_tcp_port_count++;
2243           if (mgcp_tcp_port_count == 1) {
2244             /* It's the first one */
2245             pref = prefs_find_preference(module, "tcp.gateway_port");
2246           } else if (mgcp_tcp_port_count == 2) {
2247             /* It's the second one */
2248             pref = prefs_find_preference(module, "tcp.callagent_port");
2249           }
2250           /* Otherwise it's from the command line, and we don't bother
2251              mapping it. */
2252         } else if (strcmp(dotp, "udp.port") == 0) {
2253           mgcp_udp_port_count++;
2254           if (mgcp_udp_port_count == 1) {
2255             /* It's the first one */
2256             pref = prefs_find_preference(module, "udp.gateway_port");
2257           } else if (mgcp_udp_port_count == 2) {
2258             /* It's the second one */
2259             pref = prefs_find_preference(module, "udp.callagent_port");
2260           }
2261           /* Otherwise it's from the command line, and we don't bother
2262              mapping it. */
2263         }
2264       } else if (strcmp(module->name, "smb") == 0) {
2265         /* Handle old names for SMB preferences. */
2266         if (strcmp(dotp, "smb.trans.reassembly") == 0)
2267           pref = prefs_find_preference(module, "trans_reassembly");
2268         else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
2269           pref = prefs_find_preference(module, "dcerpc_reassembly");
2270       } else if (strcmp(module->name, "ndmp") == 0) {
2271         /* Handle old names for NDMP preferences. */
2272         if (strcmp(dotp, "ndmp.desegment") == 0)
2273           pref = prefs_find_preference(module, "desegment");
2274       } else if (strcmp(module->name, "diameter") == 0) {
2275         /* Handle old names for Diameter preferences. */
2276         if (strcmp(dotp, "diameter.desegment") == 0)
2277           pref = prefs_find_preference(module, "desegment");
2278       } else if (strcmp(module->name, "pcli") == 0) {
2279         /* Handle old names for PCLI preferences. */
2280         if (strcmp(dotp, "pcli.udp_port") == 0)
2281           pref = prefs_find_preference(module, "udp_port");
2282       } else if (strcmp(module->name, "artnet") == 0) {
2283         /* Handle old names for ARTNET preferences. */
2284         if (strcmp(dotp, "artnet.udp_port") == 0)
2285           pref = prefs_find_preference(module, "udp_port");
2286       } else if (strcmp(module->name, "mapi") == 0) {
2287         /* Handle old names for MAPI preferences. */
2288         if (strcmp(dotp, "mapi_decrypt") == 0)
2289           pref = prefs_find_preference(module, "decrypt");
2290       } else if (strcmp(module->name, "fc") == 0) {
2291         /* Handle old names for Fibre Channel preferences. */
2292         if (strcmp(dotp, "reassemble_fc") == 0)
2293           pref = prefs_find_preference(module, "reassemble");
2294         else if (strcmp(dotp, "fc_max_frame_size") == 0)
2295           pref = prefs_find_preference(module, "max_frame_size");
2296       } else if (strcmp(module->name, "fcip") == 0) {
2297         /* Handle old names for Fibre Channel-over-IP preferences. */
2298         if (strcmp(dotp, "desegment_fcip_messages") == 0)
2299           pref = prefs_find_preference(module, "desegment");
2300         else if (strcmp(dotp, "fcip_port") == 0)
2301           pref = prefs_find_preference(module, "target_port");
2302       } else if (strcmp(module->name, "gtp") == 0) {
2303         /* Handle old names for GTP preferences. */
2304         if (strcmp(dotp, "gtpv0_port") == 0)
2305           pref = prefs_find_preference(module, "v0_port");
2306         else if (strcmp(dotp, "gtpv1c_port") == 0)
2307           pref = prefs_find_preference(module, "v1c_port");
2308         else if (strcmp(dotp, "gtpv1u_port") == 0)
2309           pref = prefs_find_preference(module, "v1u_port");
2310         else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
2311           pref = prefs_find_preference(module, "dissect_tpdu");
2312         else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
2313           pref = prefs_find_preference(module, "v0_dissect_cdr_as");
2314         else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
2315           pref = prefs_find_preference(module, "v0_check_etsi");
2316         else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
2317           pref = prefs_find_preference(module, "v1_check_etsi");
2318       } else if (strcmp(module->name, "ip") == 0) {
2319         /* Handle old names for IP preferences. */
2320         if (strcmp(dotp, "ip_summary_in_tree") == 0)
2321           pref = prefs_find_preference(module, "summary_in_tree");
2322       } else if (strcmp(module->name, "iscsi") == 0) {
2323         /* Handle old names for iSCSI preferences. */
2324         if (strcmp(dotp, "iscsi_port") == 0)
2325           pref = prefs_find_preference(module, "target_port");
2326       } else if (strcmp(module->name, "lmp") == 0) {
2327         /* Handle old names for LMP preferences. */
2328         if (strcmp(dotp, "lmp_version") == 0)
2329           pref = prefs_find_preference(module, "version");
2330       } else if (strcmp(module->name, "mtp3") == 0) {
2331         /* Handle old names for MTP3 preferences. */
2332         if (strcmp(dotp, "mtp3_standard") == 0)
2333           pref = prefs_find_preference(module, "standard");
2334         else if (strcmp(dotp, "net_addr_format") == 0)
2335           pref = prefs_find_preference(module, "addr_format");
2336       } else if (strcmp(module->name, "nlm") == 0) {
2337         /* Handle old names for NLM preferences. */
2338         if (strcmp(dotp, "nlm_msg_res_matching") == 0)
2339           pref = prefs_find_preference(module, "msg_res_matching");
2340       } else if (strcmp(module->name, "ppp") == 0) {
2341         /* Handle old names for PPP preferences. */
2342         if (strcmp(dotp, "ppp_fcs") == 0)
2343           pref = prefs_find_preference(module, "fcs_type");
2344         else if (strcmp(dotp, "ppp_vj") == 0)
2345           pref = prefs_find_preference(module, "decompress_vj");
2346       } else if (strcmp(module->name, "rsvp") == 0) {
2347         /* Handle old names for RSVP preferences. */
2348         if (strcmp(dotp, "rsvp_process_bundle") == 0)
2349           pref = prefs_find_preference(module, "process_bundle");
2350       } else if (strcmp(module->name, "tcp") == 0) {
2351         /* Handle old names for TCP preferences. */
2352         if (strcmp(dotp, "tcp_summary_in_tree") == 0)
2353           pref = prefs_find_preference(module, "summary_in_tree");
2354         else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
2355           pref = prefs_find_preference(module, "analyze_sequence_numbers");
2356         else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
2357           pref = prefs_find_preference(module, "relative_sequence_numbers");
2358       } else if (strcmp(module->name, "udp") == 0) {
2359         /* Handle old names for UDP preferences. */
2360         if (strcmp(dotp, "udp_summary_in_tree") == 0)
2361           pref = prefs_find_preference(module, "summary_in_tree");
2362       } else if (strcmp(module->name, "ndps") == 0) {
2363         /* Handle old names for NDPS preferences. */
2364         if (strcmp(dotp, "desegment_ndps") == 0)
2365           pref = prefs_find_preference(module, "desegment_tcp");
2366       } else if (strcmp(module->name, "http") == 0) {
2367         /* Handle old names for HTTP preferences. */
2368         if (strcmp(dotp, "desegment_http_headers") == 0)
2369           pref = prefs_find_preference(module, "desegment_headers");
2370         else if (strcmp(dotp, "desegment_http_body") == 0)
2371           pref = prefs_find_preference(module, "desegment_body");
2372       } else if (strcmp(module->name, "smpp") == 0) {
2373         /* Handle preferences that moved from SMPP. */
2374         module_t *new_module = prefs_find_module("gsm-sms-ud");
2375         if(new_module){
2376           if (strcmp(dotp, "port_number_udh_means_wsp") == 0)
2377             pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
2378           else if (strcmp(dotp, "try_dissect_1st_fragment") == 0)
2379             pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
2380         }
2381       } else if (strcmp(module->name, "asn1") == 0) {
2382         /* Handle old generic ASN.1 preferences (it's not really a
2383            rename, as the new preferences support multiple ports,
2384            but we might as well copy them over). */
2385         if (strcmp(dotp, "tcp_port") == 0)
2386           pref = prefs_find_preference(module, "tcp_ports");
2387         else if (strcmp(dotp, "udp_port") == 0)
2388           pref = prefs_find_preference(module, "udp_ports");
2389         else if (strcmp(dotp, "sctp_port") == 0)
2390           pref = prefs_find_preference(module, "sctp_ports");
2391       } else if (strcmp(module->name, "llcgprs") == 0) {
2392         if (strcmp(dotp, "ignore_cipher_bit") == 0)
2393           pref = prefs_find_preference(module, "autodetect_cipher_bit");
2394       } else if (strcmp(module->name, "erf") == 0) {
2395         if (strcmp(dotp, "erfeth") == 0) {
2396           /* Handle the old "erfeth" preference; map it to the new
2397              "ethfcs" preference, and map the values to those for
2398              the new preference. */
2399           pref = prefs_find_preference(module, "ethfcs");
2400           if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
2401             value = "TRUE";
2402           else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
2403             value = "FALSE";
2404           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2405             value = "TRUE";
2406         } else if (strcmp(dotp, "erfatm") == 0) {
2407           /* Handle the old "erfatm" preference; map it to the new
2408              "aal5_type" preference, and map the values to those for
2409              the new preference. */
2410           pref = prefs_find_preference(module, "aal5_type");
2411           if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
2412             value = "guess";
2413           else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
2414             value = "llc";
2415           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2416             value = "guess";
2417         } else if (strcmp(dotp, "erfhdlc") == 0) {
2418           /* Handle the old "erfhdlc" preference; map it to the new
2419              "hdlc_type" preference, and map the values to those for
2420              the new preference. */
2421           pref = prefs_find_preference(module, "hdlc_type");
2422           if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
2423             value = "chdlc";
2424           else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
2425             value = "ppp";
2426           else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
2427             value = "frelay";
2428           else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
2429             value = "mtp2";
2430           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2431             value = "guess";
2432         }
2433       }
2434     }
2435     if (pref == NULL)
2436       return PREFS_SET_NO_SUCH_PREF;    /* no such preference */
2437
2438     switch (pref->type) {
2439
2440     case PREF_UINT:
2441       uval = strtoul(value, &p, pref->info.base);
2442       if (p == value || *p != '\0')
2443         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2444       if (*pref->varp.uint != uval) {
2445         module->prefs_changed = TRUE;
2446         *pref->varp.uint = uval;
2447       }
2448       break;
2449
2450     case PREF_BOOL:
2451       /* XXX - give an error if it's neither "true" nor "false"? */
2452       if (g_ascii_strcasecmp(value, "true") == 0)
2453         bval = TRUE;
2454       else
2455         bval = FALSE;
2456       if (*pref->varp.boolp != bval) {
2457         module->prefs_changed = TRUE;
2458         *pref->varp.boolp = bval;
2459       }
2460       break;
2461
2462     case PREF_ENUM:
2463       /* XXX - give an error if it doesn't match? */
2464       enum_val = find_val_for_string(value,
2465                                         pref->info.enum_info.enumvals, 1);
2466       if (*pref->varp.enump != enum_val) {
2467         module->prefs_changed = TRUE;
2468         *pref->varp.enump = enum_val;
2469       }
2470       break;
2471
2472     case PREF_STRING:
2473       if (strcmp(*pref->varp.string, value) != 0) {
2474         module->prefs_changed = TRUE;
2475         g_free((void *)*pref->varp.string);
2476         *pref->varp.string = g_strdup(value);
2477       }
2478       break;
2479
2480     case PREF_RANGE:
2481     {
2482       range_t *newrange;
2483
2484       if (range_convert_str(&newrange, value, pref->info.max_value) !=
2485           CVT_NO_ERROR) {
2486         /* XXX - distinguish between CVT_SYNTAX_ERROR and
2487            CVT_NUMBER_TOO_BIG */
2488         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2489       }
2490
2491       if (!ranges_are_equal(*pref->varp.range, newrange)) {
2492         module->prefs_changed = TRUE;
2493         g_free(*pref->varp.range);
2494         *pref->varp.range = newrange;
2495       } else {
2496         g_free (newrange);
2497       }
2498       break;
2499     }
2500
2501     case PREF_STATIC_TEXT:
2502     case PREF_UAT:
2503     {
2504       break;
2505     }
2506
2507     case PREF_OBSOLETE:
2508       return PREFS_SET_OBSOLETE;        /* no such preference any more */
2509     }
2510   }
2511
2512   return PREFS_SET_OK;
2513 }
2514
2515 typedef struct {
2516         module_t *module;
2517         FILE    *pf;
2518 } write_pref_arg_t;
2519
2520 /*
2521  * Write out a single preference.
2522  */
2523 static void
2524 write_pref(gpointer data, gpointer user_data)
2525 {
2526         pref_t *pref = data;
2527         write_pref_arg_t *arg = user_data;
2528         const enum_val_t *enum_valp;
2529         const char *val_string;
2530         gchar **desc_lines;
2531         int i;
2532
2533         if (pref->type == PREF_OBSOLETE) {
2534                 /*
2535                  * This preference is no longer supported; it's not a
2536                  * real preference, so we don't write it out (i.e., we
2537                  * treat it as if it weren't found in the list of
2538                  * preferences, and we weren't called in the first place).
2539                  */
2540                 return;
2541         }
2542
2543         /*
2544          * Make multiple line descriptions appear as
2545          * multiple commented lines in prefs file.
2546          */
2547         if (g_ascii_strncasecmp(pref->description,"", 2) != 0) {
2548                 desc_lines = g_strsplit(pref->description,"\n",0);
2549                 for (i = 0; desc_lines[i] != NULL; ++i) {
2550                         fprintf(arg->pf, "\n# %s", desc_lines[i]);
2551                 }
2552                 fprintf(arg->pf, "\n");
2553                 g_strfreev(desc_lines);
2554         } else {
2555                 fprintf(arg->pf, "\n# No description\n");
2556         }
2557
2558         switch (pref->type) {
2559
2560         case PREF_UINT:
2561                 switch (pref->info.base) {
2562
2563                 case 10:
2564                         fprintf(arg->pf, "# A decimal number.\n");
2565                         fprintf(arg->pf, "%s.%s: %u\n", arg->module->name,
2566                             pref->name, *pref->varp.uint);
2567                         break;
2568
2569                 case 8:
2570                         fprintf(arg->pf, "# An octal number.\n");
2571                         fprintf(arg->pf, "%s.%s: %#o\n", arg->module->name,
2572                             pref->name, *pref->varp.uint);
2573                         break;
2574
2575                 case 16:
2576                         fprintf(arg->pf, "# A hexadecimal number.\n");
2577                         fprintf(arg->pf, "%s.%s: %#x\n", arg->module->name,
2578                             pref->name, *pref->varp.uint);
2579                         break;
2580                 }
2581                 break;
2582
2583         case PREF_BOOL:
2584                 fprintf(arg->pf, "# TRUE or FALSE (case-insensitive).\n");
2585                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2586                     *pref->varp.boolp ? "TRUE" : "FALSE");
2587                 break;
2588
2589         case PREF_ENUM:
2590                 /*
2591                  * For now, we save the "description" value, so that if we
2592                  * save the preferences older versions of Wireshark can at
2593                  * least read preferences that they supported; we support
2594                  * either the short name or the description when reading
2595                  * the preferences file or a "-o" option.
2596                  */
2597                 fprintf(arg->pf, "# One of: ");
2598                 enum_valp = pref->info.enum_info.enumvals;
2599                 val_string = NULL;
2600                 while (enum_valp->name != NULL) {
2601                         if (enum_valp->value == *pref->varp.enump)
2602                                 val_string = enum_valp->description;
2603                         fprintf(arg->pf, "%s", enum_valp->description);
2604                         enum_valp++;
2605                         if (enum_valp->name == NULL)
2606                                 fprintf(arg->pf, "\n");
2607                         else
2608                                 fprintf(arg->pf, ", ");
2609                 }
2610                 fprintf(arg->pf, "# (case-insensitive).\n");
2611                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name,
2612                     pref->name, val_string);
2613                 break;
2614
2615         case PREF_STRING:
2616                 fprintf(arg->pf, "# A string.\n");
2617                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2618                     *pref->varp.string);
2619                 break;
2620
2621         case PREF_RANGE:
2622         {
2623                 char *range_string;
2624
2625                 range_string = range_convert_range(*pref->varp.range);
2626                 fprintf(arg->pf, "# A string denoting an positive integer range (e.g., \"1-20,30-40\").\n");
2627                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2628                         range_string);
2629                 break;
2630         }
2631
2632         case PREF_STATIC_TEXT:
2633         case PREF_UAT:
2634         {
2635                 /* Nothing to do */
2636                 break;
2637         }
2638
2639         case PREF_OBSOLETE:
2640                 g_assert_not_reached();
2641                 break;
2642         }
2643 }
2644
2645 static gboolean
2646 write_module_prefs(void *value, void *data)
2647 {
2648         write_pref_arg_t arg;
2649
2650         arg.module = value;
2651         arg.pf = data;
2652         g_list_foreach(arg.module->prefs, write_pref, &arg);
2653         return FALSE;
2654 }
2655
2656 /* Write out "prefs" to the user's preferences file, and return 0.
2657
2658    If the preferences file path is NULL, write to stdout.
2659
2660    If we got an error, stuff a pointer to the path of the preferences file
2661    into "*pf_path_return", and return the errno. */
2662 int
2663 write_prefs(char **pf_path_return)
2664 {
2665   char        *pf_path;
2666   FILE        *pf;
2667   GList       *clp, *col_l;
2668   fmt_data    *cfmt;
2669   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
2670
2671   /* Needed for "-G defaultprefs" */
2672   init_prefs();
2673
2674   /* To do:
2675    * - Split output lines longer than MAX_VAL_LEN
2676    * - Create a function for the preference directory check/creation
2677    *   so that duplication can be avoided with filter.c
2678    */
2679
2680   if (pf_path_return != NULL) {
2681     pf_path = get_persconffile_path(PF_NAME, TRUE, TRUE);
2682     if ((pf = ws_fopen(pf_path, "w")) == NULL) {
2683       *pf_path_return = pf_path;
2684       return errno;
2685     }
2686   } else {
2687     pf = stdout;
2688   }
2689
2690   fputs("# Configuration file for Wireshark " VERSION ".\n"
2691     "#\n"
2692     "# This file is regenerated each time preferences are saved within\n"
2693     "# Wireshark.  Making manual changes should be safe, however.\n", pf);
2694
2695   fprintf (pf, "\n######## User Interface ########\n");
2696
2697   fprintf(pf, "\n# Vertical scrollbars should be on right side?\n");
2698   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2699   fprintf(pf, PRS_GUI_SCROLLBAR_ON_RIGHT ": %s\n",
2700                   prefs.gui_scrollbar_on_right == TRUE ? "TRUE" : "FALSE");
2701
2702   fprintf(pf, "\n# Packet-list selection bar can be used to browse w/o selecting?\n");
2703   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2704   fprintf(pf, PRS_GUI_PLIST_SEL_BROWSE ": %s\n",
2705                   prefs.gui_plist_sel_browse == TRUE ? "TRUE" : "FALSE");
2706
2707   fprintf(pf, "\n# Protocol-tree selection bar can be used to browse w/o selecting?\n");
2708   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2709   fprintf(pf, PRS_GUI_PTREE_SEL_BROWSE ": %s\n",
2710                   prefs.gui_ptree_sel_browse == TRUE ? "TRUE" : "FALSE");
2711
2712   fprintf(pf, "\n# Alternating colors in TreeViews?\n");
2713   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2714   fprintf(pf, PRS_GUI_ALTERN_COLORS ": %s\n",
2715                   prefs.gui_altern_colors == TRUE ? "TRUE" : "FALSE");
2716
2717   fprintf(pf, "\n# Place filter toolbar inside the statusbar?\n");
2718   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2719   fprintf(pf, PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR ": %s\n",
2720                  prefs.filter_toolbar_show_in_statusbar == TRUE ? "TRUE" : "FALSE");
2721
2722   fprintf(pf, "\n# Protocol-tree line style.\n");
2723   fprintf(pf, "# One of: NONE, SOLID, DOTTED, TABBED\n");
2724   fprintf(pf, PRS_GUI_PTREE_LINE_STYLE ": %s\n",
2725           gui_ptree_line_style_text[prefs.gui_ptree_line_style]);
2726
2727   fprintf(pf, "\n# Protocol-tree expander style.\n");
2728   fprintf(pf, "# One of: NONE, SQUARE, TRIANGLE, CIRCULAR\n");
2729   fprintf(pf, PRS_GUI_PTREE_EXPANDER_STYLE ": %s\n",
2730                   gui_ptree_expander_style_text[prefs.gui_ptree_expander_style]);
2731
2732   fprintf(pf, "\n# Hex dump highlight style.\n");
2733   fprintf(pf, "# One of: BOLD, INVERSE\n");
2734   fprintf(pf, PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE ": %s\n",
2735                   gui_hex_dump_highlight_style_text[prefs.gui_hex_dump_highlight_style]);
2736
2737   fprintf(pf, "\n# Main Toolbar style.\n");
2738   fprintf(pf, "# One of: ICONS, TEXT, BOTH\n");
2739   fprintf(pf, PRS_GUI_TOOLBAR_MAIN_STYLE ": %s\n",
2740                   gui_toolbar_style_text[prefs.gui_toolbar_main_style]);
2741
2742   fprintf(pf, "\n# Save window position at exit?\n");
2743   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2744   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_POSITION ": %s\n",
2745                   prefs.gui_geometry_save_position == TRUE ? "TRUE" : "FALSE");
2746
2747   fprintf(pf, "\n# Save window size at exit?\n");
2748   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2749   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_SIZE ": %s\n",
2750                   prefs.gui_geometry_save_size == TRUE ? "TRUE" : "FALSE");
2751
2752   fprintf(pf, "\n# Save window maximized state at exit?\n");
2753   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2754   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_MAXIMIZED ": %s\n",
2755                   prefs.gui_geometry_save_maximized == TRUE ? "TRUE" : "FALSE");
2756
2757   fprintf(pf, "\n# Use MacOS X style (Mac OS X with native GTK only)?\n");
2758   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2759   fprintf(pf, PRS_GUI_MACOSX_STYLE ": %s\n",
2760                   prefs.gui_macosx_style == TRUE ? "TRUE" : "FALSE");
2761
2762   fprintf(pf, "\n# Open a console window (WIN32 only)?\n");
2763   fprintf(pf, "# One of: NEVER, AUTOMATIC, ALWAYS\n");
2764   fprintf(pf, PRS_GUI_CONSOLE_OPEN ": %s\n",
2765                   gui_console_open_text[prefs.gui_console_open]);
2766
2767   fprintf(pf, "\n# The max. number of entries in the display filter list.\n");
2768   fprintf(pf, "# A decimal number.\n");
2769   fprintf(pf, PRS_GUI_RECENT_DF_ENTRIES_MAX ": %d\n",
2770                   prefs.gui_recent_df_entries_max);
2771
2772   fprintf(pf, "\n# The max. number of items in the open recent files list.\n");
2773   fprintf(pf, "# A decimal number.\n");
2774   fprintf(pf, PRS_GUI_RECENT_COUNT_MAX ": %d\n",
2775                   prefs.gui_recent_files_count_max);
2776
2777   fprintf(pf, "\n# Where to start the File Open dialog box.\n");
2778   fprintf(pf, "# One of: LAST_OPENED, SPECIFIED\n");
2779   fprintf(pf, PRS_GUI_FILEOPEN_STYLE ": %s\n",
2780                   gui_fileopen_style_text[prefs.gui_fileopen_style]);
2781
2782   if (prefs.gui_fileopen_dir != NULL) {
2783     fprintf(pf, "\n# Directory to start in when opening File Open dialog.\n");
2784     fprintf(pf, PRS_GUI_FILEOPEN_DIR ": %s\n",
2785                   prefs.gui_fileopen_dir);
2786   }
2787
2788   fprintf(pf, "\n# The preview timeout in the File Open dialog.\n");
2789   fprintf(pf, "# A decimal number (in seconds).\n");
2790   fprintf(pf, PRS_GUI_FILEOPEN_PREVIEW ": %d\n",
2791                   prefs.gui_fileopen_preview);
2792
2793   fprintf(pf, "\n# Ask to save unsaved capture files?\n");
2794   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2795   fprintf(pf, PRS_GUI_ASK_UNSAVED ": %s\n",
2796                   prefs.gui_ask_unsaved == TRUE ? "TRUE" : "FALSE");
2797
2798   fprintf(pf, "\n# Wrap to beginning/end of file during search?\n");
2799   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2800   fprintf(pf, PRS_GUI_FIND_WRAP ": %s\n",
2801                   prefs.gui_find_wrap == TRUE ? "TRUE" : "FALSE");
2802
2803   fprintf(pf, "\n# Settings dialogs use a save button?\n");
2804   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2805   fprintf(pf, PRS_GUI_USE_PREF_SAVE ": %s\n",
2806                   prefs.gui_use_pref_save == TRUE ? "TRUE" : "FALSE");
2807
2808   fprintf(pf, "\n# The path to the webbrowser.\n");
2809   fprintf(pf, "# Ex: mozilla %%s\n");
2810   fprintf(pf, PRS_GUI_WEBBROWSER ": %s\n", prefs.gui_webbrowser);
2811
2812   fprintf(pf, "\n# Custom window title. (Prepended to existing titles.)\n");
2813   fprintf(pf, PRS_GUI_WINDOW_TITLE ": %s\n",
2814               prefs.gui_window_title);
2815
2816   fprintf(pf, "\n# Custom start page title.\n");
2817   fprintf(pf, PRS_GUI_START_TITLE ": %s\n",
2818               prefs.gui_start_title);
2819
2820   fprintf(pf, "\n# Show version in start page, can be useful in custom builds.\n");
2821   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2822   fprintf(pf, PRS_GUI_VERSION_IN_START_PAGE ": %s\n",
2823                   prefs.gui_version_in_start_page == TRUE ? "TRUE" : "FALSE");
2824
2825   fprintf (pf, "\n######## User Interface: Layout ########\n");
2826
2827   fprintf(pf, "\n# Layout type (1-6).\n");
2828   fprintf(pf, PRS_GUI_LAYOUT_TYPE ": %d\n",
2829                   prefs.gui_layout_type);
2830
2831   fprintf(pf, "\n# Layout content of the panes (1-3).\n");
2832   fprintf(pf, "# One of: NONE, PLIST, PDETAILS, PBYTES\n");
2833   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_1 ": %s\n",
2834                   gui_layout_content_text[prefs.gui_layout_content_1]);
2835   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_2 ": %s\n",
2836                   gui_layout_content_text[prefs.gui_layout_content_2]);
2837   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_3 ": %s\n",
2838                   gui_layout_content_text[prefs.gui_layout_content_3]);
2839
2840   fprintf (pf, "\n######## User Interface: Columns ########\n");
2841
2842   clp = prefs.col_list;
2843   col_l = NULL;
2844   while (clp) {
2845     cfmt = (fmt_data *) clp->data;
2846     col_l = g_list_append(col_l, cfmt->title);
2847     if ((strcmp(cfmt->fmt, cust_format) == 0) && (cfmt->custom_field)) {
2848       gchar *fmt = g_strdup_printf("%s:%s", cfmt->fmt, cfmt->custom_field);
2849       col_l = g_list_append(col_l, fmt);
2850     } else {
2851       col_l = g_list_append(col_l, cfmt->fmt);
2852     }
2853     clp = clp->next;
2854   }
2855   fprintf (pf, "\n# Packet list column format.\n");
2856   fprintf (pf, "# Each pair of strings consists of a column title and its format.\n");
2857   fprintf (pf, "%s: %s\n", PRS_COL_FMT, put_string_list(col_l));
2858   /* This frees the list of strings, but not the strings to which it
2859      refers; that's what we want, as we haven't copied those strings,
2860      we just referred to them.  */
2861   g_list_free(col_l);
2862
2863   fprintf (pf, "\n######## User Interface: Font ########\n");
2864
2865   fprintf(pf, "\n# Font name for packet list, protocol tree, and hex dump panes.\n");
2866   fprintf(pf, PRS_GUI_FONT_NAME_2 ": %s\n", prefs.gui_font_name);
2867
2868   fprintf (pf, "\n######## User Interface: Colors ########\n");
2869
2870   fprintf (pf, "\n# Color preferences for a marked frame.\n");
2871   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
2872   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_FG,
2873     (prefs.gui_marked_fg.red * 255 / 65535),
2874     (prefs.gui_marked_fg.green * 255 / 65535),
2875     (prefs.gui_marked_fg.blue * 255 / 65535));
2876   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_BG,
2877     (prefs.gui_marked_bg.red * 255 / 65535),
2878     (prefs.gui_marked_bg.green * 255 / 65535),
2879     (prefs.gui_marked_bg.blue * 255 / 65535));
2880
2881   /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
2882    * file until the colors can be changed in the GUI. Currently this is not really
2883    * possible since the STOCK-icons for these colors are hardcoded.
2884    *
2885    * XXX Find a way to change the colors of the STOCK-icons on the fly and then
2886    *     add these 10 colors to the list of colors that can be changed through
2887    *     the preferences.
2888    *
2889   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_FG, prefs.gui_colorized_fg);
2890   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_BG, prefs.gui_colorized_bg);
2891   */
2892
2893   fprintf (pf, "\n# TCP stream window color preferences.\n");
2894   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
2895   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_FG,
2896     (prefs.st_client_fg.red * 255 / 65535),
2897     (prefs.st_client_fg.green * 255 / 65535),
2898     (prefs.st_client_fg.blue * 255 / 65535));
2899   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_BG,
2900     (prefs.st_client_bg.red * 255 / 65535),
2901     (prefs.st_client_bg.green * 255 / 65535),
2902     (prefs.st_client_bg.blue * 255 / 65535));
2903   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_FG,
2904     (prefs.st_server_fg.red * 255 / 65535),
2905     (prefs.st_server_fg.green * 255 / 65535),
2906     (prefs.st_server_fg.blue * 255 / 65535));
2907   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_BG,
2908     (prefs.st_server_bg.red * 255 / 65535),
2909     (prefs.st_server_bg.green * 255 / 65535),
2910     (prefs.st_server_bg.blue * 255 / 65535));
2911
2912   fprintf(pf, "\n######## Console: logging level ########\n");
2913   fprintf(pf, "# (debugging only, not in the Preferences dialog)\n");
2914   fprintf(pf, "# A bitmask of glib log levels:\n"
2915           "# G_LOG_LEVEL_ERROR    = 4\n"
2916           "# G_LOG_LEVEL_CRITICAL = 8\n"
2917           "# G_LOG_LEVEL_WARNING  = 16\n"
2918           "# G_LOG_LEVEL_MESSAGE  = 32\n"
2919           "# G_LOG_LEVEL_INFO     = 64\n"
2920           "# G_LOG_LEVEL_DEBUG    = 128\n");
2921
2922   fprintf(pf, PRS_CONSOLE_LOG_LEVEL ": %u\n",
2923           prefs.console_log_level);
2924
2925   fprintf(pf, "\n####### Capture ########\n");
2926
2927   if (prefs.capture_device != NULL) {
2928     fprintf(pf, "\n# Default capture device\n");
2929     fprintf(pf, PRS_CAP_DEVICE ": %s\n", prefs.capture_device);
2930   }
2931
2932   if (prefs.capture_devices_linktypes != NULL) {
2933     fprintf(pf, "\n# Interface link-layer header types.\n");
2934     fprintf(pf, "# A decimal number for the DLT.\n");
2935     fprintf(pf, "# Ex: en0(1),en1(143),...\n");
2936     fprintf(pf, PRS_CAP_DEVICES_LINKTYPES ": %s\n", prefs.capture_devices_linktypes);
2937   }
2938
2939   if (prefs.capture_devices_descr != NULL) {
2940     fprintf(pf, "\n# Interface descriptions.\n");
2941     fprintf(pf, "# Ex: eth0(eth0 descr),eth1(eth1 descr),...\n");
2942     fprintf(pf, PRS_CAP_DEVICES_DESCR ": %s\n", prefs.capture_devices_descr);
2943   }
2944
2945   if (prefs.capture_devices_hide != NULL) {
2946     fprintf(pf, "\n# Hide interface?\n");
2947     fprintf(pf, "# Ex: eth0,eth3,...\n");
2948     fprintf(pf, PRS_CAP_DEVICES_HIDE ": %s\n", prefs.capture_devices_hide);
2949   }
2950
2951   fprintf(pf, "\n# Capture in promiscuous mode?\n");
2952   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2953   fprintf(pf, PRS_CAP_PROM_MODE ": %s\n",
2954                   prefs.capture_prom_mode == TRUE ? "TRUE" : "FALSE");
2955
2956   fprintf(pf, "\n# Capture in Pcap-NG format?\n");
2957   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2958   fprintf(pf, PRS_CAP_PCAP_NG ": %s\n",
2959                   prefs.capture_pcap_ng == TRUE ? "TRUE" : "FALSE");
2960
2961   fprintf(pf, "\n# Update packet list in real time during capture?\n");
2962   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2963   fprintf(pf, PRS_CAP_REAL_TIME ": %s\n",
2964                   prefs.capture_real_time == TRUE ? "TRUE" : "FALSE");
2965
2966   fprintf(pf, "\n# Scroll packet list during capture?\n");
2967   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2968   fprintf(pf, PRS_CAP_AUTO_SCROLL ": %s\n",
2969                   prefs.capture_auto_scroll == TRUE ? "TRUE" : "FALSE");
2970
2971   fprintf(pf, "\n# Show capture info dialog while capturing?\n");
2972   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2973   fprintf(pf, PRS_CAP_SHOW_INFO ": %s\n",
2974                   prefs.capture_show_info == TRUE ? "TRUE" : "FALSE");
2975
2976   fprintf (pf, "\n######## Printing ########\n");
2977
2978   fprintf (pf, "\n# Can be one of \"text\" or \"postscript\".\n"
2979     "print.format: %s\n", pr_formats[prefs.pr_format]);
2980
2981   fprintf (pf, "\n# Can be one of \"command\" or \"file\".\n"
2982     "print.destination: %s\n", pr_dests[prefs.pr_dest]);
2983
2984   fprintf (pf, "\n# This is the file that gets written to when the "
2985     "destination is set to \"file\"\n"
2986     "%s: %s\n", PRS_PRINT_FILE, prefs.pr_file);
2987
2988   fprintf (pf, "\n# Output gets piped to this command when the destination "
2989     "is set to \"command\"\n"
2990     "%s: %s\n", PRS_PRINT_CMD, prefs.pr_cmd);
2991
2992   fprintf(pf, "\n####### Name Resolution ########\n");
2993
2994   fprintf(pf, "\n# Resolve addresses to names?\n");
2995   fprintf(pf, "# TRUE or FALSE (case-insensitive), or a list of address types to resolve.\n");
2996   fprintf(pf, PRS_NAME_RESOLVE ": %s\n",
2997                   name_resolve_to_string(prefs.name_resolve));
2998
2999   fprintf(pf, "\n# Name resolution concurrency.\n");
3000   fprintf(pf, "# A decimal number.\n");
3001   fprintf(pf, PRS_NAME_RESOLVE_CONCURRENCY ": %d\n",
3002                   prefs.name_resolve_concurrency);
3003
3004   fprintf(pf, "\n####### Taps/Statistics ########\n");
3005
3006   fprintf(pf, "\n# Tap update interval in ms.\n");
3007   fprintf(pf, "# An integer value greater between 100 and 10000.\n");
3008   fprintf(pf, PRS_TAP_UPDATE_INTERVAL ": %d\n",
3009           prefs.tap_update_interval);
3010   fprintf(pf, "\n# Maximum visible channels in RTP Player window.\n");
3011   fprintf(pf, "# An integer value greater than 0.\n");
3012   fprintf(pf, PRS_RTP_PLAYER_MAX_VISIBLE ": %d\n",
3013                   prefs.rtp_player_max_visible);
3014
3015   fprintf(pf, "\n####### Protocols ########\n");
3016
3017   fprintf(pf, "\n# Display hidden items in packet details pane?\n");
3018   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3019   fprintf(pf, PRS_DISPLAY_HIDDEN_PROTO_ITEMS ": %s\n",
3020                   prefs.display_hidden_proto_items == TRUE ? "TRUE" : "FALSE");
3021
3022   pe_tree_foreach(prefs_modules, write_module_prefs, pf);
3023
3024   fclose(pf);
3025
3026   /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
3027      an error indication, or maybe write to a new preferences file and
3028      rename that file on top of the old one only if there are not I/O
3029      errors. */
3030   return 0;
3031 }
3032
3033 /* Copy a set of preferences. */
3034 void
3035 copy_prefs(e_prefs *dest, e_prefs *src)
3036 {
3037   fmt_data *src_cfmt, *dest_cfmt;
3038   GList *entry;
3039
3040   dest->pr_format = src->pr_format;
3041   dest->pr_dest = src->pr_dest;
3042   dest->pr_file = g_strdup(src->pr_file);
3043   dest->pr_cmd = g_strdup(src->pr_cmd);
3044   dest->col_list = NULL;
3045   for (entry = src->col_list; entry != NULL; entry = g_list_next(entry)) {
3046     src_cfmt = entry->data;
3047     dest_cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
3048     dest_cfmt->title = g_strdup(src_cfmt->title);
3049     dest_cfmt->fmt = g_strdup(src_cfmt->fmt);
3050     if (src_cfmt->custom_field) {
3051       dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
3052     } else {
3053       dest_cfmt->custom_field = NULL;
3054     }
3055     dest->col_list = g_list_append(dest->col_list, dest_cfmt);
3056   }
3057   dest->num_cols = src->num_cols;
3058   dest->st_client_fg = src->st_client_fg;
3059   dest->st_client_bg = src->st_client_bg;
3060   dest->st_server_fg = src->st_server_fg;
3061   dest->st_server_bg = src->st_server_bg;
3062   dest->gui_scrollbar_on_right = src->gui_scrollbar_on_right;
3063   dest->gui_plist_sel_browse = src->gui_plist_sel_browse;
3064   dest->gui_ptree_sel_browse = src->gui_ptree_sel_browse;
3065   dest->gui_altern_colors = src->gui_altern_colors;
3066   dest->filter_toolbar_show_in_statusbar = src->filter_toolbar_show_in_statusbar;
3067   dest->gui_ptree_line_style = src->gui_ptree_line_style;
3068   dest->gui_ptree_expander_style = src->gui_ptree_expander_style;
3069   dest->gui_hex_dump_highlight_style = src->gui_hex_dump_highlight_style;
3070   dest->gui_toolbar_main_style = src->gui_toolbar_main_style;
3071   dest->gui_fileopen_dir = g_strdup(src->gui_fileopen_dir);
3072   dest->gui_console_open = src->gui_console_open;
3073   dest->gui_fileopen_style = src->gui_fileopen_style;
3074   dest->gui_fileopen_preview = src->gui_fileopen_preview;
3075   dest->gui_ask_unsaved = src->gui_ask_unsaved;
3076   dest->gui_find_wrap = src->gui_find_wrap;
3077   dest->gui_use_pref_save = src->gui_use_pref_save;
3078   dest->gui_layout_type = src->gui_layout_type;
3079   dest->gui_layout_content_1 = src->gui_layout_content_1;
3080   dest->gui_layout_content_2 = src->gui_layout_content_2;
3081   dest->gui_layout_content_3 = src->gui_layout_content_3;
3082   dest->gui_font_name = g_strdup(src->gui_font_name);
3083   dest->gui_marked_fg = src->gui_marked_fg;
3084   dest->gui_marked_bg = src->gui_marked_bg;
3085   dest->gui_geometry_save_position = src->gui_geometry_save_position;
3086   dest->gui_geometry_save_size = src->gui_geometry_save_size;
3087   dest->gui_geometry_save_maximized = src->gui_geometry_save_maximized;
3088   dest->gui_macosx_style = src->gui_macosx_style;
3089   dest->gui_webbrowser = g_strdup(src->gui_webbrowser);
3090   dest->gui_window_title = g_strdup(src->gui_window_title);
3091   dest->gui_start_title = g_strdup(src->gui_start_title);
3092   dest->gui_version_in_start_page = src->gui_version_in_start_page;
3093   dest->console_log_level = src->console_log_level;
3094 /*  values for the capture dialog box */
3095   dest->capture_device = g_strdup(src->capture_device);
3096   dest->capture_devices_linktypes = g_strdup(src->capture_devices_linktypes);
3097   dest->capture_devices_descr = g_strdup(src->capture_devices_descr);
3098   dest->capture_devices_hide = g_strdup(src->capture_devices_hide);
3099   dest->capture_prom_mode = src->capture_prom_mode;
3100   dest->capture_pcap_ng = src->capture_pcap_ng;
3101   dest->capture_real_time = src->capture_real_time;
3102   dest->capture_auto_scroll = src->capture_auto_scroll;
3103   dest->capture_show_info = src->capture_show_info;
3104   dest->name_resolve = src->name_resolve;
3105   dest->name_resolve_concurrency = src->name_resolve_concurrency;
3106   dest->display_hidden_proto_items = src->display_hidden_proto_items;
3107
3108 }
3109
3110 /* Free a set of preferences. */
3111 void
3112 free_prefs(e_prefs *pr)
3113 {
3114   if (pr->pr_file != NULL) {
3115     g_free(pr->pr_file);
3116     pr->pr_file = NULL;
3117   }
3118   if (pr->pr_cmd != NULL) {
3119     g_free(pr->pr_cmd);
3120     pr->pr_cmd = NULL;
3121   }
3122   free_col_info(pr);
3123   if (pr->gui_font_name != NULL) {
3124     g_free(pr->gui_font_name);
3125     pr->gui_font_name = NULL;
3126   }
3127   if (pr->gui_fileopen_dir != NULL) {
3128     g_free(pr->gui_fileopen_dir);
3129     pr->gui_fileopen_dir = NULL;
3130   }
3131   g_free(pr->gui_webbrowser);
3132   pr->gui_webbrowser = NULL;
3133   if (pr->gui_window_title != NULL) {
3134     g_free(pr->gui_window_title);
3135     pr->gui_window_title = NULL;
3136   }
3137   if (pr->gui_start_title != NULL) {
3138     g_free(pr->gui_start_title);
3139     pr->gui_start_title = NULL;
3140   }
3141   if (pr->capture_device != NULL) {
3142     g_free(pr->capture_device);
3143     pr->capture_device = NULL;
3144   }
3145   if (pr->capture_devices_linktypes != NULL) {
3146     g_free(pr->capture_devices_linktypes);
3147     pr->capture_devices_linktypes = NULL;
3148   }
3149   if (pr->capture_devices_descr != NULL) {
3150     g_free(pr->capture_devices_descr);
3151     pr->capture_devices_descr = NULL;
3152   }
3153   if (pr->capture_devices_hide != NULL) {
3154     g_free(pr->capture_devices_hide);
3155     pr->capture_devices_hide = NULL;
3156   }
3157 }
3158
3159 static void
3160 free_col_info(e_prefs *pr)
3161 {
3162   fmt_data *cfmt;
3163
3164   while (pr->col_list != NULL) {
3165     cfmt = pr->col_list->data;
3166
3167     g_free(cfmt->title);
3168     g_free(cfmt->fmt);
3169     g_free(cfmt->custom_field);
3170     g_free(cfmt);
3171     pr->col_list = g_list_remove_link(pr->col_list, pr->col_list);
3172   }
3173   g_list_free(pr->col_list);
3174   pr->col_list = NULL;
3175 }
3176
3177