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