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