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