InterfaceList: Add check for remote interface
[metze/wireshark/wip.git] / epan / prefs.c
1 /* prefs.c
2  * Routines for handling preferences
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28
29 #include <glib.h>
30
31 #include <stdio.h>
32 #include <wsutil/filesystem.h>
33 #include <epan/address.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/oids.h>
36 #ifdef HAVE_GEOIP
37 #include <epan/geoip_db.h>
38 #endif
39 #include <epan/packet.h>
40 #include <epan/prefs.h>
41 #include <epan/proto.h>
42 #include <epan/strutil.h>
43 #include <epan/column.h>
44 #include <epan/decode_as.h>
45 #include "print.h"
46 #include <wsutil/file_util.h>
47 #include <wsutil/ws_printf.h> /* ws_g_warning */
48
49 #include <epan/prefs-int.h>
50 #include <epan/uat-int.h>
51
52 #include "epan/filter_expressions.h"
53
54 #include "epan/wmem/wmem.h"
55 #include <epan/stats_tree.h>
56
57 /* Internal functions */
58 static module_t *find_subtree(module_t *parent, const char *tilte);
59 static module_t *prefs_register_module_or_subtree(module_t *parent,
60     const char *name, const char *title, const char *description, gboolean is_subtree,
61     void (*apply_cb)(void), gboolean use_gui);
62 static void prefs_register_modules(void);
63 static prefs_set_pref_e set_pref(gchar*, const gchar*, void *, gboolean);
64 static void free_col_info(GList *);
65 static void pre_init_prefs(void);
66 static gboolean prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt);
67 static gboolean parse_column_format(fmt_data *cfmt, const char *fmt);
68 static void try_convert_to_custom_column(gpointer *el_data);
69
70 #define IS_PREF_OBSOLETE(p) ((p) & PREF_OBSOLETE)
71 #define SET_PREF_OBSOLETE(p) ((p) |= PREF_OBSOLETE)
72 #define RESET_PREF_OBSOLETE(p) ((p) &= ~PREF_OBSOLETE)
73
74 #define PF_NAME         "preferences"
75 #define OLD_GPF_NAME    "wireshark.conf" /* old name for global preferences file */
76
77 static gboolean prefs_initialized = FALSE;
78 static gchar *gpf_path = NULL;
79 static gchar *cols_hidden_list = NULL;
80
81 /*
82  * XXX - variables to allow us to attempt to interpret the first
83  * "mgcp.{tcp,udp}.port" in a preferences file as
84  * "mgcp.{tcp,udp}.gateway_port" and the second as
85  * "mgcp.{tcp,udp}.callagent_port".
86  */
87 static int mgcp_tcp_port_count;
88 static int mgcp_udp_port_count;
89
90 e_prefs prefs;
91
92 static const enum_val_t gui_ptree_line_style[] = {
93     {"NONE", "NONE", 0},
94     {"SOLID", "SOLID", 1},
95     {"DOTTED", "DOTTED", 2},
96     {"TABBED", "TABBED", 3},
97     {NULL, NULL, -1}
98 };
99
100 static const enum_val_t gui_ptree_expander_style[] = {
101     {"NONE", "NONE", 0},
102     {"SQUARE", "SQUARE", 1},
103     {"TRIANGLE", "TRIANGLE", 2},
104     {"CIRCULAR", "CIRCULAR", 3},
105     {NULL, NULL, -1}
106 };
107
108 static const enum_val_t gui_hex_dump_highlight_style[] = {
109     {"BOLD", "BOLD", 0},
110     {"INVERSE", "INVERSE", 1},
111     {NULL, NULL, -1}
112 };
113
114 static const enum_val_t gui_console_open_type[] = {
115     {"NEVER", "NEVER", console_open_never},
116     {"AUTOMATIC", "AUTOMATIC", console_open_auto},
117     {"ALWAYS", "ALWAYS", console_open_always},
118     {NULL, NULL, -1}
119 };
120
121 static const enum_val_t gui_version_placement_type[] = {
122     {"WELCOME", "WELCOME", version_welcome_only},
123     {"TITLE", "TITLE", version_title_only},
124     {"BOTH", "BOTH", version_both},
125     {"NEITHER", "NEITHER", version_neither},
126     {NULL, NULL, -1}
127 };
128
129 static const enum_val_t gui_fileopen_style[] = {
130     {"LAST_OPENED", "LAST_OPENED", 0},
131     {"SPECIFIED", "SPECIFIED", 1},
132     {NULL, NULL, -1}
133 };
134
135 /* GTK knows of two ways representing "both", vertical and horizontal aligned.
136  * as this may not work on other guis, we use only "both" in general here */
137 static const enum_val_t gui_toolbar_style[] = {
138     {"ICONS", "ICONS", 0},
139     {"TEXT", "TEXT", 1},
140     {"BOTH", "BOTH", 2},
141     {NULL, NULL, -1}
142 };
143
144 static const enum_val_t gui_layout_content[] = {
145     {"NONE", "NONE", 0},
146     {"PLIST", "PLIST", 1},
147     {"PDETAILS", "PDETAILS", 2},
148     {"PBYTES", "PBYTES", 3},
149     {NULL, NULL, -1}
150 };
151
152 static const enum_val_t gui_update_channel[] = {
153     {"DEVELOPMENT", "DEVELOPMENT", UPDATE_CHANNEL_DEVELOPMENT},
154     {"STABLE", "STABLE", UPDATE_CHANNEL_STABLE},
155     {NULL, NULL, -1}
156 };
157
158 #if defined(HAVE_PCAP_CREATE)
159 /* Can set monitor mode and buffer size. */
160 static gint num_capture_cols = 7;
161 static const gchar *capture_cols[7] = {
162     "INTERFACE",
163     "LINK",
164     "PMODE",
165     "SNAPLEN",
166     "MONITOR",
167     "BUFFER",
168     "FILTER"
169 };
170 #define CAPTURE_COL_TYPE_DESCRIPTION \
171     "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
172 #elif defined(CAN_SET_CAPTURE_BUFFER_SIZE)
173 /* Can set buffer size but not monitor mode. */
174 static gint num_capture_cols = 6;
175 static const gchar *capture_cols[6] = {
176     "INTERFACE",
177     "LINK",
178     "PMODE",
179     "SNAPLEN",
180     "BUFFER",
181     "FILTER"
182 };
183 #define CAPTURE_COL_TYPE_DESCRIPTION \
184     "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, BUFFER, FILTER\n"
185 #else
186 /* Can neither set buffer size nor monitor mode. */
187 static gint num_capture_cols = 5;
188 static const gchar *capture_cols[5] = {
189     "INTERFACE",
190     "LINK",
191     "PMODE",
192     "SNAPLEN",
193     "FILTER"
194 };
195 #define CAPTURE_COL_TYPE_DESCRIPTION \
196     "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, FILTER\n"
197 #endif
198
199 static const enum_val_t gui_packet_list_elide_mode[] = {
200     {"LEFT", "LEFT", ELIDE_LEFT},
201     {"RIGHT", "RIGHT", ELIDE_RIGHT},
202     {"MIDDLE", "MIDDLE", ELIDE_MIDDLE},
203     {"NONE", "NONE", ELIDE_NONE},
204     {NULL, NULL, -1}
205 };
206
207 /*
208  * List of all modules with preference settings.
209  */
210 static wmem_tree_t *prefs_modules = NULL;
211
212 /*
213  * List of all modules that should show up at the top level of the
214  * tree in the preference dialog box.
215  */
216 static wmem_tree_t *prefs_top_level_modules = NULL;
217
218 /** Sets up memory used by proto routines. Called at program startup */
219 void
220 prefs_init(void)
221 {
222     memset(&prefs, 0, sizeof(prefs));
223     prefs_modules = wmem_tree_new(wmem_epan_scope());
224     prefs_top_level_modules = wmem_tree_new(wmem_epan_scope());
225 }
226
227 /*
228  * Free the strings for a string-like preference.
229  */
230 static void
231 free_string_like_preference(pref_t *pref)
232 {
233     g_free(*pref->varp.string);
234     *pref->varp.string = NULL;
235     g_free(pref->default_val.string);
236     pref->default_val.string = NULL;
237 }
238
239 static void
240 free_pref(gpointer data, gpointer user_data _U_)
241 {
242     pref_t *pref = (pref_t *)data;
243     int type = pref->type;
244
245     /* we reset the PREF_OBSOLETE bit in order to allow the original preference to be freed */
246     RESET_PREF_OBSOLETE(type);
247
248     switch (type) {
249     case PREF_BOOL:
250     case PREF_ENUM:
251     case PREF_UINT:
252     case PREF_DECODE_AS_UINT:
253     case PREF_STATIC_TEXT:
254     case PREF_UAT:
255     case PREF_COLOR:
256         break;
257     case PREF_STRING:
258     case PREF_FILENAME:
259     case PREF_DIRNAME:
260         g_free(*pref->varp.string);
261         *pref->varp.string = NULL;
262         g_free(pref->default_val.string);
263         pref->default_val.string = NULL;
264         break;
265     case PREF_RANGE:
266     case PREF_DECODE_AS_RANGE:
267         g_free(*pref->varp.range);
268         *pref->varp.range = NULL;
269         g_free(pref->default_val.range);
270         pref->default_val.range = NULL;
271         break;
272     case PREF_CUSTOM:
273         if (strcmp(pref->name, "columns") == 0)
274           pref->stashed_val.boolval = TRUE;
275         pref->custom_cbs.free_cb(pref);
276         break;
277     }
278
279     g_free(pref);
280 }
281
282 static guint
283 free_module_prefs(module_t *module, gpointer data _U_)
284 {
285     if (module->prefs) {
286         g_list_foreach(module->prefs, free_pref, NULL);
287         g_list_free(module->prefs);
288     }
289     module->prefs = NULL;
290     module->numprefs = 0;
291     if (module->submodules) {
292         prefs_modules_foreach_submodules(module, free_module_prefs, NULL);
293     }
294     /*  We don't free the actual module: its submodules pointer points to
295         a wmem_tree and the module itself is stored in a wmem_tree
296      */
297
298     return 0;
299 }
300
301 /** Frees memory used by proto routines. Called at program shutdown */
302 void
303 prefs_cleanup(void)
304 {
305     /*  This isn't strictly necessary since we're exiting anyway, but let's
306      *  do what clean up we can.
307      */
308     prefs_modules_foreach(free_module_prefs, NULL);
309 }
310
311 /*
312  * Register a module that will have preferences.
313  * Specify the module under which to register it or NULL to register it
314  * at the top level, the name used for the module in the preferences file,
315  * the title used in the tab for it in a preferences dialog box, and a
316  * routine to call back when we apply the preferences.
317  */
318 module_t *
319 prefs_register_module(module_t *parent, const char *name, const char *title,
320                       const char *description, void (*apply_cb)(void),
321                       const gboolean use_gui)
322 {
323     return prefs_register_module_or_subtree(parent, name, title, description,
324                                             FALSE, apply_cb, use_gui);
325 }
326
327 static void
328 prefs_deregister_module(module_t *parent, const char *name, const char *title)
329 {
330     /* Remove this module from the list of all modules */
331     module_t *module = (module_t *)wmem_tree_remove_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
332
333     if (!module)
334         return;
335
336     if (parent == NULL) {
337         /* Remove from top */
338         wmem_tree_remove_string(prefs_top_level_modules, title, WMEM_TREE_STRING_NOCASE);
339     } else if (parent->submodules) {
340         /* Remove from parent */
341         wmem_tree_remove_string(parent->submodules, title, WMEM_TREE_STRING_NOCASE);
342     }
343
344     free_module_prefs(module, NULL);
345     wmem_free(wmem_epan_scope(), module);
346 }
347
348 /*
349  * Register a subtree that will have modules under it.
350  * Specify the module under which to register it or NULL to register it
351  * at the top level and the title used in the tab for it in a preferences
352  * dialog box.
353  */
354 module_t *
355 prefs_register_subtree(module_t *parent, const char *title, const char *description,
356                        void (*apply_cb)(void))
357 {
358     return prefs_register_module_or_subtree(parent, NULL, title, description,
359                                             TRUE, apply_cb,
360                                             parent ? parent->use_gui : FALSE);
361 }
362
363 static module_t *
364 prefs_register_module_or_subtree(module_t *parent, const char *name,
365                                  const char *title, const char *description,
366                                  gboolean is_subtree, void (*apply_cb)(void),
367                                  gboolean use_gui)
368 {
369     module_t *module;
370     const char *p;
371     guchar c;
372
373     /* this module may have been created as a subtree item previously */
374     if ((module = find_subtree(parent, title))) {
375         /* the module is currently a subtree */
376         module->name = name;
377         module->apply_cb = apply_cb;
378         module->description = description;
379
380         if (prefs_find_module(name) == NULL) {
381             wmem_tree_insert_string(prefs_modules, name, module,
382                                   WMEM_TREE_STRING_NOCASE);
383         }
384
385         return module;
386     }
387
388     module = wmem_new(wmem_epan_scope(), module_t);
389     module->name = name;
390     module->title = title;
391     module->description = description;
392     module->apply_cb = apply_cb;
393     module->prefs = NULL;    /* no preferences, to start */
394     module->parent = parent;
395     module->submodules = NULL;    /* no submodules, to start */
396     module->numprefs = 0;
397     module->prefs_changed = FALSE;
398     module->obsolete = FALSE;
399     module->use_gui = use_gui;
400
401     /*
402      * Do we have a module name?
403      */
404     if (name != NULL) {
405         /*
406          * Yes.
407          * Make sure that only lower-case ASCII letters, numbers,
408          * underscores, hyphens, and dots appear in the name.
409          *
410          * Crash if there is, as that's an error in the code;
411          * you can make the title a nice string with capitalization,
412          * white space, punctuation, etc., but the name can be used
413          * on the command line, and shouldn't require quoting,
414          * shifting, etc.
415          */
416         for (p = name; (c = *p) != '\0'; p++)
417             g_assert(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '_' ||
418                  c == '-' || c == '.');
419
420         /*
421          * Make sure there's not already a module with that
422          * name.  Crash if there is, as that's an error in the
423          * code, and the code has to be fixed not to register
424          * more than one module with the same name.
425          *
426          * We search the list of all modules; the subtree stuff
427          * doesn't require preferences in subtrees to have names
428          * that reflect the subtree they're in (that would require
429          * protocol preferences to have a bogus "protocol.", or
430          * something such as that, to be added to all their names).
431          */
432         g_assert(prefs_find_module(name) == NULL);
433
434         /*
435          * Insert this module in the list of all modules.
436          */
437         wmem_tree_insert_string(prefs_modules, name, module, WMEM_TREE_STRING_NOCASE);
438     } else {
439         /*
440          * This has no name, just a title; check to make sure it's a
441          * subtree, and crash if it's not.
442          */
443         g_assert(is_subtree);
444     }
445
446     /*
447      * Insert this module into the appropriate place in the display
448      * tree.
449      */
450     if (parent == NULL) {
451         /*
452          * It goes at the top.
453          */
454         wmem_tree_insert_string(prefs_top_level_modules, title, module, WMEM_TREE_STRING_NOCASE);
455     } else {
456         /*
457          * It goes into the list for this module.
458          */
459
460         if (parent->submodules == NULL)
461             parent->submodules = wmem_tree_new(wmem_epan_scope());
462
463         wmem_tree_insert_string(parent->submodules, title, module, WMEM_TREE_STRING_NOCASE);
464     }
465
466     return module;
467 }
468
469 /*
470  * Register that a protocol has preferences.
471  */
472 module_t *protocols_module = NULL;
473
474 module_t *
475 prefs_register_protocol(int id, void (*apply_cb)(void))
476 {
477     protocol_t *protocol;
478
479     /*
480      * Have we yet created the "Protocols" subtree?
481      */
482     if (protocols_module == NULL) {
483         /*
484          * No.  Register Protocols subtree as well as any preferences
485          * for non-dissector modules.
486          */
487         pre_init_prefs();
488         prefs_register_modules();
489     }
490     protocol = find_protocol_by_id(id);
491     return prefs_register_module(protocols_module,
492                                  proto_get_protocol_filter_name(id),
493                                  proto_get_protocol_short_name(protocol),
494                                  proto_get_protocol_name(id), apply_cb, TRUE);
495 }
496
497 void
498 prefs_deregister_protocol (int id)
499 {
500     protocol_t *protocol = find_protocol_by_id(id);
501     prefs_deregister_module (protocols_module,
502                              proto_get_protocol_filter_name(id),
503                              proto_get_protocol_short_name(protocol));
504 }
505
506 module_t *
507 prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
508 {
509     protocol_t *protocol;
510     module_t   *subtree_module;
511     module_t   *new_module;
512     char       *sep = NULL, *ptr = NULL, *orig = NULL;
513
514     /*
515      * Have we yet created the "Protocols" subtree?
516      * XXX - can we just do this by registering Protocols/{subtree}?
517      * If not, why not?
518      */
519     if (protocols_module == NULL) {
520         /*
521          * No.  Register Protocols subtree as well as any preferences
522          * for non-dissector modules.
523          */
524         pre_init_prefs();
525         prefs_register_modules();
526     }
527
528     subtree_module = protocols_module;
529
530     if (subtree) {
531         /* take a copy of the buffer, orig keeps a base pointer while ptr
532          * walks through the string */
533         orig = ptr = g_strdup(subtree);
534
535         while (ptr && *ptr) {
536
537             if ((sep = strchr(ptr, '/')))
538                 *sep++ = '\0';
539
540             if (!(new_module = find_subtree(subtree_module, ptr))) {
541                 /*
542                  * There's no such module; create it, with the description
543                  * being the name (if it's later registered explicitly
544                  * with a description, that will override it).
545                  */
546                 ptr = wmem_strdup(wmem_epan_scope(), ptr),
547                 new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL);
548             }
549
550             subtree_module = new_module;
551             ptr = sep;
552
553         }
554
555         g_free(orig);
556     }
557
558     protocol = find_protocol_by_id(id);
559     return prefs_register_module(subtree_module,
560                                  proto_get_protocol_filter_name(id),
561                                  proto_get_protocol_short_name(protocol),
562                                  proto_get_protocol_name(id), apply_cb, TRUE);
563 }
564
565
566 /*
567  * Register that a protocol used to have preferences but no longer does,
568  * by creating an "obsolete" module for it.
569  */
570 module_t *
571 prefs_register_protocol_obsolete(int id)
572 {
573     module_t *module;
574     protocol_t *protocol;
575
576     /*
577      * Have we yet created the "Protocols" subtree?
578      */
579     if (protocols_module == NULL) {
580         /*
581          * No.  Register Protocols subtree as well as any preferences
582          * for non-dissector modules.
583          */
584         pre_init_prefs();
585         prefs_register_modules();
586     }
587     protocol = find_protocol_by_id(id);
588     module = prefs_register_module(protocols_module,
589                                    proto_get_protocol_filter_name(id),
590                                    proto_get_protocol_short_name(protocol),
591                                    proto_get_protocol_name(id), NULL, TRUE);
592     module->obsolete = TRUE;
593     return module;
594 }
595
596 /*
597  * Register that a statistical tap has preferences.
598  *
599  * "name" is a name for the tap to use on the command line with "-o"
600  * and in preference files.
601  *
602  * "title" is a short human-readable name for the tap.
603  *
604  * "description" is a longer human-readable description of the tap.
605  */
606 module_t *stats_module = NULL;
607
608 module_t *
609 prefs_register_stat(const char *name, const char *title,
610                     const char *description, void (*apply_cb)(void))
611 {
612     /*
613      * Have we yet created the "Statistics" subtree?
614      */
615     if (stats_module == NULL) {
616         /*
617          * No.  Register Statistics subtree as well as any preferences
618          * for non-dissector modules.
619          */
620         pre_init_prefs();
621         prefs_register_modules();
622     }
623
624     return prefs_register_module(stats_module, name, title, description,
625                                  apply_cb, TRUE);
626 }
627
628 module_t *
629 prefs_find_module(const char *name)
630 {
631     return (module_t *)wmem_tree_lookup_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
632 }
633
634 static module_t *
635 find_subtree(module_t *parent, const char *name)
636 {
637     return (module_t *)wmem_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, WMEM_TREE_STRING_NOCASE);
638 }
639
640 /*
641  * Call a callback function, with a specified argument, for each module
642  * in a list of modules.  If the list is NULL, searches the top-level
643  * list in the display tree of modules.  If any callback returns a
644  * non-zero value, we stop and return that value, otherwise we
645  * return 0.
646  *
647  * Ignores "obsolete" modules; their sole purpose is to allow old
648  * preferences for dissectors that no longer have preferences to be
649  * silently ignored in preference files.  Does not ignore subtrees,
650  * as this can be used when walking the display tree of modules.
651  */
652
653 typedef struct {
654     module_cb callback;
655     gpointer user_data;
656     guint ret;
657 } call_foreach_t;
658
659 static gboolean
660 call_foreach_cb(const void *key _U_, void *value, void *data)
661 {
662     module_t *module = (module_t*)value;
663     call_foreach_t *call_data = (call_foreach_t*)data;
664
665     if (!module->obsolete)
666         call_data->ret = (*call_data->callback)(module, call_data->user_data);
667
668     return (call_data->ret != 0);
669 }
670
671 static guint
672 prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
673                           gpointer user_data)
674 {
675     call_foreach_t call_data;
676
677     if (module_list == NULL)
678         module_list = prefs_top_level_modules;
679
680     call_data.callback = callback;
681     call_data.user_data = user_data;
682     call_data.ret = 0;
683     wmem_tree_foreach(module_list, call_foreach_cb, &call_data);
684     return call_data.ret;
685 }
686
687 /*
688  * Returns TRUE if module has any submodules
689  */
690 gboolean
691 prefs_module_has_submodules(module_t *module)
692 {
693     if (module->submodules == NULL) {
694         return FALSE;
695     }
696
697     if (wmem_tree_is_empty(module->submodules)) {
698         return FALSE;
699     }
700
701     return TRUE;
702 }
703
704 /*
705  * Call a callback function, with a specified argument, for each module
706  * in the list of all modules.  (This list does not include subtrees.)
707  *
708  * Ignores "obsolete" modules; their sole purpose is to allow old
709  * preferences for dissectors that no longer have preferences to be
710  * silently ignored in preference files.
711  */
712 guint
713 prefs_modules_foreach(module_cb callback, gpointer user_data)
714 {
715     return prefs_module_list_foreach(prefs_modules, callback, user_data);
716 }
717
718 /*
719  * Call a callback function, with a specified argument, for each submodule
720  * of specified modules.  If the module is NULL, goes through the top-level
721  * list in the display tree of modules.
722  *
723  * Ignores "obsolete" modules; their sole purpose is to allow old
724  * preferences for dissectors that no longer have preferences to be
725  * silently ignored in preference files.  Does not ignore subtrees,
726  * as this can be used when walking the display tree of modules.
727  */
728 guint
729 prefs_modules_foreach_submodules(module_t *module, module_cb callback,
730                                  gpointer user_data)
731 {
732     return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data);
733 }
734
735 static gboolean
736 call_apply_cb(const void *key _U_, void *value, void *data _U_)
737 {
738     module_t *module = (module_t *)value;
739
740     if (module->obsolete)
741         return FALSE;
742     if (module->prefs_changed) {
743         if (module->apply_cb != NULL)
744             (*module->apply_cb)();
745         module->prefs_changed = FALSE;
746     }
747     if (module->submodules)
748         wmem_tree_foreach(module->submodules, call_apply_cb, NULL);
749     return FALSE;
750 }
751
752 /*
753  * Call the "apply" callback function for each module if any of its
754  * preferences have changed, and then clear the flag saying its
755  * preferences have changed, as the module has been notified of that
756  * fact.
757  */
758 void
759 prefs_apply_all(void)
760 {
761     wmem_tree_foreach(prefs_modules, call_apply_cb, NULL);
762 }
763
764 /*
765  * Call the "apply" callback function for a specific module if any of
766  * its preferences have changed, and then clear the flag saying its
767  * preferences have changed, as the module has been notified of that
768  * fact.
769  */
770 void
771 prefs_apply(module_t *module)
772 {
773     if (module && module->prefs_changed)
774         call_apply_cb(NULL, module, NULL);
775 }
776
777 /*
778  * Register a preference in a module's list of preferences.
779  * If it has a title, give it an ordinal number; otherwise, it's a
780  * preference that won't show up in the UI, so it shouldn't get an
781  * ordinal number (the ordinal should be the ordinal in the set of
782  * *visible* preferences).
783  */
784 static pref_t *
785 register_preference(module_t *module, const char *name, const char *title,
786                     const char *description, int type)
787 {
788     pref_t *preference;
789     const gchar *p;
790     const char *name_prefix = (module->name != NULL) ? module->name : module->parent->name;
791
792     preference = g_new(pref_t,1);
793     preference->name = name;
794     preference->title = title;
795     preference->description = description;
796     preference->type = type;
797     preference->gui = GUI_ALL;  /* default */
798     if (title != NULL)
799         preference->ordinal = module->numprefs;
800     else
801         preference->ordinal = -1;    /* no ordinal for you */
802
803     /*
804      * Make sure that only lower-case ASCII letters, numbers,
805      * underscores, and dots appear in the preference name.
806      *
807      * Crash if there is, as that's an error in the code;
808      * you can make the title and description nice strings
809      * with capitalization, white space, punctuation, etc.,
810      * but the name can be used on the command line,
811      * and shouldn't require quoting, shifting, etc.
812      */
813     for (p = name; *p != '\0'; p++)
814         if (!(g_ascii_islower(*p) || g_ascii_isdigit(*p) || *p == '_' || *p == '.'))
815             g_error("Preference %s.%s contains invalid characters", module->name, name);
816
817     /*
818      * Make sure there's not already a preference with that
819      * name.  Crash if there is, as that's an error in the
820      * code, and the code has to be fixed not to register
821      * more than one preference with the same name.
822      */
823     if (prefs_find_preference(module, name) != NULL)
824         g_error("Preference %s has already been registered", name);
825
826     if ((!IS_PREF_OBSOLETE(type)) &&
827         /* Don't compare if it's a subtree */
828         (module->name != NULL)) {
829         /*
830          * Make sure the preference name doesn't begin with the
831          * module name, as that's redundant and Just Silly.
832          */
833         if (!((strncmp(name, module->name, strlen(module->name)) != 0) ||
834             (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
835             g_error("Preference %s begins with the module name", name);
836     }
837
838     /* The title shows up in the preferences dialog. Make sure it's UI-friendly. */
839     if (preference->title) {
840         const char *cur_char;
841         if (preference->type != PREF_STATIC_TEXT && g_utf8_strlen(preference->title, -1) > 80) { // Arbitrary.
842             g_error("Title for preference %s.%s is too long: %s", name_prefix, preference->name, preference->title);
843         }
844
845         if (!g_utf8_validate(preference->title, -1, NULL)) {
846             g_error("Title for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
847         }
848
849         for (cur_char = preference->title; *cur_char; cur_char = g_utf8_next_char(cur_char)) {
850             if (!g_unichar_isprint(g_utf8_get_char(cur_char))) {
851                 g_error("Title for preference %s.%s isn't printable UTF-8.", name_prefix, preference->name);
852             }
853         }
854     }
855
856     if (preference->description) {
857         if (!g_utf8_validate(preference->description, -1, NULL)) {
858             g_error("Description for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
859         }
860     }
861
862     /*
863      * We passed all of our checks. Add the preference.
864      */
865     module->prefs = g_list_append(module->prefs, preference);
866     if (title != NULL)
867         module->numprefs++;
868
869     return preference;
870 }
871
872 /*
873  * Find a preference in a module's list of preferences, given the module
874  * and the preference's name.
875  */
876 typedef struct {
877     GList *list_entry;
878     const char *name;
879     module_t *submodule;
880 } find_pref_arg_t;
881
882 static gint
883 preference_match(gconstpointer a, gconstpointer b)
884 {
885     const pref_t *pref = (const pref_t *)a;
886     const char *name = (const char *)b;
887
888     return strcmp(name, pref->name);
889 }
890
891 static gboolean
892 module_find_pref_cb(const void *key _U_, void *value, void *data)
893 {
894     find_pref_arg_t* arg = (find_pref_arg_t*)data;
895     GList *list_entry;
896     module_t *module = (module_t *)value;
897
898     if (module == NULL)
899         return FALSE;
900
901     list_entry = g_list_find_custom(module->prefs, arg->name,
902         preference_match);
903
904     if (list_entry == NULL)
905         return FALSE;
906
907     arg->list_entry = list_entry;
908     arg->submodule = module;
909     return TRUE;
910 }
911
912 /* Tries to find a preference, setting containing_module to the (sub)module
913  * holding this preference. */
914 static struct preference *
915 prefs_find_preference_with_submodule(module_t *module, const char *name,
916         module_t **containing_module)
917 {
918     find_pref_arg_t arg;
919     GList *list_entry;
920
921     if (module == NULL)
922         return NULL;    /* invalid parameters */
923
924     list_entry = g_list_find_custom(module->prefs, name,
925         preference_match);
926     arg.submodule = NULL;
927
928     if (list_entry == NULL)
929     {
930         arg.list_entry = NULL;
931         if (module->submodules != NULL)
932         {
933             arg.name = name;
934             wmem_tree_foreach(module->submodules, module_find_pref_cb, &arg);
935         }
936
937         list_entry = arg.list_entry;
938     }
939
940     if (list_entry == NULL)
941         return NULL;    /* no such preference */
942
943     if (containing_module)
944         *containing_module = arg.submodule ? arg.submodule : module;
945
946     return (struct preference *) list_entry->data;
947 }
948
949 struct preference *
950 prefs_find_preference(module_t *module, const char *name)
951 {
952     return prefs_find_preference_with_submodule(module, name, NULL);
953 }
954
955 /*
956  * Returns TRUE if the given protocol has registered preferences
957  */
958 gboolean
959 prefs_is_registered_protocol(const char *name)
960 {
961     module_t *m = prefs_find_module(name);
962
963     return (m != NULL && !m->obsolete);
964 }
965
966 /*
967  * Returns the module title of a registered protocol
968  */
969 const char *
970 prefs_get_title_by_name(const char *name)
971 {
972     module_t *m = prefs_find_module(name);
973
974     return (m != NULL && !m->obsolete) ? m->title : NULL;
975 }
976
977 /*
978  * Register a preference with an unsigned integral value.
979  */
980 void
981 prefs_register_uint_preference(module_t *module, const char *name,
982                                const char *title, const char *description,
983                                guint base, guint *var)
984 {
985     pref_t *preference;
986
987     preference = register_preference(module, name, title, description,
988                                      PREF_UINT);
989     preference->varp.uint = var;
990     preference->default_val.uint = *var;
991     g_assert(base > 0 && base != 1 && base < 37);
992     preference->info.base = base;
993 }
994
995 /*
996  * XXX Add a prefs_register_{uint16|port}_preference which sets max_value?
997  */
998
999
1000 /*
1001  * Register a "custom" preference with a unsigned integral value.
1002  * XXX - This should be temporary until we can find a better way
1003  * to do "custom" preferences
1004  */
1005 static void
1006 prefs_register_uint_custom_preference(module_t *module, const char *name,
1007                                       const char *title, const char *description,
1008                                       struct pref_custom_cbs* custom_cbs, guint *var)
1009 {
1010     pref_t *preference;
1011
1012     preference = register_preference(module, name, title, description,
1013                                      PREF_CUSTOM);
1014
1015     preference->custom_cbs = *custom_cbs;
1016     preference->varp.uint = var;
1017     preference->default_val.uint = *var;
1018 }
1019
1020 /*
1021  * Register a preference with an Boolean value.
1022  */
1023 void
1024 prefs_register_bool_preference(module_t *module, const char *name,
1025                                const char *title, const char *description,
1026                                gboolean *var)
1027 {
1028     pref_t *preference;
1029
1030     preference = register_preference(module, name, title, description,
1031                                      PREF_BOOL);
1032     preference->varp.boolp = var;
1033     preference->default_val.boolval = *var;
1034 }
1035
1036 /*
1037  * Register a preference with an enumerated value.
1038  */
1039 void
1040 prefs_register_enum_preference(module_t *module, const char *name,
1041                                const char *title, const char *description,
1042                                gint *var, const enum_val_t *enumvals,
1043                                gboolean radio_buttons)
1044 {
1045     pref_t *preference;
1046
1047     preference = register_preference(module, name, title, description,
1048                                      PREF_ENUM);
1049     preference->varp.enump = var;
1050     preference->default_val.enumval = *var;
1051     preference->info.enum_info.enumvals = enumvals;
1052     preference->info.enum_info.radio_buttons = radio_buttons;
1053 }
1054
1055 static void
1056 register_string_like_preference(module_t *module, const char *name,
1057                                 const char *title, const char *description,
1058                                 char **var, int type,
1059                                 struct pref_custom_cbs* custom_cbs,
1060                                 gboolean free_tmp)
1061 {
1062     pref_t *pref;
1063     gchar *tmp;
1064
1065     pref = register_preference(module, name, title, description, type);
1066
1067     /*
1068      * String preference values should be non-null (as you can't
1069      * keep them null after using the preferences GUI, you can at best
1070      * have them be null strings) and freeable (as we free them
1071      * if we change them).
1072      *
1073      * If the value is a null pointer, make it a copy of a null
1074      * string, otherwise make it a copy of the value.
1075      */
1076     tmp = *var;
1077     if (*var == NULL) {
1078         *var = g_strdup("");
1079     } else {
1080         *var = g_strdup(*var);
1081     }
1082     if (free_tmp) {
1083         g_free(tmp);
1084     }
1085     pref->varp.string = var;
1086     pref->default_val.string = g_strdup(*var);
1087     pref->stashed_val.string = NULL;
1088     if (type == PREF_CUSTOM) {
1089         g_assert(custom_cbs);
1090         pref->custom_cbs = *custom_cbs;
1091     }
1092 }
1093
1094 /*
1095  * For use by UI code that sets preferences.
1096  */
1097 void
1098 prefs_set_string_like_value(pref_t *pref, const gchar *value, gboolean *changed)
1099 {
1100     if (*pref->varp.string) {
1101         if (strcmp(*pref->varp.string, value) != 0) {
1102             *changed = TRUE;
1103             g_free(*pref->varp.string);
1104             *pref->varp.string = g_strdup(value);
1105         }
1106     } else if (value) {
1107         *pref->varp.string = g_strdup(value);
1108     }
1109 }
1110
1111 /*
1112  * Reset the value of a string-like preference.
1113  */
1114 static void
1115 reset_string_like_preference(pref_t *pref)
1116 {
1117     g_free(*pref->varp.string);
1118     *pref->varp.string = g_strdup(pref->default_val.string);
1119 }
1120
1121 /*
1122  * Register a preference with a character-string value.
1123  */
1124 void
1125 prefs_register_string_preference(module_t *module, const char *name,
1126                                  const char *title, const char *description,
1127                                  const char **var)
1128 {
1129 DIAG_OFF(cast-qual)
1130     register_string_like_preference(module, name, title, description,
1131                                     (char **)var, PREF_STRING, NULL, FALSE);
1132 DIAG_ON(cast-qual)
1133 }
1134
1135 /*
1136  * Register a preference with a file name (string) value.
1137  */
1138 void
1139 prefs_register_filename_preference(module_t *module, const char *name,
1140                                    const char *title, const char *description,
1141                                    const char **var)
1142 {
1143 DIAG_OFF(cast-qual)
1144     register_string_like_preference(module, name, title, description,
1145                                     (char **)var, PREF_FILENAME, NULL, FALSE);
1146 DIAG_ON(cast-qual)
1147 }
1148
1149 /*
1150  * Register a preference with a directory name (string) value.
1151  */
1152 void
1153 prefs_register_directory_preference(module_t *module, const char *name,
1154                                    const char *title, const char *description,
1155                                    const char **var)
1156 {
1157 DIAG_OFF(cast-qual)
1158     register_string_like_preference(module, name, title, description,
1159                                     (char **)var, PREF_DIRNAME, NULL, FALSE);
1160 DIAG_ON(cast-qual)
1161 }
1162
1163 /* Refactoring to handle both PREF_RANGE and PREF_DECODE_AS_RANGE */
1164 static void
1165 prefs_register_range_preference_common(module_t *module, const char *name,
1166                                 const char *title, const char *description,
1167                                 range_t **var, guint32 max_value, int type)
1168 {
1169     pref_t *preference;
1170
1171     preference = register_preference(module, name, title, description, type);
1172     preference->info.max_value = max_value;
1173
1174     /*
1175      * Range preference values should be non-null (as you can't
1176      * keep them null after using the preferences GUI, you can at best
1177      * have them be empty ranges) and freeable (as we free them
1178      * if we change them).
1179      *
1180      * If the value is a null pointer, make it an empty range.
1181      */
1182     if (*var == NULL)
1183         *var = range_empty();
1184     preference->varp.range = var;
1185     preference->default_val.range = range_copy(*var);
1186     preference->stashed_val.range = NULL;
1187 }
1188
1189 /*
1190  * Register a preference with a ranged value.
1191  */
1192 void
1193 prefs_register_range_preference(module_t *module, const char *name,
1194                                 const char *title, const char *description,
1195                                 range_t **var, guint32 max_value)
1196 {
1197     prefs_register_range_preference_common(module, name, title,
1198                 description, var, max_value, PREF_RANGE);
1199 }
1200
1201 static gboolean
1202 prefs_set_range_value_work(pref_t *pref, const gchar *value,
1203                            gboolean return_range_errors, gboolean *changed)
1204 {
1205     range_t *newrange;
1206
1207     if (range_convert_str_work(&newrange, value, pref->info.max_value,
1208                                return_range_errors) != CVT_NO_ERROR) {
1209         return FALSE;        /* number was bad */
1210     }
1211
1212     if (!ranges_are_equal(*pref->varp.range, newrange)) {
1213         *changed = TRUE;
1214         g_free(*pref->varp.range);
1215         *pref->varp.range = newrange;
1216     } else {
1217         g_free(newrange);
1218     }
1219     return TRUE;
1220 }
1221
1222 /*
1223  * For use by UI code that sets preferences.
1224  */
1225 gboolean
1226 prefs_set_range_value(pref_t *pref, const gchar *value, gboolean *changed)
1227 {
1228     return prefs_set_range_value_work(pref, value, TRUE, changed);
1229 }
1230
1231 /*
1232  * Register a static text 'preference'.  It can be used to add explanatory
1233  * text inline with other preferences in the GUI.
1234  * Note: Static preferences are not saved to the preferences file.
1235  */
1236 void
1237 prefs_register_static_text_preference(module_t *module, const char *name,
1238                                       const char *title,
1239                                       const char *description)
1240 {
1241     register_preference(module, name, title, description, PREF_STATIC_TEXT);
1242 }
1243
1244 /*
1245  * Register a uat 'preference'. It adds a button that opens the uat's window in the
1246  * preferences tab of the module.
1247  */
1248 extern void
1249 prefs_register_uat_preference(module_t *module, const char *name,
1250                               const char *title, const char *description,
1251                               uat_t* uat)
1252 {
1253
1254     pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1255
1256     preference->varp.uat = uat;
1257 }
1258
1259 /*
1260  * Register a uat 'preference' for QT only. It adds a button that opens the uat's window in the
1261  * preferences tab of the module.
1262  */
1263 extern void
1264 prefs_register_uat_preference_qt(module_t *module, const char *name,
1265                               const char *title, const char *description,
1266                               uat_t* uat)
1267 {
1268
1269     pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1270
1271     preference->varp.uat = uat;
1272
1273     preference->gui = GUI_QT;
1274 }
1275
1276 /*
1277  * Register a color preference.
1278  */
1279 void
1280 prefs_register_color_preference(module_t *module, const char *name,
1281                                 const char *title, const char *description,
1282                                 color_t *color)
1283 {
1284     pref_t* preference = register_preference(module, name, title, description, PREF_COLOR);
1285
1286     preference->varp.colorp = color;
1287     preference->default_val.color = *color;
1288 }
1289
1290 /*
1291  * Register a "custom" preference with a list.
1292  * XXX - This should be temporary until we can find a better way
1293  * to do "custom" preferences
1294  */
1295 typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
1296
1297 static void
1298 prefs_register_list_custom_preference(module_t *module, const char *name,
1299                                       const char *title, const char *description,
1300                                       struct pref_custom_cbs* custom_cbs,
1301                                       pref_custom_list_init_cb init_cb,
1302                                       GList** list)
1303 {
1304     pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1305
1306     preference->custom_cbs = *custom_cbs;
1307     init_cb(preference, list);
1308 }
1309
1310 /*
1311  * Register a custom preference.
1312  */
1313 void
1314 prefs_register_custom_preference(module_t *module, const char *name,
1315                                  const char *title, const char *description,
1316                                  struct pref_custom_cbs* custom_cbs,
1317                                  void **custom_data _U_)
1318 {
1319     pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1320
1321     preference->custom_cbs = *custom_cbs;
1322     /* XXX - wait until we can handle void** pointers
1323     preference->custom_cbs.init_cb(preference, custom_data);
1324     */
1325 }
1326
1327 /*
1328  * Register a (internal) "Decode As" preference with a ranged value.
1329  */
1330 void prefs_register_decode_as_range_preference(module_t *module, const char *name,
1331     const char *title, const char *description, range_t **var,
1332     guint32 max_value)
1333 {
1334     prefs_register_range_preference_common(module, name, title,
1335                 description, var, max_value, PREF_DECODE_AS_RANGE);
1336 }
1337
1338 /*
1339  * Register a (internal) "Decode As" preference with an unsigned integral value
1340  * for a dissector table.
1341  */
1342 void prefs_register_decode_as_preference(module_t *module, const char *name,
1343     const char *title, const char *description, guint *var)
1344 {
1345     pref_t *preference;
1346
1347     preference = register_preference(module, name, title, description,
1348                                      PREF_DECODE_AS_UINT);
1349     preference->varp.uint = var;
1350     preference->default_val.uint = *var;
1351     /* XXX - Presume base 10 for now */
1352     preference->info.base = 10;
1353 }
1354
1355 /*
1356  * Register a preference that used to be supported but no longer is.
1357  */
1358 void
1359 prefs_register_obsolete_preference(module_t *module, const char *name)
1360 {
1361     register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
1362 }
1363
1364 /*
1365  * Check to see if a preference is obsolete.
1366  */
1367 extern gboolean
1368 prefs_get_preference_obsolete(pref_t *pref)
1369 {
1370     if (pref)
1371         return (IS_PREF_OBSOLETE(pref->type) ? TRUE : FALSE);
1372
1373     return TRUE;
1374 }
1375
1376 /*
1377  * Make a preference obsolete.
1378  */
1379 extern prefs_set_pref_e
1380 prefs_set_preference_obsolete(pref_t *pref)
1381 {
1382     if (pref) {
1383         SET_PREF_OBSOLETE(pref->type);
1384         return PREFS_SET_OK;
1385     }
1386     return PREFS_SET_NO_SUCH_PREF;
1387 }
1388
1389 #if 0
1390 /* Return the value assigned to the given uint preference. */
1391 guint
1392 prefs_get_uint_preference(pref_t *pref)
1393 {
1394     if (pref && pref->type == PREF_UINT)
1395         return *pref->varp.uint;
1396     return 0;
1397 }
1398 #endif
1399
1400 /*
1401  * Call a callback function, with a specified argument, for each preference
1402  * in a given module.
1403  *
1404  * If any of the callbacks return a non-zero value, stop and return that
1405  * value, otherwise return 0.
1406  */
1407 guint
1408 prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
1409 {
1410     GList *elem;
1411     pref_t *pref;
1412     guint ret;
1413
1414     for (elem = g_list_first(module->prefs); elem != NULL; elem = g_list_next(elem)) {
1415         pref = (pref_t *)elem->data;
1416         if (IS_PREF_OBSOLETE(pref->type)) {
1417             /*
1418              * This preference is no longer supported; it's
1419              * not a real preference, so we don't call the
1420              * callback for it (i.e., we treat it as if it
1421              * weren't found in the list of preferences,
1422              * and we weren't called in the first place).
1423              */
1424             continue;
1425         }
1426
1427         ret = (*callback)(pref, user_data);
1428         if (ret != 0)
1429             return ret;
1430     }
1431     return 0;
1432 }
1433
1434 static const enum_val_t print_format_vals[] = {
1435     { "text",       "Plain Text", PR_FMT_TEXT },
1436     { "postscript", "Postscript", PR_FMT_PS },
1437     { NULL,         NULL,         0 }
1438 };
1439
1440 static const enum_val_t print_dest_vals[] = {
1441 #ifdef _WIN32
1442     /* "PR_DEST_CMD" means "to printer" on Windows */
1443     { "command", "Printer", PR_DEST_CMD },
1444 #else
1445     { "command", "Command", PR_DEST_CMD },
1446 #endif
1447     { "file",    "File",    PR_DEST_FILE },
1448     { NULL,      NULL,      0 }
1449 };
1450
1451 static const enum_val_t st_sort_col_vals[] = {
1452     { "name",    "Node name (topic/item)", ST_SORT_COL_NAME },
1453     { "count",   "Item count", ST_SORT_COL_COUNT },
1454     { "average", "Average value of the node", ST_SORT_COL_AVG },
1455     { "min",     "Minimum value of the node", ST_SORT_COL_MIN },
1456     { "max",     "Maximum value of the node", ST_SORT_COL_MAX },
1457     { "burst",   "Burst rate of the node", ST_SORT_COL_BURSTRATE },
1458     { NULL,      NULL,         0 }
1459 };
1460
1461 static void
1462 stats_callback(void)
1463 {
1464     /* Test for a sane tap update interval */
1465     if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
1466         prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
1467
1468 #ifdef HAVE_LIBPORTAUDIO
1469     /* Test for a sane max channels entry */
1470     if (prefs.rtp_player_max_visible < 1 || prefs.rtp_player_max_visible > 10)
1471         prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
1472 #endif
1473
1474     /* burst resolution can't be less than 1 (ms) */
1475     if (prefs.st_burst_resolution < 1) {
1476         prefs.st_burst_resolution = 1;
1477     }
1478     else if (prefs.st_burst_resolution > ST_MAX_BURSTRES) {
1479         prefs.st_burst_resolution = ST_MAX_BURSTRES;
1480     }
1481     /* make sure burst window value makes sense */
1482     if (prefs.st_burst_windowlen < prefs.st_burst_resolution) {
1483         prefs.st_burst_windowlen = prefs.st_burst_resolution;
1484     }
1485     /* round burst window down to multiple of resolution */
1486     prefs.st_burst_windowlen -= prefs.st_burst_windowlen%prefs.st_burst_resolution;
1487     if ((prefs.st_burst_windowlen/prefs.st_burst_resolution) > ST_MAX_BURSTBUCKETS) {
1488         prefs.st_burst_windowlen = prefs.st_burst_resolution*ST_MAX_BURSTBUCKETS;
1489     }
1490 }
1491
1492 static void
1493 gui_callback(void)
1494 {
1495     /* Ensure there is at least one file count */
1496     if (prefs.gui_recent_files_count_max == 0)
1497       prefs.gui_recent_files_count_max = 10;
1498
1499     /* Ensure there is at least one display filter entry */
1500     if (prefs.gui_recent_df_entries_max == 0)
1501       prefs.gui_recent_df_entries_max = 10;
1502 }
1503
1504 static void
1505 gui_layout_callback(void)
1506 {
1507     if (prefs.gui_layout_type == layout_unused ||
1508         prefs.gui_layout_type >= layout_type_max) {
1509       /* XXX - report an error?  It's not a syntax error - we'd need to
1510          add a way of reporting a *semantic* error. */
1511       prefs.gui_layout_type = layout_type_5;
1512     }
1513 }
1514
1515 /******************************************************
1516  * All custom preference function callbacks
1517  ******************************************************/
1518 static void custom_pref_no_cb(pref_t* pref _U_) {}
1519
1520
1521 /*
1522  * Console log level custom preference functions
1523  */
1524 static void
1525 console_log_level_reset_cb(pref_t* pref)
1526 {
1527     *pref->varp.uint = pref->default_val.uint;
1528 }
1529
1530 static prefs_set_pref_e
1531 console_log_level_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
1532 {
1533     guint    uval;
1534
1535     uval = (guint)strtoul(value, NULL, 10);
1536
1537     if (*pref->varp.uint != uval) {
1538         *changed = TRUE;
1539         *pref->varp.uint = uval;
1540     }
1541
1542     if (*pref->varp.uint & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG)) {
1543       /*
1544        * GLib >= 2.32 drops INFO and DEBUG messages by default. Tell
1545        * it not to do that.
1546        */
1547        g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
1548     }
1549
1550     return PREFS_SET_OK;
1551 }
1552
1553 static const char * console_log_level_type_name_cb(void) {
1554     return "Log level";
1555 }
1556
1557 static char * console_log_level_type_description_cb(void) {
1558     return g_strdup_printf(
1559         "Console log level (for debugging)\n"
1560         "A bitmask of log levels:\n"
1561         "ERROR    = 4\n"
1562         "CRITICAL = 8\n"
1563         "WARNING  = 16\n"
1564         "MESSAGE  = 32\n"
1565         "INFO     = 64\n"
1566         "DEBUG    = 128");
1567 }
1568
1569 static gboolean console_log_level_is_default_cb(pref_t* pref) {
1570     return *pref->varp.uint == pref->default_val.uint;
1571 }
1572
1573 static char * console_log_level_to_str_cb(pref_t* pref, gboolean default_val) {
1574     return g_strdup_printf("%u",  default_val ? pref->default_val.uint : *pref->varp.uint);
1575 }
1576
1577 /*
1578  * Column preference functions
1579  */
1580 #define PRS_COL_HIDDEN                   "column.hidden"
1581 #define PRS_COL_FMT                      "column.format"
1582 #define PRS_COL_NUM                      "column.number"
1583 static module_t *gui_column_module = NULL;
1584
1585 static prefs_set_pref_e
1586 column_hidden_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
1587 {
1588     GList       *clp;
1589     fmt_data    *cfmt;
1590     pref_t  *format_pref;
1591
1592     prefs_set_string_like_value(pref, value, changed);
1593
1594     /*
1595      * Set the "visible" flag for the existing columns; we need to
1596      * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
1597      * after setting it (which might be the case if, for example, we
1598      * set PRS_COL_HIDDEN on the command line).
1599      */
1600     format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
1601     for (clp = *format_pref->varp.list; clp != NULL; clp = clp->next) {
1602       cfmt = (fmt_data *)clp->data;
1603       cfmt->visible = prefs_is_column_visible(*pref->varp.string, cfmt);
1604     }
1605
1606     return PREFS_SET_OK;
1607 }
1608
1609 static const char *
1610 column_hidden_type_name_cb(void)
1611 {
1612     return "Packet list hidden columns";
1613 }
1614
1615 static char *
1616 column_hidden_type_description_cb(void)
1617 {
1618     return g_strdup("List all columns to hide in the packet list.");
1619 }
1620
1621 static char *
1622 column_hidden_to_str_cb(pref_t* pref, gboolean default_val)
1623 {
1624     GString     *cols_hidden = g_string_new ("");
1625     GList       *clp;
1626     fmt_data    *cfmt;
1627     pref_t  *format_pref;
1628
1629     if (default_val)
1630         return g_strdup(pref->default_val.string);
1631
1632     format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
1633     clp = (format_pref) ? *format_pref->varp.list : NULL;
1634     while (clp) {
1635         gchar *prefs_fmt;
1636         cfmt = (fmt_data *) clp->data;
1637         if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
1638             prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
1639                     col_format_to_string(cfmt->fmt),
1640                     cfmt->custom_fields,
1641                     cfmt->custom_occurrence,
1642                     cfmt->resolved ? 'R' : 'U');
1643         } else {
1644             prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
1645         }
1646         if (!cfmt->visible) {
1647             if (cols_hidden->len)
1648                 g_string_append (cols_hidden, ",");
1649             g_string_append (cols_hidden, prefs_fmt);
1650         }
1651         g_free(prefs_fmt);
1652         clp = clp->next;
1653     }
1654
1655     return g_string_free (cols_hidden, FALSE);
1656 }
1657
1658 static gboolean
1659 column_hidden_is_default_cb(pref_t* pref)
1660 {
1661     char *cur_hidden_str = column_hidden_to_str_cb(pref, FALSE);
1662     gboolean is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
1663
1664     g_free(cur_hidden_str);
1665     return is_default;
1666 }
1667
1668
1669 /* Number of columns "preference".  This is only used internally and is not written to the
1670  * preference file
1671  */
1672 static void
1673 column_num_reset_cb(pref_t* pref)
1674 {
1675     *pref->varp.uint = pref->default_val.uint;
1676 }
1677
1678 static prefs_set_pref_e
1679 column_num_set_cb(pref_t* pref _U_, const gchar* value _U_, gboolean* changed _U_)
1680 {
1681     /* Don't write this to the preferences file */
1682     return PREFS_SET_OK;
1683 }
1684
1685 static const char *
1686 column_num_type_name_cb(void)
1687 {
1688     return NULL;
1689 }
1690
1691 static char *
1692 column_num_type_description_cb(void)
1693 {
1694     return g_strdup("");
1695 }
1696
1697 static gboolean
1698 column_num_is_default_cb(pref_t* pref _U_)
1699 {
1700     return TRUE;
1701 }
1702
1703 static char *
1704 column_num_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
1705 {
1706     return g_strdup("");
1707 }
1708
1709 /*
1710  * Column format custom preference functions
1711  */
1712 static void
1713 column_format_init_cb(pref_t* pref, GList** value)
1714 {
1715     fmt_data *src_cfmt, *dest_cfmt;
1716     GList *entry;
1717
1718     pref->varp.list = value;
1719
1720     pref->default_val.list = NULL;
1721     for (entry = *pref->varp.list; entry != NULL; entry = g_list_next(entry)) {
1722         src_cfmt = (fmt_data *)entry->data;
1723         dest_cfmt = g_new(fmt_data,1);
1724         dest_cfmt->title = g_strdup(src_cfmt->title);
1725         dest_cfmt->fmt = src_cfmt->fmt;
1726         if (src_cfmt->custom_fields) {
1727             dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
1728             dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
1729         } else {
1730             dest_cfmt->custom_fields = NULL;
1731             dest_cfmt->custom_occurrence = 0;
1732         }
1733         dest_cfmt->visible = src_cfmt->visible;
1734         dest_cfmt->resolved = src_cfmt->resolved;
1735         pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
1736     }
1737 }
1738
1739 static void
1740 column_format_free_cb(pref_t* pref)
1741 {
1742     free_col_info(*pref->varp.list);
1743     free_col_info(pref->default_val.list);
1744 }
1745
1746 static void
1747 column_format_reset_cb(pref_t* pref)
1748 {
1749     fmt_data *src_cfmt, *dest_cfmt;
1750     GList *entry;
1751     pref_t  *col_num_pref;
1752
1753     free_col_info(*pref->varp.list);
1754     *pref->varp.list = NULL;
1755
1756     for (entry = pref->default_val.list; entry != NULL; entry = g_list_next(entry)) {
1757         src_cfmt = (fmt_data *)entry->data;
1758         dest_cfmt = g_new(fmt_data,1);
1759         dest_cfmt->title = g_strdup(src_cfmt->title);
1760         dest_cfmt->fmt = src_cfmt->fmt;
1761         if (src_cfmt->custom_fields) {
1762             dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
1763             dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
1764         } else {
1765             dest_cfmt->custom_fields = NULL;
1766             dest_cfmt->custom_occurrence = 0;
1767         }
1768         dest_cfmt->visible = src_cfmt->visible;
1769         dest_cfmt->resolved = src_cfmt->resolved;
1770         *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
1771     }
1772
1773     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
1774     g_assert(col_num_pref != NULL); /* Should never happen */
1775     column_num_reset_cb(col_num_pref);
1776 }
1777
1778 static prefs_set_pref_e
1779 column_format_set_cb(pref_t* pref, const gchar* value, gboolean* changed _U_)
1780 {
1781     GList    *col_l, *col_l_elt;
1782     fmt_data *cfmt;
1783     gint     llen;
1784     pref_t   *hidden_pref, *col_num_pref;
1785
1786     col_l = prefs_get_string_list(value);
1787     if (col_l == NULL)
1788       return PREFS_SET_SYNTAX_ERR;
1789     if ((g_list_length(col_l) % 2) != 0) {
1790       /* A title didn't have a matching format.  */
1791       prefs_clear_string_list(col_l);
1792       return PREFS_SET_SYNTAX_ERR;
1793     }
1794     /* Check to make sure all column formats are valid.  */
1795     col_l_elt = g_list_first(col_l);
1796     while (col_l_elt) {
1797       fmt_data cfmt_check;
1798
1799       /* Go past the title.  */
1800       col_l_elt = col_l_elt->next;
1801
1802       /* Parse the format to see if it's valid.  */
1803       if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
1804         /* It's not a valid column format.  */
1805         prefs_clear_string_list(col_l);
1806         return PREFS_SET_SYNTAX_ERR;
1807       }
1808       if (cfmt_check.fmt != COL_CUSTOM) {
1809         /* Some predefined columns have been migrated to use custom columns.
1810          * We'll convert these silently here */
1811         try_convert_to_custom_column(&col_l_elt->data);
1812       } else {
1813         /* We don't need the custom column field on this pass. */
1814         g_free(cfmt_check.custom_fields);
1815       }
1816
1817       /* Go past the format.  */
1818       col_l_elt = col_l_elt->next;
1819     }
1820
1821     /* They're all valid; process them. */
1822     free_col_info(*pref->varp.list);
1823     *pref->varp.list = NULL;
1824     hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN);
1825     g_assert(hidden_pref != NULL); /* Should never happen */
1826     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
1827     g_assert(col_num_pref != NULL); /* Should never happen */
1828     llen             = g_list_length(col_l);
1829     *col_num_pref->varp.uint = llen / 2;
1830     col_l_elt = g_list_first(col_l);
1831     while (col_l_elt) {
1832       cfmt           = g_new(fmt_data,1);
1833       cfmt->title    = g_strdup((gchar *)col_l_elt->data);
1834       col_l_elt      = col_l_elt->next;
1835       parse_column_format(cfmt, (char *)col_l_elt->data);
1836       cfmt->visible   = prefs_is_column_visible(*hidden_pref->varp.string, cfmt);
1837       col_l_elt      = col_l_elt->next;
1838       *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
1839     }
1840
1841     prefs_clear_string_list(col_l);
1842     free_string_like_preference(hidden_pref);
1843     return PREFS_SET_OK;
1844 }
1845
1846
1847 static const char *
1848 column_format_type_name_cb(void)
1849 {
1850     return "Packet list column format";
1851 }
1852
1853 static char *
1854 column_format_type_description_cb(void)
1855 {
1856     return g_strdup("Each pair of strings consists of a column title and its format");
1857 }
1858
1859 static gboolean
1860 column_format_is_default_cb(pref_t* pref)
1861 {
1862     GList       *clp = *pref->varp.list,
1863                 *pref_col = g_list_first(clp),
1864                 *def_col = g_list_first(pref->default_val.list);
1865     fmt_data    *cfmt, *def_cfmt;
1866     gboolean    is_default = TRUE;
1867     pref_t      *col_num_pref;
1868
1869     /* See if the column data has changed from the default */
1870     col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
1871     if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
1872         is_default = FALSE;
1873     } else {
1874         while (pref_col && def_col) {
1875             cfmt = (fmt_data *) pref_col->data;
1876             def_cfmt = (fmt_data *) def_col->data;
1877             if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
1878                     (cfmt->fmt != def_cfmt->fmt) ||
1879                     (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) &&
1880                      ((g_strcmp0(cfmt->custom_fields, def_cfmt->custom_fields) != 0) ||
1881                       (cfmt->resolved != def_cfmt->resolved)))) {
1882                 is_default = FALSE;
1883                 break;
1884             }
1885
1886             pref_col = pref_col->next;
1887             def_col = def_col->next;
1888         }
1889     }
1890
1891     return is_default;
1892 }
1893
1894 static char *
1895 column_format_to_str_cb(pref_t* pref, gboolean default_val)
1896 {
1897     GList       *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
1898     GList       *clp = g_list_first(pref_l);
1899     GList       *col_l;
1900     fmt_data    *cfmt;
1901     gchar       *prefs_fmt;
1902     char        *column_format_str;
1903
1904     col_l = NULL;
1905     while (clp) {
1906         cfmt = (fmt_data *) clp->data;
1907         col_l = g_list_append(col_l, g_strdup(cfmt->title));
1908         if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
1909             prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
1910                     col_format_to_string(cfmt->fmt),
1911                     cfmt->custom_fields,
1912                     cfmt->custom_occurrence,
1913                     cfmt->resolved ? 'R' : 'U');
1914         } else {
1915             prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
1916         }
1917         col_l = g_list_append(col_l, prefs_fmt);
1918         clp = clp->next;
1919     }
1920
1921     column_format_str = join_string_list(col_l);
1922     prefs_clear_string_list(col_l);
1923     return column_format_str;
1924 }
1925
1926
1927 /******  Capture column custom preference functions  ******/
1928
1929 /* This routine is only called when Wireshark is started, NOT when another profile is selected.
1930    Copy the pref->capture_columns list (just loaded with the capture_cols[] struct values)
1931    to prefs->default_val.list.
1932 */
1933 static void
1934 capture_column_init_cb(pref_t* pref, GList** capture_cols_values)
1935 {
1936     GList   *ccv_list = *capture_cols_values,
1937             *dlist = NULL;
1938
1939     /*  */
1940     while (ccv_list) {
1941         dlist = g_list_append(dlist, g_strdup((gchar *)ccv_list->data));
1942         ccv_list = ccv_list->next;
1943     }
1944
1945     pref->default_val.list = dlist;
1946     pref->varp.list = &prefs.capture_columns;
1947     pref->stashed_val.boolval = FALSE;
1948 }
1949
1950 /* Free the prefs->capture_columns list strings and remove the list entries.
1951    Note that since pref->varp.list points to &prefs.capture_columns, it is
1952    also freed.
1953 */
1954 static void
1955 capture_column_free_cb(pref_t* pref)
1956 {
1957     prefs_clear_string_list(prefs.capture_columns);
1958     prefs.capture_columns = NULL;
1959
1960     if (pref->stashed_val.boolval == TRUE) {
1961       prefs_clear_string_list(pref->default_val.list);
1962       pref->default_val.list = NULL;
1963     }
1964 }
1965
1966 /* Copy pref->default_val.list to *pref->varp.list.
1967 */
1968 static void
1969 capture_column_reset_cb(pref_t* pref)
1970 {
1971     GList *vlist = NULL, *dlist;
1972
1973     /* Free the column name strings and remove the links from *pref->varp.list */
1974     prefs_clear_string_list(*pref->varp.list);
1975
1976     for (dlist = pref->default_val.list; dlist != NULL; dlist = g_list_next(dlist)) {
1977       vlist = g_list_append(vlist, g_strdup((gchar *)dlist->data));
1978     }
1979     *pref->varp.list = vlist;
1980 }
1981
1982 static prefs_set_pref_e
1983 capture_column_set_cb(pref_t* pref, const gchar* value, gboolean* changed _U_)
1984 {
1985     GList *col_l  = prefs_get_string_list(value);
1986     GList *col_l_elt;
1987     gchar *col_name;
1988     int i;
1989
1990     if (col_l == NULL)
1991       return PREFS_SET_SYNTAX_ERR;
1992
1993     capture_column_free_cb(pref);
1994
1995     /* If value (the list of capture.columns read from preferences) is empty, set capture.columns
1996        to the full list of valid capture column names. */
1997     col_l_elt = g_list_first(col_l);
1998     if (!(*(gchar *)col_l_elt->data)) {
1999         for (i = 0; i < num_capture_cols; i++) {
2000           col_name = g_strdup(capture_cols[i]);
2001           prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2002         }
2003     }
2004
2005     /* Verify that all the column names are valid. If not, use the entire list of valid columns.
2006      */
2007     while (col_l_elt) {
2008       gboolean found_match = FALSE;
2009       col_name = (gchar *)col_l_elt->data;
2010
2011       for (i = 0; i < num_capture_cols; i++) {
2012         if (strcmp(col_name, capture_cols[i])==0) {
2013           found_match = TRUE;
2014           break;
2015         }
2016       }
2017       if (!found_match) {
2018         /* One or more cols are invalid so use the entire list of valid cols. */
2019         for (i = 0; i < num_capture_cols; i++) {
2020           col_name = g_strdup(capture_cols[i]);
2021           prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2022         }
2023         pref->varp.list = &prefs.capture_columns;
2024         prefs_clear_string_list(col_l);
2025         return PREFS_SET_SYNTAX_ERR;
2026       }
2027       col_l_elt = col_l_elt->next;
2028     }
2029
2030     col_l_elt = g_list_first(col_l);
2031     while (col_l_elt) {
2032       col_name = (gchar *)col_l_elt->data;
2033       prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2034       col_l_elt = col_l_elt->next;
2035     }
2036     pref->varp.list = &prefs.capture_columns;
2037     g_list_free(col_l);
2038     return PREFS_SET_OK;
2039 }
2040
2041
2042 static const char *
2043 capture_column_type_name_cb(void)
2044 {
2045     return "Column list";
2046 }
2047
2048 static char *
2049 capture_column_type_description_cb(void)
2050 {
2051     return g_strdup(
2052         "List of columns to be displayed in the capture options dialog.\n"
2053         CAPTURE_COL_TYPE_DESCRIPTION);
2054 }
2055
2056 static gboolean
2057 capture_column_is_default_cb(pref_t* pref)
2058 {
2059     GList   *pref_col = g_list_first(prefs.capture_columns),
2060             *def_col = g_list_first(pref->default_val.list);
2061     gboolean is_default = TRUE;
2062
2063     /* See if the column data has changed from the default */
2064     while (pref_col && def_col) {
2065         if (strcmp((gchar *)pref_col->data, (gchar *)def_col->data) != 0) {
2066             is_default = FALSE;
2067             break;
2068         }
2069         pref_col = pref_col->next;
2070         def_col = def_col->next;
2071     }
2072
2073     /* Ensure the same column count */
2074     if (((pref_col == NULL) && (def_col != NULL)) ||
2075         ((pref_col != NULL) && (def_col == NULL)))
2076         is_default = FALSE;
2077
2078     return is_default;
2079 }
2080
2081 static char *
2082 capture_column_to_str_cb(pref_t* pref, gboolean default_val)
2083 {
2084
2085     GList       *pref_l = default_val ? pref->default_val.list : prefs.capture_columns;
2086     GList       *clp = g_list_first(pref_l);
2087     GList       *col_l = NULL;
2088     gchar       *col;
2089     char        *capture_column_str;
2090
2091     while (clp) {
2092         col = (gchar *) clp->data;
2093         col_l = g_list_append(col_l, g_strdup(col));
2094         clp = clp->next;
2095     }
2096
2097     capture_column_str = join_string_list(col_l);
2098     prefs_clear_string_list(col_l);
2099     return capture_column_str;
2100 }
2101
2102 static prefs_set_pref_e
2103 colorized_frame_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
2104 {
2105     prefs_set_string_like_value(pref, value, changed);
2106
2107     return PREFS_SET_OK;
2108 }
2109
2110 static const char *
2111 colorized_frame_type_name_cb(void)
2112 {
2113    /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
2114     * file until the colors can be changed in the GUI. Currently this is not really
2115     * possible since the STOCK-icons for these colors are hardcoded.
2116     *
2117     * XXX Find a way to change the colors of the STOCK-icons on the fly and then
2118     *     add these 10 colors to the list of colors that can be changed through
2119     *     the preferences.
2120     *
2121     */
2122     return NULL;
2123 }
2124
2125 static char *
2126 colorized_frame_type_description_cb(void)
2127 {
2128     return g_strdup("");
2129 }
2130
2131 static gboolean
2132 colorized_frame_is_default_cb(pref_t* pref _U_)
2133 {
2134     return TRUE;
2135 }
2136
2137 static char *
2138 colorized_frame_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
2139 {
2140     return g_strdup("");
2141 }
2142
2143 /*
2144  * Register all non-dissector modules' preferences.
2145  */
2146 static module_t *gui_module = NULL;
2147 static module_t *gui_color_module = NULL;
2148 static module_t *nameres_module = NULL;
2149
2150 static void
2151 prefs_register_modules(void)
2152 {
2153     module_t *printing, *capture_module, *console_module,
2154         *gui_layout_module, *gui_font_module;
2155 #ifdef HAVE_EXTCAP
2156     module_t *extcap_module;
2157 #endif
2158
2159     struct pref_custom_cbs custom_cbs;
2160
2161     if (protocols_module != NULL) {
2162         /* Already setup preferences */
2163         return;
2164     }
2165
2166 #ifdef HAVE_EXTCAP
2167     /* GUI
2168      * These are "simple" GUI preferences that can be read/written using the
2169      * preference module API.  These preferences still use their own
2170      * configuration screens for access, but this cuts down on the
2171      * preference "string compare list" in set_pref()
2172      */
2173     extcap_module = prefs_register_module(NULL, "extcap", "Extcap Utilities",
2174         "Extcap Utilities", NULL, FALSE);
2175
2176     /* Setting default value to true */
2177     prefs.extcap_save_on_start = TRUE;
2178     prefs_register_bool_preference(extcap_module, "gui_save_on_start",
2179                                    "Save arguments on start of capture",
2180                                    "Save arguments on start of capture",
2181                                    &prefs.extcap_save_on_start);
2182 #endif
2183
2184     /* GUI
2185      * These are "simple" GUI preferences that can be read/written using the
2186      * preference module API.  These preferences still use their own
2187      * configuration screens for access, but this cuts down on the
2188      * preference "string compare list" in set_pref()
2189      */
2190     gui_module = prefs_register_module(NULL, "gui", "User Interface",
2191         "User Interface", &gui_callback, FALSE);
2192
2193     /* gui.console_open is placed first in the list so that any problems encountered
2194      *  in the following prefs can be displayed in the console window.
2195      */
2196     prefs_register_enum_preference(gui_module, "console_open",
2197                        "Open a console window",
2198                        "Open a console window (Windows only)",
2199                        (gint*)(void*)(&prefs.gui_console_open), gui_console_open_type, FALSE);
2200
2201     prefs_register_obsolete_preference(gui_module, "scrollbar_on_right");
2202     prefs_register_obsolete_preference(gui_module, "packet_list_sel_browse");
2203     prefs_register_obsolete_preference(gui_module, "protocol_tree_sel_browse");
2204
2205     prefs_register_bool_preference(gui_module, "tree_view_altern_colors",
2206                                    "Alternating colors in TreeViews",
2207                                    "Alternating colors in TreeViews?",
2208                                    &prefs.gui_altern_colors);
2209
2210     prefs_register_bool_preference(gui_module, "expert_composite_eyecandy",
2211                                    "Display Icons on Expert Composite Dialog Tabs",
2212                                    "Display Icons on Expert Composite Dialog Tabs?",
2213                                    &prefs.gui_expert_composite_eyecandy);
2214
2215     prefs_register_bool_preference(gui_module, "filter_toolbar_show_in_statusbar",
2216                                    "Place filter toolbar inside the statusbar",
2217                                    "Place filter toolbar inside the statusbar?",
2218                                    &prefs.filter_toolbar_show_in_statusbar);
2219
2220     prefs_register_enum_preference(gui_module, "protocol_tree_line_style",
2221                        "Protocol-tree line style",
2222                        "Protocol-tree line style",
2223                        &prefs.gui_ptree_line_style, gui_ptree_line_style, FALSE);
2224
2225     prefs_register_enum_preference(gui_module, "protocol_tree_expander_style",
2226                        "Protocol-tree expander style",
2227                        "Protocol-tree expander style",
2228                        &prefs.gui_ptree_expander_style, gui_ptree_expander_style, FALSE);
2229
2230     prefs_register_enum_preference(gui_module, "hex_dump_highlight_style",
2231                        "Hex dump highlight style",
2232                        "Hex dump highlight style",
2233                        &prefs.gui_hex_dump_highlight_style, gui_hex_dump_highlight_style, FALSE);
2234
2235     gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL);
2236
2237     custom_cbs.free_cb = free_string_like_preference;
2238     custom_cbs.reset_cb = reset_string_like_preference;
2239     custom_cbs.set_cb = column_hidden_set_cb;
2240     custom_cbs.type_name_cb = column_hidden_type_name_cb;
2241     custom_cbs.type_description_cb = column_hidden_type_description_cb;
2242     custom_cbs.is_default_cb = column_hidden_is_default_cb;
2243     custom_cbs.to_str_cb = column_hidden_to_str_cb;
2244     register_string_like_preference(gui_column_module, PRS_COL_HIDDEN, "Packet list hidden columns",
2245         "List all columns to hide in the packet list",
2246         &cols_hidden_list, PREF_CUSTOM, &custom_cbs, FALSE);
2247
2248     custom_cbs.free_cb = column_format_free_cb;
2249     custom_cbs.reset_cb = column_format_reset_cb;
2250     custom_cbs.set_cb = column_format_set_cb;
2251     custom_cbs.type_name_cb = column_format_type_name_cb;
2252     custom_cbs.type_description_cb = column_format_type_description_cb;
2253     custom_cbs.is_default_cb = column_format_is_default_cb;
2254     custom_cbs.to_str_cb = column_format_to_str_cb;
2255
2256     prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT, "Packet list column format",
2257         "Each pair of strings consists of a column title and its format", &custom_cbs,
2258         column_format_init_cb, &prefs.col_list);
2259
2260     /* Number of columns.  This is only used internally and is not written to the
2261      * preference file
2262      */
2263     custom_cbs.free_cb = custom_pref_no_cb;
2264     custom_cbs.reset_cb = column_num_reset_cb;
2265     custom_cbs.set_cb = column_num_set_cb;
2266     custom_cbs.type_name_cb = column_num_type_name_cb;
2267     custom_cbs.type_description_cb = column_num_type_description_cb;
2268     custom_cbs.is_default_cb = column_num_is_default_cb;
2269     custom_cbs.to_str_cb = column_num_to_str_cb;
2270     prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM, "Number of columns",
2271         "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
2272
2273     /* User Interface : Font */
2274     gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL);
2275
2276     prefs_register_obsolete_preference(gui_font_module, "font_name");
2277
2278     register_string_like_preference(gui_font_module, "gtk2.font_name", "Font name",
2279         "Font name for packet list, protocol tree, and hex dump panes. (GTK+)",
2280         &prefs.gui_gtk2_font_name, PREF_STRING, NULL, TRUE);
2281
2282     register_string_like_preference(gui_font_module, "qt.font_name", "Font name",
2283         "Font name for packet list, protocol tree, and hex dump panes. (Qt)",
2284         &prefs.gui_qt_font_name, PREF_STRING, NULL, TRUE);
2285
2286     /* User Interface : Colors */
2287     gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL);
2288
2289     prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
2290         "Color preferences for a marked frame", &prefs.gui_marked_fg);
2291
2292     prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
2293         "Color preferences for a marked frame", &prefs.gui_marked_bg);
2294
2295     prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
2296         "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
2297
2298     prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
2299         "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
2300
2301     prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
2302         "TCP stream window color preference", &prefs.st_client_fg);
2303
2304     prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
2305         "TCP stream window color preference", &prefs.st_client_bg);
2306
2307     prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
2308         "TCP stream window color preference", &prefs.st_server_fg);
2309
2310     prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
2311         "TCP stream window color preference", &prefs.st_server_bg);
2312
2313     custom_cbs.free_cb = free_string_like_preference;
2314     custom_cbs.reset_cb = reset_string_like_preference;
2315     custom_cbs.set_cb = colorized_frame_set_cb;
2316     custom_cbs.type_name_cb = colorized_frame_type_name_cb;
2317     custom_cbs.type_description_cb = colorized_frame_type_description_cb;
2318     custom_cbs.is_default_cb = colorized_frame_is_default_cb;
2319     custom_cbs.to_str_cb = colorized_frame_to_str_cb;
2320     register_string_like_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
2321         "Filter Colorized Foreground",
2322         &prefs.gui_colorized_fg, PREF_CUSTOM, &custom_cbs, TRUE);
2323
2324     custom_cbs.free_cb = free_string_like_preference;
2325     custom_cbs.reset_cb = reset_string_like_preference;
2326     custom_cbs.set_cb = colorized_frame_set_cb;
2327     custom_cbs.type_name_cb = colorized_frame_type_name_cb;
2328     custom_cbs.type_description_cb = colorized_frame_type_description_cb;
2329     custom_cbs.is_default_cb = colorized_frame_is_default_cb;
2330     custom_cbs.to_str_cb = colorized_frame_to_str_cb;
2331     register_string_like_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
2332         "Filter Colorized Background",
2333         &prefs.gui_colorized_bg, PREF_CUSTOM, &custom_cbs, TRUE);
2334
2335     prefs_register_color_preference(gui_color_module, "color_filter_bg.valid", "Valid color filter background",
2336         "Valid color filter background", &prefs.gui_text_valid);
2337
2338     prefs_register_color_preference(gui_color_module, "color_filter_bg.invalid", "Invalid color filter background",
2339         "Invalid color filter background", &prefs.gui_text_invalid);
2340
2341     prefs_register_color_preference(gui_color_module, "color_filter_bg.deprecated", "Deprecated color filter background",
2342         "Deprecated color filter background", &prefs.gui_text_deprecated);
2343
2344     prefs_register_enum_preference(gui_module, "fileopen.style",
2345                        "Where to start the File Open dialog box",
2346                        "Where to start the File Open dialog box",
2347                        &prefs.gui_fileopen_style, gui_fileopen_style, FALSE);
2348
2349     prefs_register_uint_preference(gui_module, "recent_files_count.max",
2350                                    "The max. number of items in the open recent files list",
2351                                    "The max. number of items in the open recent files list",
2352                                    10,
2353                                    &prefs.gui_recent_files_count_max);
2354
2355     prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
2356                                    "The max. number of entries in the display filter list",
2357                                    "The max. number of entries in the display filter list",
2358                                    10,
2359                                    &prefs.gui_recent_df_entries_max);
2360
2361     register_string_like_preference(gui_module, "fileopen.dir", "Start Directory",
2362         "Directory to start in when opening File Open dialog.",
2363         &prefs.gui_fileopen_dir, PREF_DIRNAME, NULL, TRUE);
2364
2365     prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
2366
2367     prefs_register_uint_preference(gui_module, "fileopen.preview",
2368                                    "The preview timeout in the File Open dialog",
2369                                    "The preview timeout in the File Open dialog",
2370                                    10,
2371                                    &prefs.gui_fileopen_preview);
2372
2373     prefs_register_bool_preference(gui_module, "ask_unsaved",
2374                                    "Ask to save unsaved capture files",
2375                                    "Ask to save unsaved capture files?",
2376                                    &prefs.gui_ask_unsaved);
2377
2378     prefs_register_bool_preference(gui_module, "find_wrap",
2379                                    "Wrap to beginning/end of file during search",
2380                                    "Wrap to beginning/end of file during search?",
2381                                    &prefs.gui_find_wrap);
2382
2383     prefs_register_bool_preference(gui_module, "use_pref_save",
2384                                    "Settings dialogs use a save button",
2385                                    "Settings dialogs use a save button?",
2386                                    &prefs.gui_use_pref_save);
2387
2388     prefs_register_bool_preference(gui_module, "geometry.save.position",
2389                                    "Save window position at exit",
2390                                    "Save window position at exit?",
2391                                    &prefs.gui_geometry_save_position);
2392
2393     prefs_register_bool_preference(gui_module, "geometry.save.size",
2394                                    "Save window size at exit",
2395                                    "Save window size at exit?",
2396                                    &prefs.gui_geometry_save_size);
2397
2398     prefs_register_bool_preference(gui_module, "geometry.save.maximized",
2399                                    "Save window maximized state at exit",
2400                                    "Save window maximized state at exit?",
2401                                    &prefs.gui_geometry_save_maximized);
2402
2403     /* GTK+ only */
2404     prefs_register_bool_preference(gui_module, "macosx_style",
2405                                    "Use OS X style",
2406                                    "Use OS X style (OS X with native GTK only)?",
2407                                    &prefs.gui_macosx_style);
2408
2409     prefs_register_obsolete_preference(gui_module, "geometry.main.x");
2410     prefs_register_obsolete_preference(gui_module, "geometry.main.y");
2411     prefs_register_obsolete_preference(gui_module, "geometry.main.width");
2412     prefs_register_obsolete_preference(gui_module, "geometry.main.height");
2413     prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
2414
2415     prefs_register_enum_preference(gui_module, "toolbar_main_style",
2416                        "Main Toolbar style",
2417                        "Main Toolbar style",
2418                        &prefs.gui_toolbar_main_style, gui_toolbar_style, FALSE);
2419
2420     prefs_register_enum_preference(gui_module, "toolbar_filter_style",
2421                        "Filter Toolbar style",
2422                        "Filter Toolbar style",
2423                        &prefs.gui_toolbar_filter_style, gui_toolbar_style, FALSE);
2424
2425     register_string_like_preference(gui_module, "webbrowser", "The path to the webbrowser",
2426         "The path to the webbrowser (Ex: mozilla)",
2427         &prefs.gui_webbrowser, PREF_STRING, NULL, TRUE);
2428
2429     prefs_register_bool_preference(gui_module, "update.enabled",
2430                                    "Check for updates",
2431                                    "Check for updates (Windows only)",
2432                                    &prefs.gui_update_enabled);
2433
2434     prefs_register_enum_preference(gui_module, "update.channel",
2435                        "Update channel",
2436                        "The type of update to fetch. You should probably leave this set to UPDATE_CHANNEL_STABLE.",
2437                        (gint*)(void*)(&prefs.gui_update_channel), gui_update_channel, FALSE);
2438
2439     prefs_register_uint_preference(gui_module, "update.interval",
2440                                    "How often to check for software updates",
2441                                    "How often to check for software updates in seconds",
2442                                    10,
2443                                    &prefs.gui_update_interval);
2444
2445     register_string_like_preference(gui_module, "window_title", "Custom window title",
2446         "Custom window title to be appended to the existing title\n%P = profile name\n%V = version info",
2447         &prefs.gui_window_title, PREF_STRING, NULL, TRUE);
2448
2449     register_string_like_preference(gui_module, "prepend_window_title", "Custom window title prefix",
2450         "Custom window title to be prepended to the existing title\n%P = profile name\n%V = version info",
2451         &prefs.gui_prepend_window_title, PREF_STRING, NULL, TRUE);
2452
2453     register_string_like_preference(gui_module, "start_title", "Custom start page title",
2454         "Custom start page title",
2455         &prefs.gui_start_title, PREF_STRING, NULL, TRUE);
2456
2457     prefs_register_enum_preference(gui_module, "version_placement",
2458                        "Show version in the start page and/or main screen's title bar",
2459                        "Show version in the start page and/or main screen's title bar",
2460                        (gint*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, FALSE);
2461
2462     prefs_register_bool_preference(gui_module, "auto_scroll_on_expand",
2463                                    "Automatically scroll packet details",
2464                                    "When selecting a new packet, automatically scroll"
2465                                    "to the packet detail item that matches the most"
2466                                    "recently selected item",
2467                                    &prefs.gui_auto_scroll_on_expand);
2468
2469     prefs_register_uint_preference(gui_module, "auto_scroll_percentage",
2470                                    "Packet detail scroll percentage",
2471                                    "The percentage down the view the recently expanded detail item should be scrolled",
2472                                    10,
2473                                    &prefs.gui_auto_scroll_percentage);
2474
2475     /* User Interface : Layout */
2476     gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
2477
2478     prefs_register_uint_preference(gui_layout_module, "layout_type",
2479                                    "Layout type",
2480                                    "Layout type (1-6)",
2481                                    10,
2482                                    (guint*)(void*)(&prefs.gui_layout_type));
2483
2484     prefs_register_enum_preference(gui_layout_module, "layout_content_1",
2485                        "Layout content of the pane 1",
2486                        "Layout content of the pane 1",
2487                        (gint*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, FALSE);
2488
2489     prefs_register_enum_preference(gui_layout_module, "layout_content_2",
2490                        "Layout content of the pane 2",
2491                        "Layout content of the pane 2",
2492                        (gint*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, FALSE);
2493
2494     prefs_register_enum_preference(gui_layout_module, "layout_content_3",
2495                        "Layout content of the pane 3",
2496                        "Layout content of the pane 3",
2497                        (gint*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, FALSE);
2498
2499     prefs_register_bool_preference(gui_layout_module, "packet_list_separator.enabled",
2500                                    "Enable Packet List Separator",
2501                                    "Enable Packet List Separator",
2502                                    &prefs.gui_qt_packet_list_separator);
2503
2504     prefs_register_bool_preference(gui_module, "packet_editor.enabled",
2505                                    "Enable Packet Editor",
2506                                    "Enable Packet Editor (Experimental)",
2507                                    &prefs.gui_packet_editor);
2508
2509     prefs_register_enum_preference(gui_module, "packet_list_elide_mode",
2510                        "Elide mode",
2511                        "The position of \"...\" in packet list text.",
2512                        (gint*)(void*)(&prefs.gui_packet_list_elide_mode), gui_packet_list_elide_mode, FALSE);
2513
2514     prefs_register_bool_preference(gui_layout_module, "packet_list_show_related",
2515                                    "Show Related Packets",
2516                                    "Show related packet indicators in the first column",
2517                                    &prefs.gui_packet_list_show_related);
2518
2519     prefs_register_bool_preference(gui_layout_module, "packet_list_show_minimap",
2520                                    "Enable Intelligent Scroll Bar",
2521                                    "Show the intelligent scroll bar (a minimap of packet list colors in the scrollbar)",
2522                                    &prefs.gui_packet_list_show_minimap);
2523
2524
2525     prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
2526                                    "Show hidden interfaces",
2527                                    "Show all interfaces, including interfaces marked as hidden",
2528                                    &prefs.gui_interfaces_show_hidden);
2529
2530 #ifdef HAVE_PCAP_REMOTE
2531     prefs_register_bool_preference(gui_module, "interfaces_remote_display",
2532                                    "Show Remote interfaces",
2533                                    "Show remote interfaces in the interface selection",
2534                                    &prefs.gui_interfaces_remote_display);
2535 #endif
2536
2537     register_string_like_preference(gui_module, "interfaces_hidden_types", "Hide interface types in list",
2538         "Hide the given interface types in the startup list",
2539         &prefs.gui_interfaces_hide_types, PREF_STRING, NULL, TRUE);
2540
2541     /* Console
2542      * These are preferences that can be read/written using the
2543      * preference module API.  These preferences still use their own
2544      * configuration screens for access, but this cuts down on the
2545      * preference "string compare list" in set_pref()
2546      */
2547     console_module = prefs_register_module(NULL, "console", "Console",
2548         "Console logging and debugging output", NULL, FALSE);
2549
2550     custom_cbs.free_cb = custom_pref_no_cb;
2551     custom_cbs.reset_cb = console_log_level_reset_cb;
2552     custom_cbs.set_cb = console_log_level_set_cb;
2553     custom_cbs.type_name_cb = console_log_level_type_name_cb;
2554     custom_cbs.type_description_cb = console_log_level_type_description_cb;
2555     custom_cbs.is_default_cb = console_log_level_is_default_cb;
2556     custom_cbs.to_str_cb = console_log_level_to_str_cb;
2557     prefs_register_uint_custom_preference(console_module, "log.level", "logging level",
2558         "A bitmask of GLib log levels", &custom_cbs, &prefs.console_log_level);
2559
2560     prefs_register_bool_preference(console_module, "incomplete_dissectors_check_debug",
2561                                    "Print debug line for incomplete dissectors",
2562                                    "Look for dissectors that left some bytes undecoded (debug)",
2563                                    &prefs.incomplete_dissectors_check_debug);
2564
2565     /* Capture
2566      * These are preferences that can be read/written using the
2567      * preference module API.  These preferences still use their own
2568      * configuration screens for access, but this cuts down on the
2569      * preference "string compare list" in set_pref()
2570      */
2571     capture_module = prefs_register_module(NULL, "capture", "Capture",
2572         "Capture preferences", NULL, FALSE);
2573
2574     register_string_like_preference(capture_module, "device", "Default capture device",
2575         "Default capture device",
2576         &prefs.capture_device, PREF_STRING, NULL, FALSE);
2577
2578     register_string_like_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
2579         "Interface link-layer header types (Ex: en0(1),en1(143),...)",
2580         &prefs.capture_devices_linktypes, PREF_STRING, NULL, FALSE);
2581
2582     register_string_like_preference(capture_module, "devices_descr", "Interface descriptions",
2583         "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
2584         &prefs.capture_devices_descr, PREF_STRING, NULL, FALSE);
2585
2586     register_string_like_preference(capture_module, "devices_hide", "Hide interface",
2587         "Hide interface? (Ex: eth0,eth3,...)",
2588         &prefs.capture_devices_hide, PREF_STRING, NULL, FALSE);
2589
2590     register_string_like_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
2591         "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
2592         &prefs.capture_devices_monitor_mode, PREF_STRING, NULL, FALSE);
2593
2594 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
2595     register_string_like_preference(capture_module, "devices_buffersize", "Interface buffer size",
2596         "Interface buffer size (Ex: en0(1),en1(143),...)",
2597         &prefs.capture_devices_buffersize, PREF_STRING, NULL, FALSE);
2598 #endif
2599
2600     register_string_like_preference(capture_module, "devices_snaplen", "Interface snap length",
2601         "Interface snap length (Ex: en0(65535),en1(1430),...)",
2602         &prefs.capture_devices_snaplen, PREF_STRING, NULL, FALSE);
2603
2604     register_string_like_preference(capture_module, "devices_pmode", "Interface promiscuous mode",
2605         "Interface promiscuous mode (Ex: en0(0),en1(1),...)",
2606         &prefs.capture_devices_pmode, PREF_STRING, NULL, FALSE);
2607
2608     prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
2609         "Capture in promiscuous mode?", &prefs.capture_prom_mode);
2610
2611     register_string_like_preference(capture_module, "devices_filter", "Interface capture filter",
2612         "Interface capture filter (Ex: en0(tcp),en1(udp),...)",
2613         &prefs.capture_devices_filter, PREF_STRING, NULL, FALSE);
2614
2615     prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in Pcap-NG format",
2616         "Capture in Pcap-NG format?", &prefs.capture_pcap_ng);
2617
2618     prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
2619         "Update packet list in real time during capture?", &prefs.capture_real_time);
2620
2621     /* We might want to make this a "recent" setting. */
2622     prefs_register_bool_preference(capture_module, "auto_scroll", "Scroll packet list during capture",
2623         "Scroll packet list during capture?", &prefs.capture_auto_scroll);
2624
2625     /* GTK+ only */
2626     prefs_register_bool_preference(capture_module, "show_info", "Show capture info dialog while capturing",
2627         "Show capture info dialog while capturing?", &prefs.capture_show_info);
2628
2629     prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
2630
2631     custom_cbs.free_cb = capture_column_free_cb;
2632     custom_cbs.reset_cb = capture_column_reset_cb;
2633     custom_cbs.set_cb = capture_column_set_cb;
2634     custom_cbs.type_name_cb = capture_column_type_name_cb;
2635     custom_cbs.type_description_cb = capture_column_type_description_cb;
2636     custom_cbs.is_default_cb = capture_column_is_default_cb;
2637     custom_cbs.to_str_cb = capture_column_to_str_cb;
2638     prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
2639         "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
2640
2641     /* Name Resolution */
2642     nameres_module = prefs_register_module(NULL, "nameres", "Name Resolution",
2643         "Name Resolution", NULL, TRUE);
2644     addr_resolve_pref_init(nameres_module);
2645     oid_pref_init(nameres_module);
2646 #ifdef HAVE_GEOIP
2647     geoip_db_pref_init(nameres_module);
2648 #endif
2649
2650     /* Printing */
2651     printing = prefs_register_module(NULL, "print", "Printing",
2652         "Printing", NULL, TRUE);
2653
2654     prefs_register_enum_preference(printing, "format",
2655                                    "Format", "Can be one of \"text\" or \"postscript\"",
2656                                    &prefs.pr_format, print_format_vals, TRUE);
2657
2658     prefs_register_enum_preference(printing, "destination",
2659                                    "Print to", "Can be one of \"command\" or \"file\"",
2660                                    &prefs.pr_dest, print_dest_vals, TRUE);
2661
2662 #ifndef _WIN32
2663     register_string_like_preference(printing, "command", "Command",
2664         "Output gets piped to this command when the destination is set to \"command\"",
2665         &prefs.pr_cmd, PREF_STRING, NULL, TRUE);
2666 #endif
2667
2668     register_string_like_preference(printing, "file", "File",
2669         "This is the file that gets written to when the destination is set to \"file\"",
2670         &prefs.pr_file, PREF_FILENAME, NULL, TRUE);
2671
2672     /* Statistics */
2673     stats_module = prefs_register_module(NULL, "statistics", "Statistics",
2674         "Statistics", &stats_callback, TRUE);
2675
2676     prefs_register_uint_preference(stats_module, "update_interval",
2677                                    "Tap update interval in ms",
2678                                    "Determines time between tap updates",
2679                                    10,
2680                                    &prefs.tap_update_interval);
2681
2682 #ifdef HAVE_LIBPORTAUDIO
2683     prefs_register_uint_preference(stats_module, "rtp_player_max_visible",
2684                                    "Max visible channels in RTP Player",
2685                                    "Determines maximum height of RTP Player window",
2686                                    10,
2687                                    &prefs.rtp_player_max_visible);
2688 #endif
2689
2690     prefs_register_bool_preference(stats_module, "st_enable_burstinfo",
2691             "Enable the calculation of burst information",
2692             "If enabled burst rates will be calcuted for statistics that use the stats_tree system. "
2693             "Burst rates are calculated over a much shorter time interval than the rate column.",
2694             &prefs.st_enable_burstinfo);
2695
2696     prefs_register_bool_preference(stats_module, "st_burst_showcount",
2697             "Show burst count for item rather than rate",
2698             "If selected the stats_tree statistics nodes will show the count of events "
2699             "within the burst window instead of a burst rate. Burst rate is calculated "
2700             "as number of events within burst window divided by the burst windown length.",
2701             &prefs.st_burst_showcount);
2702
2703     prefs_register_uint_preference(stats_module, "st_burst_resolution",
2704             "Burst rate resolution (ms)",
2705             "Sets the duration of the time interval into which events are grouped when calculating "
2706             "the burst rate. Higher resolution (smaller number) increases processing overhead.",
2707             10,&prefs.st_burst_resolution);
2708
2709     prefs_register_uint_preference(stats_module, "st_burst_windowlen",
2710             "Burst rate window size (ms)",
2711             "Sets the duration of the sliding window during which the burst rate is "
2712             "measured. Longer window relative to burst rate resolution increases "
2713             "processing overhead. Will be truncated to a multiple of burst resolution.",
2714             10,&prefs.st_burst_windowlen);
2715
2716     prefs_register_enum_preference(stats_module, "st_sort_defcolflag",
2717             "Default sort column for stats_tree stats",
2718             "Sets the default column by which stats based on the stats_tree "
2719             "system is sorted.",
2720             &prefs.st_sort_defcolflag, st_sort_col_vals, FALSE);
2721
2722      prefs_register_bool_preference(stats_module, "st_sort_defdescending",
2723             "Default stats_tree sort order is descending",
2724             "When selected, statistics based on the stats_tree system will by default "
2725             "be sorted in descending order.",
2726             &prefs.st_sort_defdescending);
2727
2728      prefs_register_bool_preference(stats_module, "st_sort_casesensitve",
2729             "Case sensitive sort of stats_tree item names",
2730             "When selected, the item/node names of statistics based on the stats_tree "
2731             "system will be sorted taking case into account. Else the case of the name "
2732             "will be ignored.",
2733             &prefs.st_sort_casesensitve);
2734
2735      prefs_register_bool_preference(stats_module, "st_sort_rng_nameonly",
2736             "Always sort 'range' nodes by name",
2737             "When selected, the stats_tree nodes representing a range of values "
2738             "(0-49, 50-100, etc.) will always be sorted by name (the range of the "
2739             "node). Else range nodes are sorted by the same column as the rest of "
2740             " the tree.",
2741             &prefs.st_sort_rng_nameonly);
2742
2743      prefs_register_bool_preference(stats_module, "st_sort_rng_fixorder",
2744             "Always sort 'range' nodes in ascending order",
2745             "When selected, the stats_tree nodes representing a range of values "
2746             "(0-49, 50-100, etc.) will always be sorted ascending; else it follows "
2747             "the sort direction of the tree. Only effective if \"Always sort "
2748             "'range' nodes by name\" is also selected.",
2749             &prefs.st_sort_rng_fixorder);
2750
2751      prefs_register_bool_preference(stats_module, "st_sort_showfullname",
2752             "Display the full stats_tree plug-in name",
2753             "When selected, the full name (including menu path) of the stats_tree "
2754             "plug-in is show in windows. If cleared the plug-in name is shown "
2755             "without menu path (only the part of the name after last '/' character.)",
2756             &prefs.st_sort_showfullname);
2757
2758     /* Protocols */
2759     protocols_module = prefs_register_module(NULL, "protocols", "Protocols",
2760                                              "Protocols", NULL, TRUE);
2761
2762     prefs_register_bool_preference(protocols_module, "display_hidden_proto_items",
2763                                    "Display hidden protocol items",
2764                                    "Display all hidden protocol items in the packet list.",
2765                                    &prefs.display_hidden_proto_items);
2766
2767     prefs_register_bool_preference(protocols_module, "display_byte_fields_with_spaces",
2768                                    "Display byte fields with a space character between bytes",
2769                                    "Display all byte fields with a space character between each byte in the packet list.",
2770                                    &prefs.display_byte_fields_with_spaces);
2771
2772     prefs_register_bool_preference(protocols_module, "enable_incomplete_dissectors_check",
2773                                    "Look for incomplete dissectors",
2774                                    "Look for dissectors that left some bytes undecoded.",
2775                                    &prefs.enable_incomplete_dissectors_check);
2776
2777     /* Obsolete preferences
2778      * These "modules" were reorganized/renamed to correspond to their GUI
2779      * configuration screen within the preferences dialog
2780      */
2781
2782     /* taps is now part of the stats module */
2783     prefs_register_module(NULL, "taps", "TAPS", "TAPS", NULL, FALSE);
2784     /* packet_list is now part of the protocol (parent) module */
2785     prefs_register_module(NULL, "packet_list", "PACKET_LIST", "PACKET_LIST", NULL, FALSE);
2786     /* stream is now part of the gui module */
2787     prefs_register_module(NULL, "stream", "STREAM", "STREAM", NULL, FALSE);
2788
2789 }
2790
2791 /* Parse through a list of comma-separated, possibly quoted strings.
2792    Return a list of the string data. */
2793 GList *
2794 prefs_get_string_list(const gchar *str)
2795 {
2796     enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
2797
2798     gint      state = PRE_STRING, i = 0, j = 0;
2799     gboolean  backslash = FALSE;
2800     guchar    cur_c;
2801     gchar    *slstr = NULL;
2802     GList    *sl = NULL;
2803
2804     /* Allocate a buffer for the first string.   */
2805     slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2806     j = 0;
2807
2808     for (;;) {
2809         cur_c = str[i];
2810         if (cur_c == '\0') {
2811             /* It's the end of the input, so it's the end of the string we
2812                were working on, and there's no more input. */
2813             if (state == IN_QUOT || backslash) {
2814                 /* We were in the middle of a quoted string or backslash escape,
2815                    and ran out of characters; that's an error.  */
2816                 g_free(slstr);
2817                 prefs_clear_string_list(sl);
2818                 return NULL;
2819             }
2820             slstr[j] = '\0';
2821             sl = g_list_append(sl, slstr);
2822             break;
2823         }
2824         if (cur_c == '"' && ! backslash) {
2825             switch (state) {
2826             case PRE_STRING:
2827                 /* We hadn't yet started processing a string; this starts the
2828                    string, and we're now quoting.  */
2829                 state = IN_QUOT;
2830                 break;
2831             case IN_QUOT:
2832                 /* We're in the middle of a quoted string, and we saw a quotation
2833                    mark; we're no longer quoting.   */
2834                 state = NOT_IN_QUOT;
2835                 break;
2836             case NOT_IN_QUOT:
2837                 /* We're working on a string, but haven't seen a quote; we're
2838                    now quoting.  */
2839                 state = IN_QUOT;
2840                 break;
2841             default:
2842                 break;
2843             }
2844         } else if (cur_c == '\\' && ! backslash) {
2845             /* We saw a backslash, and the previous character wasn't a
2846                backslash; escape the next character.
2847
2848                This also means we've started a new string. */
2849             backslash = TRUE;
2850             if (state == PRE_STRING)
2851                 state = NOT_IN_QUOT;
2852         } else if (cur_c == ',' && state != IN_QUOT && ! backslash) {
2853             /* We saw a comma, and we're not in the middle of a quoted string
2854                and it wasn't preceded by a backslash; it's the end of
2855                the string we were working on...  */
2856             slstr[j] = '\0';
2857             sl = g_list_append(sl, slstr);
2858
2859             /* ...and the beginning of a new string.  */
2860             state = PRE_STRING;
2861             slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2862             j = 0;
2863         } else if (!g_ascii_isspace(cur_c) || state != PRE_STRING) {
2864             /* Either this isn't a white-space character, or we've started a
2865                string (i.e., already seen a non-white-space character for that
2866                string and put it into the string).
2867
2868                The character is to be put into the string; do so if there's
2869                room.  */
2870             if (j < COL_MAX_LEN) {
2871                 slstr[j] = cur_c;
2872                 j++;
2873             }
2874
2875             /* If it was backslash-escaped, we're done with the backslash escape.  */
2876             backslash = FALSE;
2877         }
2878         i++;
2879     }
2880     return(sl);
2881 }
2882
2883 char *join_string_list(GList *sl)
2884 {
2885     GString      *joined_str = g_string_new("");
2886     GList        *cur, *first;
2887     gchar        *str;
2888     gchar        *quoted_str;
2889     guint         item_count = 0;
2890
2891     cur = first = g_list_first(sl);
2892     while (cur) {
2893         item_count++;
2894         str = (gchar *)cur->data;
2895
2896         if (cur != first)
2897             g_string_append_c(joined_str, ',');
2898
2899         if (item_count % 2) {
2900             /* Wrap the line.  */
2901             g_string_append(joined_str, "\n\t");
2902         } else
2903             g_string_append_c(joined_str, ' ');
2904
2905         quoted_str = g_strescape(str, "");
2906         g_string_append_printf(joined_str, "\"%s\"", quoted_str);
2907         g_free(quoted_str);
2908
2909         cur = cur->next;
2910     }
2911     return g_string_free(joined_str, FALSE);
2912 }
2913
2914 void
2915 prefs_clear_string_list(GList *sl)
2916 {
2917     /* g_list_free_full() only exists since 2.28. */
2918     g_list_foreach(sl, (GFunc)g_free, NULL);
2919     g_list_free(sl);
2920 }
2921
2922 /*
2923  * Takes a string, a pointer to an array of "enum_val_t"s, and a default gint
2924  * value.
2925  * The array must be terminated by an entry with a null "name" string.
2926  *
2927  * If the string matches a "name" string in an entry, the value from that
2928  * entry is returned.
2929  *
2930  * Otherwise, if a string matches a "description" string in an entry, the
2931  * value from that entry is returned; we do that for backwards compatibility,
2932  * as we used to have only a "name" string that was used both for command-line
2933  * and configuration-file values and in the GUI (which meant either that
2934  * the GUI had what might be somewhat cryptic values to select from or that
2935  * the "-o" flag took long strings, often with spaces in them).
2936  *
2937  * Otherwise, the default value that was passed as the third argument is
2938  * returned.
2939  */
2940 static gint
2941 find_val_for_string(const char *needle, const enum_val_t *haystack,
2942                     gint default_value)
2943 {
2944     int i;
2945
2946     for (i = 0; haystack[i].name != NULL; i++) {
2947         if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
2948             return haystack[i].value;
2949         }
2950     }
2951     for (i = 0; haystack[i].name != NULL; i++) {
2952         if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
2953             return haystack[i].value;
2954         }
2955     }
2956     return default_value;
2957 }
2958
2959
2960 /* Array of columns that have been migrated to custom columns */
2961 struct deprecated_columns {
2962     const gchar *col_fmt;
2963     const gchar *col_expr;
2964 };
2965 static struct deprecated_columns migrated_columns[] = {
2966     { /* COL_COS_VALUE */ "%U", "vlan.priority" },
2967     { /* COL_CIRCUIT_ID */ "%c", "iax2.call" },
2968     { /* COL_BSSGP_TLLI */ "%l", "bssgp.tlli" },
2969     { /* COL_HPUX_SUBSYS */ "%H", "nettl.subsys" },
2970     { /* COL_HPUX_DEVID */ "%P", "nettl.devid" },
2971     { /* COL_FR_DLCI */ "%C", "fr.dlci" },
2972     { /* COL_REL_CONV_TIME */ "%rct", "tcp.time_relative" },
2973     { /* COL_DELTA_CONV_TIME */ "%dct", "tcp.time_delta" },
2974     { /* COL_OXID */ "%XO", "fc.ox_id" },
2975     { /* COL_RXID */ "%XR", "fc.rx_id" },
2976     { /* COL_SRCIDX */ "%Xd", "mdshdr.srcidx" },
2977     { /* COL_DSTIDX */ "%Xs", "mdshdr.dstidx" },
2978     { /* COL_DCE_CTX */ "%z", "dcerpc.cn_ctx_id" }
2979 };
2980
2981 static gboolean
2982 is_deprecated_column_format(const gchar* fmt)
2983 {
2984     guint haystack_idx;
2985
2986     for (haystack_idx = 0;
2987          haystack_idx < G_N_ELEMENTS(migrated_columns);
2988          ++haystack_idx) {
2989
2990         if (strcmp(migrated_columns[haystack_idx].col_fmt, fmt) == 0) {
2991             return TRUE;
2992         }
2993     }
2994
2995     return FALSE;
2996 }
2997
2998 /* Preferences file format:
2999  * - Configuration directives start at the beginning of the line, and
3000  *   are terminated with a colon.
3001  * - Directives can be continued on the next line by preceding them with
3002  *   whitespace.
3003  *
3004  * Example:
3005
3006 # This is a comment line
3007 print.command: lpr
3008 print.file: /a/very/long/path/
3009             to/wireshark-out.ps
3010  *
3011  */
3012
3013 #define DEF_NUM_COLS    7
3014
3015 /*
3016  * Parse a column format, filling in the relevant fields of a fmt_data.
3017  */
3018 static gboolean
3019 parse_column_format(fmt_data *cfmt, const char *fmt)
3020 {
3021     const gchar *cust_format = col_format_to_string(COL_CUSTOM);
3022     size_t cust_format_len = strlen(cust_format);
3023     gchar **cust_format_info;
3024     char *p;
3025     int col_fmt;
3026     gchar *col_custom_fields = NULL;
3027     long col_custom_occurrence = 0;
3028     gboolean col_resolved = TRUE;
3029
3030     /*
3031      * Is this a custom column?
3032      */
3033     if ((strlen(fmt) > cust_format_len) && (fmt[cust_format_len] == ':') &&
3034         strncmp(fmt, cust_format, cust_format_len) == 0) {
3035         /* Yes. */
3036         col_fmt = COL_CUSTOM;
3037         cust_format_info = g_strsplit(&fmt[cust_format_len+1],":",3); /* add 1 for ':' */
3038         col_custom_fields = g_strdup(cust_format_info[0]);
3039         if (col_custom_fields && cust_format_info[1]) {
3040             col_custom_occurrence = strtol(cust_format_info[1], &p, 10);
3041             if (p == cust_format_info[1] || *p != '\0') {
3042                 /* Not a valid number. */
3043                 g_free(col_custom_fields);
3044                 g_strfreev(cust_format_info);
3045                 return FALSE;
3046             }
3047         }
3048         if (col_custom_fields && cust_format_info[1] && cust_format_info[2]) {
3049             col_resolved = (cust_format_info[2][0] == 'U') ? FALSE : TRUE;
3050         }
3051         g_strfreev(cust_format_info);
3052     } else {
3053         col_fmt = get_column_format_from_str(fmt);
3054         if ((col_fmt == -1) && (!is_deprecated_column_format(fmt)))
3055             return FALSE;
3056     }
3057
3058     cfmt->fmt = col_fmt;
3059     cfmt->custom_fields = col_custom_fields;
3060     cfmt->custom_occurrence = (int)col_custom_occurrence;
3061     cfmt->resolved = col_resolved;
3062     return TRUE;
3063 }
3064
3065 /* Initialize non-dissector preferences to wired-in default values Called
3066  * at program startup and any time the profile changes. (The dissector
3067  * preferences are assumed to be set to those values by the dissectors.)
3068  * They may be overridden by the global preferences file or the user's
3069  * preferences file.
3070  */
3071 static void
3072 init_prefs(void)
3073 {
3074     if (prefs_initialized)
3075         return;
3076
3077     uat_load_all();
3078
3079     /*
3080      * Ensure the "global" preferences have been initialized so the
3081      * preference API has the proper default values to work from
3082      */
3083     pre_init_prefs();
3084
3085     prefs_register_modules();
3086
3087     filter_expression_init();
3088
3089     prefs_initialized = TRUE;
3090 }
3091
3092 /*
3093  * Initialize non-dissector preferences used by the "register preference" API
3094  * to default values so the default values can be used when registered.
3095  *
3096  * String, filename, and directory preferences will be g_freed so they must
3097  * be g_mallocated.
3098  */
3099 static void
3100 pre_init_prefs(void)
3101 {
3102     int         i;
3103     gchar       *col_name;
3104     fmt_data    *cfmt;
3105     static const gchar *col_fmt[DEF_NUM_COLS*2] = {
3106         "No.",      "%m", "Time",        "%t",
3107         "Source",   "%s", "Destination", "%d",
3108         "Protocol", "%p", "Length",      "%L",
3109         "Info",     "%i"};
3110
3111     prefs.pr_format  = PR_FMT_TEXT;
3112     prefs.pr_dest    = PR_DEST_CMD;
3113     if (prefs.pr_file) g_free(prefs.pr_file);
3114     prefs.pr_file    = g_strdup("wireshark.out");
3115     if (prefs.pr_cmd) g_free(prefs.pr_cmd);
3116     prefs.pr_cmd     = g_strdup("lpr");
3117
3118     prefs.gui_altern_colors = FALSE;
3119     prefs.gui_expert_composite_eyecandy = FALSE;
3120     prefs.gui_ptree_line_style = 0;
3121     prefs.gui_ptree_expander_style = 1;
3122     prefs.gui_hex_dump_highlight_style = 1;
3123     prefs.filter_toolbar_show_in_statusbar = FALSE;
3124     prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
3125     prefs.gui_toolbar_filter_style = TB_STYLE_TEXT;
3126     /* These will be g_freed, so they must be g_mallocated. */
3127     if (prefs.gui_gtk2_font_name) g_free(prefs.gui_gtk2_font_name);
3128 #ifdef _WIN32
3129     prefs.gui_gtk2_font_name         = g_strdup("Lucida Console 10");
3130 #else
3131     prefs.gui_gtk2_font_name         = g_strdup("Monospace 10");
3132 #endif
3133     /* We try to find the best font in the Qt code */
3134     if (prefs.gui_qt_font_name) g_free(prefs.gui_qt_font_name);
3135     prefs.gui_qt_font_name           = g_strdup("");
3136     prefs.gui_marked_fg.red          =     65535;
3137     prefs.gui_marked_fg.green        =     65535;
3138     prefs.gui_marked_fg.blue         =     65535;
3139     prefs.gui_marked_bg.red          =         0;
3140     prefs.gui_marked_bg.green        =      8224;
3141     prefs.gui_marked_bg.blue         =     10794;
3142     prefs.gui_ignored_fg.red         =     32767;
3143     prefs.gui_ignored_fg.green       =     32767;
3144     prefs.gui_ignored_fg.blue        =     32767;
3145     prefs.gui_ignored_bg.red         =     65535;
3146     prefs.gui_ignored_bg.green       =     65535;
3147     prefs.gui_ignored_bg.blue        =     65535;
3148     if (prefs.gui_colorized_fg) g_free(prefs.gui_colorized_fg);
3149     prefs.gui_colorized_fg           = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
3150     if (prefs.gui_colorized_bg) g_free(prefs.gui_colorized_bg);
3151     prefs.gui_colorized_bg           = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
3152     prefs.st_client_fg.red           = 32767;
3153     prefs.st_client_fg.green         =     0;
3154     prefs.st_client_fg.blue          =     0;
3155     prefs.st_client_bg.red           = 64507;
3156     prefs.st_client_bg.green         = 60909;
3157     prefs.st_client_bg.blue          = 60909;
3158     prefs.st_server_fg.red           =     0;
3159     prefs.st_server_fg.green         =     0;
3160     prefs.st_server_fg.blue          = 32767;
3161     prefs.st_server_bg.red           = 60909;
3162     prefs.st_server_bg.green         = 60909;
3163     prefs.st_server_bg.blue          = 64507;
3164     prefs.gui_text_valid.red         = 0xAFFF; /* light green */
3165     prefs.gui_text_valid.green       = 0xFFFF;
3166     prefs.gui_text_valid.blue        = 0xAFFF;
3167     prefs.gui_text_invalid.red       = 0xFFFF; /* light red */
3168     prefs.gui_text_invalid.green     = 0xAFFF;
3169     prefs.gui_text_invalid.blue      = 0xAFFF;
3170     prefs.gui_text_deprecated.red    = 0xFFFF; /* light yellow */
3171     prefs.gui_text_deprecated.green  = 0xFFFF;
3172     prefs.gui_text_deprecated.blue   = 0xAFFF;
3173     prefs.gui_geometry_save_position = TRUE;
3174     prefs.gui_geometry_save_size     = TRUE;
3175     prefs.gui_geometry_save_maximized= TRUE;
3176     prefs.gui_macosx_style           = TRUE;
3177     prefs.gui_console_open           = console_open_never;
3178     prefs.gui_fileopen_style         = FO_STYLE_LAST_OPENED;
3179     prefs.gui_recent_df_entries_max  = 10;
3180     prefs.gui_recent_files_count_max = 10;
3181     if (prefs.gui_fileopen_dir) g_free(prefs.gui_fileopen_dir);
3182     prefs.gui_fileopen_dir           = g_strdup(get_persdatafile_dir());
3183     prefs.gui_fileopen_preview       = 3;
3184     prefs.gui_ask_unsaved            = TRUE;
3185     prefs.gui_find_wrap              = TRUE;
3186     prefs.gui_use_pref_save          = FALSE;
3187     prefs.gui_update_enabled         = TRUE;
3188     prefs.gui_update_channel         = UPDATE_CHANNEL_STABLE;
3189     prefs.gui_update_interval        = 60*60*24; /* Seconds */
3190     if (prefs.gui_webbrowser) g_free(prefs.gui_webbrowser);
3191     prefs.gui_webbrowser             = g_strdup("");
3192     if (prefs.gui_window_title) g_free(prefs.gui_window_title);
3193     prefs.gui_window_title           = g_strdup("");
3194     if (prefs.gui_prepend_window_title) g_free(prefs.gui_prepend_window_title);
3195     prefs.gui_prepend_window_title   = g_strdup("");
3196     if (prefs.gui_start_title) g_free(prefs.gui_start_title);
3197     prefs.gui_start_title            = g_strdup("The World's Most Popular Network Protocol Analyzer");
3198     prefs.gui_version_placement      = version_both;
3199     prefs.gui_auto_scroll_on_expand  = FALSE;
3200     prefs.gui_auto_scroll_percentage = 0;
3201     prefs.gui_layout_type            = layout_type_5;
3202     prefs.gui_layout_content_1       = layout_pane_content_plist;
3203     prefs.gui_layout_content_2       = layout_pane_content_pdetails;
3204     prefs.gui_layout_content_3       = layout_pane_content_pbytes;
3205     prefs.gui_packet_editor          = FALSE;
3206     prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
3207     prefs.gui_packet_list_show_related = TRUE;
3208     prefs.gui_packet_list_show_minimap = TRUE;
3209     if (prefs.gui_interfaces_hide_types) g_free (prefs.gui_interfaces_hide_types);
3210     prefs.gui_interfaces_hide_types = g_strdup("");
3211     prefs.gui_interfaces_show_hidden = FALSE;
3212 #ifdef HAVE_PCAP_REMOTE
3213     prefs.gui_interfaces_remote_display = TRUE;
3214 #endif
3215
3216     prefs.gui_qt_packet_list_separator = FALSE;
3217
3218     if (prefs.col_list) {
3219         free_col_info(prefs.col_list);
3220         prefs.col_list = NULL;
3221     }
3222     for (i = 0; i < DEF_NUM_COLS; i++) {
3223         cfmt = g_new(fmt_data,1);
3224         cfmt->title = g_strdup(col_fmt[i * 2]);
3225         parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
3226         cfmt->visible = TRUE;
3227         cfmt->resolved = TRUE;
3228         cfmt->custom_fields = NULL;
3229         cfmt->custom_occurrence = 0;
3230         prefs.col_list = g_list_append(prefs.col_list, cfmt);
3231     }
3232     prefs.num_cols  = DEF_NUM_COLS;
3233
3234 /* set the default values for the capture dialog box */
3235     prefs.capture_prom_mode             = TRUE;
3236 #ifdef PCAP_NG_DEFAULT
3237     prefs.capture_pcap_ng               = TRUE;
3238 #else
3239     prefs.capture_pcap_ng               = FALSE;
3240 #endif
3241     prefs.capture_real_time             = TRUE;
3242     prefs.capture_auto_scroll           = TRUE;
3243     prefs.capture_show_info             = FALSE;
3244
3245     if (!prefs.capture_columns) {
3246         /* First time through */
3247         for (i = 0; i < num_capture_cols; i++) {
3248             col_name = g_strdup(capture_cols[i]);
3249             prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3250         }
3251     }
3252
3253     prefs.console_log_level          =
3254         G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
3255
3256 /* set the default values for the tap/statistics dialog box */
3257     prefs.tap_update_interval    = TAP_UPDATE_DEFAULT_INTERVAL;
3258     prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
3259     prefs.st_enable_burstinfo = TRUE;
3260     prefs.st_burst_showcount = FALSE;
3261     prefs.st_burst_resolution = ST_DEF_BURSTRES;
3262     prefs.st_burst_windowlen = ST_DEF_BURSTLEN;
3263     prefs.st_sort_casesensitve = TRUE;
3264     prefs.st_sort_rng_fixorder = TRUE;
3265     prefs.st_sort_rng_nameonly = TRUE;
3266     prefs.st_sort_defcolflag = ST_SORT_COL_COUNT;
3267     prefs.st_sort_defdescending = TRUE;
3268     prefs.st_sort_showfullname = FALSE;
3269     prefs.display_hidden_proto_items = FALSE;
3270     prefs.display_byte_fields_with_spaces = FALSE;
3271 }
3272
3273 /*
3274  * Reset a single dissector preference.
3275  */
3276 static void
3277 reset_pref(pref_t *pref)
3278 {
3279     int type;
3280     if (!pref) return;
3281
3282     type = pref->type;
3283
3284     /*
3285      * This preference is no longer supported; it's not a
3286      * real preference, so we don't reset it (i.e., we
3287      * treat it as if it weren't found in the list of
3288      * preferences, and we weren't called in the first place).
3289      */
3290     if (IS_PREF_OBSOLETE(type))
3291         return;
3292     else
3293         RESET_PREF_OBSOLETE(type);
3294
3295     switch (type) {
3296
3297     case PREF_UINT:
3298     case PREF_DECODE_AS_UINT:
3299         *pref->varp.uint = pref->default_val.uint;
3300         break;
3301
3302     case PREF_BOOL:
3303         *pref->varp.boolp = pref->default_val.boolval;
3304         break;
3305
3306     case PREF_ENUM:
3307         /*
3308          * For now, we save the "description" value, so that if we
3309          * save the preferences older versions of Wireshark can at
3310          * least read preferences that they supported; we support
3311          * either the short name or the description when reading
3312          * the preferences file or a "-o" option.
3313          */
3314         *pref->varp.enump = pref->default_val.enumval;
3315         break;
3316
3317     case PREF_STRING:
3318     case PREF_FILENAME:
3319     case PREF_DIRNAME:
3320         reset_string_like_preference(pref);
3321         break;
3322
3323     case PREF_RANGE:
3324     case PREF_DECODE_AS_RANGE:
3325         g_free(*pref->varp.range);
3326         *pref->varp.range = range_copy(pref->default_val.range);
3327         break;
3328
3329     case PREF_STATIC_TEXT:
3330     case PREF_UAT:
3331         /* Nothing to do */
3332         break;
3333
3334     case PREF_COLOR:
3335         *pref->varp.colorp = pref->default_val.color;
3336         break;
3337
3338     case PREF_CUSTOM:
3339         pref->custom_cbs.reset_cb(pref);
3340         break;
3341     }
3342 }
3343
3344 static void
3345 reset_pref_cb(gpointer data, gpointer user_data _U_)
3346 {
3347     pref_t *pref = (pref_t *) data;
3348     reset_pref(pref);
3349 }
3350
3351 typedef struct {
3352     module_t *module;
3353 } reset_pref_arg_t;
3354
3355 /*
3356  * Reset all preferences for a module.
3357  */
3358 static gboolean
3359 reset_module_prefs(const void *key _U_, void *value, void *data _U_)
3360 {
3361     reset_pref_arg_t arg;
3362
3363     arg.module = (module_t *)value;
3364     g_list_foreach(arg.module->prefs, reset_pref_cb, &arg);
3365     return FALSE;
3366 }
3367
3368 /* Reset preferences */
3369 void
3370 prefs_reset(void)
3371 {
3372     prefs_initialized = FALSE;
3373     g_free(prefs.saved_at_version);
3374     prefs.saved_at_version = NULL;
3375
3376     /*
3377      * Unload all UAT preferences.
3378      */
3379     uat_unload_all();
3380
3381     /*
3382      * Unload any loaded MIBs.
3383      */
3384     oids_cleanup();
3385
3386     /*
3387      * Free the filter expression list.
3388      */
3389     filter_expression_free(*pfilter_expression_head);
3390     *pfilter_expression_head = NULL;
3391
3392     /*
3393      * Reset the non-dissector preferences.
3394      */
3395     init_prefs();
3396
3397     /*
3398      * Reset the non-UAT dissector preferences.
3399      */
3400     wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL);
3401 }
3402
3403 /* Read the preferences file, fill in "prefs", and return a pointer to it.
3404
3405    If we got an error (other than "it doesn't exist") trying to read
3406    the global preferences file, stuff the errno into "*gpf_errno_return"
3407    and a pointer to the path of the file into "*gpf_path_return", and
3408    return NULL.
3409
3410    If we got an error (other than "it doesn't exist") trying to read
3411    the user's preferences file, stuff the errno into "*pf_errno_return"
3412    and a pointer to the path of the file into "*pf_path_return", and
3413    return NULL. */
3414 e_prefs *
3415 read_prefs(int *gpf_errno_return, int *gpf_read_errno_return,
3416            char **gpf_path_return, int *pf_errno_return,
3417            int *pf_read_errno_return, char **pf_path_return)
3418 {
3419     int         err;
3420     char        *pf_path;
3421     FILE        *pf;
3422
3423     /* clean up libsmi structures before reading prefs */
3424     oids_cleanup();
3425
3426     init_prefs();
3427
3428     /*
3429      * If we don't already have the pathname of the global preferences
3430      * file, construct it.  Then, in either case, try to open the file.
3431      */
3432     if (gpf_path == NULL) {
3433         /*
3434          * We don't have the path; try the new path first, and, if that
3435          * file doesn't exist, try the old path.
3436          */
3437         gpf_path = get_datafile_path(PF_NAME);
3438         if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
3439             /*
3440              * It doesn't exist by the new name; try the old name.
3441              */
3442             g_free(gpf_path);
3443             gpf_path = get_datafile_path(OLD_GPF_NAME);
3444             pf = ws_fopen(gpf_path, "r");
3445         }
3446     } else {
3447         /*
3448          * We have the path; try it.
3449          */
3450         pf = ws_fopen(gpf_path, "r");
3451     }
3452
3453     /*
3454      * If we were able to open the file, read it.
3455      * XXX - if it failed for a reason other than "it doesn't exist",
3456      * report the error.
3457      */
3458     *gpf_path_return = NULL;
3459     if (pf != NULL) {
3460         /*
3461          * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
3462          * seen.
3463          */
3464         mgcp_tcp_port_count = 0;
3465         mgcp_udp_port_count = 0;
3466
3467         /* We succeeded in opening it; read it. */
3468         err = read_prefs_file(gpf_path, pf, set_pref, NULL);
3469         if (err != 0) {
3470             /* We had an error reading the file; return the errno and the
3471                pathname, so our caller can report the error. */
3472             *gpf_errno_return = 0;
3473             *gpf_read_errno_return = err;
3474             *gpf_path_return = gpf_path;
3475         }
3476         fclose(pf);
3477     } else {
3478         /* We failed to open it.  If we failed for some reason other than
3479            "it doesn't exist", return the errno and the pathname, so our
3480            caller can report the error. */
3481         if (errno != ENOENT) {
3482             *gpf_errno_return = errno;
3483             *gpf_read_errno_return = 0;
3484             *gpf_path_return = gpf_path;
3485         }
3486     }
3487
3488     /* Construct the pathname of the user's preferences file. */
3489     pf_path = get_persconffile_path(PF_NAME, TRUE);
3490
3491     /* Read the user's preferences file, if it exists. */
3492     *pf_path_return = NULL;
3493     if ((pf = ws_fopen(pf_path, "r")) != NULL) {
3494         /*
3495          * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
3496          * seen.
3497          */
3498         mgcp_tcp_port_count = 0;
3499         mgcp_udp_port_count = 0;
3500
3501         /* We succeeded in opening it; read it. */
3502         err = read_prefs_file(pf_path, pf, set_pref, NULL);
3503         if (err != 0) {
3504             /* We had an error reading the file; return the errno and the
3505                pathname, so our caller can report the error. */
3506             *pf_errno_return = 0;
3507             *pf_read_errno_return = err;
3508             *pf_path_return = pf_path;
3509         } else
3510             g_free(pf_path);
3511         fclose(pf);
3512     } else {
3513         /* We failed to open it.  If we failed for some reason other than
3514            "it doesn't exist", return the errno and the pathname, so our
3515            caller can report the error. */
3516         if (errno != ENOENT) {
3517             *pf_errno_return = errno;
3518             *pf_read_errno_return = 0;
3519             *pf_path_return = pf_path;
3520         } else
3521             g_free(pf_path);
3522     }
3523
3524     /* load SMI modules if needed */
3525     oids_init();
3526
3527     return &prefs;
3528 }
3529
3530 /* read the preferences file (or similar) and call the callback
3531  * function to set each key/value pair found */
3532 int
3533 read_prefs_file(const char *pf_path, FILE *pf,
3534                 pref_set_pair_cb pref_set_pair_fct, void *private_data)
3535 {
3536     enum {
3537         START,    /* beginning of a line */
3538         IN_VAR,   /* processing key name */
3539         PRE_VAL,  /* finished processing key name, skipping white space befor evalue */
3540         IN_VAL,   /* processing value */
3541         IN_SKIP   /* skipping to the end of the line */
3542     } state = START;
3543     int       got_c;
3544     GString  *cur_val;
3545     GString  *cur_var;
3546     gboolean  got_val = FALSE;
3547     gint      fline = 1, pline = 1;
3548     gchar     hint[] = "(save preferences to remove this warning)";
3549     gchar     ver[128];
3550
3551     cur_val = g_string_new("");
3552     cur_var = g_string_new("");
3553
3554     /* Try to read in the profile name in the first line of the preferences file. */
3555     if (fscanf(pf, "# Configuration file for %127[^\r\n]", ver) == 1) {
3556         /* Assume trailing period and remove it */
3557         g_free(prefs.saved_at_version);
3558         prefs.saved_at_version = g_strndup(ver, strlen(ver) - 1);
3559     }
3560     rewind(pf);
3561
3562     while ((got_c = ws_getc_unlocked(pf)) != EOF) {
3563         if (got_c == '\r') {
3564             /* Treat CR-LF at the end of a line like LF, so that if we're reading
3565              * a Windows-format file on UN*X, we handle it the same way we'd handle
3566              * a UN*X-format file. */
3567             got_c = ws_getc_unlocked(pf);
3568             if (got_c == EOF)
3569                 break;
3570             if (got_c != '\n') {
3571                 /* Put back the character after the CR, and process the CR normally. */
3572                 ungetc(got_c, pf);
3573                 got_c = '\r';
3574             }
3575         }
3576         if (got_c == '\n') {
3577             state = START;
3578             fline++;
3579             continue;
3580         }
3581
3582         switch (state) {
3583         case START:
3584             if (g_ascii_isalnum(got_c)) {
3585                 if (cur_var->len > 0) {
3586                     if (got_val) {
3587                         if (cur_val->len > 0) {
3588                             if (cur_val->str[cur_val->len-1] == ',') {
3589                                 /*
3590                                  * If the pref has a trailing comma, eliminate it.
3591                                  */
3592                                 cur_val->str[cur_val->len-1] = '\0';
3593                                 ws_g_warning ("%s line %d: trailing comma in \"%s\" %s", pf_path, pline, cur_var->str, hint);
3594                             }
3595                         }
3596                         /* Call the routine to set the preference; it will parse
3597                            the value as appropriate.
3598
3599                            Since we're reading a file, rather than processing
3600                            explicit user input, for range preferences, silently
3601                            lower values in excess of the range's maximum, rather
3602                            than reporting errors and failing. */
3603                         switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
3604
3605                         case PREFS_SET_OK:
3606                             break;
3607
3608                         case PREFS_SET_SYNTAX_ERR:
3609                             ws_g_warning ("Syntax error in preference \"%s\" at line %d of\n%s %s",
3610                                        cur_var->str, pline, pf_path, hint);
3611                             break;
3612
3613                         case PREFS_SET_NO_SUCH_PREF:
3614                             /*
3615                              * If "print.command" silently ignore it because it's valid
3616                              * on non-Win32 platforms.
3617                              */
3618                             if (strcmp(cur_var->str, "print.command") != 0)
3619                                 ws_g_warning ("No such preference \"%s\" at line %d of\n%s %s",
3620                                            cur_var->str, pline, pf_path, hint);
3621                             prefs.unknown_prefs = TRUE;
3622                             break;
3623
3624                         case PREFS_SET_OBSOLETE:
3625                             if (strcmp(cur_var->str, "print.command") != 0)
3626                                 /* If an attempt is made to save the preferences, a popup warning will be
3627                                    displayed stating that obsolete prefs have been detected and the user will
3628                                    be given the opportunity to save these prefs under a different profile name.
3629                                    The prefs in question need to be listed in the console window so that the
3630                                    user can make an informed choice.
3631                                 */
3632                                 ws_g_warning ("Obsolete preference \"%s\" at line %d of\n%s %s",
3633                                            cur_var->str, pline, pf_path, hint);
3634                             prefs.unknown_prefs = TRUE;
3635                             break;
3636                         }
3637                     } else {
3638                         ws_g_warning ("Incomplete preference at line %d: of\n%s %s", pline, pf_path, hint);
3639                     }
3640                 }
3641                 state      = IN_VAR;
3642                 got_val    = FALSE;
3643                 g_string_truncate(cur_var, 0);
3644                 g_string_append_c(cur_var, (gchar) got_c);
3645                 pline = fline;
3646             } else if (g_ascii_isspace(got_c) && cur_var->len > 0 && got_val) {
3647                 state = PRE_VAL;
3648             } else if (got_c == '#') {
3649                 state = IN_SKIP;
3650             } else {
3651                 ws_g_warning ("Malformed preference at line %d of\n%s %s", fline, pf_path, hint);
3652             }
3653             break;
3654         case IN_VAR:
3655             if (got_c != ':') {
3656                 g_string_append_c(cur_var, (gchar) got_c);
3657             } else {
3658                 /* This is a colon (':') */
3659                 state   = PRE_VAL;
3660                 g_string_truncate(cur_val, 0);
3661                 /*
3662                  * Set got_val to TRUE to accommodate prefs such as
3663                  * "gui.fileopen.dir" that do not require a value.
3664                  */
3665                 got_val = TRUE;
3666             }
3667             break;
3668         case PRE_VAL:
3669             if (!g_ascii_isspace(got_c)) {
3670                 state = IN_VAL;
3671                 g_string_append_c(cur_val, (gchar) got_c);
3672             }
3673             break;
3674         case IN_VAL:
3675             g_string_append_c(cur_val, (gchar) got_c);
3676             break;
3677         case IN_SKIP:
3678             break;
3679         }
3680     }
3681     if (cur_var->len > 0) {
3682         if (got_val) {
3683             /* Call the routine to set the preference; it will parse
3684                the value as appropriate.
3685
3686                Since we're reading a file, rather than processing
3687                explicit user input, for range preferences, silently
3688                lower values in excess of the range's maximum, rather
3689                than reporting errors and failing. */
3690             switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
3691
3692             case PREFS_SET_OK:
3693                 break;
3694
3695             case PREFS_SET_SYNTAX_ERR:
3696                 ws_g_warning ("Syntax error in preference %s at line %d of\n%s %s",
3697                            cur_var->str, pline, pf_path, hint);
3698                 break;
3699
3700             case PREFS_SET_NO_SUCH_PREF:
3701                 ws_g_warning ("No such preference \"%s\" at line %d of\n%s %s",
3702                            cur_var->str, pline, pf_path, hint);
3703                 prefs.unknown_prefs = TRUE;
3704                 break;
3705
3706             case PREFS_SET_OBSOLETE:
3707                 prefs.unknown_prefs = TRUE;
3708                 break;
3709             }
3710         } else {
3711             ws_g_warning("Incomplete preference at line %d of\n%s %s",
3712                        pline, pf_path, hint);
3713         }
3714     }
3715
3716     g_string_free(cur_val, TRUE);
3717     g_string_free(cur_var, TRUE);
3718
3719     if (ferror(pf))
3720         return errno;
3721     else
3722         return 0;
3723 }
3724
3725 /*
3726  * If we were handed a preference starting with "uat:", try to turn it into
3727  * a valid uat entry.
3728  */
3729 static gboolean
3730 prefs_set_uat_pref(char *uat_entry) {
3731     gchar *p, *colonp;
3732     uat_t *uat;
3733     gchar *err = NULL;
3734     gboolean ret;
3735
3736     colonp = strchr(uat_entry, ':');
3737     if (colonp == NULL)
3738         return FALSE;
3739
3740     p = colonp;
3741     *p++ = '\0';
3742
3743     /*
3744      * Skip over any white space (there probably won't be any, but
3745      * as we allow it in the preferences file, we might as well
3746      * allow it here).
3747      */
3748     while (g_ascii_isspace(*p))
3749         p++;
3750     if (*p == '\0') {
3751         /*
3752          * Put the colon back, so if our caller uses, in an
3753          * error message, the string they passed us, the message
3754          * looks correct.
3755          */
3756         *colonp = ':';
3757         return FALSE;
3758     }
3759
3760     uat = uat_find(uat_entry);
3761     *colonp = ':';
3762     if (uat == NULL) {
3763         return FALSE;
3764     }
3765
3766     ret = uat_load_str(uat, p, &err);
3767     g_free(err);
3768     return ret;
3769 }
3770
3771 /*
3772  * Given a string of the form "<pref name>:<pref value>", as might appear
3773  * as an argument to a "-o" option, parse it and set the preference in
3774  * question.  Return an indication of whether it succeeded or failed
3775  * in some fashion.
3776  */
3777 prefs_set_pref_e
3778 prefs_set_pref(char *prefarg)
3779 {
3780     gchar *p, *colonp;
3781     prefs_set_pref_e ret;
3782
3783     /*
3784      * Set the counters of "mgcp.{tcp,udp}.port" entries we've
3785      * seen to values that keep us from trying to interpret them
3786      * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
3787      * as, from the command line, we have no way of guessing which
3788      * the user had in mind.
3789      */
3790     mgcp_tcp_port_count = -1;
3791     mgcp_udp_port_count = -1;
3792
3793     colonp = strchr(prefarg, ':');
3794     if (colonp == NULL)
3795         return PREFS_SET_SYNTAX_ERR;
3796
3797     p = colonp;
3798     *p++ = '\0';
3799
3800     /*
3801      * Skip over any white space (there probably won't be any, but
3802      * as we allow it in the preferences file, we might as well
3803      * allow it here).
3804      */
3805     while (g_ascii_isspace(*p))
3806         p++;
3807     if (*p == '\0') {
3808         /*
3809          * Put the colon back, so if our caller uses, in an
3810          * error message, the string they passed us, the message
3811          * looks correct.
3812          */
3813         *colonp = ':';
3814         return PREFS_SET_SYNTAX_ERR;
3815     }
3816     if (strcmp(prefarg, "uat")) {
3817         ret = set_pref(prefarg, p, NULL, TRUE);
3818     } else {
3819         ret = prefs_set_uat_pref(p) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
3820     }
3821     *colonp = ':';    /* put the colon back */
3822     return ret;
3823 }
3824
3825 guint prefs_get_uint_value(const char *module_name, const char* pref_name)
3826 {
3827     pref_t *pref = prefs_find_preference(prefs_find_module(module_name), pref_name);
3828     g_assert(pref != NULL);
3829
3830     return *pref->varp.uint;
3831 }
3832
3833 range_t* prefs_get_range_value(const char *module_name, const char* pref_name)
3834 {
3835     pref_t *pref = prefs_find_preference(prefs_find_module(module_name), pref_name);
3836     g_assert(pref != NULL);
3837
3838     return range_copy(*pref->varp.range);
3839 }
3840
3841 /*
3842  * Returns TRUE if the given device is hidden
3843  */
3844 gboolean
3845 prefs_is_capture_device_hidden(const char *name)
3846 {
3847     gchar *tok, *devices;
3848     size_t len;
3849
3850     if (prefs.capture_devices_hide && name) {
3851         devices = g_strdup (prefs.capture_devices_hide);
3852         len = strlen (name);
3853         for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
3854             if (strlen (tok) == len && strcmp (name, tok) == 0) {
3855                 g_free (devices);
3856                 return TRUE;
3857             }
3858         }
3859         g_free (devices);
3860     }
3861
3862     return FALSE;
3863 }
3864
3865 /*
3866  * Returns TRUE if the given column is visible (not hidden)
3867  */
3868 static gboolean
3869 prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt)
3870 {
3871     gchar *tok, *cols;
3872     fmt_data cfmt_hidden;
3873
3874     /*
3875      * Do we have a list of hidden columns?
3876      */
3877     if (cols_hidden) {
3878         /*
3879          * Yes - check the column against each of the ones in the
3880          * list.
3881          */
3882         cols = g_strdup(cols_hidden);
3883         for (tok = strtok(cols, ","); tok; tok = strtok(NULL, ",")) {
3884             tok = g_strstrip(tok);
3885
3886             /*
3887              * Parse this column format.
3888              */
3889             if (!parse_column_format(&cfmt_hidden, tok)) {
3890                 /*
3891                  * It's not valid; ignore it.
3892                  */
3893                 continue;
3894             }
3895
3896             /*
3897              * Does it match the column?
3898              */
3899             if (cfmt->fmt != cfmt_hidden.fmt) {
3900                 /* No. */
3901                 g_free(cfmt_hidden.custom_fields);
3902                 cfmt_hidden.custom_fields = NULL;
3903                 continue;
3904             }
3905             if (cfmt->fmt == COL_CUSTOM) {
3906                 /*
3907                  * A custom column has to have the
3908                  * same custom field and occurrence.
3909                  */
3910                 if (cfmt_hidden.custom_fields && cfmt->custom_fields) {
3911                     if (strcmp(cfmt->custom_fields,
3912                                cfmt_hidden.custom_fields) != 0) {
3913                         /* Different fields. */
3914                         g_free(cfmt_hidden.custom_fields);
3915                         cfmt_hidden.custom_fields = NULL;
3916                         continue;
3917                     }
3918                     if (cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) {
3919                         /* Different occurrences. */
3920                         g_free(cfmt_hidden.custom_fields);
3921                         cfmt_hidden.custom_fields = NULL;
3922                         continue;
3923                     }
3924                 }
3925             }
3926
3927             /*
3928              * OK, they match, so it's one of the hidden fields,
3929              * hence not visible.
3930              */
3931             g_free(cfmt_hidden.custom_fields);
3932             g_free(cols);
3933             return FALSE;
3934         }
3935         g_free(cols);
3936     }
3937
3938     /*
3939      * No - either there are no hidden columns or this isn't one
3940      * of them - so it is visible.
3941      */
3942     return TRUE;
3943 }
3944
3945 /*
3946  * Returns TRUE if the given device should capture in monitor mode by default
3947  */
3948 gboolean
3949 prefs_capture_device_monitor_mode(const char *name)
3950 {
3951     gchar *tok, *devices;
3952     size_t len;
3953
3954     if (prefs.capture_devices_monitor_mode && name) {
3955         devices = g_strdup (prefs.capture_devices_monitor_mode);
3956         len = strlen (name);
3957         for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
3958             if (strlen (tok) == len && strcmp (name, tok) == 0) {
3959                 g_free (devices);
3960                 return TRUE;
3961             }
3962         }
3963         g_free (devices);
3964     }
3965
3966     return FALSE;
3967 }
3968
3969 /*
3970  * Returns TRUE if the user has marked this column as visible
3971  */
3972 gboolean
3973 prefs_capture_options_dialog_column_is_visible(const gchar *column)
3974 {
3975     GList *curr;
3976     gchar *col;
3977
3978     for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)) {
3979         col = (gchar *)curr->data;
3980         if (col && (g_ascii_strcasecmp(col, column) == 0)) {
3981             return TRUE;
3982         }
3983     }
3984     return FALSE;
3985 }
3986
3987 #define PRS_GUI_FILTER_LABEL             "gui.filter_expressions.label"
3988 #define PRS_GUI_FILTER_EXPR              "gui.filter_expressions.expr"
3989 #define PRS_GUI_FILTER_ENABLED           "gui.filter_expressions.enabled"
3990
3991 /*
3992  * Extract the red, green, and blue components of a 24-bit RGB value
3993  * and convert them from [0,255] to [0,65535].
3994  */
3995 #define RED_COMPONENT(x)   (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
3996 #define GREEN_COMPONENT(x) (guint16) (((((x) >>  8) & 0xff) * 65535 / 255))
3997 #define BLUE_COMPONENT(x)  (guint16) ( (((x)        & 0xff) * 65535 / 255))
3998
3999 char
4000 string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
4001 {
4002     char c;
4003
4004     memset(name_resolve, 0, sizeof(e_addr_resolve));
4005     while ((c = *string++) != '\0') {
4006         switch (c) {
4007         case 'm':
4008             name_resolve->mac_name = TRUE;
4009             break;
4010         case 'n':
4011             name_resolve->network_name = TRUE;
4012             break;
4013         case 'N':
4014             name_resolve->use_external_net_name_resolver = TRUE;
4015             break;
4016         case 't':
4017             name_resolve->transport_name = TRUE;
4018             break;
4019         case 'C':
4020             /* DEPRECATED */
4021             /* name_resolve->concurrent_dns */
4022             break;
4023         case 'd':
4024             name_resolve->dns_pkt_addr_resolution = TRUE;
4025             break;
4026         case 'v':
4027             name_resolve->vlan_name = TRUE;
4028             break;
4029         default:
4030             /*
4031              * Unrecognized letter.
4032              */
4033             return c;
4034         }
4035     }
4036     return '\0';
4037 }
4038
4039 static void
4040 try_convert_to_custom_column(gpointer *el_data)
4041 {
4042     guint haystack_idx;
4043
4044     gchar **fmt = (gchar **) el_data;
4045
4046     for (haystack_idx = 0;
4047          haystack_idx < G_N_ELEMENTS(migrated_columns);
4048          ++haystack_idx) {
4049
4050         if (strcmp(migrated_columns[haystack_idx].col_fmt, *fmt) == 0) {
4051             gchar *cust_col = g_strdup_printf("%%Cus:%s:0",
4052                                 migrated_columns[haystack_idx].col_expr);
4053
4054             g_free(*fmt);
4055             *fmt = cust_col;
4056         }
4057     }
4058 }
4059
4060 static gboolean
4061 deprecated_heur_dissector_pref(gchar *pref_name, const gchar *value)
4062 {
4063     struct heur_pref_name
4064     {
4065         const char* pref_name;
4066         const char* short_name;
4067         gboolean  more_dissectors; /* For multiple dissectors controlled by the same preference */
4068     };
4069
4070     struct heur_pref_name heur_prefs[] = {
4071         {"acn.heuristic_acn", "acn_udp", 0},
4072         {"bfcp.enable", "bfcp_tcp", 1},
4073         {"bfcp.enable", "bfcp_udp", 0},
4074         {"bt-dht.enable", "bittorrent_dht_udp", 0},
4075         {"bt-utp.enable", "bt_utp_udp", 0},
4076         {"cattp.enable", "cattp_udp", 0},
4077         {"cfp.enable", "fp_eth", 0},
4078         {"dicom.heuristic", "dicom_tcp", 0},
4079         {"dnp3.heuristics", "dnp3_tcp", 1},
4080         {"dnp3.heuristics", "dnp3_udp", 0},
4081         {"dvb-s2_modeadapt.enable", "dvb_s2_udp", 0},
4082         {"esl.enable", "esl_eth", 0},
4083         {"fp.udp_heur", "fp_udp", 0},
4084         {"gvsp.enable_heuristic", "gvsp_udp", 0},
4085         {"hdcp2.enable", "hdcp2_tcp", 0},
4086         {"hislip.enable_heuristic", "hislip_tcp", 0},
4087         {"infiniband.dissect_eoib", "mellanox_eoib", 1},
4088         {"infiniband.identify_payload", "eth_over_ib", 0},
4089         {"jxta.udp.heuristic", "jxta_udp", 0},
4090         {"jxta.tcp.heuristic", "jxta_tcp", 0},
4091         {"jxta.sctp.heuristic", "jxta_sctp", 0},
4092         {"mac-lte.heuristic_mac_lte_over_udp", "mac_lte_udp", 0},
4093         {"mbim.bulk_heuristic", "mbim_usb_bulk", 0},
4094         {"norm.heuristic_norm", "rmt_norm_udp", 0},
4095         {"openflow.heuristic", "openflow_tcp", 0},
4096         {"pdcp-lte.heuristic_pdcp_lte_over_udp", "pdcp_lte_udp", 0},
4097         {"rlc.heuristic_rlc_over_udp", "rlc_udp", 0},
4098         {"rlc-lte.heuristic_rlc_lte_over_udp", "rlc_lte_udp", 0},
4099         {"rtcp.heuristic_rtcp", "rtcp_udp", 1},
4100         {"rtcp.heuristic_rtcp", "rtcp_stun", 0},
4101         {"rtp.heuristic_rtp", "rtp_udp", 1},
4102         {"rtp.heuristic_rtp", "rtp_stun", 0},
4103         {"teredo.heuristic_teredo", "teredo_udp", 0},
4104         {"vssmonitoring.use_heuristics", "vssmonitoring_eth", 0},
4105         {"xml.heuristic", "xml_http", 1},
4106         {"xml.heuristic", "xml_sip", 1},
4107         {"xml.heuristic", "xml_media", 0},
4108         {"xml.heuristic_tcp", "xml_tcp", 0},
4109         {"xml.heuristic_udp", "xml_udp", 0},
4110     };
4111
4112     unsigned int i;
4113     heur_dtbl_entry_t* heuristic;
4114
4115
4116     for (i = 0; i < sizeof(heur_prefs)/sizeof(struct heur_pref_name); i++)
4117     {
4118         if (strcmp(pref_name, heur_prefs[i].pref_name) == 0)
4119         {
4120             heuristic = find_heur_dissector_by_unique_short_name(heur_prefs[i].short_name);
4121             if (heuristic != NULL) {
4122                 heuristic->enabled = ((g_ascii_strcasecmp(value, "true") == 0) ? TRUE : FALSE);
4123             }
4124
4125             if (!heur_prefs[i].more_dissectors)
4126                 return TRUE;
4127         }
4128     }
4129
4130
4131     return FALSE;
4132 }
4133
4134 static gboolean
4135 deprecated_enable_dissector_pref(gchar *pref_name, const gchar *value)
4136 {
4137     struct dissector_pref_name
4138     {
4139         const char* pref_name;
4140         const char* short_name;
4141     };
4142
4143     struct dissector_pref_name dissector_prefs[] = {
4144         {"transum.tsumenabled", "TRANSUM"},
4145         {"snort.enable_snort_dissector", "Snort"},
4146         {"prp.enable", "PRP"},
4147     };
4148
4149     unsigned int i;
4150     int proto_id;
4151
4152     for (i = 0; i < sizeof(dissector_prefs)/sizeof(struct dissector_pref_name); i++)
4153     {
4154         if (strcmp(pref_name, dissector_prefs[i].pref_name) == 0)
4155         {
4156             proto_id = proto_get_id_by_short_name(dissector_prefs[i].short_name);
4157             if (proto_id >= 0)
4158                 proto_set_decoding(proto_id, ((g_ascii_strcasecmp(value, "true") == 0) ? TRUE : FALSE));
4159             return TRUE;
4160         }
4161     }
4162
4163     return FALSE;
4164 }
4165
4166 static gboolean
4167 deprecated_port_pref(gchar *pref_name, const gchar *value)
4168 {
4169     struct port_pref_name
4170     {
4171         const char* pref_name;
4172         const char* module_name;
4173         const char* table_name;
4174         guint base;
4175     };
4176
4177     struct obsolete_pref_name
4178     {
4179         const char* pref_name;
4180     };
4181
4182     /* For now this is only supporting TCP/UDP port dissector preferences
4183        which are assumed to be decimal */
4184     struct port_pref_name port_prefs[] = {
4185         /* TCP */
4186         {"cmp.tcp_alternate_port", "CMP", "tcp.port", 10},
4187         {"h248.tcp_port", "H248", "tcp.port", 10},
4188         {"cops.tcp.cops_port", "COPS", "tcp.port", 10},
4189         {"dhcpfo.tcp_port", "DHCPFO", "tcp.port", 10},
4190         {"enttec.tcp_port", "ENTTEC", "tcp.port", 10},
4191         {"forces.tcp_alternate_port", "ForCES", "tcp.port", 10},
4192         {"ged125.tcp_port", "GED125", "tcp.port", 10},
4193         {"hpfeeds.dissector_port", "HPFEEDS", "tcp.port", 10},
4194         {"lsc.port", "LSC", "tcp.port", 10},
4195         {"megaco.tcp.txt_port", "MEGACO", "tcp.port", 10},
4196         {"netsync.tcp_port", "Netsync", "tcp.port", 10},
4197         {"osi.tpkt_port", "OSI", "tcp.port", 10},
4198         {"rsync.tcp_port", "RSYNC", "tcp.port", 10},
4199         {"sametime.tcp_port", "SAMETIME", "tcp.port", 10},
4200         {"sigcomp.tcp.port2", "SIGCOMP", "tcp.port", 10},
4201         {"synphasor.tcp_port", "SYNCHROPHASOR", "tcp.port", 10},
4202         {"tipc.alternate_port", "TIPC", "tcp.port", 10},
4203         {"vnc.alternate_port", "VNC", "tcp.port", 10},
4204         {"scop.port", "SCoP", "tcp.port", 10},
4205         {"scop.port_secure", "SCoP", "tcp.port", 10},
4206         /* UDP */
4207         {"h248.udp_port", "H248", "udp.port", 10},
4208         {"actrace.udp_port", "ACtrace", "udp.port", 10},
4209         {"brp.port", "BRP", "udp.port", 10},
4210         {"bvlc.additional_udp_port", "BVLC", "udp.port", 10},
4211         {"capwap.udp.port.control", "CAPWAP-CONTROL", "udp.port", 10},
4212         {"capwap.udp.port.data", "CAPWAP-CONTROL", "udp.port", 10},
4213         {"coap.udp_port", "CoAP", "udp.port", 10},
4214         {"enttec.udp_port", "ENTTEC", "udp.port", 10},
4215         {"forces.udp_alternate_port", "ForCES", "udp.port", 10},
4216         {"ldss.udp_port", "LDSS", "udp.port", 10},
4217         {"lmp.udp_port", "LMP", "udp.port", 10},
4218         {"ltp.port", "LTP", "udp.port", 10},
4219         {"lwres.udp.lwres_port", "LWRES", "udp.port", 10},
4220         {"megaco.udp.txt_port", "MEGACO", "udp.port", 10},
4221         {"pgm.udp.encap_ucast_port", "PGM", "udp.port", 10},
4222         {"pgm.udp.encap_mcast_port", "PGM", "udp.port", 10},
4223         {"quic.udp.quic.port", "QUIC", "udp.port", 10},
4224         {"quic.udp.quics.port", "QUIC", "udp.port", 10},
4225         {"radius.alternate_port", "RADIUS", "udp.port", 10},
4226         {"rdt.default_udp_port", "RDT", "udp.port", 10},
4227         {"alc.default.udp_port", "ALC", "udp.port", 10},
4228         {"sigcomp.udp.port2", "SIGCOMP", "udp.port", 10},
4229         {"synphasor.udp_port", "SYNCHROPHASOR", "udp.port", 10},
4230         {"tdmop.udpport", "TDMoP", "udp.port", 10},
4231         {"uaudp.port1", "UAUDP", "udp.port", 10},
4232         {"uaudp.port2", "UAUDP", "udp.port", 10},
4233         {"uaudp.port3", "UAUDP", "udp.port", 10},
4234         {"uaudp.port4", "UAUDP", "udp.port", 10},
4235         {"uhd.dissector_port", "UHD", "udp.port", 10},
4236         {"vrt.dissector_port", "VITA 49", "udp.port", 10},
4237         {"vuze-dht.udp_port", "Vuze-DHT", "udp.port", 10},
4238         {"wimaxasncp.udp.wimax_port", "WiMAX ASN CP", "udp.port", 10},
4239     };
4240
4241     struct port_pref_name port_range_prefs[] = {
4242         /* TCP */
4243         {"couchbase.tcp.ports", "Couchbase", "tcp.port", 10},
4244         {"gsm_ipa.tcp_ports", "GSM over IP", "tcp.port", 10},
4245         {"kafka.tcp.ports", "Kafka", "tcp.port", 10},
4246         {"kt.tcp.ports", "Kyoto Tycoon", "tcp.port", 10},
4247         {"memcache.tcp.ports", "MEMCACHE", "tcp.port", 10},
4248         {"mrcpv2.tcp.port_range", "MRCPv2", "tcp.port", 10},
4249         {"rtsp.tcp.port_range", "RTSP", "tcp.port", 10},
4250         {"sip.tcp.ports", "SIP", "tcp.port", 10},
4251         {"tds.tcp_ports", "TDS", "tcp.port", 10},
4252         {"uma.tcp.ports", "UMA", "tcp.port", 10},
4253         /* UDP */
4254         {"aruba_erm.udp.ports", "ARUBA_ERM", "udp.port", 10},
4255         {"diameter.udp.ports", "DIAMETER", "udp.port", 10},
4256         {"dmp.udp_ports", "DMP", "udp.port", 10},
4257         {"dns.udp.ports", "DNS", "udp.port", 10},
4258         {"gsm_ipa.udp_ports", "GSM over IP", "udp.port", 10},
4259         {"hcrt.dissector_udp_port", "HCrt", "udp.port", 10},
4260         {"memcache.udp.ports", "MEMCACHE", "udp.port", 10},
4261         {"nb_rtpmux.udp_ports", "NB_RTPMUX", "udp.port", 10},
4262         {"gprs-ns.udp.ports", "GPRS-NS", "udp.port", 10},
4263         {"p_mul.udp_ports", "P_MUL", "udp.port", 10},
4264         {"radius.ports", "RADIUS", "udp.port", 10},
4265         {"sflow.ports", "sFlow", "udp.port", 10},
4266         {"sscop.udp.ports", "SSCOP", "udp.port", 10},
4267         {"tftp.udp_ports", "TFTP", "udp.port", 10},
4268         {"tipc.udp.ports", "TIPC", "udp.port", 10},
4269     };
4270
4271     /* These are subdissectors of TPKT/OSITP that used to have a
4272        TCP port preference even though they were never
4273        directly on TCP.  Convert them to use Decode As
4274        with the TPKT dissector handle */
4275     struct port_pref_name tpkt_subdissector_port_prefs[] = {
4276         {"dap.tcp.port", "DAP", "tcp.port", 10},
4277         {"disp.tcp.port", "DISP", "tcp.port", 10},
4278         {"dop.tcp.port", "DOP", "tcp.port", 10},
4279         {"dsp.tcp.port", "DSP", "tcp.port", 10},
4280         {"p1.tcp.port", "P1", "tcp.port", 10},
4281         {"p7.tcp.port", "P7", "tcp.port", 10},
4282         {"rdp.tcp.port", "RDP", "tcp.port", 10},
4283     };
4284
4285     /* These are obsolete preferences from the dissectors' view,
4286        (typically because of a switch from a single value to a
4287        range value) but the name of the preference conflicts
4288        with the generated preference name from the dissector table.
4289        Don't allow the obsolete preference through to be handled */
4290     struct obsolete_pref_name obsolete_prefs[] = {
4291         {"diameter.tcp.port"},
4292         {"kafka.tcp.port"},
4293         {"mrcpv2.tcp.port"},
4294         {"rtsp.tcp.port"},
4295         {"sip.tcp.port"},
4296         {"t38.tcp.port"},
4297     };
4298
4299     unsigned int i;
4300     char     *p;
4301     guint    uval;
4302     dissector_table_t sub_dissectors;
4303     dissector_handle_t handle, tpkt_handle;
4304     module_t *module;
4305     pref_t *pref;
4306
4307     for (i = 0; i < sizeof(port_prefs)/sizeof(struct port_pref_name); i++)
4308     {
4309         if (strcmp(pref_name, port_prefs[i].pref_name) == 0)
4310         {
4311             /* XXX - give an error if it doesn't fit in a guint? */
4312             uval = (guint)strtoul(value, &p, port_prefs[i].base);
4313             if (p == value || *p != '\0')
4314                 return FALSE;        /* number was bad */
4315
4316             module = prefs_find_module((gchar*)port_prefs[i].module_name);
4317             pref = prefs_find_preference(module, port_prefs[i].table_name);
4318             if (pref != NULL)
4319             {
4320                 module->prefs_changed = TRUE;
4321                 *pref->varp.uint = uval;
4322             }
4323
4324             /* If the value is zero, it wouldn't add to the Decode As tables */
4325             if (uval != 0)
4326             {
4327                 sub_dissectors = find_dissector_table(port_prefs[i].table_name);
4328                 if (sub_dissectors != NULL) {
4329                     handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)port_prefs[i].module_name);
4330                     if (handle != NULL) {
4331                         dissector_change_uint(port_prefs[i].table_name, uval, handle);
4332                         decode_build_reset_list(port_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval), NULL, NULL);
4333                     }
4334                 }
4335             }
4336
4337             return TRUE;
4338         }
4339     }
4340
4341     for (i = 0; i < sizeof(port_range_prefs)/sizeof(struct port_pref_name); i++)
4342     {
4343         if (strcmp(pref_name, port_range_prefs[i].pref_name) == 0)
4344         {
4345             guint32 range_i, range_j;
4346
4347             sub_dissectors = find_dissector_table(port_range_prefs[i].table_name);
4348             if (sub_dissectors != NULL) {
4349                 switch (dissector_table_get_type(sub_dissectors)) {
4350                 case FT_UINT8:
4351                 case FT_UINT16:
4352                 case FT_UINT24:
4353                 case FT_UINT32:
4354                     break;
4355
4356                 default:
4357                     g_error("The dissector table %s (%s) is not an integer type - are you using a buggy plugin?", port_range_prefs[i].table_name, get_dissector_table_ui_name(port_range_prefs[i].table_name));
4358                     g_assert_not_reached();
4359                 }
4360
4361                 module = prefs_find_module((gchar*)port_range_prefs[i].module_name);
4362                 pref = prefs_find_preference(module, port_range_prefs[i].table_name);
4363                 if (pref != NULL)
4364                 {
4365                     if (!prefs_set_range_value(pref, value, &module->prefs_changed))
4366                     {
4367                         return FALSE;        /* number was bad */
4368                     }
4369
4370                     handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)port_range_prefs[i].module_name);
4371                     if (handle != NULL) {
4372
4373                         for (range_i = 0; range_i < (*pref->varp.range)->nranges; range_i++) {
4374                             for (range_j = (*pref->varp.range)->ranges[range_i].low; range_j < (*pref->varp.range)->ranges[range_i].high; range_j++) {
4375                                 dissector_change_uint(port_range_prefs[i].table_name, range_j, handle);
4376                                 decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(range_j), NULL, NULL);
4377                             }
4378
4379                             dissector_change_uint(port_range_prefs[i].table_name, (*pref->varp.range)->ranges[range_i].high, handle);
4380                             decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[range_i].high), NULL, NULL);
4381                         }
4382                     }
4383                 }
4384             }
4385
4386             return TRUE;
4387         }
4388     }
4389
4390     for (i = 0; i < sizeof(tpkt_subdissector_port_prefs)/sizeof(struct port_pref_name); i++)
4391     {
4392         if (strcmp(pref_name, tpkt_subdissector_port_prefs[i].pref_name) == 0)
4393         {
4394             /* XXX - give an error if it doesn't fit in a guint? */
4395             uval = (guint)strtoul(value, &p, tpkt_subdissector_port_prefs[i].base);
4396             if (p == value || *p != '\0')
4397                 return FALSE;        /* number was bad */
4398
4399             /* If the value is 0 or 102 (default TPKT port), don't add to the Decode As tables */
4400             if ((uval != 0) && (uval != 102))
4401             {
4402                 tpkt_handle = find_dissector("tpkt");
4403                 if (tpkt_handle != NULL) {
4404                     dissector_change_uint(tpkt_subdissector_port_prefs[i].table_name, uval, tpkt_handle);
4405                 }
4406             }
4407
4408             return TRUE;
4409         }
4410     }
4411
4412     for (i = 0; i < sizeof(obsolete_prefs)/sizeof(struct obsolete_pref_name); i++)
4413     {
4414         if (strcmp(pref_name, obsolete_prefs[i].pref_name) == 0)
4415         {
4416             /* Just ignore the preference */
4417             return TRUE;
4418         }
4419     }
4420     return FALSE;
4421 }
4422
4423 static prefs_set_pref_e
4424 set_pref(gchar *pref_name, const gchar *value, void *private_data _U_,
4425          gboolean return_range_errors)
4426 {
4427     unsigned long int cval;
4428     guint    uval;
4429     gboolean bval;
4430     gint     enum_val;
4431     char     *p;
4432     gchar    *dotp, *last_dotp;
4433     static gchar *filter_label = NULL;
4434     static gboolean filter_enabled = FALSE;
4435     gchar    *filter_expr = NULL;
4436     module_t *module, *containing_module;
4437     pref_t   *pref;
4438     int type;
4439
4440     if (strcmp(pref_name, PRS_GUI_FILTER_LABEL) == 0) {
4441         filter_label = g_strdup(value);
4442     } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED) == 0) {
4443         filter_enabled = (strcmp(value, "TRUE") == 0) ? TRUE : FALSE;
4444     } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR) == 0) {
4445         filter_expr = g_strdup(value);
4446         filter_expression_new(filter_label, filter_expr, filter_enabled);
4447         g_free(filter_label);
4448         g_free(filter_expr);
4449     } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
4450         /* Convert deprecated value to closest current equivalent */
4451         if (g_ascii_strcasecmp(value, "true") == 0) {
4452             prefs.gui_version_placement = version_both;
4453         } else {
4454             prefs.gui_version_placement = version_neither;
4455         }
4456     } else if (strcmp(pref_name, "name_resolve") == 0 ||
4457                strcmp(pref_name, "capture.name_resolve") == 0) {
4458         /*
4459          * Handle the deprecated name resolution options.
4460          *
4461          * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
4462          * RESOLV_ALL and RESOLV_NONE.
4463          *
4464          * Otherwise, we treat it as a list of name types we want to resolve.
4465          */
4466         if (g_ascii_strcasecmp(value, "true") == 0) {
4467             gbl_resolv_flags.mac_name = TRUE;
4468             gbl_resolv_flags.network_name = TRUE;
4469             gbl_resolv_flags.transport_name = TRUE;
4470         }
4471         else if (g_ascii_strcasecmp(value, "false") == 0) {
4472             disable_name_resolution();
4473         }
4474         else {
4475             /* start out with none set */
4476             disable_name_resolution();
4477             if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
4478                 return PREFS_SET_SYNTAX_ERR;
4479         }
4480     } else if (deprecated_heur_dissector_pref(pref_name, value)) {
4481          /* Handled within deprecated_heur_dissector_pref() if found */
4482     } else if (deprecated_enable_dissector_pref(pref_name, value)) {
4483          /* Handled within deprecated_enable_dissector_pref() if found */
4484     } else if (deprecated_port_pref(pref_name, value)) {
4485          /* Handled within deprecated_port_pref() if found */
4486     } else {
4487         /* Handle deprecated "global" options that don't have a module
4488          * associated with them
4489          */
4490         if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
4491             (strcmp(pref_name, "name_resolve_load_smi_modules") == 0)  ||
4492             (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
4493             module = nameres_module;
4494             dotp = pref_name;
4495         } else {
4496             /* To which module does this preference belong? */
4497             module = NULL;
4498             last_dotp = pref_name;
4499             while (!module) {
4500                 dotp = strchr(last_dotp, '.');
4501                 if (dotp == NULL) {
4502                     /* Either there's no such module, or no module was specified.
4503                        In either case, that means there's no such preference. */
4504                     return PREFS_SET_NO_SUCH_PREF;
4505                 }
4506                 *dotp = '\0'; /* separate module and preference name */
4507                 module = prefs_find_module(pref_name);
4508
4509                 /*
4510                  * XXX - "Diameter" rather than "diameter" was used in earlier
4511                  * versions of Wireshark; if we didn't find the module, and its name
4512                  * was "Diameter", look for "diameter" instead.
4513                  *
4514                  * In addition, the BEEP protocol used to be the BXXP protocol,
4515                  * so if we didn't find the module, and its name was "bxxp",
4516                  * look for "beep" instead.
4517                  *
4518                  * Also, the preferences for GTP v0 and v1 were combined under
4519                  * a single "gtp" heading, and the preferences for SMPP were
4520                  * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
4521                  * However, SMPP now has its own preferences, so we just map
4522                  * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
4523                  *
4524                  * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
4525                  * and "nsip" to "gprs_ns".
4526                  *
4527                  * The SynOptics Network Management Protocol (SONMP) is now known by
4528                  * its modern name, the Nortel Discovery Protocol (NDP).
4529                  */
4530                 if (module == NULL) {
4531                     if (strcmp(pref_name, "column") == 0)
4532                         module = gui_column_module;
4533                     else if (strcmp(pref_name, "Diameter") == 0)
4534                         module = prefs_find_module("diameter");
4535                     else if (strcmp(pref_name, "bxxp") == 0)
4536                         module = prefs_find_module("beep");
4537                     else if (strcmp(pref_name, "gtpv0") == 0 ||
4538                              strcmp(pref_name, "gtpv1") == 0)
4539                         module = prefs_find_module("gtp");
4540                     else if (strcmp(pref_name, "smpp-gsm-sms") == 0)
4541                         module = prefs_find_module("gsm-sms-ud");
4542                     else if (strcmp(pref_name, "dcp") == 0)
4543                         module = prefs_find_module("dccp");
4544                     else if (strcmp(pref_name, "x.25") == 0)
4545                         module = prefs_find_module("x25");
4546                     else if (strcmp(pref_name, "x411") == 0)
4547                         module = prefs_find_module("p1");
4548                     else if (strcmp(pref_name, "nsip") == 0)
4549                         module = prefs_find_module("gprs-ns");
4550                     else if (strcmp(pref_name, "sonmp") == 0)
4551                         module = prefs_find_module("ndp");
4552                     else if (strcmp(pref_name, "etheric") == 0 ||
4553                              strcmp(pref_name, "isup_thin") == 0) {
4554                         /* This protocol was removed 7. July 2009 */
4555                         return PREFS_SET_OBSOLETE;
4556                     }
4557                     if (module) {
4558                         ws_g_warning ("Preference \"%s.%s\" has been converted to \"%s.%s.%s\"\n"
4559                                    "Save your preferences to make this change permanent.",
4560                                    pref_name, dotp+1, module->parent->name, pref_name, dotp+1);
4561                         prefs.unknown_prefs = TRUE;
4562                     }
4563                 }
4564                 *dotp = '.';                /* put the preference string back */
4565                 dotp++;                     /* skip past separator to preference name */
4566                 last_dotp = dotp;
4567             }
4568         }
4569
4570         /* The pref is located in the module or a submodule.
4571          * Assume module, then search for a submodule holding the pref. */
4572         containing_module = module;
4573         pref = prefs_find_preference_with_submodule(module, dotp, &containing_module);
4574
4575         if (pref == NULL) {
4576             prefs.unknown_prefs = TRUE;
4577
4578             /* "gui" prefix was added to column preferences for better organization
4579              * within the preferences file
4580              */
4581             if (module == gui_column_module) {
4582                 /* While this has a subtree, there is no apply callback, so no
4583                  * need to use prefs_find_preference_with_submodule to update
4584                  * containing_module. It would not be useful. */
4585                 pref = prefs_find_preference(module, pref_name);
4586             }
4587             else if (strcmp(module->name, "mgcp") == 0) {
4588                 /*
4589                  * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
4590                  * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
4591                  * were used in earlier versions of Wireshark; if we didn't find the
4592                  * preference, it was an MGCP preference, and its name was
4593                  * "display raw text toggle" or "display dissect tree", look for
4594                  * "display_raw_text" or "display_dissect_tree" instead.
4595                  *
4596                  * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
4597                  * the gateway and callagent ports were given those names; we interpret
4598                  * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
4599                  * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
4600                  * they were registered by the MCCP dissector and thus that's the
4601                  * order in which they were written to the preferences file.  (If
4602                  * we're not reading the preferences file, but are handling stuff
4603                  * from a "-o" command-line option, we have no clue which the user
4604                  * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
4605                  * or "mgcp.{tcp,udp}.callagent_port" instead.)
4606                  */
4607                 if (strcmp(dotp, "display raw text toggle") == 0)
4608                     pref = prefs_find_preference(module, "display_raw_text");
4609                 else if (strcmp(dotp, "display dissect tree") == 0)
4610                     pref = prefs_find_preference(module, "display_dissect_tree");
4611                 else if (strcmp(dotp, "tcp.port") == 0) {
4612                     mgcp_tcp_port_count++;
4613                     if (mgcp_tcp_port_count == 1) {
4614                         /* It's the first one */
4615                         pref = prefs_find_preference(module, "tcp.gateway_port");
4616                     } else if (mgcp_tcp_port_count == 2) {
4617                         /* It's the second one */
4618                         pref = prefs_find_preference(module, "tcp.callagent_port");
4619                     }
4620                     /* Otherwise it's from the command line, and we don't bother
4621                        mapping it. */
4622                 } else if (strcmp(dotp, "udp.port") == 0) {
4623                     mgcp_udp_port_count++;
4624                     if (mgcp_udp_port_count == 1) {
4625                         /* It's the first one */
4626                         pref = prefs_find_preference(module, "udp.gateway_port");
4627                     } else if (mgcp_udp_port_count == 2) {
4628                         /* It's the second one */
4629                         pref = prefs_find_preference(module, "udp.callagent_port");
4630                     }
4631                     /* Otherwise it's from the command line, and we don't bother
4632                        mapping it. */
4633                 }
4634             } else if (strcmp(module->name, "smb") == 0) {
4635                 /* Handle old names for SMB preferences. */
4636                 if (strcmp(dotp, "smb.trans.reassembly") == 0)
4637                     pref = prefs_find_preference(module, "trans_reassembly");
4638                 else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
4639                     pref = prefs_find_preference(module, "dcerpc_reassembly");
4640             } else if (strcmp(module->name, "ndmp") == 0) {
4641                 /* Handle old names for NDMP preferences. */
4642                 if (strcmp(dotp, "ndmp.desegment") == 0)
4643                     pref = prefs_find_preference(module, "desegment");
4644             } else if (strcmp(module->name, "diameter") == 0) {
4645                 /* Handle old names for Diameter preferences. */
4646                 if (strcmp(dotp, "diameter.desegment") == 0)
4647                     pref = prefs_find_preference(module, "desegment");
4648             } else if (strcmp(module->name, "pcli") == 0) {
4649                 /* Handle old names for PCLI preferences. */
4650                 if (strcmp(dotp, "pcli.udp_port") == 0)
4651                     pref = prefs_find_preference(module, "udp_port");
4652             } else if (strcmp(module->name, "artnet") == 0) {
4653                 /* Handle old names for ARTNET preferences. */
4654                 if (strcmp(dotp, "artnet.udp_port") == 0)
4655                     pref = prefs_find_preference(module, "udp_port");
4656             } else if (strcmp(module->name, "mapi") == 0) {
4657                 /* Handle old names for MAPI preferences. */
4658                 if (strcmp(dotp, "mapi_decrypt") == 0)
4659                     pref = prefs_find_preference(module, "decrypt");
4660             } else if (strcmp(module->name, "fc") == 0) {
4661                 /* Handle old names for Fibre Channel preferences. */
4662                 if (strcmp(dotp, "reassemble_fc") == 0)
4663                     pref = prefs_find_preference(module, "reassemble");
4664                 else if (strcmp(dotp, "fc_max_frame_size") == 0)
4665                     pref = prefs_find_preference(module, "max_frame_size");
4666             } else if (strcmp(module->name, "fcip") == 0) {
4667                 /* Handle old names for Fibre Channel-over-IP preferences. */
4668                 if (strcmp(dotp, "desegment_fcip_messages") == 0)
4669                     pref = prefs_find_preference(module, "desegment");
4670                 else if (strcmp(dotp, "fcip_port") == 0)
4671                     pref = prefs_find_preference(module, "target_port");
4672             } else if (strcmp(module->name, "gtp") == 0) {
4673                 /* Handle old names for GTP preferences. */
4674                 if (strcmp(dotp, "gtpv0_port") == 0)
4675                     pref = prefs_find_preference(module, "v0_port");
4676                 else if (strcmp(dotp, "gtpv1c_port") == 0)
4677                     pref = prefs_find_preference(module, "v1c_port");
4678                 else if (strcmp(dotp, "gtpv1u_port") == 0)
4679                     pref = prefs_find_preference(module, "v1u_port");
4680                 else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
4681                     pref = prefs_find_preference(module, "dissect_tpdu");
4682                 else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
4683                     pref = prefs_find_preference(module, "v0_dissect_cdr_as");
4684                 else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
4685                     pref = prefs_find_preference(module, "v0_check_etsi");
4686                 else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
4687                     pref = prefs_find_preference(module, "v1_check_etsi");
4688             } else if (strcmp(module->name, "ip") == 0) {
4689                 /* Handle old names for IP preferences. */
4690                 if (strcmp(dotp, "ip_summary_in_tree") == 0)
4691                     pref = prefs_find_preference(module, "summary_in_tree");
4692             } else if (strcmp(module->name, "iscsi") == 0) {
4693                 /* Handle old names for iSCSI preferences. */
4694                 if (strcmp(dotp, "iscsi_port") == 0)
4695                     pref = prefs_find_preference(module, "target_port");
4696             } else if (strcmp(module->name, "lmp") == 0) {
4697                 /* Handle old names for LMP preferences. */
4698                 if (strcmp(dotp, "lmp_version") == 0)
4699                     pref = prefs_find_preference(module, "version");
4700             } else if (strcmp(module->name, "mtp3") == 0) {
4701                 /* Handle old names for MTP3 preferences. */
4702                 if (strcmp(dotp, "mtp3_standard") == 0)
4703                     pref = prefs_find_preference(module, "standard");
4704                 else if (strcmp(dotp, "net_addr_format") == 0)
4705                     pref = prefs_find_preference(module, "addr_format");
4706             } else if (strcmp(module->name, "nlm") == 0) {
4707                 /* Handle old names for NLM preferences. */
4708                 if (strcmp(dotp, "nlm_msg_res_matching") == 0)
4709                     pref = prefs_find_preference(module, "msg_res_matching");
4710             } else if (strcmp(module->name, "ppp") == 0) {
4711                 /* Handle old names for PPP preferences. */
4712                 if (strcmp(dotp, "ppp_fcs") == 0)
4713                     pref = prefs_find_preference(module, "fcs_type");
4714                 else if (strcmp(dotp, "ppp_vj") == 0)
4715                     pref = prefs_find_preference(module, "decompress_vj");
4716             } else if (strcmp(module->name, "rsvp") == 0) {
4717                 /* Handle old names for RSVP preferences. */
4718                 if (strcmp(dotp, "rsvp_process_bundle") == 0)
4719                     pref = prefs_find_preference(module, "process_bundle");
4720             } else if (strcmp(module->name, "tcp") == 0) {
4721                 /* Handle old names for TCP preferences. */
4722                 if (strcmp(dotp, "tcp_summary_in_tree") == 0)
4723                     pref = prefs_find_preference(module, "summary_in_tree");
4724                 else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
4725                     pref = prefs_find_preference(module, "analyze_sequence_numbers");
4726                 else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
4727                     pref = prefs_find_preference(module, "relative_sequence_numbers");
4728             } else if (strcmp(module->name, "udp") == 0) {
4729                 /* Handle old names for UDP preferences. */
4730                 if (strcmp(dotp, "udp_summary_in_tree") == 0)
4731                     pref = prefs_find_preference(module, "summary_in_tree");
4732             } else if (strcmp(module->name, "ndps") == 0) {
4733                 /* Handle old names for NDPS preferences. */
4734                 if (strcmp(dotp, "desegment_ndps") == 0)
4735                     pref = prefs_find_preference(module, "desegment_tcp");
4736             } else if (strcmp(module->name, "http") == 0) {
4737                 /* Handle old names for HTTP preferences. */
4738                 if (strcmp(dotp, "desegment_http_headers") == 0)
4739                     pref = prefs_find_preference(module, "desegment_headers");
4740                 else if (strcmp(dotp, "desegment_http_body") == 0)
4741                     pref = prefs_find_preference(module, "desegment_body");
4742             } else if (strcmp(module->name, "smpp") == 0) {
4743                 /* Handle preferences that moved from SMPP. */
4744                 module_t *new_module = prefs_find_module("gsm-sms-ud");
4745                 if (new_module) {
4746                     if (strcmp(dotp, "port_number_udh_means_wsp") == 0) {
4747                         pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
4748                         containing_module = new_module;
4749                     } else if (strcmp(dotp, "try_dissect_1st_fragment") == 0) {
4750                         pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
4751                         containing_module = new_module;
4752                     }
4753                 }
4754             } else if (strcmp(module->name, "asn1") == 0) {
4755                 /* Handle old generic ASN.1 preferences (it's not really a
4756                    rename, as the new preferences support multiple ports,
4757                    but we might as well copy them over). */
4758                 if (strcmp(dotp, "tcp_port") == 0)
4759                     pref = prefs_find_preference(module, "tcp_ports");
4760                 else if (strcmp(dotp, "udp_port") == 0)
4761                     pref = prefs_find_preference(module, "udp_ports");
4762                 else if (strcmp(dotp, "sctp_port") == 0)
4763                     pref = prefs_find_preference(module, "sctp_ports");
4764             } else if (strcmp(module->name, "llcgprs") == 0) {
4765                 if (strcmp(dotp, "ignore_cipher_bit") == 0)
4766                     pref = prefs_find_preference(module, "autodetect_cipher_bit");
4767             } else if (strcmp(module->name, "erf") == 0) {
4768                 if (strcmp(dotp, "erfeth") == 0) {
4769                     /* Handle the old "erfeth" preference; map it to the new
4770                        "ethfcs" preference, and map the values to those for
4771                        the new preference. */
4772                     pref = prefs_find_preference(module, "ethfcs");
4773                     if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
4774                         value = "TRUE";
4775                     else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
4776                         value = "FALSE";
4777                     else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
4778                         value = "TRUE";
4779                 } else if (strcmp(dotp, "erfatm") == 0) {
4780                     /* Handle the old "erfatm" preference; map it to the new
4781                        "aal5_type" preference, and map the values to those for
4782                        the new preference. */
4783                     pref = prefs_find_preference(module, "aal5_type");
4784                     if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
4785                         value = "guess";
4786                     else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
4787                         value = "llc";
4788                     else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
4789                         value = "guess";
4790                 } else if (strcmp(dotp, "erfhdlc") == 0) {
4791                     /* Handle the old "erfhdlc" preference; map it to the new
4792                        "hdlc_type" preference, and map the values to those for
4793                        the new preference. */
4794                     pref = prefs_find_preference(module, "hdlc_type");
4795                     if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
4796                         value = "chdlc";
4797                     else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
4798                         value = "ppp";
4799                     else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
4800                         value = "frelay";
4801                     else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
4802                         value = "mtp2";
4803                     else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
4804                         value = "guess";
4805                 }
4806             } else if (strcmp(module->name, "eth") == 0) {
4807                 /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
4808                 if (strcmp(dotp, "qinq_ethertype") == 0) {
4809                     module_t *new_module = prefs_find_module("vlan");
4810                     if (new_module) {
4811                         pref = prefs_find_preference(new_module, "qinq_ethertype");
4812                         containing_module = new_module;
4813                     }
4814                 }
4815             } else if (strcmp(module->name, "taps") == 0) {
4816                 /* taps preferences moved to "statistics" module */
4817                 if (strcmp(dotp, "update_interval") == 0 ||
4818                     strcmp(dotp, "rtp_player_max_visible") == 0)
4819                     pref = prefs_find_preference(stats_module, dotp);
4820             } else if (strcmp(module->name, "packet_list") == 0) {
4821                 /* packet_list preferences moved to protocol module */
4822                 if (strcmp(dotp, "display_hidden_proto_items") == 0)
4823                     pref = prefs_find_preference(protocols_module, dotp);
4824             } else if (strcmp(module->name, "stream") == 0) {
4825                 /* stream preferences moved to gui color module */
4826                 if ((strcmp(dotp, "client.fg") == 0) ||
4827                     (strcmp(dotp, "client.bg") == 0) ||
4828                     (strcmp(dotp, "server.fg") == 0) ||
4829                     (strcmp(dotp, "server.bg") == 0))
4830                     pref = prefs_find_preference(gui_color_module, pref_name);
4831             } else if (strcmp(module->name, "nameres") == 0) {
4832                 if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
4833                     pref = prefs_find_preference(nameres_module, pref_name);
4834                 } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
4835                     pref = prefs_find_preference(nameres_module, "load_smi_modules");
4836                 } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
4837                     pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
4838                 }
4839             }
4840         }
4841         if (pref == NULL)
4842             return PREFS_SET_NO_SUCH_PREF;        /* no such preference */
4843
4844         type = pref->type;
4845         if (IS_PREF_OBSOLETE(type)) {
4846             return PREFS_SET_OBSOLETE;        /* no such preference any more */
4847         } else {
4848             RESET_PREF_OBSOLETE(type);
4849         }
4850
4851         switch (type) {
4852
4853         case PREF_UINT:
4854             /* XXX - give an error if it doesn't fit in a guint? */
4855             uval = (guint)strtoul(value, &p, pref->info.base);
4856             if (p == value || *p != '\0')
4857                 return PREFS_SET_SYNTAX_ERR;        /* number was bad */
4858             if (*pref->varp.uint != uval) {
4859                 containing_module->prefs_changed = TRUE;
4860                 *pref->varp.uint = uval;
4861             }
4862             break;
4863         case PREF_DECODE_AS_UINT:
4864         {
4865             /* This is for backwards compatibility in case any of the preferences
4866                that shared the "Decode As" preference name and used to be PREF_UINT
4867                are now applied directly to the Decode As funtionality */
4868
4869             dissector_table_t sub_dissectors;
4870             dissector_handle_t handle;
4871
4872             /* XXX - give an error if it doesn't fit in a guint? */
4873             uval = (guint)strtoul(value, &p, pref->info.base);
4874             if (p == value || *p != '\0')
4875                 return PREFS_SET_SYNTAX_ERR;        /* number was bad */
4876
4877             if (*pref->varp.uint != uval) {
4878                 containing_module->prefs_changed = TRUE;
4879                 *pref->varp.uint = uval;
4880
4881                 /* Name of preference is the dissector table */
4882                 sub_dissectors = find_dissector_table(pref->name);
4883                 if (sub_dissectors != NULL) {
4884                     handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)module->title);
4885                     if (handle != NULL) {
4886                         if (uval != 0) {
4887                             dissector_change_uint(pref->name, uval, handle);
4888                             decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval), NULL, NULL);
4889                         } else {
4890                             dissector_delete_uint(pref->name, *pref->varp.uint, handle);
4891                             decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), pref->varp.uint, NULL, NULL);
4892                         }
4893
4894                         /* XXX - Do we save the decode_as_entries file here? */
4895                     }
4896                 }
4897             }
4898             break;
4899         }
4900         case PREF_BOOL:
4901             /* XXX - give an error if it's neither "true" nor "false"? */
4902             if (g_ascii_strcasecmp(value, "true") == 0)
4903                 bval = TRUE;
4904             else
4905                 bval = FALSE;
4906             if (*pref->varp.boolp != bval) {
4907                 containing_module->prefs_changed = TRUE;
4908                 *pref->varp.boolp = bval;
4909             }
4910             break;
4911
4912         case PREF_ENUM:
4913             /* XXX - give an error if it doesn't match? */
4914             enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
4915                                            *pref->varp.enump);
4916             if (*pref->varp.enump != enum_val) {
4917                 containing_module->prefs_changed = TRUE;
4918                 *pref->varp.enump = enum_val;
4919             }
4920             break;
4921
4922         case PREF_STRING:
4923         case PREF_FILENAME:
4924         case PREF_DIRNAME:
4925             prefs_set_string_like_value(pref, value, &containing_module->prefs_changed);
4926             break;
4927
4928         case PREF_RANGE:
4929         {
4930             if (!prefs_set_range_value_work(pref, value, return_range_errors,
4931                                             &containing_module->prefs_changed))
4932                 return PREFS_SET_SYNTAX_ERR;        /* number was bad */
4933             break;
4934         }
4935         case PREF_DECODE_AS_RANGE:
4936         {
4937             /* This is for backwards compatibility in case any of the preferences
4938                that shared the "Decode As" preference name and used to be PREF_RANGE
4939                are now applied directly to the Decode As funtionality */
4940             range_t *newrange;
4941             dissector_table_t sub_dissectors;
4942             dissector_handle_t handle;
4943             guint32 i, j;
4944
4945             if (range_convert_str_work(&newrange, value, pref->info.max_value,
4946                                        return_range_errors) != CVT_NO_ERROR) {
4947                 return PREFS_SET_SYNTAX_ERR;        /* number was bad */
4948             }
4949
4950             if (!ranges_are_equal(*pref->varp.range, newrange)) {
4951                 g_free(*pref->varp.range);
4952                 *pref->varp.range = newrange;
4953                 containing_module->prefs_changed = TRUE;
4954
4955                 /* Name of preference is the dissector table */
4956                 sub_dissectors = find_dissector_table(pref->name);
4957                 if (sub_dissectors != NULL) {
4958                     handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)module->title);
4959                     if (handle != NULL) {
4960                         /* Delete all of the old values from the dissector table */
4961                                 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
4962                                         for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
4963                                 dissector_delete_uint(pref->name, j, handle);
4964                                 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
4965                             }
4966
4967                             dissector_delete_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
4968                             decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
4969                                 }
4970
4971                         /* Add new values to the dissector table */
4972                                 for (i = 0; i < newrange->nranges; i++) {
4973                                         for (j = newrange->ranges[i].low; j < newrange->ranges[i].high; j++) {
4974                                 dissector_change_uint(pref->name, j, handle);
4975                                 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
4976                             }
4977
4978                             dissector_change_uint(pref->name, newrange->ranges[i].high, handle);
4979                             decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(newrange->ranges[i].high), NULL, NULL);
4980                                 }
4981
4982                         /* XXX - Do we save the decode_as_entries file here? */
4983                     }
4984                 }
4985             } else {
4986                 g_free(newrange);
4987             }
4988             break;
4989         }
4990
4991         case PREF_COLOR:
4992         {
4993             cval = strtoul(value, NULL, 16);
4994             if ((pref->varp.colorp->red != RED_COMPONENT(cval)) ||
4995                 (pref->varp.colorp->green != GREEN_COMPONENT(cval)) ||
4996                 (pref->varp.colorp->blue != BLUE_COMPONENT(cval))) {
4997                 containing_module->prefs_changed = TRUE;
4998                 pref->varp.colorp->red   = RED_COMPONENT(cval);
4999                 pref->varp.colorp->green = GREEN_COMPONENT(cval);
5000                 pref->varp.colorp->blue  = BLUE_COMPONENT(cval);
5001             }
5002             break;
5003         }
5004
5005         case PREF_CUSTOM:
5006             return pref->custom_cbs.set_cb(pref, value, &containing_module->prefs_changed);
5007
5008         case PREF_STATIC_TEXT:
5009         case PREF_UAT:
5010         {
5011             break;
5012         }
5013         }
5014     }
5015
5016     return PREFS_SET_OK;
5017 }
5018
5019 typedef struct {
5020     FILE     *pf;
5021     gboolean is_gui_module;
5022 } write_gui_pref_arg_t;
5023
5024 const char *
5025 prefs_pref_type_name(pref_t *pref)
5026 {
5027     const char *type_name = "[Unknown]";
5028     int type;
5029
5030     if (!pref) {
5031         return type_name; /* ...or maybe assert? */
5032     }
5033
5034     type = pref->type;
5035
5036     if (IS_PREF_OBSOLETE(type)) {
5037         type_name = "Obsolete";
5038     } else {
5039         RESET_PREF_OBSOLETE(type);
5040     }
5041
5042     switch (type) {
5043
5044     case PREF_UINT:
5045         switch (pref->info.base) {
5046
5047         case 10:
5048             type_name = "Decimal";
5049             break;
5050
5051         case 8:
5052             type_name = "Octal";
5053             break;
5054
5055         case 16:
5056             type_name = "Hexadecimal";
5057             break;
5058         }
5059         break;
5060
5061     case PREF_BOOL:
5062         type_name = "Boolean";
5063         break;
5064
5065     case PREF_ENUM:
5066         type_name = "Choice";
5067         break;
5068
5069     case PREF_STRING:
5070         type_name = "String";
5071         break;
5072
5073     case PREF_FILENAME:
5074         type_name = "Filename";
5075         break;
5076
5077     case PREF_DIRNAME:
5078         type_name = "Directory";
5079         break;
5080
5081     case PREF_RANGE:
5082         type_name = "Range";
5083         break;
5084
5085     case PREF_COLOR:
5086         type_name = "Color";
5087         break;
5088
5089     case PREF_CUSTOM:
5090         if (pref->custom_cbs.type_name_cb)
5091             return pref->custom_cbs.type_name_cb();
5092         type_name = "Custom";
5093         break;
5094
5095     case PREF_DECODE_AS_UINT:
5096         type_name = "Decode As value";
5097         break;
5098
5099     case PREF_DECODE_AS_RANGE:
5100         type_name = "Range (for Decode As)";
5101         break;
5102
5103     case PREF_STATIC_TEXT:
5104         type_name = "Static text";
5105         break;
5106
5107     case PREF_UAT:
5108         type_name = "UAT";
5109         break;
5110     }
5111     return type_name;
5112 }
5113
5114 char *
5115 prefs_pref_type_description(pref_t *pref)
5116 {
5117     const char *type_desc = "An unknown preference type";
5118     int type;
5119
5120     if (!pref) {
5121         return g_strdup_printf("%s.", type_desc); /* ...or maybe assert? */
5122     }
5123
5124     type = pref->type;
5125
5126     if (IS_PREF_OBSOLETE(type)) {
5127         type_desc = "An obsolete preference";
5128     } else {
5129         RESET_PREF_OBSOLETE(type);
5130     }
5131
5132     switch (type) {
5133
5134     case PREF_UINT:
5135         switch (pref->info.base) {
5136
5137         case 10:
5138             type_desc = "A decimal number";
5139             break;
5140
5141         case 8:
5142             type_desc = "An octal number";
5143             break;
5144
5145         case 16:
5146             type_desc = "A hexadecimal number";
5147             break;
5148         }
5149         break;
5150
5151     case PREF_BOOL:
5152         type_desc = "TRUE or FALSE (case-insensitive)";
5153         break;
5154
5155     case PREF_ENUM:
5156     {
5157         const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
5158         GString *enum_str = g_string_new("One of: ");
5159         while (enum_valp->name != NULL) {
5160             g_string_append(enum_str, enum_valp->description);
5161             enum_valp++;
5162             if (enum_valp->name != NULL)
5163                 g_string_append(enum_str, ", ");
5164         }
5165         g_string_append(enum_str, "\n(case-insensitive).");
5166         return g_string_free(enum_str, FALSE);
5167         break;
5168     }
5169
5170     case PREF_STRING:
5171         type_desc = "A string";
5172         break;
5173
5174     case PREF_FILENAME:
5175         type_desc = "A path to a file";
5176         break;
5177
5178     case PREF_DIRNAME:
5179         type_desc = "A path to a directory";
5180         break;
5181
5182     case PREF_RANGE:
5183     {
5184         type_desc = "A string denoting an positive integer range (e.g., \"1-20,30-40\")";
5185         break;
5186     }
5187
5188     case PREF_COLOR:
5189     {
5190         type_desc = "A six-digit hexadecimal RGB color triplet (e.g. fce94f)";
5191         break;
5192     }
5193
5194     case PREF_CUSTOM:
5195         if (pref->custom_cbs.type_description_cb)
5196             return pref->custom_cbs.type_description_cb();
5197         type_desc = "A custom value";
5198         break;
5199
5200     case PREF_DECODE_AS_UINT:
5201         type_desc = "An integer value used in Decode As";
5202         break;
5203
5204     case PREF_DECODE_AS_RANGE:
5205         type_desc = "A string denoting an positive integer range for Decode As";
5206         break;
5207
5208     case PREF_STATIC_TEXT:
5209         type_desc = "[Static text]";
5210         break;
5211
5212     case PREF_UAT:
5213         type_desc = "Configuration data stored in its own file";
5214         break;
5215
5216     default:
5217         break;
5218     }
5219     return g_strdup(type_desc);
5220 }
5221
5222 static gboolean
5223 prefs_pref_is_default(pref_t *pref)
5224 {
5225     int type;
5226     if (!pref) return FALSE;
5227
5228     type = pref->type;
5229     if (IS_PREF_OBSOLETE(type)) {
5230         return FALSE;
5231     } else {
5232         RESET_PREF_OBSOLETE(type);
5233     }
5234
5235     switch (type) {
5236
5237     case PREF_DECODE_AS_UINT:
5238         if (pref->default_val.uint == *pref->varp.uint)
5239             return TRUE;
5240         break;
5241
5242     case PREF_UINT:
5243         if (pref->default_val.uint == *pref->varp.uint)
5244             return TRUE;
5245         break;
5246
5247     case PREF_BOOL:
5248         if (pref->default_val.boolval == *pref->varp.boolp)
5249             return TRUE;
5250         break;
5251
5252     case PREF_ENUM:
5253         if (pref->default_val.enumval == *pref->varp.enump)
5254             return TRUE;
5255         break;
5256
5257     case PREF_STRING:
5258     case PREF_FILENAME:
5259     case PREF_DIRNAME:
5260         if (!(g_strcmp0(pref->default_val.string, *pref->varp.string)))
5261             return TRUE;
5262         break;
5263
5264     case PREF_DECODE_AS_RANGE:
5265     case PREF_RANGE:
5266     {
5267         if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
5268             return TRUE;
5269         break;
5270     }
5271
5272     case PREF_COLOR:
5273     {
5274         if ((pref->default_val.color.red == pref->varp.colorp->red) &&
5275             (pref->default_val.color.green == pref->varp.colorp->green) &&
5276             (pref->default_val.color.blue == pref->varp.colorp->blue))
5277             return TRUE;
5278         break;
5279     }
5280
5281     case PREF_CUSTOM:
5282         return pref->custom_cbs.is_default_cb(pref);
5283
5284     case PREF_STATIC_TEXT:
5285     case PREF_UAT:
5286         return FALSE;
5287         /* g_assert_not_reached(); */
5288         break;
5289     }
5290     return FALSE;
5291 }
5292
5293 char *
5294 prefs_pref_to_str(pref_t *pref, pref_source_t source) {
5295     const char *pref_text = "[Unknown]";
5296     void *valp; /* pointer to preference value */
5297     color_t *pref_color;
5298     gchar *tmp_value, *ret_value;
5299     int type;
5300
5301     if (!pref) {
5302         return g_strdup(pref_text);
5303     }
5304
5305     switch (source) {
5306         case pref_default:
5307             valp = &pref->default_val;
5308             /* valp = &boolval, &enumval, etc. are implied by union property */
5309             pref_color = &pref->default_val.color;
5310             break;
5311         case pref_stashed:
5312             valp = &pref->stashed_val;
5313             /* valp = &boolval, &enumval, etc. are implied by union property */
5314             pref_color = &pref->stashed_val.color;
5315             break;
5316         case pref_current:
5317             valp = pref->varp.uint;
5318             /* valp = boolval, enumval, etc. are implied by union property */
5319             pref_color = pref->varp.colorp;
5320             break;
5321         default:
5322             return g_strdup(pref_text);
5323     }
5324
5325     type = pref->type;
5326     if (IS_PREF_OBSOLETE(type)) {
5327         pref_text = "[Obsolete]";
5328     } else {
5329         RESET_PREF_OBSOLETE(type);
5330     }
5331
5332     switch (type) {
5333
5334     case PREF_DECODE_AS_UINT:
5335     case PREF_UINT:
5336     {
5337         guint pref_uint = *(guint *) valp;
5338         switch (pref->info.base) {
5339
5340         case 10:
5341             return g_strdup_printf("%u", pref_uint);
5342
5343         case 8:
5344             return g_strdup_printf("%#o", pref_uint);
5345
5346         case 16:
5347             return g_strdup_printf("%#x", pref_uint);
5348         }
5349         break;
5350     }
5351
5352     case PREF_BOOL:
5353         return g_strdup((*(gboolean *) valp) ? "TRUE" : "FALSE");
5354
5355     case PREF_ENUM:
5356     {
5357         gint pref_enumval = *(gint *) valp;
5358         /*
5359          * For now, we return the "description" value, so that if we
5360          * save the preferences older versions of Wireshark can at
5361          * least read preferences that they supported; we support
5362          * either the short name or the description when reading
5363          * the preferences file or a "-o" option.
5364          */
5365         const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
5366         while (enum_valp->name != NULL) {
5367             if (enum_valp->value == pref_enumval)
5368                 return g_strdup(enum_valp->description);
5369             enum_valp++;
5370         }
5371         break;
5372     }
5373
5374     case PREF_STRING:
5375     case PREF_FILENAME:
5376     case PREF_DIRNAME:
5377         return g_strdup(*(const char **) valp);
5378
5379     case PREF_DECODE_AS_RANGE:
5380     case PREF_RANGE:
5381         /* Convert wmem to g_alloc memory */
5382         tmp_value = range_convert_range(NULL, *(range_t **) valp);
5383         ret_value = g_strdup(tmp_value);
5384         wmem_free(NULL, tmp_value);
5385         return ret_value;
5386
5387     case PREF_COLOR:
5388         return g_strdup_printf("%02x%02x%02x",
5389                    (pref_color->red * 255 / 65535),
5390                    (pref_color->green * 255 / 65535),
5391                    (pref_color->blue * 255 / 65535));
5392
5393     case PREF_CUSTOM:
5394         if (pref->custom_cbs.to_str_cb)
5395             return pref->custom_cbs.to_str_cb(pref, source == pref_default ? TRUE : FALSE);
5396         pref_text = "[Custom]";
5397         break;
5398
5399     case PREF_STATIC_TEXT:
5400         pref_text = "[Static text]";
5401         break;
5402
5403     case PREF_UAT:
5404     {
5405         uat_t *uat = pref->varp.uat;
5406         if (uat && uat->filename)
5407             return g_strdup_printf("[Managed in the file \"%s\"]", uat->filename);
5408         else
5409             pref_text = "[Managed in an unknown file]";
5410         break;
5411     }
5412
5413     default:
5414         break;
5415     }
5416     return g_strdup(pref_text);
5417 }
5418
5419 /*
5420  * Write out a single dissector preference.
5421  */
5422 static void
5423 write_pref(gpointer data, gpointer user_data)
5424 {
5425     pref_t *pref = (pref_t *)data;
5426     write_pref_arg_t *arg = (write_pref_arg_t *)user_data;
5427     gchar **desc_lines;
5428     int i;
5429     int type;
5430
5431     type = pref->type;
5432
5433     if (IS_PREF_OBSOLETE(type)) {
5434         /*
5435          * This preference is no longer supported; it's not a
5436          * real preference, so we don't write it out (i.e., we
5437          * treat it as if it weren't found in the list of
5438          * preferences, and we weren't called in the first place).
5439          */
5440         return;
5441     } else {
5442         RESET_PREF_OBSOLETE(type);
5443     }
5444
5445     switch (type) {
5446
5447     case PREF_STATIC_TEXT:
5448     case PREF_UAT:
5449         /* Nothing to do; don't bother printing the description */
5450         return;
5451     case PREF_DECODE_AS_UINT:
5452     case PREF_DECODE_AS_RANGE:
5453         /* Data is saved through Decode As mechanism and not part of preferences file */
5454         return;
5455     default:
5456         break;
5457     }
5458
5459     if (pref->type != PREF_CUSTOM || pref->custom_cbs.type_name_cb() != NULL) {
5460         /*
5461          * The prefix will either be the module name or the parent
5462          * name if it's a subtree
5463          */
5464         const char *name_prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
5465         char *type_desc, *pref_text;
5466         const char * def_prefix = prefs_pref_is_default(pref) ? "#" : "";
5467
5468         if (pref->type == PREF_CUSTOM) fprintf(arg->pf, "\n# %s", pref->custom_cbs.type_name_cb());
5469         fprintf(arg->pf, "\n");
5470         if (pref->description &&
5471                 (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
5472             if (pref->type != PREF_CUSTOM) {
5473                 /* We get duplicate lines otherwise. */
5474
5475                 desc_lines = g_strsplit(pref->description,"\n",0);
5476                 for (i = 0; desc_lines[i] != NULL; ++i) {
5477                     fprintf(arg->pf, "# %s\n", desc_lines[i]);
5478                 }
5479                 g_strfreev(desc_lines);
5480             }
5481         } else {
5482             fprintf(arg->pf, "# No description\n");
5483         }
5484
5485         type_desc = prefs_pref_type_description(pref);
5486         desc_lines = g_strsplit(type_desc,"\n",0);
5487         for (i = 0; desc_lines[i] != NULL; ++i) {
5488             fprintf(arg->pf, "# %s\n", desc_lines[i]);
5489         }
5490         g_strfreev(desc_lines);
5491         g_free(type_desc);
5492
5493         pref_text = prefs_pref_to_str(pref, pref_current);
5494         fprintf(arg->pf, "%s%s.%s: ", def_prefix, name_prefix, pref->name);
5495         desc_lines = g_strsplit(pref_text,"\n",0);
5496         for (i = 0; desc_lines[i] != NULL; ++i) {
5497             fprintf(arg->pf, "%s%s\n", i == 0 ? "" : def_prefix, desc_lines[i]);
5498         }
5499         if (i == 0) fprintf(arg->pf, "\n");
5500         g_strfreev(desc_lines);
5501         g_free(pref_text);
5502     }
5503
5504 }
5505
5506 /*
5507  * Write out all preferences for a module.
5508  */
5509 static guint
5510 write_module_prefs(module_t *module, gpointer user_data)
5511 {
5512     write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
5513     write_pref_arg_t arg;
5514
5515     /* The GUI module needs to be explicitly called out so it
5516        can be written out of order */
5517     if ((module == gui_module) && (gui_pref_arg->is_gui_module != TRUE))
5518         return 0;
5519
5520     /* Write a header for the main modules and GUI sub-modules */
5521     if (((module->parent == NULL) || (module->parent == gui_module)) &&
5522         ((prefs_module_has_submodules(module)) ||
5523          (module->numprefs > 0) ||
5524          (module->name == NULL))) {
5525          if ((module->name == NULL) && (module->parent != NULL)) {
5526             fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
5527          } else {
5528             fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
5529          }
5530     }
5531
5532     arg.module = module;
5533     arg.pf = gui_pref_arg->pf;
5534     g_list_foreach(arg.module->prefs, write_pref, &arg);
5535
5536     if (prefs_module_has_submodules(module))
5537         return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
5538
5539     return 0;
5540 }
5541
5542 /* Write out "prefs" to the user's preferences file, and return 0.
5543
5544    If the preferences file path is NULL, write to stdout.
5545
5546    If we got an error, stuff a pointer to the path of the preferences file
5547    into "*pf_path_return", and return the errno. */
5548 int
5549 write_prefs(char **pf_path_return)
5550 {
5551     char        *pf_path;
5552     FILE        *pf;
5553     write_gui_pref_arg_t write_gui_pref_info;
5554
5555     /* Needed for "-G defaultprefs" */
5556     init_prefs();
5557
5558     /* To do:
5559      * - Split output lines longer than MAX_VAL_LEN
5560      * - Create a function for the preference directory check/creation
5561      *   so that duplication can be avoided with filter.c
5562      */
5563
5564     if (pf_path_return != NULL) {
5565         pf_path = get_persconffile_path(PF_NAME, TRUE);
5566         if ((pf = ws_fopen(pf_path, "w")) == NULL) {
5567             *pf_path_return = pf_path;
5568             return errno;
5569         }
5570         g_free(pf_path);
5571     } else {
5572         pf = stdout;
5573     }
5574
5575     fputs("# Configuration file for Wireshark " VERSION ".\n"
5576           "#\n"
5577           "# This file is regenerated each time preferences are saved within\n"
5578           "# Wireshark. Making manual changes should be safe, however.\n"
5579           "# Preferences that have been commented out have not been\n"
5580           "# changed from their default value.\n", pf);
5581
5582     /*
5583      * For "backwards compatibility" the GUI module is written first as it's
5584      * at the top of the file.  This is followed by all modules that can't
5585      * fit into the preferences read/write API.  Finally the remaining modules
5586      * are written in alphabetical order (including of course the protocol preferences)
5587      */
5588     write_gui_pref_info.pf = pf;
5589     write_gui_pref_info.is_gui_module = TRUE;
5590
5591     write_module_prefs(gui_module, &write_gui_pref_info);
5592
5593     {
5594         struct filter_expression *fe = *(struct filter_expression **)prefs.filter_expressions;
5595
5596         if (fe != NULL)
5597             fprintf(pf, "\n####### Filter Expressions ########\n\n");
5598
5599         while (fe != NULL) {
5600             if (fe->deleted == FALSE) {
5601                 fprintf(pf, "%s: %s\n", PRS_GUI_FILTER_LABEL, fe->label);
5602                 fprintf(pf, "%s: %s\n", PRS_GUI_FILTER_ENABLED,
5603                         fe->enabled == TRUE ? "TRUE" : "FALSE");
5604                 fprintf(pf, "%s: %s\n", PRS_GUI_FILTER_EXPR, fe->expression);
5605             }
5606             fe = fe->next;
5607         }
5608     }
5609
5610     write_gui_pref_info.is_gui_module = FALSE;
5611     prefs_modules_foreach_submodules(NULL, write_module_prefs, &write_gui_pref_info);
5612
5613     fclose(pf);
5614
5615     /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
5616        an error indication, or maybe write to a new preferences file and
5617        rename that file on top of the old one only if there are not I/O
5618        errors. */
5619     return 0;
5620 }
5621
5622 /** The col_list is only partly managed by the custom preference API
5623  * because its data is shared between multiple preferences, so
5624  * it's freed here
5625  */
5626 static void
5627 free_col_info(GList *list)
5628 {
5629     fmt_data *cfmt;
5630     GList *list_head = list;
5631
5632     while (list != NULL) {
5633         cfmt = (fmt_data *)list->data;
5634
5635         g_free(cfmt->title);
5636         g_free(cfmt->custom_fields);
5637         g_free(cfmt);
5638         list = g_list_next(list);
5639     }
5640     g_list_free(list_head);
5641 }
5642
5643 /*
5644  * Editor modelines
5645  *
5646  * Local Variables:
5647  * c-basic-offset: 4
5648  * tab-width: 8
5649  * indent-tabs-mode: nil
5650  * End:
5651  *
5652  * ex: set shiftwidth=4 tabstop=8 expandtab:
5653  * :indentSize=4:tabSize=8:noTabs=true:
5654  */