/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 | | */ |