Don't pass a null pointer to strcmp.
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <errno.h>
31
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include <glib.h>
37
38 #include <stdio.h>
39 #include <epan/filesystem.h>
40 #include <epan/address.h>
41 #include <epan/addr_resolv.h>
42 #include <epan/oids.h>
43 #ifdef HAVE_GEOIP
44 #include <epan/geoip_db.h>
45 #endif
46 #include <epan/packet.h>
47 #include <epan/prefs.h>
48 #include <epan/proto.h>
49 #include <epan/strutil.h>
50 #include <epan/column.h>
51 #include "print.h"
52 #include <wsutil/file_util.h>
53
54 #include <epan/prefs-int.h>
55 #include <epan/uat-int.h>
56
57 #include "epan/filter_expressions.h"
58
59 /* Internal functions */
60 static module_t *find_subtree(module_t *parent, const char *tilte);
61 static module_t *prefs_register_module_or_subtree(module_t *parent,
62     const char *name, const char *title, const char *description, gboolean is_subtree,
63     void (*apply_cb)(void), gboolean use_gui);
64 static prefs_set_pref_e set_pref(gchar*, gchar*, void *, gboolean);
65 static void write_string_list(FILE *, GList *, gboolean is_default);
66 static void free_col_info(GList *);
67 static void pre_init_prefs(void);
68 static gboolean prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt);
69 static gboolean parse_column_format(fmt_data *cfmt, const char *fmt);
70 static void try_convert_to_custom_column(gpointer *el_data);
71
72
73 #define PF_NAME         "preferences"
74 #define OLD_GPF_NAME    "wireshark.conf"        /* old name for global preferences file */
75
76 static gboolean prefs_initialized = FALSE;
77 static gboolean prefs_pre_initialized = FALSE;
78 static gchar *gpf_path = NULL;
79 static gchar *cols_hidden_list = NULL;
80
81 /*
82  * XXX - variables to allow us to attempt to interpret the first
83  * "mgcp.{tcp,udp}.port" in a preferences file as
84  * "mgcp.{tcp,udp}.gateway_port" and the second as
85  * "mgcp.{tcp,udp}.callagent_port".
86  */
87 static int mgcp_tcp_port_count;
88 static int mgcp_udp_port_count;
89
90 e_prefs prefs;
91
92 static enum_val_t gui_ptree_line_style[] = {
93                 {"NONE", "NONE", 0},
94                 {"SOLID", "SOLID", 1},
95                 {"DOTTED", "DOTTED", 2},
96                 {"TABBED", "TABBED", 3},
97                 {NULL, NULL, -1}
98         };
99
100 static enum_val_t gui_ptree_expander_style[] = {
101                 {"NONE", "NONE", 0},
102                 {"SQUARE", "SQUARE", 1},
103                 {"TRIANGLE", "TRIANGLE", 2},
104                 {"CIRCULAR", "CIRCULAR", 3},
105                 {NULL, NULL, -1}
106         };
107
108 static enum_val_t gui_hex_dump_highlight_style[] = {
109                 {"BOLD", "BOLD", 0},
110                 {"INVERSE", "INVERSE", 1},
111                 {NULL, NULL, -1}
112         };
113
114 static enum_val_t gui_console_open_type[] = {
115                 {"NEVER", "NEVER", console_open_never},
116                 {"AUTOMATIC", "AUTOMATIC", console_open_auto},
117                 {"ALWAYS", "ALWAYS", console_open_always},
118                 {NULL, NULL, -1}
119         };
120
121 static enum_val_t gui_version_placement_type[] = {
122                 {"WELCOME", "WELCOME", version_welcome_only},
123                 {"TITLE", "TITLE", version_title_only},
124                 {"BOTH", "BOTH", version_both},
125                 {"NEITHER", "NEITHER", version_neither},
126                 {NULL, NULL, -1}
127         };
128
129 static enum_val_t gui_fileopen_style[] = {
130                 {"LAST_OPENED", "LAST_OPENED", 0},
131                 {"SPECIFIED", "SPECIFIED", 1},
132                 {NULL, NULL, -1}
133         };
134
135 /* GTK knows of two ways representing "both", vertical and horizontal aligned.
136  * as this may not work on other guis, we use only "both" in general here */
137 static enum_val_t gui_toolbar_style[] = {
138                 {"ICONS", "ICONS", 0},
139                 {"TEXT", "TEXT", 1},
140                 {"BOTH", "BOTH", 2},
141                 {NULL, NULL, -1}
142         };
143
144 static enum_val_t gui_layout_content[] = {
145                 {"NONE", "NONE", 0},
146                 {"PLIST", "PLIST", 1},
147                 {"PDETAILS", "PDETAILS", 2},
148                 {"PBYTES", "PBYTES", 3},
149                 {NULL, NULL, -1}
150         };
151
152 /*
153  * List of all modules with preference settings.
154  */
155 static emem_tree_t *prefs_modules = NULL;
156
157 /*
158  * List of all modules that should show up at the top level of the
159  * tree in the preference dialog box.
160  */
161 static emem_tree_t *prefs_top_level_modules = NULL;
162
163 /** Sets up memory used by proto routines. Called at program startup */
164 void
165 prefs_init(void)
166 {
167     prefs_modules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_modules");
168     prefs_top_level_modules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_top_level_modules");
169 }
170
171 static void
172 free_pref(gpointer data, gpointer user_data _U_)
173 {
174     pref_t *pref = data;
175
176     switch (pref->type) {
177     case PREF_OBSOLETE:
178     case PREF_BOOL:
179     case PREF_ENUM:
180     case PREF_UINT:
181     case PREF_STATIC_TEXT:
182     case PREF_UAT:
183     case PREF_COLOR:
184         break;
185     case PREF_STRING:
186     case PREF_FILENAME:
187         g_free((char *)*pref->varp.string);
188         *pref->varp.string = NULL;
189         g_free(pref->default_val.string);
190         break;
191     case PREF_RANGE:
192         g_free(*pref->varp.range);
193         *pref->varp.range = NULL;
194         g_free(pref->default_val.range);
195         break;
196     case PREF_CUSTOM:
197         pref->custom_cbs.free_cb(pref);
198         break;
199     }
200
201     g_free(pref);
202 }
203
204 static guint
205 free_module_prefs(module_t *module, gpointer data _U_)
206 {
207     g_list_foreach(module->prefs, free_pref, NULL);
208     g_list_free(module->prefs);
209     module->prefs = NULL;
210     module->numprefs = 0;
211     /*  We don't free the actual module: its submodules pointer points to
212         a pe_tree and the module itself is stored in a pe_tree
213      */
214
215     return 0;
216 }
217
218 /** Frees memory used by proto routines. Called at program shutdown */
219 void
220 prefs_cleanup(void)
221 {
222     /*  This isn't strictly necessary since we're exiting anyway, but let's
223      *  do what clean up we can.
224      */
225     prefs_modules_foreach(free_module_prefs, NULL);
226 }
227
228 /*
229  * Register a module that will have preferences.
230  * Specify the module under which to register it or NULL to register it
231  * at the top level, the name used for the module in the preferences file,
232  * the title used in the tab for it in a preferences dialog box, and a
233  * routine to call back when we apply the preferences.
234  */
235 module_t *
236 prefs_register_module(module_t *parent, const char *name, const char *title,
237                       const char *description, void (*apply_cb)(void),
238                       const gboolean use_gui)
239 {
240     return prefs_register_module_or_subtree(parent, name, title, description,
241                                             FALSE, apply_cb, use_gui);
242 }
243
244 /*
245  * Register a subtree that will have modules under it.
246  * Specify the module under which to register it or NULL to register it
247  * at the top level and the title used in the tab for it in a preferences
248  * dialog box.
249  */
250 module_t *
251 prefs_register_subtree(module_t *parent, const char *title, const char *description,
252                        void (*apply_cb)(void))
253 {
254     return prefs_register_module_or_subtree(parent, NULL, title, description,
255                                             TRUE, apply_cb,
256                                             parent ? parent->use_gui : FALSE);
257 }
258
259 static module_t *
260 prefs_register_module_or_subtree(module_t *parent, const char *name,
261                                  const char *title, const char *description,
262                                  gboolean is_subtree, void (*apply_cb)(void),
263                                  gboolean use_gui)
264 {
265     module_t *module;
266     const char *p;
267     guchar c;
268
269     /* this module may have been created as a subtree item previously */
270     if((module = find_subtree(parent, title))) {
271         /* the module is currently a subtree */
272         module->name = name;
273         module->apply_cb = apply_cb;
274         module->description = description;
275
276         if (prefs_find_module(name) == NULL) {
277             pe_tree_insert_string(prefs_modules, name, module,
278                                   EMEM_TREE_STRING_NOCASE);
279         }
280
281         return module;
282     }
283
284     module = g_malloc(sizeof (module_t));
285     module->name = name;
286     module->title = title;
287     module->description = description;
288     module->apply_cb = apply_cb;
289     module->prefs = NULL;    /* no preferences, to start */
290     module->parent = parent;
291     module->submodules = NULL;    /* no submodules, to start */
292     module->numprefs = 0;
293     module->prefs_changed = FALSE;
294     module->obsolete = FALSE;
295     module->use_gui = use_gui;
296
297     /*
298      * Do we have a module name?
299      */
300     if (name != NULL) {
301         /*
302          * Yes.
303          * Make sure that only lower-case ASCII letters, numbers,
304          * underscores, hyphens, and dots appear in the name.
305          *
306          * Crash if there is, as that's an error in the code;
307          * you can make the title a nice string with capitalization,
308          * white space, punctuation, etc., but the name can be used
309          * on the command line, and shouldn't require quoting,
310          * shifting, etc.
311          */
312         for (p = name; (c = *p) != '\0'; p++)
313             g_assert(isascii(c) &&
314                 (islower(c) || isdigit(c) || c == '_' ||
315                  c == '-' || c == '.'));
316
317         /*
318          * Make sure there's not already a module with that
319          * name.  Crash if there is, as that's an error in the
320          * code, and the code has to be fixed not to register
321          * more than one module with the same name.
322          *
323          * We search the list of all modules; the subtree stuff
324          * doesn't require preferences in subtrees to have names
325          * that reflect the subtree they're in (that would require
326          * protocol preferences to have a bogus "protocol.", or
327          * something such as that, to be added to all their names).
328          */
329         g_assert(prefs_find_module(name) == NULL);
330
331         /*
332          * Insert this module in the list of all modules.
333          */
334         pe_tree_insert_string(prefs_modules, name, module, EMEM_TREE_STRING_NOCASE);
335     } else {
336         /*
337          * This has no name, just a title; check to make sure it's a
338          * subtree, and crash if it's not.
339          */
340         g_assert(is_subtree);
341     }
342
343     /*
344      * Insert this module into the appropriate place in the display
345      * tree.
346      */
347     if (parent == NULL) {
348         /*
349          * It goes at the top.
350          */
351         pe_tree_insert_string(prefs_top_level_modules, title, module, EMEM_TREE_STRING_NOCASE);
352     } else {
353         /*
354          * It goes into the list for this module.
355          */
356
357         if (parent->submodules == NULL)
358             parent->submodules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_submodules");
359
360         pe_tree_insert_string(parent->submodules, title, module, EMEM_TREE_STRING_NOCASE);
361     }
362
363     return module;
364 }
365
366 /*
367  * Register that a protocol has preferences.
368  */
369 module_t *protocols_module = NULL;
370
371 module_t *
372 prefs_register_protocol(int id, void (*apply_cb)(void))
373 {
374     protocol_t *protocol;
375
376     /*
377      * Have we yet created the "Protocols" subtree?
378      */
379     if (protocols_module == NULL) {
380         /*
381          * No.  Register Protocols subtree as well as any preferences
382          * for non-dissector modules.
383          */
384         prefs_register_modules();
385     }
386     protocol = find_protocol_by_id(id);
387     return prefs_register_module(protocols_module,
388                                  proto_get_protocol_filter_name(id),
389                                  proto_get_protocol_short_name(protocol),
390                                  proto_get_protocol_name(id), apply_cb, TRUE);
391 }
392
393 module_t *
394 prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
395 {
396     protocol_t *protocol;
397     module_t   *subtree_module;
398     module_t   *new_module;
399     char       *sep = NULL, *ptr = NULL;
400
401     /*
402      * Have we yet created the "Protocols" subtree?
403      * XXX - can we just do this by registering Protocols/{subtree}?
404      * If not, why not?
405      */
406     if (protocols_module == NULL) {
407         /*
408          * No.  Register Protocols subtree as well as any preferences
409          * for non-dissector modules.
410          */
411         prefs_register_modules();
412     }
413
414     subtree_module = protocols_module;
415
416     if(subtree) {
417         /* take a copy of the buffer */
418         ptr = g_strdup(subtree);
419
420         while(ptr && *ptr) {
421
422             if((sep = strchr(ptr, '/')))
423                 *sep++ = '\0';
424
425             if(!(new_module = find_subtree(subtree_module, ptr))) {
426                 /*
427                  * There's no such module; create it, with the description
428                  * being the name (if it's later registered explicitly
429                  * with a description, that will override it).
430                  */
431                 new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL);
432             }
433
434             subtree_module = new_module;
435             ptr = sep;
436
437         }
438     }
439
440     protocol = find_protocol_by_id(id);
441     return prefs_register_module(subtree_module,
442                                  proto_get_protocol_filter_name(id),
443                                  proto_get_protocol_short_name(protocol),
444                                  proto_get_protocol_name(id), apply_cb, TRUE);
445 }
446
447
448 /*
449  * Register that a protocol used to have preferences but no longer does,
450  * by creating an "obsolete" module for it.
451  */
452 module_t *
453 prefs_register_protocol_obsolete(int id)
454 {
455     module_t *module;
456     protocol_t *protocol;
457
458     /*
459      * Have we yet created the "Protocols" subtree?
460      */
461     if (protocols_module == NULL) {
462         /*
463          * No.  Register Protocols subtree as well as any preferences
464          * for non-dissector modules.
465          */
466         prefs_register_modules();
467     }
468     protocol = find_protocol_by_id(id);
469     module = prefs_register_module(protocols_module,
470                                    proto_get_protocol_filter_name(id),
471                                    proto_get_protocol_short_name(protocol),
472                                    proto_get_protocol_name(id), NULL, TRUE);
473     module->obsolete = TRUE;
474     return module;
475 }
476
477 /*
478  * Register that a statistical tap has preferences.
479  *
480  * "name" is a name for the tap to use on the command line with "-o"
481  * and in preference files.
482  *
483  * "title" is a short human-readable name for the tap.
484  *
485  * "description" is a longer human-readable description of the tap.
486  */
487 module_t *stats_module = NULL;
488
489 module_t *
490 prefs_register_stat(const char *name, const char *title,
491                     const char *description, void (*apply_cb)(void))
492 {
493     /*
494      * Have we yet created the "Statistics" subtree?
495      */
496     if (stats_module == NULL) {
497         /*
498          * No.  Register Statistics subtree as well as any preferences
499          * for non-dissector modules.
500          */
501          prefs_register_modules();
502     }
503
504     return prefs_register_module(stats_module, name, title, description,
505                                  apply_cb, TRUE);
506 }
507
508 module_t *
509 prefs_find_module(const char *name)
510 {
511     return pe_tree_lookup_string(prefs_modules, name, EMEM_TREE_STRING_NOCASE);
512 }
513
514 static module_t *
515 find_subtree(module_t *parent, const char *name)
516 {
517     return pe_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, EMEM_TREE_STRING_NOCASE);
518 }
519
520 /*
521  * Call a callback function, with a specified argument, for each module
522  * in a list of modules.  If the list is NULL, searches the top-level
523  * list in the display tree of modules.  If any callback returns a
524  * non-zero value, we stop and return that value, otherwise we
525  * return 0.
526  *
527  * Ignores "obsolete" modules; their sole purpose is to allow old
528  * preferences for dissectors that no longer have preferences to be
529  * silently ignored in preference files.  Does not ignore subtrees,
530  * as this can be used when walking the display tree of modules.
531  */
532
533 typedef struct {
534     module_cb callback;
535     gpointer user_data;
536     guint ret;
537 } call_foreach_t;
538
539 static gboolean
540 call_foreach_cb(void *value, void *data)
541 {
542     module_t *module = (module_t*)value;
543     call_foreach_t *call_data = (call_foreach_t*)data;
544
545     if (!module->obsolete) {
546         call_data->ret = (*call_data->callback)(module, call_data->user_data);
547     }
548     return (call_data->ret != 0);
549 }
550
551 static guint
552 prefs_module_list_foreach(emem_tree_t *module_list, module_cb callback,
553                           gpointer user_data)
554 {
555     call_foreach_t call_data;
556
557     if (module_list == NULL)
558         module_list = prefs_top_level_modules;
559
560     call_data.callback = callback;
561     call_data.user_data = user_data;
562     call_data.ret = 0;
563     pe_tree_foreach(module_list, call_foreach_cb, &call_data);
564     return call_data.ret;
565 }
566
567 /*
568  * Returns TRUE if module has any submodules
569  */
570 gboolean
571 prefs_module_has_submodules(module_t *module)
572 {
573     if (module->submodules == NULL) {
574         return FALSE;
575     }
576
577     if (module->submodules->tree == NULL) {
578         return FALSE;
579     }
580
581     return TRUE;
582 }
583
584 /*
585  * Call a callback function, with a specified argument, for each module
586  * in the list of all modules.  (This list does not include subtrees.)
587  *
588  * Ignores "obsolete" modules; their sole purpose is to allow old
589  * preferences for dissectors that no longer have preferences to be
590  * silently ignored in preference files.
591  */
592 guint
593 prefs_modules_foreach(module_cb callback, gpointer user_data)
594 {
595     return prefs_module_list_foreach(prefs_modules, callback, user_data);
596 }
597
598 /*
599  * Call a callback function, with a specified argument, for each submodule
600  * of specified modules.  If the module is NULL, goes through the top-level
601  * list in the display tree of modules.
602  *
603  * Ignores "obsolete" modules; their sole purpose is to allow old
604  * preferences for dissectors that no longer have preferences to be
605  * silently ignored in preference files.  Does not ignore subtrees,
606  * as this can be used when walking the display tree of modules.
607  */
608 guint
609 prefs_modules_foreach_submodules(module_t *module, module_cb callback,
610                                  gpointer user_data)
611 {
612     return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data);
613 }
614
615 static gboolean
616 call_apply_cb(void *value, void *data _U_)
617 {
618     module_t *module = value;
619
620     if (module->obsolete)
621         return FALSE;
622     if (module->prefs_changed) {
623         if (module->apply_cb != NULL)
624             (*module->apply_cb)();
625         module->prefs_changed = FALSE;
626     }
627     return FALSE;
628 }
629
630 /*
631  * Call the "apply" callback function for each module if any of its
632  * preferences have changed, and then clear the flag saying its
633  * preferences have changed, as the module has been notified of that
634  * fact.
635  */
636 void
637 prefs_apply_all(void)
638 {
639     pe_tree_foreach(prefs_modules, call_apply_cb, NULL);
640 }
641
642 /*
643  * Call the "apply" callback function for a specific module if any of
644  * its preferences have changed, and then clear the flag saying its
645  * preferences have changed, as the module has been notified of that
646  * fact.
647  */
648 void
649 prefs_apply(module_t *module)
650 {
651     if (module && module->prefs_changed)
652         call_apply_cb(module, NULL);
653 }
654
655 /*
656  * Register a preference in a module's list of preferences.
657  * If it has a title, give it an ordinal number; otherwise, it's a
658  * preference that won't show up in the UI, so it shouldn't get an
659  * ordinal number (the ordinal should be the ordinal in the set of
660  * *visible* preferences).
661  */
662 static pref_t *
663 register_preference(module_t *module, const char *name, const char *title,
664                     const char *description, pref_type_t type)
665 {
666     pref_t *preference;
667     const gchar *p;
668
669     preference = g_malloc(sizeof (pref_t));
670     preference->name = name;
671     preference->title = title;
672     preference->description = description;
673     preference->type = type;
674     if (title != NULL)
675         preference->ordinal = module->numprefs;
676     else
677         preference->ordinal = -1;    /* no ordinal for you */
678
679     /*
680      * Make sure that only lower-case ASCII letters, numbers,
681      * underscores, and dots appear in the preference name.
682      *
683      * Crash if there is, as that's an error in the code;
684      * you can make the title and description nice strings
685      * with capitalization, white space, punctuation, etc.,
686      * but the name can be used on the command line,
687      * and shouldn't require quoting, shifting, etc.
688      */
689     for (p = name; *p != '\0'; p++)
690         if (!(isascii((guchar)*p) &&
691             (islower((guchar)*p) || isdigit((guchar)*p) || *p == '_' || *p == '.')))
692             g_error("Preference %s.%s contains invalid characters", module->name, name);
693
694     /*
695      * Make sure there's not already a preference with that
696      * name.  Crash if there is, as that's an error in the
697      * code, and the code has to be fixed not to register
698      * more than one preference with the same name.
699      */
700     if (prefs_find_preference(module, name) != NULL)
701         g_error("Preference %s has already been registered", name);
702
703     if ((type != PREF_OBSOLETE) &&
704         /* Don't compare if its a subtree */
705         (module->name != NULL)) {
706         /*
707          * Make sure the preference name doesn't begin with the
708          * module name, as that's redundant and Just Silly.
709          */
710         if(!((strncmp(name, module->name, strlen(module->name)) != 0) ||
711             (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
712             g_error("Preference %s begins with the module name", name);
713     }
714
715     /*
716      * There isn't already one with that name, so add the
717      * preference.
718      */
719     module->prefs = g_list_append(module->prefs, preference);
720     if (title != NULL)
721         module->numprefs++;
722
723     return preference;
724 }
725
726 /*
727  * Find a preference in a module's list of preferences, given the module
728  * and the preference's name.
729  */
730 typedef struct {
731     GList *list_entry;
732     const char *name;
733 } find_pref_arg_t;
734
735 static gint
736 preference_match(gconstpointer a, gconstpointer b)
737 {
738     const pref_t *pref = a;
739     const char *name = b;
740
741     return strcmp(name, pref->name);
742 }
743
744 static gboolean module_find_pref_cb(void *value, void *data)
745 {
746     find_pref_arg_t* arg = (find_pref_arg_t*)data;
747     GList *list_entry;
748     module_t *module = value;
749
750     if (module == NULL)
751         return FALSE;
752
753     list_entry = g_list_find_custom(module->prefs, arg->name,
754         preference_match);
755
756     if (list_entry == NULL)
757         return FALSE;
758
759     arg->list_entry = list_entry;
760     return TRUE;
761 }
762
763 struct preference *
764 prefs_find_preference(module_t *module, const char *name)
765 {
766     find_pref_arg_t arg;
767     GList *list_entry;
768
769     if (module == NULL)
770         return NULL;    /* invalid parameters */
771
772     list_entry = g_list_find_custom(module->prefs, name,
773         preference_match);
774
775     if (list_entry == NULL)
776     {
777         arg.list_entry = NULL;
778         if (module->submodules != NULL)
779         {
780             arg.name = name;
781             pe_tree_foreach(module->submodules, module_find_pref_cb, &arg);
782         }
783
784         list_entry = arg.list_entry;
785     }
786
787     if (list_entry == NULL)
788     {
789         return NULL;    /* no such preference */
790     }
791
792     return (struct preference *) list_entry->data;
793 }
794
795 /*
796  * Returns TRUE if the given protocol has registered preferences
797  */
798 gboolean
799 prefs_is_registered_protocol(const char *name)
800 {
801     module_t *m = prefs_find_module(name);
802
803     return (m != NULL && !m->obsolete);
804 }
805
806 /*
807  * Returns the module title of a registered protocol
808  */
809 const char *
810 prefs_get_title_by_name(const char *name)
811 {
812     module_t *m = prefs_find_module(name);
813
814     return (m != NULL && !m->obsolete) ? m->title : NULL;
815 }
816
817 /*
818  * Register a preference with an unsigned integral value.
819  */
820 void
821 prefs_register_uint_preference(module_t *module, const char *name,
822                                const char *title, const char *description,
823                                guint base, guint *var)
824 {
825     pref_t *preference;
826
827     preference = register_preference(module, name, title, description,
828                                      PREF_UINT);
829     preference->varp.uint = var;
830     preference->default_val.uint = *var;
831     g_assert(base > 0 && base != 1 && base < 37);
832     preference->info.base = base;
833 }
834
835 /*
836  * Register a "custom" preference with a unsigned integral value.
837  * XXX - This should be temporary until we can find a better way
838  * to do "custom" preferences
839  */
840 static void
841 prefs_register_uint_custom_preference(module_t *module, const char *name,
842                                const char *title, const char *description,
843                                struct pref_custom_cbs* custom_cbs, guint *var)
844 {
845     pref_t *preference;
846
847     preference = register_preference(module, name, title, description,
848                                      PREF_CUSTOM);
849
850     preference->custom_cbs = *custom_cbs;
851     preference->varp.uint = var;
852     preference->default_val.uint = *var;
853 }
854
855 /*
856  * Register a preference with an Boolean value.
857  */
858 void
859 prefs_register_bool_preference(module_t *module, const char *name,
860                                const char *title, const char *description,
861                                gboolean *var)
862 {
863     pref_t *preference;
864
865     preference = register_preference(module, name, title, description,
866                                      PREF_BOOL);
867     preference->varp.boolp = var;
868     preference->default_val.boolval = *var;
869 }
870
871 /*
872  * Register a preference with an enumerated value.
873  */
874 void
875 prefs_register_enum_preference(module_t *module, const char *name,
876                                const char *title, const char *description,
877                                gint *var, const enum_val_t *enumvals,
878                                gboolean radio_buttons)
879 {
880     pref_t *preference;
881
882     preference = register_preference(module, name, title, description,
883                                      PREF_ENUM);
884     preference->varp.enump = var;
885     preference->default_val.enumval = *var;
886     preference->info.enum_info.enumvals = enumvals;
887     preference->info.enum_info.radio_buttons = radio_buttons;
888 }
889
890 static pref_t*
891 register_string_like_preference(module_t *module, const char *name,
892                                 const char *title, const char *description,
893                                 const char **var, pref_type_t type)
894 {
895     pref_t *preference;
896     char *varcopy;
897
898     preference = register_preference(module, name, title, description,
899                                      type);
900
901     /*
902      * String preference values should be non-null (as you can't
903      * keep them null after using the preferences GUI, you can at best
904      * have them be null strings) and freeable (as we free them
905      * if we change them).
906      *
907      * If the value is a null pointer, make it a copy of a null
908      * string, otherwise make it a copy of the value.
909      */
910     if (*var == NULL) {
911         *var = g_strdup("");
912         varcopy = g_strdup("");
913     } else {
914         *var = g_strdup(*var);
915         varcopy = g_strdup(*var);
916     }
917     preference->varp.string = var;
918     preference->default_val.string = varcopy;
919     preference->saved_val.string = NULL;
920
921     return preference;
922 }
923
924 /*
925  * Register a preference with a character-string value.
926  */
927 void
928 prefs_register_string_preference(module_t *module, const char *name,
929                                  const char *title, const char *description,
930                                  const char **var)
931 {
932     register_string_like_preference(module, name, title, description, var,
933                                     PREF_STRING);
934 }
935
936 /*
937  * Register a "custom" preference with a character-string value.
938  * XXX - This should be temporary until we can find a better way
939  * to do "custom" preferences
940  */
941 static
942 void prefs_register_string_custom_preference(module_t *module, const char *name,
943                                  const char *title, const char *description,
944                                  struct pref_custom_cbs* custom_cbs, const char **var)
945 {
946     pref_t *preference;
947
948     preference = register_string_like_preference(module, name, title, description, var,
949                                     PREF_CUSTOM);
950
951     preference->custom_cbs = *custom_cbs;
952 }
953
954
955 /*
956  * Register a preference with a file name (string) value.
957  */
958 void
959 prefs_register_filename_preference(module_t *module, const char *name,
960                                    const char *title, const char *description,
961                                    const char **var)
962 {
963     register_string_like_preference(module, name, title, description, var,
964                                     PREF_FILENAME);
965 }
966
967 /*
968  * Register a preference with a ranged value.
969  */
970 void
971 prefs_register_range_preference(module_t *module, const char *name,
972                                 const char *title, const char *description,
973                                 range_t **var, guint32 max_value)
974 {
975     pref_t *preference;
976
977     preference = register_preference(module, name, title, description,
978                                      PREF_RANGE);
979     preference->info.max_value = max_value;
980
981
982     /*
983      * Range preference values should be non-null (as you can't
984      * keep them null after using the preferences GUI, you can at best
985      * have them be empty ranges) and freeable (as we free them
986      * if we change them).
987      *
988      * If the value is a null pointer, make it an empty range.
989      */
990     if (*var == NULL)
991         *var = range_empty();
992     preference->varp.range = var;
993     preference->default_val.range = range_copy(*var);
994     preference->saved_val.range = NULL;
995 }
996
997 /*
998  * Register a static text 'preference'.  It can be used to add explanatory
999  * text inline with other preferences in the GUI.
1000  * Note: Static preferences are not saved to the preferences file.
1001  */
1002 void
1003 prefs_register_static_text_preference(module_t *module, const char *name,
1004                                       const char *title,
1005                                       const char *description)
1006 {
1007     register_preference(module, name, title, description, PREF_STATIC_TEXT);
1008 }
1009
1010 /*
1011  * Register a uat 'preference'. It adds a button that opens the uat's window in the
1012  * preferences tab of the module.
1013  */
1014 extern void
1015 prefs_register_uat_preference(module_t *module, const char *name,
1016                               const char *title, const char *description,
1017                               void* uat)
1018 {
1019
1020     pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1021
1022     preference->varp.uat = uat;
1023 }
1024
1025 /*
1026  * Register a color preference.
1027  */
1028 void prefs_register_color_preference(module_t *module, const char *name,
1029     const char *title, const char *description, color_t *color)
1030 {
1031     pref_t* preference = register_preference(module, name, title, description, PREF_COLOR);
1032
1033     preference->varp.color = color;
1034     preference->default_val.color = *color;
1035 }
1036
1037 /*
1038  * Register a "custom" preference with a list.
1039  * XXX - This should be temporary until we can find a better way
1040  * to do "custom" preferences
1041  */
1042 typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
1043
1044 static
1045 void prefs_register_list_custom_preference(module_t *module, const char *name,
1046     const char *title, const char *description, struct pref_custom_cbs* custom_cbs,
1047     pref_custom_list_init_cb init_cb, GList** list)
1048 {
1049     pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1050
1051     preference->custom_cbs = *custom_cbs;
1052     init_cb(preference, list);
1053 }
1054
1055 /*
1056  * Register a custom preference.
1057  */
1058 void prefs_register_custom_preference(module_t *module, const char *name,
1059     const char *title, const char *description, struct pref_custom_cbs* custom_cbs,
1060     void** custom_data _U_)
1061 {
1062     pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1063
1064     preference->custom_cbs = *custom_cbs;
1065     /* XXX - wait until we can handle void** pointers
1066     preference->custom_cbs.init_cb(preference, custom_data);
1067     */
1068 }
1069
1070 /*
1071  * Register a preference that used to be supported but no longer is.
1072  */
1073 void
1074 prefs_register_obsolete_preference(module_t *module, const char *name)
1075 {
1076     register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
1077 }
1078
1079 /*
1080  * Check to see if a preference is obsolete.
1081  */
1082 extern gboolean
1083 prefs_get_preference_obsolete(pref_t *pref)
1084 {
1085     if (pref) {
1086         return pref->type == PREF_OBSOLETE ? TRUE : FALSE;
1087     }
1088     return TRUE;
1089 }
1090
1091 /*
1092  * Make a preference obsolete.
1093  */
1094 extern prefs_set_pref_e
1095 prefs_set_preference_obsolete(pref_t *pref)
1096 {
1097     if (pref) {
1098         pref->type = PREF_OBSOLETE;
1099         return PREFS_SET_OK;
1100     }
1101     return PREFS_SET_NO_SUCH_PREF;
1102 }
1103
1104 /* Return the value assigned to the given uint preference. */
1105 guint prefs_get_uint_preference(pref_t *pref)
1106 {
1107     if (pref && pref->type == PREF_UINT)
1108         return *pref->varp.uint;
1109     return 0;
1110 }
1111
1112 /*
1113  * Call a callback function, with a specified argument, for each preference
1114  * in a given module.
1115  *
1116  * If any of the callbacks return a non-zero value, stop and return that
1117  * value, otherwise return 0.
1118  */
1119 guint
1120 prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
1121 {
1122     GList *elem;
1123     pref_t *pref;
1124     guint ret;
1125
1126     for (elem = g_list_first(module->prefs); elem != NULL; elem = g_list_next(elem)) {
1127         pref = elem->data;
1128         if (pref->type == PREF_OBSOLETE) {
1129             /*
1130              * This preference is no longer supported; it's
1131              * not a real preference, so we don't call the
1132              * callback for it (i.e., we treat it as if it
1133              * weren't found in the list of preferences,
1134              * and we weren't called in the first place).
1135              */
1136             continue;
1137         }
1138
1139         ret = (*callback)(pref, user_data);
1140         if (ret != 0)
1141             return ret;
1142     }
1143     return 0;
1144 }
1145
1146 static const enum_val_t print_format_vals[] = {
1147     { "text",       "Plain Text", PR_FMT_TEXT },
1148     { "postscript", "Postscript", PR_FMT_PS },
1149     { NULL,         NULL,         0 }
1150 };
1151
1152 static const enum_val_t print_dest_vals[] = {
1153 #ifdef _WIN32
1154     /* "PR_DEST_CMD" means "to printer" on Windows */
1155     { "command", "Printer", PR_DEST_CMD },
1156 #else
1157     { "command", "Command", PR_DEST_CMD },
1158 #endif
1159     { "file",    "File",    PR_DEST_FILE },
1160     { NULL,      NULL,      0 }
1161 };
1162
1163 static void stats_callback(void)
1164 {
1165     /* Test for a sane tap update interval */
1166     if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000) {
1167             prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
1168     }
1169
1170 #ifdef HAVE_LIBPORTAUDIO
1171     /* Test for a sane max channels entry */
1172     if (prefs.rtp_player_max_visible < 1 || prefs.rtp_player_max_visible > 10)
1173             prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
1174 #endif
1175
1176 }
1177
1178 static void gui_callback(void)
1179 {
1180     /* Ensure there is at least one file count */
1181     if (prefs.gui_recent_files_count_max == 0)
1182       prefs.gui_recent_files_count_max = 10;
1183
1184     /* Ensure there is at least one display filter entry */
1185     if (prefs.gui_recent_df_entries_max == 0)
1186       prefs.gui_recent_df_entries_max = 10;
1187 }
1188
1189 static void gui_layout_callback(void)
1190 {
1191     if (prefs.gui_layout_type == layout_unused ||
1192         prefs.gui_layout_type >= layout_type_max) {
1193       /* XXX - report an error?  It's not a syntax error - we'd need to
1194          add a way of reporting a *semantic* error. */
1195       prefs.gui_layout_type = layout_type_5;
1196     }
1197 }
1198
1199 /******************************************************
1200  * All custom preference function callbacks
1201  ******************************************************/
1202 static void custom_pref_no_cb(pref_t* pref _U_) {}
1203
1204
1205 /*
1206  * Console log level custom preference functions
1207  */
1208 static void console_log_level_reset_cb(pref_t* pref)
1209 {
1210     *pref->varp.uint = pref->default_val.uint;
1211 }
1212
1213 static prefs_set_pref_e console_log_level_set_cb(pref_t* pref, gchar* value, gboolean* changed)
1214 {
1215     guint    uval;
1216
1217     uval = strtoul(value, NULL, 10);
1218
1219     if (*pref->varp.uint != uval) {
1220         *changed = TRUE;
1221         *pref->varp.uint = uval;
1222     }
1223
1224     if (*pref->varp.uint & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG)) {
1225       /*
1226        * GLib >= 2.32 drops INFO and DEBUG messages by default. Tell
1227        * it not to do that.
1228        */
1229        g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
1230     }
1231
1232     return PREFS_SET_OK;
1233 }
1234
1235 static void console_log_level_write_cb(pref_t* pref, write_pref_arg_t* arg)
1236 {
1237     const char *prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
1238
1239     fprintf(arg->pf, "# (debugging only, not in the Preferences dialog)\n");
1240     fprintf(arg->pf, "# A bitmask of glib log levels:\n"
1241           "# G_LOG_LEVEL_ERROR    = 4\n"
1242           "# G_LOG_LEVEL_CRITICAL = 8\n"
1243           "# G_LOG_LEVEL_WARNING  = 16\n"
1244           "# G_LOG_LEVEL_MESSAGE  = 32\n"
1245           "# G_LOG_LEVEL_INFO     = 64\n"
1246           "# G_LOG_LEVEL_DEBUG    = 128\n");
1247
1248     if (*pref->varp.uint == pref->default_val.uint)
1249         fprintf(arg->pf, "#");
1250     fprintf(arg->pf, "%s.%s: %u\n", prefix,
1251                 pref->name, *pref->varp.uint);
1252 }
1253
1254 /*
1255  * Column hidden custom preference functions
1256  */
1257 #define PRS_COL_HIDDEN                   "column.hidden"
1258 #define PRS_COL_FMT                      "column.format"
1259 #define PRS_COL_NUM                      "column.number"
1260 static module_t *gui_column_module = NULL;
1261
1262 static void column_hidden_free_cb(pref_t* pref)
1263 {
1264     g_free((char *)*pref->varp.string);
1265     *pref->varp.string = NULL;
1266     g_free(pref->default_val.string);
1267 }
1268
1269 static void column_hidden_reset_cb(pref_t* pref)
1270 {
1271     g_free((void *)*pref->varp.string);
1272     *pref->varp.string = g_strdup(pref->default_val.string);
1273 }
1274
1275 static prefs_set_pref_e column_hidden_set_cb(pref_t* pref, gchar* value, gboolean* changed)
1276 {
1277     GList       *clp;
1278     fmt_data    *cfmt;
1279     pref_t  *format_pref;
1280
1281     if (*pref->varp.string && (strcmp(*pref->varp.string, value) != 0)) {
1282         *changed = TRUE;
1283         g_free((void *)*pref->varp.string);
1284         *pref->varp.string = g_strdup(value);
1285     }
1286
1287     /*
1288      * Set the "visible" flag for the existing columns; we need to
1289      * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
1290      * after setting it (which might be the case if, for example, we
1291      * set PRS_COL_HIDDEN on the command line).
1292      */
1293     format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
1294     for (clp = *format_pref->varp.list; clp != NULL; clp = clp->next) {
1295       cfmt = (fmt_data *)clp->data;
1296       cfmt->visible = prefs_is_column_visible(*pref->varp.string, cfmt);
1297     }
1298
1299     return PREFS_SET_OK;
1300 }
1301
1302 static void column_hidden_write_cb(pref_t* pref, write_pref_arg_t* arg)
1303 {
1304   GString     *cols_hidden = g_string_new ("");
1305   GList       *clp, *col_l;
1306   fmt_data    *cfmt;
1307   const char *prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
1308   pref_t  *format_pref;
1309
1310   format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
1311   clp = *format_pref->varp.list;
1312   col_l = NULL;
1313   while (clp) {
1314     gchar *prefs_fmt;
1315     cfmt = (fmt_data *) clp->data;
1316     col_l = g_list_append(col_l, g_strdup(cfmt->title));
1317     if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_field)) {
1318       prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
1319                                   col_format_to_string(cfmt->fmt),
1320                                   cfmt->custom_field,
1321                                   cfmt->custom_occurrence,
1322                                   cfmt->resolved ? 'R' : 'U');
1323     } else {
1324       prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
1325     }
1326     col_l = g_list_append(col_l, prefs_fmt);
1327     if (!cfmt->visible) {
1328       if (cols_hidden->len) {
1329              g_string_append (cols_hidden, ",");
1330       }
1331       g_string_append (cols_hidden, prefs_fmt);
1332     }
1333     clp = clp->next;
1334   }
1335   fprintf (arg->pf, "\n# Packet list hidden columns.\n");
1336   fprintf (arg->pf, "# List all columns to hide in the packet list.\n");
1337   if (strcmp(cols_hidden->str, pref->default_val.string) == 0)
1338     fprintf(arg->pf, "#");
1339   fprintf (arg->pf, "%s.%s: %s\n", prefix, pref->name, cols_hidden->str);
1340   /* This frees the list of strings, but not the strings to which it
1341      refers; they are free'ed in write_string_list(). */
1342   g_string_free (cols_hidden, TRUE);
1343   g_list_free(col_l);
1344 }
1345
1346 /* Number of columns "preference".  This is only used internally and is not written to the
1347  * preference file
1348  */
1349 static void column_num_reset_cb(pref_t* pref)
1350 {
1351     *pref->varp.uint = pref->default_val.uint;
1352 }
1353
1354 static prefs_set_pref_e column_num_set_cb(pref_t* pref _U_, gchar* value _U_, gboolean* changed _U_)
1355 {
1356     /* Don't write this to the preferences file */
1357     return PREFS_SET_OK;
1358 }
1359
1360 static void column_num_write_cb(pref_t* pref _U_, write_pref_arg_t* arg _U_) {}
1361
1362 /*
1363  * Column format custom preference functions
1364  */
1365 static void column_format_init_cb(pref_t* pref, GList** value)
1366 {
1367     fmt_data *src_cfmt, *dest_cfmt;
1368     GList *entry;
1369
1370     pref->varp.list = value;
1371
1372     pref->default_val.list = NULL;
1373     for (entry = *pref->varp.list; entry != NULL; entry = g_list_next(entry)) {
1374         src_cfmt = entry->data;
1375         dest_cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1376         dest_cfmt->title = g_strdup(src_cfmt->title);
1377         dest_cfmt->fmt = src_cfmt->fmt;
1378         if (src_cfmt->custom_field) {
1379             dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
1380             dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
1381         } else {
1382             dest_cfmt->custom_field = NULL;
1383             dest_cfmt->custom_occurrence = 0;
1384         }
1385         dest_cfmt->visible = src_cfmt->visible;
1386         dest_cfmt->resolved = src_cfmt->resolved;
1387         pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
1388     }
1389 }
1390
1391 static void column_format_free_cb(pref_t* pref)
1392 {
1393     free_col_info(*pref->varp.list);
1394     free_col_info(pref->default_val.list);
1395 }
1396
1397 static void column_format_reset_cb(pref_t* pref)
1398 {
1399     fmt_data *src_cfmt, *dest_cfmt;
1400     GList *entry;
1401     pref_t  *col_num_pref;
1402
1403     free_col_info(*pref->varp.list);
1404     *pref->varp.list = NULL;
1405
1406     for (entry = pref->default_val.list; entry != NULL; entry = g_list_next(entry)) {
1407         src_cfmt = entry->data;
1408         dest_cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1409         dest_cfmt->title = g_strdup(src_cfmt->title);
1410         dest_cfmt->fmt = src_cfmt->fmt;
1411         if (src_cfmt->custom_field) {
1412             dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
1413             dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
1414         } else {
1415             dest_cfmt->custom_field = NULL;
1416             dest_cfmt->custom_occurrence = 0;
1417         }
1418         dest_cfmt->visible = src_cfmt->visible;
1419         dest_cfmt->resolved = src_cfmt->resolved;
1420         *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
1421     }
1422
1423     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
1424     column_num_reset_cb(col_num_pref);
1425 }
1426
1427 static prefs_set_pref_e column_format_set_cb(pref_t* pref, gchar* value, gboolean* changed _U_)
1428 {
1429     GList    *col_l, *col_l_elt;
1430     fmt_data *cfmt;
1431     gint     llen;
1432     pref_t   *hidden_pref, *col_num_pref;
1433
1434     col_l = prefs_get_string_list(value);
1435     if (col_l == NULL)
1436       return PREFS_SET_SYNTAX_ERR;
1437     if ((g_list_length(col_l) % 2) != 0) {
1438       /* A title didn't have a matching format.  */
1439       prefs_clear_string_list(col_l);
1440       return PREFS_SET_SYNTAX_ERR;
1441     }
1442     /* Check to make sure all column formats are valid.  */
1443     col_l_elt = g_list_first(col_l);
1444     while(col_l_elt) {
1445       fmt_data cfmt_check;
1446
1447       /* Go past the title.  */
1448       col_l_elt = col_l_elt->next;
1449
1450       /* Parse the format to see if it's valid.  */
1451       if (!parse_column_format(&cfmt_check, col_l_elt->data)) {
1452         /* It's not a valid column format.  */
1453         prefs_clear_string_list(col_l);
1454         return PREFS_SET_SYNTAX_ERR;
1455       }
1456       if (cfmt_check.fmt != COL_CUSTOM) {
1457         /* Some predefined columns have been migrated to use custom colums.
1458          * We'll convert these silently here */
1459         try_convert_to_custom_column(&col_l_elt->data);
1460       } else {
1461         /* We don't need the custom column field on this pass. */
1462         g_free(cfmt_check.custom_field);
1463       }
1464
1465       /* Go past the format.  */
1466       col_l_elt = col_l_elt->next;
1467     }
1468
1469     /* They're all valid; process them. */
1470     free_col_info(*pref->varp.list);
1471     *pref->varp.list = NULL;
1472     hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN);
1473     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
1474     llen             = g_list_length(col_l);
1475     *col_num_pref->varp.uint = llen / 2;
1476     col_l_elt = g_list_first(col_l);
1477     while(col_l_elt) {
1478       cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1479       cfmt->title    = g_strdup(col_l_elt->data);
1480       col_l_elt      = col_l_elt->next;
1481       parse_column_format(cfmt, col_l_elt->data);
1482       cfmt->visible   = prefs_is_column_visible((gchar*)(*hidden_pref->varp.string), cfmt);
1483       col_l_elt      = col_l_elt->next;
1484       *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
1485     }
1486
1487     prefs_clear_string_list(col_l);
1488     column_hidden_free_cb(hidden_pref);
1489     return PREFS_SET_OK;
1490 }
1491
1492 static void column_format_write_cb(pref_t* pref, write_pref_arg_t* arg)
1493 {
1494   GList       *clp = *pref->varp.list, *col_l,
1495               *pref_col = g_list_first(clp),
1496               *def_col = g_list_first(pref->default_val.list);
1497   fmt_data    *cfmt, *def_cfmt;
1498   gchar       *prefs_fmt;
1499   gboolean    is_default = TRUE;
1500   pref_t      *col_num_pref;
1501   const char *prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
1502
1503   /* See if the column data has changed from the default */
1504   col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
1505   if (*col_num_pref->varp.uint != col_num_pref->default_val.uint) {
1506      is_default = FALSE;
1507   } else {
1508       while (pref_col && def_col) {
1509           cfmt = (fmt_data *) pref_col->data;
1510           def_cfmt = (fmt_data *) def_col->data;
1511           if ((strcmp(cfmt->title, def_cfmt->title) != 0) ||
1512               (cfmt->fmt != def_cfmt->fmt) ||
1513               (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_field)) &&
1514                  ((strcmp(cfmt->custom_field, def_cfmt->custom_field) != 0) ||
1515                  (cfmt->resolved != def_cfmt->resolved)))) {
1516              is_default = FALSE;
1517              break;
1518           }
1519
1520           pref_col = pref_col->next;
1521           def_col = def_col->next;
1522       }
1523   }
1524
1525   /* Now write the current columns */
1526   col_l = NULL;
1527   while (clp) {
1528     cfmt = (fmt_data *) clp->data;
1529     col_l = g_list_append(col_l, g_strdup(cfmt->title));
1530     if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_field)) {
1531       prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
1532                                   col_format_to_string(cfmt->fmt),
1533                                   cfmt->custom_field,
1534                                   cfmt->custom_occurrence,
1535                                   cfmt->resolved ? 'R' : 'U');
1536     } else {
1537       prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
1538     }
1539     col_l = g_list_append(col_l, prefs_fmt);
1540     clp = clp->next;
1541   }
1542
1543   fprintf (arg->pf, "\n# Packet list column format.\n");
1544   fprintf (arg->pf, "# Each pair of strings consists of a column title and its format.\n");
1545   if (is_default)
1546      fprintf(arg->pf, "#");
1547   fprintf(arg->pf, "%s.%s: ", prefix, pref->name);
1548   write_string_list(arg->pf, col_l, is_default);
1549   fprintf(arg->pf, "\n");
1550   /* This frees the list of strings, but not the strings to which it
1551      refers; they are free'ed in write_string_list(). */
1552   g_list_free(col_l);
1553 }
1554
1555 /*
1556  * Capture column custom preference functions
1557  */
1558 static void capture_column_init_cb(pref_t* pref, GList** value)
1559 {
1560     GList   *list = *value,
1561             *list_copy = NULL;
1562     gchar   *col;
1563
1564     pref->varp.list = value;
1565     /* Copy the current list */
1566     while (list) {
1567         col = (gchar *)list->data;
1568         list_copy = g_list_append(list_copy, g_strdup(col));
1569         list = list->next;
1570     }
1571
1572     pref->default_val.list = list_copy;
1573 }
1574
1575 static void capture_column_free_cb(pref_t* pref)
1576 {
1577     GList   *list = *pref->varp.list;
1578     gchar    *col_name;
1579
1580     while (list != NULL) {
1581         col_name = list->data;
1582
1583         g_free(col_name);
1584         list = g_list_remove_link(list, list);
1585     }
1586     g_list_free(list);
1587
1588     list = pref->default_val.list;
1589     while (list != NULL) {
1590         col_name = list->data;
1591
1592         g_free(col_name);
1593         list = g_list_remove_link(list, list);
1594     }
1595     g_list_free(list);
1596 }
1597
1598 static void capture_column_reset_cb(pref_t* pref)
1599 {
1600     GList   *list_copy = *pref->varp.list,
1601             *list = pref->default_val.list;
1602     gchar    *col_name;
1603
1604     /* Clear the list before it's copied */
1605     while (list_copy != NULL) {
1606         col_name = list_copy->data;
1607
1608         g_free(col_name);
1609         list_copy = g_list_remove_link(list_copy, list_copy);
1610     }
1611
1612     while (list) {
1613         col_name = (gchar *)list->data;
1614         list_copy = g_list_append(list_copy, g_strdup(col_name));
1615         list = list->next;
1616     }
1617 }
1618
1619 static prefs_set_pref_e capture_column_set_cb(pref_t* pref, gchar* value, gboolean* changed _U_)
1620 {
1621     GList    *col_l, *col_l_elt;
1622     gchar    *col_name;
1623
1624     col_l = prefs_get_string_list(value);
1625     if (col_l == NULL)
1626       return PREFS_SET_SYNTAX_ERR;
1627
1628     g_list_free(*pref->varp.list);
1629     *pref->varp.list = NULL;
1630
1631     col_l_elt = g_list_first(col_l);
1632     while(col_l_elt) {
1633       col_name = (gchar *)col_l_elt->data;
1634       *pref->varp.list = g_list_append(*pref->varp.list, col_name);
1635       col_l_elt = col_l_elt->next;
1636     }
1637
1638     return PREFS_SET_OK;
1639 }
1640
1641 static void capture_column_write_cb(pref_t* pref, write_pref_arg_t* arg)
1642 {
1643   GList       *clp = *pref->varp.list,
1644               *col_l = NULL,
1645               *pref_col = g_list_first(clp),
1646               *def_col = g_list_first(pref->default_val.list);
1647   gchar *col, *def_col_str;
1648   gboolean is_default = TRUE;
1649   const char *prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
1650
1651   /* See if the column data has changed from the default */
1652   while (pref_col && def_col) {
1653       col = (gchar *)pref_col->data;
1654       def_col_str = (gchar *) def_col->data;
1655       if (strcmp(col, def_col_str) != 0) {
1656          is_default = FALSE;
1657          break;
1658       }
1659
1660       pref_col = pref_col->next;
1661       def_col = def_col->next;
1662   }
1663
1664   /* Ensure the same column count */
1665   if (((pref_col == NULL) && (def_col != NULL)) ||
1666       ((pref_col != NULL) && (def_col == NULL)))
1667      is_default = FALSE;
1668
1669   while (clp) {
1670     col = (gchar *) clp->data;
1671     col_l = g_list_append(col_l, g_strdup(col));
1672     clp = clp->next;
1673   }
1674
1675   fprintf(arg->pf, "\n# Capture options dialog column list.\n");
1676   fprintf(arg->pf, "# List of columns to be displayed.\n");
1677   fprintf(arg->pf, "# Possible values: INTERFACE,LINK,PMODE,SNAPLEN,MONITOR,BUFFER,FILTER\n");
1678   if (is_default)
1679      fprintf(arg->pf, "#");
1680   fprintf(arg->pf, "%s.%s: ", prefix, pref->name);
1681   write_string_list(arg->pf, col_l, is_default);
1682   fprintf(arg->pf, "\n");
1683   /* This frees the list of strings, but not the strings to which it
1684      refers; they are free'ed in write_string_list(). */
1685   g_list_free(col_l);
1686
1687 }
1688
1689
1690 static void colorized_frame_free_cb(pref_t* pref)
1691 {
1692     g_free((char *)*pref->varp.string);
1693     *pref->varp.string = NULL;
1694     g_free(pref->default_val.string);
1695 }
1696
1697 static void colorized_frame_reset_cb(pref_t* pref)
1698 {
1699     g_free((void *)*pref->varp.string);
1700     *pref->varp.string = g_strdup(pref->default_val.string);
1701 }
1702
1703 static prefs_set_pref_e colorized_frame_set_cb(pref_t* pref, gchar* value, gboolean* changed)
1704 {
1705     if (strcmp(*pref->varp.string, value) != 0) {
1706         *changed = TRUE;
1707         g_free((void *)*pref->varp.string);
1708         *pref->varp.string = g_strdup(value);
1709     }
1710
1711     return PREFS_SET_OK;
1712 }
1713
1714 static void colorized_frame_write_cb(pref_t* pref _U_, write_pref_arg_t* arg _U_)
1715 {
1716    /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
1717     * file until the colors can be changed in the GUI. Currently this is not really
1718     * possible since the STOCK-icons for these colors are hardcoded.
1719     *
1720     * XXX Find a way to change the colors of the STOCK-icons on the fly and then
1721     *     add these 10 colors to the list of colors that can be changed through
1722     *     the preferences.
1723     *
1724     */
1725 }
1726
1727 /*
1728  * Register all non-dissector modules' preferences.
1729  */
1730 static module_t *gui_module = NULL;
1731 static module_t *gui_color_module = NULL;
1732 static module_t *nameres_module = NULL;
1733
1734 void
1735 prefs_register_modules(void)
1736 {
1737     module_t *printing, *capture_module, *console_module,
1738         *gui_layout_module, *gui_font_module;
1739     struct pref_custom_cbs custom_cbs;
1740
1741     if (protocols_module != NULL) {
1742         /* Already setup preferences */
1743         return;
1744     }
1745
1746     /* Ensure the "global" preferences have been initialized so the
1747      * preference API has the proper default values to work from
1748      */
1749     pre_init_prefs();
1750
1751     /* GUI
1752      * These are "simple" GUI preferences that can be read/written using the
1753      * preference module API.  These preferences still use their own
1754      * configuration screens for access, but this cuts down on the
1755      * preference "string compare list" in set_pref()
1756      */
1757     gui_module = prefs_register_module(NULL, "gui", "User Interface",
1758         "User Interface", &gui_callback, FALSE);
1759
1760     prefs_register_bool_preference(gui_module, "scrollbar_on_right",
1761                                    "Vertical scrollbars on right side",
1762                                    "Vertical scrollbars should be on right side?",
1763                                    &prefs.gui_scrollbar_on_right);
1764
1765     prefs_register_bool_preference(gui_module, "packet_list_sel_browse",
1766                                    "Packet-list selection bar browse",
1767                                    "Packet-list selection bar can be used to browse w/o selecting?",
1768                                    &prefs.gui_plist_sel_browse);
1769
1770     prefs_register_bool_preference(gui_module, "protocol_tree_sel_browse",
1771                                    "Protocol-tree selection bar browse",
1772                                    "Protocol-tree selection bar can be used to browse w/o selecting?",
1773                                    &prefs.gui_ptree_sel_browse);
1774
1775     prefs_register_bool_preference(gui_module, "tree_view_altern_colors",
1776                                    "Alternating colors in TreeViews",
1777                                    "Alternating colors in TreeViews?",
1778                                    &prefs.gui_altern_colors);
1779
1780     prefs_register_bool_preference(gui_module, "expert_composite_eyecandy",
1781                                    "Display LEDs on Expert Composite Dialog Tabs",
1782                                    "Display LEDs on Expert Composite Dialog Tabs?",
1783                                    &prefs.gui_expert_composite_eyecandy);
1784
1785     prefs_register_bool_preference(gui_module, "filter_toolbar_show_in_statusbar",
1786                                    "Place filter toolbar inside the statusbar",
1787                                    "Place filter toolbar inside the statusbar?",
1788                                    &prefs.filter_toolbar_show_in_statusbar);
1789
1790     prefs_register_enum_preference(gui_module, "protocol_tree_line_style",
1791                        "Protocol-tree line style",
1792                        "Protocol-tree line style",
1793                        &prefs.gui_ptree_line_style, gui_ptree_line_style, FALSE);
1794
1795     prefs_register_enum_preference(gui_module, "protocol_tree_expander_style",
1796                        "Protocol-tree expander style",
1797                        "Protocol-tree expander style",
1798                        &prefs.gui_ptree_expander_style, gui_ptree_expander_style, FALSE);
1799
1800     prefs_register_enum_preference(gui_module, "hex_dump_highlight_style",
1801                        "Hex dump highlight style",
1802                        "Hex dump highlight style",
1803                        &prefs.gui_hex_dump_highlight_style, gui_hex_dump_highlight_style, FALSE);
1804
1805     gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL);
1806
1807     custom_cbs.free_cb = column_hidden_free_cb;
1808     custom_cbs.reset_cb = column_hidden_reset_cb;
1809     custom_cbs.set_cb = column_hidden_set_cb;
1810     custom_cbs.write_cb = column_hidden_write_cb;
1811     prefs_register_string_custom_preference(gui_column_module, PRS_COL_HIDDEN, "Packet list hidden columns",
1812         "List all columns to hide in the packet list", &custom_cbs, (const char **)&cols_hidden_list);
1813
1814     custom_cbs.free_cb = column_format_free_cb;
1815     custom_cbs.reset_cb = column_format_reset_cb;
1816     custom_cbs.set_cb = column_format_set_cb;
1817     custom_cbs.write_cb = column_format_write_cb;
1818
1819     prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT, "Packet list column format",
1820         "Each pair of strings consists of a column title and its format", &custom_cbs,
1821         column_format_init_cb, &prefs.col_list);
1822
1823     /* Number of columns.  This is only used internally and is not written to the
1824      * preference file
1825      */
1826     custom_cbs.free_cb = custom_pref_no_cb;
1827     custom_cbs.reset_cb = column_num_reset_cb;
1828     custom_cbs.set_cb = column_num_set_cb;
1829     custom_cbs.write_cb = column_num_write_cb;
1830     prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM, "Number of columns",
1831         "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
1832
1833     /* User Interface : Font */
1834     gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL);
1835
1836     prefs_register_obsolete_preference(gui_font_module, "font_name");
1837
1838     prefs_register_string_preference(gui_font_module, "gtk2.font_name", "Font name",
1839         "Font name for packet list, protocol tree, and hex dump panes.", (const char**)(&prefs.gui_font_name));
1840
1841     /* User Interface : Colors */
1842     gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL);
1843
1844     prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
1845         "Color preferences for a marked frame", &prefs.gui_marked_fg);
1846
1847     prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
1848         "Color preferences for a marked frame", &prefs.gui_marked_bg);
1849
1850     prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
1851         "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
1852
1853     prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
1854         "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
1855
1856     prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
1857         "TCP stream window color preference", &prefs.st_client_fg);
1858
1859     prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
1860         "TCP stream window color preference", &prefs.st_client_bg);
1861
1862     prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
1863         "TCP stream window color preference", &prefs.st_server_fg);
1864
1865     prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
1866         "TCP stream window color preference", &prefs.st_server_bg);
1867
1868     custom_cbs.free_cb = colorized_frame_free_cb;
1869     custom_cbs.reset_cb = colorized_frame_reset_cb;
1870     custom_cbs.set_cb = colorized_frame_set_cb;
1871     custom_cbs.write_cb = colorized_frame_write_cb;
1872     prefs_register_string_custom_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
1873         "Filter Colorized Foreground", &custom_cbs, (const char **)&prefs.gui_colorized_fg);
1874
1875     custom_cbs.free_cb = colorized_frame_free_cb;
1876     custom_cbs.reset_cb = colorized_frame_reset_cb;
1877     custom_cbs.set_cb = colorized_frame_set_cb;
1878     custom_cbs.write_cb = colorized_frame_write_cb;
1879     prefs_register_string_custom_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
1880         "Filter Colorized Background", &custom_cbs, (const char **)&prefs.gui_colorized_bg);
1881
1882     prefs_register_enum_preference(gui_module, "console_open",
1883                        "Open a console window",
1884                        "Open a console window (WIN32 only)",
1885                        (gint*)(void*)(&prefs.gui_console_open), gui_console_open_type, FALSE);
1886
1887     prefs_register_enum_preference(gui_module, "fileopen.style",
1888                        "Where to start the File Open dialog box",
1889                        "Where to start the File Open dialog box",
1890                        &prefs.gui_fileopen_style, gui_fileopen_style, FALSE);
1891
1892     prefs_register_uint_preference(gui_module, "recent_files_count.max",
1893                                    "The max. number of items in the open recent files list",
1894                                    "The max. number of items in the open recent files list",
1895                                    10,
1896                                    &prefs.gui_recent_files_count_max);
1897
1898     prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
1899                                    "The max. number of entries in the display filter list",
1900                                    "The max. number of entries in the display filter list",
1901                                    10,
1902                                    &prefs.gui_recent_df_entries_max);
1903
1904     prefs_register_string_preference(gui_module, "fileopen.dir", "Start Directory",
1905         "Directory to start in when opening File Open dialog.", (const char**)(&prefs.gui_fileopen_dir));
1906
1907     prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
1908
1909     prefs_register_uint_preference(gui_module, "fileopen.preview",
1910                                    "The preview timeout in the File Open dialog",
1911                                    "The preview timeout in the File Open dialog",
1912                                    10,
1913                                    &prefs.gui_fileopen_preview);
1914
1915     prefs_register_bool_preference(gui_module, "ask_unsaved",
1916                                    "Ask to save unsaved capture files",
1917                                    "Ask to save unsaved capture files?",
1918                                    &prefs.gui_ask_unsaved);
1919
1920     prefs_register_bool_preference(gui_module, "find_wrap",
1921                                    "Wrap to beginning/end of file during search",
1922                                    "Wrap to beginning/end of file during search?",
1923                                    &prefs.gui_find_wrap);
1924
1925     prefs_register_bool_preference(gui_module, "use_pref_save",
1926                                    "Settings dialogs use a save button",
1927                                    "Settings dialogs use a save button?",
1928                                    &prefs.gui_use_pref_save);
1929
1930     prefs_register_bool_preference(gui_module, "geometry.save.position",
1931                                    "Save window position at exit",
1932                                    "Save window position at exit?",
1933                                    &prefs.gui_geometry_save_position);
1934
1935     prefs_register_bool_preference(gui_module, "geometry.save.size",
1936                                    "Save window size at exit",
1937                                    "Save window size at exit?",
1938                                    &prefs.gui_geometry_save_size);
1939
1940     prefs_register_bool_preference(gui_module, "geometry.save.maximized",
1941                                    "Save window maximized state at exit",
1942                                    "Save window maximized state at exit?",
1943                                    &prefs.gui_geometry_save_maximized);
1944
1945     prefs_register_bool_preference(gui_module, "macosx_style",
1946                                    "Use Mac OS X style",
1947                                    "Use Mac OS X style (Mac OS X with native GTK only)?",
1948                                    &prefs.gui_macosx_style);
1949
1950     prefs_register_obsolete_preference(gui_module, "geometry.main.x");
1951     prefs_register_obsolete_preference(gui_module, "geometry.main.y");
1952     prefs_register_obsolete_preference(gui_module, "geometry.main.width");
1953     prefs_register_obsolete_preference(gui_module, "geometry.main.height");
1954     prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
1955
1956     prefs_register_enum_preference(gui_module, "toolbar_main_style",
1957                        "Main Toolbar style",
1958                        "Main Toolbar style",
1959                        &prefs.gui_toolbar_main_style, gui_toolbar_style, FALSE);
1960
1961     prefs_register_enum_preference(gui_module, "toolbar_filter_style",
1962                        "Filter Toolbar style",
1963                        "Filter Toolbar style",
1964                        &prefs.gui_toolbar_filter_style, gui_toolbar_style, FALSE);
1965
1966     prefs_register_string_preference(gui_module, "webbrowser", "The path to the webbrowser",
1967         "The path to the webbrowser (Ex: mozilla)", (const char**)(&prefs.gui_webbrowser));
1968
1969     prefs_register_string_preference(gui_module, "window_title", "Custom window title",
1970         "Custom window title. (Appended to existing titles.)", (const char**)(&prefs.gui_window_title));
1971
1972     prefs_register_string_preference(gui_module, "start_title", "Custom start page title",
1973         "Custom start page title", (const char**)(&prefs.gui_start_title));
1974
1975     prefs_register_enum_preference(gui_module, "version_placement",
1976                        "Show version in the start page and/or main screen's title bar",
1977                        "Show version in the start page and/or main screen's title bar",
1978                        (gint*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, FALSE);
1979
1980     prefs_register_bool_preference(gui_module, "auto_scroll_on_expand",
1981                                    "Automatically scroll the recently expanded item",
1982                                    "Automatically scroll the recently expanded item",
1983                                    &prefs.gui_auto_scroll_on_expand);
1984
1985     prefs_register_uint_preference(gui_module, "auto_scroll_percentage",
1986                                    "The percentage down the view the recently expanded item should be scrolled",
1987                                    "The percentage down the view the recently expanded item should be scrolled",
1988                                    10,
1989                                    &prefs.gui_auto_scroll_percentage);
1990
1991     /* User Interface : Layout */
1992     gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
1993
1994     prefs_register_uint_preference(gui_layout_module, "layout_type",
1995                                    "Layout type",
1996                                    "Layout type (1-6)",
1997                                    10,
1998                                    (guint*)(void*)(&prefs.gui_layout_type));
1999
2000     prefs_register_enum_preference(gui_layout_module, "layout_content_1",
2001                        "Layout content of the pane 1",
2002                        "Layout content of the pane 1",
2003                        (gint*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, FALSE);
2004
2005     prefs_register_enum_preference(gui_layout_module, "layout_content_2",
2006                        "Layout content of the pane 2",
2007                        "Layout content of the pane 2",
2008                        (gint*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, FALSE);
2009
2010     prefs_register_enum_preference(gui_layout_module, "layout_content_3",
2011                        "Layout content of the pane 3",
2012                        "Layout content of the pane 3",
2013                        (gint*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, FALSE);
2014
2015     /* Console
2016      * These are preferences that can be read/written using the
2017      * preference module API.  These preferences still use their own
2018      * configuration screens for access, but this cuts down on the
2019      * preference "string compare list" in set_pref()
2020      */
2021     console_module = prefs_register_module(NULL, "console", "Console",
2022         "CONSOLE", NULL, FALSE);
2023
2024     custom_cbs.free_cb = custom_pref_no_cb;
2025     custom_cbs.reset_cb = console_log_level_reset_cb;
2026     custom_cbs.set_cb = console_log_level_set_cb;
2027     custom_cbs.write_cb = console_log_level_write_cb;
2028     prefs_register_uint_custom_preference(console_module, "log.level", "logging level",
2029         "A bitmask of glib log levels", &custom_cbs, &prefs.console_log_level);
2030
2031     /* Capture
2032      * These are preferences that can be read/written using the
2033      * preference module API.  These preferences still use their own
2034      * configuration screens for access, but this cuts down on the
2035      * preference "string compare list" in set_pref()
2036      */
2037     capture_module = prefs_register_module(NULL, "capture", "Capture",
2038         "CAPTURE", NULL, FALSE);
2039
2040     prefs_register_string_preference(capture_module, "device", "Default capture device",
2041         "Default capture device", (const char**)(&prefs.capture_device));
2042
2043     prefs_register_string_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
2044         "Interface link-layer header types (Ex: en0(1),en1(143),...)",
2045         (const char**)(&prefs.capture_devices_linktypes));
2046
2047     prefs_register_string_preference(capture_module, "devices_descr", "Interface descriptions",
2048         "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
2049         (const char**)(&prefs.capture_devices_descr));
2050
2051     prefs_register_string_preference(capture_module, "devices_hide", "Hide interface",
2052         "Hide interface? (Ex: eth0,eth3,...)", (const char**)(&prefs.capture_devices_hide));
2053
2054     prefs_register_string_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
2055         "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
2056         (const char**)(&prefs.capture_devices_monitor_mode));
2057
2058     prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
2059         "Capture in promiscuous mode?", &prefs.capture_prom_mode);
2060
2061     prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in Pcap-NG format",
2062         "Capture in Pcap-NG format?", &prefs.capture_pcap_ng);
2063
2064     prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
2065         "Update packet list in real time during capture?", &prefs.capture_real_time);
2066
2067     prefs_register_bool_preference(capture_module, "auto_scroll", "Scroll packet list during capture",
2068         "Scroll packet list during capture?", &prefs.capture_auto_scroll);
2069
2070     prefs_register_bool_preference(capture_module, "show_info", "Show capture info dialog while capturing",
2071         "Show capture info dialog while capturing?", &prefs.capture_show_info);
2072
2073     prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
2074
2075     custom_cbs.free_cb = capture_column_free_cb;
2076     custom_cbs.reset_cb = capture_column_reset_cb;
2077     custom_cbs.set_cb = capture_column_set_cb;
2078     custom_cbs.write_cb = capture_column_write_cb;
2079     prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
2080         "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
2081
2082     /* Name Resolution */
2083     nameres_module = prefs_register_module(NULL, "nameres", "Name Resolution",
2084         "Name Resolution", NULL, TRUE);
2085     addr_resolve_pref_init(nameres_module);
2086     oid_pref_init(nameres_module);
2087 #ifdef HAVE_GEOIP
2088     geoip_db_pref_init(nameres_module);
2089 #endif
2090
2091     /* Printing */
2092     printing = prefs_register_module(NULL, "print", "Printing",
2093         "Printing", NULL, TRUE);
2094
2095     prefs_register_enum_preference(printing, "format",
2096                                    "Format", "Can be one of \"text\" or \"postscript\"",
2097                                    &prefs.pr_format, print_format_vals, TRUE);
2098
2099     prefs_register_enum_preference(printing, "destination",
2100                                    "Print to", "Can be one of \"command\" or \"file\"",
2101                                    &prefs.pr_dest, print_dest_vals, TRUE);
2102
2103 #ifndef _WIN32
2104     prefs_register_string_preference(printing, "command", "Command",
2105         "Output gets piped to this command when the destination is set to \"command\"", (const char**)(&prefs.pr_cmd));
2106 #endif
2107
2108     prefs_register_filename_preference(printing, "file", "File",
2109         "This is the file that gets written to when the destination is set to \"file\"", (const char**)(&prefs.pr_file));
2110
2111
2112     /* Statistics */
2113     stats_module = prefs_register_module(NULL, "statistics", "Statistics",
2114         "Statistics", &stats_callback, TRUE);
2115
2116     prefs_register_uint_preference(stats_module, "update_interval",
2117                                    "Tap update interval in ms",
2118                                    "Determines time between tap updates",
2119                                    10,
2120                                    &prefs.tap_update_interval);
2121
2122 #ifdef HAVE_LIBPORTAUDIO
2123     prefs_register_uint_preference(stats_module, "rtp_player_max_visible",
2124                                    "Max visible channels in RTP Player",
2125                                    "Determines maximum height of RTP Player window",
2126                                    10,
2127                                    &prefs.rtp_player_max_visible);
2128 #endif
2129
2130
2131     /* Protocols */
2132     protocols_module = prefs_register_module(NULL, "protocols", "Protocols",
2133                                              "Protocols", NULL, TRUE);
2134
2135     prefs_register_bool_preference(protocols_module, "display_hidden_proto_items",
2136                                    "Display hidden protocol items",
2137                                    "Display all hidden protocol items in the packet list.",
2138                                    &prefs.display_hidden_proto_items);
2139
2140     /* Obsolete preferences
2141      * These "modules" were reorganized/renamed to correspond to their GUI
2142      * configuration screen within the preferences dialog
2143      */
2144
2145     /* taps is now part of the stats module */
2146     prefs_register_module(NULL, "taps", "TAPS", "TAPS", NULL, FALSE);
2147     /* packet_list is now part of the protocol (parent) module */
2148     prefs_register_module(NULL, "packet_list", "PACKET_LIST", "PACKET_LIST", NULL, FALSE);
2149     /* stream is now part of the gui module */
2150     prefs_register_module(NULL, "stream", "STREAM", "STREAM", NULL, FALSE);
2151
2152 }
2153
2154 /* Parse through a list of comma-separated, possibly quoted strings.
2155    Return a list of the string data. */
2156 GList *
2157 prefs_get_string_list(gchar *str)
2158 {
2159   enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
2160
2161   gint      state = PRE_STRING, i = 0, j = 0;
2162   gboolean  backslash = FALSE;
2163   guchar    cur_c;
2164   gchar    *slstr = NULL;
2165   GList    *sl = NULL;
2166
2167   /* Allocate a buffer for the first string.   */
2168   slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2169   j = 0;
2170
2171   for (;;) {
2172     cur_c = str[i];
2173     if (cur_c == '\0') {
2174       /* It's the end of the input, so it's the end of the string we
2175          were working on, and there's no more input. */
2176       if (state == IN_QUOT || backslash) {
2177         /* We were in the middle of a quoted string or backslash escape,
2178            and ran out of characters; that's an error.  */
2179         g_free(slstr);
2180         prefs_clear_string_list(sl);
2181         return NULL;
2182       }
2183       slstr[j] = '\0';
2184       sl = g_list_append(sl, slstr);
2185       break;
2186     }
2187     if (cur_c == '"' && ! backslash) {
2188       switch (state) {
2189         case PRE_STRING:
2190           /* We hadn't yet started processing a string; this starts the
2191              string, and we're now quoting.  */
2192           state = IN_QUOT;
2193           break;
2194         case IN_QUOT:
2195           /* We're in the middle of a quoted string, and we saw a quotation
2196              mark; we're no longer quoting.   */
2197           state = NOT_IN_QUOT;
2198           break;
2199         case NOT_IN_QUOT:
2200           /* We're working on a string, but haven't seen a quote; we're
2201              now quoting.  */
2202           state = IN_QUOT;
2203           break;
2204         default:
2205           break;
2206       }
2207     } else if (cur_c == '\\' && ! backslash) {
2208       /* We saw a backslash, and the previous character wasn't a
2209          backslash; escape the next character.
2210
2211          This also means we've started a new string. */
2212       backslash = TRUE;
2213       if (state == PRE_STRING)
2214         state = NOT_IN_QUOT;
2215     } else if (cur_c == ',' && state != IN_QUOT && ! backslash) {
2216       /* We saw a comma, and we're not in the middle of a quoted string
2217          and it wasn't preceded by a backslash; it's the end of
2218          the string we were working on...  */
2219       slstr[j] = '\0';
2220       sl = g_list_append(sl, slstr);
2221
2222       /* ...and the beginning of a new string.  */
2223       state = PRE_STRING;
2224       slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2225       j = 0;
2226     } else if (!isspace(cur_c) || state != PRE_STRING) {
2227       /* Either this isn't a white-space character, or we've started a
2228          string (i.e., already seen a non-white-space character for that
2229          string and put it into the string).
2230
2231          The character is to be put into the string; do so if there's
2232          room.  */
2233       if (j < COL_MAX_LEN) {
2234         slstr[j] = cur_c;
2235         j++;
2236       }
2237
2238       /* If it was backslash-escaped, we're done with the backslash escape.  */
2239       backslash = FALSE;
2240     }
2241     i++;
2242   }
2243   return(sl);
2244 }
2245
2246 static void
2247 write_string_list(FILE *f, GList *sl, gboolean is_default)
2248 {
2249   char          pref_str[8];
2250   GList        *clp = g_list_first(sl);
2251   gchar        *str;
2252   int           cur_len = 0;
2253   gchar        *quoted_str;
2254   size_t        str_len;
2255   gchar        *strp, *quoted_strp, c;
2256   guint         item_count = 0;
2257   gboolean      first = TRUE;
2258
2259   while (clp) {
2260     item_count++;
2261     str = clp->data;
2262
2263     /* Allocate a buffer big enough to hold the entire string, with each
2264        character quoted (that's the worst case).  */
2265     str_len = strlen(str);
2266     quoted_str = g_malloc(str_len*2 + 1);
2267
2268     /* Now quote any " or \ characters in it. */
2269     strp = str;
2270     quoted_strp = quoted_str;
2271     while ((c = *strp++) != '\0') {
2272       if (c == '"' || c == '\\') {
2273         /* It has to be backslash-quoted.  */
2274         *quoted_strp++ = '\\';
2275       }
2276       *quoted_strp++ = c;
2277     }
2278     *quoted_strp = '\0';
2279
2280     {
2281       cur_len = 0;
2282       if (!first) {
2283         pref_str[cur_len] = ','; cur_len++;
2284       }
2285
2286       if (item_count % 2) {
2287         /* Wrap the line.  */
2288         pref_str[cur_len] = '\n'; cur_len++;
2289         if (is_default) {
2290           pref_str[cur_len] = '#'; cur_len++;
2291         }
2292         pref_str[cur_len] = '\t'; cur_len++;
2293       } else {
2294         pref_str[cur_len] = ' '; cur_len++;
2295       }
2296       pref_str[cur_len] = '\0';
2297       fprintf(f, "%s\"%s\"", pref_str, quoted_str);
2298       first = FALSE;
2299     }
2300     g_free(quoted_str);
2301     g_free(str);
2302     clp = clp->next;
2303   }
2304 }
2305
2306 void
2307 prefs_clear_string_list(GList *sl)
2308 {
2309   GList *l = sl;
2310
2311   while (l) {
2312     g_free(l->data);
2313     l = g_list_remove_link(l, l);
2314   }
2315 }
2316
2317 /*
2318  * Takes a string, a pointer to an array of "enum_val_t"s, and a default gint
2319  * value.
2320  * The array must be terminated by an entry with a null "name" string.
2321  *
2322  * If the string matches a "name" string in an entry, the value from that
2323  * entry is returned.
2324  *
2325  * Otherwise, if a string matches a "desctiption" string in an entry, the
2326  * value from that entry is returned; we do that for backwards compatibility,
2327  * as we used to have only a "name" string that was used both for command-line
2328  * and configuration-file values and in the GUI (which meant either that
2329  * the GUI had what might be somewhat cryptic values to select from or that
2330  * the "-o" flag took long strings, often with spaces in them).
2331  *
2332  * Otherwise, the default value that was passed as the third argument is
2333  * returned.
2334  */
2335 static gint
2336 find_val_for_string(const char *needle, const enum_val_t *haystack,
2337                     gint default_value)
2338 {
2339     int i;
2340
2341     for (i = 0; haystack[i].name != NULL; i++) {
2342         if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
2343             return haystack[i].value;
2344         }
2345     }
2346     for (i = 0; haystack[i].name != NULL; i++) {
2347         if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
2348             return haystack[i].value;
2349         }
2350     }
2351     return default_value;
2352 }
2353
2354 /* Preferences file format:
2355  * - Configuration directives start at the beginning of the line, and
2356  *   are terminated with a colon.
2357  * - Directives can be continued on the next line by preceding them with
2358  *   whitespace.
2359  *
2360  * Example:
2361
2362 # This is a comment line
2363 print.command: lpr
2364 print.file: /a/very/long/path/
2365             to/wireshark-out.ps
2366  *
2367  */
2368
2369 #define DEF_NUM_COLS    7
2370
2371 /*
2372  * Parse a column format, filling in the relevant fields of a fmt_data.
2373  */
2374 static gboolean
2375 parse_column_format(fmt_data *cfmt, const char *fmt)
2376 {
2377   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
2378   size_t cust_format_len = strlen(cust_format);
2379   gchar **cust_format_info;
2380   char *p;
2381   int col_fmt;
2382   gchar *col_custom_field;
2383   long col_custom_occurrence;
2384   gboolean col_resolved;
2385
2386   /*
2387    * Is this a custom column?
2388    */
2389   if ((strlen(fmt) > cust_format_len) && (fmt[cust_format_len] == ':') &&
2390       strncmp(fmt, cust_format, cust_format_len) == 0) {
2391     /* Yes. */
2392     col_fmt = COL_CUSTOM;
2393     cust_format_info = g_strsplit(&fmt[cust_format_len+1],":",3); /* add 1 for ':' */
2394     col_custom_field = g_strdup(cust_format_info[0]);
2395     if (col_custom_field && cust_format_info[1]) {
2396       col_custom_occurrence = strtol(cust_format_info[1], &p, 10);
2397       if (p == cust_format_info[1] || *p != '\0') {
2398         /* Not a valid number. */
2399         g_free(col_custom_field);
2400         g_strfreev(cust_format_info);
2401         return FALSE;
2402       }
2403     } else {
2404       col_custom_occurrence = 0;
2405     }
2406     if (col_custom_field && cust_format_info[1] && cust_format_info[2]) {
2407       col_resolved = (cust_format_info[2][0] == 'U') ? FALSE : TRUE;
2408     } else {
2409       col_resolved = TRUE;
2410     }
2411     g_strfreev(cust_format_info);
2412   } else {
2413     col_fmt = get_column_format_from_str(fmt);
2414     if (col_fmt == -1)
2415       return FALSE;
2416     col_custom_field = NULL;
2417     col_custom_occurrence = 0;
2418     col_resolved = TRUE;
2419   }
2420
2421   cfmt->fmt = col_fmt;
2422   cfmt->custom_field = col_custom_field;
2423   cfmt->custom_occurrence = (int)col_custom_occurrence;
2424   cfmt->resolved = col_resolved;
2425   return TRUE;
2426 }
2427
2428 /* Initialize non-dissector preferences to wired-in default values.
2429  * (The dissector preferences are assumed to be set to those values
2430  * by the dissectors.)
2431  * They may be overridden by the global preferences file or the
2432  *  user's preferences file.
2433  */
2434 static void
2435 init_prefs(void)
2436 {
2437   if (prefs_initialized)
2438     return;
2439
2440   uat_load_all();
2441
2442   pre_init_prefs();
2443
2444   filter_expression_init(TRUE);
2445
2446   prefs_initialized = TRUE;
2447 }
2448
2449 /* Initialize non-dissector preferences used by the "register preference" API
2450  * to default values so the default values can be used when registered
2451  */
2452 static void
2453 pre_init_prefs(void)
2454 {
2455   int         i;
2456   gchar       *col_name;
2457   fmt_data    *cfmt;
2458   static const gchar *col_fmt[DEF_NUM_COLS*2] = {
2459                             "No.",      "%m", "Time",        "%t",
2460                             "Source",   "%s", "Destination", "%d",
2461                             "Protocol", "%p", "Length",      "%L",
2462                             "Info",     "%i"};
2463 #if defined(HAVE_PCAP_CREATE)
2464   static gint num_capture_cols = 7;
2465   static const gchar *capture_cols[7] = {
2466                                 "INTERFACE",
2467                                 "LINK",
2468                                 "PMODE",
2469                                 "SNAPLEN",
2470                                 "MONITOR",
2471                                 "BUFFER",
2472                                 "FILTER"};
2473 #elif defined(_WIN32) && !defined (HAVE_PCAP_CREATE)
2474   static gint num_capture_cols = 6;
2475   static const gchar *capture_cols[6] = {
2476                                 "INTERFACE",
2477                                 "LINK",
2478                                 "PMODE",
2479                                 "SNAPLEN",
2480                                 "BUFFER",
2481                                 "FILTER"};
2482 #else
2483   static gint num_capture_cols = 5;
2484   static const gchar *capture_cols[5] = {
2485                                 "INTERFACE",
2486                                 "LINK",
2487                                 "PMODE",
2488                                 "SNAPLEN",
2489                                 "FILTER"};
2490 #endif
2491
2492   if (prefs_pre_initialized)
2493      return;
2494
2495   prefs.pr_format  = PR_FMT_TEXT;
2496   prefs.pr_dest    = PR_DEST_CMD;
2497   prefs.pr_file    = g_strdup("wireshark.out");
2498   prefs.pr_cmd     = g_strdup("lpr");
2499
2500   prefs.gui_scrollbar_on_right = TRUE;
2501   prefs.gui_plist_sel_browse = FALSE;
2502   prefs.gui_ptree_sel_browse = FALSE;
2503   prefs.gui_altern_colors = FALSE;
2504   prefs.gui_expert_composite_eyecandy = FALSE;
2505   prefs.gui_ptree_line_style = 0;
2506   prefs.gui_ptree_expander_style = 1;
2507   prefs.gui_hex_dump_highlight_style = 1;
2508   prefs.filter_toolbar_show_in_statusbar = FALSE;
2509   prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
2510   prefs.gui_toolbar_filter_style = TB_STYLE_TEXT;
2511 #ifdef _WIN32
2512   prefs.gui_font_name = g_strdup("Lucida Console 10");
2513 #else
2514   /*
2515    * XXX - for now, we make the initial font name a pattern that matches
2516    * only ISO 8859/1 fonts, so that we don't match 2-byte fonts such
2517    * as ISO 10646 fonts.
2518    *
2519    * Users in locales using other one-byte fonts will have to choose
2520    * a different font from the preferences dialog - or put the font
2521    * selection in the global preferences file to make that font the
2522    * default for all users who don't explicitly specify a different
2523    * font.
2524    *
2525    * Making this a font set rather than a font has two problems:
2526    *
2527    *    1) as far as I know, you can't select font sets with the
2528    *       font selection dialog;
2529    *
2530    *  2) if you use a font set, the text to be drawn must be a
2531    *       multi-byte string in the appropriate locale, but
2532    *       Wireshark does *NOT* guarantee that's the case - in
2533    *       the hex-dump window, each character in the text portion
2534    *       of the display must be a *single* byte, and in the
2535    *       packet-list and protocol-tree windows, text extracted
2536    *       from the packet is not necessarily in the right format.
2537    *
2538    * "Doing this right" may, for the packet-list and protocol-tree
2539    * windows, require that dissectors know what the locale is
2540    * *AND* know what locale and text representation is used in
2541    * the packets they're dissecting, and may be impossible in
2542    * the hex-dump window (except by punting and displaying only
2543    * ASCII characters).
2544    *
2545    * GTK+ 2.0 may simplify part of the problem, as it will, as I
2546    * understand it, use UTF-8-encoded Unicode as its internal
2547    * character set; however, we'd still have to know whatever
2548    * character set and encoding is used in the packet (which
2549    * may differ for different protocols, e.g. SMB might use
2550    * PC code pages for some strings and Unicode for others, whilst
2551    * NFS might use some UNIX character set encoding, e.g. ISO 8859/x,
2552    * or one of the EUC character sets for Asian languages, or one
2553    * of the other multi-byte character sets, or UTF-8, or...).
2554    *
2555    * I.e., as far as I can tell, "internationalizing" the packet-list,
2556    * protocol-tree, and hex-dump windows involves a lot more than, say,
2557    * just using font sets rather than fonts.
2558    */
2559   /* XXX - the above comment was about the GTK1 font stuff, just remove this comment now */
2560   /* XXX- is this the correct default font name for GTK2 none win32? */
2561   prefs.gui_font_name = g_strdup("Monospace 10");
2562 #endif
2563   prefs.gui_marked_fg.pixel        =     65535;
2564   prefs.gui_marked_fg.red          =     65535;
2565   prefs.gui_marked_fg.green        =     65535;
2566   prefs.gui_marked_fg.blue         =     65535;
2567   prefs.gui_marked_bg.pixel        =         0;
2568   prefs.gui_marked_bg.red          =         0;
2569   prefs.gui_marked_bg.green        =         0;
2570   prefs.gui_marked_bg.blue         =         0;
2571   prefs.gui_ignored_fg.pixel       =     32767;
2572   prefs.gui_ignored_fg.red         =     32767;
2573   prefs.gui_ignored_fg.green       =     32767;
2574   prefs.gui_ignored_fg.blue        =     32767;
2575   prefs.gui_ignored_bg.pixel       =     65535;
2576   prefs.gui_ignored_bg.red         =     65535;
2577   prefs.gui_ignored_bg.green       =     65535;
2578   prefs.gui_ignored_bg.blue        =     65535;
2579   prefs.gui_colorized_fg           = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
2580   prefs.gui_colorized_bg           = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
2581   prefs.st_client_fg.pixel         =     0;
2582   prefs.st_client_fg.red           = 32767;
2583   prefs.st_client_fg.green         =     0;
2584   prefs.st_client_fg.blue          =     0;
2585   prefs.st_client_bg.pixel         =     0;
2586   prefs.st_client_bg.red           = 64507;
2587   prefs.st_client_bg.green         = 60909;
2588   prefs.st_client_bg.blue          = 60909;
2589   prefs.st_server_fg.pixel         =     0;
2590   prefs.st_server_fg.red           =     0;
2591   prefs.st_server_fg.green         =     0;
2592   prefs.st_server_fg.blue          = 32767;
2593   prefs.st_server_bg.pixel         =     0;
2594   prefs.st_server_bg.red           = 60909;
2595   prefs.st_server_bg.green         = 60909;
2596   prefs.st_server_bg.blue          = 64507;
2597   prefs.gui_geometry_save_position = FALSE;
2598   prefs.gui_geometry_save_size     = TRUE;
2599   prefs.gui_geometry_save_maximized= TRUE;
2600   prefs.gui_macosx_style           = TRUE;
2601   prefs.gui_console_open           = console_open_never;
2602   prefs.gui_fileopen_style         = FO_STYLE_LAST_OPENED;
2603   prefs.gui_recent_df_entries_max  = 10;
2604   prefs.gui_recent_files_count_max = 10;
2605   prefs.gui_fileopen_dir           = g_strdup(get_persdatafile_dir());
2606   prefs.gui_fileopen_preview       = 3;
2607   prefs.gui_ask_unsaved            = TRUE;
2608   prefs.gui_find_wrap              = TRUE;
2609   prefs.gui_use_pref_save          = FALSE;
2610   prefs.gui_webbrowser             = g_strdup(HTML_VIEWER " %s");
2611   prefs.gui_window_title           = g_strdup("");
2612   prefs.gui_start_title            = g_strdup("The World's Most Popular Network Protocol Analyzer");
2613   prefs.gui_version_placement      = version_both;
2614   prefs.gui_auto_scroll_on_expand  = FALSE;
2615   prefs.gui_auto_scroll_percentage = 0;
2616   prefs.gui_layout_type            = layout_type_5;
2617   prefs.gui_layout_content_1       = layout_pane_content_plist;
2618   prefs.gui_layout_content_2       = layout_pane_content_pdetails;
2619   prefs.gui_layout_content_3       = layout_pane_content_pbytes;
2620
2621   prefs.col_list = NULL;
2622   for (i = 0; i < DEF_NUM_COLS; i++) {
2623     cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
2624     cfmt->title = g_strdup(col_fmt[i * 2]);
2625     parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
2626     cfmt->visible = TRUE;
2627     cfmt->resolved = TRUE;
2628     cfmt->custom_field = NULL;
2629     cfmt->custom_occurrence = 0;
2630     prefs.col_list = g_list_append(prefs.col_list, cfmt);
2631   }
2632   prefs.num_cols  = DEF_NUM_COLS;
2633
2634 /* set the default values for the capture dialog box */
2635   prefs.capture_prom_mode             = TRUE;
2636 #ifdef PCAP_NG_DEFAULT
2637   prefs.capture_pcap_ng               = TRUE;
2638 #else
2639   prefs.capture_pcap_ng               = FALSE;
2640 #endif
2641   prefs.capture_real_time             = TRUE;
2642   prefs.capture_auto_scroll           = TRUE;
2643   prefs.capture_show_info             = FALSE;
2644
2645   prefs.capture_columns               = NULL;
2646   for (i = 0; i < num_capture_cols; i++) {
2647     col_name = g_strdup(capture_cols[i]);
2648     prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2649   }
2650
2651   prefs.console_log_level          =
2652       G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
2653
2654 /* set the default values for the tap/statistics dialog box */
2655   prefs.tap_update_interval    = TAP_UPDATE_DEFAULT_INTERVAL;
2656   prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
2657
2658   prefs.display_hidden_proto_items = FALSE;
2659
2660   prefs_pre_initialized = TRUE;
2661 }
2662
2663 /*
2664  * Reset a single dissector preference.
2665  */
2666 static void
2667 reset_pref(gpointer data, gpointer user_data _U_)
2668 {
2669     pref_t *pref = data;
2670
2671     switch (pref->type) {
2672
2673     case PREF_UINT:
2674         *pref->varp.uint = pref->default_val.uint;
2675         break;
2676
2677     case PREF_BOOL:
2678         *pref->varp.boolp = pref->default_val.boolval;
2679         break;
2680
2681     case PREF_ENUM:
2682         /*
2683          * For now, we save the "description" value, so that if we
2684          * save the preferences older versions of Wireshark can at
2685          * least read preferences that they supported; we support
2686          * either the short name or the description when reading
2687          * the preferences file or a "-o" option.
2688          */
2689         *pref->varp.enump = pref->default_val.enumval;
2690         break;
2691
2692     case PREF_STRING:
2693     case PREF_FILENAME:
2694         g_free((void *)*pref->varp.string);
2695         *pref->varp.string = g_strdup(pref->default_val.string);
2696         break;
2697
2698     case PREF_RANGE:
2699         g_free(*pref->varp.range);
2700         *pref->varp.range = range_copy(pref->default_val.range);
2701         break;
2702
2703     case PREF_STATIC_TEXT:
2704     case PREF_UAT:
2705         /* Nothing to do */
2706         break;
2707
2708     case PREF_COLOR:
2709         *pref->varp.color = pref->default_val.color;
2710         break;
2711
2712     case PREF_CUSTOM:
2713         pref->custom_cbs.reset_cb(pref);
2714         break;
2715
2716     case PREF_OBSOLETE:
2717         /*
2718          * This preference is no longer supported; it's not a
2719          * real preference, so we don't reset it (i.e., we
2720          * treat it as if it weren't found in the list of
2721          * preferences, and we weren't called in the first place).
2722          */
2723         break;
2724     }
2725 }
2726
2727 typedef struct {
2728     module_t *module;
2729 } reset_pref_arg_t;
2730
2731 /*
2732  * Reset all preferences for a module.
2733  */
2734 static gboolean
2735 reset_module_prefs(void *value, void *data _U_)
2736 {
2737     reset_pref_arg_t arg;
2738
2739     arg.module = value;
2740     g_list_foreach(arg.module->prefs, reset_pref, &arg);
2741     return FALSE;
2742 }
2743
2744 /* Reset preferences */
2745 void
2746 prefs_reset(void)
2747 {
2748   prefs_initialized = FALSE;
2749
2750   /*
2751    * Unload all UAT preferences.
2752    */
2753   uat_unload_all();
2754
2755   /*
2756    * Unload any loaded MIBs.
2757    */
2758   oids_cleanup();
2759
2760   /*
2761    * Reset the non-dissector preferences.
2762    */
2763   init_prefs();
2764
2765   /*
2766    * Reset the non-UAT dissector preferences.
2767    */
2768   pe_tree_foreach(prefs_modules, reset_module_prefs, NULL);
2769 }
2770
2771 /* Read the preferences file, fill in "prefs", and return a pointer to it.
2772
2773    If we got an error (other than "it doesn't exist") trying to read
2774    the global preferences file, stuff the errno into "*gpf_errno_return"
2775    and a pointer to the path of the file into "*gpf_path_return", and
2776    return NULL.
2777
2778    If we got an error (other than "it doesn't exist") trying to read
2779    the user's preferences file, stuff the errno into "*pf_errno_return"
2780    and a pointer to the path of the file into "*pf_path_return", and
2781    return NULL. */
2782 e_prefs *
2783 read_prefs(int *gpf_errno_return, int *gpf_read_errno_return,
2784            char **gpf_path_return, int *pf_errno_return,
2785            int *pf_read_errno_return, char **pf_path_return)
2786 {
2787   int         err;
2788   char        *pf_path;
2789   FILE        *pf;
2790
2791   /* clean up libsmi structures before reading prefs */
2792   oids_cleanup();
2793
2794   init_prefs();
2795
2796   /*
2797    * If we don't already have the pathname of the global preferences
2798    * file, construct it.  Then, in either case, try to open the file.
2799    */
2800   if (gpf_path == NULL) {
2801     /*
2802      * We don't have the path; try the new path first, and, if that
2803      * file doesn't exist, try the old path.
2804      */
2805     gpf_path = get_datafile_path(PF_NAME);
2806     if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
2807       /*
2808        * It doesn't exist by the new name; try the old name.
2809        */
2810       g_free(gpf_path);
2811       gpf_path = get_datafile_path(OLD_GPF_NAME);
2812       pf = ws_fopen(gpf_path, "r");
2813     }
2814   } else {
2815     /*
2816      * We have the path; try it.
2817      */
2818     pf = ws_fopen(gpf_path, "r");
2819   }
2820
2821   /*
2822    * If we were able to open the file, read it.
2823    * XXX - if it failed for a reason other than "it doesn't exist",
2824    * report the error.
2825    */
2826   *gpf_path_return = NULL;
2827   if (pf != NULL) {
2828     /*
2829      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
2830      * seen.
2831      */
2832     mgcp_tcp_port_count = 0;
2833     mgcp_udp_port_count = 0;
2834
2835     /* We succeeded in opening it; read it. */
2836     err = read_prefs_file(gpf_path, pf, set_pref, NULL);
2837     if (err != 0) {
2838       /* We had an error reading the file; return the errno and the
2839          pathname, so our caller can report the error. */
2840       *gpf_errno_return = 0;
2841       *gpf_read_errno_return = err;
2842       *gpf_path_return = gpf_path;
2843     }
2844     fclose(pf);
2845   } else {
2846     /* We failed to open it.  If we failed for some reason other than
2847        "it doesn't exist", return the errno and the pathname, so our
2848        caller can report the error. */
2849     if (errno != ENOENT) {
2850       *gpf_errno_return = errno;
2851       *gpf_read_errno_return = 0;
2852       *gpf_path_return = gpf_path;
2853     }
2854   }
2855
2856   /* Construct the pathname of the user's preferences file. */
2857   pf_path = get_persconffile_path(PF_NAME, TRUE, FALSE);
2858
2859   /* Read the user's preferences file, if it exists. */
2860   *pf_path_return = NULL;
2861   if ((pf = ws_fopen(pf_path, "r")) != NULL) {
2862     /*
2863      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
2864      * seen.
2865      */
2866     mgcp_tcp_port_count = 0;
2867     mgcp_udp_port_count = 0;
2868
2869     /* We succeeded in opening it; read it. */
2870     err = read_prefs_file(pf_path, pf, set_pref, NULL);
2871     if (err != 0) {
2872       /* We had an error reading the file; return the errno and the
2873          pathname, so our caller can report the error. */
2874       *pf_errno_return = 0;
2875       *pf_read_errno_return = err;
2876       *pf_path_return = pf_path;
2877     } else
2878       g_free(pf_path);
2879     fclose(pf);
2880   } else {
2881     /* We failed to open it.  If we failed for some reason other than
2882        "it doesn't exist", return the errno and the pathname, so our
2883        caller can report the error. */
2884     if (errno != ENOENT) {
2885       *pf_errno_return = errno;
2886       *pf_read_errno_return = 0;
2887       *pf_path_return = pf_path;
2888     } else
2889       g_free(pf_path);
2890   }
2891
2892   /* load SMI modules if needed */
2893   oids_init();
2894
2895   return &prefs;
2896 }
2897
2898 /* read the preferences file (or similiar) and call the callback
2899  * function to set each key/value pair found */
2900 int
2901 read_prefs_file(const char *pf_path, FILE *pf,
2902                 pref_set_pair_cb pref_set_pair_fct, void *private_data)
2903 {
2904   enum { START, IN_VAR, PRE_VAL, IN_VAL, IN_SKIP };
2905   int       got_c, state = START;
2906   GString  *cur_val;
2907   GString  *cur_var;
2908   gboolean  got_val = FALSE;
2909   gint      fline = 1, pline = 1;
2910   gchar     hint[] = "(applying your preferences once should remove this warning)";
2911
2912   cur_val = g_string_new("");
2913   cur_var = g_string_new("");
2914
2915   while ((got_c = getc(pf)) != EOF) {
2916     if (got_c == '\n') {
2917       state = START;
2918       fline++;
2919       continue;
2920     }
2921
2922     switch (state) {
2923       case START:
2924         if (isalnum(got_c)) {
2925           if (cur_var->len > 0) {
2926             if (got_val) {
2927               /*  Convert the string to a range.  Since we're reading the
2928                *  preferences file, silently lower values in excess of the
2929                *  range's maximum.
2930                */
2931               switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
2932
2933               case PREFS_SET_OK:
2934                 break;
2935
2936               case PREFS_SET_SYNTAX_ERR:
2937                 g_warning ("%s line %d: Syntax error in preference %s %s", pf_path, pline, cur_var->str, hint);
2938                 break;
2939
2940               case PREFS_SET_NO_SUCH_PREF:
2941                 g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
2942                                 pline, cur_var->str, hint);
2943                 break;
2944
2945               case PREFS_SET_OBSOLETE:
2946                 /* We silently ignore attempts to set these; it's
2947                    probably not the user's fault that it's in there -
2948                    they may have saved preferences with a release that
2949                    supported them. */
2950                 break;
2951               }
2952             } else {
2953               g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
2954             }
2955           }
2956           state      = IN_VAR;
2957           got_val    = FALSE;
2958           g_string_truncate(cur_var, 0);
2959           g_string_append_c(cur_var, (gchar) got_c);
2960           pline = fline;
2961         } else if (isspace(got_c) && cur_var->len > 0 && got_val) {
2962           state = PRE_VAL;
2963         } else if (got_c == '#') {
2964           state = IN_SKIP;
2965         } else {
2966           g_warning ("%s line %d: Malformed line %s", pf_path, fline, hint);
2967         }
2968         break;
2969       case IN_VAR:
2970         if (got_c != ':') {
2971           g_string_append_c(cur_var, (gchar) got_c);
2972         } else {
2973           state   = PRE_VAL;
2974           g_string_truncate(cur_val, 0);
2975           got_val = TRUE;
2976         }
2977         break;
2978       case PRE_VAL:
2979         if (!isspace(got_c)) {
2980           state = IN_VAL;
2981           g_string_append_c(cur_val, (gchar) got_c);
2982         }
2983         break;
2984       case IN_VAL:
2985         g_string_append_c(cur_val, (gchar) got_c);
2986         break;
2987     }
2988   }
2989   if (cur_var->len > 0) {
2990     if (got_val) {
2991       /*  Convert the string to a range.  Since we're reading the
2992        *  preferences file, silently lower values in excess of the
2993        *  range's maximum.
2994        */
2995       switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
2996
2997       case PREFS_SET_OK:
2998         break;
2999
3000       case PREFS_SET_SYNTAX_ERR:
3001         g_warning ("%s line %d: Syntax error in preference %s %s", pf_path, pline, cur_var->str, hint);
3002         break;
3003
3004       case PREFS_SET_NO_SUCH_PREF:
3005         g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
3006                         pline, cur_var->str, hint);
3007         break;
3008
3009       case PREFS_SET_OBSOLETE:
3010         /* We silently ignore attempts to set these; it's probably not
3011            the user's fault that it's in there - they may have saved
3012            preferences with a release that supported it. */
3013         break;
3014       }
3015     } else {
3016       g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
3017     }
3018   }
3019
3020   g_string_free(cur_val, TRUE);
3021   g_string_free(cur_var, TRUE);
3022
3023   if (ferror(pf))
3024     return errno;
3025   else
3026     return 0;
3027 }
3028
3029 /*
3030  * If we were handed a preference starting with "uat:", try to turn it into
3031  * a valid uat entry.
3032  */
3033 static gboolean
3034 prefs_set_uat_pref(char *uat_entry) {
3035     gchar *p, *colonp;
3036     uat_t *uat;
3037     gchar *err;
3038
3039     colonp = strchr(uat_entry, ':');
3040     if (colonp == NULL)
3041         return FALSE;
3042
3043     p = colonp;
3044     *p++ = '\0';
3045
3046     /*
3047      * Skip over any white space (there probably won't be any, but
3048      * as we allow it in the preferences file, we might as well
3049      * allow it here).
3050      */
3051     while (isspace((guchar)*p))
3052         p++;
3053     if (*p == '\0') {
3054         /*
3055          * Put the colon back, so if our caller uses, in an
3056          * error message, the string they passed us, the message
3057          * looks correct.
3058          */
3059         *colonp = ':';
3060         return FALSE;
3061     }
3062
3063     uat = uat_find(uat_entry);
3064     *colonp = ':';
3065     if (uat == NULL) {
3066         return FALSE;
3067     }
3068
3069     if (uat_load_str(uat, p, &err)) {
3070         return TRUE;
3071     }
3072     return FALSE;
3073 }
3074
3075 /*
3076  * Given a string of the form "<pref name>:<pref value>", as might appear
3077  * as an argument to a "-o" option, parse it and set the preference in
3078  * question.  Return an indication of whether it succeeded or failed
3079  * in some fashion.
3080  */
3081 prefs_set_pref_e
3082 prefs_set_pref(char *prefarg)
3083 {
3084     gchar *p, *colonp;
3085     prefs_set_pref_e ret;
3086
3087     /*
3088      * Set the counters of "mgcp.{tcp,udp}.port" entries we've
3089      * seen to values that keep us from trying to interpret tham
3090      * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
3091      * as, from the command line, we have no way of guessing which
3092      * the user had in mind.
3093      */
3094     mgcp_tcp_port_count = -1;
3095     mgcp_udp_port_count = -1;
3096
3097     colonp = strchr(prefarg, ':');
3098     if (colonp == NULL)
3099         return PREFS_SET_SYNTAX_ERR;
3100
3101     p = colonp;
3102     *p++ = '\0';
3103
3104     /*
3105      * Skip over any white space (there probably won't be any, but
3106      * as we allow it in the preferences file, we might as well
3107      * allow it here).
3108      */
3109     while (isspace((guchar)*p))
3110         p++;
3111     if (*p == '\0') {
3112         /*
3113          * Put the colon back, so if our caller uses, in an
3114          * error message, the string they passed us, the message
3115          * looks correct.
3116          */
3117         *colonp = ':';
3118         return PREFS_SET_SYNTAX_ERR;
3119     }
3120     if (strcmp(prefarg, "uat")) {
3121         ret = set_pref(prefarg, p, NULL, TRUE);
3122     } else {
3123         ret = prefs_set_uat_pref(p) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
3124     }
3125     *colonp = ':';    /* put the colon back */
3126     return ret;
3127 }
3128
3129 /*
3130  * Returns TRUE if the given device is hidden
3131  */
3132 gboolean
3133 prefs_is_capture_device_hidden(const char *name)
3134 {
3135     gchar *tok, *devices;
3136     size_t len;
3137
3138     if (prefs.capture_devices_hide && name) {
3139         devices = g_strdup (prefs.capture_devices_hide);
3140         len = strlen (name);
3141         for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
3142             if (strlen (tok) == len && strcmp (name, tok) == 0) {
3143                 g_free (devices);
3144                 return TRUE;
3145             }
3146         }
3147         g_free (devices);
3148     }
3149
3150     return FALSE;
3151 }
3152
3153 /*
3154  * Returns TRUE if the given column is visible (not hidden)
3155  */
3156 static gboolean
3157 prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt)
3158 {
3159     gchar *tok, *cols;
3160     fmt_data cfmt_hidden;
3161
3162     /*
3163      * Do we have a list of hidden columns?
3164      */
3165     if (cols_hidden) {
3166         /*
3167          * Yes - check the column against each of the ones in the
3168          * list.
3169          */
3170         cols = g_strdup(cols_hidden);
3171         for (tok = strtok(cols, ","); tok; tok = strtok(NULL, ",")) {
3172             tok = g_strstrip(tok);
3173
3174             /*
3175              * Parse this column format.
3176              */
3177             if (!parse_column_format(&cfmt_hidden, tok)) {
3178                 /*
3179                  * It's not valid; ignore it.
3180                  */
3181                 continue;
3182             }
3183
3184             /*
3185              * Does it match the column?
3186              */
3187             if (cfmt->fmt != cfmt_hidden.fmt) {
3188                 /* No. */
3189                 g_free(cfmt_hidden.custom_field);
3190                 continue;
3191             }
3192             if (cfmt->fmt == COL_CUSTOM) {
3193                 /*
3194                  * A custom column has to have the
3195                  * same custom field and occurrence.
3196                  */
3197                 if (strcmp(cfmt->custom_field,
3198                            cfmt_hidden.custom_field) != 0) {
3199                     /* Different fields. */
3200                     g_free(cfmt_hidden.custom_field);
3201                     continue;
3202                 }
3203                 if (cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) {
3204                     /* Different occurrences. */
3205                     g_free(cfmt_hidden.custom_field);
3206                     continue;
3207                 }
3208             }
3209
3210             /*
3211              * OK, they match, so it's one of the hidden fields,
3212              * hence not visible.
3213              */
3214             g_free(cfmt_hidden.custom_field);
3215             g_free(cols);
3216             return FALSE;
3217         }
3218         g_free(cols);
3219     }
3220
3221     /*
3222      * No - either there are no hidden columns or this isn't one
3223      * of them - so it is visible.
3224      */
3225     return TRUE;
3226 }
3227
3228 /*
3229  * Returns TRUE if the given device should capture in monitor mode by default
3230  */
3231 gboolean
3232 prefs_capture_device_monitor_mode(const char *name)
3233 {
3234     gchar *tok, *devices;
3235     size_t len;
3236
3237     if (prefs.capture_devices_monitor_mode && name) {
3238         devices = g_strdup (prefs.capture_devices_monitor_mode);
3239         len = strlen (name);
3240         for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
3241             if (strlen (tok) == len && strcmp (name, tok) == 0) {
3242                 g_free (devices);
3243                 return TRUE;
3244             }
3245         }
3246         g_free (devices);
3247     }
3248
3249     return FALSE;
3250 }
3251
3252 /*
3253  * Returns TRUE if the user has marked this column as visible
3254  */
3255 gboolean
3256 prefs_capture_options_dialog_column_is_visible(const gchar *column)
3257 {
3258     GList *curr;
3259     gchar *col;
3260
3261     for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)) {
3262         col = (gchar *)curr->data;
3263         if (col && (g_ascii_strcasecmp(col, column) == 0)) {
3264             return TRUE;
3265         }
3266     }
3267     return FALSE;
3268 }
3269
3270 #define PRS_GUI_FILTER_LABEL             "gui.filter_expressions.label"
3271 #define PRS_GUI_FILTER_EXPR              "gui.filter_expressions.expr"
3272 #define PRS_GUI_FILTER_ENABLED           "gui.filter_expressions.enabled"
3273
3274 #define RED_COMPONENT(x)   (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
3275 #define GREEN_COMPONENT(x) (guint16) (((((x) >>  8) & 0xff) * 65535 / 255))
3276 #define BLUE_COMPONENT(x)  (guint16) ( (((x)        & 0xff) * 65535 / 255))
3277
3278 char
3279 string_to_name_resolve(char *string, e_addr_resolve *name_resolve)
3280 {
3281   char c;
3282
3283   memset(name_resolve, 0, sizeof(e_addr_resolve));
3284   while ((c = *string++) != '\0') {
3285       switch (c) {
3286       case 'm':
3287           name_resolve->mac_name = TRUE;
3288           break;
3289       case 'n':
3290           name_resolve->network_name = TRUE;
3291           break;
3292       case 'N':
3293           name_resolve->use_external_net_name_resolver = TRUE;
3294           break;
3295       case 't':
3296           name_resolve->transport_name = TRUE;
3297           break;
3298       case 'C':
3299           name_resolve->concurrent_dns = TRUE;
3300           break;
3301       default:
3302           /*
3303            * Unrecognized letter.
3304            */
3305           return c;
3306       }
3307   }
3308   return '\0';
3309 }
3310
3311
3312 static void
3313 try_convert_to_custom_column(gpointer *el_data)
3314 {
3315     /* Array of columns that have been migrated to custom columns */
3316     struct {
3317         gint el;
3318         gchar *col_expr;
3319     } migrated_columns[] = {
3320         { COL_COS_VALUE, "vlan.priority" },
3321         { COL_CIRCUIT_ID, "iax2.call" },
3322         { COL_BSSGP_TLLI, "bssgp.tlli" },
3323         { COL_HPUX_SUBSYS, "nettl.subsys" },
3324         { COL_HPUX_DEVID, "nettl.devid" },
3325         { COL_FR_DLCI, "fr.dlci" },
3326         { COL_REL_CONV_TIME, "tcp.time_relative" },
3327         { COL_DELTA_CONV_TIME, "tcp.time_delta" },
3328         { COL_OXID, "fc.ox_id" },
3329         { COL_RXID, "fc.rx_id" },
3330         { COL_SRCIDX, "mdshdr.srcidx" },
3331         { COL_DSTIDX, "mdshdr.dstidx" },
3332         { COL_DCE_CTX, "dcerpc.cn_ctx_id" }
3333     };
3334
3335     guint haystack_idx;
3336     const gchar *haystack_fmt;
3337
3338     gchar **fmt = (gchar **) el_data;
3339
3340     for (haystack_idx = 0;
3341          haystack_idx < G_N_ELEMENTS(migrated_columns);
3342          ++haystack_idx) {
3343
3344         haystack_fmt = col_format_to_string(migrated_columns[haystack_idx].el);
3345         if (strcmp(haystack_fmt, *fmt) == 0) {
3346             gchar *cust_col = g_strdup_printf("%%Cus:%s:0",
3347                                 migrated_columns[haystack_idx].col_expr);
3348
3349             g_free(*fmt);
3350             *fmt = cust_col;
3351         }
3352     }
3353 }
3354
3355 static prefs_set_pref_e
3356 set_pref(gchar *pref_name, gchar *value, void *private_data _U_,
3357          gboolean return_range_errors)
3358 {
3359   unsigned long int cval;
3360   guint    uval;
3361   gboolean bval;
3362   gint     enum_val;
3363   char     *p;
3364   gchar    *dotp, *last_dotp;
3365   static gchar *filter_label = NULL;
3366   static gboolean filter_enabled = FALSE;
3367   gchar    *filter_expr = NULL;
3368   module_t *module;
3369   pref_t   *pref;
3370   gboolean had_a_dot;
3371
3372   if (strcmp(pref_name, PRS_GUI_FILTER_LABEL) == 0) {
3373     filter_label = g_strdup(value);
3374   } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED) == 0) {
3375     filter_enabled = (strcmp(value, "TRUE") == 0) ? TRUE : FALSE;
3376   } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR) == 0) {
3377     filter_expr = g_strdup(value);
3378     filter_expression_new(filter_label, filter_expr, filter_enabled);
3379     g_free(filter_label);
3380     g_free(filter_expr);
3381   } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
3382     /* Convert deprecated value to closest current equivalent */
3383     if (g_ascii_strcasecmp(value, "true") == 0) {
3384             prefs.gui_version_placement = version_both;
3385     } else {
3386             prefs.gui_version_placement = version_neither;
3387     }
3388 /* handle the deprecated name resolution options */
3389   } else if (strcmp(pref_name, "name_resolve") == 0 ||
3390              strcmp(pref_name, "capture.name_resolve") == 0) {
3391     /*
3392      * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
3393      * RESOLV_ALL and RESOLV_NONE.
3394      *
3395      * Otherwise, we treat it as a list of name types we want to resolve.
3396      */
3397      if (g_ascii_strcasecmp(value, "true") == 0) {
3398         gbl_resolv_flags.mac_name = TRUE;
3399         gbl_resolv_flags.network_name = TRUE;
3400         gbl_resolv_flags.transport_name = TRUE;
3401         gbl_resolv_flags.concurrent_dns = TRUE;
3402      }
3403      else if (g_ascii_strcasecmp(value, "false") == 0) {
3404         gbl_resolv_flags.mac_name = FALSE;
3405         gbl_resolv_flags.network_name = FALSE;
3406         gbl_resolv_flags.transport_name = FALSE;
3407         gbl_resolv_flags.concurrent_dns = FALSE;
3408      }
3409      else {
3410         /* start out with none set */
3411         gbl_resolv_flags.mac_name = FALSE;
3412         gbl_resolv_flags.network_name = FALSE;
3413         gbl_resolv_flags.transport_name = FALSE;
3414         gbl_resolv_flags.concurrent_dns = FALSE;
3415         if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
3416            return PREFS_SET_SYNTAX_ERR;
3417      }
3418   } else {
3419     /* Handle deprecated "global" options that don't have a module
3420      * associated with them
3421      */
3422     if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
3423         (strcmp(pref_name, "name_resolve_load_smi_modules") == 0)  ||
3424         (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
3425         module = nameres_module;
3426         dotp = pref_name;
3427     } else {
3428       /* To which module does this preference belong? */
3429       module = NULL;
3430       last_dotp = pref_name;
3431       had_a_dot = FALSE;
3432       while (!module) {
3433         dotp = strchr(last_dotp, '.');
3434         if (dotp == NULL) {
3435             if (had_a_dot) {
3436               /* no such module */
3437               return PREFS_SET_NO_SUCH_PREF;
3438             }
3439             else {
3440               /* no ".", so no module/name separator */
3441               return PREFS_SET_SYNTAX_ERR;
3442             }
3443         }
3444         else {
3445             had_a_dot = TRUE;
3446         }
3447         *dotp = '\0';           /* separate module and preference name */
3448         module = prefs_find_module(pref_name);
3449
3450         /*
3451          * XXX - "Diameter" rather than "diameter" was used in earlier
3452          * versions of Wireshark; if we didn't find the module, and its name
3453          * was "Diameter", look for "diameter" instead.
3454          *
3455          * In addition, the BEEP protocol used to be the BXXP protocol,
3456          * so if we didn't find the module, and its name was "bxxp",
3457          * look for "beep" instead.
3458          *
3459          * Also, the preferences for GTP v0 and v1 were combined under
3460          * a single "gtp" heading, and the preferences for SMPP were
3461          * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
3462          * However, SMPP now has its own preferences, so we just map
3463          * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
3464          *
3465          * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
3466          * and "nsip" to "gprs_ns".
3467          *
3468          * The SynOptics Network Management Protocol (SONMP) is now known by
3469          * its modern name, the Nortel Discovery Protocol (NDP).
3470          *
3471          */
3472         if (module == NULL) {
3473           if (strcmp(pref_name, "column") == 0)
3474             module = gui_column_module;
3475           else if (strcmp(pref_name, "Diameter") == 0)
3476             module = prefs_find_module("diameter");
3477           else if (strcmp(pref_name, "bxxp") == 0)
3478             module = prefs_find_module("beep");
3479           else if (strcmp(pref_name, "gtpv0") == 0 ||
3480                    strcmp(pref_name, "gtpv1") == 0)
3481             module = prefs_find_module("gtp");
3482           else if (strcmp(pref_name, "smpp-gsm-sms") == 0)
3483             module = prefs_find_module("gsm-sms-ud");
3484           else if (strcmp(pref_name, "dcp") == 0)
3485             module = prefs_find_module("dccp");
3486           else if (strcmp(pref_name, "x.25") == 0)
3487             module = prefs_find_module("x25");
3488           else if (strcmp(pref_name, "x411") == 0)
3489             module = prefs_find_module("p1");
3490           else if (strcmp(pref_name, "nsip") == 0)
3491             module = prefs_find_module("gprs-ns");
3492           else if (strcmp(pref_name, "sonmp") == 0)
3493             module = prefs_find_module("ndp");
3494           else if (strcmp(pref_name, "etheric") == 0 ||
3495                    strcmp(pref_name, "isup_thin") == 0)
3496             /* This protocols was removed 7. July 2009 */
3497             return PREFS_SET_OBSOLETE;
3498         }
3499         *dotp = '.';                /* put the preference string back */
3500         dotp++;                        /* skip past separator to preference name */
3501         last_dotp = dotp;
3502       }
3503     }
3504
3505     pref = prefs_find_preference(module, dotp);
3506
3507     if (pref == NULL) {
3508       /* "gui" prefix was added to column preferences for better organization
3509        * within the preferences file
3510        */
3511       if ((strcmp(pref_name, PRS_COL_HIDDEN) == 0) ||
3512           (strcmp(pref_name, PRS_COL_FMT) == 0)) {
3513          pref = prefs_find_preference(module, pref_name);
3514       }
3515       else if (strcmp(module->name, "mgcp") == 0) {
3516         /*
3517          * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
3518          * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
3519          * were used in earlier versions of Wireshark; if we didn't find the
3520          * preference, it was an MGCP preference, and its name was
3521          * "display raw text toggle" or "display dissect tree", look for
3522          * "display_raw_text" or "display_dissect_tree" instead.
3523          *
3524          * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
3525          * the gateway and callagent ports were given those names; we interpret
3526          * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
3527          * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
3528          * they were registered by the MCCP dissector and thus that's the
3529          * order in which they were written to the preferences file.  (If
3530          * we're not reading the preferences file, but are handling stuff
3531          * from a "-o" command-line option, we have no clue which the user
3532          * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
3533          * or "mgcp.{tcp,udp}.callagent_port" instead.)
3534          */
3535         if (strcmp(dotp, "display raw text toggle") == 0)
3536           pref = prefs_find_preference(module, "display_raw_text");
3537         else if (strcmp(dotp, "display dissect tree") == 0)
3538           pref = prefs_find_preference(module, "display_dissect_tree");
3539         else if (strcmp(dotp, "tcp.port") == 0) {
3540           mgcp_tcp_port_count++;
3541           if (mgcp_tcp_port_count == 1) {
3542             /* It's the first one */
3543             pref = prefs_find_preference(module, "tcp.gateway_port");
3544           } else if (mgcp_tcp_port_count == 2) {
3545             /* It's the second one */
3546             pref = prefs_find_preference(module, "tcp.callagent_port");
3547           }
3548           /* Otherwise it's from the command line, and we don't bother
3549              mapping it. */
3550         } else if (strcmp(dotp, "udp.port") == 0) {
3551           mgcp_udp_port_count++;
3552           if (mgcp_udp_port_count == 1) {
3553             /* It's the first one */
3554             pref = prefs_find_preference(module, "udp.gateway_port");
3555           } else if (mgcp_udp_port_count == 2) {
3556             /* It's the second one */
3557             pref = prefs_find_preference(module, "udp.callagent_port");
3558           }
3559           /* Otherwise it's from the command line, and we don't bother
3560              mapping it. */
3561         }
3562       } else if (strcmp(module->name, "smb") == 0) {
3563         /* Handle old names for SMB preferences. */
3564         if (strcmp(dotp, "smb.trans.reassembly") == 0)
3565           pref = prefs_find_preference(module, "trans_reassembly");
3566         else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
3567           pref = prefs_find_preference(module, "dcerpc_reassembly");
3568       } else if (strcmp(module->name, "ndmp") == 0) {
3569         /* Handle old names for NDMP preferences. */
3570         if (strcmp(dotp, "ndmp.desegment") == 0)
3571           pref = prefs_find_preference(module, "desegment");
3572       } else if (strcmp(module->name, "diameter") == 0) {
3573         /* Handle old names for Diameter preferences. */
3574         if (strcmp(dotp, "diameter.desegment") == 0)
3575           pref = prefs_find_preference(module, "desegment");
3576       } else if (strcmp(module->name, "pcli") == 0) {
3577         /* Handle old names for PCLI preferences. */
3578         if (strcmp(dotp, "pcli.udp_port") == 0)
3579           pref = prefs_find_preference(module, "udp_port");
3580       } else if (strcmp(module->name, "artnet") == 0) {
3581         /* Handle old names for ARTNET preferences. */
3582         if (strcmp(dotp, "artnet.udp_port") == 0)
3583           pref = prefs_find_preference(module, "udp_port");
3584       } else if (strcmp(module->name, "mapi") == 0) {
3585         /* Handle old names for MAPI preferences. */
3586         if (strcmp(dotp, "mapi_decrypt") == 0)
3587           pref = prefs_find_preference(module, "decrypt");
3588       } else if (strcmp(module->name, "fc") == 0) {
3589         /* Handle old names for Fibre Channel preferences. */
3590         if (strcmp(dotp, "reassemble_fc") == 0)
3591           pref = prefs_find_preference(module, "reassemble");
3592         else if (strcmp(dotp, "fc_max_frame_size") == 0)
3593           pref = prefs_find_preference(module, "max_frame_size");
3594       } else if (strcmp(module->name, "fcip") == 0) {
3595         /* Handle old names for Fibre Channel-over-IP preferences. */
3596         if (strcmp(dotp, "desegment_fcip_messages") == 0)
3597           pref = prefs_find_preference(module, "desegment");
3598         else if (strcmp(dotp, "fcip_port") == 0)
3599           pref = prefs_find_preference(module, "target_port");
3600       } else if (strcmp(module->name, "gtp") == 0) {
3601         /* Handle old names for GTP preferences. */
3602         if (strcmp(dotp, "gtpv0_port") == 0)
3603           pref = prefs_find_preference(module, "v0_port");
3604         else if (strcmp(dotp, "gtpv1c_port") == 0)
3605           pref = prefs_find_preference(module, "v1c_port");
3606         else if (strcmp(dotp, "gtpv1u_port") == 0)
3607           pref = prefs_find_preference(module, "v1u_port");
3608         else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
3609           pref = prefs_find_preference(module, "dissect_tpdu");
3610         else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
3611           pref = prefs_find_preference(module, "v0_dissect_cdr_as");
3612         else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
3613           pref = prefs_find_preference(module, "v0_check_etsi");
3614         else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
3615           pref = prefs_find_preference(module, "v1_check_etsi");
3616       } else if (strcmp(module->name, "ip") == 0) {
3617         /* Handle old names for IP preferences. */
3618         if (strcmp(dotp, "ip_summary_in_tree") == 0)
3619           pref = prefs_find_preference(module, "summary_in_tree");
3620       } else if (strcmp(module->name, "iscsi") == 0) {
3621         /* Handle old names for iSCSI preferences. */
3622         if (strcmp(dotp, "iscsi_port") == 0)
3623           pref = prefs_find_preference(module, "target_port");
3624       } else if (strcmp(module->name, "lmp") == 0) {
3625         /* Handle old names for LMP preferences. */
3626         if (strcmp(dotp, "lmp_version") == 0)
3627           pref = prefs_find_preference(module, "version");
3628       } else if (strcmp(module->name, "mtp3") == 0) {
3629         /* Handle old names for MTP3 preferences. */
3630         if (strcmp(dotp, "mtp3_standard") == 0)
3631           pref = prefs_find_preference(module, "standard");
3632         else if (strcmp(dotp, "net_addr_format") == 0)
3633           pref = prefs_find_preference(module, "addr_format");
3634       } else if (strcmp(module->name, "nlm") == 0) {
3635         /* Handle old names for NLM preferences. */
3636         if (strcmp(dotp, "nlm_msg_res_matching") == 0)
3637           pref = prefs_find_preference(module, "msg_res_matching");
3638       } else if (strcmp(module->name, "ppp") == 0) {
3639         /* Handle old names for PPP preferences. */
3640         if (strcmp(dotp, "ppp_fcs") == 0)
3641           pref = prefs_find_preference(module, "fcs_type");
3642         else if (strcmp(dotp, "ppp_vj") == 0)
3643           pref = prefs_find_preference(module, "decompress_vj");
3644       } else if (strcmp(module->name, "rsvp") == 0) {
3645         /* Handle old names for RSVP preferences. */
3646         if (strcmp(dotp, "rsvp_process_bundle") == 0)
3647           pref = prefs_find_preference(module, "process_bundle");
3648       } else if (strcmp(module->name, "tcp") == 0) {
3649         /* Handle old names for TCP preferences. */
3650         if (strcmp(dotp, "tcp_summary_in_tree") == 0)
3651           pref = prefs_find_preference(module, "summary_in_tree");
3652         else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
3653           pref = prefs_find_preference(module, "analyze_sequence_numbers");
3654         else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
3655           pref = prefs_find_preference(module, "relative_sequence_numbers");
3656       } else if (strcmp(module->name, "udp") == 0) {
3657         /* Handle old names for UDP preferences. */
3658         if (strcmp(dotp, "udp_summary_in_tree") == 0)
3659           pref = prefs_find_preference(module, "summary_in_tree");
3660       } else if (strcmp(module->name, "ndps") == 0) {
3661         /* Handle old names for NDPS preferences. */
3662         if (strcmp(dotp, "desegment_ndps") == 0)
3663           pref = prefs_find_preference(module, "desegment_tcp");
3664       } else if (strcmp(module->name, "http") == 0) {
3665         /* Handle old names for HTTP preferences. */
3666         if (strcmp(dotp, "desegment_http_headers") == 0)
3667           pref = prefs_find_preference(module, "desegment_headers");
3668         else if (strcmp(dotp, "desegment_http_body") == 0)
3669           pref = prefs_find_preference(module, "desegment_body");
3670       } else if (strcmp(module->name, "smpp") == 0) {
3671         /* Handle preferences that moved from SMPP. */
3672         module_t *new_module = prefs_find_module("gsm-sms-ud");
3673         if(new_module){
3674           if (strcmp(dotp, "port_number_udh_means_wsp") == 0)
3675             pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
3676           else if (strcmp(dotp, "try_dissect_1st_fragment") == 0)
3677             pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
3678         }
3679       } else if (strcmp(module->name, "asn1") == 0) {
3680         /* Handle old generic ASN.1 preferences (it's not really a
3681            rename, as the new preferences support multiple ports,
3682            but we might as well copy them over). */
3683         if (strcmp(dotp, "tcp_port") == 0)
3684           pref = prefs_find_preference(module, "tcp_ports");
3685         else if (strcmp(dotp, "udp_port") == 0)
3686           pref = prefs_find_preference(module, "udp_ports");
3687         else if (strcmp(dotp, "sctp_port") == 0)
3688           pref = prefs_find_preference(module, "sctp_ports");
3689       } else if (strcmp(module->name, "llcgprs") == 0) {
3690         if (strcmp(dotp, "ignore_cipher_bit") == 0)
3691           pref = prefs_find_preference(module, "autodetect_cipher_bit");
3692       } else if (strcmp(module->name, "erf") == 0) {
3693         if (strcmp(dotp, "erfeth") == 0) {
3694           /* Handle the old "erfeth" preference; map it to the new
3695              "ethfcs" preference, and map the values to those for
3696              the new preference. */
3697           pref = prefs_find_preference(module, "ethfcs");
3698           if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
3699             value = "TRUE";
3700           else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
3701             value = "FALSE";
3702           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
3703             value = "TRUE";
3704         } else if (strcmp(dotp, "erfatm") == 0) {
3705           /* Handle the old "erfatm" preference; map it to the new
3706              "aal5_type" preference, and map the values to those for
3707              the new preference. */
3708           pref = prefs_find_preference(module, "aal5_type");
3709           if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
3710             value = "guess";
3711           else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
3712             value = "llc";
3713           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
3714             value = "guess";
3715         } else if (strcmp(dotp, "erfhdlc") == 0) {
3716           /* Handle the old "erfhdlc" preference; map it to the new
3717              "hdlc_type" preference, and map the values to those for
3718              the new preference. */
3719           pref = prefs_find_preference(module, "hdlc_type");
3720           if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
3721             value = "chdlc";
3722           else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
3723             value = "ppp";
3724           else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
3725             value = "frelay";
3726           else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
3727             value = "mtp2";
3728           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
3729             value = "guess";
3730         }
3731       } else if (strcmp(module->name, "eth") == 0) {
3732         /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
3733         if (strcmp(dotp, "qinq_ethertype") == 0) {
3734           module_t *new_module = prefs_find_module("vlan");
3735           if(new_module) {
3736             pref = prefs_find_preference(new_module, "qinq_ethertype");
3737             module = new_module;
3738           }
3739         }
3740       } else if (strcmp(module->name, "taps") == 0) {
3741           /* taps preferences moved to stats module */
3742           if (strcmp(dotp, "update_interval") == 0 || strcmp(value, "rtp_player_max_visible") == 0)
3743             pref = prefs_find_preference(stats_module, dotp);
3744       } else if (strcmp(module->name, "packet_list") == 0) {
3745           /* packet_list preferences moved to protocol module */
3746           if (strcmp(dotp, "display_hidden_proto_items") == 0)
3747             pref = prefs_find_preference(protocols_module, dotp);
3748       } else if (strcmp(module->name, "stream") == 0) {
3749           /* stream preferences moved to gui color module */
3750           if ((strcmp(dotp, "stream.client.fg") == 0) || (strcmp(value, "stream.client.bg") == 0) ||
3751               (strcmp(dotp, "stream.server.fg") == 0) || (strcmp(value, "stream.server.bg") == 0))
3752             pref = prefs_find_preference(gui_color_module, pref_name);
3753       } else if (strcmp(module->name, "nameres") == 0) {
3754           if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
3755             pref = prefs_find_preference(nameres_module, pref_name);
3756           } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
3757             pref = prefs_find_preference(nameres_module, "load_smi_modules");
3758           } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
3759             pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
3760           }
3761       }
3762     }
3763     if (pref == NULL)
3764       return PREFS_SET_NO_SUCH_PREF;        /* no such preference */
3765
3766     switch (pref->type) {
3767
3768     case PREF_UINT:
3769       uval = strtoul(value, &p, pref->info.base);
3770       if (p == value || *p != '\0')
3771         return PREFS_SET_SYNTAX_ERR;        /* number was bad */
3772       if (*pref->varp.uint != uval) {
3773         module->prefs_changed = TRUE;
3774         *pref->varp.uint = uval;
3775       }
3776       break;
3777
3778     case PREF_BOOL:
3779       /* XXX - give an error if it's neither "true" nor "false"? */
3780       if (g_ascii_strcasecmp(value, "true") == 0)
3781         bval = TRUE;
3782       else
3783         bval = FALSE;
3784       if (*pref->varp.boolp != bval) {
3785         module->prefs_changed = TRUE;
3786         *pref->varp.boolp = bval;
3787       }
3788       break;
3789
3790     case PREF_ENUM:
3791       /* XXX - give an error if it doesn't match? */
3792       enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
3793                                      *pref->varp.enump);
3794       if (*pref->varp.enump != enum_val) {
3795         module->prefs_changed = TRUE;
3796         *pref->varp.enump = enum_val;
3797       }
3798       break;
3799
3800     case PREF_STRING:
3801     case PREF_FILENAME:
3802       if (strcmp(*pref->varp.string, value) != 0) {
3803         module->prefs_changed = TRUE;
3804         g_free((void *)*pref->varp.string);
3805         *pref->varp.string = g_strdup(value);
3806       }
3807       break;
3808
3809     case PREF_RANGE:
3810     {
3811       range_t *newrange;
3812
3813       if (range_convert_str_work(&newrange, value, pref->info.max_value,
3814                                  return_range_errors) != CVT_NO_ERROR) {
3815         return PREFS_SET_SYNTAX_ERR;        /* number was bad */
3816       }
3817
3818       if (!ranges_are_equal(*pref->varp.range, newrange)) {
3819         module->prefs_changed = TRUE;
3820         g_free(*pref->varp.range);
3821         *pref->varp.range = newrange;
3822       } else {
3823         g_free (newrange);
3824       }
3825       break;
3826     }
3827
3828     case PREF_COLOR:
3829     {
3830       cval = strtoul(value, NULL, 16);
3831       pref->varp.color->pixel = 0;
3832       if ((pref->varp.color->red != RED_COMPONENT(cval)) ||
3833           (pref->varp.color->green != GREEN_COMPONENT(cval)) ||
3834           (pref->varp.color->blue != BLUE_COMPONENT(cval))) {
3835           module->prefs_changed = TRUE;
3836           pref->varp.color->red   = RED_COMPONENT(cval);
3837           pref->varp.color->green = GREEN_COMPONENT(cval);
3838           pref->varp.color->blue  = BLUE_COMPONENT(cval);
3839       }
3840       break;
3841     }
3842
3843     case PREF_CUSTOM:
3844         return pref->custom_cbs.set_cb(pref, value, &module->prefs_changed);
3845
3846     case PREF_STATIC_TEXT:
3847     case PREF_UAT:
3848     {
3849       break;
3850     }
3851
3852     case PREF_OBSOLETE:
3853       return PREFS_SET_OBSOLETE;        /* no such preference any more */
3854     }
3855   }
3856
3857   return PREFS_SET_OK;
3858 }
3859
3860 typedef struct {
3861     FILE     *pf;
3862     gboolean is_gui_module;
3863 } write_gui_pref_arg_t;
3864
3865 /*
3866  * Write out a single dissector preference.
3867  */
3868 static void
3869 write_pref(gpointer data, gpointer user_data)
3870 {
3871     pref_t *pref = data;
3872     write_pref_arg_t *arg = user_data;
3873     const enum_val_t *enum_valp;
3874     const char *val_string, *prefix;
3875     gchar **desc_lines;
3876     int i;
3877
3878     switch (pref->type) {
3879     case PREF_OBSOLETE:
3880         /*
3881          * This preference is no longer supported; it's not a
3882          * real preference, so we don't write it out (i.e., we
3883          * treat it as if it weren't found in the list of
3884          * preferences, and we weren't called in the first place).
3885          */
3886         return;
3887
3888     case PREF_STATIC_TEXT:
3889     case PREF_UAT:
3890         /* Nothing to do; don't bother printing the description */
3891         return;
3892     default:
3893         break;
3894     }
3895
3896     /*
3897      * The prefix will either be the module name or the parent
3898      * name if its a subtree
3899      */
3900     prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
3901
3902     /*
3903      * Make multiple line descriptions appear as
3904      * multiple commented lines in prefs file.
3905      */
3906     if (pref->type != PREF_CUSTOM) {
3907         if (pref->description &&
3908                 (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
3909             desc_lines = g_strsplit(pref->description,"\n",0);
3910             for (i = 0; desc_lines[i] != NULL; ++i) {
3911                 fprintf(arg->pf, "\n# %s", desc_lines[i]);
3912             }
3913             fprintf(arg->pf, "\n");
3914             g_strfreev(desc_lines);
3915         } else {
3916             fprintf(arg->pf, "\n# No description\n");
3917         }
3918     }
3919
3920     switch (pref->type) {
3921
3922     case PREF_UINT:
3923         switch (pref->info.base) {
3924
3925         case 10:
3926             fprintf(arg->pf, "# A decimal number.\n");
3927             if (pref->default_val.uint == *pref->varp.uint)
3928                 fprintf(arg->pf, "#");
3929             fprintf(arg->pf, "%s.%s: %u\n", prefix,
3930                 pref->name, *pref->varp.uint);
3931             break;
3932
3933         case 8:
3934             fprintf(arg->pf, "# An octal number.\n");
3935             if (pref->default_val.uint == *pref->varp.uint)
3936                 fprintf(arg->pf, "#");
3937             fprintf(arg->pf, "%s.%s: %#o\n", prefix,
3938                 pref->name, *pref->varp.uint);
3939             break;
3940
3941         case 16:
3942             fprintf(arg->pf, "# A hexadecimal number.\n");
3943             if (pref->default_val.uint == *pref->varp.uint)
3944                 fprintf(arg->pf, "#");
3945             fprintf(arg->pf, "%s.%s: %#x\n", prefix,
3946                 pref->name, *pref->varp.uint);
3947             break;
3948         }
3949         break;
3950
3951     case PREF_BOOL:
3952         fprintf(arg->pf, "# TRUE or FALSE (case-insensitive).\n");
3953         if (pref->default_val.boolval == *pref->varp.boolp)
3954             fprintf(arg->pf, "#");
3955         fprintf(arg->pf, "%s.%s: %s\n", prefix, pref->name,
3956             *pref->varp.boolp ? "TRUE" : "FALSE");
3957         break;
3958
3959     case PREF_ENUM:
3960         /*
3961          * For now, we save the "description" value, so that if we
3962          * save the preferences older versions of Wireshark can at
3963          * least read preferences that they supported; we support
3964          * either the short name or the description when reading
3965          * the preferences file or a "-o" option.
3966          */
3967         fprintf(arg->pf, "# One of: ");
3968         enum_valp = pref->info.enum_info.enumvals;
3969         val_string = NULL;
3970         while (enum_valp->name != NULL) {
3971             if (enum_valp->value == *pref->varp.enump)
3972                 val_string = enum_valp->description;
3973             fprintf(arg->pf, "%s", enum_valp->description);
3974             enum_valp++;
3975             if (enum_valp->name == NULL)
3976                 fprintf(arg->pf, "\n");
3977             else
3978                 fprintf(arg->pf, ", ");
3979         }
3980         fprintf(arg->pf, "# (case-insensitive).\n");
3981         if (pref->default_val.enumval == *pref->varp.enump)
3982             fprintf(arg->pf, "#");
3983         fprintf(arg->pf, "%s.%s: %s\n", prefix,
3984             pref->name, val_string);
3985         break;
3986
3987     case PREF_STRING:
3988     case PREF_FILENAME:
3989         fprintf(arg->pf, "# A string.\n");
3990         if (!(strcmp(pref->default_val.string, *pref->varp.string)))
3991             fprintf(arg->pf, "#");
3992         fprintf(arg->pf, "%s.%s: %s\n", prefix, pref->name,
3993             *pref->varp.string);
3994         break;
3995
3996     case PREF_RANGE:
3997     {
3998         char *range_string_p;
3999
4000         range_string_p = range_convert_range(*pref->varp.range);
4001         fprintf(arg->pf, "# A string denoting an positive integer range (e.g., \"1-20,30-40\").\n");
4002         if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
4003             fprintf(arg->pf, "#");
4004         fprintf(arg->pf, "%s.%s: %s\n", prefix, pref->name,
4005             range_string_p);
4006         break;
4007     }
4008
4009     case PREF_COLOR:
4010     {
4011         fprintf (arg->pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
4012         if ((pref->default_val.color.red == pref->varp.color->red) &&
4013             (pref->default_val.color.green == pref->varp.color->green) &&
4014             (pref->default_val.color.blue == pref->varp.color->blue))
4015             fprintf(arg->pf, "#");
4016         fprintf (arg->pf, "%s.%s: %02x%02x%02x\n", prefix, pref->name,
4017                    (pref->varp.color->red * 255 / 65535),
4018                    (pref->varp.color->green * 255 / 65535),
4019                    (pref->varp.color->blue * 255 / 65535));
4020         break;
4021     }
4022
4023     case PREF_CUSTOM:
4024         pref->custom_cbs.write_cb(pref, arg);
4025         break;
4026
4027     case PREF_OBSOLETE:
4028     case PREF_STATIC_TEXT:
4029     case PREF_UAT:
4030         g_assert_not_reached();
4031         break;
4032     }
4033 }
4034
4035 /*
4036  * Write out all preferences for a module.
4037  */
4038 static guint
4039 write_module_prefs(module_t *module, gpointer user_data)
4040 {
4041     write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
4042     write_pref_arg_t arg;
4043
4044     /* The GUI module needs to be explicitly called out so it
4045        can be written out of order */
4046     if ((module == gui_module) && (gui_pref_arg->is_gui_module != TRUE))
4047         return 0;
4048
4049     /* Write a header for the main modules and GUI sub-modules */
4050     if (((module->parent == NULL) || (module->parent == gui_module)) &&
4051         ((prefs_module_has_submodules(module)) ||
4052          (module->numprefs > 0) ||
4053          (module->name == NULL))) {
4054          if ((module->name == NULL) && (module->parent != NULL)) {
4055             fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
4056          } else {
4057             fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
4058          }
4059     }
4060
4061     arg.module = module;
4062     arg.pf = gui_pref_arg->pf;
4063     g_list_foreach(arg.module->prefs, write_pref, &arg);
4064
4065     if(prefs_module_has_submodules(module))
4066         return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
4067
4068     return 0;
4069 }
4070
4071 /* Write out "prefs" to the user's preferences file, and return 0.
4072
4073    If the preferences file path is NULL, write to stdout.
4074
4075    If we got an error, stuff a pointer to the path of the preferences file
4076    into "*pf_path_return", and return the errno. */
4077 int
4078 write_prefs(char **pf_path_return)
4079 {
4080   char        *pf_path;
4081   FILE        *pf;
4082   write_gui_pref_arg_t write_gui_pref_info;
4083
4084   /* Needed for "-G defaultprefs" */
4085   init_prefs();
4086
4087   /* To do:
4088    * - Split output lines longer than MAX_VAL_LEN
4089    * - Create a function for the preference directory check/creation
4090    *   so that duplication can be avoided with filter.c
4091    */
4092
4093   if (pf_path_return != NULL) {
4094     pf_path = get_persconffile_path(PF_NAME, TRUE, TRUE);
4095     if ((pf = ws_fopen(pf_path, "w")) == NULL) {
4096       *pf_path_return = pf_path;
4097       return errno;
4098     }
4099   } else {
4100     pf = stdout;
4101   }
4102
4103   fputs("# Configuration file for Wireshark " VERSION ".\n"
4104         "#\n"
4105         "# This file is regenerated each time preferences are saved within\n"
4106         "# Wireshark.  Making manual changes should be safe, however.\n"
4107         "# Preferences that have been commented out have not been\n"
4108         "# changed from their default value.\n", pf);
4109
4110   /*
4111    * For "backwards compatibility" the GUI module is written first as its
4112    * at the top of the file.  This is followed by all modules that can't
4113    * fit into the preferences read/write API.  Finally the remaining modules
4114    * are written in alphabetical order (including of course the protocol preferences)
4115    */
4116   write_gui_pref_info.pf = pf;
4117   write_gui_pref_info.is_gui_module = TRUE;
4118
4119   write_module_prefs(gui_module, &write_gui_pref_info);
4120
4121   {
4122     struct filter_expression *fe = *(struct filter_expression **)prefs.filter_expressions;
4123
4124     if (fe != NULL)
4125       fprintf(pf, "\n####### Filter Expressions ########\n");
4126
4127     while (fe != NULL) {
4128       if (fe->deleted == FALSE) {
4129         fprintf(pf, "%s: %s\n", PRS_GUI_FILTER_LABEL, fe->label);
4130         fprintf(pf, "%s: %s\n", PRS_GUI_FILTER_ENABLED,
4131         fe->enabled == TRUE ? "TRUE" : "FALSE");
4132         fprintf(pf, "%s: %s\n", PRS_GUI_FILTER_EXPR, fe->expression);
4133       }
4134       fe = fe->next;
4135     }
4136   }
4137
4138   write_gui_pref_info.is_gui_module = FALSE;
4139   prefs_modules_foreach_submodules(NULL, write_module_prefs, &write_gui_pref_info);
4140
4141   fclose(pf);
4142
4143   /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
4144      an error indication, or maybe write to a new preferences file and
4145      rename that file on top of the old one only if there are not I/O
4146      errors. */
4147   return 0;
4148 }
4149
4150 /** The col_list is only partly managed by the custom preference API
4151  * because its data is shared between multiple preferences, so
4152  * it's freed here
4153  */
4154 static void
4155 free_col_info(GList * list)
4156 {
4157   fmt_data *cfmt;
4158
4159   while (list != NULL) {
4160     cfmt = list->data;
4161
4162     g_free(cfmt->title);
4163     g_free(cfmt->custom_field);
4164     g_free(cfmt);
4165     list = g_list_remove_link(list, list);
4166   }
4167   g_list_free(list);
4168   list = NULL;
4169 }