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