Convert range API to always use wmem memory.
[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         wmem_free(wmem_epan_scope(), *pref->varp.range);
268         *pref->varp.range = NULL;
269         wmem_free(wmem_epan_scope(), 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(wmem_epan_scope());
1184     preference->varp.range = var;
1185     preference->default_val.range = range_copy(wmem_epan_scope(), *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(wmem_epan_scope(), &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         wmem_free(wmem_epan_scope(), *pref->varp.range);
1215         *pref->varp.range = newrange;
1216     } else {
1217         wmem_free(wmem_epan_scope(), 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         wmem_free(wmem_epan_scope(), *pref->varp.range);
3326         *pref->varp.range = range_copy(wmem_epan_scope(), 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 *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},