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