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