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