Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/prefs.c
Line
Count
Source (jump to first uncovered line)
1
/* prefs.c
2
 * Routines for handling preferences
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include "config.h"
12
0
#define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
13
14
#include "ws_diag_control.h"
15
16
#include <stdlib.h>
17
#include <string.h>
18
#include <errno.h>
19
#ifdef _WIN32
20
#include <windows.h>
21
#endif
22
23
#include <glib.h>
24
25
#include <stdio.h>
26
#include <wsutil/application_flavor.h>
27
#include <wsutil/filesystem.h>
28
#include <epan/addr_resolv.h>
29
#include <epan/oids.h>
30
#include <epan/maxmind_db.h>
31
#include <epan/packet.h>
32
#include <epan/prefs.h>
33
#include <epan/proto.h>
34
#include <epan/strutil.h>
35
#include <epan/column.h>
36
#include <epan/decode_as.h>
37
#include <ui/capture_opts.h>
38
#include <wsutil/file_util.h>
39
#include <wsutil/report_message.h>
40
#include <wsutil/wslog.h>
41
#include <wsutil/ws_assert.h>
42
#include <wsutil/array.h>
43
44
#include <epan/prefs-int.h>
45
#include <epan/uat-int.h>
46
47
#include "epan/filter_expressions.h"
48
49
#include "epan/wmem_scopes.h"
50
#include <epan/stats_tree.h>
51
52
#define REG_HKCU_WIRESHARK_KEY "Software\\Wireshark"
53
54
/*
55
 * Module alias.
56
 */
57
typedef struct pref_module_alias {
58
    const char *name;           /**< name of module alias */
59
    module_t *module;           /**< module for which it's an alias */
60
} module_alias_t;
61
62
/* Internal functions */
63
static module_t *find_subtree(module_t *parent, const char *tilte);
64
static module_t *prefs_register_module_or_subtree(module_t *parent,
65
    const char *name, const char *title, const char *description, const char *help,
66
    bool is_subtree, void (*apply_cb)(void), bool use_gui);
67
static void prefs_register_modules(void);
68
static module_t *prefs_find_module_alias(const char *name);
69
static prefs_set_pref_e set_pref(char*, const char*, void *, bool);
70
static void free_col_info(GList *);
71
static void pre_init_prefs(void);
72
static bool prefs_is_column_visible(const char *cols_hidden, int col);
73
static bool prefs_is_column_fmt_visible(const char *cols_hidden, fmt_data *cfmt);
74
static unsigned prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
75
                          void *user_data, bool skip_obsolete);
76
static int find_val_for_string(const char *needle, const enum_val_t *haystack, int default_value);
77
78
28
#define PF_NAME         "preferences"
79
14
#define OLD_GPF_NAME    "wireshark.conf" /* old name for global preferences file */
80
81
static bool prefs_initialized;
82
static char *gpf_path;
83
static char *cols_hidden_list;
84
static char *cols_hidden_fmt_list;
85
static bool gui_theme_is_dark;
86
87
/*
88
 * XXX - variables to allow us to attempt to interpret the first
89
 * "mgcp.{tcp,udp}.port" in a preferences file as
90
 * "mgcp.{tcp,udp}.gateway_port" and the second as
91
 * "mgcp.{tcp,udp}.callagent_port".
92
 */
93
static int mgcp_tcp_port_count;
94
static int mgcp_udp_port_count;
95
96
e_prefs prefs;
97
98
static const enum_val_t gui_console_open_type[] = {
99
    {"NEVER", "NEVER", LOG_CONSOLE_OPEN_NEVER},
100
    {"AUTOMATIC", "AUTOMATIC", LOG_CONSOLE_OPEN_AUTO},
101
    {"ALWAYS", "ALWAYS", LOG_CONSOLE_OPEN_ALWAYS},
102
    {NULL, NULL, -1}
103
};
104
105
static const enum_val_t gui_version_placement_type[] = {
106
    {"WELCOME", "WELCOME", version_welcome_only},
107
    {"TITLE", "TITLE", version_title_only},
108
    {"BOTH", "BOTH", version_both},
109
    {"NEITHER", "NEITHER", version_neither},
110
    {NULL, NULL, -1}
111
};
112
113
static const enum_val_t gui_fileopen_style[] = {
114
    {"LAST_OPENED", "LAST_OPENED", FO_STYLE_LAST_OPENED},
115
    {"SPECIFIED", "SPECIFIED", FO_STYLE_SPECIFIED},
116
    {"CWD", "CWD", FO_STYLE_CWD},
117
    {NULL, NULL, -1}
118
};
119
120
static const enum_val_t gui_toolbar_style[] = {
121
    {"ICONS", "ICONS", 0},
122
    {"TEXT", "TEXT", 1},
123
    {"BOTH", "BOTH", 2},
124
    {NULL, NULL, -1}
125
};
126
127
static const enum_val_t gui_layout_content[] = {
128
    {"NONE", "NONE", 0},
129
    {"PLIST", "PLIST", 1},
130
    {"PDETAILS", "PDETAILS", 2},
131
    {"PBYTES", "PBYTES", 3},
132
    {"PDIAGRAM", "PDIAGRAM", 4},
133
    {NULL, NULL, -1}
134
};
135
136
static const enum_val_t gui_packet_dialog_layout[] = {
137
    {"vertical", "Vertical (Stacked)", layout_vertical},
138
    {"horizontal", "Horizontal (Side-by-side)", layout_horizontal},
139
    {NULL, NULL, -1}
140
};
141
142
static const enum_val_t gui_update_channel[] = {
143
    {"DEVELOPMENT", "DEVELOPMENT", UPDATE_CHANNEL_DEVELOPMENT},
144
    {"STABLE", "STABLE", UPDATE_CHANNEL_STABLE},
145
    {NULL, NULL, -1}
146
};
147
148
static const enum_val_t gui_selection_style[] = {
149
    {"DEFAULT", "DEFAULT",   COLOR_STYLE_DEFAULT},
150
    {"FLAT",    "FLAT",      COLOR_STYLE_FLAT},
151
    {"GRADIENT", "GRADIENT", COLOR_STYLE_GRADIENT},
152
    {NULL, NULL, -1}
153
};
154
155
static const enum_val_t gui_color_scheme[] = {
156
    {"system",  "System Default",   COLOR_SCHEME_DEFAULT},
157
    {"light",   "Light Mode",       COLOR_SCHEME_LIGHT},
158
    {"dark",    "Dark Mode",        COLOR_SCHEME_DARK},
159
    {NULL, NULL, -1}
160
};
161
162
static const enum_val_t gui_packet_list_copy_format_options_for_keyboard_shortcut[] = {
163
    {"TEXT", "Text", COPY_FORMAT_TEXT},
164
    {"CSV",  "CSV",  COPY_FORMAT_CSV},
165
    {"YAML", "YAML", COPY_FORMAT_YAML},
166
    {"HTML", "HTML", COPY_FORMAT_HTML},
167
    {NULL, NULL, -1}
168
};
169
170
/* None : Historical behavior, no deinterlacing */
171
#define CONV_DEINT_CHOICE_NONE 0
172
/* MI : MAC & Interface */
173
#define CONV_DEINT_CHOICE_MI CONV_DEINT_KEY_MAC + CONV_DEINT_KEY_INTERFACE
174
/* VM : VLAN & MAC */
175
#define CONV_DEINT_CHOICE_VM CONV_DEINT_KEY_VLAN + CONV_DEINT_KEY_MAC
176
/* VMI : VLAN & MAC & Interface */
177
#define CONV_DEINT_CHOICE_VMI CONV_DEINT_KEY_VLAN + CONV_DEINT_KEY_MAC + CONV_DEINT_KEY_INTERFACE
178
179
static const enum_val_t conv_deint_options[] = {
180
    {"NONE", "NONE", CONV_DEINT_CHOICE_NONE},
181
    {".MI", ".MI", CONV_DEINT_CHOICE_MI },
182
    {"VM.", "VM.", CONV_DEINT_CHOICE_VM },
183
    {"VMI", "VMI", CONV_DEINT_CHOICE_VMI },
184
    {NULL, NULL, -1}
185
};
186
187
static const enum_val_t abs_time_format_options[] = {
188
    {"NEVER", "Never", ABS_TIME_ASCII_NEVER},
189
    {"TREE", "Protocol tree only", ABS_TIME_ASCII_TREE},
190
    {"COLUMN", "Protocol tree and columns", ABS_TIME_ASCII_COLUMN},
191
    {"ALWAYS", "Always", ABS_TIME_ASCII_ALWAYS},
192
    {NULL, NULL, -1}
193
};
194
195
static int num_capture_cols = 7;
196
static const char *capture_cols[7] = {
197
    "INTERFACE",
198
    "LINK",
199
    "PMODE",
200
    "SNAPLEN",
201
    "MONITOR",
202
    "BUFFER",
203
    "FILTER"
204
};
205
#define CAPTURE_COL_TYPE_DESCRIPTION \
206
0
    "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
207
208
static const enum_val_t gui_packet_list_elide_mode[] = {
209
    {"LEFT", "LEFT", ELIDE_LEFT},
210
    {"RIGHT", "RIGHT", ELIDE_RIGHT},
211
    {"MIDDLE", "MIDDLE", ELIDE_MIDDLE},
212
    {"NONE", "NONE", ELIDE_NONE},
213
    {NULL, NULL, -1}
214
};
215
216
/** Struct to hold preference data */
217
struct preference {
218
    const char *name;                /**< name of preference */
219
    const char *title;               /**< title to use in GUI */
220
    const char *description;         /**< human-readable description of preference */
221
    int ordinal;                     /**< ordinal number of this preference */
222
    pref_type_e type;                /**< type of that preference */
223
    bool obsolete;                   /**< obsolete preference flag */
224
    unsigned int effect_flags;       /**< Flags of types effected by preference (PREF_TYPE_DISSECTION, PREF_EFFECT_CAPTURE, etc).
225
                                          Flags must be non-zero to ensure saving to disk */
226
    union {                          /* The Qt preference code assumes that these will all be pointers (and unique) */
227
        unsigned *uint;
228
        bool *boolp;
229
        int *enump;
230
        char **string;
231
        range_t **range;
232
        struct epan_uat* uat;
233
        color_t *colorp;
234
        GList** list;
235
    } varp;                          /**< pointer to variable storing the value */
236
    union {
237
        unsigned uint;
238
        bool boolval;
239
        int enumval;
240
        char *string;
241
        range_t *range;
242
        color_t color;
243
        GList* list;
244
    } stashed_val;                     /**< original value, when editing from the GUI */
245
    union {
246
        unsigned uint;
247
        bool boolval;
248
        int enumval;
249
        char *string;
250
        range_t *range;
251
        color_t color;
252
        GList* list;
253
    } default_val;                   /**< the default value of the preference */
254
    union {
255
      unsigned base;                 /**< input/output base, for PREF_UINT */
256
      uint32_t max_value;            /**< maximum value of a range */
257
      struct {
258
        const enum_val_t *enumvals;  /**< list of name & values */
259
        bool radio_buttons;          /**< true if it should be shown as
260
                                          radio buttons rather than as an
261
                                          option menu or combo box in
262
                                          the preferences tab */
263
      } enum_info;                   /**< for PREF_ENUM */
264
    } info;                          /**< display/text file information */
265
    struct pref_custom_cbs custom_cbs;   /**< for PREF_CUSTOM */
266
    const char *dissector_table;     /**< for PREF_DECODE_AS_RANGE */
267
    const char *dissector_desc;      /**< for PREF_DECODE_AS_RANGE */
268
};
269
270
const char* prefs_get_description(pref_t *pref)
271
0
{
272
0
    return pref->description;
273
0
}
274
275
const char* prefs_get_title(pref_t *pref)
276
0
{
277
0
    return pref->title;
278
0
}
279
280
int prefs_get_type(pref_t *pref)
281
0
{
282
0
    return pref->type;
283
0
}
284
285
const char* prefs_get_name(pref_t *pref)
286
0
{
287
0
    return pref->name;
288
0
}
289
290
uint32_t prefs_get_max_value(pref_t *pref)
291
0
{
292
0
    return pref->info.max_value;
293
0
}
294
295
const char* prefs_get_dissector_table(pref_t *pref)
296
0
{
297
0
    return pref->dissector_table;
298
0
}
299
300
static const char* prefs_get_dissector_description(pref_t *pref)
301
0
{
302
0
    return pref->dissector_desc;
303
0
}
304
305
/*
306
 * List of all modules with preference settings.
307
 */
308
static wmem_tree_t *prefs_modules;
309
310
/*
311
 * List of all modules that should show up at the top level of the
312
 * tree in the preference dialog box.
313
 */
314
static wmem_tree_t *prefs_top_level_modules;
315
316
/*
317
 * List of aliases for modules.
318
 */
319
static wmem_tree_t *prefs_module_aliases;
320
321
/** Sets up memory used by proto routines. Called at program startup */
322
void
323
prefs_init(void)
324
14
{
325
14
    memset(&prefs, 0, sizeof(prefs));
326
14
    prefs_modules = wmem_tree_new(wmem_epan_scope());
327
14
    prefs_top_level_modules = wmem_tree_new(wmem_epan_scope());
328
14
    prefs_module_aliases = wmem_tree_new(wmem_epan_scope());
329
14
}
330
331
/*
332
 * Free the strings for a string-like preference.
333
 */
334
static void
335
free_string_like_preference(pref_t *pref)
336
0
{
337
0
    g_free(*pref->varp.string);
338
0
    *pref->varp.string = NULL;
339
0
    g_free(pref->default_val.string);
340
0
    pref->default_val.string = NULL;
341
0
}
342
343
static void
344
free_pref(void *data, void *user_data _U_)
345
0
{
346
0
    pref_t *pref = (pref_t *)data;
347
348
0
    switch (pref->type) {
349
0
    case PREF_BOOL:
350
0
    case PREF_ENUM:
351
0
    case PREF_UINT:
352
0
    case PREF_STATIC_TEXT:
353
0
    case PREF_UAT:
354
0
    case PREF_COLOR:
355
0
        break;
356
0
    case PREF_STRING:
357
0
    case PREF_SAVE_FILENAME:
358
0
    case PREF_OPEN_FILENAME:
359
0
    case PREF_DIRNAME:
360
0
    case PREF_PASSWORD:
361
0
    case PREF_DISSECTOR:
362
0
        free_string_like_preference(pref);
363
0
        break;
364
0
    case PREF_RANGE:
365
0
    case PREF_DECODE_AS_RANGE:
366
0
        wmem_free(wmem_epan_scope(), *pref->varp.range);
367
0
        *pref->varp.range = NULL;
368
0
        wmem_free(wmem_epan_scope(), pref->default_val.range);
369
0
        pref->default_val.range = NULL;
370
0
        break;
371
0
    case PREF_CUSTOM:
372
0
        if (strcmp(pref->name, "columns") == 0)
373
0
          pref->stashed_val.boolval = true;
374
0
        pref->custom_cbs.free_cb(pref);
375
0
        break;
376
    /* non-generic preferences */
377
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
378
0
        break;
379
0
    }
380
381
0
    g_free(pref);
382
0
}
383
384
static unsigned
385
free_module_prefs(module_t *module, void *data _U_)
386
0
{
387
0
    if (module->prefs) {
388
0
        g_list_foreach(module->prefs, free_pref, NULL);
389
0
        g_list_free(module->prefs);
390
0
    }
391
0
    module->prefs = NULL;
392
0
    module->numprefs = 0;
393
0
    if (module->submodules) {
394
0
        prefs_module_list_foreach(module->submodules, free_module_prefs, NULL, false);
395
0
    }
396
    /*  We don't free the actual module: its submodules pointer points to
397
        a wmem_tree and the module itself is stored in a wmem_tree
398
     */
399
400
0
    return 0;
401
0
}
402
403
/** Frees memory used by proto routines. Called at program shutdown */
404
void
405
prefs_cleanup(void)
406
0
{
407
    /*  This isn't strictly necessary since we're exiting anyway, but let's
408
     *  do what clean up we can.
409
     */
410
0
    prefs_module_list_foreach(prefs_modules, free_module_prefs, NULL, false);
411
412
    /* Clean the uats */
413
0
    uat_cleanup();
414
415
    /* Shut down mmdbresolve */
416
0
    maxmind_db_pref_cleanup();
417
418
0
    g_free(prefs.saved_at_version);
419
0
    g_free(gpf_path);
420
0
    gpf_path = NULL;
421
0
}
422
423
void prefs_set_gui_theme_is_dark(bool is_dark)
424
0
{
425
0
    gui_theme_is_dark = is_dark;
426
0
}
427
428
/*
429
 * Register a module that will have preferences.
430
 * Specify the module under which to register it or NULL to register it
431
 * at the top level, the name used for the module in the preferences file,
432
 * the title used in the tab for it in a preferences dialog box, and a
433
 * routine to call back when we apply the preferences.
434
 */
435
static module_t *
436
prefs_register_module(module_t *parent, const char *name, const char *title,
437
                      const char *description, const char *help, void (*apply_cb)(void),
438
                      const bool use_gui)
439
12.6k
{
440
12.6k
    return prefs_register_module_or_subtree(parent, name, title, description, help,
441
12.6k
                                            false, apply_cb, use_gui);
442
12.6k
}
443
444
static void
445
prefs_deregister_module(module_t *parent, const char *name, const char *title)
446
0
{
447
    /* Remove this module from the list of all modules */
448
0
    module_t *module = (module_t *)wmem_tree_remove_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
449
450
0
    if (!module)
451
0
        return;
452
453
0
    if (parent == NULL) {
454
        /* Remove from top */
455
0
        wmem_tree_remove_string(prefs_top_level_modules, title, WMEM_TREE_STRING_NOCASE);
456
0
    } else if (parent->submodules) {
457
        /* Remove from parent */
458
0
        wmem_tree_remove_string(parent->submodules, title, WMEM_TREE_STRING_NOCASE);
459
0
    }
460
461
0
    free_module_prefs(module, NULL);
462
0
    wmem_free(wmem_epan_scope(), module);
463
0
}
464
465
/*
466
 * Register a subtree that will have modules under it.
467
 * Specify the module under which to register it or NULL to register it
468
 * at the top level and the title used in the tab for it in a preferences
469
 * dialog box.
470
 */
471
static module_t *
472
prefs_register_subtree(module_t *parent, const char *title, const char *description,
473
                       void (*apply_cb)(void))
474
98
{
475
98
    return prefs_register_module_or_subtree(parent, NULL, title, description, NULL,
476
98
                                            true, apply_cb,
477
98
                                            parent ? parent->use_gui : false);
478
98
}
479
480
static module_t *
481
prefs_register_module_or_subtree(module_t *parent, const char *name,
482
                                 const char *title, const char *description,
483
                                 const char *help,
484
                                 bool is_subtree, void (*apply_cb)(void),
485
                                 bool use_gui)
486
12.7k
{
487
12.7k
    module_t *module;
488
489
    /* this module may have been created as a subtree item previously */
490
12.7k
    if ((module = find_subtree(parent, title))) {
491
        /* the module is currently a subtree */
492
14
        module->name = name;
493
14
        module->apply_cb = apply_cb;
494
14
        module->description = description;
495
14
        module->help = help;
496
497
        /* Registering it as a module (not just as a subtree) twice is an
498
         * error in the code for the same reason as below. */
499
14
        if (prefs_find_module(name) != NULL) {
500
0
            ws_error("Preference module \"%s\" is being registered twice", name);
501
0
        }
502
14
        wmem_tree_insert_string(prefs_modules, name, module,
503
14
                              WMEM_TREE_STRING_NOCASE);
504
505
14
        return module;
506
14
    }
507
508
12.7k
    module = wmem_new(wmem_epan_scope(), module_t);
509
12.7k
    module->name = name;
510
12.7k
    module->title = title;
511
12.7k
    module->description = description;
512
12.7k
    module->help = help;
513
12.7k
    module->apply_cb = apply_cb;
514
12.7k
    module->prefs = NULL;    /* no preferences, to start */
515
12.7k
    module->parent = parent;
516
12.7k
    module->submodules = NULL;    /* no submodules, to start */
517
12.7k
    module->numprefs = 0;
518
12.7k
    module->prefs_changed_flags = 0;
519
12.7k
    module->obsolete = false;
520
12.7k
    module->use_gui = use_gui;
521
    /* A module's preferences affects dissection unless otherwise told */
522
12.7k
    module->effect_flags = PREF_EFFECT_DISSECTION;
523
524
    /*
525
     * Do we have a module name?
526
     */
527
12.7k
    if (name != NULL) {
528
529
        /* Accept any letter case to conform with protocol names. ASN1 protocols
530
         * don't use lower case names, so we can't require lower case. */
531
12.6k
        if (module_check_valid_name(name, false) != '\0') {
532
0
                ws_error("Preference module \"%s\" contains invalid characters", name);
533
0
        }
534
535
        /*
536
         * Make sure there's not already a module with that
537
         * name.  Crash if there is, as that's an error in the
538
         * code, and the code has to be fixed not to register
539
         * more than one module with the same name.
540
         *
541
         * We search the list of all modules; the subtree stuff
542
         * doesn't require preferences in subtrees to have names
543
         * that reflect the subtree they're in (that would require
544
         * protocol preferences to have a bogus "protocol.", or
545
         * something such as that, to be added to all their names).
546
         */
547
12.6k
        if (prefs_find_module(name) != NULL)
548
0
            ws_error("Preference module \"%s\" is being registered twice", name);
549
550
        /*
551
         * Insert this module in the list of all modules.
552
         */
553
12.6k
        wmem_tree_insert_string(prefs_modules, name, module, WMEM_TREE_STRING_NOCASE);
554
12.6k
    } else {
555
        /*
556
         * This has no name, just a title; check to make sure it's a
557
         * subtree, and crash if it's not.
558
         */
559
98
        if (!is_subtree)
560
0
            ws_error("Preferences module with no name is being registered at the top level");
561
98
    }
562
563
    /*
564
     * Insert this module into the appropriate place in the display
565
     * tree.
566
     */
567
12.7k
    if (parent == NULL) {
568
        /*
569
         * It goes at the top.
570
         */
571
168
        wmem_tree_insert_string(prefs_top_level_modules, title, module, WMEM_TREE_STRING_NOCASE);
572
12.5k
    } else {
573
        /*
574
         * It goes into the list for this module.
575
         */
576
577
12.5k
        if (parent->submodules == NULL)
578
112
            parent->submodules = wmem_tree_new(wmem_epan_scope());
579
580
12.5k
        wmem_tree_insert_string(parent->submodules, title, module, WMEM_TREE_STRING_NOCASE);
581
12.5k
    }
582
583
12.7k
    return module;
584
12.7k
}
585
586
void
587
prefs_register_module_alias(const char *name, module_t *module)
588
140
{
589
140
    module_alias_t *alias;
590
591
    /*
592
     * Accept any name that can occur in protocol names. We allow upper-case
593
     * letters, to handle the Diameter dissector having used "Diameter" rather
594
     * than "diameter" as its preference module name in the past.
595
     *
596
     * Crash if the name is invalid, as that's an error in the code, but the name
597
     * can be used on the command line, and shouldn't require quoting, etc.
598
     */
599
140
    if (module_check_valid_name(name, false) != '\0') {
600
0
        ws_error("Preference module alias \"%s\" contains invalid characters", name);
601
0
    }
602
603
    /*
604
     * Make sure there's not already an alias with that
605
     * name.  Crash if there is, as that's an error in the
606
     * code, and the code has to be fixed not to register
607
     * more than one alias with the same name.
608
     *
609
     * We search the list of all aliases.
610
     */
611
140
    if (prefs_find_module_alias(name) != NULL)
612
0
        ws_error("Preference module alias \"%s\" is being registered twice", name);
613
614
140
    alias = wmem_new(wmem_epan_scope(), module_alias_t);
615
140
    alias->name = name;
616
140
    alias->module = module;
617
618
    /*
619
     * Insert this module in the list of all modules.
620
     */
621
140
    wmem_tree_insert_string(prefs_module_aliases, name, alias, WMEM_TREE_STRING_NOCASE);
622
140
}
623
624
/*
625
 * Register that a protocol has preferences.
626
 */
627
module_t *protocols_module;
628
629
module_t *
630
prefs_register_protocol(int id, void (*apply_cb)(void))
631
11.7k
{
632
11.7k
    protocol_t *protocol;
633
634
    /*
635
     * Have we yet created the "Protocols" subtree?
636
     */
637
11.7k
    if (protocols_module == NULL) {
638
        /*
639
         * No.  Register Protocols subtree as well as any preferences
640
         * for non-dissector modules.
641
         */
642
14
        pre_init_prefs();
643
14
        prefs_register_modules();
644
14
    }
645
11.7k
    protocol = find_protocol_by_id(id);
646
11.7k
    if (protocol == NULL)
647
0
        ws_error("Protocol preferences being registered with an invalid protocol ID");
648
11.7k
    return prefs_register_module(protocols_module,
649
11.7k
                                 proto_get_protocol_filter_name(id),
650
11.7k
                                 proto_get_protocol_short_name(protocol),
651
11.7k
                                 proto_get_protocol_name(id), NULL, apply_cb, true);
652
11.7k
}
653
654
void
655
prefs_deregister_protocol (int id)
656
0
{
657
0
    protocol_t *protocol = find_protocol_by_id(id);
658
0
    if (protocol == NULL)
659
0
        ws_error("Protocol preferences being de-registered with an invalid protocol ID");
660
0
    prefs_deregister_module (protocols_module,
661
0
                             proto_get_protocol_filter_name(id),
662
0
                             proto_get_protocol_short_name(protocol));
663
0
}
664
665
module_t *
666
prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
667
616
{
668
616
    protocol_t *protocol;
669
616
    module_t   *subtree_module;
670
616
    module_t   *new_module;
671
616
    char       *sep = NULL, *ptr = NULL, *orig = NULL;
672
673
    /*
674
     * Have we yet created the "Protocols" subtree?
675
     * XXX - can we just do this by registering Protocols/{subtree}?
676
     * If not, why not?
677
     */
678
616
    if (protocols_module == NULL) {
679
        /*
680
         * No.  Register Protocols subtree as well as any preferences
681
         * for non-dissector modules.
682
         */
683
0
        pre_init_prefs();
684
0
        prefs_register_modules();
685
0
    }
686
687
616
    subtree_module = protocols_module;
688
689
616
    if (subtree) {
690
        /* take a copy of the buffer, orig keeps a base pointer while ptr
691
         * walks through the string */
692
616
        orig = ptr = g_strdup(subtree);
693
694
1.33k
        while (ptr && *ptr) {
695
696
714
            if ((sep = strchr(ptr, '/')))
697
98
                *sep++ = '\0';
698
699
714
            if (!(new_module = find_subtree(subtree_module, ptr))) {
700
                /*
701
                 * There's no such module; create it, with the description
702
                 * being the name (if it's later registered explicitly
703
                 * with a description, that will override it).
704
                 */
705
42
                ptr = wmem_strdup(wmem_epan_scope(), ptr);
706
42
                new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL);
707
42
            }
708
709
714
            subtree_module = new_module;
710
714
            ptr = sep;
711
712
714
        }
713
714
616
        g_free(orig);
715
616
    }
716
717
616
    protocol = find_protocol_by_id(id);
718
616
    if (protocol == NULL)
719
0
        ws_error("Protocol subtree being registered with an invalid protocol ID");
720
616
    return prefs_register_module(subtree_module,
721
616
                                 proto_get_protocol_filter_name(id),
722
616
                                 proto_get_protocol_short_name(protocol),
723
616
                                 proto_get_protocol_name(id), NULL, apply_cb, true);
724
616
}
725
726
727
/*
728
 * Register that a protocol used to have preferences but no longer does,
729
 * by creating an "obsolete" module for it.
730
 */
731
module_t *
732
prefs_register_protocol_obsolete(int id)
733
140
{
734
140
    module_t *module;
735
140
    protocol_t *protocol;
736
737
    /*
738
     * Have we yet created the "Protocols" subtree?
739
     */
740
140
    if (protocols_module == NULL) {
741
        /*
742
         * No.  Register Protocols subtree as well as any preferences
743
         * for non-dissector modules.
744
         */
745
0
        pre_init_prefs();
746
0
        prefs_register_modules();
747
0
    }
748
140
    protocol = find_protocol_by_id(id);
749
140
    if (protocol == NULL)
750
0
        ws_error("Protocol being registered with an invalid protocol ID");
751
140
    module = prefs_register_module(protocols_module,
752
140
                                   proto_get_protocol_filter_name(id),
753
140
                                   proto_get_protocol_short_name(protocol),
754
140
                                   proto_get_protocol_name(id), NULL, NULL, true);
755
140
    module->obsolete = true;
756
140
    return module;
757
140
}
758
759
/*
760
 * Register that a statistical tap has preferences.
761
 *
762
 * "name" is a name for the tap to use on the command line with "-o"
763
 * and in preference files.
764
 *
765
 * "title" is a short human-readable name for the tap.
766
 *
767
 * "description" is a longer human-readable description of the tap.
768
 */
769
module_t *stats_module;
770
771
module_t *
772
prefs_register_stat(const char *name, const char *title,
773
                    const char *description, void (*apply_cb)(void))
774
0
{
775
    /*
776
     * Have we yet created the "Statistics" subtree?
777
     */
778
0
    if (stats_module == NULL) {
779
        /*
780
         * No.  Register Statistics subtree as well as any preferences
781
         * for non-dissector modules.
782
         */
783
0
        pre_init_prefs();
784
0
        prefs_register_modules();
785
0
    }
786
787
0
    return prefs_register_module(stats_module, name, title, description, NULL,
788
0
                                 apply_cb, true);
789
0
}
790
791
/*
792
 * Register that a codec has preferences.
793
 *
794
 * "name" is a name for the codec to use on the command line with "-o"
795
 * and in preference files.
796
 *
797
 * "title" is a short human-readable name for the codec.
798
 *
799
 * "description" is a longer human-readable description of the codec.
800
 */
801
module_t *codecs_module;
802
803
module_t *
804
prefs_register_codec(const char *name, const char *title,
805
                     const char *description, void (*apply_cb)(void))
806
0
{
807
    /*
808
     * Have we yet created the "Codecs" subtree?
809
     */
810
0
    if (codecs_module == NULL) {
811
        /*
812
         * No.  Register Codecs subtree as well as any preferences
813
         * for non-dissector modules.
814
         */
815
0
        pre_init_prefs();
816
0
        prefs_register_modules();
817
0
    }
818
819
0
    return prefs_register_module(codecs_module, name, title, description, NULL,
820
0
                                 apply_cb, true);
821
0
}
822
823
module_t *
824
prefs_find_module(const char *name)
825
24.0k
{
826
24.0k
    return (module_t *)wmem_tree_lookup_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
827
24.0k
}
828
829
static module_t *
830
find_subtree(module_t *parent, const char *name)
831
13.4k
{
832
13.4k
    return (module_t *)wmem_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, WMEM_TREE_STRING_NOCASE);
833
13.4k
}
834
835
/*
836
 * Call a callback function, with a specified argument, for each module
837
 * in a list of modules.  If the list is NULL, searches the top-level
838
 * list in the display tree of modules.  If any callback returns a
839
 * non-zero value, we stop and return that value, otherwise we
840
 * return 0.
841
 *
842
 * Normally "obsolete" modules are ignored; their sole purpose is to allow old
843
 * preferences for dissectors that no longer have preferences to be
844
 * silently ignored in preference files.  Does not ignore subtrees,
845
 * as this can be used when walking the display tree of modules.
846
 */
847
848
typedef struct {
849
    module_cb callback;
850
    void *user_data;
851
    unsigned ret;
852
    bool skip_obsolete;
853
} call_foreach_t;
854
855
static bool
856
call_foreach_cb(const void *key _U_, void *value, void *data)
857
0
{
858
0
    module_t *module = (module_t*)value;
859
0
    call_foreach_t *call_data = (call_foreach_t*)data;
860
861
0
    if (!call_data->skip_obsolete || !module->obsolete)
862
0
        call_data->ret = (*call_data->callback)(module, call_data->user_data);
863
864
0
    return (call_data->ret != 0);
865
0
}
866
867
static unsigned
868
prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
869
                          void *user_data, bool skip_obsolete)
870
0
{
871
0
    call_foreach_t call_data;
872
873
0
    if (module_list == NULL)
874
0
        module_list = prefs_top_level_modules;
875
876
0
    call_data.callback = callback;
877
0
    call_data.user_data = user_data;
878
0
    call_data.ret = 0;
879
0
    call_data.skip_obsolete = skip_obsolete;
880
0
    wmem_tree_foreach(module_list, call_foreach_cb, &call_data);
881
0
    return call_data.ret;
882
0
}
883
884
/*
885
 * Returns true if module has any submodules
886
 */
887
bool
888
prefs_module_has_submodules(module_t *module)
889
0
{
890
0
    if (module->submodules == NULL) {
891
0
        return false;
892
0
    }
893
894
0
    if (wmem_tree_is_empty(module->submodules)) {
895
0
        return false;
896
0
    }
897
898
0
    return true;
899
0
}
900
901
/*
902
 * Call a callback function, with a specified argument, for each module
903
 * in the list of all modules.  (This list does not include subtrees.)
904
 *
905
 * Ignores "obsolete" modules; their sole purpose is to allow old
906
 * preferences for dissectors that no longer have preferences to be
907
 * silently ignored in preference files.
908
 */
909
unsigned
910
prefs_modules_foreach(module_cb callback, void *user_data)
911
0
{
912
0
    return prefs_module_list_foreach(prefs_modules, callback, user_data, true);
913
0
}
914
915
/*
916
 * Call a callback function, with a specified argument, for each submodule
917
 * of specified modules.  If the module is NULL, goes through the top-level
918
 * list in the display tree of modules.
919
 *
920
 * Ignores "obsolete" modules; their sole purpose is to allow old
921
 * preferences for dissectors that no longer have preferences to be
922
 * silently ignored in preference files.  Does not ignore subtrees,
923
 * as this can be used when walking the display tree of modules.
924
 */
925
unsigned
926
prefs_modules_foreach_submodules(module_t *module, module_cb callback,
927
                                 void *user_data)
928
0
{
929
0
    return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data, true);
930
0
}
931
932
static bool
933
call_apply_cb(const void *key _U_, void *value, void *data _U_)
934
25.9k
{
935
25.9k
    module_t *module = (module_t *)value;
936
937
25.9k
    if (module->obsolete)
938
280
        return false;
939
25.6k
    if (module->prefs_changed_flags) {
940
70
        if (module->apply_cb != NULL)
941
28
            (*module->apply_cb)();
942
70
        module->prefs_changed_flags = 0;
943
70
    }
944
25.6k
    if (module->submodules)
945
182
        wmem_tree_foreach(module->submodules, call_apply_cb, NULL);
946
25.6k
    return false;
947
25.9k
}
948
949
/*
950
 * Call the "apply" callback function for each module if any of its
951
 * preferences have changed, and then clear the flag saying its
952
 * preferences have changed, as the module has been notified of that
953
 * fact.
954
 */
955
void
956
prefs_apply_all(void)
957
14
{
958
14
    wmem_tree_foreach(prefs_modules, call_apply_cb, NULL);
959
14
}
960
961
/*
962
 * Call the "apply" callback function for a specific module if any of
963
 * its preferences have changed, and then clear the flag saying its
964
 * preferences have changed, as the module has been notified of that
965
 * fact.
966
 */
967
void
968
prefs_apply(module_t *module)
969
0
{
970
0
    if (module && module->prefs_changed_flags)
971
0
        call_apply_cb(NULL, module, NULL);
972
0
}
973
974
static module_t *
975
prefs_find_module_alias(const char *name)
976
140
{
977
140
    module_alias_t *alias;
978
979
140
    alias = (module_alias_t *)wmem_tree_lookup_string(prefs_module_aliases, name, WMEM_TREE_STRING_NOCASE);
980
140
    if (alias == NULL)
981
140
        return NULL;
982
0
    return alias->module;
983
140
}
984
985
/*
986
 * Register a preference in a module's list of preferences.
987
 * If it has a title, give it an ordinal number; otherwise, it's a
988
 * preference that won't show up in the UI, so it shouldn't get an
989
 * ordinal number (the ordinal should be the ordinal in the set of
990
 * *visible* preferences).
991
 */
992
static pref_t *
993
register_preference(module_t *module, const char *name, const char *title,
994
                    const char *description, pref_type_e type, bool obsolete)
995
36.4k
{
996
36.4k
    pref_t *preference;
997
36.4k
    const char *p;
998
36.4k
    const char *name_prefix = (module->name != NULL) ? module->name : module->parent->name;
999
1000
36.4k
    preference = g_new(pref_t,1);
1001
36.4k
    preference->name = name;
1002
36.4k
    preference->title = title;
1003
36.4k
    preference->description = description;
1004
36.4k
    preference->type = type;
1005
36.4k
    preference->obsolete = obsolete;
1006
    /* Default to module's preference effects */
1007
36.4k
    preference->effect_flags = module->effect_flags;
1008
1009
36.4k
    if (title != NULL)
1010
32.7k
        preference->ordinal = module->numprefs;
1011
3.71k
    else
1012
3.71k
        preference->ordinal = -1;    /* no ordinal for you */
1013
1014
    /*
1015
     * Make sure that only lower-case ASCII letters, numbers,
1016
     * underscores, and dots appear in the preference name.
1017
     *
1018
     * Crash if there is, as that's an error in the code;
1019
     * you can make the title and description nice strings
1020
     * with capitalization, white space, punctuation, etc.,
1021
     * but the name can be used on the command line,
1022
     * and shouldn't require quoting, shifting, etc.
1023
     */
1024
533k
    for (p = name; *p != '\0'; p++)
1025
496k
        if (!(g_ascii_islower(*p) || g_ascii_isdigit(*p) || *p == '_' || *p == '.'))
1026
0
            ws_error("Preference \"%s.%s\" contains invalid characters", module->name, name);
1027
1028
    /*
1029
     * Make sure there's not already a preference with that
1030
     * name.  Crash if there is, as that's an error in the
1031
     * code, and the code has to be fixed not to register
1032
     * more than one preference with the same name.
1033
     */
1034
36.4k
    if (prefs_find_preference(module, name) != NULL)
1035
0
        ws_error("Preference %s has already been registered", name);
1036
1037
36.4k
    if ((!preference->obsolete) &&
1038
        /* Don't compare if it's a subtree */
1039
36.4k
        (module->name != NULL)) {
1040
        /*
1041
         * Make sure the preference name doesn't begin with the
1042
         * module name, as that's redundant and Just Silly.
1043
         */
1044
32.2k
        if (!((strncmp(name, module->name, strlen(module->name)) != 0) ||
1045
32.2k
            (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
1046
0
            ws_error("Preference %s begins with the module name", name);
1047
32.2k
    }
1048
1049
    /* The title shows up in the preferences dialog. Make sure it's UI-friendly. */
1050
36.4k
    if (preference->title) {
1051
32.7k
        const char *cur_char;
1052
32.7k
        if (preference->type != PREF_STATIC_TEXT && g_utf8_strlen(preference->title, -1) > 80) { // Arbitrary.
1053
0
            ws_error("Title for preference %s.%s is too long: %s", name_prefix, preference->name, preference->title);
1054
0
        }
1055
1056
32.7k
        if (!g_utf8_validate(preference->title, -1, NULL)) {
1057
0
            ws_error("Title for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
1058
0
        }
1059
1060
974k
        for (cur_char = preference->title; *cur_char; cur_char = g_utf8_next_char(cur_char)) {
1061
942k
            if (!g_unichar_isprint(g_utf8_get_char(cur_char))) {
1062
0
                ws_error("Title for preference %s.%s isn't printable UTF-8.", name_prefix, preference->name);
1063
0
            }
1064
942k
        }
1065
32.7k
    }
1066
1067
36.4k
    if (preference->description) {
1068
32.4k
        if (!g_utf8_validate(preference->description, -1, NULL)) {
1069
0
            ws_error("Description for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
1070
0
        }
1071
32.4k
    }
1072
1073
    /*
1074
     * We passed all of our checks. Add the preference.
1075
     */
1076
36.4k
    module->prefs = g_list_append(module->prefs, preference);
1077
36.4k
    if (title != NULL)
1078
32.7k
        module->numprefs++;
1079
1080
36.4k
    return preference;
1081
36.4k
}
1082
1083
/*
1084
 * Find a preference in a module's list of preferences, given the module
1085
 * and the preference's name.
1086
 */
1087
typedef struct {
1088
    GList *list_entry;
1089
    const char *name;
1090
    module_t *submodule;
1091
} find_pref_arg_t;
1092
1093
static int
1094
preference_match(const void *a, const void *b)
1095
182k
{
1096
182k
    const pref_t *pref = (const pref_t *)a;
1097
182k
    const char *name = (const char *)b;
1098
1099
182k
    return strcmp(name, pref->name);
1100
182k
}
1101
1102
static bool
1103
module_find_pref_cb(const void *key _U_, void *value, void *data)
1104
2.60k
{
1105
2.60k
    find_pref_arg_t* arg = (find_pref_arg_t*)data;
1106
2.60k
    GList *list_entry;
1107
2.60k
    module_t *module = (module_t *)value;
1108
1109
2.60k
    if (module == NULL)
1110
0
        return false;
1111
1112
2.60k
    list_entry = g_list_find_custom(module->prefs, arg->name,
1113
2.60k
        preference_match);
1114
1115
2.60k
    if (list_entry == NULL)
1116
2.60k
        return false;
1117
1118
0
    arg->list_entry = list_entry;
1119
0
    arg->submodule = module;
1120
0
    return true;
1121
2.60k
}
1122
1123
/* Tries to find a preference, setting containing_module to the (sub)module
1124
 * holding this preference. */
1125
static pref_t *
1126
prefs_find_preference_with_submodule(module_t *module, const char *name,
1127
        module_t **containing_module)
1128
48.0k
{
1129
48.0k
    find_pref_arg_t arg;
1130
48.0k
    GList *list_entry;
1131
1132
48.0k
    if (module == NULL)
1133
0
        return NULL;    /* invalid parameters */
1134
1135
48.0k
    list_entry = g_list_find_custom(module->prefs, name,
1136
48.0k
        preference_match);
1137
48.0k
    arg.submodule = NULL;
1138
1139
48.0k
    if (list_entry == NULL)
1140
46.2k
    {
1141
46.2k
        arg.list_entry = NULL;
1142
46.2k
        if (module->submodules != NULL)
1143
798
        {
1144
798
            arg.name = name;
1145
798
            wmem_tree_foreach(module->submodules, module_find_pref_cb, &arg);
1146
798
        }
1147
1148
46.2k
        list_entry = arg.list_entry;
1149
46.2k
    }
1150
1151
48.0k
    if (list_entry == NULL)
1152
46.2k
        return NULL;    /* no such preference */
1153
1154
1.75k
    if (containing_module)
1155
56
        *containing_module = arg.submodule ? arg.submodule : module;
1156
1157
1.75k
    return (pref_t *) list_entry->data;
1158
48.0k
}
1159
1160
pref_t *
1161
prefs_find_preference(module_t *module, const char *name)
1162
47.9k
{
1163
47.9k
    return prefs_find_preference_with_submodule(module, name, NULL);
1164
47.9k
}
1165
1166
/*
1167
 * Returns true if the given protocol has registered preferences
1168
 */
1169
bool
1170
prefs_is_registered_protocol(const char *name)
1171
0
{
1172
0
    module_t *m = prefs_find_module(name);
1173
1174
0
    return (m != NULL && !m->obsolete);
1175
0
}
1176
1177
/*
1178
 * Returns the module title of a registered protocol
1179
 */
1180
const char *
1181
prefs_get_title_by_name(const char *name)
1182
0
{
1183
0
    module_t *m = prefs_find_module(name);
1184
1185
0
    return (m != NULL && !m->obsolete) ? m->title : NULL;
1186
0
}
1187
1188
/*
1189
 * Register a preference with an unsigned integral value.
1190
 */
1191
void
1192
prefs_register_uint_preference(module_t *module, const char *name,
1193
                               const char *title, const char *description,
1194
                               unsigned base, unsigned *var)
1195
2.45k
{
1196
2.45k
    pref_t *preference;
1197
1198
2.45k
    preference = register_preference(module, name, title, description,
1199
2.45k
                                     PREF_UINT, false);
1200
2.45k
    preference->varp.uint = var;
1201
2.45k
    preference->default_val.uint = *var;
1202
2.45k
    ws_assert(base > 0 && base != 1 && base < 37);
1203
2.45k
    preference->info.base = base;
1204
2.45k
}
1205
1206
/*
1207
 * XXX Add a prefs_register_{uint16|port}_preference which sets max_value?
1208
 */
1209
1210
1211
/*
1212
 * Register a "custom" preference with a unsigned integral value.
1213
 * XXX - This should be temporary until we can find a better way
1214
 * to do "custom" preferences
1215
 */
1216
static void
1217
prefs_register_uint_custom_preference(module_t *module, const char *name,
1218
                                      const char *title, const char *description,
1219
                                      struct pref_custom_cbs* custom_cbs, unsigned *var)
1220
14
{
1221
14
    pref_t *preference;
1222
1223
14
    preference = register_preference(module, name, title, description,
1224
14
                                     PREF_CUSTOM, false);
1225
1226
14
    preference->custom_cbs = *custom_cbs;
1227
14
    preference->varp.uint = var;
1228
14
    preference->default_val.uint = *var;
1229
14
}
1230
1231
/*
1232
 * Register a preference with an Boolean value.
1233
 */
1234
void
1235
prefs_register_bool_preference(module_t *module, const char *name,
1236
                               const char *title, const char *description,
1237
                               bool *var)
1238
12.2k
{
1239
12.2k
    pref_t *preference;
1240
1241
12.2k
    preference = register_preference(module, name, title, description,
1242
12.2k
                                     PREF_BOOL, false);
1243
12.2k
    preference->varp.boolp = var;
1244
12.2k
    preference->default_val.boolval = *var;
1245
12.2k
}
1246
1247
unsigned int prefs_set_bool_value(pref_t *pref, bool value, pref_source_t source)
1248
0
{
1249
0
    unsigned int changed = 0;
1250
1251
0
    switch (source)
1252
0
    {
1253
0
    case pref_default:
1254
0
        if (pref->default_val.boolval != value) {
1255
0
            pref->default_val.boolval = value;
1256
0
            changed = prefs_get_effect_flags(pref);
1257
0
        }
1258
0
        break;
1259
0
    case pref_stashed:
1260
0
        if (pref->stashed_val.boolval != value) {
1261
0
            pref->stashed_val.boolval = value;
1262
0
            changed = prefs_get_effect_flags(pref);
1263
0
        }
1264
0
        break;
1265
0
    case pref_current:
1266
0
        if (*pref->varp.boolp != value) {
1267
0
            *pref->varp.boolp = value;
1268
0
            changed = prefs_get_effect_flags(pref);
1269
0
        }
1270
0
        break;
1271
0
    default:
1272
0
        ws_assert_not_reached();
1273
0
        break;
1274
0
    }
1275
1276
0
    return changed;
1277
0
}
1278
1279
void prefs_invert_bool_value(pref_t *pref, pref_source_t source)
1280
0
{
1281
0
    switch (source)
1282
0
    {
1283
0
    case pref_default:
1284
0
        pref->default_val.boolval = !pref->default_val.boolval;
1285
0
        break;
1286
0
    case pref_stashed:
1287
0
        pref->stashed_val.boolval = !pref->stashed_val.boolval;
1288
0
        break;
1289
0
    case pref_current:
1290
0
        *pref->varp.boolp = !(*pref->varp.boolp);
1291
0
        break;
1292
0
    default:
1293
0
        ws_assert_not_reached();
1294
0
        break;
1295
0
    }
1296
0
}
1297
1298
bool prefs_get_bool_value(pref_t *pref, pref_source_t source)
1299
382
{
1300
382
    switch (source)
1301
382
    {
1302
0
    case pref_default:
1303
0
        return pref->default_val.boolval;
1304
0
    case pref_stashed:
1305
0
        return pref->stashed_val.boolval;
1306
382
    case pref_current:
1307
382
        return *pref->varp.boolp;
1308
0
    default:
1309
0
        ws_assert_not_reached();
1310
0
        break;
1311
382
    }
1312
1313
0
    return false;
1314
382
}
1315
1316
/*
1317
 * Register a preference with an enumerated value.
1318
 */
1319
/*
1320
 * XXX Should we get rid of the radio_buttons parameter and make that
1321
 * behavior automatic depending on the number of items?
1322
 */
1323
void
1324
prefs_register_enum_preference(module_t *module, const char *name,
1325
                               const char *title, const char *description,
1326
                               int *var, const enum_val_t *enumvals,
1327
                               bool radio_buttons)
1328
3.24k
{
1329
3.24k
    pref_t *preference;
1330
1331
    /* Validate that the "name one would use on the command line for the value"
1332
     * doesn't require quoting, etc. It's all treated case-insensitively so we
1333
     * don't care about upper vs lower case.
1334
     */
1335
17.3k
    for (size_t i = 0; enumvals[i].name != NULL; i++) {
1336
119k
        for (const char *p = enumvals[i].name; *p != '\0'; p++)
1337
105k
            if (!(g_ascii_isalnum(*p) || *p == '_' || *p == '.' || *p == '-'))
1338
0
                ws_error("Preference \"%s.%s\" enum value name \"%s\" contains invalid characters",
1339
14.0k
                    module->name, name, enumvals[i].name);
1340
14.0k
    }
1341
1342
1343
3.24k
    preference = register_preference(module, name, title, description,
1344
3.24k
                                     PREF_ENUM, false);
1345
3.24k
    preference->varp.enump = var;
1346
3.24k
    preference->default_val.enumval = *var;
1347
3.24k
    preference->info.enum_info.enumvals = enumvals;
1348
3.24k
    preference->info.enum_info.radio_buttons = radio_buttons;
1349
3.24k
}
1350
1351
unsigned int prefs_set_enum_value(pref_t *pref, int value, pref_source_t source)
1352
0
{
1353
0
    unsigned int changed = 0;
1354
1355
0
    switch (source)
1356
0
    {
1357
0
    case pref_default:
1358
0
        if (pref->default_val.enumval != value) {
1359
0
            pref->default_val.enumval = value;
1360
0
            changed = prefs_get_effect_flags(pref);
1361
0
        }
1362
0
        break;
1363
0
    case pref_stashed:
1364
0
        if (pref->stashed_val.enumval != value) {
1365
0
            pref->stashed_val.enumval = value;
1366
0
            changed = prefs_get_effect_flags(pref);
1367
0
        }
1368
0
        break;
1369
0
    case pref_current:
1370
0
        if (*pref->varp.enump != value) {
1371
0
            *pref->varp.enump = value;
1372
0
            changed = prefs_get_effect_flags(pref);
1373
0
        }
1374
0
        break;
1375
0
    default:
1376
0
        ws_assert_not_reached();
1377
0
        break;
1378
0
    }
1379
1380
0
    return changed;
1381
0
}
1382
1383
unsigned int prefs_set_enum_string_value(pref_t *pref, const char *value, pref_source_t source)
1384
0
{
1385
0
    int enum_val = find_val_for_string(value, pref->info.enum_info.enumvals, *pref->varp.enump);
1386
1387
0
    return prefs_set_enum_value(pref, enum_val, source);
1388
0
}
1389
1390
int prefs_get_enum_value(pref_t *pref, pref_source_t source)
1391
0
{
1392
0
    switch (source)
1393
0
    {
1394
0
    case pref_default:
1395
0
        return pref->default_val.enumval;
1396
0
    case pref_stashed:
1397
0
        return pref->stashed_val.enumval;
1398
0
    case pref_current:
1399
0
        return *pref->varp.enump;
1400
0
    default:
1401
0
        ws_assert_not_reached();
1402
0
        break;
1403
0
    }
1404
1405
0
    return 0;
1406
0
}
1407
1408
const enum_val_t* prefs_get_enumvals(pref_t *pref)
1409
0
{
1410
0
    return pref->info.enum_info.enumvals;
1411
0
}
1412
1413
bool prefs_get_enum_radiobuttons(pref_t *pref)
1414
0
{
1415
0
    return pref->info.enum_info.radio_buttons;
1416
0
}
1417
1418
/*
1419
 * For use by UI code that sets preferences.
1420
 */
1421
unsigned int
1422
prefs_set_custom_value(pref_t *pref, const char *value, pref_source_t source _U_)
1423
0
{
1424
    /* XXX - support pref source for custom preferences */
1425
0
    unsigned int changed = 0;
1426
0
    pref->custom_cbs.set_cb(pref, value, &changed);
1427
0
    return changed;
1428
0
}
1429
1430
static void
1431
register_string_like_preference(module_t *module, const char *name,
1432
                                const char *title, const char *description,
1433
                                char **var, pref_type_e type,
1434
                                struct pref_custom_cbs* custom_cbs,
1435
                                bool free_tmp)
1436
1.40k
{
1437
1.40k
    pref_t *pref;
1438
1.40k
    char *tmp;
1439
1440
1.40k
    pref = register_preference(module, name, title, description, type, false);
1441
1442
    /*
1443
     * String preference values should be non-null (as you can't
1444
     * keep them null after using the preferences GUI, you can at best
1445
     * have them be null strings) and freeable (as we free them
1446
     * if we change them).
1447
     *
1448
     * If the value is a null pointer, make it a copy of a null
1449
     * string, otherwise make it a copy of the value.
1450
     */
1451
1.40k
    tmp = *var;
1452
1.40k
    if (*var == NULL) {
1453
952
        *var = g_strdup("");
1454
952
    } else {
1455
448
        *var = g_strdup(*var);
1456
448
    }
1457
1.40k
    if (free_tmp) {
1458
126
        g_free(tmp);
1459
126
    }
1460
1.40k
    pref->varp.string = var;
1461
1.40k
    pref->default_val.string = g_strdup(*var);
1462
1.40k
    pref->stashed_val.string = NULL;
1463
1.40k
    if (type == PREF_CUSTOM) {
1464
56
        ws_assert(custom_cbs);
1465
56
        pref->custom_cbs = *custom_cbs;
1466
56
    }
1467
1.40k
}
1468
1469
/*
1470
 * Assign to a string preference.
1471
 */
1472
static void
1473
pref_set_string_like_pref_value(pref_t *pref, const char *value)
1474
0
{
1475
0
DIAG_OFF(cast-qual)
1476
0
    g_free((void *)*pref->varp.string);
1477
0
DIAG_ON(cast-qual)
1478
0
    *pref->varp.string = g_strdup(value);
1479
0
}
1480
1481
/*
1482
 * For use by UI code that sets preferences.
1483
 */
1484
unsigned int
1485
prefs_set_string_value(pref_t *pref, const char* value, pref_source_t source)
1486
0
{
1487
0
    unsigned int changed = 0;
1488
1489
0
    switch (source)
1490
0
    {
1491
0
    case pref_default:
1492
0
        if (*pref->default_val.string) {
1493
0
            if (strcmp(pref->default_val.string, value) != 0) {
1494
0
                changed = prefs_get_effect_flags(pref);
1495
0
                g_free(pref->default_val.string);
1496
0
                pref->default_val.string = g_strdup(value);
1497
0
            }
1498
0
        } else if (value) {
1499
0
            pref->default_val.string = g_strdup(value);
1500
0
        }
1501
0
        break;
1502
0
    case pref_stashed:
1503
0
        if (pref->stashed_val.string) {
1504
0
            if (strcmp(pref->stashed_val.string, value) != 0) {
1505
0
                changed = prefs_get_effect_flags(pref);
1506
0
                g_free(pref->stashed_val.string);
1507
0
                pref->stashed_val.string = g_strdup(value);
1508
0
            }
1509
0
        } else if (value) {
1510
0
            pref->stashed_val.string = g_strdup(value);
1511
0
        }
1512
0
        break;
1513
0
    case pref_current:
1514
0
        if (*pref->varp.string) {
1515
0
            if (strcmp(*pref->varp.string, value) != 0) {
1516
0
                changed = prefs_get_effect_flags(pref);
1517
0
                pref_set_string_like_pref_value(pref, value);
1518
0
            }
1519
0
        } else if (value) {
1520
0
            pref_set_string_like_pref_value(pref, value);
1521
0
        }
1522
0
        break;
1523
0
    default:
1524
0
        ws_assert_not_reached();
1525
0
        break;
1526
0
    }
1527
1528
0
    return changed;
1529
0
}
1530
1531
char* prefs_get_string_value(pref_t *pref, pref_source_t source)
1532
0
{
1533
0
    switch (source)
1534
0
    {
1535
0
    case pref_default:
1536
0
        return pref->default_val.string;
1537
0
    case pref_stashed:
1538
0
        return pref->stashed_val.string;
1539
0
    case pref_current:
1540
0
        return *pref->varp.string;
1541
0
    default:
1542
0
        ws_assert_not_reached();
1543
0
        break;
1544
0
    }
1545
1546
0
    return NULL;
1547
0
}
1548
1549
/*
1550
 * Reset the value of a string-like preference.
1551
 */
1552
static void
1553
reset_string_like_preference(pref_t *pref)
1554
0
{
1555
0
    g_free(*pref->varp.string);
1556
0
    *pref->varp.string = g_strdup(pref->default_val.string);
1557
0
}
1558
1559
/*
1560
 * Register a preference with a character-string value.
1561
 */
1562
void
1563
prefs_register_string_preference(module_t *module, const char *name,
1564
                                 const char *title, const char *description,
1565
                                 const char **var)
1566
868
{
1567
868
DIAG_OFF(cast-qual)
1568
868
    register_string_like_preference(module, name, title, description,
1569
868
                                    (char **)var, PREF_STRING, NULL, false);
1570
868
DIAG_ON(cast-qual)
1571
868
}
1572
1573
/*
1574
 * Register a preference with a file name (string) value.
1575
 */
1576
void
1577
prefs_register_filename_preference(module_t *module, const char *name,
1578
                                   const char *title, const char *description,
1579
                                   const char **var, bool for_writing)
1580
182
{
1581
182
DIAG_OFF(cast-qual)
1582
182
    register_string_like_preference(module, name, title, description, (char **)var,
1583
182
                                    for_writing ? PREF_SAVE_FILENAME : PREF_OPEN_FILENAME, NULL, false);
1584
182
DIAG_ON(cast-qual)
1585
182
}
1586
1587
/*
1588
 * Register a preference with a directory name (string) value.
1589
 */
1590
void
1591
prefs_register_directory_preference(module_t *module, const char *name,
1592
                                   const char *title, const char *description,
1593
                                   const char **var)
1594
14
{
1595
14
DIAG_OFF(cast-qual)
1596
14
    register_string_like_preference(module, name, title, description,
1597
14
                                    (char **)var, PREF_DIRNAME, NULL, false);
1598
14
DIAG_ON(cast-qual)
1599
14
}
1600
1601
/* Refactoring to handle both PREF_RANGE and PREF_DECODE_AS_RANGE */
1602
static pref_t*
1603
prefs_register_range_preference_common(module_t *module, const char *name,
1604
                                const char *title, const char *description,
1605
                                range_t **var, uint32_t max_value, pref_type_e type)
1606
10.2k
{
1607
10.2k
    pref_t *preference;
1608
1609
10.2k
    preference = register_preference(module, name, title, description, type, false);
1610
10.2k
    preference->info.max_value = max_value;
1611
1612
    /*
1613
     * Range preference values should be non-null (as you can't
1614
     * keep them null after using the preferences GUI, you can at best
1615
     * have them be empty ranges) and freeable (as we free them
1616
     * if we change them).
1617
     *
1618
     * If the value is a null pointer, make it an empty range.
1619
     */
1620
10.2k
    if (*var == NULL)
1621
28
        *var = range_empty(wmem_epan_scope());
1622
10.2k
    preference->varp.range = var;
1623
10.2k
    preference->default_val.range = range_copy(wmem_epan_scope(), *var);
1624
10.2k
    preference->stashed_val.range = NULL;
1625
1626
10.2k
    return preference;
1627
10.2k
}
1628
1629
/*
1630
 * Register a preference with a ranged value.
1631
 */
1632
void
1633
prefs_register_range_preference(module_t *module, const char *name,
1634
                                const char *title, const char *description,
1635
                                range_t **var, uint32_t max_value)
1636
448
{
1637
448
    prefs_register_range_preference_common(module, name, title,
1638
448
                description, var, max_value, PREF_RANGE);
1639
448
}
1640
1641
bool
1642
prefs_set_range_value_work(pref_t *pref, const char *value,
1643
                           bool return_range_errors, unsigned int *changed_flags)
1644
0
{
1645
0
    range_t *newrange;
1646
1647
0
    if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1648
0
                               return_range_errors) != CVT_NO_ERROR) {
1649
0
        return false;        /* number was bad */
1650
0
    }
1651
1652
0
    if (!ranges_are_equal(*pref->varp.range, newrange)) {
1653
0
        *changed_flags |= prefs_get_effect_flags(pref);
1654
0
        wmem_free(wmem_epan_scope(), *pref->varp.range);
1655
0
        *pref->varp.range = newrange;
1656
0
    } else {
1657
0
        wmem_free(wmem_epan_scope(), newrange);
1658
0
    }
1659
0
    return true;
1660
0
}
1661
1662
/*
1663
 * For use by UI code that sets preferences.
1664
 */
1665
unsigned int
1666
prefs_set_stashed_range_value(pref_t *pref, const char *value)
1667
0
{
1668
0
    range_t *newrange;
1669
1670
0
    if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1671
0
                               true) != CVT_NO_ERROR) {
1672
0
        return 0;        /* number was bad */
1673
0
    }
1674
1675
0
    if (!ranges_are_equal(pref->stashed_val.range, newrange)) {
1676
0
        wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1677
0
        pref->stashed_val.range = newrange;
1678
0
    } else {
1679
0
        wmem_free(wmem_epan_scope(), newrange);
1680
0
    }
1681
0
    return prefs_get_effect_flags(pref);
1682
1683
0
}
1684
1685
bool prefs_add_list_value(pref_t *pref, void* value, pref_source_t source)
1686
0
{
1687
0
    switch (source)
1688
0
    {
1689
0
    case pref_default:
1690
0
        pref->default_val.list = g_list_prepend(pref->default_val.list, value);
1691
0
        break;
1692
0
    case pref_stashed:
1693
0
        pref->stashed_val.list = g_list_prepend(pref->stashed_val.list, value);
1694
0
        break;
1695
0
    case pref_current:
1696
0
        *pref->varp.list = g_list_prepend(*pref->varp.list, value);
1697
0
        break;
1698
0
    default:
1699
0
        ws_assert_not_reached();
1700
0
        break;
1701
0
    }
1702
1703
0
    return true;
1704
0
}
1705
1706
GList* prefs_get_list_value(pref_t *pref, pref_source_t source)
1707
0
{
1708
0
    switch (source)
1709
0
    {
1710
0
    case pref_default:
1711
0
        return pref->default_val.list;
1712
0
    case pref_stashed:
1713
0
        return pref->stashed_val.list;
1714
0
    case pref_current:
1715
0
        return *pref->varp.list;
1716
0
    default:
1717
0
        ws_assert_not_reached();
1718
0
        break;
1719
0
    }
1720
1721
0
    return NULL;
1722
0
}
1723
1724
bool prefs_set_range_value(pref_t *pref, range_t *value, pref_source_t source)
1725
0
{
1726
0
    bool changed = false;
1727
1728
0
    switch (source)
1729
0
    {
1730
0
    case pref_default:
1731
0
        if (!ranges_are_equal(pref->default_val.range, value)) {
1732
0
            wmem_free(wmem_epan_scope(), pref->default_val.range);
1733
0
            pref->default_val.range = range_copy(wmem_epan_scope(), value);
1734
0
            changed = true;
1735
0
        }
1736
0
        break;
1737
0
    case pref_stashed:
1738
0
        if (!ranges_are_equal(pref->stashed_val.range, value)) {
1739
0
            wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1740
0
            pref->stashed_val.range = range_copy(wmem_epan_scope(), value);
1741
0
            changed = true;
1742
0
        }
1743
0
        break;
1744
0
    case pref_current:
1745
0
        if (!ranges_are_equal(*pref->varp.range, value)) {
1746
0
            wmem_free(wmem_epan_scope(), *pref->varp.range);
1747
0
            *pref->varp.range = range_copy(wmem_epan_scope(), value);
1748
0
            changed = true;
1749
0
        }
1750
0
        break;
1751
0
    default:
1752
0
        ws_assert_not_reached();
1753
0
        break;
1754
0
    }
1755
1756
0
    return changed;
1757
0
}
1758
1759
range_t* prefs_get_range_value_real(pref_t *pref, pref_source_t source)
1760
406
{
1761
406
    switch (source)
1762
406
    {
1763
0
    case pref_default:
1764
0
        return pref->default_val.range;
1765
0
    case pref_stashed:
1766
0
        return pref->stashed_val.range;
1767
406
    case pref_current:
1768
406
        return *pref->varp.range;
1769
0
    default:
1770
0
        ws_assert_not_reached();
1771
0
        break;
1772
406
    }
1773
1774
0
    return NULL;
1775
406
}
1776
1777
range_t* prefs_get_range_value(const char *module_name, const char* pref_name)
1778
406
{
1779
406
    pref_t *pref = prefs_find_preference(prefs_find_module(module_name), pref_name);
1780
406
    if (pref == NULL) {
1781
0
        return NULL;
1782
0
    }
1783
406
    return prefs_get_range_value_real(pref, pref_current);
1784
406
}
1785
1786
void
1787
prefs_range_add_value(pref_t *pref, uint32_t val)
1788
0
{
1789
0
    range_add_value(wmem_epan_scope(), pref->varp.range, val);
1790
0
}
1791
1792
void
1793
prefs_range_remove_value(pref_t *pref, uint32_t val)
1794
0
{
1795
0
    range_remove_value(wmem_epan_scope(), pref->varp.range, val);
1796
0
}
1797
1798
/*
1799
 * Register a static text 'preference'.  It can be used to add explanatory
1800
 * text inline with other preferences in the GUI.
1801
 * Note: Static preferences are not saved to the preferences file.
1802
 */
1803
void
1804
prefs_register_static_text_preference(module_t *module, const char *name,
1805
                                      const char *title,
1806
                                      const char *description)
1807
1.14k
{
1808
1.14k
    register_preference(module, name, title, description, PREF_STATIC_TEXT, false);
1809
1.14k
}
1810
1811
/*
1812
 * Register a uat 'preference'. It adds a button that opens the uat's window in the
1813
 * preferences tab of the module.
1814
 */
1815
extern void
1816
prefs_register_uat_preference(module_t *module, const char *name,
1817
                              const char *title, const char *description,
1818
                              uat_t* uat)
1819
1.80k
{
1820
1.80k
    pref_t* preference = register_preference(module, name, title, description, PREF_UAT, false);
1821
1822
1.80k
    preference->varp.uat = uat;
1823
1.80k
}
1824
1825
struct epan_uat* prefs_get_uat_value(pref_t *pref)
1826
0
{
1827
0
    return pref->varp.uat;
1828
0
}
1829
1830
/*
1831
 * Register a color preference.
1832
 */
1833
void
1834
prefs_register_color_preference(module_t *module, const char *name,
1835
                                const char *title, const char *description,
1836
                                color_t *color)
1837
252
{
1838
252
    pref_t* preference = register_preference(module, name, title, description, PREF_COLOR, false);
1839
1840
252
    preference->varp.colorp = color;
1841
252
    preference->default_val.color = *color;
1842
252
}
1843
1844
bool prefs_set_color_value(pref_t *pref, color_t value, pref_source_t source)
1845
0
{
1846
0
    bool changed = false;
1847
1848
0
    switch (source)
1849
0
    {
1850
0
    case pref_default:
1851
0
        if ((pref->default_val.color.red != value.red) ||
1852
0
            (pref->default_val.color.green != value.green) ||
1853
0
            (pref->default_val.color.blue != value.blue)) {
1854
0
            changed = true;
1855
0
            pref->default_val.color = value;
1856
0
        }
1857
0
        break;
1858
0
    case pref_stashed:
1859
0
        if ((pref->stashed_val.color.red != value.red) ||
1860
0
            (pref->stashed_val.color.green != value.green) ||
1861
0
            (pref->stashed_val.color.blue != value.blue)) {
1862
0
            changed = true;
1863
0
            pref->stashed_val.color = value;
1864
0
        }
1865
0
        break;
1866
0
    case pref_current:
1867
0
        if ((pref->varp.colorp->red != value.red) ||
1868
0
            (pref->varp.colorp->green != value.green) ||
1869
0
            (pref->varp.colorp->blue != value.blue)) {
1870
0
            changed = true;
1871
0
            *pref->varp.colorp = value;
1872
0
        }
1873
0
        break;
1874
0
    default:
1875
0
        ws_assert_not_reached();
1876
0
        break;
1877
0
    }
1878
1879
0
    return changed;
1880
0
}
1881
1882
color_t* prefs_get_color_value(pref_t *pref, pref_source_t source)
1883
0
{
1884
0
    switch (source)
1885
0
    {
1886
0
    case pref_default:
1887
0
        return &pref->default_val.color;
1888
0
    case pref_stashed:
1889
0
        return &pref->stashed_val.color;
1890
0
    case pref_current:
1891
0
        return pref->varp.colorp;
1892
0
    default:
1893
0
        ws_assert_not_reached();
1894
0
        break;
1895
0
    }
1896
1897
0
    return NULL;
1898
0
}
1899
1900
/*
1901
 * Register a "custom" preference with a list.
1902
 * XXX - This should be temporary until we can find a better way
1903
 * to do "custom" preferences
1904
 */
1905
typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
1906
1907
static void
1908
prefs_register_list_custom_preference(module_t *module, const char *name,
1909
                                      const char *title, const char *description,
1910
                                      struct pref_custom_cbs* custom_cbs,
1911
                                      pref_custom_list_init_cb init_cb,
1912
                                      GList** list)
1913
28
{
1914
28
    pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM, false);
1915
1916
28
    preference->custom_cbs = *custom_cbs;
1917
28
    init_cb(preference, list);
1918
28
}
1919
1920
/*
1921
 * Register a custom preference.
1922
 */
1923
void
1924
prefs_register_custom_preference(module_t *module, const char *name,
1925
                                 const char *title, const char *description,
1926
                                 struct pref_custom_cbs* custom_cbs,
1927
                                 void **custom_data _U_)
1928
0
{
1929
0
    pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM, false);
1930
1931
0
    preference->custom_cbs = *custom_cbs;
1932
    /* XXX - wait until we can handle void** pointers
1933
    preference->custom_cbs.init_cb(preference, custom_data);
1934
    */
1935
0
}
1936
1937
/*
1938
 * Register a dedicated TCP preference for SEQ analysis overriding.
1939
 * This is similar to the data structure from enum preference, except
1940
 * that when a preference dialog is used, the stashed value is the list
1941
 * of frame data pointers whose sequence analysis override will be set
1942
 * to the current value if the dialog is accepted.
1943
 *
1944
 * We don't need to read or write the value from the preferences file
1945
 * (or command line), because the override is reset to the default (0)
1946
 * for each frame when a new capture file is loaded.
1947
 */
1948
void
1949
prefs_register_custom_preference_TCP_Analysis(module_t *module, const char *name,
1950
                               const char *title, const char *description,
1951
                               int *var, const enum_val_t *enumvals,
1952
                               bool radio_buttons)
1953
14
{
1954
14
    pref_t *preference;
1955
1956
14
    preference = register_preference(module, name, title, description,
1957
14
                                     PREF_PROTO_TCP_SNDAMB_ENUM, false);
1958
14
    preference->varp.enump = var;
1959
14
    preference->default_val.enumval = *var;
1960
14
    preference->stashed_val.list = NULL;
1961
14
    preference->info.enum_info.enumvals = enumvals;
1962
14
    preference->info.enum_info.radio_buttons = radio_buttons;
1963
14
}
1964
1965
/*
1966
 * Register a (internal) "Decode As" preference with a ranged value.
1967
 */
1968
void prefs_register_decode_as_range_preference(module_t *module, const char *name,
1969
    const char *title, const char *description, range_t **var,
1970
    uint32_t max_value, const char *dissector_table, const char *dissector_description)
1971
9.75k
{
1972
9.75k
    pref_t *preference;
1973
1974
9.75k
    preference = prefs_register_range_preference_common(module, name, title,
1975
9.75k
                description, var, max_value, PREF_DECODE_AS_RANGE);
1976
9.75k
    preference->dissector_desc = dissector_description;
1977
9.75k
    preference->dissector_table = dissector_table;
1978
9.75k
}
1979
1980
/*
1981
 * Register a preference with password value.
1982
 */
1983
void
1984
prefs_register_password_preference(module_t *module, const char *name,
1985
                                 const char *title, const char *description,
1986
                                 const char **var)
1987
0
{
1988
0
DIAG_OFF(cast-qual)
1989
0
    register_string_like_preference(module, name, title, description,
1990
0
                                    (char **)var, PREF_PASSWORD, NULL, false);
1991
0
DIAG_ON(cast-qual)
1992
0
}
1993
1994
/*
1995
 * Register a preference with a dissector name.
1996
 */
1997
void
1998
prefs_register_dissector_preference(module_t *module, const char *name,
1999
                                    const char *title, const char *description,
2000
                                    const char **var)
2001
56
{
2002
56
DIAG_OFF(cast-qual)
2003
56
    register_string_like_preference(module, name, title, description,
2004
56
                                    (char **)var, PREF_DISSECTOR, NULL, false);
2005
56
DIAG_ON(cast-qual)
2006
56
}
2007
2008
bool prefs_add_decode_as_value(pref_t *pref, unsigned value, bool replace)
2009
0
{
2010
0
    switch(pref->type)
2011
0
    {
2012
0
    case PREF_DECODE_AS_RANGE:
2013
0
        if (replace)
2014
0
        {
2015
            /* If range has single value, replace it */
2016
0
            if (((*pref->varp.range)->nranges == 1) &&
2017
0
                ((*pref->varp.range)->ranges[0].low == (*pref->varp.range)->ranges[0].high)) {
2018
0
                wmem_free(wmem_epan_scope(), *pref->varp.range);
2019
0
                *pref->varp.range = range_empty(wmem_epan_scope());
2020
0
            }
2021
0
        }
2022
2023
0
        prefs_range_add_value(pref, value);
2024
0
        break;
2025
0
    default:
2026
        /* XXX - Worth asserting over? */
2027
0
        break;
2028
0
    }
2029
2030
0
    return true;
2031
0
}
2032
2033
bool prefs_remove_decode_as_value(pref_t *pref, unsigned value, bool set_default _U_)
2034
0
{
2035
0
    switch(pref->type)
2036
0
    {
2037
0
    case PREF_DECODE_AS_RANGE:
2038
        /* XXX - We could set to the default if the value is the only one
2039
         * in the range.
2040
         */
2041
0
        prefs_range_remove_value(pref, value);
2042
0
        break;
2043
0
    default:
2044
0
        break;
2045
0
    }
2046
2047
0
    return true;
2048
0
}
2049
2050
/*
2051
 * Register a preference that used to be supported but no longer is.
2052
 */
2053
void
2054
prefs_register_obsolete_preference(module_t *module, const char *name)
2055
3.71k
{
2056
3.71k
    register_preference(module, name, NULL, NULL, PREF_STATIC_TEXT, true);
2057
3.71k
}
2058
2059
bool
2060
prefs_is_preference_obsolete(pref_t *pref)
2061
0
{
2062
0
    return pref->obsolete;
2063
0
}
2064
2065
void
2066
prefs_set_preference_effect_fields(module_t *module, const char *name)
2067
14
{
2068
14
    pref_t * pref = prefs_find_preference(module, name);
2069
14
    if (pref) {
2070
14
        prefs_set_effect_flags(pref, prefs_get_effect_flags(pref) | PREF_EFFECT_FIELDS);
2071
14
    }
2072
14
}
2073
2074
unsigned
2075
pref_stash(pref_t *pref, void *unused _U_)
2076
0
{
2077
0
    ws_assert(!pref->obsolete);
2078
2079
0
    switch (pref->type) {
2080
2081
0
    case PREF_UINT:
2082
0
        pref->stashed_val.uint = *pref->varp.uint;
2083
0
        break;
2084
2085
0
    case PREF_BOOL:
2086
0
        pref->stashed_val.boolval = *pref->varp.boolp;
2087
0
        break;
2088
2089
0
    case PREF_ENUM:
2090
0
        pref->stashed_val.enumval = *pref->varp.enump;
2091
0
        break;
2092
2093
0
    case PREF_STRING:
2094
0
    case PREF_SAVE_FILENAME:
2095
0
    case PREF_OPEN_FILENAME:
2096
0
    case PREF_DIRNAME:
2097
0
    case PREF_PASSWORD:
2098
0
    case PREF_DISSECTOR:
2099
0
        g_free(pref->stashed_val.string);
2100
0
        pref->stashed_val.string = g_strdup(*pref->varp.string);
2101
0
        break;
2102
2103
0
    case PREF_DECODE_AS_RANGE:
2104
0
    case PREF_RANGE:
2105
0
        wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2106
0
        pref->stashed_val.range = range_copy(wmem_epan_scope(), *pref->varp.range);
2107
0
        break;
2108
2109
0
    case PREF_COLOR:
2110
0
        pref->stashed_val.color = *pref->varp.colorp;
2111
0
        break;
2112
2113
0
    case PREF_STATIC_TEXT:
2114
0
    case PREF_UAT:
2115
0
    case PREF_CUSTOM:
2116
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
2117
0
        break;
2118
2119
0
    default:
2120
0
        ws_assert_not_reached();
2121
0
        break;
2122
0
    }
2123
0
    return 0;
2124
0
}
2125
2126
unsigned
2127
pref_unstash(pref_t *pref, void *unstash_data_p)
2128
0
{
2129
0
    pref_unstash_data_t *unstash_data = (pref_unstash_data_t *)unstash_data_p;
2130
0
    dissector_table_t sub_dissectors = NULL;
2131
0
    dissector_handle_t handle = NULL;
2132
2133
0
    ws_assert(!pref->obsolete);
2134
2135
    /* Revert the preference to its saved value. */
2136
0
    switch (pref->type) {
2137
2138
0
    case PREF_UINT:
2139
0
        if (*pref->varp.uint != pref->stashed_val.uint) {
2140
0
            unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2141
0
            *pref->varp.uint = pref->stashed_val.uint;
2142
0
        }
2143
0
        break;
2144
2145
0
    case PREF_BOOL:
2146
0
        if (*pref->varp.boolp != pref->stashed_val.boolval) {
2147
0
            unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2148
0
            *pref->varp.boolp = pref->stashed_val.boolval;
2149
0
        }
2150
0
        break;
2151
2152
0
    case PREF_ENUM:
2153
0
        if (*pref->varp.enump != pref->stashed_val.enumval) {
2154
0
            unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2155
0
            *pref->varp.enump = pref->stashed_val.enumval;
2156
0
        }
2157
0
        break;
2158
2159
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
2160
0
    {
2161
        /* The preference dialogs are modal so the frame_data pointers should
2162
         * still be valid; otherwise we could store the frame numbers to
2163
         * change.
2164
         */
2165
0
        frame_data *fdata;
2166
0
        for (GList* elem = pref->stashed_val.list; elem != NULL; elem = elem->next) {
2167
0
            fdata = (frame_data*)elem->data;
2168
0
            if (fdata->tcp_snd_manual_analysis != *pref->varp.enump) {
2169
0
                unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2170
0
                fdata->tcp_snd_manual_analysis = *pref->varp.enump;
2171
0
            }
2172
0
        }
2173
0
        break;
2174
0
    }
2175
0
    case PREF_STRING:
2176
0
    case PREF_SAVE_FILENAME:
2177
0
    case PREF_OPEN_FILENAME:
2178
0
    case PREF_DIRNAME:
2179
0
    case PREF_PASSWORD:
2180
0
    case PREF_DISSECTOR:
2181
0
        if (strcmp(*pref->varp.string, pref->stashed_val.string) != 0) {
2182
0
            unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2183
0
            g_free(*pref->varp.string);
2184
0
            *pref->varp.string = g_strdup(pref->stashed_val.string);
2185
0
        }
2186
0
        break;
2187
2188
0
    case PREF_DECODE_AS_RANGE:
2189
0
    {
2190
0
        const char* table_name = prefs_get_dissector_table(pref);
2191
0
        if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2192
0
            uint32_t i, j;
2193
0
            unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2194
2195
0
            if (unstash_data->handle_decode_as) {
2196
0
                sub_dissectors = find_dissector_table(table_name);
2197
0
                if (sub_dissectors != NULL) {
2198
0
                    const char *handle_desc = prefs_get_dissector_description(pref);
2199
                    // It should perhaps be possible to get this via dissector name.
2200
0
                    handle = dissector_table_get_dissector_handle(sub_dissectors, handle_desc);
2201
0
                    if (handle != NULL) {
2202
                        /* Set the current handle to NULL for all the old values
2203
                         * in the dissector table. If there isn't an initial
2204
                         * handle, this actually deletes the entry. (If there
2205
                         * is an initial entry, keep it around so that the
2206
                         * user can see the original value.)
2207
                         *
2208
                         * XXX - If there's an initial handle which is not this,
2209
                         * reset it instead? At least this leaves the initial
2210
                         * handle visible in the Decode As table.
2211
                         */
2212
0
                        for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2213
0
                            for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2214
0
                                dissector_change_uint(table_name, j, NULL);
2215
0
                                decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2216
0
                            }
2217
2218
0
                            dissector_change_uint(table_name, (*pref->varp.range)->ranges[i].high, NULL);
2219
0
                            decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2220
0
                        }
2221
0
                    }
2222
0
                }
2223
0
            }
2224
2225
0
            wmem_free(wmem_epan_scope(), *pref->varp.range);
2226
0
            *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2227
2228
0
            if (unstash_data->handle_decode_as) {
2229
0
                if ((sub_dissectors != NULL) && (handle != NULL)) {
2230
2231
                    /* Add new values to the dissector table */
2232
0
                    for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2233
2234
0
                        for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2235
0
                            dissector_change_uint(table_name, j, handle);
2236
0
                            decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2237
0
                        }
2238
2239
0
                        dissector_change_uint(table_name, (*pref->varp.range)->ranges[i].high, handle);
2240
0
                        decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2241
0
                    }
2242
0
                }
2243
0
            }
2244
0
        }
2245
0
        break;
2246
0
    }
2247
0
    case PREF_RANGE:
2248
0
        if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2249
0
            unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2250
0
            wmem_free(wmem_epan_scope(), *pref->varp.range);
2251
0
            *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2252
0
        }
2253
0
    break;
2254
2255
0
    case PREF_COLOR:
2256
0
        if ((pref->varp.colorp->blue != pref->stashed_val.color.blue) ||
2257
0
            (pref->varp.colorp->red != pref->stashed_val.color.red) ||
2258
0
            (pref->varp.colorp->green != pref->stashed_val.color.green)) {
2259
0
            unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2260
0
            *pref->varp.colorp = pref->stashed_val.color;
2261
0
        }
2262
0
        break;
2263
2264
0
    case PREF_STATIC_TEXT:
2265
0
    case PREF_UAT:
2266
0
    case PREF_CUSTOM:
2267
0
        break;
2268
2269
0
    default:
2270
0
        ws_assert_not_reached();
2271
0
        break;
2272
0
    }
2273
0
    return 0;
2274
0
}
2275
2276
void
2277
0
reset_stashed_pref(pref_t *pref) {
2278
2279
0
    ws_assert(!pref->obsolete);
2280
2281
0
    switch (pref->type) {
2282
2283
0
    case PREF_UINT:
2284
0
        pref->stashed_val.uint = pref->default_val.uint;
2285
0
        break;
2286
2287
0
    case PREF_BOOL:
2288
0
        pref->stashed_val.boolval = pref->default_val.boolval;
2289
0
        break;
2290
2291
0
    case PREF_ENUM:
2292
0
        pref->stashed_val.enumval = pref->default_val.enumval;
2293
0
        break;
2294
2295
0
    case PREF_STRING:
2296
0
    case PREF_SAVE_FILENAME:
2297
0
    case PREF_OPEN_FILENAME:
2298
0
    case PREF_DIRNAME:
2299
0
    case PREF_PASSWORD:
2300
0
    case PREF_DISSECTOR:
2301
0
        g_free(pref->stashed_val.string);
2302
0
        pref->stashed_val.string = g_strdup(pref->default_val.string);
2303
0
        break;
2304
2305
0
    case PREF_DECODE_AS_RANGE:
2306
0
    case PREF_RANGE:
2307
0
        wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2308
0
        pref->stashed_val.range = range_copy(wmem_epan_scope(), pref->default_val.range);
2309
0
        break;
2310
2311
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
2312
0
        if (pref->stashed_val.list != NULL) {
2313
0
            g_list_free(pref->stashed_val.list);
2314
0
            pref->stashed_val.list = NULL;
2315
0
        }
2316
0
        break;
2317
2318
0
    case PREF_COLOR:
2319
0
        memcpy(&pref->stashed_val.color, &pref->default_val.color, sizeof(color_t));
2320
0
        break;
2321
2322
0
    case PREF_STATIC_TEXT:
2323
0
    case PREF_UAT:
2324
0
    case PREF_CUSTOM:
2325
0
        break;
2326
2327
0
    default:
2328
0
        ws_assert_not_reached();
2329
0
        break;
2330
0
    }
2331
0
}
2332
2333
unsigned
2334
pref_clean_stash(pref_t *pref, void *unused _U_)
2335
0
{
2336
0
    ws_assert(!pref->obsolete);
2337
2338
0
    switch (pref->type) {
2339
2340
0
    case PREF_UINT:
2341
0
        break;
2342
2343
0
    case PREF_BOOL:
2344
0
        break;
2345
2346
0
    case PREF_ENUM:
2347
0
        break;
2348
2349
0
    case PREF_STRING:
2350
0
    case PREF_SAVE_FILENAME:
2351
0
    case PREF_OPEN_FILENAME:
2352
0
    case PREF_DIRNAME:
2353
0
    case PREF_PASSWORD:
2354
0
    case PREF_DISSECTOR:
2355
0
        if (pref->stashed_val.string != NULL) {
2356
0
            g_free(pref->stashed_val.string);
2357
0
            pref->stashed_val.string = NULL;
2358
0
        }
2359
0
        break;
2360
2361
0
    case PREF_DECODE_AS_RANGE:
2362
0
    case PREF_RANGE:
2363
0
        if (pref->stashed_val.range != NULL) {
2364
0
            wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2365
0
            pref->stashed_val.range = NULL;
2366
0
        }
2367
0
        break;
2368
2369
0
    case PREF_STATIC_TEXT:
2370
0
    case PREF_UAT:
2371
0
    case PREF_COLOR:
2372
0
    case PREF_CUSTOM:
2373
0
        break;
2374
2375
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
2376
0
        if (pref->stashed_val.list != NULL) {
2377
0
            g_list_free(pref->stashed_val.list);
2378
0
            pref->stashed_val.list = NULL;
2379
0
        }
2380
0
        break;
2381
2382
0
    default:
2383
0
        ws_assert_not_reached();
2384
0
        break;
2385
0
    }
2386
0
    return 0;
2387
0
}
2388
2389
/*
2390
 * Call a callback function, with a specified argument, for each preference
2391
 * in a given module.
2392
 *
2393
 * If any of the callbacks return a non-zero value, stop and return that
2394
 * value, otherwise return 0.
2395
 */
2396
unsigned
2397
prefs_pref_foreach(module_t *module, pref_cb callback, void *user_data)
2398
0
{
2399
0
    GList *elem;
2400
0
    pref_t *pref;
2401
0
    unsigned ret;
2402
2403
0
    for (elem = g_list_first(module->prefs); elem != NULL; elem = g_list_next(elem)) {
2404
0
        pref = (pref_t *)elem->data;
2405
0
        if (!pref || pref->obsolete) {
2406
            /*
2407
             * This preference is no longer supported; it's
2408
             * not a real preference, so we don't call the
2409
             * callback for it (i.e., we treat it as if it
2410
             * weren't found in the list of preferences,
2411
             * and we weren't called in the first place).
2412
             */
2413
0
            continue;
2414
0
        }
2415
2416
0
        ret = (*callback)(pref, user_data);
2417
0
        if (ret != 0)
2418
0
            return ret;
2419
0
    }
2420
0
    return 0;
2421
0
}
2422
2423
static const enum_val_t st_sort_col_vals[] = {
2424
    { "name",    "Node name (topic/item)", ST_SORT_COL_NAME },
2425
    { "count",   "Item count", ST_SORT_COL_COUNT },
2426
    { "average", "Average value of the node", ST_SORT_COL_AVG },
2427
    { "min",     "Minimum value of the node", ST_SORT_COL_MIN },
2428
    { "max",     "Maximum value of the node", ST_SORT_COL_MAX },
2429
    { "burst",   "Burst rate of the node", ST_SORT_COL_BURSTRATE },
2430
    { NULL,      NULL,         0 }
2431
};
2432
2433
static const enum_val_t st_format_vals[] = {
2434
    { "text",  "Plain text",             ST_FORMAT_PLAIN },
2435
    { "csv",   "Comma separated values", ST_FORMAT_CSV   },
2436
    { "xml",   "XML document",           ST_FORMAT_XML   },
2437
    { "yaml",  "YAML document",          ST_FORMAT_YAML  },
2438
    { NULL,    NULL,                     0 }
2439
};
2440
2441
static void
2442
stats_callback(void)
2443
0
{
2444
    /* Test for a sane tap update interval */
2445
0
    if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
2446
0
        prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
2447
2448
    /* burst resolution can't be less than 1 (ms) */
2449
0
    if (prefs.st_burst_resolution < 1) {
2450
0
        prefs.st_burst_resolution = 1;
2451
0
    }
2452
0
    else if (prefs.st_burst_resolution > ST_MAX_BURSTRES) {
2453
0
        prefs.st_burst_resolution = ST_MAX_BURSTRES;
2454
0
    }
2455
    /* make sure burst window value makes sense */
2456
0
    if (prefs.st_burst_windowlen < prefs.st_burst_resolution) {
2457
0
        prefs.st_burst_windowlen = prefs.st_burst_resolution;
2458
0
    }
2459
    /* round burst window down to multiple of resolution */
2460
0
    prefs.st_burst_windowlen -= prefs.st_burst_windowlen%prefs.st_burst_resolution;
2461
0
    if ((prefs.st_burst_windowlen/prefs.st_burst_resolution) > ST_MAX_BURSTBUCKETS) {
2462
0
        prefs.st_burst_windowlen = prefs.st_burst_resolution*ST_MAX_BURSTBUCKETS;
2463
0
    }
2464
0
}
2465
2466
static void
2467
gui_callback(void)
2468
0
{
2469
    /* Ensure there is at least one file count */
2470
0
    if (prefs.gui_recent_files_count_max == 0)
2471
0
      prefs.gui_recent_files_count_max = 10;
2472
2473
    /* Ensure there is at least one display filter entry */
2474
0
    if (prefs.gui_recent_df_entries_max == 0)
2475
0
      prefs.gui_recent_df_entries_max = 10;
2476
2477
    /* number of decimal places should be between 2 and 10 */
2478
0
    if (prefs.gui_decimal_places1 < 2) {
2479
0
        prefs.gui_decimal_places1 = 2;
2480
0
    } else if (prefs.gui_decimal_places1 > 10) {
2481
0
        prefs.gui_decimal_places1 = 10;
2482
0
    }
2483
    /* number of decimal places should be between 2 and 10 */
2484
0
    if (prefs.gui_decimal_places2 < 2) {
2485
0
        prefs.gui_decimal_places2 = 2;
2486
0
    } else if (prefs.gui_decimal_places2 > 10) {
2487
0
        prefs.gui_decimal_places2 = 10;
2488
0
    }
2489
    /* number of decimal places should be between 2 and 10 */
2490
0
    if (prefs.gui_decimal_places3 < 2) {
2491
0
        prefs.gui_decimal_places3 = 2;
2492
0
    } else if (prefs.gui_decimal_places3 > 10) {
2493
0
        prefs.gui_decimal_places3 = 10;
2494
0
    }
2495
0
}
2496
2497
static void
2498
gui_layout_callback(void)
2499
0
{
2500
0
    if (prefs.gui_layout_type == layout_unused ||
2501
0
        prefs.gui_layout_type >= layout_type_max) {
2502
      /* XXX - report an error?  It's not a syntax error - we'd need to
2503
         add a way of reporting a *semantic* error. */
2504
0
      prefs.gui_layout_type = layout_type_2;
2505
0
    }
2506
0
}
2507
2508
/******************************************************
2509
 * All custom preference function callbacks
2510
 ******************************************************/
2511
0
static void custom_pref_no_cb(pref_t* pref _U_) {}
2512
2513
/*
2514
 * Column preference functions
2515
 */
2516
14
#define PRS_COL_HIDDEN_FMT               "column.hidden"
2517
14
#define PRS_COL_HIDDEN                   "column.hide"
2518
14
#define PRS_COL_FMT                      "column.format"
2519
14
#define PRS_COL_NUM                      "column.number"
2520
static module_t *gui_column_module;
2521
2522
static prefs_set_pref_e
2523
column_hidden_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
2524
0
{
2525
0
    GList       *clp;
2526
0
    fmt_data    *cfmt;
2527
0
    pref_t  *format_pref;
2528
2529
    /*
2530
     * Prefer the new preference to the old format-based preference if we've
2531
     * read it. (We probably could just compare the string to NULL and "".)
2532
     */
2533
0
    prefs.cols_hide_new = true;
2534
2535
0
    (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2536
2537
    /*
2538
     * Set the "visible" flag for the existing columns; we need to
2539
     * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
2540
     * after setting it (which might be the case if, for example, we
2541
     * set PRS_COL_HIDDEN on the command line).
2542
     */
2543
0
    format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2544
0
    clp = (format_pref) ? *format_pref->varp.list : NULL;
2545
0
    int cidx = 1;
2546
0
    while (clp) {
2547
0
      cfmt = (fmt_data *)clp->data;
2548
0
      cfmt->visible = prefs_is_column_visible(*pref->varp.string, cidx);
2549
0
      cidx++;
2550
0
      clp = clp->next;
2551
0
    }
2552
2553
0
    return PREFS_SET_OK;
2554
0
}
2555
2556
static const char *
2557
column_hidden_type_name_cb(void)
2558
0
{
2559
0
    return "Packet list hidden columns";
2560
0
}
2561
2562
static char *
2563
column_hidden_type_description_cb(void)
2564
0
{
2565
0
    return g_strdup("List all column indices (1-indexed) to hide in the packet list.");
2566
0
}
2567
2568
static char *
2569
column_hidden_to_str_cb(pref_t* pref, bool default_val)
2570
0
{
2571
0
    GString     *cols_hidden;
2572
0
    GList       *clp;
2573
0
    fmt_data    *cfmt;
2574
0
    pref_t  *format_pref;
2575
0
    int          cidx = 1;
2576
2577
0
    if (default_val)
2578
0
        return g_strdup(pref->default_val.string);
2579
2580
0
    cols_hidden = g_string_new("");
2581
0
    format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2582
0
    clp = (format_pref) ? *format_pref->varp.list : NULL;
2583
0
    while (clp) {
2584
0
        cfmt = (fmt_data *) clp->data;
2585
0
        if (!cfmt->visible) {
2586
0
            if (cols_hidden->len)
2587
0
                g_string_append (cols_hidden, ",");
2588
0
            g_string_append_printf (cols_hidden, "%i", cidx);
2589
0
        }
2590
0
        clp = clp->next;
2591
0
        cidx++;
2592
0
    }
2593
2594
0
    return g_string_free (cols_hidden, FALSE);
2595
0
}
2596
2597
static bool
2598
column_hidden_is_default_cb(pref_t* pref)
2599
0
{
2600
0
    char *cur_hidden_str = column_hidden_to_str_cb(pref, false);
2601
0
    bool is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2602
2603
0
    g_free(cur_hidden_str);
2604
0
    return is_default;
2605
0
}
2606
2607
static prefs_set_pref_e
2608
column_hidden_fmt_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
2609
0
{
2610
0
    GList       *clp;
2611
0
    fmt_data    *cfmt;
2612
0
    pref_t  *format_pref;
2613
2614
0
    (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2615
2616
    /*
2617
     * Set the "visible" flag for the existing columns; we need to
2618
     * do this if we set PRS_COL_HIDDEN_FMT but don't set PRS_COL_FMT
2619
     * after setting it (which might be the case if, for example, we
2620
     * set PRS_COL_HIDDEN_FMT on the command line; it shouldn't happen
2621
     * when reading the configuration file because we write (both of)
2622
     * the hidden column prefs before the column format prefs.)
2623
     */
2624
0
    format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2625
0
    clp = (format_pref) ? *format_pref->varp.list : NULL;
2626
0
    while (clp) {
2627
0
      cfmt = (fmt_data *)clp->data;
2628
0
      cfmt->visible = prefs_is_column_fmt_visible(*pref->varp.string, cfmt);
2629
0
      clp = clp->next;
2630
0
    }
2631
2632
0
    return PREFS_SET_OK;
2633
0
}
2634
2635
static const char *
2636
column_hidden_fmt_type_name_cb(void)
2637
0
{
2638
0
    return "Packet list hidden column formats (deprecated)";
2639
0
}
2640
2641
static char *
2642
column_hidden_fmt_type_description_cb(void)
2643
0
{
2644
0
    return g_strdup("List all column formats to hide in the packet list. Deprecated in favor of the index-based preference.");
2645
0
}
2646
2647
static char *
2648
column_hidden_fmt_to_str_cb(pref_t* pref, bool default_val)
2649
0
{
2650
0
    GString     *cols_hidden;
2651
0
    GList       *clp;
2652
0
    fmt_data    *cfmt;
2653
0
    pref_t  *format_pref;
2654
2655
0
    if (default_val)
2656
0
        return g_strdup(pref->default_val.string);
2657
2658
0
    cols_hidden = g_string_new("");
2659
0
    format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2660
0
    clp = (format_pref) ? *format_pref->varp.list : NULL;
2661
0
    while (clp) {
2662
0
        char *prefs_fmt;
2663
0
        cfmt = (fmt_data *) clp->data;
2664
0
        if (!cfmt->visible) {
2665
0
            if (cols_hidden->len)
2666
0
                g_string_append (cols_hidden, ",");
2667
0
            prefs_fmt = column_fmt_data_to_str(cfmt);
2668
0
            g_string_append(cols_hidden, prefs_fmt);
2669
0
            g_free(prefs_fmt);
2670
0
        }
2671
0
        clp = clp->next;
2672
0
    }
2673
2674
0
    return g_string_free (cols_hidden, FALSE);
2675
0
}
2676
2677
static bool
2678
column_hidden_fmt_is_default_cb(pref_t* pref)
2679
0
{
2680
0
    char *cur_hidden_str = column_hidden_fmt_to_str_cb(pref, false);
2681
0
    bool is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2682
2683
0
    g_free(cur_hidden_str);
2684
0
    return is_default;
2685
0
}
2686
2687
/* Number of columns "preference".  This is only used internally and is not written to the
2688
 * preference file
2689
 */
2690
static void
2691
column_num_reset_cb(pref_t* pref)
2692
0
{
2693
0
    *pref->varp.uint = pref->default_val.uint;
2694
0
}
2695
2696
static prefs_set_pref_e
2697
column_num_set_cb(pref_t* pref _U_, const char* value _U_, unsigned int* changed_flags _U_)
2698
0
{
2699
    /* Don't write this to the preferences file */
2700
0
    return PREFS_SET_OK;
2701
0
}
2702
2703
static const char *
2704
column_num_type_name_cb(void)
2705
0
{
2706
0
    return NULL;
2707
0
}
2708
2709
static char *
2710
column_num_type_description_cb(void)
2711
0
{
2712
0
    return g_strdup("");
2713
0
}
2714
2715
static bool
2716
column_num_is_default_cb(pref_t* pref _U_)
2717
0
{
2718
0
    return true;
2719
0
}
2720
2721
static char *
2722
column_num_to_str_cb(pref_t* pref _U_, bool default_val _U_)
2723
0
{
2724
0
    return g_strdup("");
2725
0
}
2726
2727
/*
2728
 * Column format custom preference functions
2729
 */
2730
static void
2731
column_format_init_cb(pref_t* pref, GList** value)
2732
14
{
2733
14
    fmt_data *src_cfmt, *dest_cfmt;
2734
14
    GList *entry;
2735
2736
14
    pref->varp.list = value;
2737
2738
14
    pref->default_val.list = NULL;
2739
112
    for (entry = *pref->varp.list; entry != NULL; entry = g_list_next(entry)) {
2740
98
        src_cfmt = (fmt_data *)entry->data;
2741
98
        dest_cfmt = g_new(fmt_data,1);
2742
98
        dest_cfmt->title = g_strdup(src_cfmt->title);
2743
98
        dest_cfmt->fmt = src_cfmt->fmt;
2744
98
        if (src_cfmt->custom_fields) {
2745
0
            dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2746
0
            dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2747
98
        } else {
2748
98
            dest_cfmt->custom_fields = NULL;
2749
98
            dest_cfmt->custom_occurrence = 0;
2750
98
        }
2751
98
        dest_cfmt->visible = src_cfmt->visible;
2752
98
        dest_cfmt->display = src_cfmt->display;
2753
98
        pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
2754
98
    }
2755
2756
14
    column_register_fields();
2757
14
}
2758
2759
static void
2760
column_format_free_cb(pref_t* pref)
2761
0
{
2762
0
    free_col_info(*pref->varp.list);
2763
0
    free_col_info(pref->default_val.list);
2764
0
}
2765
2766
static void
2767
column_format_reset_cb(pref_t* pref)
2768
0
{
2769
0
    fmt_data *src_cfmt, *dest_cfmt;
2770
0
    GList *entry;
2771
0
    pref_t  *col_num_pref;
2772
2773
0
    free_col_info(*pref->varp.list);
2774
0
    *pref->varp.list = NULL;
2775
2776
0
    for (entry = pref->default_val.list; entry != NULL; entry = g_list_next(entry)) {
2777
0
        src_cfmt = (fmt_data *)entry->data;
2778
0
        dest_cfmt = g_new(fmt_data,1);
2779
0
        dest_cfmt->title = g_strdup(src_cfmt->title);
2780
0
        dest_cfmt->fmt = src_cfmt->fmt;
2781
0
        if (src_cfmt->custom_fields) {
2782
0
            dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2783
0
            dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2784
0
        } else {
2785
0
            dest_cfmt->custom_fields = NULL;
2786
0
            dest_cfmt->custom_occurrence = 0;
2787
0
        }
2788
0
        dest_cfmt->visible = src_cfmt->visible;
2789
0
        dest_cfmt->display = src_cfmt->display;
2790
0
        *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
2791
0
    }
2792
2793
0
    col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2794
0
    ws_assert(col_num_pref != NULL); /* Should never happen */
2795
0
    column_num_reset_cb(col_num_pref);
2796
0
}
2797
2798
static prefs_set_pref_e
2799
column_format_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags _U_)
2800
0
{
2801
0
    GList    *col_l, *col_l_elt;
2802
0
    fmt_data *cfmt;
2803
0
    int      llen;
2804
0
    pref_t   *hidden_pref, *col_num_pref;
2805
2806
0
    col_l = prefs_get_string_list(value);
2807
0
    if (col_l == NULL)
2808
0
      return PREFS_SET_SYNTAX_ERR;
2809
0
    if ((g_list_length(col_l) % 2) != 0) {
2810
      /* A title didn't have a matching format.  */
2811
0
      prefs_clear_string_list(col_l);
2812
0
      return PREFS_SET_SYNTAX_ERR;
2813
0
    }
2814
    /* Check to make sure all column formats are valid.  */
2815
0
    col_l_elt = g_list_first(col_l);
2816
0
    while (col_l_elt) {
2817
0
      fmt_data cfmt_check;
2818
2819
      /* Go past the title.  */
2820
0
      col_l_elt = col_l_elt->next;
2821
2822
      /* Some predefined columns have been migrated to use custom columns.
2823
       * We'll convert these silently here */
2824
0
      try_convert_to_custom_column((char **)&col_l_elt->data);
2825
2826
      /* Parse the format to see if it's valid.  */
2827
0
      if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
2828
        /* It's not a valid column format.  */
2829
0
        prefs_clear_string_list(col_l);
2830
0
        return PREFS_SET_SYNTAX_ERR;
2831
0
      }
2832
0
      if (cfmt_check.fmt == COL_CUSTOM) {
2833
        /* We don't need the custom column field on this pass. */
2834
0
        g_free(cfmt_check.custom_fields);
2835
0
      }
2836
2837
      /* Go past the format.  */
2838
0
      col_l_elt = col_l_elt->next;
2839
0
    }
2840
2841
    /* They're all valid; process them. */
2842
0
    free_col_info(*pref->varp.list);
2843
0
    *pref->varp.list = NULL;
2844
0
    if (prefs.cols_hide_new) {
2845
0
      hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN);
2846
0
    } else {
2847
0
      hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN_FMT);
2848
0
    }
2849
0
    ws_assert(hidden_pref != NULL); /* Should never happen */
2850
0
    col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2851
0
    ws_assert(col_num_pref != NULL); /* Should never happen */
2852
0
    llen             = g_list_length(col_l);
2853
0
    *col_num_pref->varp.uint = llen / 2;
2854
0
    col_l_elt = g_list_first(col_l);
2855
0
    int cidx = 1;
2856
0
    while (col_l_elt) {
2857
0
      cfmt           = g_new(fmt_data,1);
2858
0
      cfmt->title    = g_strdup((char *)col_l_elt->data);
2859
0
      col_l_elt      = col_l_elt->next;
2860
0
      parse_column_format(cfmt, (char *)col_l_elt->data);
2861
0
      if (prefs.cols_hide_new) {
2862
0
        cfmt->visible   = prefs_is_column_visible(*hidden_pref->varp.string, cidx);
2863
0
      } else {
2864
0
        cfmt->visible   = prefs_is_column_fmt_visible(*hidden_pref->varp.string, cfmt);
2865
0
      }
2866
0
      col_l_elt      = col_l_elt->next;
2867
0
      *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
2868
0
      cidx++;
2869
0
    }
2870
2871
0
    prefs_clear_string_list(col_l);
2872
0
    free_string_like_preference(hidden_pref);
2873
0
    column_register_fields();
2874
0
    return PREFS_SET_OK;
2875
0
}
2876
2877
2878
static const char *
2879
column_format_type_name_cb(void)
2880
0
{
2881
0
    return "Packet list column format";
2882
0
}
2883
2884
static char *
2885
column_format_type_description_cb(void)
2886
0
{
2887
0
    return g_strdup("Each pair of strings consists of a column title and its format");
2888
0
}
2889
2890
static bool
2891
column_format_is_default_cb(pref_t* pref)
2892
0
{
2893
0
    GList       *clp = *pref->varp.list,
2894
0
                *pref_col = g_list_first(clp),
2895
0
                *def_col = g_list_first(pref->default_val.list);
2896
0
    fmt_data    *cfmt, *def_cfmt;
2897
0
    bool        is_default = true;
2898
0
    pref_t      *col_num_pref;
2899
2900
    /* See if the column data has changed from the default */
2901
0
    col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2902
0
    if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
2903
0
        is_default = false;
2904
0
    } else {
2905
0
        while (pref_col && def_col) {
2906
0
            cfmt = (fmt_data *) pref_col->data;
2907
0
            def_cfmt = (fmt_data *) def_col->data;
2908
0
            if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
2909
0
                    (cfmt->fmt != def_cfmt->fmt) ||
2910
0
                    (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) &&
2911
0
                     ((g_strcmp0(cfmt->custom_fields, def_cfmt->custom_fields) != 0) ||
2912
0
                      (cfmt->display != def_cfmt->display)))) {
2913
0
                is_default = false;
2914
0
                break;
2915
0
            }
2916
2917
0
            pref_col = pref_col->next;
2918
0
            def_col = def_col->next;
2919
0
        }
2920
0
    }
2921
2922
0
    return is_default;
2923
0
}
2924
2925
static char *
2926
column_format_to_str_cb(pref_t* pref, bool default_val)
2927
0
{
2928
0
    GList       *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
2929
0
    GList       *clp = g_list_first(pref_l);
2930
0
    GList       *col_l;
2931
0
    fmt_data    *cfmt;
2932
0
    char        *column_format_str;
2933
2934
0
    col_l = NULL;
2935
0
    while (clp) {
2936
0
        cfmt = (fmt_data *) clp->data;
2937
0
        col_l = g_list_append(col_l, g_strdup(cfmt->title));
2938
0
        col_l = g_list_append(col_l, column_fmt_data_to_str(cfmt));
2939
0
        clp = clp->next;
2940
0
    }
2941
2942
0
    column_format_str = join_string_list(col_l);
2943
0
    prefs_clear_string_list(col_l);
2944
0
    return column_format_str;
2945
0
}
2946
2947
2948
/******  Capture column custom preference functions  ******/
2949
2950
/* This routine is only called when Wireshark is started, NOT when another profile is selected.
2951
   Copy the pref->capture_columns list (just loaded with the capture_cols[] struct values)
2952
   to prefs->default_val.list.
2953
*/
2954
static void
2955
capture_column_init_cb(pref_t* pref, GList** capture_cols_values)
2956
14
{
2957
14
    GList   *ccv_list = *capture_cols_values,
2958
14
            *dlist = NULL;
2959
2960
    /*  */
2961
112
    while (ccv_list) {
2962
98
        dlist = g_list_append(dlist, g_strdup((char *)ccv_list->data));
2963
98
        ccv_list = ccv_list->next;
2964
98
    }
2965
2966
14
    pref->default_val.list = dlist;
2967
14
    pref->varp.list = &prefs.capture_columns;
2968
14
    pref->stashed_val.boolval = false;
2969
14
}
2970
2971
/* Free the prefs->capture_columns list strings and remove the list entries.
2972
   Note that since pref->varp.list points to &prefs.capture_columns, it is
2973
   also freed.
2974
*/
2975
static void
2976
capture_column_free_cb(pref_t* pref)
2977
0
{
2978
0
    prefs_clear_string_list(prefs.capture_columns);
2979
0
    prefs.capture_columns = NULL;
2980
2981
0
    if (pref->stashed_val.boolval == true) {
2982
0
      prefs_clear_string_list(pref->default_val.list);
2983
0
      pref->default_val.list = NULL;
2984
0
    }
2985
0
}
2986
2987
/* Copy pref->default_val.list to *pref->varp.list.
2988
*/
2989
static void
2990
capture_column_reset_cb(pref_t* pref)
2991
0
{
2992
0
    GList *vlist = NULL, *dlist;
2993
2994
    /* Free the column name strings and remove the links from *pref->varp.list */
2995
0
    prefs_clear_string_list(*pref->varp.list);
2996
2997
0
    for (dlist = pref->default_val.list; dlist != NULL; dlist = g_list_next(dlist)) {
2998
0
      vlist = g_list_append(vlist, g_strdup((char *)dlist->data));
2999
0
    }
3000
0
    *pref->varp.list = vlist;
3001
0
}
3002
3003
static prefs_set_pref_e
3004
capture_column_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags _U_)
3005
0
{
3006
0
    GList *col_l  = prefs_get_string_list(value);
3007
0
    GList *col_l_elt;
3008
0
    char *col_name;
3009
0
    int i;
3010
3011
0
    if (col_l == NULL)
3012
0
      return PREFS_SET_SYNTAX_ERR;
3013
3014
0
    capture_column_free_cb(pref);
3015
3016
    /* If value (the list of capture.columns read from preferences) is empty, set capture.columns
3017
       to the full list of valid capture column names. */
3018
0
    col_l_elt = g_list_first(col_l);
3019
0
    if (!(*(char *)col_l_elt->data)) {
3020
0
        for (i = 0; i < num_capture_cols; i++) {
3021
0
          col_name = g_strdup(capture_cols[i]);
3022
0
          prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3023
0
        }
3024
0
    }
3025
3026
    /* Verify that all the column names are valid. If not, use the entire list of valid columns.
3027
     */
3028
0
    while (col_l_elt) {
3029
0
      bool found_match = false;
3030
0
      col_name = (char *)col_l_elt->data;
3031
3032
0
      for (i = 0; i < num_capture_cols; i++) {
3033
0
        if (strcmp(col_name, capture_cols[i])==0) {
3034
0
          found_match = true;
3035
0
          break;
3036
0
        }
3037
0
      }
3038
0
      if (!found_match) {
3039
        /* One or more cols are invalid so use the entire list of valid cols. */
3040
0
        for (i = 0; i < num_capture_cols; i++) {
3041
0
          col_name = g_strdup(capture_cols[i]);
3042
0
          prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3043
0
        }
3044
0
        pref->varp.list = &prefs.capture_columns;
3045
0
        prefs_clear_string_list(col_l);
3046
0
        return PREFS_SET_SYNTAX_ERR;
3047
0
      }
3048
0
      col_l_elt = col_l_elt->next;
3049
0
    }
3050
3051
0
    col_l_elt = g_list_first(col_l);
3052
0
    while (col_l_elt) {
3053
0
      col_name = (char *)col_l_elt->data;
3054
0
      prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3055
0
      col_l_elt = col_l_elt->next;
3056
0
    }
3057
0
    pref->varp.list = &prefs.capture_columns;
3058
0
    g_list_free(col_l);
3059
0
    return PREFS_SET_OK;
3060
0
}
3061
3062
3063
static const char *
3064
capture_column_type_name_cb(void)
3065
0
{
3066
0
    return "Column list";
3067
0
}
3068
3069
static char *
3070
capture_column_type_description_cb(void)
3071
0
{
3072
0
    return g_strdup(
3073
0
        "List of columns to be displayed in the capture options dialog.\n"
3074
0
        CAPTURE_COL_TYPE_DESCRIPTION);
3075
0
}
3076
3077
static bool
3078
capture_column_is_default_cb(pref_t* pref)
3079
0
{
3080
0
    GList   *pref_col = g_list_first(prefs.capture_columns),
3081
0
            *def_col = g_list_first(pref->default_val.list);
3082
0
    bool is_default = true;
3083
3084
    /* See if the column data has changed from the default */
3085
0
    while (pref_col && def_col) {
3086
0
        if (strcmp((char *)pref_col->data, (char *)def_col->data) != 0) {
3087
0
            is_default = false;
3088
0
            break;
3089
0
        }
3090
0
        pref_col = pref_col->next;
3091
0
        def_col = def_col->next;
3092
0
    }
3093
3094
    /* Ensure the same column count */
3095
0
    if (((pref_col == NULL) && (def_col != NULL)) ||
3096
0
        ((pref_col != NULL) && (def_col == NULL)))
3097
0
        is_default = false;
3098
3099
0
    return is_default;
3100
0
}
3101
3102
static char *
3103
capture_column_to_str_cb(pref_t* pref, bool default_val)
3104
0
{
3105
3106
0
    GList       *pref_l = default_val ? pref->default_val.list : prefs.capture_columns;
3107
0
    GList       *clp = g_list_first(pref_l);
3108
0
    GList       *col_l = NULL;
3109
0
    char        *col;
3110
0
    char        *capture_column_str;
3111
3112
0
    while (clp) {
3113
0
        col = (char *) clp->data;
3114
0
        col_l = g_list_append(col_l, g_strdup(col));
3115
0
        clp = clp->next;
3116
0
    }
3117
3118
0
    capture_column_str = join_string_list(col_l);
3119
0
    prefs_clear_string_list(col_l);
3120
0
    return capture_column_str;
3121
0
}
3122
3123
static prefs_set_pref_e
3124
colorized_frame_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
3125
0
{
3126
0
    (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
3127
0
    return PREFS_SET_OK;
3128
0
}
3129
3130
static const char *
3131
colorized_frame_type_name_cb(void)
3132
0
{
3133
   /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
3134
    * file until the colors can be changed in the GUI. Currently this is not really
3135
    * possible since the STOCK-icons for these colors are hardcoded.
3136
    *
3137
    * XXX Find a way to change the colors of the STOCK-icons on the fly and then
3138
    *     add these 10 colors to the list of colors that can be changed through
3139
    *     the preferences.
3140
    *
3141
    */
3142
0
    return NULL;
3143
0
}
3144
3145
static char *
3146
colorized_frame_type_description_cb(void)
3147
0
{
3148
0
    return g_strdup("");
3149
0
}
3150
3151
static bool
3152
colorized_frame_is_default_cb(pref_t* pref _U_)
3153
0
{
3154
0
    return true;
3155
0
}
3156
3157
static char *
3158
colorized_frame_to_str_cb(pref_t* pref _U_, bool default_val _U_)
3159
0
{
3160
0
    return g_strdup("");
3161
0
}
3162
3163
/*
3164
 * Register all non-dissector modules' preferences.
3165
 */
3166
static module_t *gui_module;
3167
static module_t *gui_color_module;
3168
static module_t *nameres_module;
3169
3170
static void
3171
prefs_register_modules(void)
3172
28
{
3173
28
    module_t *printing, *capture_module, *console_module,
3174
28
        *gui_layout_module, *gui_font_module;
3175
28
    module_t *extcap_module;
3176
28
    unsigned int layout_gui_flags;
3177
28
    struct pref_custom_cbs custom_cbs;
3178
3179
28
    if (protocols_module != NULL) {
3180
        /* Already setup preferences */
3181
14
        return;
3182
14
    }
3183
3184
    /* GUI
3185
     * These are "simple" GUI preferences that can be read/written using the
3186
     * preference module API.  These preferences still use their own
3187
     * configuration screens for access, but this cuts down on the
3188
     * preference "string compare list" in set_pref()
3189
     */
3190
14
    extcap_module = prefs_register_module(NULL, "extcap", "Extcap Utilities",
3191
14
        "Extcap Utilities", NULL, NULL, false);
3192
3193
    /* Setting default value to true */
3194
14
    prefs.extcap_save_on_start = true;
3195
14
    prefs_register_bool_preference(extcap_module, "gui_save_on_start",
3196
14
                                   "Save arguments on start of capture",
3197
14
                                   "Save arguments on start of capture",
3198
14
                                   &prefs.extcap_save_on_start);
3199
3200
    /* GUI
3201
     * These are "simple" GUI preferences that can be read/written using the
3202
     * preference module API.  These preferences still use their own
3203
     * configuration screens for access, but this cuts down on the
3204
     * preference "string compare list" in set_pref()
3205
     */
3206
14
    gui_module = prefs_register_module(NULL, "gui", "User Interface",
3207
14
        "User Interface", NULL, &gui_callback, false);
3208
    /*
3209
     * The GUI preferences don't affect dissection in general.
3210
     * Any changes are signaled in other ways, so PREF_EFFECT_GUI doesn't
3211
     * explicitly do anything, but wslua_set_preference expects *some*
3212
     * effect flag to be set if the preference was changed.
3213
     * We have to do this again for all the submodules (except for the
3214
     * layout submodule, which has its own effect flag).
3215
     */
3216
14
    unsigned gui_effect_flags = prefs_get_module_effect_flags(gui_module);
3217
14
    gui_effect_flags |= PREF_EFFECT_GUI;
3218
14
    gui_effect_flags &= (~PREF_EFFECT_DISSECTION);
3219
14
    prefs_set_module_effect_flags(gui_module, gui_effect_flags);
3220
3221
    /*
3222
     * gui.console_open is stored in the registry in addition to the
3223
     * preferences file. It is also read independently by ws_log_init()
3224
     * for early log initialization of the console.
3225
     */
3226
14
    prefs_register_enum_preference(gui_module, "console_open",
3227
14
                       "Open a console window",
3228
14
                       "Open a console window (Windows only)",
3229
14
                       (int *)&ws_log_console_open, gui_console_open_type, false);
3230
3231
14
    prefs_register_obsolete_preference(gui_module, "scrollbar_on_right");
3232
14
    prefs_register_obsolete_preference(gui_module, "packet_list_sel_browse");
3233
14
    prefs_register_obsolete_preference(gui_module, "protocol_tree_sel_browse");
3234
14
    prefs_register_obsolete_preference(gui_module, "tree_view_altern_colors");
3235
14
    prefs_register_obsolete_preference(gui_module, "expert_composite_eyecandy");
3236
14
    prefs_register_obsolete_preference(gui_module, "filter_toolbar_show_in_statusbar");
3237
3238
14
    prefs_register_bool_preference(gui_module, "restore_filter_after_following_stream",
3239
14
                                   "Restore current display filter after following a stream",
3240
14
                                   "Restore current display filter after following a stream?",
3241
14
                                   &prefs.restore_filter_after_following_stream);
3242
3243
14
    prefs_register_obsolete_preference(gui_module, "protocol_tree_line_style");
3244
3245
14
    prefs_register_obsolete_preference(gui_module, "protocol_tree_expander_style");
3246
3247
14
    prefs_register_obsolete_preference(gui_module, "hex_dump_highlight_style");
3248
3249
14
    prefs_register_obsolete_preference(gui_module, "packet_editor.enabled");
3250
3251
14
    gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL);
3252
14
    prefs_set_module_effect_flags(gui_column_module, gui_effect_flags);
3253
    /* For reading older preference files with "column." preferences */
3254
14
    prefs_register_module_alias("column", gui_column_module);
3255
3256
3257
14
    custom_cbs.free_cb = free_string_like_preference;
3258
14
    custom_cbs.reset_cb = reset_string_like_preference;
3259
14
    custom_cbs.set_cb = column_hidden_set_cb;
3260
14
    custom_cbs.type_name_cb = column_hidden_type_name_cb;
3261
14
    custom_cbs.type_description_cb = column_hidden_type_description_cb;
3262
14
    custom_cbs.is_default_cb = column_hidden_is_default_cb;
3263
14
    custom_cbs.to_str_cb = column_hidden_to_str_cb;
3264
14
    register_string_like_preference(gui_column_module, PRS_COL_HIDDEN, "Packet list hidden columns",
3265
14
        "List all column indices (1-indexed) to hide in the packet list",
3266
14
        &cols_hidden_list, PREF_CUSTOM, &custom_cbs, false);
3267
3268
14
    custom_cbs.set_cb = column_hidden_fmt_set_cb;
3269
14
    custom_cbs.type_name_cb = column_hidden_fmt_type_name_cb;
3270
14
    custom_cbs.type_description_cb = column_hidden_fmt_type_description_cb;
3271
14
    custom_cbs.is_default_cb = column_hidden_fmt_is_default_cb;
3272
14
    custom_cbs.to_str_cb = column_hidden_fmt_to_str_cb;
3273
3274
14
    register_string_like_preference(gui_column_module, PRS_COL_HIDDEN_FMT, "Packet list hidden column formats (deprecated)",
3275
14
        "List all column formats to hide in the packet list; deprecated in favor of the index-based preference",
3276
14
        &cols_hidden_fmt_list, PREF_CUSTOM, &custom_cbs, false);
3277
3278
14
    custom_cbs.free_cb = column_format_free_cb;
3279
14
    custom_cbs.reset_cb = column_format_reset_cb;
3280
14
    custom_cbs.set_cb = column_format_set_cb;
3281
14
    custom_cbs.type_name_cb = column_format_type_name_cb;
3282
14
    custom_cbs.type_description_cb = column_format_type_description_cb;
3283
14
    custom_cbs.is_default_cb = column_format_is_default_cb;
3284
14
    custom_cbs.to_str_cb = column_format_to_str_cb;
3285
3286
14
    prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT, "Packet list column format",
3287
14
        "Each pair of strings consists of a column title and its format", &custom_cbs,
3288
14
        column_format_init_cb, &prefs.col_list);
3289
3290
    /* Number of columns.  This is only used internally and is not written to the
3291
     * preference file
3292
     */
3293
14
    custom_cbs.free_cb = custom_pref_no_cb;
3294
14
    custom_cbs.reset_cb = column_num_reset_cb;
3295
14
    custom_cbs.set_cb = column_num_set_cb;
3296
14
    custom_cbs.type_name_cb = column_num_type_name_cb;
3297
14
    custom_cbs.type_description_cb = column_num_type_description_cb;
3298
14
    custom_cbs.is_default_cb = column_num_is_default_cb;
3299
14
    custom_cbs.to_str_cb = column_num_to_str_cb;
3300
14
    prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM, "Number of columns",
3301
14
        "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
3302
3303
    /* User Interface : Font */
3304
14
    gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL);
3305
14
    prefs_set_module_effect_flags(gui_font_module, gui_effect_flags);
3306
3307
14
    prefs_register_obsolete_preference(gui_font_module, "font_name");
3308
3309
14
    prefs_register_obsolete_preference(gui_font_module, "gtk2.font_name");
3310
3311
14
    register_string_like_preference(gui_font_module, "qt.font_name", "Font name",
3312
14
        "Font name for packet list, protocol tree, and hex dump panes. (Qt)",
3313
14
        &prefs.gui_font_name, PREF_STRING, NULL, true);
3314
3315
    /* User Interface : Colors */
3316
14
    gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL);
3317
14
    unsigned gui_color_effect_flags = gui_effect_flags | PREF_EFFECT_GUI_COLOR;
3318
14
    prefs_set_module_effect_flags(gui_color_module, gui_color_effect_flags);
3319
3320
14
    prefs_register_enum_preference(gui_color_module, "color_scheme", "Color scheme", "Color scheme",
3321
14
        &prefs.gui_color_scheme, gui_color_scheme, false);
3322
3323
14
    prefs_register_color_preference(gui_color_module, "active_frame.fg", "Foreground color for an active selected item",
3324
14
        "Foreground color for an active selected item", &prefs.gui_active_fg);
3325
3326
14
    prefs_register_color_preference(gui_color_module, "active_frame.bg", "Background color for an active selected item",
3327
14
        "Background color for an active selected item", &prefs.gui_active_bg);
3328
3329
14
    prefs_register_enum_preference(gui_color_module, "active_frame.style", "Color style for an active selected item",
3330
14
        "Color style for an active selected item", &prefs.gui_active_style, gui_selection_style, false);
3331
3332
14
    prefs_register_color_preference(gui_color_module, "inactive_frame.fg", "Foreground color for an inactive selected item",
3333
14
        "Foreground color for an inactive selected item", &prefs.gui_inactive_fg);
3334
3335
14
    prefs_register_color_preference(gui_color_module, "inactive_frame.bg", "Background color for an inactive selected item",
3336
14
        "Background color for an inactive selected item", &prefs.gui_inactive_bg);
3337
3338
14
    prefs_register_enum_preference(gui_color_module, "inactive_frame.style", "Color style for an inactive selected item",
3339
14
        "Color style for an inactive selected item", &prefs.gui_inactive_style, gui_selection_style, false);
3340
3341
14
    prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
3342
14
        "Color preferences for a marked frame", &prefs.gui_marked_fg);
3343
3344
14
    prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
3345
14
        "Color preferences for a marked frame", &prefs.gui_marked_bg);
3346
3347
14
    prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
3348
14
        "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
3349
3350
14
    prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
3351
14
        "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
3352
3353
14
    prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
3354
14
        "TCP stream window color preference", &prefs.st_client_fg);
3355
3356
14
    prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
3357
14
        "TCP stream window color preference", &prefs.st_client_bg);
3358
3359
14
    prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
3360
14
        "TCP stream window color preference", &prefs.st_server_fg);
3361
3362
14
    prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
3363
14
        "TCP stream window color preference", &prefs.st_server_bg);
3364
3365
14
    custom_cbs.free_cb = free_string_like_preference;
3366
14
    custom_cbs.reset_cb = reset_string_like_preference;
3367
14
    custom_cbs.set_cb = colorized_frame_set_cb;
3368
14
    custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3369
14
    custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3370
14
    custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3371
14
    custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3372
14
    register_string_like_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
3373
14
        "Filter Colorized Foreground",
3374
14
        &prefs.gui_colorized_fg, PREF_CUSTOM, &custom_cbs, true);
3375
3376
14
    custom_cbs.free_cb = free_string_like_preference;
3377
14
    custom_cbs.reset_cb = reset_string_like_preference;
3378
14
    custom_cbs.set_cb = colorized_frame_set_cb;
3379
14
    custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3380
14
    custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3381
14
    custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3382
14
    custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3383
14
    register_string_like_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
3384
14
        "Filter Colorized Background",
3385
14
        &prefs.gui_colorized_bg, PREF_CUSTOM, &custom_cbs, true);
3386
3387
14
    prefs_register_color_preference(gui_color_module, "color_filter_fg.valid", "Valid color filter foreground",
3388
14
        "Valid color filter foreground", &prefs.gui_filter_valid_fg);
3389
14
    prefs_register_color_preference(gui_color_module, "color_filter_bg.valid", "Valid color filter background",
3390
14
        "Valid color filter background", &prefs.gui_filter_valid_bg);
3391
3392
14
    prefs_register_color_preference(gui_color_module, "color_filter_fg.invalid", "Invalid color filter foreground",
3393
14
        "Invalid color filter foreground", &prefs.gui_filter_invalid_fg);
3394
14
    prefs_register_color_preference(gui_color_module, "color_filter_bg.invalid", "Invalid color filter background",
3395
14
        "Invalid color filter background", &prefs.gui_filter_invalid_bg);
3396
3397
14
    prefs_register_color_preference(gui_color_module, "color_filter_fg.deprecated", "Deprecated color filter foreground",
3398
14
        "Deprecated color filter foreground", &prefs.gui_filter_deprecated_fg);
3399
14
    prefs_register_color_preference(gui_color_module, "color_filter_bg.deprecated", "Deprecated color filter background",
3400
14
        "Deprecated color filter background", &prefs.gui_filter_deprecated_bg);
3401
3402
14
    prefs_register_enum_preference(gui_module, "fileopen.style",
3403
14
                       "Where to start the File Open dialog box",
3404
14
                       "Where to start the File Open dialog box",
3405
14
                       &prefs.gui_fileopen_style, gui_fileopen_style, false);
3406
3407
14
    prefs_register_uint_preference(gui_module, "recent_files_count.max",
3408
14
                                   "The max. number of items in the open recent files list",
3409
14
                                   "The max. number of items in the open recent files list",
3410
14
                                   10,
3411
14
                                   &prefs.gui_recent_files_count_max);
3412
3413
14
    prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
3414
14
                                   "The max. number of entries in the display filter list",
3415
14
                                   "The max. number of entries in the display filter list",
3416
14
                                   10,
3417
14
                                   &prefs.gui_recent_df_entries_max);
3418
3419
14
    register_string_like_preference(gui_module, "fileopen.dir", "Start Directory",
3420
14
        "Directory to start in when opening File Open dialog.",
3421
14
        &prefs.gui_fileopen_dir, PREF_DIRNAME, NULL, true);
3422
3423
14
    prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
3424
3425
14
    prefs_register_uint_preference(gui_module, "fileopen.preview",
3426
14
                                   "The preview timeout in the File Open dialog",
3427
14
                                   "The preview timeout in the File Open dialog",
3428
14
                                   10,
3429
14
                                   &prefs.gui_fileopen_preview);
3430
3431
14
    register_string_like_preference(gui_module, "tlskeylog_command", "Program to launch with TLS Keylog",
3432
14
        "Program path or command line to launch with SSLKEYLOGFILE",
3433
14
        &prefs.gui_tlskeylog_command, PREF_STRING, NULL, true);
3434
3435
14
    prefs_register_bool_preference(gui_module, "ask_unsaved",
3436
14
                                   "Ask to save unsaved capture files",
3437
14
                                   "Ask to save unsaved capture files?",
3438
14
                                   &prefs.gui_ask_unsaved);
3439
3440
14
    prefs_register_bool_preference(gui_module, "autocomplete_filter",
3441
14
                                   "Display autocompletion for filter text",
3442
14
                                   "Display an autocomplete suggestion for display and capture filter controls",
3443
14
                                   &prefs.gui_autocomplete_filter);
3444
3445
14
    prefs_register_bool_preference(gui_module, "find_wrap",
3446
14
                                   "Wrap to beginning/end of file during search",
3447
14
                                   "Wrap to beginning/end of file during search?",
3448
14
                                   &prefs.gui_find_wrap);
3449
3450
14
    prefs_register_obsolete_preference(gui_module, "use_pref_save");
3451
3452
14
    prefs_register_bool_preference(gui_module, "geometry.save.position",
3453
14
                                   "Save window position at exit",
3454
14
                                   "Save window position at exit?",
3455
14
                                   &prefs.gui_geometry_save_position);
3456
3457
14
    prefs_register_bool_preference(gui_module, "geometry.save.size",
3458
14
                                   "Save window size at exit",
3459
14
                                   "Save window size at exit?",
3460
14
                                   &prefs.gui_geometry_save_size);
3461
3462
14
    prefs_register_bool_preference(gui_module, "geometry.save.maximized",
3463
14
                                   "Save window maximized state at exit",
3464
14
                                   "Save window maximized state at exit?",
3465
14
                                   &prefs.gui_geometry_save_maximized);
3466
3467
14
    prefs_register_obsolete_preference(gui_module, "macosx_style");
3468
3469
14
    prefs_register_obsolete_preference(gui_module, "geometry.main.x");
3470
14
    prefs_register_obsolete_preference(gui_module, "geometry.main.y");
3471
14
    prefs_register_obsolete_preference(gui_module, "geometry.main.width");
3472
14
    prefs_register_obsolete_preference(gui_module, "geometry.main.height");
3473
14
    prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
3474
3475
14
    prefs_register_enum_preference(gui_module, "toolbar_main_style",
3476
14
                       "Main Toolbar style",
3477
14
                       "Main Toolbar style",
3478
14
                       &prefs.gui_toolbar_main_style, gui_toolbar_style, false);
3479
3480
14
    prefs_register_obsolete_preference(gui_module, "toolbar_filter_style");
3481
14
    prefs_register_obsolete_preference(gui_module, "webbrowser");
3482
3483
14
    prefs_register_bool_preference(gui_module, "update.enabled",
3484
14
                                   "Check for updates",
3485
14
                                   "Check for updates (Windows and macOS only)",
3486
14
                                   &prefs.gui_update_enabled);
3487
3488
14
    prefs_register_enum_preference(gui_module, "update.channel",
3489
14
                       "Update channel",
3490
14
                       "The type of update to fetch. You should probably leave this set to STABLE.",
3491
14
                       (int*)(void*)(&prefs.gui_update_channel), gui_update_channel, false);
3492
3493
14
    prefs_register_uint_preference(gui_module, "update.interval",
3494
14
                                   "How often to check for software updates",
3495
14
                                   "How often to check for software updates in seconds",
3496
14
                                   10,
3497
14
                                   &prefs.gui_update_interval);
3498
3499
14
    prefs_register_uint_preference(gui_module, "debounce.timer",
3500
14
                                   "How long to wait before processing computationally intensive user input",
3501
14
                                   "How long to wait (in milliseconds) before processing "
3502
14
                                   "computationally intensive user input. "
3503
14
                                   "If you type quickly, consider lowering the value for a 'snappier' "
3504
14
                                   "experience. "
3505
14
                                   "If you type slowly, consider increasing the value to avoid performance issues. "
3506
14
                                   "This is currently used to delay searches in View -> Internals -> Supported Protocols "
3507
14
                                   "and Preferences -> Advanced menu.",
3508
14
                                   10,
3509
14
                                   &prefs.gui_debounce_timer);
3510
3511
14
    register_string_like_preference(gui_module, "window_title", "Custom window title",
3512
14
        "Custom window title to be appended to the existing title\n"
3513
14
        "%C = capture comment from command line\n"
3514
14
        "%F = file path of the capture file\n"
3515
14
        "%P = profile name\n"
3516
14
        "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3517
14
        "%V = version info",
3518
14
        &prefs.gui_window_title, PREF_STRING, NULL, true);
3519
3520
14
    register_string_like_preference(gui_module, "prepend_window_title", "Custom window title prefix",
3521
14
        "Custom window title to be prepended to the existing title\n"
3522
14
        "%C = capture comment from command line\n"
3523
14
        "%F = file path of the capture file\n"
3524
14
        "%P = profile name\n"
3525
14
        "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3526
14
        "%V = version info",
3527
14
        &prefs.gui_prepend_window_title, PREF_STRING, NULL, true);
3528
3529
14
    register_string_like_preference(gui_module, "start_title", "Custom start page title",
3530
14
        "Custom start page title",
3531
14
        &prefs.gui_start_title, PREF_STRING, NULL, true);
3532
3533
14
    prefs_register_enum_preference(gui_module, "version_placement",
3534
14
                       "Show version in the start page and/or main screen's title bar",
3535
14
                       "Show version in the start page and/or main screen's title bar",
3536
14
                       (int*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, false);
3537
3538
14
    prefs_register_obsolete_preference(gui_module, "auto_scroll_on_expand");
3539
14
    prefs_register_obsolete_preference(gui_module, "auto_scroll_percentage");
3540
3541
14
    prefs_register_uint_preference(gui_module, "max_export_objects",
3542
14
                                   "Maximum number of exported objects",
3543
14
                                   "The maximum number of objects that can be exported",
3544
14
                                   10,
3545
14
                                   &prefs.gui_max_export_objects);
3546
14
    prefs_register_uint_preference(gui_module, "max_tree_items",
3547
14
                                   "Maximum number of tree items",
3548
14
                                   "The maximum number of items that can be added to the dissection tree (Increase with caution)",
3549
14
                                   10,
3550
14
                                   &prefs.gui_max_tree_items);
3551
    /*
3552
     * Used independently by proto_tree_add_node, call_dissector*, dissector_try_heuristic,
3553
     * and increment_dissection_depth.
3554
     */
3555
14
    prefs_register_uint_preference(gui_module, "max_tree_depth",
3556
14
                                   "Maximum dissection depth",
3557
14
                                   "The maximum depth for dissection tree and protocol layer checks. (Increase with caution)",
3558
14
                                   10,
3559
14
                                   &prefs.gui_max_tree_depth);
3560
3561
14
    prefs_register_bool_preference(gui_module, "welcome_page.show_recent",
3562
14
                                   "Show recent files on the welcome page",
3563
14
                                   "This will enable or disable the 'Open' list on the welcome page.",
3564
14
                                   &prefs.gui_welcome_page_show_recent);
3565
3566
    /* User Interface : Layout */
3567
14
    gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
3568
    /* Adjust the preference effects of layout GUI for better handling of preferences at Wireshark (GUI) level */
3569
14
    layout_gui_flags = prefs_get_module_effect_flags(gui_layout_module);
3570
14
    layout_gui_flags |= PREF_EFFECT_GUI_LAYOUT;
3571
14
    layout_gui_flags &= (~PREF_EFFECT_DISSECTION);
3572
3573
14
    prefs_register_uint_preference(gui_layout_module, "layout_type",
3574
14
                                   "Layout type",
3575
14
                                   "Layout type (1-6)",
3576
14
                                   10,
3577
14
                                   (unsigned*)(void*)(&prefs.gui_layout_type));
3578
14
    prefs_set_effect_flags_by_name(gui_layout_module, "layout_type", layout_gui_flags);
3579
3580
14
    prefs_register_enum_preference(gui_layout_module, "layout_content_1",
3581
14
                       "Layout content of the pane 1",
3582
14
                       "Layout content of the pane 1",
3583
14
                       (int*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, false);
3584
14
    prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_1", layout_gui_flags);
3585
3586
14
    prefs_register_enum_preference(gui_layout_module, "layout_content_2",
3587
14
                       "Layout content of the pane 2",
3588
14
                       "Layout content of the pane 2",
3589
14
                       (int*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, false);
3590
14
    prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_2", layout_gui_flags);
3591
3592
14
    prefs_register_enum_preference(gui_layout_module, "layout_content_3",
3593
14
                       "Layout content of the pane 3",
3594
14
                       "Layout content of the pane 3",
3595
14
                       (int*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, false);
3596
14
    prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_3", layout_gui_flags);
3597
3598
14
    prefs_register_bool_preference(gui_layout_module, "packet_list_separator.enabled",
3599
14
                                   "Enable Packet List Separator",
3600
14
                                   "Enable Packet List Separator",
3601
14
                                   &prefs.gui_packet_list_separator);
3602
3603
14
    prefs_register_bool_preference(gui_layout_module, "packet_header_column_definition.enabled",
3604
14
                                    "Show column definition in packet list header",
3605
14
                                    "Show column definition in packet list header",
3606
14
                                    &prefs.gui_packet_header_column_definition);
3607
3608
    /* packet_list_hover_style affects the colors, not the layout.
3609
     * It's in the layout module to group it with the other packet list
3610
     * preferences for the user's benefit with the dialog.
3611
     */
3612
14
    prefs_register_bool_preference(gui_layout_module, "packet_list_hover_style.enabled",
3613
14
                                   "Enable Packet List mouse-over colorization",
3614
14
                                   "Enable Packet List mouse-over colorization",
3615
14
                                   &prefs.gui_packet_list_hover_style);
3616
14
    prefs_set_effect_flags_by_name(gui_layout_module, "packet_list_hover_style.enabled", gui_color_effect_flags);
3617
3618
14
    prefs_register_bool_preference(gui_layout_module, "show_selected_packet.enabled",
3619
14
                                   "Show selected packet in the Status Bar",
3620
14
                                   "Show selected packet in the Status Bar",
3621
14
                                   &prefs.gui_show_selected_packet);
3622
3623
14
    prefs_register_bool_preference(gui_layout_module, "show_file_load_time.enabled",
3624
14
                                   "Show file load time in the Status Bar",
3625
14
                                   "Show file load time in the Status Bar",
3626
14
                                   &prefs.gui_show_file_load_time);
3627
3628
14
    prefs_register_enum_preference(gui_layout_module, "packet_dialog_layout",
3629
14
                                   "Packet Dialog layout",
3630
14
                                   "Packet Dialog layout",
3631
14
                                   (unsigned*)(void*)(&prefs.gui_packet_dialog_layout), gui_packet_dialog_layout, false);
3632
3633
14
    prefs_register_enum_preference(gui_module, "packet_list_elide_mode",
3634
14
                       "Elide mode",
3635
14
                       "The position of \"...\" (ellipsis) in packet list text.",
3636
14
                       (int*)(void*)(&prefs.gui_packet_list_elide_mode), gui_packet_list_elide_mode, false);
3637
14
    prefs_register_uint_preference(gui_module, "decimal_places1",
3638
14
            "Count of decimal places for values of type 1",
3639
14
            "Sets the count of decimal places for values of type 1."
3640
14
            "Type 1 values are defined by authors."
3641
14
            "Value can be in range 2 to 10.",
3642
14
            10,&prefs.gui_decimal_places1);
3643
3644
14
    prefs_register_uint_preference(gui_module, "decimal_places2",
3645
14
            "Count of decimal places for values of type 2",
3646
14
            "Sets the count of decimal places for values of type 2."
3647
14
            "Type 2 values are defined by authors."
3648
14
            "Value can be in range 2 to 10.",
3649
14
            10,&prefs.gui_decimal_places2);
3650
3651
14
    prefs_register_uint_preference(gui_module, "decimal_places3",
3652
14
            "Count of decimal places for values of type 3",
3653
14
            "Sets the count of decimal places for values of type 3."
3654
14
            "Type 3 values are defined by authors."
3655
14
            "Value can be in range 2 to 10.",
3656
14
            10,&prefs.gui_decimal_places3);
3657
3658
14
    prefs_register_bool_preference(gui_module, "rtp_player_use_disk1",
3659
14
            "RTP Player saves temporary data to disk",
3660
14
            "If set to true, RTP Player saves temporary data to "
3661
14
            "temp files on disk. If not set, it uses memory."
3662
14
            "Every stream uses one file therefore you might touch "
3663
14
            "OS limit for count of opened files."
3664
14
            "When ui.rtp_player_use_disk2 is set to true too, it uses "
3665
14
            " two files per RTP stream together."
3666
14
            ,&prefs.gui_rtp_player_use_disk1);
3667
3668
14
    prefs_register_bool_preference(gui_module, "rtp_player_use_disk2",
3669
14
            "RTP Player saves temporary dictionary for data to disk",
3670
14
            "If set to true, RTP Player saves temporary dictionary to "
3671
14
            "temp files on disk. If not set, it uses memory."
3672
14
            "Every stream uses one file therefore you might touch "
3673
14
            "OS limit for count of opened files."
3674
14
            "When ui.rtp_player_use_disk1 is set to true too, it uses "
3675
14
            " two files per RTP stream."
3676
14
            ,&prefs.gui_rtp_player_use_disk2);
3677
3678
14
    prefs_register_enum_preference(gui_layout_module, "gui_packet_list_copy_format_options_for_keyboard_shortcut",
3679
14
                                   "Allows text to be copied with selected format",
3680
14
                                   "Allows text to be copied with selected format when copied via keyboard",
3681
14
                                   (int*)(void*)(&prefs.gui_packet_list_copy_format_options_for_keyboard_shortcut),
3682
14
                                   gui_packet_list_copy_format_options_for_keyboard_shortcut, false);
3683
3684
14
    prefs_register_bool_preference(gui_layout_module, "gui_packet_list_copy_text_with_aligned_columns",
3685
14
                                   "Allows text to be copied with aligned columns",
3686
14
                                   "Allows text to be copied with aligned columns when copied via menu or keyboard",
3687
14
                                   &prefs.gui_packet_list_copy_text_with_aligned_columns);
3688
3689
14
    prefs_register_bool_preference(gui_layout_module, "packet_list_show_related",
3690
14
                                   "Show Related Packets",
3691
14
                                   "Show related packet indicators in the first column",
3692
14
                                   &prefs.gui_packet_list_show_related);
3693
3694
14
    prefs_register_bool_preference(gui_layout_module, "packet_list_show_minimap",
3695
14
                                   "Enable Intelligent Scroll Bar",
3696
14
                                   "Show the intelligent scroll bar (a minimap of packet list colors in the scrollbar)",
3697
14
                                   &prefs.gui_packet_list_show_minimap);
3698
3699
14
    prefs_register_bool_preference(gui_module, "packet_list_is_sortable",
3700
14
                                   "Allow packet list to be sortable",
3701
14
                                   "To prevent sorting by mistake (which can take some time to calculate), it can be disabled",
3702
14
                                   &prefs.gui_packet_list_sortable);
3703
3704
14
    prefs_register_uint_preference(gui_module, "packet_list_cached_rows_max",
3705
14
                                   "Maximum cached rows",
3706
14
                                   "Maximum number of rows that can be sorted by columns that require dissection. Increasing this increases memory consumption by caching column text",
3707
14
                                   10,
3708
14
                                   &prefs.gui_packet_list_cached_rows_max);
3709
3710
14
    prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
3711
14
                                   "Show hidden interfaces",
3712
14
                                   "Show all interfaces, including interfaces marked as hidden",
3713
14
                                   &prefs.gui_interfaces_show_hidden);
3714
3715
14
    prefs_register_bool_preference(gui_module, "interfaces_remote_display",
3716
14
                                   "Show Remote interfaces",
3717
14
                                   "Show remote interfaces in the interface selection",
3718
14
                                   &prefs.gui_interfaces_remote_display);
3719
3720
14
    register_string_like_preference(gui_module, "interfaces_hidden_types", "Hide interface types in list",
3721
14
        "Hide the given interface types in the startup list.\n"
3722
14
        "A comma-separated string of interface type values (e.g. 5,9).\n"
3723
14
         "0 = Wired,\n"
3724
14
         "1 = AirPCAP,\n"
3725
14
         "2 = Pipe,\n"
3726
14
         "3 = STDIN,\n"
3727
14
         "4 = Bluetooth,\n"
3728
14
         "5 = Wireless,\n"
3729
14
         "6 = Dial-Up,\n"
3730
14
         "7 = USB,\n"
3731
14
         "8 = External Capture,\n"
3732
14
         "9 = Virtual",
3733
14
        &prefs.gui_interfaces_hide_types, PREF_STRING, NULL, true);
3734
3735
14
    prefs_register_bool_preference(gui_module, "io_graph_automatic_update",
3736
14
        "Enables automatic updates for IO Graph",
3737
14
        "Enables automatic updates for IO Graph",
3738
14
        &prefs.gui_io_graph_automatic_update);
3739
3740
14
    prefs_register_bool_preference(gui_module, "io_graph_enable_legend",
3741
14
        "Enables the legend of IO Graph",
3742
14
        "Enables the legend of IO Graph",
3743
14
        &prefs.gui_io_graph_enable_legend);
3744
3745
14
    prefs_register_bool_preference(gui_module, "plot_automatic_update",
3746
14
        "Enables automatic updates for Plot",
3747
14
        "Enables automatic updates for Plot",
3748
14
        &prefs.gui_plot_automatic_update);
3749
3750
14
    prefs_register_bool_preference(gui_module, "plot_enable_legend",
3751
14
        "Enables the legend of Plot",
3752
14
        "Enables the legend of Plot",
3753
14
        &prefs.gui_plot_enable_legend);
3754
3755
14
    prefs_register_bool_preference(gui_module, "show_byteview_in_dialog",
3756
14
        "Show the byte view in the packet details dialog",
3757
14
        "Show the byte view in the packet details dialog",
3758
14
        &prefs.gui_packet_details_show_byteview);
3759
3760
    /* Console
3761
     * These are preferences that can be read/written using the
3762
     * preference module API.  These preferences still use their own
3763
     * configuration screens for access, but this cuts down on the
3764
     * preference "string compare list" in set_pref()
3765
     */
3766
14
    console_module = prefs_register_module(NULL, "console", "Console",
3767
14
        "Console logging and debugging output", NULL, NULL, false);
3768
3769
14
    prefs_register_obsolete_preference(console_module, "log.level");
3770
3771
14
    prefs_register_bool_preference(console_module, "incomplete_dissectors_check_debug",
3772
14
                                   "Print debug line for incomplete dissectors",
3773
14
                                   "Look for dissectors that left some bytes undecoded (debug)",
3774
14
                                   &prefs.incomplete_dissectors_check_debug);
3775
3776
    /* Display filter Expressions
3777
     * This used to be an array of individual fields that has now been
3778
     * converted to a UAT.  Just make it part of the GUI category even
3779
     * though the name of the preference will never be seen in preference
3780
     * file
3781
     */
3782
14
    filter_expression_register_uat(gui_module);
3783
3784
    /* Capture
3785
     * These are preferences that can be read/written using the
3786
     * preference module API.  These preferences still use their own
3787
     * configuration screens for access, but this cuts down on the
3788
     * preference "string compare list" in set_pref()
3789
     */
3790
14
    capture_module = prefs_register_module(NULL, "capture", "Capture",
3791
14
        "Capture preferences", NULL, NULL, false);
3792
    /* Capture preferences don't affect dissection */
3793
14
    prefs_set_module_effect_flags(capture_module, PREF_EFFECT_CAPTURE);
3794
3795
14
    register_string_like_preference(capture_module, "device", "Default capture device",
3796
14
        "Default capture device",
3797
14
        &prefs.capture_device, PREF_STRING, NULL, false);
3798
3799
14
    register_string_like_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
3800
14
        "Interface link-layer header types (Ex: en0(1),en1(143),...)",
3801
14
        &prefs.capture_devices_linktypes, PREF_STRING, NULL, false);
3802
3803
14
    register_string_like_preference(capture_module, "devices_descr", "Interface descriptions",
3804
14
        "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
3805
14
        &prefs.capture_devices_descr, PREF_STRING, NULL, false);
3806
3807
14
    register_string_like_preference(capture_module, "devices_hide", "Hide interface",
3808
14
        "Hide interface? (Ex: eth0,eth3,...)",
3809
14
        &prefs.capture_devices_hide, PREF_STRING, NULL, false);
3810
3811
14
    register_string_like_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
3812
14
        "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
3813
14
        &prefs.capture_devices_monitor_mode, PREF_STRING, NULL, false);
3814
3815
14
    register_string_like_preference(capture_module, "devices_buffersize", "Interface buffer size",
3816
14
        "Interface buffer size (Ex: en0(1),en1(143),...)",
3817
14
        &prefs.capture_devices_buffersize, PREF_STRING, NULL, false);
3818
3819
14
    register_string_like_preference(capture_module, "devices_snaplen", "Interface snap length",
3820
14
        "Interface snap length (Ex: en0(65535),en1(1430),...)",
3821
14
        &prefs.capture_devices_snaplen, PREF_STRING, NULL, false);
3822
3823
14
    register_string_like_preference(capture_module, "devices_pmode", "Interface promiscuous mode",
3824
14
        "Interface promiscuous mode (Ex: en0(0),en1(1),...)",
3825
14
        &prefs.capture_devices_pmode, PREF_STRING, NULL, false);
3826
3827
14
    prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
3828
14
        "Capture in promiscuous mode?", &prefs.capture_prom_mode);
3829
3830
14
    prefs_register_bool_preference(capture_module, "monitor_mode", "Capture in monitor mode on 802.11 devices",
3831
14
        "Capture in monitor mode on all 802.11 devices that support it?", &prefs.capture_monitor_mode);
3832
3833
14
    register_string_like_preference(capture_module, "devices_filter", "Interface capture filter",
3834
14
        "Interface capture filter (Ex: en0(tcp),en1(udp),...)",
3835
14
        &prefs.capture_devices_filter, PREF_STRING, NULL, false);
3836
3837
14
    prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in pcapng format",
3838
14
        "Capture in pcapng format?", &prefs.capture_pcap_ng);
3839
3840
14
    prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
3841
14
        "Update packet list in real time during capture?", &prefs.capture_real_time);
3842
3843
14
    prefs_register_uint_preference(capture_module, "update_interval",
3844
14
                                   "Capture update interval",
3845
14
                                   "Capture update interval in ms",
3846
14
                                   10,
3847
14
                                   &prefs.capture_update_interval);
3848
3849
14
    prefs_register_bool_preference(capture_module, "no_interface_load", "Don't load interfaces on startup",
3850
14
        "Don't automatically load capture interfaces on startup", &prefs.capture_no_interface_load);
3851
3852
14
    prefs_register_bool_preference(capture_module, "no_extcap", "Disable external capture interfaces",
3853
14
        "Disable external capture modules (extcap)", &prefs.capture_no_extcap);
3854
3855
14
    prefs_register_obsolete_preference(capture_module, "auto_scroll");
3856
3857
14
    prefs_register_bool_preference(capture_module, "show_info", "Show capture information dialog while capturing",
3858
14
        "Show capture information dialog while capturing?", &prefs.capture_show_info);
3859
3860
14
    prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
3861
3862
14
    custom_cbs.free_cb = capture_column_free_cb;
3863
14
    custom_cbs.reset_cb = capture_column_reset_cb;
3864
14
    custom_cbs.set_cb = capture_column_set_cb;
3865
14
    custom_cbs.type_name_cb = capture_column_type_name_cb;
3866
14
    custom_cbs.type_description_cb = capture_column_type_description_cb;
3867
14
    custom_cbs.is_default_cb = capture_column_is_default_cb;
3868
14
    custom_cbs.to_str_cb = capture_column_to_str_cb;
3869
14
    prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
3870
14
        "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
3871
3872
    /* Name Resolution */
3873
14
    nameres_module = prefs_register_module(NULL, "nameres", "Name Resolution",
3874
14
        "Name Resolution", "ChCustPreferencesSection.html#ChCustPrefsNameSection", addr_resolve_pref_apply, true);
3875
14
    addr_resolve_pref_init(nameres_module);
3876
14
    oid_pref_init(nameres_module);
3877
14
    maxmind_db_pref_init(nameres_module);
3878
3879
    /* Printing
3880
     * None of these have any effect; we keep them as obsolete preferences
3881
     * in order to avoid errors when reading older preference files.
3882
     */
3883
14
    printing = prefs_register_module(NULL, "print", "Printing",
3884
14
        "Printing", NULL, NULL, false);
3885
14
    prefs_register_obsolete_preference(printing, "format");
3886
14
    prefs_register_obsolete_preference(printing, "command");
3887
14
    prefs_register_obsolete_preference(printing, "file");
3888
3889
    /* Codecs */
3890
14
    codecs_module = prefs_register_module(NULL, "codecs", "Codecs",
3891
14
        "Codecs", NULL, NULL, true);
3892
3893
    /* Statistics */
3894
14
    stats_module = prefs_register_module(NULL, "statistics", "Statistics",
3895
14
        "Statistics", "ChCustPreferencesSection.html#_statistics", &stats_callback, true);
3896
3897
14
    prefs_register_uint_preference(stats_module, "update_interval",
3898
14
                                   "Tap update interval in ms",
3899
14
                                   "Determines time between tap updates",
3900
14
                                   10,
3901
14
                                   &prefs.tap_update_interval);
3902
3903
14
    prefs_register_uint_preference(stats_module, "flow_graph_max_export_items",
3904
14
                                   "Maximum Flow Graph items to export as image",
3905
14
                                   "The maximum number of Flow Graph items (frames) "
3906
14
                                   "to include when exporting the graph as an image. "
3907
14
                                   "Note that some formats (e.g., JPEG) have inherent "
3908
14
                                   "pixel limits and image viewers might be unable to "
3909
14
                                   "handle very large images.",
3910
14
                                   10,
3911
14
                                   &prefs.flow_graph_max_export_items);
3912
3913
14
    prefs_register_bool_preference(stats_module, "st_enable_burstinfo",
3914
14
            "Enable the calculation of burst information",
3915
14
            "If enabled burst rates will be calculated for statistics that use the stats_tree system. "
3916
14
            "Burst rates are calculated over a much shorter time interval than the rate column.",
3917
14
            &prefs.st_enable_burstinfo);
3918
3919
14
    prefs_register_bool_preference(stats_module, "st_burst_showcount",
3920
14
            "Show burst count for item rather than rate",
3921
14
            "If selected the stats_tree statistics nodes will show the count of events "
3922
14
            "within the burst window instead of a burst rate. Burst rate is calculated "
3923
14
            "as number of events within burst window divided by the burst windown length.",
3924
14
            &prefs.st_burst_showcount);
3925
3926
14
    prefs_register_uint_preference(stats_module, "st_burst_resolution",
3927
14
            "Burst rate resolution (ms)",
3928
14
            "Sets the duration of the time interval into which events are grouped when calculating "
3929
14
            "the burst rate. Higher resolution (smaller number) increases processing overhead.",
3930
14
            10,&prefs.st_burst_resolution);
3931
3932
14
    prefs_register_uint_preference(stats_module, "st_burst_windowlen",
3933
14
            "Burst rate window size (ms)",
3934
14
            "Sets the duration of the sliding window during which the burst rate is "
3935
14
            "measured. Longer window relative to burst rate resolution increases "
3936
14
            "processing overhead. Will be truncated to a multiple of burst resolution.",
3937
14
            10,&prefs.st_burst_windowlen);
3938
3939
14
    prefs_register_enum_preference(stats_module, "st_sort_defcolflag",
3940
14
            "Default sort column for stats_tree stats",
3941
14
            "Sets the default column by which stats based on the stats_tree "
3942
14
            "system is sorted.",
3943
14
            &prefs.st_sort_defcolflag, st_sort_col_vals, false);
3944
3945
14
    prefs_register_bool_preference(stats_module, "st_sort_defdescending",
3946
14
            "Default stats_tree sort order is descending",
3947
14
            "When selected, statistics based on the stats_tree system will by default "
3948
14
            "be sorted in descending order.",
3949
14
            &prefs.st_sort_defdescending);
3950
3951
14
    prefs_register_bool_preference(stats_module, "st_sort_casesensitve",
3952
14
            "Case sensitive sort of stats_tree item names",
3953
14
            "When selected, the item/node names of statistics based on the stats_tree "
3954
14
            "system will be sorted taking case into account. Else the case of the name "
3955
14
            "will be ignored.",
3956
14
            &prefs.st_sort_casesensitve);
3957
3958
14
    prefs_register_bool_preference(stats_module, "st_sort_rng_nameonly",
3959
14
            "Always sort 'range' nodes by name",
3960
14
            "When selected, the stats_tree nodes representing a range of values "
3961
14
            "(0-49, 50-100, etc.) will always be sorted by name (the range of the "
3962
14
            "node). Else range nodes are sorted by the same column as the rest of "
3963
14
            " the tree.",
3964
14
            &prefs.st_sort_rng_nameonly);
3965
3966
14
    prefs_register_bool_preference(stats_module, "st_sort_rng_fixorder",
3967
14
            "Always sort 'range' nodes in ascending order",
3968
14
            "When selected, the stats_tree nodes representing a range of values "
3969
14
            "(0-49, 50-100, etc.) will always be sorted ascending; else it follows "
3970
14
            "the sort direction of the tree. Only effective if \"Always sort "
3971
14
            "'range' nodes by name\" is also selected.",
3972
14
            &prefs.st_sort_rng_fixorder);
3973
3974
14
    prefs_register_bool_preference(stats_module, "st_sort_showfullname",
3975
14
            "Display the full stats_tree plug-in name",
3976
14
            "When selected, the full name (including menu path) of the stats_tree "
3977
14
            "plug-in is show in windows. If cleared the plug-in name is shown "
3978
14
            "without menu path (only the part of the name after last '/' character.)",
3979
14
            &prefs.st_sort_showfullname);
3980
3981
14
    prefs_register_enum_preference(stats_module, "output_format",
3982
14
            "Default output format",
3983
14
            "Sets the default output format for statistical data. Only supported "
3984
14
            "by taps using the stats_tree system currently; other taps may honor "
3985
14
            "this preference in the future. ",
3986
14
            &prefs.st_format, st_format_vals, false);
3987
3988
14
    module_t *conv_module;
3989
    // avoid using prefs_register_stat to prevent lint complaint about recursion
3990
14
    conv_module = prefs_register_module(stats_module, "conv", "Conversations",
3991
14
            "Conversations & Endpoints", NULL, NULL, true);
3992
14
    prefs_register_bool_preference(conv_module, "machine_readable",
3993
14
            "Display exact (machine-readable) byte counts",
3994
14
            "When enabled, exact machine-readable byte counts are displayed. "
3995
14
            "When disabled, human readable numbers with SI prefixes are displayed.",
3996
14
            &prefs.conv_machine_readable);
3997
3998
    /* Protocols */
3999
14
    protocols_module = prefs_register_module(NULL, "protocols", "Protocols",
4000
14
                                             "Protocols", "ChCustPreferencesSection.html#ChCustPrefsProtocolsSection", NULL, true);
4001
4002
14
    prefs_register_bool_preference(protocols_module, "display_hidden_proto_items",
4003
14
                                   "Display hidden protocol items",
4004
14
                                   "Display all hidden protocol items in the packet list.",
4005
14
                                   &prefs.display_hidden_proto_items);
4006
4007
14
    prefs_register_bool_preference(protocols_module, "display_byte_fields_with_spaces",
4008
14
                                   "Display byte fields with a space character between bytes",
4009
14
                                   "Display all byte fields with a space character between each byte in the packet list.",
4010
14
                                   &prefs.display_byte_fields_with_spaces);
4011
4012
    /*
4013
     * Note the -t /  option only affects the display of the packet timestamp
4014
     * in the default time column; this is for all other absolute times.
4015
     */
4016
14
    prefs_register_enum_preference(protocols_module, "display_abs_time_ascii",
4017
14
                                   "Format absolute times like asctime",
4018
14
                                   "When to format absolute times similar to asctime instead of ISO 8601, for backwards compatibility with older Wireshark.",
4019
14
                                   (int*)&prefs.display_abs_time_ascii, abs_time_format_options, false);
4020
4021
14
    prefs_register_bool_preference(protocols_module, "enable_incomplete_dissectors_check",
4022
14
                                   "Look for incomplete dissectors",
4023
14
                                   "Look for dissectors that left some bytes undecoded.",
4024
14
                                   &prefs.enable_incomplete_dissectors_check);
4025
4026
14
    prefs_register_bool_preference(protocols_module, "strict_conversation_tracking_heuristics",
4027
14
                                   "Enable stricter conversation tracking heuristics",
4028
14
                                   "Protocols may use things like VLAN ID or interface ID to narrow the potential for duplicate conversations. "
4029
14
                                   "Currently ICMP and ICMPv6 use this preference to add VLAN ID to conversation tracking, and IPv4 uses this preference to take VLAN ID into account during reassembly",
4030
14
                                   &prefs.strict_conversation_tracking_heuristics);
4031
4032
14
    prefs_register_bool_preference(protocols_module, "ignore_dup_frames",
4033
14
                                   "Ignore duplicate frames",
4034
14
                                   "Ignore frames that are exact duplicates of any previous frame.",
4035
14
                                   &prefs.ignore_dup_frames);
4036
4037
14
    prefs_register_enum_preference(protocols_module, "conversation_deinterlacing_key",
4038
14
                                   "Deinterlacing conversations key",
4039
14
                                   "Separate into different conversations frames that look like duplicates but have different Interface, MAC, or VLAN field values.",
4040
14
                                   (int *)&prefs.conversation_deinterlacing_key, conv_deint_options, false);
4041
4042
14
    prefs_register_uint_preference(protocols_module, "ignore_dup_frames_cache_entries",
4043
14
            "The max number of hashes to keep in memory for determining duplicates frames",
4044
14
            "If \"Ignore duplicate frames\" is set, this setting sets the maximum number "
4045
14
            "of cache entries to maintain. A 0 means no limit.",
4046
14
            10, &prefs.ignore_dup_frames_cache_entries);
4047
4048
4049
    /* Obsolete preferences
4050
     * These "modules" were reorganized/renamed to correspond to their GUI
4051
     * configuration screen within the preferences dialog
4052
     */
4053
4054
    /* taps is now part of the stats module */
4055
14
    prefs_register_module(NULL, "taps", "TAPS", "TAPS", NULL, NULL, false);
4056
    /* packet_list is now part of the protocol (parent) module */
4057
14
    prefs_register_module(NULL, "packet_list", "PACKET_LIST", "PACKET_LIST", NULL, NULL, false);
4058
    /* stream is now part of the gui module */
4059
14
    prefs_register_module(NULL, "stream", "STREAM", "STREAM", NULL, NULL, false);
4060
4061
14
}
4062
4063
/* Parse through a list of comma-separated, possibly quoted strings.
4064
   Return a list of the string data. */
4065
GList *
4066
prefs_get_string_list(const char *str)
4067
0
{
4068
0
    enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
4069
4070
0
    int       state = PRE_STRING, i = 0;
4071
0
    bool      backslash = false;
4072
0
    unsigned char    cur_c;
4073
0
    const size_t default_size = 64;
4074
0
    GString  *slstr = NULL;
4075
0
    GList    *sl = NULL;
4076
4077
    /* Allocate a buffer for the first string.   */
4078
0
    slstr = g_string_sized_new(default_size);
4079
4080
0
    for (;;) {
4081
0
        cur_c = str[i];
4082
0
        if (cur_c == '\0') {
4083
            /* It's the end of the input, so it's the end of the string we
4084
               were working on, and there's no more input. */
4085
0
            if (state == IN_QUOT || backslash) {
4086
                /* We were in the middle of a quoted string or backslash escape,
4087
                   and ran out of characters; that's an error.  */
4088
0
                g_string_free(slstr, TRUE);
4089
0
                prefs_clear_string_list(sl);
4090
0
                return NULL;
4091
0
            }
4092
0
            if (slstr->len > 0)
4093
0
                sl = g_list_append(sl, g_string_free(slstr, FALSE));
4094
0
            else
4095
0
                g_string_free(slstr, TRUE);
4096
0
            break;
4097
0
        }
4098
0
        if (cur_c == '"' && !backslash) {
4099
0
            switch (state) {
4100
0
            case PRE_STRING:
4101
                /* We hadn't yet started processing a string; this starts the
4102
                   string, and we're now quoting.  */
4103
0
                state = IN_QUOT;
4104
0
                break;
4105
0
            case IN_QUOT:
4106
                /* We're in the middle of a quoted string, and we saw a quotation
4107
                   mark; we're no longer quoting.   */
4108
0
                state = NOT_IN_QUOT;
4109
0
                break;
4110
0
            case NOT_IN_QUOT:
4111
                /* We're working on a string, but haven't seen a quote; we're
4112
                   now quoting.  */
4113
0
                state = IN_QUOT;
4114
0
                break;
4115
0
            default:
4116
0
                break;
4117
0
            }
4118
0
        } else if (cur_c == '\\' && !backslash) {
4119
            /* We saw a backslash, and the previous character wasn't a
4120
               backslash; escape the next character.
4121
4122
               This also means we've started a new string. */
4123
0
            backslash = true;
4124
0
            if (state == PRE_STRING)
4125
0
                state = NOT_IN_QUOT;
4126
0
        } else if (cur_c == ',' && state != IN_QUOT && !backslash) {
4127
            /* We saw a comma, and we're not in the middle of a quoted string
4128
               and it wasn't preceded by a backslash; it's the end of
4129
               the string we were working on...  */
4130
0
            if (slstr->len > 0) {
4131
0
                sl = g_list_append(sl, g_string_free(slstr, FALSE));
4132
0
                slstr = g_string_sized_new(default_size);
4133
0
            }
4134
4135
            /* ...and the beginning of a new string.  */
4136
0
            state = PRE_STRING;
4137
0
        } else if (!g_ascii_isspace(cur_c) || state != PRE_STRING) {
4138
            /* Either this isn't a white-space character, or we've started a
4139
               string (i.e., already seen a non-white-space character for that
4140
               string and put it into the string).
4141
4142
               The character is to be put into the string; do so.  */
4143
0
            g_string_append_c(slstr, cur_c);
4144
4145
            /* If it was backslash-escaped, we're done with the backslash escape.  */
4146
0
            backslash = false;
4147
0
        }
4148
0
        i++;
4149
0
    }
4150
0
    return(sl);
4151
0
}
4152
4153
char *join_string_list(GList *sl)
4154
0
{
4155
0
    GString      *joined_str = g_string_new("");
4156
0
    GList        *cur, *first;
4157
0
    char         *str;
4158
0
    unsigned      item_count = 0;
4159
4160
0
    cur = first = g_list_first(sl);
4161
0
    while (cur) {
4162
0
        item_count++;
4163
0
        str = (char *)cur->data;
4164
4165
0
        if (cur != first)
4166
0
            g_string_append_c(joined_str, ',');
4167
4168
0
        if (item_count % 2) {
4169
            /* Wrap the line.  */
4170
0
            g_string_append(joined_str, "\n\t");
4171
0
        } else
4172
0
            g_string_append_c(joined_str, ' ');
4173
4174
0
        g_string_append_c(joined_str, '"');
4175
0
        while (*str) {
4176
0
            gunichar uc = g_utf8_get_char (str);
4177
4178
0
            if (uc == '"' || uc == '\\')
4179
0
                g_string_append_c(joined_str, '\\');
4180
4181
0
            if (g_unichar_isprint(uc))
4182
0
                g_string_append_unichar (joined_str, uc);
4183
4184
0
            str = g_utf8_next_char (str);
4185
0
        }
4186
4187
0
        g_string_append_c(joined_str, '"');
4188
4189
0
        cur = cur->next;
4190
0
    }
4191
0
    return g_string_free(joined_str, FALSE);
4192
0
}
4193
4194
void
4195
prefs_clear_string_list(GList *sl)
4196
0
{
4197
0
    g_list_free_full(sl, g_free);
4198
0
}
4199
4200
/*
4201
 * Takes a string, a pointer to an array of "enum_val_t"s, and a default int
4202
 * value.
4203
 * The array must be terminated by an entry with a null "name" string.
4204
 *
4205
 * If the string matches a "name" string in an entry, the value from that
4206
 * entry is returned.
4207
 *
4208
 * Otherwise, if a string matches a "description" string in an entry, the
4209
 * value from that entry is returned; we do that for backwards compatibility,
4210
 * as we used to have only a "name" string that was used both for command-line
4211
 * and configuration-file values and in the GUI (which meant either that
4212
 * the GUI had what might be somewhat cryptic values to select from or that
4213
 * the "-o" flag took long strings, often with spaces in them).
4214
 *
4215
 * Otherwise, the default value that was passed as the third argument is
4216
 * returned.
4217
 */
4218
static int
4219
find_val_for_string(const char *needle, const enum_val_t *haystack,
4220
                    int default_value)
4221
0
{
4222
0
    int i;
4223
4224
0
    for (i = 0; haystack[i].name != NULL; i++) {
4225
0
        if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
4226
0
            return haystack[i].value;
4227
0
        }
4228
0
    }
4229
0
    for (i = 0; haystack[i].name != NULL; i++) {
4230
0
        if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
4231
0
            return haystack[i].value;
4232
0
        }
4233
0
    }
4234
0
    return default_value;
4235
0
}
4236
4237
/* Preferences file format:
4238
 * - Configuration directives start at the beginning of the line, and
4239
 *   are terminated with a colon.
4240
 * - Directives can be continued on the next line by preceding them with
4241
 *   whitespace.
4242
 *
4243
 * Example:
4244
4245
# This is a comment line
4246
print.command: lpr
4247
print.file: /a/very/long/path/
4248
            to/wireshark-out.ps
4249
 *
4250
 */
4251
4252
/* Initialize non-dissector preferences to wired-in default values Called
4253
 * at program startup and any time the profile changes. (The dissector
4254
 * preferences are assumed to be set to those values by the dissectors.)
4255
 * They may be overridden by the global preferences file or the user's
4256
 * preferences file.
4257
 */
4258
static void
4259
init_prefs(void)
4260
14
{
4261
14
    if (prefs_initialized)
4262
0
        return;
4263
4264
14
    uat_load_all();
4265
4266
    /*
4267
     * Ensure the "global" preferences have been initialized so the
4268
     * preference API has the proper default values to work from
4269
     */
4270
14
    pre_init_prefs();
4271
4272
14
    prefs_register_modules();
4273
4274
14
    prefs_initialized = true;
4275
14
}
4276
4277
/*
4278
 * Initialize non-dissector preferences used by the "register preference" API
4279
 * to default values so the default values can be used when registered.
4280
 *
4281
 * String, filename, and directory preferences will be g_freed so they must
4282
 * be g_mallocated.
4283
 */
4284
static void
4285
pre_init_prefs(void)
4286
28
{
4287
28
    int         i;
4288
28
    char        *col_name;
4289
28
    fmt_data    *cfmt;
4290
28
    static const char *col_fmt_packets[] = {
4291
28
        "No.",      "%m", "Time",        "%t",
4292
28
        "Source",   "%s", "Destination", "%d",
4293
28
        "Protocol", "%p", "Length",      "%L",
4294
28
        "Info",     "%i" };
4295
28
    static const char **col_fmt = col_fmt_packets;
4296
28
    int num_cols = 7;
4297
4298
28
    if (application_flavor_is_stratoshark()) {
4299
0
        static const char *col_fmt_logs[] = {
4300
0
            "No.",              "%m",
4301
0
            "Time",             "%t",
4302
0
            "Event name",       "%Cus:sysdig.event_name:0:R",
4303
0
            "Dir",              "%Cus:evt.dir:0:R",
4304
0
            "Proc Name",        "%Cus:proc.name:0:R",
4305
0
            "PID",              "%Cus:proc.pid:0:R",
4306
0
            "TID",              "%Cus:thread.tid:0:R",
4307
0
            "FD",               "%Cus:fd.num:0:R",
4308
0
            "FD Name",          "%Cus:fd.name:0:R",
4309
0
            "Container Name",   "%Cus:container.name:0:R",
4310
0
            "Arguments",        "%Cus:evt.args:0:R",
4311
0
            "Info",             "%i"
4312
0
            };
4313
0
        col_fmt = col_fmt_logs;
4314
0
        num_cols = 12;
4315
0
    }
4316
4317
28
    prefs.restore_filter_after_following_stream = false;
4318
28
    prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
4319
    /* We try to find the best font in the Qt code */
4320
28
    g_free(prefs.gui_font_name);
4321
28
    prefs.gui_font_name              = g_strdup("");
4322
28
    prefs.gui_active_fg.red          =         0;
4323
28
    prefs.gui_active_fg.green        =         0;
4324
28
    prefs.gui_active_fg.blue         =         0;
4325
28
    prefs.gui_active_bg.red          =     52223;
4326
28
    prefs.gui_active_bg.green        =     59647;
4327
28
    prefs.gui_active_bg.blue         =     65535;
4328
28
    prefs.gui_active_style           = COLOR_STYLE_DEFAULT;
4329
28
    prefs.gui_inactive_fg.red        =         0;
4330
28
    prefs.gui_inactive_fg.green      =         0;
4331
28
    prefs.gui_inactive_fg.blue       =         0;
4332
28
    prefs.gui_inactive_bg.red        =     61439;
4333
28
    prefs.gui_inactive_bg.green      =     61439;
4334
28
    prefs.gui_inactive_bg.blue       =     61439;
4335
28
    prefs.gui_inactive_style         = COLOR_STYLE_DEFAULT;
4336
28
    prefs.gui_marked_fg.red          =     65535;
4337
28
    prefs.gui_marked_fg.green        =     65535;
4338
28
    prefs.gui_marked_fg.blue         =     65535;
4339
28
    prefs.gui_marked_bg.red          =         0;
4340
28
    prefs.gui_marked_bg.green        =      8224;
4341
28
    prefs.gui_marked_bg.blue         =     10794;
4342
28
    prefs.gui_ignored_fg.red         =     32767;
4343
28
    prefs.gui_ignored_fg.green       =     32767;
4344
28
    prefs.gui_ignored_fg.blue        =     32767;
4345
28
    prefs.gui_ignored_bg.red         =     65535;
4346
28
    prefs.gui_ignored_bg.green       =     65535;
4347
28
    prefs.gui_ignored_bg.blue        =     65535;
4348
28
    g_free(prefs.gui_colorized_fg);
4349
28
    prefs.gui_colorized_fg           = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
4350
28
    g_free(prefs.gui_colorized_bg);
4351
28
    prefs.gui_colorized_bg           = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
4352
28
    prefs.st_client_fg.red           = 32767;
4353
28
    prefs.st_client_fg.green         =     0;
4354
28
    prefs.st_client_fg.blue          =     0;
4355
28
    prefs.st_client_bg.red           = 64507;
4356
28
    prefs.st_client_bg.green         = 60909;
4357
28
    prefs.st_client_bg.blue          = 60909;
4358
28
    prefs.st_server_fg.red           =     0;
4359
28
    prefs.st_server_fg.green         =     0;
4360
28
    prefs.st_server_fg.blue          = 32767;
4361
28
    prefs.st_server_bg.red           = 60909;
4362
28
    prefs.st_server_bg.green         = 60909;
4363
28
    prefs.st_server_bg.blue          = 64507;
4364
4365
28
    if (gui_theme_is_dark) {
4366
        // Green, red and yellow with HSV V = 84
4367
0
        prefs.gui_filter_valid_bg.red         = 0x0000; /* dark green */
4368
0
        prefs.gui_filter_valid_bg.green       = 0x66ff;
4369
0
        prefs.gui_filter_valid_bg.blue        = 0x0000;
4370
0
        prefs.gui_filter_valid_fg.red         = 0xFFFF;
4371
0
        prefs.gui_filter_valid_fg.green       = 0xFFFF;
4372
0
        prefs.gui_filter_valid_fg.blue        = 0xFFFF;
4373
0
        prefs.gui_filter_invalid_bg.red       = 0x66FF; /* dark red */
4374
0
        prefs.gui_filter_invalid_bg.green     = 0x0000;
4375
0
        prefs.gui_filter_invalid_bg.blue      = 0x0000;
4376
0
        prefs.gui_filter_invalid_fg.red       = 0xFFFF;
4377
0
        prefs.gui_filter_invalid_fg.green     = 0xFFFF;
4378
0
        prefs.gui_filter_invalid_fg.blue      = 0xFFFF;
4379
0
        prefs.gui_filter_deprecated_bg.red    = 0x66FF; /* dark yellow / olive */
4380
0
        prefs.gui_filter_deprecated_bg.green  = 0x66FF;
4381
0
        prefs.gui_filter_deprecated_bg.blue   = 0x0000;
4382
0
        prefs.gui_filter_deprecated_fg.red    = 0xFFFF;
4383
0
        prefs.gui_filter_deprecated_fg.green  = 0xFFFF;
4384
0
        prefs.gui_filter_deprecated_fg.blue   = 0xFFFF;
4385
28
    } else {
4386
        // Green, red and yellow with HSV V = 20
4387
28
        prefs.gui_filter_valid_bg.red         = 0xAFFF; /* light green */
4388
28
        prefs.gui_filter_valid_bg.green       = 0xFFFF;
4389
28
        prefs.gui_filter_valid_bg.blue        = 0xAFFF;
4390
28
        prefs.gui_filter_valid_fg.red         = 0x0000;
4391
28
        prefs.gui_filter_valid_fg.green       = 0x0000;
4392
28
        prefs.gui_filter_valid_fg.blue        = 0x0000;
4393
28
        prefs.gui_filter_invalid_bg.red       = 0xFFFF; /* light red */
4394
28
        prefs.gui_filter_invalid_bg.green     = 0xAFFF;
4395
28
        prefs.gui_filter_invalid_bg.blue      = 0xAFFF;
4396
28
        prefs.gui_filter_invalid_fg.red       = 0x0000;
4397
28
        prefs.gui_filter_invalid_fg.green     = 0x0000;
4398
28
        prefs.gui_filter_invalid_fg.blue      = 0x0000;
4399
28
        prefs.gui_filter_deprecated_bg.red    = 0xFFFF; /* light yellow */
4400
28
        prefs.gui_filter_deprecated_bg.green  = 0xFFFF;
4401
28
        prefs.gui_filter_deprecated_bg.blue   = 0xAFFF;
4402
28
        prefs.gui_filter_deprecated_fg.red    = 0x0000;
4403
28
        prefs.gui_filter_deprecated_fg.green  = 0x0000;
4404
28
        prefs.gui_filter_deprecated_fg.blue   = 0x0000;
4405
28
    }
4406
4407
28
    prefs.gui_geometry_save_position = true;
4408
28
    prefs.gui_geometry_save_size     = true;
4409
28
    prefs.gui_geometry_save_maximized= true;
4410
28
    prefs.gui_fileopen_style         = FO_STYLE_LAST_OPENED;
4411
28
    prefs.gui_recent_df_entries_max  = 10;
4412
28
    prefs.gui_recent_files_count_max = 10;
4413
28
    g_free(prefs.gui_fileopen_dir);
4414
28
    prefs.gui_fileopen_dir           = g_strdup(get_persdatafile_dir());
4415
28
    prefs.gui_fileopen_preview       = 3;
4416
28
    g_free(prefs.gui_tlskeylog_command);
4417
28
    prefs.gui_tlskeylog_command      = g_strdup("");
4418
28
    prefs.gui_ask_unsaved            = true;
4419
28
    prefs.gui_autocomplete_filter    = true;
4420
28
    prefs.gui_find_wrap              = true;
4421
28
    prefs.gui_update_enabled         = true;
4422
28
    prefs.gui_update_channel         = UPDATE_CHANNEL_STABLE;
4423
28
    prefs.gui_update_interval        = 60*60*24; /* Seconds */
4424
28
    prefs.gui_debounce_timer         = 400; /* milliseconds */
4425
28
    g_free(prefs.gui_window_title);
4426
28
    prefs.gui_window_title           = g_strdup("");
4427
28
    g_free(prefs.gui_prepend_window_title);
4428
28
    prefs.gui_prepend_window_title   = g_strdup("");
4429
28
    g_free(prefs.gui_start_title);
4430
28
    prefs.gui_start_title            = g_strdup("The World's Most Popular Network Protocol Analyzer");
4431
28
    prefs.gui_version_placement      = version_both;
4432
28
    prefs.gui_welcome_page_show_recent = true;
4433
28
    prefs.gui_layout_type            = layout_type_2;
4434
28
    prefs.gui_layout_content_1       = layout_pane_content_plist;
4435
28
    prefs.gui_layout_content_2       = layout_pane_content_pdetails;
4436
28
    prefs.gui_layout_content_3       = layout_pane_content_pbytes;
4437
28
    prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
4438
28
    prefs.gui_packet_list_copy_format_options_for_keyboard_shortcut = COPY_FORMAT_TEXT;
4439
28
    prefs.gui_packet_list_copy_text_with_aligned_columns = false;
4440
28
    prefs.gui_packet_list_show_related = true;
4441
28
    prefs.gui_packet_list_show_minimap = true;
4442
28
    prefs.gui_packet_list_sortable     = true;
4443
28
    prefs.gui_packet_list_cached_rows_max = 10000;
4444
28
    g_free (prefs.gui_interfaces_hide_types);
4445
28
    prefs.gui_interfaces_hide_types = g_strdup("");
4446
28
    prefs.gui_interfaces_show_hidden = false;
4447
28
    prefs.gui_interfaces_remote_display = true;
4448
28
    prefs.gui_packet_list_separator = false;
4449
28
    prefs.gui_packet_header_column_definition = true;
4450
28
    prefs.gui_packet_list_hover_style = true;
4451
28
    prefs.gui_show_selected_packet = false;
4452
28
    prefs.gui_show_file_load_time = false;
4453
28
    prefs.gui_max_export_objects     = 1000;
4454
28
    prefs.gui_max_tree_items = 1 * 1000 * 1000;
4455
28
    prefs.gui_max_tree_depth = 5 * 100;
4456
28
    prefs.gui_decimal_places1 = DEF_GUI_DECIMAL_PLACES1;
4457
28
    prefs.gui_decimal_places2 = DEF_GUI_DECIMAL_PLACES2;
4458
28
    prefs.gui_decimal_places3 = DEF_GUI_DECIMAL_PLACES3;
4459
4460
28
    if (prefs.col_list) {
4461
14
        free_col_info(prefs.col_list);
4462
14
        prefs.col_list = NULL;
4463
14
    }
4464
224
    for (i = 0; i < num_cols; i++) {
4465
196
        cfmt = g_new0(fmt_data,1);
4466
196
        cfmt->title = g_strdup(col_fmt[i * 2]);
4467
196
        cfmt->visible = true;
4468
196
        cfmt->display = COLUMN_DISPLAY_STRINGS;
4469
196
        parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
4470
196
        prefs.col_list = g_list_append(prefs.col_list, cfmt);
4471
196
    }
4472
28
    prefs.num_cols  = num_cols;
4473
4474
/* set the default values for the capture dialog box */
4475
28
    prefs.capture_prom_mode             = true;
4476
28
    prefs.capture_monitor_mode          = false;
4477
28
    prefs.capture_pcap_ng               = true;
4478
28
    prefs.capture_real_time             = true;
4479
28
    prefs.capture_update_interval       = DEFAULT_UPDATE_INTERVAL;
4480
28
    prefs.capture_no_extcap             = false;
4481
28
    prefs.capture_show_info             = false;
4482
4483
28
    if (!prefs.capture_columns) {
4484
        /* First time through */
4485
112
        for (i = 0; i < num_capture_cols; i++) {
4486
98
            col_name = g_strdup(capture_cols[i]);
4487
98
            prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
4488
98
        }
4489
14
    }
4490
4491
/* set the default values for the tap/statistics dialog box */
4492
28
    prefs.tap_update_interval    = TAP_UPDATE_DEFAULT_INTERVAL;
4493
28
    prefs.flow_graph_max_export_items = 1000;
4494
28
    prefs.st_enable_burstinfo = true;
4495
28
    prefs.st_burst_showcount = false;
4496
28
    prefs.st_burst_resolution = ST_DEF_BURSTRES;
4497
28
    prefs.st_burst_windowlen = ST_DEF_BURSTLEN;
4498
28
    prefs.st_sort_casesensitve = true;
4499
28
    prefs.st_sort_rng_fixorder = true;
4500
28
    prefs.st_sort_rng_nameonly = true;
4501
28
    prefs.st_sort_defcolflag = ST_SORT_COL_COUNT;
4502
28
    prefs.st_sort_defdescending = true;
4503
28
    prefs.st_sort_showfullname = false;
4504
28
    prefs.conv_machine_readable = false;
4505
4506
    /* protocols */
4507
28
    prefs.display_hidden_proto_items = false;
4508
28
    prefs.display_byte_fields_with_spaces = false;
4509
28
    prefs.display_abs_time_ascii = ABS_TIME_ASCII_TREE;
4510
28
    prefs.ignore_dup_frames = false;
4511
28
    prefs.ignore_dup_frames_cache_entries = 10000;
4512
4513
    /* set the default values for the io graph dialog */
4514
28
    prefs.gui_io_graph_automatic_update = true;
4515
28
    prefs.gui_io_graph_enable_legend = true;
4516
4517
    /* set the default values for the plot dialog */
4518
28
    prefs.gui_plot_automatic_update = true;
4519
28
    prefs.gui_plot_enable_legend = true;
4520
4521
    /* set the default values for the packet dialog */
4522
28
    prefs.gui_packet_dialog_layout   = layout_vertical;
4523
28
    prefs.gui_packet_details_show_byteview = true;
4524
28
}
4525
4526
/*
4527
 * Reset a single dissector preference.
4528
 */
4529
void
4530
reset_pref(pref_t *pref)
4531
0
{
4532
0
    if (!pref) return;
4533
4534
    /*
4535
     * This preference is no longer supported; it's not a
4536
     * real preference, so we don't reset it (i.e., we
4537
     * treat it as if it weren't found in the list of
4538
     * preferences, and we weren't called in the first place).
4539
     */
4540
0
    if (pref->obsolete)
4541
0
        return;
4542
4543
0
    switch (pref->type) {
4544
4545
0
    case PREF_UINT:
4546
0
        *pref->varp.uint = pref->default_val.uint;
4547
0
        break;
4548
4549
0
    case PREF_BOOL:
4550
0
        *pref->varp.boolp = pref->default_val.boolval;
4551
0
        break;
4552
4553
0
    case PREF_ENUM:
4554
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
4555
0
        *pref->varp.enump = pref->default_val.enumval;
4556
0
        break;
4557
4558
0
    case PREF_STRING:
4559
0
    case PREF_SAVE_FILENAME:
4560
0
    case PREF_OPEN_FILENAME:
4561
0
    case PREF_DIRNAME:
4562
0
    case PREF_PASSWORD:
4563
0
    case PREF_DISSECTOR:
4564
0
        reset_string_like_preference(pref);
4565
0
        break;
4566
4567
0
    case PREF_RANGE:
4568
0
    case PREF_DECODE_AS_RANGE:
4569
0
        wmem_free(wmem_epan_scope(), *pref->varp.range);
4570
0
        *pref->varp.range = range_copy(wmem_epan_scope(), pref->default_val.range);
4571
0
        break;
4572
4573
0
    case PREF_STATIC_TEXT:
4574
0
    case PREF_UAT:
4575
        /* Nothing to do */
4576
0
        break;
4577
4578
0
    case PREF_COLOR:
4579
0
        *pref->varp.colorp = pref->default_val.color;
4580
0
        break;
4581
4582
0
    case PREF_CUSTOM:
4583
0
        pref->custom_cbs.reset_cb(pref);
4584
0
        break;
4585
0
    }
4586
0
}
4587
4588
static void
4589
reset_pref_cb(void *data, void *user_data)
4590
0
{
4591
0
    pref_t *pref = (pref_t *) data;
4592
0
    module_t *module = (module_t *)user_data;
4593
4594
0
    if (pref && (pref->type == PREF_RANGE || pref->type == PREF_DECODE_AS_RANGE)) {
4595
        /*
4596
         * Some dissectors expect the range (returned via prefs_get_range_value)
4597
         * to remain valid if it has not changed. If it did change, then we
4598
         * should set "prefs_changed_flags" to ensure that the preference apply
4599
         * callback is invoked. That callback will notify dissectors that it
4600
         * should no longer assume the range to be valid.
4601
         */
4602
0
        if (ranges_are_equal(*pref->varp.range, pref->default_val.range)) {
4603
            /* Optimization: do not invoke apply callback if nothing changed. */
4604
0
            return;
4605
0
        }
4606
0
        module->prefs_changed_flags |= prefs_get_effect_flags(pref);
4607
0
    }
4608
0
    reset_pref(pref);
4609
0
}
4610
4611
/*
4612
 * Reset all preferences for a module.
4613
 */
4614
static bool
4615
reset_module_prefs(const void *key _U_, void *value, void *data _U_)
4616
0
{
4617
0
    module_t *module = (module_t *)value;
4618
0
    g_list_foreach(module->prefs, reset_pref_cb, module);
4619
0
    return false;
4620
0
}
4621
4622
/* Reset preferences */
4623
void
4624
prefs_reset(void)
4625
0
{
4626
0
    prefs_initialized = false;
4627
0
    g_free(prefs.saved_at_version);
4628
0
    prefs.saved_at_version = NULL;
4629
4630
    /*
4631
     * Unload all UAT preferences.
4632
     */
4633
0
    uat_unload_all();
4634
4635
    /*
4636
     * Unload any loaded MIBs.
4637
     */
4638
0
    oids_cleanup();
4639
4640
    /*
4641
     * Reset the non-dissector preferences.
4642
     */
4643
0
    init_prefs();
4644
4645
    /*
4646
     * Reset the non-UAT dissector preferences.
4647
     */
4648
0
    wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL);
4649
0
}
4650
4651
#ifdef _WIN32
4652
static void
4653
read_registry(void)
4654
{
4655
    HKEY hTestKey;
4656
    DWORD data;
4657
    DWORD data_size = sizeof(DWORD);
4658
    DWORD ret;
4659
4660
    ret = RegOpenKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY, 0, KEY_READ, &hTestKey);
4661
    if (ret != ERROR_SUCCESS && ret != ERROR_FILE_NOT_FOUND) {
4662
        ws_noisy("Cannot open HKCU "REG_HKCU_WIRESHARK_KEY": 0x%lx", ret);
4663
        return;
4664
    }
4665
4666
    ret = RegQueryValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN, NULL, NULL, (LPBYTE)&data, &data_size);
4667
    if (ret == ERROR_SUCCESS) {
4668
        ws_log_console_open = (ws_log_console_open_pref)data;
4669
        ws_noisy("Got "LOG_HKCU_CONSOLE_OPEN" from Windows registry: %d", ws_log_console_open);
4670
    }
4671
    else if (ret != ERROR_FILE_NOT_FOUND) {
4672
        ws_noisy("Error reading registry key "LOG_HKCU_CONSOLE_OPEN": 0x%lx", ret);
4673
    }
4674
4675
    RegCloseKey(hTestKey);
4676
}
4677
#endif
4678
4679
void
4680
prefs_read_module(const char *module)
4681
0
{
4682
0
    int         err;
4683
0
    char        *pf_path;
4684
0
    FILE        *pf;
4685
4686
0
    module_t *target_module = prefs_find_module(module);
4687
0
    if (!target_module) {
4688
0
        return;
4689
0
    }
4690
4691
    /* Construct the pathname of the user's preferences file for the module. */
4692
0
    char *pf_name = wmem_strdup_printf(NULL, "%s.cfg", module);
4693
0
    pf_path = get_persconffile_path(pf_name, true);
4694
0
    wmem_free(NULL, pf_name);
4695
4696
    /* Read the user's module preferences file, if it exists and is not a dir. */
4697
0
    if (!test_for_regular_file(pf_path) || ((pf = ws_fopen(pf_path, "r")) == NULL)) {
4698
0
        g_free(pf_path);
4699
        /* Fall back to the user's generic preferences file. */
4700
0
        pf_path = get_persconffile_path(PF_NAME, true);
4701
0
        pf = ws_fopen(pf_path, "r");
4702
0
    }
4703
4704
0
    if (pf != NULL) {
4705
        /* We succeeded in opening it; read it. */
4706
0
        err = read_prefs_file(pf_path, pf, set_pref, target_module);
4707
0
        if (err != 0) {
4708
            /* We had an error reading the file; report it. */
4709
0
            report_warning("Error reading your preferences file \"%s\": %s.",
4710
0
                           pf_path, g_strerror(err));
4711
0
        } else
4712
0
            g_free(pf_path);
4713
0
        fclose(pf);
4714
0
    } else {
4715
        /* We failed to open it.  If we failed for some reason other than
4716
           "it doesn't exist", return the errno and the pathname, so our
4717
           caller can report the error. */
4718
0
        if (errno != ENOENT) {
4719
0
            report_warning("Can't open your preferences file \"%s\": %s.",
4720
0
                           pf_path, g_strerror(errno));
4721
0
        } else
4722
0
            g_free(pf_path);
4723
0
    }
4724
4725
0
    return;
4726
0
}
4727
4728
/* Read the preferences file, fill in "prefs", and return a pointer to it.
4729
4730
   If we got an error (other than "it doesn't exist") we report it through
4731
   the UI. */
4732
e_prefs *
4733
read_prefs(void)
4734
14
{
4735
14
    int         err;
4736
14
    char        *pf_path;
4737
14
    FILE        *pf;
4738
4739
    /* clean up libsmi structures before reading prefs */
4740
14
    oids_cleanup();
4741
4742
14
    init_prefs();
4743
4744
#ifdef _WIN32
4745
    read_registry();
4746
#endif
4747
4748
    /*
4749
     * If we don't already have the pathname of the global preferences
4750
     * file, construct it.  Then, in either case, try to open the file.
4751
     */
4752
14
    if (gpf_path == NULL) {
4753
        /*
4754
         * We don't have the path; try the new path first, and, if that
4755
         * file doesn't exist, try the old path.
4756
         */
4757
14
        gpf_path = get_datafile_path(PF_NAME);
4758
14
        if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
4759
            /*
4760
             * It doesn't exist by the new name; try the old name.
4761
             */
4762
14
            g_free(gpf_path);
4763
14
            gpf_path = get_datafile_path(OLD_GPF_NAME);
4764
14
            pf = ws_fopen(gpf_path, "r");
4765
14
        }
4766
14
    } else {
4767
        /*
4768
         * We have the path; try it.
4769
         */
4770
0
        pf = ws_fopen(gpf_path, "r");
4771
0
    }
4772
4773
    /*
4774
     * If we were able to open the file, read it.
4775
     * XXX - if it failed for a reason other than "it doesn't exist",
4776
     * report the error.
4777
     */
4778
14
    if (pf != NULL) {
4779
        /*
4780
         * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4781
         * seen.
4782
         */
4783
0
        mgcp_tcp_port_count = 0;
4784
0
        mgcp_udp_port_count = 0;
4785
4786
        /* We succeeded in opening it; read it. */
4787
0
        err = read_prefs_file(gpf_path, pf, set_pref, NULL);
4788
0
        if (err != 0) {
4789
            /* We had an error reading the file; report it. */
4790
0
            report_warning("Error reading global preferences file \"%s\": %s.",
4791
0
                           gpf_path, g_strerror(err));
4792
0
        }
4793
0
        fclose(pf);
4794
14
    } else {
4795
        /* We failed to open it.  If we failed for some reason other than
4796
           "it doesn't exist", report the error. */
4797
14
        if (errno != ENOENT) {
4798
0
            if (errno != 0) {
4799
0
                report_warning("Can't open global preferences file \"%s\": %s.",
4800
0
                               gpf_path, g_strerror(errno));
4801
0
            }
4802
0
        }
4803
14
    }
4804
4805
    /* Construct the pathname of the user's preferences file. */
4806
14
    pf_path = get_persconffile_path(PF_NAME, true);
4807
4808
    /* Read the user's preferences file, if it exists. */
4809
14
    if ((pf = ws_fopen(pf_path, "r")) != NULL) {
4810
        /*
4811
         * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4812
         * seen.
4813
         */
4814
0
        mgcp_tcp_port_count = 0;
4815
0
        mgcp_udp_port_count = 0;
4816
4817
        /* We succeeded in opening it; read it. */
4818
0
        err = read_prefs_file(pf_path, pf, set_pref, NULL);
4819
0
        if (err != 0) {
4820
            /* We had an error reading the file; report it. */
4821
0
            report_warning("Error reading your preferences file \"%s\": %s.",
4822
0
                           pf_path, g_strerror(err));
4823
0
        } else
4824
0
            g_free(pf_path);
4825
0
        fclose(pf);
4826
14
    } else {
4827
        /* We failed to open it.  If we failed for some reason other than
4828
           "it doesn't exist", return the errno and the pathname, so our
4829
           caller can report the error. */
4830
14
        if (errno != ENOENT) {
4831
0
            report_warning("Can't open your preferences file \"%s\": %s.",
4832
0
                           pf_path, g_strerror(errno));
4833
0
        } else
4834
14
            g_free(pf_path);
4835
14
    }
4836
4837
    /* load SMI modules if needed */
4838
14
    oids_init();
4839
4840
14
    return &prefs;
4841
14
}
4842
4843
/* read the preferences file (or similar) and call the callback
4844
 * function to set each key/value pair found */
4845
int
4846
read_prefs_file(const char *pf_path, FILE *pf,
4847
                pref_set_pair_cb pref_set_pair_fct, void *private_data)
4848
0
{
4849
0
    enum {
4850
0
        START,    /* beginning of a line */
4851
0
        IN_VAR,   /* processing key name */
4852
0
        PRE_VAL,  /* finished processing key name, skipping white space before value */
4853
0
        IN_VAL,   /* processing value */
4854
0
        IN_SKIP   /* skipping to the end of the line */
4855
0
    } state = START;
4856
0
    int       got_c;
4857
0
    GString  *cur_val;
4858
0
    GString  *cur_var;
4859
0
    bool      got_val = false;
4860
0
    int       fline = 1, pline = 1;
4861
0
    char      hint[] = "(save preferences to remove this warning)";
4862
0
    char      ver[128];
4863
4864
0
    cur_val = g_string_new("");
4865
0
    cur_var = g_string_new("");
4866
4867
    /* Try to read in the profile name in the first line of the preferences file. */
4868
0
    if (fscanf(pf, "# Configuration file for %127[^\r\n]", ver) == 1) {
4869
        /* Assume trailing period and remove it */
4870
0
        g_free(prefs.saved_at_version);
4871
0
        prefs.saved_at_version = g_strndup(ver, strlen(ver) - 1);
4872
0
    }
4873
0
    rewind(pf);
4874
4875
0
    while ((got_c = ws_getc_unlocked(pf)) != EOF) {
4876
0
        if (got_c == '\r') {
4877
            /* Treat CR-LF at the end of a line like LF, so that if we're reading
4878
             * a Windows-format file on UN*X, we handle it the same way we'd handle
4879
             * a UN*X-format file. */
4880
0
            got_c = ws_getc_unlocked(pf);
4881
0
            if (got_c == EOF)
4882
0
                break;
4883
0
            if (got_c != '\n') {
4884
                /* Put back the character after the CR, and process the CR normally. */
4885
0
                ungetc(got_c, pf);
4886
0
                got_c = '\r';
4887
0
            }
4888
0
        }
4889
0
        if (got_c == '\n') {
4890
0
            state = START;
4891
0
            fline++;
4892
0
            continue;
4893
0
        }
4894
4895
0
        switch (state) {
4896
0
        case START:
4897
0
            if (g_ascii_isalnum(got_c)) {
4898
0
                if (cur_var->len > 0) {
4899
0
                    if (got_val) {
4900
0
                        if (cur_val->len > 0) {
4901
0
                            if (cur_val->str[cur_val->len-1] == ',') {
4902
                                /*
4903
                                 * If the pref has a trailing comma, eliminate it.
4904
                                 */
4905
0
                                cur_val->str[cur_val->len-1] = '\0';
4906
0
                                ws_warning("%s line %d: trailing comma in \"%s\" %s", pf_path, pline, cur_var->str, hint);
4907
0
                            }
4908
0
                        }
4909
                        /* Call the routine to set the preference; it will parse
4910
                           the value as appropriate.
4911
4912
                           Since we're reading a file, rather than processing
4913
                           explicit user input, for range preferences, silently
4914
                           lower values in excess of the range's maximum, rather
4915
                           than reporting errors and failing. */
4916
0
                        switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false)) {
4917
4918
0
                        case PREFS_SET_OK:
4919
0
                            break;
4920
4921
0
                        case PREFS_SET_SYNTAX_ERR:
4922
0
                            report_warning("Syntax error in preference \"%s\" at line %d of\n%s %s",
4923
0
                                       cur_var->str, pline, pf_path, hint);
4924
0
                            break;
4925
4926
0
                        case PREFS_SET_NO_SUCH_PREF:
4927
0
                            ws_warning("No such preference \"%s\" at line %d of\n%s %s",
4928
0
                                       cur_var->str, pline, pf_path, hint);
4929
0
                            prefs.unknown_prefs = true;
4930
0
                            break;
4931
4932
0
                        case PREFS_SET_OBSOLETE:
4933
                            /*
4934
                             * If an attempt is made to save the
4935
                             * preferences, a popup warning will be
4936
                             * displayed stating that obsolete prefs
4937
                             * have been detected and the user will
4938
                             * be given the opportunity to save these
4939
                             * prefs under a different profile name.
4940
                             * The prefs in question need to be listed
4941
                             * in the console window so that the
4942
                             * user can make an informed choice.
4943
                             */
4944
0
                            ws_warning("Obsolete preference \"%s\" at line %d of\n%s %s",
4945
0
                                       cur_var->str, pline, pf_path, hint);
4946
0
                            prefs.unknown_prefs = true;
4947
0
                            break;
4948
0
                        }
4949
0
                    } else {
4950
0
                        ws_warning("Incomplete preference at line %d: of\n%s %s", pline, pf_path, hint);
4951
0
                    }
4952
0
                }
4953
0
                state      = IN_VAR;
4954
0
                got_val    = false;
4955
0
                g_string_truncate(cur_var, 0);
4956
0
                g_string_append_c(cur_var, (char) got_c);
4957
0
                pline = fline;
4958
0
            } else if (g_ascii_isspace(got_c) && cur_var->len > 0 && got_val) {
4959
0
                state = PRE_VAL;
4960
0
            } else if (got_c == '#') {
4961
0
                state = IN_SKIP;
4962
0
            } else {
4963
0
                ws_warning("Malformed preference at line %d of\n%s %s", fline, pf_path, hint);
4964
0
            }
4965
0
            break;
4966
0
        case IN_VAR:
4967
0
            if (got_c != ':') {
4968
0
                g_string_append_c(cur_var, (char) got_c);
4969
0
            } else {
4970
                /* This is a colon (':') */
4971
0
                state   = PRE_VAL;
4972
0
                g_string_truncate(cur_val, 0);
4973
                /*
4974
                 * Set got_val to true to accommodate prefs such as
4975
                 * "gui.fileopen.dir" that do not require a value.
4976
                 */
4977
0
                got_val = true;
4978
0
            }
4979
0
            break;
4980
0
        case PRE_VAL:
4981
0
            if (!g_ascii_isspace(got_c)) {
4982
0
                state = IN_VAL;
4983
0
                g_string_append_c(cur_val, (char) got_c);
4984
0
            }
4985
0
            break;
4986
0
        case IN_VAL:
4987
0
            g_string_append_c(cur_val, (char) got_c);
4988
0
            break;
4989
0
        case IN_SKIP:
4990
0
            break;
4991
0
        }
4992
0
    }
4993
0
    if (cur_var->len > 0) {
4994
0
        if (got_val) {
4995
            /* Call the routine to set the preference; it will parse
4996
               the value as appropriate.
4997
4998
               Since we're reading a file, rather than processing
4999
               explicit user input, for range preferences, silently
5000
               lower values in excess of the range's maximum, rather
5001
               than reporting errors and failing. */
5002
0
            switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false)) {
5003
5004
0
            case PREFS_SET_OK:
5005
0
                break;
5006
5007
0
            case PREFS_SET_SYNTAX_ERR:
5008
0
                ws_warning("Syntax error in preference %s at line %d of\n%s %s",
5009
0
                           cur_var->str, pline, pf_path, hint);
5010
0
                break;
5011
5012
0
            case PREFS_SET_NO_SUCH_PREF:
5013
0
                ws_warning("No such preference \"%s\" at line %d of\n%s %s",
5014
0
                           cur_var->str, pline, pf_path, hint);
5015
0
                prefs.unknown_prefs = true;
5016
0
                break;
5017
5018
0
            case PREFS_SET_OBSOLETE:
5019
0
                prefs.unknown_prefs = true;
5020
0
                break;
5021
0
            }
5022
0
        } else {
5023
0
            ws_warning("Incomplete preference at line %d of\n%s %s",
5024
0
                       pline, pf_path, hint);
5025
0
        }
5026
0
    }
5027
5028
0
    g_string_free(cur_val, TRUE);
5029
0
    g_string_free(cur_var, TRUE);
5030
5031
0
    if (ferror(pf))
5032
0
        return errno;
5033
0
    else
5034
0
        return 0;
5035
0
}
5036
5037
/*
5038
 * If we were handed a preference starting with "uat:", try to turn it into
5039
 * a valid uat entry.
5040
 */
5041
static bool
5042
0
prefs_set_uat_pref(char *uat_entry, char **errmsg) {
5043
0
    char *p, *colonp;
5044
0
    uat_t *uat;
5045
0
    bool ret;
5046
5047
0
    colonp = strchr(uat_entry, ':');
5048
0
    if (colonp == NULL)
5049
0
        return false;
5050
5051
0
    p = colonp;
5052
0
    *p++ = '\0';
5053
5054
    /*
5055
     * Skip over any white space (there probably won't be any, but
5056
     * as we allow it in the preferences file, we might as well
5057
     * allow it here).
5058
     */
5059
0
    while (g_ascii_isspace(*p))
5060
0
        p++;
5061
0
    if (*p == '\0') {
5062
        /*
5063
         * Put the colon back, so if our caller uses, in an
5064
         * error message, the string they passed us, the message
5065
         * looks correct.
5066
         */
5067
0
        *colonp = ':';
5068
0
        return false;
5069
0
    }
5070
5071
0
    uat = uat_find(uat_entry);
5072
0
    *colonp = ':';
5073
0
    if (uat == NULL) {
5074
0
        *errmsg = g_strdup("Unknown preference");
5075
0
        return false;
5076
0
    }
5077
5078
0
    ret = uat_load_str(uat, p, errmsg);
5079
0
    return ret;
5080
0
}
5081
5082
/*
5083
 * Given a string of the form "<pref name>:<pref value>", as might appear
5084
 * as an argument to a "-o" option, parse it and set the preference in
5085
 * question.  Return an indication of whether it succeeded or failed
5086
 * in some fashion.
5087
 */
5088
prefs_set_pref_e
5089
prefs_set_pref(char *prefarg, char **errmsg)
5090
56
{
5091
56
    char *p, *colonp;
5092
56
    prefs_set_pref_e ret;
5093
5094
    /*
5095
     * Set the counters of "mgcp.{tcp,udp}.port" entries we've
5096
     * seen to values that keep us from trying to interpret them
5097
     * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
5098
     * as, from the command line, we have no way of guessing which
5099
     * the user had in mind.
5100
     */
5101
56
    mgcp_tcp_port_count = -1;
5102
56
    mgcp_udp_port_count = -1;
5103
5104
56
    *errmsg = NULL;
5105
5106
56
    colonp = strchr(prefarg, ':');
5107
56
    if (colonp == NULL)
5108
0
        return PREFS_SET_SYNTAX_ERR;
5109
5110
56
    p = colonp;
5111
56
    *p++ = '\0';
5112
5113
    /*
5114
     * Skip over any white space (there probably won't be any, but
5115
     * as we allow it in the preferences file, we might as well
5116
     * allow it here).
5117
     */
5118
56
    while (g_ascii_isspace(*p))
5119
0
        p++;
5120
    /* The empty string is a legal value for range preferences (PREF_RANGE,
5121
     * PREF_DECODE_AS_RANGE), and string-like preferences (PREF_STRING,
5122
     * PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME), indeed often
5123
     * not just useful but the default. A user might have a value saved
5124
     * to their preference file but want to override it to default behavior.
5125
     * Individual preference handlers of those types should be prepared to
5126
     * deal with an empty string. For other types, it is up to set_pref() to
5127
     * test for the empty string and set PREFS_SET_SYNTAX_ERROR there.
5128
     */
5129
56
    if (strcmp(prefarg, "uat")) {
5130
56
        ret = set_pref(prefarg, p, NULL, true);
5131
56
    } else {
5132
0
        ret = prefs_set_uat_pref(p, errmsg) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
5133
0
    }
5134
56
    *colonp = ':';    /* put the colon back */
5135
56
    return ret;
5136
56
}
5137
5138
unsigned prefs_get_uint_value(pref_t *pref, pref_source_t source)
5139
0
{
5140
0
    switch (source)
5141
0
    {
5142
0
    case pref_default:
5143
0
        return pref->default_val.uint;
5144
0
    case pref_stashed:
5145
0
        return pref->stashed_val.uint;
5146
0
    case pref_current:
5147
0
        return *pref->varp.uint;
5148
0
    default:
5149
0
        ws_assert_not_reached();
5150
0
        break;
5151
0
    }
5152
5153
0
    return 0;
5154
0
}
5155
5156
char* prefs_get_password_value(pref_t *pref, pref_source_t source)
5157
0
{
5158
0
    return prefs_get_string_value(pref, source);
5159
0
}
5160
5161
5162
unsigned int prefs_set_uint_value(pref_t *pref, unsigned value, pref_source_t source)
5163
0
{
5164
0
    unsigned int changed = 0;
5165
0
    switch (source)
5166
0
    {
5167
0
    case pref_default:
5168
0
        if (pref->default_val.uint != value) {
5169
0
            pref->default_val.uint = value;
5170
0
            changed = prefs_get_effect_flags(pref);
5171
0
        }
5172
0
        break;
5173
0
    case pref_stashed:
5174
0
        if (pref->stashed_val.uint != value) {
5175
0
            pref->stashed_val.uint = value;
5176
0
            changed = prefs_get_effect_flags(pref);
5177
0
        }
5178
0
        break;
5179
0
    case pref_current:
5180
0
        if (*pref->varp.uint != value) {
5181
0
            *pref->varp.uint = value;
5182
0
            changed = prefs_get_effect_flags(pref);
5183
0
        }
5184
0
        break;
5185
0
    default:
5186
0
        ws_assert_not_reached();
5187
0
        break;
5188
0
    }
5189
5190
0
    return changed;
5191
0
}
5192
5193
/*
5194
 * For use by UI code that sets preferences.
5195
 */
5196
unsigned int
5197
prefs_set_password_value(pref_t *pref, const char* value, pref_source_t source)
5198
0
{
5199
0
    return prefs_set_string_value(pref, value, source);
5200
0
}
5201
5202
5203
unsigned prefs_get_uint_base(pref_t *pref)
5204
0
{
5205
0
    return pref->info.base;
5206
0
}
5207
5208
/*
5209
 * Returns true if the given device is hidden
5210
 */
5211
bool
5212
prefs_is_capture_device_hidden(const char *name)
5213
0
{
5214
0
    char *tok, *devices;
5215
0
    size_t len;
5216
5217
0
    if (prefs.capture_devices_hide && name) {
5218
0
        devices = g_strdup (prefs.capture_devices_hide);
5219
0
        len = strlen (name);
5220
0
        for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
5221
0
            if (strlen (tok) == len && strcmp (name, tok) == 0) {
5222
0
                g_free (devices);
5223
0
                return true;
5224
0
            }
5225
0
        }
5226
0
        g_free (devices);
5227
0
    }
5228
5229
0
    return false;
5230
0
}
5231
5232
/*
5233
 * Returns true if the given column is visible (not hidden)
5234
 */
5235
static bool
5236
prefs_is_column_visible(const char *cols_hidden, int col)
5237
0
{
5238
0
    char *tok, *cols, *p;
5239
0
    int cidx;
5240
5241
    /*
5242
     * Do we have a list of hidden columns?
5243
     */
5244
0
    if (cols_hidden) {
5245
        /*
5246
         * Yes - check the column against each of the ones in the
5247
         * list.
5248
         */
5249
0
        cols = g_strdup(cols_hidden);
5250
0
        for (tok = strtok(cols, ","); tok; tok = strtok(NULL, ",")) {
5251
0
            tok = g_strstrip(tok);
5252
5253
0
            cidx = (int)strtol(tok, &p, 10);
5254
0
            if (p == tok || *p != '\0') {
5255
0
                continue;
5256
0
            }
5257
0
            if (cidx != col) {
5258
0
                continue;
5259
0
            }
5260
            /*
5261
             * OK, they match, so it's one of the hidden fields,
5262
             * hence not visible.
5263
             */
5264
0
            g_free(cols);
5265
0
            return false;
5266
0
        }
5267
0
        g_free(cols);
5268
0
    }
5269
5270
    /*
5271
     * No - either there are no hidden columns or this isn't one
5272
     * of them - so it is visible.
5273
     */
5274
0
    return true;
5275
0
}
5276
5277
/*
5278
 * Returns true if the given column is visible (not hidden)
5279
 */
5280
static bool
5281
prefs_is_column_fmt_visible(const char *cols_hidden, fmt_data *cfmt)
5282
0
{
5283
0
    char *tok, *cols;
5284
0
    fmt_data cfmt_hidden;
5285
5286
    /*
5287
     * Do we have a list of hidden columns?
5288
     */
5289
0
    if (cols_hidden) {
5290
        /*
5291
         * Yes - check the column against each of the ones in the
5292
         * list.
5293
         */
5294
0
        cols = g_strdup(cols_hidden);
5295
0
        for (tok = strtok(cols, ","); tok; tok = strtok(NULL, ",")) {
5296
0
            tok = g_strstrip(tok);
5297
5298
            /*
5299
             * Parse this column format.
5300
             */
5301
0
            if (!parse_column_format(&cfmt_hidden, tok)) {
5302
                /*
5303
                 * It's not valid; ignore it.
5304
                 */
5305
0
                continue;
5306
0
            }
5307
5308
            /*
5309
             * Does it match the column?
5310
             */
5311
0
            if (cfmt->fmt != cfmt_hidden.fmt) {
5312
                /* No. */
5313
0
                g_free(cfmt_hidden.custom_fields);
5314
0
                cfmt_hidden.custom_fields = NULL;
5315
0
                continue;
5316
0
            }
5317
0
            if (cfmt->fmt == COL_CUSTOM) {
5318
                /*
5319
                 * A custom column has to have the same custom field
5320
                 * and occurrence.
5321
                 */
5322
0
                if (cfmt_hidden.custom_fields && cfmt->custom_fields) {
5323
0
                    if (strcmp(cfmt->custom_fields,
5324
0
                               cfmt_hidden.custom_fields) != 0) {
5325
                        /* Different fields. */
5326
0
                        g_free(cfmt_hidden.custom_fields);
5327
0
                        cfmt_hidden.custom_fields = NULL;
5328
0
                        continue;
5329
0
                    }
5330
0
                    if (cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) {
5331
                        /* Different occurrences settings. */
5332
0
                        g_free(cfmt_hidden.custom_fields);
5333
0
                        cfmt_hidden.custom_fields = NULL;
5334
0
                        continue;
5335
0
                    }
5336
0
                }
5337
0
            }
5338
5339
            /*
5340
             * OK, they match, so it's one of the hidden fields,
5341
             * hence not visible.
5342
             */
5343
0
            g_free(cfmt_hidden.custom_fields);
5344
0
            g_free(cols);
5345
0
            return false;
5346
0
        }
5347
0
        g_free(cols);
5348
0
    }
5349
5350
    /*
5351
     * No - either there are no hidden columns or this isn't one
5352
     * of them - so it is visible.
5353
     */
5354
0
    return true;
5355
0
}
5356
5357
/*
5358
 * Returns true if the given device should capture in monitor mode by default
5359
 */
5360
bool
5361
prefs_capture_device_monitor_mode(const char *name)
5362
0
{
5363
0
    char *tok, *devices;
5364
0
    size_t len;
5365
5366
0
    if (prefs.capture_devices_monitor_mode && name) {
5367
0
        devices = g_strdup (prefs.capture_devices_monitor_mode);
5368
0
        len = strlen (name);
5369
0
        for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
5370
0
            if (strlen (tok) == len && strcmp (name, tok) == 0) {
5371
0
                g_free (devices);
5372
0
                return true;
5373
0
            }
5374
0
        }
5375
0
        g_free (devices);
5376
0
    }
5377
5378
0
    return false;
5379
0
}
5380
5381
/*
5382
 * Returns true if the user has marked this column as visible
5383
 */
5384
bool
5385
prefs_capture_options_dialog_column_is_visible(const char *column)
5386
0
{
5387
0
    GList *curr;
5388
0
    char *col;
5389
5390
0
    for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)) {
5391
0
        col = (char *)curr->data;
5392
0
        if (col && (g_ascii_strcasecmp(col, column) == 0)) {
5393
0
            return true;
5394
0
        }
5395
0
    }
5396
0
    return false;
5397
0
}
5398
5399
bool
5400
prefs_has_layout_pane_content (layout_pane_content_e layout_pane_content)
5401
0
{
5402
0
    return ((prefs.gui_layout_content_1 == layout_pane_content) ||
5403
0
            (prefs.gui_layout_content_2 == layout_pane_content) ||
5404
0
            (prefs.gui_layout_content_3 == layout_pane_content));
5405
0
}
5406
5407
56
#define PRS_GUI_FILTER_LABEL             "gui.filter_expressions.label"
5408
56
#define PRS_GUI_FILTER_EXPR              "gui.filter_expressions.expr"
5409
56
#define PRS_GUI_FILTER_ENABLED           "gui.filter_expressions.enabled"
5410
5411
/*
5412
 * Extract the red, green, and blue components of a 24-bit RGB value
5413
 * and convert them from [0,255] to [0,65535].
5414
 */
5415
0
#define RED_COMPONENT(x)   (uint16_t) (((((x) >> 16) & 0xff) * 65535 / 255))
5416
0
#define GREEN_COMPONENT(x) (uint16_t) (((((x) >>  8) & 0xff) * 65535 / 255))
5417
0
#define BLUE_COMPONENT(x)  (uint16_t) ( (((x)        & 0xff) * 65535 / 255))
5418
5419
char
5420
string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
5421
0
{
5422
0
    char c;
5423
5424
0
    memset(name_resolve, 0, sizeof(e_addr_resolve));
5425
0
    while ((c = *string++) != '\0') {
5426
0
        switch (c) {
5427
0
        case 'g':
5428
0
            name_resolve->maxmind_geoip = true;
5429
0
            break;
5430
0
        case 'm':
5431
0
            name_resolve->mac_name = true;
5432
0
            break;
5433
0
        case 'n':
5434
0
            name_resolve->network_name = true;
5435
0
            break;
5436
0
        case 'N':
5437
0
            name_resolve->use_external_net_name_resolver = true;
5438
0
            break;
5439
0
        case 't':
5440
0
            name_resolve->transport_name = true;
5441
0
            break;
5442
0
        case 'd':
5443
0
            name_resolve->dns_pkt_addr_resolution = true;
5444
0
            break;
5445
0
        case 's':
5446
0
            name_resolve->handshake_sni_addr_resolution = true;
5447
0
            break;
5448
0
        case 'v':
5449
0
            name_resolve->vlan_name = true;
5450
0
            break;
5451
0
        default:
5452
            /*
5453
             * Unrecognized letter.
5454
             */
5455
0
            return c;
5456
0
        }
5457
0
    }
5458
0
    return '\0';
5459
0
}
5460
5461
static bool
5462
deprecated_heur_dissector_pref(char *pref_name, const char *value)
5463
56
{
5464
56
    struct heur_pref_name
5465
56
    {
5466
56
        const char* pref_name;
5467
56
        const char* short_name;
5468
56
        bool      more_dissectors; /* For multiple dissectors controlled by the same preference */
5469
56
    };
5470
5471
56
    struct heur_pref_name heur_prefs[] = {
5472
56
        {"acn.heuristic_acn", "acn_udp", 0},
5473
56
        {"bfcp.enable", "bfcp_tcp", 1},
5474
56
        {"bfcp.enable", "bfcp_udp", 0},
5475
56
        {"bt-dht.enable", "bittorrent_dht_udp", 0},
5476
56
        {"bt-utp.enable", "bt_utp_udp", 0},
5477
56
        {"cattp.enable", "cattp_udp", 0},
5478
56
        {"cfp.enable", "fp_eth", 0},
5479
56
        {"dicom.heuristic", "dicom_tcp", 0},
5480
56
        {"dnp3.heuristics", "dnp3_tcp", 1},
5481
56
        {"dnp3.heuristics", "dnp3_udp", 0},
5482
56
        {"dvb-s2_modeadapt.enable", "dvb_s2_udp", 0},
5483
56
        {"esl.enable", "esl_eth", 0},
5484
56
        {"fp.udp_heur", "fp_udp", 0},
5485
56
        {"gvsp.enable_heuristic", "gvsp_udp", 0},
5486
56
        {"hdcp2.enable", "hdcp2_tcp", 0},
5487
56
        {"hislip.enable_heuristic", "hislip_tcp", 0},
5488
56
        {"infiniband.dissect_eoib", "mellanox_eoib", 1},
5489
56
        {"infiniband.identify_payload", "eth_over_ib", 0},
5490
56
        {"jxta.udp.heuristic", "jxta_udp", 0},
5491
56
        {"jxta.tcp.heuristic", "jxta_tcp", 0},
5492
56
        {"jxta.sctp.heuristic", "jxta_sctp", 0},
5493
56
        {"mac-lte.heuristic_mac_lte_over_udp", "mac_lte_udp", 0},
5494
56
        {"mbim.bulk_heuristic", "mbim_usb_bulk", 0},
5495
56
        {"norm.heuristic_norm", "rmt_norm_udp", 0},
5496
56
        {"openflow.heuristic", "openflow_tcp", 0},
5497
56
        {"pdcp-lte.heuristic_pdcp_lte_over_udp", "pdcp_lte_udp", 0},
5498
56
        {"rlc.heuristic_rlc_over_udp", "rlc_udp", 0},
5499
56
        {"rlc-lte.heuristic_rlc_lte_over_udp", "rlc_lte_udp", 0},
5500
56
        {"rtcp.heuristic_rtcp", "rtcp_udp", 1},
5501
56
        {"rtcp.heuristic_rtcp", "rtcp_stun", 0},
5502
56
        {"rtp.heuristic_rtp", "rtp_udp", 1},
5503
56
        {"rtp.heuristic_rtp", "rtp_stun", 0},
5504
56
        {"teredo.heuristic_teredo", "teredo_udp", 0},
5505
56
        {"vssmonitoring.use_heuristics", "vssmonitoring_eth", 0},
5506
56
        {"xml.heuristic", "xml_http", 1},
5507
56
        {"xml.heuristic", "xml_sip", 1},
5508
56
        {"xml.heuristic", "xml_media", 0},
5509
56
        {"xml.heuristic_tcp", "xml_tcp", 0},
5510
56
        {"xml.heuristic_udp", "xml_udp", 0},
5511
56
    };
5512
5513
56
    unsigned int i;
5514
56
    heur_dtbl_entry_t* heuristic;
5515
5516
5517
2.24k
    for (i = 0; i < array_length(heur_prefs); i++)
5518
2.18k
    {
5519
2.18k
        if (strcmp(pref_name, heur_prefs[i].pref_name) == 0)
5520
0
        {
5521
0
            heuristic = find_heur_dissector_by_unique_short_name(heur_prefs[i].short_name);
5522
0
            if (heuristic != NULL) {
5523
0
                heuristic->enabled = ((g_ascii_strcasecmp(value, "true") == 0) ? true : false);
5524
0
            }
5525
5526
0
            if (!heur_prefs[i].more_dissectors)
5527
0
                return true;
5528
0
        }
5529
2.18k
    }
5530
5531
5532
56
    return false;
5533
56
}
5534
5535
static bool
5536
deprecated_enable_dissector_pref(char *pref_name, const char *value)
5537
56
{
5538
56
    struct dissector_pref_name
5539
56
    {
5540
56
        const char* pref_name;
5541
56
        const char* short_name;
5542
56
    };
5543
5544
56
    struct dissector_pref_name dissector_prefs[] = {
5545
56
        {"transum.tsumenabled", "TRANSUM"},
5546
56
        {"snort.enable_snort_dissector", "Snort"},
5547
56
        {"prp.enable", "PRP"},
5548
56
    };
5549
5550
56
    unsigned int i;
5551
56
    int proto_id;
5552
5553
224
    for (i = 0; i < array_length(dissector_prefs); i++)
5554
168
    {
5555
168
        if (strcmp(pref_name, dissector_prefs[i].pref_name) == 0)
5556
0
        {
5557
0
            proto_id = proto_get_id_by_short_name(dissector_prefs[i].short_name);
5558
0
            if (proto_id >= 0)
5559
0
                proto_set_decoding(proto_id, ((g_ascii_strcasecmp(value, "true") == 0) ? true : false));
5560
0
            return true;
5561
0
        }
5562
168
    }
5563
5564
56
    return false;
5565
56
}
5566
5567
static bool
5568
deprecated_port_pref(char *pref_name, const char *value)
5569
56
{
5570
56
    struct port_pref_name
5571
56
    {
5572
56
        const char* pref_name;
5573
56
        const char* module_name;    /* the protocol filter name */
5574
56
        const char* table_name;
5575
56
        unsigned base;
5576
56
    };
5577
5578
56
    struct obsolete_pref_name
5579
56
    {
5580
56
        const char* pref_name;
5581
56
    };
5582
5583
    /* For now this is only supporting TCP/UDP port and RTP payload
5584
     * types dissector preferences, which are assumed to be decimal */
5585
    /* module_name is the filter name of the destination port preference,
5586
     * which is usually the same as the original module but not
5587
     * necessarily (e.g., if the preference is for what is now a PINO.)
5588
     * XXX:  Most of these were changed pre-2.0. Can we end support
5589
     * for migrating legacy preferences at some point?
5590
     */
5591
56
    struct port_pref_name port_prefs[] = {
5592
        /* TCP */
5593
56
        {"cmp.tcp_alternate_port", "cmp", "tcp.port", 10},
5594
56
        {"h248.tcp_port", "h248", "tcp.port", 10},
5595
56
        {"cops.tcp.cops_port", "cops", "tcp.port", 10},
5596
56
        {"dhcpfo.tcp_port", "dhcpfo", "tcp.port", 10},
5597
56
        {"enttec.tcp_port", "enttec", "tcp.port", 10},
5598
56
        {"forces.tcp_alternate_port", "forces", "tcp.port", 10},
5599
56
        {"ged125.tcp_port", "ged125", "tcp.port", 10},
5600
56
        {"hpfeeds.dissector_port", "hpfeeds", "tcp.port", 10},
5601
56
        {"lsc.port", "lsc", "tcp.port", 10},
5602
56
        {"megaco.tcp.txt_port", "megaco", "tcp.port", 10},
5603
56
        {"netsync.tcp_port", "netsync", "tcp.port", 10},
5604
56
        {"osi.tpkt_port", "osi", "tcp.port", 10},
5605
56
        {"rsync.tcp_port", "rsync", "tcp.port", 10},
5606
56
        {"sametime.tcp_port", "sametime", "tcp.port", 10},
5607
56
        {"sigcomp.tcp.port2", "sigcomp", "tcp.port", 10},
5608
56
        {"synphasor.tcp_port", "synphasor", "tcp.port", 10},
5609
56
        {"tipc.alternate_port", "tipc", "tcp.port", 10},
5610
56
        {"vnc.alternate_port", "vnc", "tcp.port", 10},
5611
56
        {"scop.port", "scop", "tcp.port", 10},
5612
56
        {"scop.port_secure", "scop", "tcp.port", 10},
5613
56
        {"tpncp.tcp.trunkpack_port", "tpncp", "tcp.port", 10},
5614
        /* UDP */
5615
56
        {"h248.udp_port", "h248", "udp.port", 10},
5616
56
        {"actrace.udp_port", "actrace", "udp.port", 10},
5617
56
        {"brp.port", "brp", "udp.port", 10},
5618
56
        {"bvlc.additional_udp_port", "bvlc", "udp.port", 10},
5619
56
        {"capwap.udp.port.control", "capwap", "udp.port", 10},
5620
56
        {"capwap.udp.port.data", "capwap", "udp.port", 10},
5621
56
        {"coap.udp_port", "coap", "udp.port", 10},
5622
56
        {"enttec.udp_port", "enttec", "udp.port", 10},
5623
56
        {"forces.udp_alternate_port", "forces", "udp.port", 10},
5624
56
        {"ldss.udp_port", "ldss", "udp.port", 10},
5625
56
        {"lmp.udp_port", "lmp", "udp.port", 10},
5626
56
        {"ltp.port", "ltp", "udp.port", 10},
5627
56
        {"lwres.udp.lwres_port", "lwres", "udp.port", 10},
5628
56
        {"megaco.udp.txt_port", "megaco", "udp.port", 10},
5629
56
        {"pfcp.port_pfcp", "pfcp", "udp.port", 10},
5630
56
        {"pgm.udp.encap_ucast_port", "pgm", "udp.port", 10},
5631
56
        {"pgm.udp.encap_mcast_port", "pgm", "udp.port", 10},
5632
56
        {"quic.udp.quic.port", "quic", "udp.port", 10},
5633
56
        {"quic.udp.quics.port", "quic", "udp.port", 10},
5634
56
        {"radius.alternate_port", "radius", "udp.port", 10},
5635
56
        {"rdt.default_udp_port", "rdt", "udp.port", 10},
5636
56
        {"alc.default.udp_port", "alc", "udp.port", 10},
5637
56
        {"sigcomp.udp.port2", "sigcomp", "udp.port", 10},
5638
56
        {"synphasor.udp_port", "synphasor", "udp.port", 10},
5639
56
        {"tdmop.udpport", "tdmop", "udp.port", 10},
5640
56
        {"uaudp.port1", "uaudp", "udp.port", 10},
5641
56
        {"uaudp.port2", "uaudp", "udp.port", 10},
5642
56
        {"uaudp.port3", "uaudp", "udp.port", 10},
5643
56
        {"uaudp.port4", "uaudp", "udp.port", 10},
5644
56
        {"uhd.dissector_port", "uhd", "udp.port", 10},
5645
56
        {"vrt.dissector_port", "vrt", "udp.port", 10},
5646
56
        {"tpncp.udp.trunkpack_port", "tpncp", "udp.port", 10},
5647
        /* SCTP */
5648
56
        {"hnbap.port", "hnbap", "sctp.port", 10},
5649
56
        {"m2pa.port", "m2pa", "sctp.port", 10},
5650
56
        {"megaco.sctp.txt_port", "megaco", "sctp.port", 10},
5651
56
        {"rua.port", "rua", "sctp.port", 10},
5652
        /* SCTP PPI */
5653
56
        {"lapd.sctp_payload_protocol_identifier", "lapd", "sctp.ppi", 10},
5654
        /* SCCP SSN */
5655
56
        {"ranap.sccp_ssn", "ranap", "sccp.ssn", 10},
5656
56
    };
5657
5658
56
    struct port_pref_name port_range_prefs[] = {
5659
        /* TCP */
5660
56
        {"couchbase.tcp.ports", "couchbase", "tcp.port", 10},
5661
56
        {"gsm_ipa.tcp_ports", "gsm_ipa", "tcp.port", 10},
5662
56
        {"kafka.tcp.ports", "kafka", "tcp.port", 10},
5663
56
        {"kt.tcp.ports", "kt", "tcp.port", 10},
5664
56
        {"memcache.tcp.ports", "memcache", "tcp.port", 10},
5665
56
        {"mrcpv2.tcp.port_range", "mrcpv2", "tcp.port", 10},
5666
56
        {"pdu_transport.ports.tcp", "pdu_transport", "tcp.port", 10},
5667
56
        {"rtsp.tcp.port_range", "rtsp", "tcp.port", 10},
5668
56
        {"sip.tcp.ports", "sip", "tcp.port", 10},
5669
56
        {"someip.ports.tcp", "someip", "tcp.port", 10},
5670
56
        {"tds.tcp_ports", "tds", "tcp.port", 10},
5671
56
        {"tpkt.tcp.ports", "tpkt", "tcp.port", 10},
5672
56
        {"uma.tcp.ports", "uma", "tcp.port", 10},
5673
        /* UDP */
5674
56
        {"aruba_erm.udp.ports", "arubs_erm", "udp.port", 10},
5675
56
        {"diameter.udp.ports", "diameter", "udp.port", 10},
5676
56
        {"dmp.udp_ports", "dmp", "udp.port", 10},
5677
56
        {"dns.udp.ports", "dns", "udp.port", 10},
5678
56
        {"gsm_ipa.udp_ports", "gsm_ipa", "udp.port", 10},
5679
56
        {"hcrt.dissector_udp_port", "hcrt", "udp.port", 10},
5680
56
        {"memcache.udp.ports", "memcache", "udp.port", 10},
5681
56
        {"nb_rtpmux.udp_ports", "nb_rtpmux", "udp.port", 10},
5682
56
        {"gprs-ns.udp.ports", "gprs-ns", "udp.port", 10},
5683
56
        {"p_mul.udp_ports", "p_mul", "udp.port", 10},
5684
56
        {"pdu_transport.ports.udp", "pdu_transport", "udp.port", 10},
5685
56
        {"radius.ports", "radius", "udp.port", 10},
5686
56
        {"sflow.ports", "sflow", "udp.port", 10},
5687
56
        {"someip.ports.udp", "someip", "udp.port", 10},
5688
56
        {"sscop.udp.ports", "sscop", "udp.port", 10},
5689
56
        {"tftp.udp_ports", "tftp", "udp.port", 10},
5690
56
        {"tipc.udp.ports", "tipc", "udp.port", 10},
5691
        /* RTP */
5692
56
        {"amr.dynamic.payload.type", "amr", "rtp.pt", 10},
5693
56
        {"amr.wb.dynamic.payload.type", "amr_wb", "rtp.pt", 10},
5694
56
        {"dvb-s2_modeadapt.dynamic.payload.type", "dvb-s2_modeadapt", "rtp.pt", 10},
5695
56
        {"evs.dynamic.payload.type", "evs", "rtp.pt", 10},
5696
56
        {"h263p.dynamic.payload.type", "h263p", "rtp.pt", 10},
5697
56
        {"h264.dynamic.payload.type", "h264", "rtp.pt", 10},
5698
56
        {"h265.dynamic.payload.type", "h265", "rtp.pt", 10},
5699
56
        {"ismacryp.dynamic.payload.type", "ismacryp", "rtp.pt", 10},
5700
56
        {"iuup.dynamic.payload.type", "iuup", "rtp.pt", 10},
5701
56
        {"lapd.rtp_payload_type", "lapd", "rtp.pt", 10},
5702
56
        {"mp4ves.dynamic.payload.type", "mp4ves", "rtp.pt", 10},
5703
56
        {"mtp2.rtp_payload_type", "mtp2", "rtp.pt", 10},
5704
56
        {"opus.dynamic.payload.type", "opus", "rtp.pt", 10},
5705
56
        {"rtp.rfc2198_payload_type", "rtp_rfc2198", "rtp.pt", 10},
5706
56
        {"rtpevent.event_payload_type_value", "rtpevent", "rtp.pt", 10},
5707
56
        {"rtpevent.cisco_nse_payload_type_value", "rtpevent", "rtp.pt", 10},
5708
56
        {"rtpmidi.midi_payload_type_value", "rtpmidi", "rtp.pt", 10},
5709
56
        {"vp8.dynamic.payload.type", "vp8", "rtp.pt", 10},
5710
        /* SCTP */
5711
56
        {"diameter.sctp.ports", "diameter", "sctp.port", 10},
5712
56
        {"sgsap.sctp_ports", "sgsap", "sctp.port", 10},
5713
        /* SCCP SSN */
5714
56
        {"pcap.ssn", "pcap", "sccp.ssn", 10},
5715
56
    };
5716
5717
    /* These are subdissectors of TPKT/OSITP that used to have a
5718
       TCP port preference even though they were never
5719
       directly on TCP.  Convert them to use Decode As
5720
       with the TPKT dissector handle */
5721
56
    struct port_pref_name tpkt_subdissector_port_prefs[] = {
5722
56
        {"dap.tcp.port", "dap", "tcp.port", 10},
5723
56
        {"disp.tcp.port", "disp", "tcp.port", 10},
5724
56
        {"dop.tcp.port", "dop", "tcp.port", 10},
5725
56
        {"dsp.tcp.port", "dsp", "tcp.port", 10},
5726
56
        {"p1.tcp.port", "p1", "tcp.port", 10},
5727
56
        {"p7.tcp.port", "p7", "tcp.port", 10},
5728
56
        {"rdp.tcp.port", "rdp", "tcp.port", 10},
5729
56
    };
5730
5731
    /* These are obsolete preferences from the dissectors' view,
5732
       (typically because of a switch from a single value to a
5733
       range value) but the name of the preference conflicts
5734
       with the generated preference name from the dissector table.
5735
       Don't allow the obsolete preference through to be handled */
5736
56
    struct obsolete_pref_name obsolete_prefs[] = {
5737
56
        {"diameter.tcp.port"},
5738
56
        {"kafka.tcp.port"},
5739
56
        {"mrcpv2.tcp.port"},
5740
56
        {"rtsp.tcp.port"},
5741
56
        {"sip.tcp.port"},
5742
56
        {"t38.tcp.port"},
5743
56
    };
5744
5745
56
    unsigned int i;
5746
56
    unsigned uval;
5747
56
    dissector_table_t sub_dissectors;
5748
56
    dissector_handle_t handle, tpkt_handle;
5749
56
    module_t *module;
5750
56
    pref_t *pref;
5751
5752
56
    static bool sanity_checked;
5753
56
    if (!sanity_checked) {
5754
14
        sanity_checked = true;
5755
840
        for (i = 0; i < G_N_ELEMENTS(port_prefs); i++) {
5756
826
            module = prefs_find_module(port_prefs[i].module_name);
5757
826
            if (!module) {
5758
0
                ws_warning("Deprecated ports pref check - module '%s' not found", port_prefs[i].module_name);
5759
0
                continue;
5760
0
            }
5761
826
            pref = prefs_find_preference(module, port_prefs[i].table_name);
5762
826
            if (!pref) {
5763
0
                ws_warning("Deprecated ports pref '%s.%s' not found", module->name, port_prefs[i].table_name);
5764
0
                continue;
5765
0
            }
5766
826
            if (pref->type != PREF_DECODE_AS_RANGE) {
5767
0
                ws_warning("Deprecated ports pref '%s.%s' has wrong type: %#x (%s)", module->name, port_prefs[i].table_name, pref->type, prefs_pref_type_name(pref));
5768
0
            }
5769
826
        }
5770
14
    }
5771
5772
3.36k
    for (i = 0; i < G_N_ELEMENTS(port_prefs); i++) {
5773
3.30k
        if (strcmp(pref_name, port_prefs[i].pref_name) == 0) {
5774
0
            if (!ws_basestrtou32(value, NULL, &uval, port_prefs[i].base))
5775
0
                return false;        /* number was bad */
5776
5777
0
            module = prefs_find_module(port_prefs[i].module_name);
5778
0
            pref = prefs_find_preference(module, port_prefs[i].table_name);
5779
0
            if (pref != NULL) {
5780
0
                module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5781
0
                if (pref->type == PREF_DECODE_AS_RANGE) {
5782
                    // The legacy preference was a port number, but the new
5783
                    // preference is a port range. Add to existing range.
5784
0
                    if (uval) {
5785
0
                        prefs_range_add_value(pref, uval);
5786
0
                    }
5787
0
                }
5788
0
            }
5789
5790
            /* If the value is zero, it wouldn't add to the Decode As tables */
5791
0
            if (uval != 0)
5792
0
            {
5793
0
                sub_dissectors = find_dissector_table(port_prefs[i].table_name);
5794
0
                if (sub_dissectors != NULL) {
5795
0
                    handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5796
0
                    if (handle != NULL) {
5797
0
                        dissector_change_uint(port_prefs[i].table_name, uval, handle);
5798
0
                        decode_build_reset_list(port_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval), NULL, NULL);
5799
0
                    }
5800
0
                }
5801
0
            }
5802
5803
0
            return true;
5804
0
        }
5805
3.30k
    }
5806
5807
2.91k
    for (i = 0; i < array_length(port_range_prefs); i++)
5808
2.85k
    {
5809
2.85k
        if (strcmp(pref_name, port_range_prefs[i].pref_name) == 0)
5810
0
        {
5811
0
            uint32_t range_i, range_j;
5812
5813
0
            sub_dissectors = find_dissector_table(port_range_prefs[i].table_name);
5814
0
            if (sub_dissectors != NULL) {
5815
0
                switch (dissector_table_get_type(sub_dissectors)) {
5816
0
                case FT_UINT8:
5817
0
                case FT_UINT16:
5818
0
                case FT_UINT24:
5819
0
                case FT_UINT32:
5820
0
                    break;
5821
5822
0
                default:
5823
0
                    ws_error("The dissector table %s (%s) is not an integer type - are you using a buggy plugin?", port_range_prefs[i].table_name, get_dissector_table_ui_name(port_range_prefs[i].table_name));
5824
0
                    ws_assert_not_reached();
5825
0
                }
5826
5827
0
                module = prefs_find_module(port_range_prefs[i].module_name);
5828
0
                pref = prefs_find_preference(module, port_range_prefs[i].table_name);
5829
0
                if (pref != NULL)
5830
0
                {
5831
0
                    if (!prefs_set_range_value_work(pref, value, true, &module->prefs_changed_flags))
5832
0
                    {
5833
0
                        return false;        /* number was bad */
5834
0
                    }
5835
5836
0
                    handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5837
0
                    if (handle != NULL) {
5838
5839
0
                        for (range_i = 0; range_i < (*pref->varp.range)->nranges; range_i++) {
5840
0
                            for (range_j = (*pref->varp.range)->ranges[range_i].low; range_j < (*pref->varp.range)->ranges[range_i].high; range_j++) {
5841
0
                                dissector_change_uint(port_range_prefs[i].table_name, range_j, handle);
5842
0
                                decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(range_j), NULL, NULL);
5843
0
                            }
5844
5845
0
                            dissector_change_uint(port_range_prefs[i].table_name, (*pref->varp.range)->ranges[range_i].high, handle);
5846
0
                            decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[range_i].high), NULL, NULL);
5847
0
                        }
5848
0
                    }
5849
0
                }
5850
0
            }
5851
5852
0
            return true;
5853
0
        }
5854
2.85k
    }
5855
5856
448
    for (i = 0; i < array_length(tpkt_subdissector_port_prefs); i++)
5857
392
    {
5858
392
        if (strcmp(pref_name, tpkt_subdissector_port_prefs[i].pref_name) == 0)
5859
0
        {
5860
            /* XXX - give an error if it doesn't fit in a unsigned? */
5861
0
            if (!ws_basestrtou32(value, NULL, &uval, tpkt_subdissector_port_prefs[i].base))
5862
0
                return false;        /* number was bad */
5863
5864
            /* If the value is 0 or 102 (default TPKT port), don't add to the Decode As tables */
5865
0
            if ((uval != 0) && (uval != 102))
5866
0
            {
5867
0
                tpkt_handle = find_dissector("tpkt");
5868
0
                if (tpkt_handle != NULL) {
5869
0
                    dissector_change_uint(tpkt_subdissector_port_prefs[i].table_name, uval, tpkt_handle);
5870
0
                }
5871
0
            }
5872
5873
0
            return true;
5874
0
        }
5875
392
    }
5876
5877
392
    for (i = 0; i < array_length(obsolete_prefs); i++)
5878
336
    {
5879
336
        if (strcmp(pref_name, obsolete_prefs[i].pref_name) == 0)
5880
0
        {
5881
            /* Just ignore the preference */
5882
0
            return true;
5883
0
        }
5884
336
    }
5885
56
    return false;
5886
56
}
5887
5888
static prefs_set_pref_e
5889
set_pref(char *pref_name, const char *value, void *private_data,
5890
         bool return_range_errors)
5891
56
{
5892
56
    unsigned cval;
5893
56
    unsigned uval;
5894
56
    bool     bval;
5895
56
    int      enum_val;
5896
56
    char     *dotp, *last_dotp;
5897
56
    static char *filter_label = NULL;
5898
56
    static bool filter_enabled = false;
5899
56
    module_t *module, *containing_module, *target_module;
5900
56
    pref_t   *pref;
5901
56
    bool converted_pref = false;
5902
5903
56
    target_module = (module_t*)private_data;
5904
5905
    //The PRS_GUI field names are here for backwards compatibility
5906
    //display filters have been converted to a UAT.
5907
56
    if (strcmp(pref_name, PRS_GUI_FILTER_LABEL) == 0) {
5908
        /* Assume that PRS_GUI_FILTER_EXPR follows this preference. In case of
5909
         * malicious preference files, free the previous value to limit the size
5910
         * of leaked memory.  */
5911
0
        g_free(filter_label);
5912
0
        filter_label = g_strdup(value);
5913
56
    } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED) == 0) {
5914
0
        filter_enabled = (strcmp(value, "TRUE") == 0) ? true : false;
5915
56
    } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR) == 0) {
5916
        /* Comments not supported for "old" preference style */
5917
0
        filter_expression_new(filter_label, value, "", filter_enabled);
5918
0
        g_free(filter_label);
5919
0
        filter_label = NULL;
5920
        /* Remember to save the new UAT to file. */
5921
0
        prefs.filter_expressions_old = true;
5922
56
    } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
5923
        /* Convert deprecated value to closest current equivalent */
5924
0
        if (g_ascii_strcasecmp(value, "true") == 0) {
5925
0
            prefs.gui_version_placement = version_both;
5926
0
        } else {
5927
0
            prefs.gui_version_placement = version_neither;
5928
0
        }
5929
56
    } else if (strcmp(pref_name, "name_resolve") == 0 ||
5930
56
               strcmp(pref_name, "capture.name_resolve") == 0) {
5931
        /*
5932
         * Handle the deprecated name resolution options.
5933
         *
5934
         * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
5935
         * RESOLV_ALL and RESOLV_NONE.
5936
         *
5937
         * Otherwise, we treat it as a list of name types we want to resolve.
5938
         */
5939
0
        if (g_ascii_strcasecmp(value, "true") == 0) {
5940
0
            gbl_resolv_flags.mac_name = true;
5941
0
            gbl_resolv_flags.network_name = true;
5942
0
            gbl_resolv_flags.transport_name = true;
5943
0
        }
5944
0
        else if (g_ascii_strcasecmp(value, "false") == 0) {
5945
0
            disable_name_resolution();
5946
0
        }
5947
0
        else {
5948
            /* start out with none set */
5949
0
            disable_name_resolution();
5950
0
            if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
5951
0
                return PREFS_SET_SYNTAX_ERR;
5952
0
        }
5953
56
    } else if (deprecated_heur_dissector_pref(pref_name, value)) {
5954
         /* Handled within deprecated_heur_dissector_pref() if found */
5955
56
    } else if (deprecated_enable_dissector_pref(pref_name, value)) {
5956
         /* Handled within deprecated_enable_dissector_pref() if found */
5957
56
    } else if (deprecated_port_pref(pref_name, value)) {
5958
         /* Handled within deprecated_port_pref() if found */
5959
56
    } else if (strcmp(pref_name, "console.log.level") == 0) {
5960
        /* Handled on the command line within ws_log_parse_args() */
5961
0
        return PREFS_SET_OK;
5962
56
    } else {
5963
        /* Handle deprecated "global" options that don't have a module
5964
         * associated with them
5965
         */
5966
56
        if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
5967
56
            (strcmp(pref_name, "name_resolve_load_smi_modules") == 0)  ||
5968
56
            (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
5969
0
            module = nameres_module;
5970
0
            dotp = pref_name;
5971
56
        } else {
5972
            /* To which module does this preference belong? */
5973
56
            module = NULL;
5974
56
            last_dotp = pref_name;
5975
112
            while (!module) {
5976
56
                dotp = strchr(last_dotp, '.');
5977
56
                if (dotp == NULL) {
5978
                    /* Either there's no such module, or no module was specified.
5979
                       In either case, that means there's no such preference. */
5980
0
                    return PREFS_SET_NO_SUCH_PREF;
5981
0
                }
5982
56
                *dotp = '\0'; /* separate module and preference name */
5983
56
                module = prefs_find_module(pref_name);
5984
5985
                /*
5986
                 * XXX - "Diameter" rather than "diameter" was used in earlier
5987
                 * versions of Wireshark; if we didn't find the module, and its name
5988
                 * was "Diameter", look for "diameter" instead.
5989
                 *
5990
                 * In addition, the BEEP protocol used to be the BXXP protocol,
5991
                 * so if we didn't find the module, and its name was "bxxp",
5992
                 * look for "beep" instead.
5993
                 *
5994
                 * Also, the preferences for GTP v0 and v1 were combined under
5995
                 * a single "gtp" heading, and the preferences for SMPP were
5996
                 * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
5997
                 * However, SMPP now has its own preferences, so we just map
5998
                 * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
5999
                 *
6000
                 * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
6001
                 * and "nsip" to "gprs_ns".
6002
                 *
6003
                 * The SynOptics Network Management Protocol (SONMP) is now known by
6004
                 * its modern name, the Nortel Discovery Protocol (NDP).
6005
                 */
6006
56
                if (module == NULL) {
6007
                    /*
6008
                     * See if there's a backwards-compatibility name
6009
                     * that maps to this module.
6010
                     */
6011
0
                    module = prefs_find_module_alias(pref_name);
6012
0
                    if (module == NULL) {
6013
                        /*
6014
                         * There's no alias for the module; see if the
6015
                         * module name matches any protocol aliases.
6016
                         */
6017
0
                        header_field_info *hfinfo = proto_registrar_get_byalias(pref_name);
6018
0
                        if (hfinfo) {
6019
0
                            module = (module_t *) wmem_tree_lookup_string(prefs_modules, hfinfo->abbrev, WMEM_TREE_STRING_NOCASE);
6020
0
                        }
6021
0
                    }
6022
0
                    if (module == NULL) {
6023
                        /*
6024
                         * There aren't any aliases.  Was the module
6025
                         * removed rather than renamed?
6026
                         */
6027
0
                        if (strcmp(pref_name, "etheric") == 0 ||
6028
0
                            strcmp(pref_name, "isup_thin") == 0) {
6029
                            /*
6030
                             * The dissectors for these protocols were
6031
                             * removed as obsolete on 2009-07-70 in change
6032
                             * 739bfc6ff035583abb9434e0e988048de38a8d9a.
6033
                             */
6034
0
                            return PREFS_SET_OBSOLETE;
6035
0
                        }
6036
0
                    }
6037
0
                    if (module) {
6038
0
                        converted_pref = true;
6039
0
                        prefs.unknown_prefs = true;
6040
0
                    }
6041
0
                }
6042
56
                *dotp = '.';                /* put the preference string back */
6043
56
                dotp++;                     /* skip past separator to preference name */
6044
56
                last_dotp = dotp;
6045
56
            }
6046
56
        }
6047
6048
        /* The pref is located in the module or a submodule.
6049
         * Assume module, then search for a submodule holding the pref. */
6050
56
        containing_module = module;
6051
56
        pref = prefs_find_preference_with_submodule(module, dotp, &containing_module);
6052
6053
56
        if (pref == NULL) {
6054
0
            prefs.unknown_prefs = true;
6055
6056
            /* "gui" prefix was added to column preferences for better organization
6057
             * within the preferences file
6058
             */
6059
0
            if (module == gui_column_module) {
6060
                /* While this has a subtree, there is no apply callback, so no
6061
                 * need to use prefs_find_preference_with_submodule to update
6062
                 * containing_module. It would not be useful. */
6063
0
                pref = prefs_find_preference(module, pref_name);
6064
0
            }
6065
0
            else if (strcmp(module->name, "mgcp") == 0) {
6066
                /*
6067
                 * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
6068
                 * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
6069
                 * were used in earlier versions of Wireshark; if we didn't find the
6070
                 * preference, it was an MGCP preference, and its name was
6071
                 * "display raw text toggle" or "display dissect tree", look for
6072
                 * "display_raw_text" or "display_dissect_tree" instead.
6073
                 *
6074
                 * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
6075
                 * the gateway and callagent ports were given those names; we interpret
6076
                 * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
6077
                 * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
6078
                 * they were registered by the MCCP dissector and thus that's the
6079
                 * order in which they were written to the preferences file.  (If
6080
                 * we're not reading the preferences file, but are handling stuff
6081
                 * from a "-o" command-line option, we have no clue which the user
6082
                 * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
6083
                 * or "mgcp.{tcp,udp}.callagent_port" instead.)
6084
                 */
6085
0
                if (strcmp(dotp, "display raw text toggle") == 0)
6086
0
                    pref = prefs_find_preference(module, "display_raw_text");
6087
0
                else if (strcmp(dotp, "display dissect tree") == 0)
6088
0
                    pref = prefs_find_preference(module, "display_dissect_tree");
6089
0
                else if (strcmp(dotp, "tcp.port") == 0) {
6090
0
                    mgcp_tcp_port_count++;
6091
0
                    if (mgcp_tcp_port_count == 1) {
6092
                        /* It's the first one */
6093
0
                        pref = prefs_find_preference(module, "tcp.gateway_port");
6094
0
                    } else if (mgcp_tcp_port_count == 2) {
6095
                        /* It's the second one */
6096
0
                        pref = prefs_find_preference(module, "tcp.callagent_port");
6097
0
                    }
6098
                    /* Otherwise it's from the command line, and we don't bother
6099
                       mapping it. */
6100
0
                } else if (strcmp(dotp, "udp.port") == 0) {
6101
0
                    mgcp_udp_port_count++;
6102
0
                    if (mgcp_udp_port_count == 1) {
6103
                        /* It's the first one */
6104
0
                        pref = prefs_find_preference(module, "udp.gateway_port");
6105
0
                    } else if (mgcp_udp_port_count == 2) {
6106
                        /* It's the second one */
6107
0
                        pref = prefs_find_preference(module, "udp.callagent_port");
6108
0
                    }
6109
                    /* Otherwise it's from the command line, and we don't bother
6110
                       mapping it. */
6111
0
                }
6112
0
            } else if (strcmp(module->name, "smb") == 0) {
6113
                /* Handle old names for SMB preferences. */
6114
0
                if (strcmp(dotp, "smb.trans.reassembly") == 0)
6115
0
                    pref = prefs_find_preference(module, "trans_reassembly");
6116
0
                else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
6117
0
                    pref = prefs_find_preference(module, "dcerpc_reassembly");
6118
0
            } else if (strcmp(module->name, "ndmp") == 0) {
6119
                /* Handle old names for NDMP preferences. */
6120
0
                if (strcmp(dotp, "ndmp.desegment") == 0)
6121
0
                    pref = prefs_find_preference(module, "desegment");
6122
0
            } else if (strcmp(module->name, "diameter") == 0) {
6123
                /* Handle old names for Diameter preferences. */
6124
0
                if (strcmp(dotp, "diameter.desegment") == 0)
6125
0
                    pref = prefs_find_preference(module, "desegment");
6126
0
            } else if (strcmp(module->name, "pcli") == 0) {
6127
                /* Handle old names for PCLI preferences. */
6128
0
                if (strcmp(dotp, "pcli.udp_port") == 0)
6129
0
                    pref = prefs_find_preference(module, "udp_port");
6130
0
            } else if (strcmp(module->name, "artnet") == 0) {
6131
                /* Handle old names for ARTNET preferences. */
6132
0
                if (strcmp(dotp, "artnet.udp_port") == 0)
6133
0
                    pref = prefs_find_preference(module, "udp_port");
6134
0
            } else if (strcmp(module->name, "mapi") == 0) {
6135
                /* Handle old names for MAPI preferences. */
6136
0
                if (strcmp(dotp, "mapi_decrypt") == 0)
6137
0
                    pref = prefs_find_preference(module, "decrypt");
6138
0
            } else if (strcmp(module->name, "fc") == 0) {
6139
                /* Handle old names for Fibre Channel preferences. */
6140
0
                if (strcmp(dotp, "reassemble_fc") == 0)
6141
0
                    pref = prefs_find_preference(module, "reassemble");
6142
0
                else if (strcmp(dotp, "fc_max_frame_size") == 0)
6143
0
                    pref = prefs_find_preference(module, "max_frame_size");
6144
0
            } else if (strcmp(module->name, "fcip") == 0) {
6145
                /* Handle old names for Fibre Channel-over-IP preferences. */
6146
0
                if (strcmp(dotp, "desegment_fcip_messages") == 0)
6147
0
                    pref = prefs_find_preference(module, "desegment");
6148
0
                else if (strcmp(dotp, "fcip_port") == 0)
6149
0
                    pref = prefs_find_preference(module, "target_port");
6150
0
            } else if (strcmp(module->name, "gtp") == 0) {
6151
                /* Handle old names for GTP preferences. */
6152
0
                if (strcmp(dotp, "gtpv0_port") == 0)
6153
0
                    pref = prefs_find_preference(module, "v0_port");
6154
0
                else if (strcmp(dotp, "gtpv1c_port") == 0)
6155
0
                    pref = prefs_find_preference(module, "v1c_port");
6156
0
                else if (strcmp(dotp, "gtpv1u_port") == 0)
6157
0
                    pref = prefs_find_preference(module, "v1u_port");
6158
0
                else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
6159
0
                    pref = prefs_find_preference(module, "dissect_tpdu");
6160
0
                else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
6161
0
                    pref = prefs_find_preference(module, "v0_dissect_cdr_as");
6162
0
                else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
6163
0
                    pref = prefs_find_preference(module, "v0_check_etsi");
6164
0
                else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
6165
0
                    pref = prefs_find_preference(module, "v1_check_etsi");
6166
0
            } else if (strcmp(module->name, "ip") == 0) {
6167
                /* Handle old names for IP preferences. */
6168
0
                if (strcmp(dotp, "ip_summary_in_tree") == 0)
6169
0
                    pref = prefs_find_preference(module, "summary_in_tree");
6170
0
            } else if (strcmp(module->name, "iscsi") == 0) {
6171
                /* Handle old names for iSCSI preferences. */
6172
0
                if (strcmp(dotp, "iscsi_port") == 0)
6173
0
                    pref = prefs_find_preference(module, "target_port");
6174
0
            } else if (strcmp(module->name, "lmp") == 0) {
6175
                /* Handle old names for LMP preferences. */
6176
0
                if (strcmp(dotp, "lmp_version") == 0)
6177
0
                    pref = prefs_find_preference(module, "version");
6178
0
            } else if (strcmp(module->name, "mtp3") == 0) {
6179
                /* Handle old names for MTP3 preferences. */
6180
0
                if (strcmp(dotp, "mtp3_standard") == 0)
6181
0
                    pref = prefs_find_preference(module, "standard");
6182
0
                else if (strcmp(dotp, "net_addr_format") == 0)
6183
0
                    pref = prefs_find_preference(module, "addr_format");
6184
0
            } else if (strcmp(module->name, "nlm") == 0) {
6185
                /* Handle old names for NLM preferences. */
6186
0
                if (strcmp(dotp, "nlm_msg_res_matching") == 0)
6187
0
                    pref = prefs_find_preference(module, "msg_res_matching");
6188
0
            } else if (strcmp(module->name, "ppp") == 0) {
6189
                /* Handle old names for PPP preferences. */
6190
0
                if (strcmp(dotp, "ppp_fcs") == 0)
6191
0
                    pref = prefs_find_preference(module, "fcs_type");
6192
0
                else if (strcmp(dotp, "ppp_vj") == 0)
6193
0
                    pref = prefs_find_preference(module, "decompress_vj");
6194
0
            } else if (strcmp(module->name, "rsvp") == 0) {
6195
                /* Handle old names for RSVP preferences. */
6196
0
                if (strcmp(dotp, "rsvp_process_bundle") == 0)
6197
0
                    pref = prefs_find_preference(module, "process_bundle");
6198
0
            } else if (strcmp(module->name, "tcp") == 0) {
6199
                /* Handle old names for TCP preferences. */
6200
0
                if (strcmp(dotp, "tcp_summary_in_tree") == 0)
6201
0
                    pref = prefs_find_preference(module, "summary_in_tree");
6202
0
                else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
6203
0
                    pref = prefs_find_preference(module, "analyze_sequence_numbers");
6204
0
                else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
6205
0
                    pref = prefs_find_preference(module, "relative_sequence_numbers");
6206
0
                else if (strcmp(dotp, "dissect_experimental_options_with_magic") == 0)
6207
0
                    pref = prefs_find_preference(module, "dissect_experimental_options_rfc6994");
6208
0
            } else if (strcmp(module->name, "udp") == 0) {
6209
                /* Handle old names for UDP preferences. */
6210
0
                if (strcmp(dotp, "udp_summary_in_tree") == 0)
6211
0
                    pref = prefs_find_preference(module, "summary_in_tree");
6212
0
            } else if (strcmp(module->name, "ndps") == 0) {
6213
                /* Handle old names for NDPS preferences. */
6214
0
                if (strcmp(dotp, "desegment_ndps") == 0)
6215
0
                    pref = prefs_find_preference(module, "desegment_tcp");
6216
0
            } else if (strcmp(module->name, "http") == 0) {
6217
                /* Handle old names for HTTP preferences. */
6218
0
                if (strcmp(dotp, "desegment_http_headers") == 0)
6219
0
                    pref = prefs_find_preference(module, "desegment_headers");
6220
0
                else if (strcmp(dotp, "desegment_http_body") == 0)
6221
0
                    pref = prefs_find_preference(module, "desegment_body");
6222
0
            } else if (strcmp(module->name, "smpp") == 0) {
6223
                /* Handle preferences that moved from SMPP. */
6224
0
                module_t *new_module = prefs_find_module("gsm-sms-ud");
6225
0
                if (new_module) {
6226
0
                    if (strcmp(dotp, "port_number_udh_means_wsp") == 0) {
6227
0
                        pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
6228
0
                        containing_module = new_module;
6229
0
                    } else if (strcmp(dotp, "try_dissect_1st_fragment") == 0) {
6230
0
                        pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
6231
0
                        containing_module = new_module;
6232
0
                    }
6233
0
                }
6234
0
            } else if (strcmp(module->name, "asn1") == 0) {
6235
                /* Handle old generic ASN.1 preferences (it's not really a
6236
                   rename, as the new preferences support multiple ports,
6237
                   but we might as well copy them over). */
6238
0
                if (strcmp(dotp, "tcp_port") == 0)
6239
0
                    pref = prefs_find_preference(module, "tcp_ports");
6240
0
                else if (strcmp(dotp, "udp_port") == 0)
6241
0
                    pref = prefs_find_preference(module, "udp_ports");
6242
0
                else if (strcmp(dotp, "sctp_port") == 0)
6243
0
                    pref = prefs_find_preference(module, "sctp_ports");
6244
0
            } else if (strcmp(module->name, "llcgprs") == 0) {
6245
0
                if (strcmp(dotp, "ignore_cipher_bit") == 0)
6246
0
                    pref = prefs_find_preference(module, "autodetect_cipher_bit");
6247
0
            } else if (strcmp(module->name, "erf") == 0) {
6248
0
                if (strcmp(dotp, "erfeth") == 0) {
6249
                    /* Handle the old "erfeth" preference; map it to the new
6250
                       "ethfcs" preference, and map the values to those for
6251
                       the new preference. */
6252
0
                    pref = prefs_find_preference(module, "ethfcs");
6253
0
                    if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
6254
0
                        value = "TRUE";
6255
0
                    else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
6256
0
                        value = "FALSE";
6257
0
                    else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6258
0
                        value = "TRUE";
6259
0
                } else if (strcmp(dotp, "erfatm") == 0) {
6260
                    /* Handle the old "erfatm" preference; map it to the new
6261
                       "aal5_type" preference, and map the values to those for
6262
                       the new preference. */
6263
0
                    pref = prefs_find_preference(module, "aal5_type");
6264
0
                    if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
6265
0
                        value = "guess";
6266
0
                    else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
6267
0
                        value = "llc";
6268
0
                    else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6269
0
                        value = "guess";
6270
0
                } else if (strcmp(dotp, "erfhdlc") == 0) {
6271
                    /* Handle the old "erfhdlc" preference; map it to the new
6272
                       "hdlc_type" preference, and map the values to those for
6273
                       the new preference. */
6274
0
                    pref = prefs_find_preference(module, "hdlc_type");
6275
0
                    if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
6276
0
                        value = "chdlc";
6277
0
                    else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
6278
0
                        value = "ppp";
6279
0
                    else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
6280
0
                        value = "frelay";
6281
0
                    else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
6282
0
                        value = "mtp2";
6283
0
                    else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6284
0
                        value = "guess";
6285
0
                }
6286
0
            } else if (strcmp(module->name, "eth") == 0) {
6287
                /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
6288
0
                if (strcmp(dotp, "qinq_ethertype") == 0) {
6289
0
                    module_t *new_module = prefs_find_module("vlan");
6290
0
                    if (new_module) {
6291
0
                        pref = prefs_find_preference(new_module, "qinq_ethertype");
6292
0
                        containing_module = new_module;
6293
0
                    }
6294
0
                }
6295
0
            } else if (strcmp(module->name, "taps") == 0) {
6296
                /* taps preferences moved to "statistics" module */
6297
0
                if (strcmp(dotp, "update_interval") == 0)
6298
0
                    pref = prefs_find_preference(stats_module, dotp);
6299
0
            } else if (strcmp(module->name, "packet_list") == 0) {
6300
                /* packet_list preferences moved to protocol module */
6301
0
                if (strcmp(dotp, "display_hidden_proto_items") == 0)
6302
0
                    pref = prefs_find_preference(protocols_module, dotp);
6303
0
            } else if (strcmp(module->name, "stream") == 0) {
6304
                /* stream preferences moved to gui color module */
6305
0
                if ((strcmp(dotp, "client.fg") == 0) ||
6306
0
                    (strcmp(dotp, "client.bg") == 0) ||
6307
0
                    (strcmp(dotp, "server.fg") == 0) ||
6308
0
                    (strcmp(dotp, "server.bg") == 0))
6309
0
                    pref = prefs_find_preference(gui_color_module, pref_name);
6310
0
            } else if (strcmp(module->name, "nameres") == 0) {
6311
0
                if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
6312
0
                    pref = prefs_find_preference(nameres_module, pref_name);
6313
0
                } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
6314
0
                    pref = prefs_find_preference(nameres_module, "load_smi_modules");
6315
0
                } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
6316
0
                    pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
6317
0
                }
6318
0
            } else if (strcmp(module->name, "extcap") == 0) {
6319
                /* Handle the old "sshdump.remotesudo" preference; map it to the new
6320
                  "sshdump.remotepriv" preference, and map the boolean values to the
6321
                  appropriate strings of the new preference. */
6322
0
                if (strcmp(dotp, "sshdump.remotesudo") == 0) {
6323
0
                    pref = prefs_find_preference(module, "sshdump.remotepriv");
6324
0
                    if (g_ascii_strcasecmp(value, "true") == 0)
6325
0
                        value = "sudo";
6326
0
                    else
6327
0
                        value = "none";
6328
0
                }
6329
0
            }
6330
0
            if (pref) {
6331
0
                converted_pref = true;
6332
0
            }
6333
0
        }
6334
56
        if (pref == NULL ) {
6335
0
            if (strcmp(module->name, "extcap") == 0 && g_list_length(module->prefs) <= 1) {
6336
                    /*
6337
                    * Assume that we've skipped extcap preference registration
6338
                    * and that only extcap.gui_save_on_start is loaded.
6339
                    */
6340
0
                    return PREFS_SET_OK;
6341
0
                }
6342
0
            return PREFS_SET_NO_SUCH_PREF;    /* no such preference */
6343
0
        }
6344
6345
56
        if (target_module && target_module != containing_module) {
6346
            /* Ignore */
6347
0
            return PREFS_SET_OK;
6348
0
        }
6349
6350
56
        if (pref->obsolete)
6351
0
            return PREFS_SET_OBSOLETE;        /* no such preference any more */
6352
6353
56
        if (converted_pref) {
6354
0
            ws_warning("Preference \"%s\" has been converted to \"%s.%s\"\n"
6355
0
                       "Save your preferences to make this change permanent.",
6356
0
                       pref_name, module->name ? module->name : module->parent->name, prefs_get_name(pref));
6357
0
        }
6358
6359
56
        switch (pref->type) {
6360
6361
0
        case PREF_UINT:
6362
0
            if (!ws_basestrtou32(value, NULL, &uval, pref->info.base))
6363
0
                return PREFS_SET_SYNTAX_ERR;        /* number was bad */
6364
0
            if (*pref->varp.uint != uval) {
6365
0
                containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6366
0
                *pref->varp.uint = uval;
6367
0
            }
6368
0
            break;
6369
56
        case PREF_BOOL:
6370
            /* XXX - give an error if it's neither "true" nor "false"? */
6371
56
            if (g_ascii_strcasecmp(value, "true") == 0)
6372
0
                bval = true;
6373
56
            else
6374
56
                bval = false;
6375
56
            if (*pref->varp.boolp != bval) {
6376
56
                containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6377
56
                *pref->varp.boolp = bval;
6378
56
            }
6379
56
            break;
6380
6381
0
        case PREF_ENUM:
6382
            /* XXX - give an error if it doesn't match? */
6383
0
            enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
6384
0
                                           *pref->varp.enump);
6385
0
            if (*pref->varp.enump != enum_val) {
6386
0
                containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6387
0
                *pref->varp.enump = enum_val;
6388
0
            }
6389
0
            break;
6390
6391
0
        case PREF_STRING:
6392
0
        case PREF_SAVE_FILENAME:
6393
0
        case PREF_OPEN_FILENAME:
6394
0
        case PREF_DIRNAME:
6395
0
        case PREF_DISSECTOR:
6396
0
            containing_module->prefs_changed_flags |= prefs_set_string_value(pref, value, pref_current);
6397
0
            break;
6398
6399
0
        case PREF_PASSWORD:
6400
            /* Read value is every time empty */
6401
0
            containing_module->prefs_changed_flags |= prefs_set_string_value(pref, "", pref_current);
6402
0
            break;
6403
6404
0
        case PREF_RANGE:
6405
0
        {
6406
0
            if (!prefs_set_range_value_work(pref, value, return_range_errors,
6407
0
                                            &containing_module->prefs_changed_flags))
6408
0
                return PREFS_SET_SYNTAX_ERR;        /* number was bad */
6409
0
            break;
6410
0
        }
6411
0
        case PREF_DECODE_AS_RANGE:
6412
0
        {
6413
            /* This is for backwards compatibility in case any of the preferences
6414
               that shared the "Decode As" preference name and used to be PREF_RANGE
6415
               are now applied directly to the Decode As funtionality */
6416
0
            range_t *newrange;
6417
0
            dissector_table_t sub_dissectors;
6418
0
            dissector_handle_t handle;
6419
0
            uint32_t i, j;
6420
6421
0
            if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
6422
0
                                       return_range_errors) != CVT_NO_ERROR) {
6423
0
                return PREFS_SET_SYNTAX_ERR;        /* number was bad */
6424
0
            }
6425
6426
0
            if (!ranges_are_equal(*pref->varp.range, newrange)) {
6427
0
                wmem_free(wmem_epan_scope(), *pref->varp.range);
6428
0
                *pref->varp.range = newrange;
6429
0
                containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6430
6431
0
                const char* table_name = prefs_get_dissector_table(pref);
6432
0
                sub_dissectors = find_dissector_table(table_name);
6433
0
                if (sub_dissectors != NULL) {
6434
0
                    handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
6435
0
                    if (handle != NULL) {
6436
                        /* Delete all of the old values from the dissector table */
6437
0
                        for (i = 0; i < (*pref->varp.range)->nranges; i++) {
6438
0
                            for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
6439
0
                                dissector_delete_uint(table_name, j, handle);
6440
0
                                decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
6441
0
                            }
6442
6443
0
                            dissector_delete_uint(table_name, (*pref->varp.range)->ranges[i].high, handle);
6444
0
                            decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
6445
0
                        }
6446
6447
                        /* Add new values to the dissector table */
6448
0
                        for (i = 0; i < newrange->nranges; i++) {
6449
0
                            for (j = newrange->ranges[i].low; j < newrange->ranges[i].high; j++) {
6450
0
                                dissector_change_uint(table_name, j, handle);
6451
0
                                decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
6452
0
                            }
6453
6454
0
                            dissector_change_uint(table_name, newrange->ranges[i].high, handle);
6455
0
                            decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(newrange->ranges[i].high), NULL, NULL);
6456
0
                        }
6457
6458
                        /* XXX - Do we save the decode_as_entries file here? */
6459
0
                    }
6460
0
                }
6461
0
            } else {
6462
0
                wmem_free(wmem_epan_scope(), newrange);
6463
0
            }
6464
0
            break;
6465
0
        }
6466
6467
0
        case PREF_COLOR:
6468
0
        {
6469
0
            if (!ws_hexstrtou32(value, NULL, &cval))
6470
0
                return PREFS_SET_SYNTAX_ERR;        /* number was bad */
6471
0
            if ((pref->varp.colorp->red != RED_COMPONENT(cval)) ||
6472
0
                (pref->varp.colorp->green != GREEN_COMPONENT(cval)) ||
6473
0
                (pref->varp.colorp->blue != BLUE_COMPONENT(cval))) {
6474
0
                containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6475
0
                pref->varp.colorp->red   = RED_COMPONENT(cval);
6476
0
                pref->varp.colorp->green = GREEN_COMPONENT(cval);
6477
0
                pref->varp.colorp->blue  = BLUE_COMPONENT(cval);
6478
0
            }
6479
0
            break;
6480
0
        }
6481
6482
0
        case PREF_CUSTOM:
6483
0
            return pref->custom_cbs.set_cb(pref, value, &containing_module->prefs_changed_flags);
6484
6485
0
        case PREF_STATIC_TEXT:
6486
0
        case PREF_UAT:
6487
0
            break;
6488
6489
0
        case PREF_PROTO_TCP_SNDAMB_ENUM:
6490
0
        {
6491
            /* There's no point in setting the TCP sequence override
6492
             * value from the command line, because the pref is different
6493
             * for each frame and reset to the default (0) for each new
6494
             * file.
6495
             */
6496
0
            break;
6497
0
        }
6498
56
        }
6499
56
    }
6500
6501
56
    return PREFS_SET_OK;
6502
56
}
6503
6504
typedef struct {
6505
    FILE     *pf;
6506
    bool is_gui_module;
6507
} write_gui_pref_arg_t;
6508
6509
const char *
6510
prefs_pref_type_name(pref_t *pref)
6511
0
{
6512
0
    const char *type_name = "[Unknown]";
6513
6514
0
    if (!pref) {
6515
0
        return type_name; /* ...or maybe assert? */
6516
0
    }
6517
6518
0
    if (pref->obsolete) {
6519
0
        type_name = "Obsolete";
6520
0
    } else {
6521
0
        switch (pref->type) {
6522
6523
0
        case PREF_UINT:
6524
0
            switch (pref->info.base) {
6525
6526
0
            case 10:
6527
0
                type_name = "Decimal";
6528
0
                break;
6529
6530
0
            case 8:
6531
0
                type_name = "Octal";
6532
0
                break;
6533
6534
0
            case 16:
6535
0
                type_name = "Hexadecimal";
6536
0
                break;
6537
0
            }
6538
0
            break;
6539
6540
0
        case PREF_BOOL:
6541
0
            type_name = "Boolean";
6542
0
            break;
6543
6544
0
        case PREF_ENUM:
6545
0
        case PREF_PROTO_TCP_SNDAMB_ENUM:
6546
0
            type_name = "Choice";
6547
0
            break;
6548
6549
0
        case PREF_STRING:
6550
0
            type_name = "String";
6551
0
            break;
6552
6553
0
        case PREF_SAVE_FILENAME:
6554
0
        case PREF_OPEN_FILENAME:
6555
0
            type_name = "Filename";
6556
0
            break;
6557
6558
0
        case PREF_DIRNAME:
6559
0
            type_name = "Directory";
6560
0
            break;
6561
6562
0
        case PREF_RANGE:
6563
0
            type_name = "Range";
6564
0
            break;
6565
6566
0
        case PREF_COLOR:
6567
0
            type_name = "Color";
6568
0
            break;
6569
6570
0
        case PREF_CUSTOM:
6571
0
            if (pref->custom_cbs.type_name_cb)
6572
0
                return pref->custom_cbs.type_name_cb();
6573
0
            type_name = "Custom";
6574
0
            break;
6575
6576
0
        case PREF_DECODE_AS_RANGE:
6577
0
            type_name = "Range (for Decode As)";
6578
0
            break;
6579
6580
0
        case PREF_STATIC_TEXT:
6581
0
            type_name = "Static text";
6582
0
            break;
6583
6584
0
        case PREF_UAT:
6585
0
            type_name = "UAT";
6586
0
            break;
6587
6588
0
        case PREF_PASSWORD:
6589
0
            type_name = "Password";
6590
0
            break;
6591
6592
0
        case PREF_DISSECTOR:
6593
0
            type_name = "Dissector";
6594
0
            break;
6595
0
        }
6596
0
    }
6597
6598
0
    return type_name;
6599
0
}
6600
6601
unsigned int
6602
prefs_get_effect_flags(pref_t *pref)
6603
70
{
6604
70
    if (pref == NULL)
6605
0
        return 0;
6606
6607
70
    return pref->effect_flags;
6608
70
}
6609
6610
void
6611
prefs_set_effect_flags(pref_t *pref, unsigned int flags)
6612
84
{
6613
84
    if (pref != NULL) {
6614
84
        if (flags == 0) {
6615
0
            ws_error("Setting \"%s\" preference effect flags to 0", pref->name);
6616
0
        }
6617
84
        pref->effect_flags = flags;
6618
84
    }
6619
84
}
6620
6621
void
6622
prefs_set_effect_flags_by_name(module_t * module, const char *pref, unsigned int flags)
6623
70
{
6624
70
    prefs_set_effect_flags(prefs_find_preference(module, pref), flags);
6625
70
}
6626
6627
unsigned int
6628
prefs_get_module_effect_flags(module_t * module)
6629
28
{
6630
28
    if (module == NULL)
6631
0
        return 0;
6632
6633
28
    return module->effect_flags;
6634
28
}
6635
6636
void
6637
prefs_set_module_effect_flags(module_t * module, unsigned int flags)
6638
70
{
6639
70
    if (module != NULL) {
6640
70
        if (flags == 0) {
6641
0
            ws_error("Setting module \"%s\" preference effect flags to 0", module->name);
6642
0
        }
6643
70
        module->effect_flags = flags;
6644
70
    }
6645
70
}
6646
6647
char *
6648
prefs_pref_type_description(pref_t *pref)
6649
0
{
6650
0
    const char *type_desc = "An unknown preference type";
6651
6652
0
    if (!pref) {
6653
0
        return ws_strdup_printf("%s.", type_desc); /* ...or maybe assert? */
6654
0
    }
6655
6656
0
    if (pref->obsolete) {
6657
0
        type_desc = "An obsolete preference";
6658
0
    } else {
6659
0
        switch (pref->type) {
6660
6661
0
        case PREF_UINT:
6662
0
            switch (pref->info.base) {
6663
6664
0
            case 10:
6665
0
                type_desc = "A decimal number";
6666
0
                break;
6667
6668
0
            case 8:
6669
0
                type_desc = "An octal number";
6670
0
                break;
6671
6672
0
            case 16:
6673
0
                type_desc = "A hexadecimal number";
6674
0
                break;
6675
0
            }
6676
0
            break;
6677
6678
0
        case PREF_BOOL:
6679
0
            type_desc = "true or false (case-insensitive)";
6680
0
            break;
6681
6682
0
        case PREF_ENUM:
6683
0
        case PREF_PROTO_TCP_SNDAMB_ENUM:
6684
0
        {
6685
0
            const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6686
0
            GString *enum_str = g_string_new("One of: ");
6687
0
            GString *desc_str = g_string_new("\nEquivalently, one of: ");
6688
0
            bool distinct = false;
6689
0
            while (enum_valp->name != NULL) {
6690
0
                g_string_append(enum_str, enum_valp->name);
6691
0
                g_string_append(desc_str, enum_valp->description);
6692
0
                if (g_strcmp0(enum_valp->name, enum_valp->description) != 0) {
6693
0
                    distinct = true;
6694
0
                }
6695
0
                enum_valp++;
6696
0
                if (enum_valp->name != NULL) {
6697
0
                    g_string_append(enum_str, ", ");
6698
0
                    g_string_append(desc_str, ", ");
6699
0
                }
6700
0
            }
6701
0
            if (distinct) {
6702
0
                g_string_append(enum_str, desc_str->str);
6703
0
            }
6704
0
            g_string_free(desc_str, TRUE);
6705
0
            g_string_append(enum_str, "\n(case-insensitive).");
6706
0
            return g_string_free(enum_str, FALSE);
6707
0
        }
6708
6709
0
        case PREF_STRING:
6710
0
            type_desc = "A string";
6711
0
            break;
6712
6713
0
        case PREF_SAVE_FILENAME:
6714
0
        case PREF_OPEN_FILENAME:
6715
0
            type_desc = "A path to a file";
6716
0
            break;
6717
6718
0
        case PREF_DIRNAME:
6719
0
            type_desc = "A path to a directory";
6720
0
            break;
6721
6722
0
        case PREF_RANGE:
6723
0
        {
6724
0
            type_desc = "A string denoting an positive integer range (e.g., \"1-20,30-40\")";
6725
0
            break;
6726
0
        }
6727
6728
0
        case PREF_COLOR:
6729
0
        {
6730
0
            type_desc = "A six-digit hexadecimal RGB color triplet (e.g. fce94f)";
6731
0
            break;
6732
0
        }
6733
6734
0
        case PREF_CUSTOM:
6735
0
            if (pref->custom_cbs.type_description_cb)
6736
0
                return pref->custom_cbs.type_description_cb();
6737
0
            type_desc = "A custom value";
6738
0
            break;
6739
6740
0
        case PREF_DECODE_AS_RANGE:
6741
0
            type_desc = "A string denoting an positive integer range for Decode As";
6742
0
            break;
6743
6744
0
        case PREF_STATIC_TEXT:
6745
0
            type_desc = "[Static text]";
6746
0
            break;
6747
6748
0
        case PREF_UAT:
6749
0
            type_desc = "Configuration data stored in its own file";
6750
0
            break;
6751
6752
0
        case PREF_PASSWORD:
6753
0
            type_desc = "Password (never stored on disk)";
6754
0
            break;
6755
6756
0
        case PREF_DISSECTOR:
6757
0
            type_desc = "A dissector name";
6758
0
            break;
6759
6760
0
        default:
6761
0
            break;
6762
0
        }
6763
0
    }
6764
6765
0
    return g_strdup(type_desc);
6766
0
}
6767
6768
bool
6769
prefs_pref_is_default(pref_t *pref)
6770
0
{
6771
0
    if (!pref) return false;
6772
6773
0
    if (pref->obsolete) {
6774
0
        return false;
6775
0
    }
6776
6777
0
    switch (pref->type) {
6778
6779
0
    case PREF_UINT:
6780
0
        if (pref->default_val.uint == *pref->varp.uint)
6781
0
            return true;
6782
0
        break;
6783
6784
0
    case PREF_BOOL:
6785
0
        if (pref->default_val.boolval == *pref->varp.boolp)
6786
0
            return true;
6787
0
        break;
6788
6789
0
    case PREF_ENUM:
6790
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
6791
0
        if (pref->default_val.enumval == *pref->varp.enump)
6792
0
            return true;
6793
0
        break;
6794
6795
0
    case PREF_STRING:
6796
0
    case PREF_SAVE_FILENAME:
6797
0
    case PREF_OPEN_FILENAME:
6798
0
    case PREF_DIRNAME:
6799
0
    case PREF_PASSWORD:
6800
0
    case PREF_DISSECTOR:
6801
0
        if (!(g_strcmp0(pref->default_val.string, *pref->varp.string)))
6802
0
            return true;
6803
0
        break;
6804
6805
0
    case PREF_DECODE_AS_RANGE:
6806
0
    case PREF_RANGE:
6807
0
    {
6808
0
        if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
6809
0
            return true;
6810
0
        break;
6811
0
    }
6812
6813
0
    case PREF_COLOR:
6814
0
    {
6815
0
        if ((pref->default_val.color.red == pref->varp.colorp->red) &&
6816
0
            (pref->default_val.color.green == pref->varp.colorp->green) &&
6817
0
            (pref->default_val.color.blue == pref->varp.colorp->blue))
6818
0
            return true;
6819
0
        break;
6820
0
    }
6821
6822
0
    case PREF_CUSTOM:
6823
0
        return pref->custom_cbs.is_default_cb(pref);
6824
6825
0
    case PREF_STATIC_TEXT:
6826
0
    case PREF_UAT:
6827
0
        return false;
6828
        /* ws_assert_not_reached(); */
6829
0
        break;
6830
0
    }
6831
6832
0
    return false;
6833
0
}
6834
6835
char *
6836
prefs_pref_to_str(pref_t *pref, pref_source_t source)
6837
0
{
6838
0
    const char *pref_text = "[Unknown]";
6839
0
    void *valp; /* pointer to preference value */
6840
0
    color_t *pref_color;
6841
0
    char *tmp_value, *ret_value;
6842
6843
0
    if (!pref) {
6844
0
        return g_strdup(pref_text);
6845
0
    }
6846
6847
0
    switch (source) {
6848
0
        case pref_default:
6849
0
            valp = &pref->default_val;
6850
            /* valp = &boolval, &enumval, etc. are implied by union property */
6851
0
            pref_color = &pref->default_val.color;
6852
0
            break;
6853
0
        case pref_stashed:
6854
0
            valp = &pref->stashed_val;
6855
            /* valp = &boolval, &enumval, etc. are implied by union property */
6856
0
            pref_color = &pref->stashed_val.color;
6857
0
            break;
6858
0
        case pref_current:
6859
0
            valp = pref->varp.uint;
6860
            /* valp = boolval, enumval, etc. are implied by union property */
6861
0
            pref_color = pref->varp.colorp;
6862
0
            break;
6863
0
        default:
6864
0
            return g_strdup(pref_text);
6865
0
    }
6866
6867
0
    if (pref->obsolete) {
6868
0
        pref_text = "[Obsolete]";
6869
0
    } else {
6870
0
        switch (pref->type) {
6871
6872
0
        case PREF_UINT:
6873
0
        {
6874
0
            unsigned pref_uint = *(unsigned *) valp;
6875
0
            switch (pref->info.base) {
6876
6877
0
            case 10:
6878
0
                return ws_strdup_printf("%u", pref_uint);
6879
6880
0
            case 8:
6881
0
                return ws_strdup_printf("%#o", pref_uint);
6882
6883
0
            case 16:
6884
0
                return ws_strdup_printf("%#x", pref_uint);
6885
0
            }
6886
0
            break;
6887
0
        }
6888
6889
0
        case PREF_BOOL:
6890
0
            return g_strdup((*(bool *) valp) ? "TRUE" : "FALSE");
6891
6892
0
        case PREF_ENUM:
6893
0
        case PREF_PROTO_TCP_SNDAMB_ENUM:
6894
0
        {
6895
0
            int pref_enumval = *(int *) valp;
6896
0
            const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6897
            /*
6898
            * TODO - We write the "description" value, because the "name" values
6899
            * weren't validated to be command line friendly until 5.0, and a few
6900
            * of them had to be changed. This allows older versions of Wireshark
6901
            * to read preferences that they supported, as we supported either
6902
            * the short name or the description when reading the preference files
6903
            * or an "-o" option. Once 5.0 is the oldest supported version, switch
6904
            * to writing the name below.
6905
            */
6906
0
            while (enum_valp->name != NULL) {
6907
0
                if (enum_valp->value == pref_enumval)
6908
0
                    return g_strdup(enum_valp->description);
6909
0
                enum_valp++;
6910
0
            }
6911
0
            break;
6912
0
        }
6913
6914
0
        case PREF_STRING:
6915
0
        case PREF_SAVE_FILENAME:
6916
0
        case PREF_OPEN_FILENAME:
6917
0
        case PREF_DIRNAME:
6918
0
        case PREF_PASSWORD:
6919
0
        case PREF_DISSECTOR:
6920
0
            return g_strdup(*(const char **) valp);
6921
6922
0
        case PREF_DECODE_AS_RANGE:
6923
0
        case PREF_RANGE:
6924
            /* Convert wmem to g_alloc memory */
6925
0
            tmp_value = range_convert_range(NULL, *(range_t **) valp);
6926
0
            ret_value = g_strdup(tmp_value);
6927
0
            wmem_free(NULL, tmp_value);
6928
0
            return ret_value;
6929
6930
0
        case PREF_COLOR:
6931
0
            return ws_strdup_printf("%02x%02x%02x",
6932
0
                    (pref_color->red * 255 / 65535),
6933
0
                    (pref_color->green * 255 / 65535),
6934
0
                    (pref_color->blue * 255 / 65535));
6935
6936
0
        case PREF_CUSTOM:
6937
0
            if (pref->custom_cbs.to_str_cb)
6938
0
                return pref->custom_cbs.to_str_cb(pref, source == pref_default ? true : false);
6939
0
            pref_text = "[Custom]";
6940
0
            break;
6941
6942
0
        case PREF_STATIC_TEXT:
6943
0
            pref_text = "[Static text]";
6944
0
            break;
6945
6946
0
        case PREF_UAT:
6947
0
        {
6948
0
            uat_t *uat = pref->varp.uat;
6949
0
            if (uat && uat->filename)
6950
0
                return ws_strdup_printf("[Managed in the file \"%s\"]", uat->filename);
6951
0
            else
6952
0
                pref_text = "[Managed in an unknown file]";
6953
0
            break;
6954
0
        }
6955
6956
0
        default:
6957
0
            break;
6958
0
        }
6959
0
    }
6960
6961
0
    return g_strdup(pref_text);
6962
0
}
6963
6964
/*
6965
 * Write out a single dissector preference.
6966
 */
6967
static void
6968
write_pref(void *data, void *user_data)
6969
0
{
6970
0
    pref_t *pref = (pref_t *)data;
6971
0
    write_pref_arg_t *arg = (write_pref_arg_t *)user_data;
6972
0
    char **desc_lines;
6973
0
    int i;
6974
6975
0
    if (!pref || pref->obsolete) {
6976
        /*
6977
         * This preference is no longer supported; it's not a
6978
         * real preference, so we don't write it out (i.e., we
6979
         * treat it as if it weren't found in the list of
6980
         * preferences, and we weren't called in the first place).
6981
         */
6982
0
        return;
6983
0
    }
6984
6985
0
    switch (pref->type) {
6986
6987
0
    case PREF_STATIC_TEXT:
6988
0
    case PREF_UAT:
6989
        /* Nothing to do; don't bother printing the description */
6990
0
        return;
6991
0
    case PREF_DECODE_AS_RANGE:
6992
        /* Data is saved through Decode As mechanism and not part of preferences file */
6993
0
        return;
6994
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
6995
        /* Not written to the preference file because the override is only
6996
         * for the lifetime of the capture file and there is no single
6997
         * value to write.
6998
         */
6999
0
        return;
7000
0
    default:
7001
0
        break;
7002
0
    }
7003
7004
0
    if (pref->type != PREF_CUSTOM || pref->custom_cbs.type_name_cb() != NULL) {
7005
        /*
7006
         * The prefix will either be the module name or the parent
7007
         * name if it's a subtree
7008
         */
7009
0
        const char *name_prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
7010
0
        char *type_desc, *pref_text;
7011
0
        const char * def_prefix = prefs_pref_is_default(pref) ? "#" : "";
7012
7013
0
        if (pref->type == PREF_CUSTOM)
7014
0
            fprintf(arg->pf, "\n# %s", pref->custom_cbs.type_name_cb());
7015
0
        fprintf(arg->pf, "\n");
7016
0
        if (pref->description &&
7017
0
                (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
7018
0
            if (pref->type != PREF_CUSTOM) {
7019
                /* We get duplicate lines otherwise. */
7020
7021
0
                desc_lines = g_strsplit(pref->description, "\n", 0);
7022
0
                for (i = 0; desc_lines[i] != NULL; ++i) {
7023
0
                    fprintf(arg->pf, "# %s\n", desc_lines[i]);
7024
0
                }
7025
0
                g_strfreev(desc_lines);
7026
0
            }
7027
0
        } else {
7028
0
            fprintf(arg->pf, "# No description\n");
7029
0
        }
7030
7031
0
        type_desc = prefs_pref_type_description(pref);
7032
0
        desc_lines = g_strsplit(type_desc, "\n", 0);
7033
0
        for (i = 0; desc_lines[i] != NULL; ++i) {
7034
0
            fprintf(arg->pf, "# %s\n", desc_lines[i]);
7035
0
        }
7036
0
        g_strfreev(desc_lines);
7037
0
        g_free(type_desc);
7038
7039
0
        pref_text = prefs_pref_to_str(pref, pref_current);
7040
0
        fprintf(arg->pf, "%s%s.%s: ", def_prefix, name_prefix, pref->name);
7041
0
        if (pref->type != PREF_PASSWORD)
7042
0
        {
7043
0
            desc_lines = g_strsplit(pref_text, "\n", 0);
7044
0
            for (i = 0; desc_lines[i] != NULL; ++i) {
7045
0
                fprintf(arg->pf, "%s%s\n", i == 0 ? "" : def_prefix, desc_lines[i]);
7046
0
            }
7047
0
            if (i == 0)
7048
0
                fprintf(arg->pf, "\n");
7049
0
            g_strfreev(desc_lines);
7050
0
        } else {
7051
            /* We never store password value */
7052
0
            fprintf(arg->pf, "\n");
7053
0
        }
7054
0
        g_free(pref_text);
7055
0
    }
7056
7057
0
}
7058
7059
static void
7060
count_non_uat_pref(void *data, void *user_data)
7061
0
{
7062
0
    pref_t *pref = (pref_t *)data;
7063
0
    int *arg = (int *)user_data;
7064
7065
0
    switch (pref->type)
7066
0
    {
7067
0
    case PREF_UAT:
7068
0
    case PREF_DECODE_AS_RANGE:
7069
0
    case PREF_PROTO_TCP_SNDAMB_ENUM:
7070
        //These types are not written in preference file
7071
0
        break;
7072
0
    default:
7073
0
        (*arg)++;
7074
0
        break;
7075
0
    }
7076
0
}
7077
7078
static int num_non_uat_prefs(module_t *module)
7079
0
{
7080
0
    int num = 0;
7081
7082
0
    g_list_foreach(module->prefs, count_non_uat_pref, &num);
7083
7084
0
    return num;
7085
0
}
7086
7087
/*
7088
 * Write out all preferences for a module.
7089
 */
7090
static unsigned
7091
write_module_prefs(module_t *module, void *user_data)
7092
0
{
7093
0
    write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
7094
0
    write_pref_arg_t arg;
7095
7096
    /* The GUI module needs to be explicitly called out so it
7097
       can be written out of order */
7098
0
    if ((module == gui_module) && (gui_pref_arg->is_gui_module != true))
7099
0
        return 0;
7100
7101
    /* Write a header for the main modules and GUI sub-modules */
7102
0
    if (((module->parent == NULL) || (module->parent == gui_module)) &&
7103
0
        ((prefs_module_has_submodules(module)) ||
7104
0
         (num_non_uat_prefs(module) > 0) ||
7105
0
         (module->name == NULL))) {
7106
0
         if ((module->name == NULL) && (module->parent != NULL)) {
7107
0
            fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
7108
0
         } else {
7109
0
            fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
7110
0
         }
7111
0
    }
7112
7113
0
    arg.module = module;
7114
0
    arg.pf = gui_pref_arg->pf;
7115
0
    g_list_foreach(arg.module->prefs, write_pref, &arg);
7116
7117
0
    if (prefs_module_has_submodules(module))
7118
0
        return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
7119
7120
0
    return 0;
7121
0
}
7122
7123
#ifdef _WIN32
7124
static void
7125
write_registry(void)
7126
{
7127
    HKEY hTestKey;
7128
    DWORD data;
7129
    DWORD data_size;
7130
    DWORD ret;
7131
7132
    ret = RegCreateKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY, 0, NULL,
7133
                            REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
7134
                            &hTestKey, NULL);
7135
    if (ret != ERROR_SUCCESS) {
7136
        ws_noisy("Cannot open HKCU "REG_HKCU_WIRESHARK_KEY": 0x%lx", ret);
7137
        return;
7138
    }
7139
7140
    data = ws_log_console_open;
7141
    data_size = sizeof(DWORD);
7142
    ret = RegSetValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN, 0, REG_DWORD, (const BYTE *)&data, data_size);
7143
    if (ret == ERROR_SUCCESS) {
7144
        ws_noisy("Wrote "LOG_HKCU_CONSOLE_OPEN" to Windows registry: 0x%lu", data);
7145
    }
7146
    else {
7147
        ws_noisy("Error writing registry key "LOG_HKCU_CONSOLE_OPEN": 0x%lx", ret);
7148
    }
7149
7150
    RegCloseKey(hTestKey);
7151
}
7152
#endif
7153
7154
/* Write out "prefs" to the user's preferences file, and return 0.
7155
7156
   If the preferences file path is NULL, write to stdout.
7157
7158
   If we got an error, stuff a pointer to the path of the preferences file
7159
   into "*pf_path_return", and return the errno. */
7160
int
7161
write_prefs(char **pf_path_return)
7162
0
{
7163
0
    char        *pf_path;
7164
0
    FILE        *pf;
7165
0
    write_gui_pref_arg_t write_gui_pref_info;
7166
7167
    /* Needed for "-G defaultprefs" */
7168
0
    init_prefs();
7169
7170
#ifdef _WIN32
7171
    write_registry();
7172
#endif
7173
7174
    /* To do:
7175
     * - Split output lines longer than MAX_VAL_LEN
7176
     * - Create a function for the preference directory check/creation
7177
     *   so that duplication can be avoided with filter.c
7178
     */
7179
7180
0
    if (pf_path_return != NULL) {
7181
0
        pf_path = get_persconffile_path(PF_NAME, true);
7182
0
        if ((pf = ws_fopen(pf_path, "w")) == NULL) {
7183
0
            *pf_path_return = pf_path;
7184
0
            return errno;
7185
0
        }
7186
0
        g_free(pf_path);
7187
0
    } else {
7188
0
        pf = stdout;
7189
0
    }
7190
7191
    /*
7192
     * If the preferences file is being written, be sure to write UAT files
7193
     * first that were migrated from the preferences file.
7194
     */
7195
0
    if (pf_path_return != NULL) {
7196
0
        if (prefs.filter_expressions_old) {
7197
0
            char *err = NULL;
7198
0
            prefs.filter_expressions_old = false;
7199
0
            if (!uat_save(uat_get_table_by_name("Display expressions"), &err)) {
7200
0
                ws_warning("Unable to save Display expressions: %s", err);
7201
0
                g_free(err);
7202
0
            }
7203
0
        }
7204
7205
0
        module_t *extcap_module = prefs_find_module("extcap");
7206
0
        if (extcap_module && !prefs.capture_no_extcap) {
7207
0
            char *ext_path = get_persconffile_path("extcap.cfg", true);
7208
0
            FILE *extf;
7209
0
            if ((extf = ws_fopen(ext_path, "w")) == NULL) {
7210
0
                if (errno != EISDIR) {
7211
0
                    ws_warning("Unable to save extcap preferences \"%s\": %s",
7212
0
                        ext_path, g_strerror(errno));
7213
0
                }
7214
0
                g_free(ext_path);
7215
0
            } else {
7216
0
                g_free(ext_path);
7217
7218
0
                fputs("# Extcap configuration file for Wireshark " VERSION ".\n"
7219
0
                      "#\n"
7220
0
                      "# This file is regenerated each time preferences are saved within\n"
7221
0
                      "# Wireshark. Making manual changes should be safe, however.\n"
7222
0
                      "# Preferences that have been commented out have not been\n"
7223
0
                      "# changed from their default value.\n", extf);
7224
7225
0
                write_gui_pref_info.pf = extf;
7226
0
                write_gui_pref_info.is_gui_module = false;
7227
7228
0
                write_module_prefs(extcap_module, &write_gui_pref_info);
7229
7230
0
                fclose(extf);
7231
0
            }
7232
0
        }
7233
0
    }
7234
7235
0
    fputs("# Configuration file for Wireshark " VERSION ".\n"
7236
0
          "#\n"
7237
0
          "# This file is regenerated each time preferences are saved within\n"
7238
0
          "# Wireshark. Making manual changes should be safe, however.\n"
7239
0
          "# Preferences that have been commented out have not been\n"
7240
0
          "# changed from their default value.\n", pf);
7241
7242
    /*
7243
     * For "backwards compatibility" the GUI module is written first as it's
7244
     * at the top of the file.  This is followed by all modules that can't
7245
     * fit into the preferences read/write API.  Finally the remaining modules
7246
     * are written in alphabetical order (including of course the protocol preferences)
7247
     */
7248
0
    write_gui_pref_info.pf = pf;
7249
0
    write_gui_pref_info.is_gui_module = true;
7250
7251
0
    write_module_prefs(gui_module, &write_gui_pref_info);
7252
7253
0
    write_gui_pref_info.is_gui_module = false;
7254
0
    prefs_modules_foreach_submodules(NULL, write_module_prefs, &write_gui_pref_info);
7255
7256
0
    fclose(pf);
7257
7258
    /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
7259
       an error indication, or maybe write to a new preferences file and
7260
       rename that file on top of the old one only if there are not I/O
7261
       errors. */
7262
0
    return 0;
7263
0
}
7264
7265
/** The col_list is only partly managed by the custom preference API
7266
 * because its data is shared between multiple preferences, so
7267
 * it's freed here
7268
 */
7269
static void
7270
free_col_info(GList *list)
7271
14
{
7272
14
    fmt_data *cfmt;
7273
14
    GList *list_head = list;
7274
7275
112
    while (list != NULL) {
7276
98
        cfmt = (fmt_data *)list->data;
7277
7278
98
        g_free(cfmt->title);
7279
98
        g_free(cfmt->custom_fields);
7280
98
        g_free(cfmt);
7281
98
        list = g_list_next(list);
7282
98
    }
7283
14
    g_list_free(list_head);
7284
14
}
7285
7286
/*
7287
 * Editor modelines
7288
 *
7289
 * Local Variables:
7290
 * c-basic-offset: 4
7291
 * tab-width: 8
7292
 * indent-tabs-mode: nil
7293
 * End:
7294
 *
7295
 * ex: set shiftwidth=4 tabstop=8 expandtab:
7296
 * :indentSize=4:tabSize=8:noTabs=true:
7297
 */