Bug Summary

File:builds/wireshark/wireshark/ui/recent.c
Warning:line 1836, column 13
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name recent.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/ui -I /builds/wireshark/wireshark/build/ui -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-05-30-100320-3678-1 -x c /builds/wireshark/wireshark/ui/recent.c
1/* recent.c
2 * Recent "preference" handling routines
3 * Copyright 2004, Ulf Lamping <[email protected]>
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <[email protected]>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12#include "config.h"
13
14#include <wireshark.h>
15
16#include <stdlib.h>
17#include <errno(*__errno_location ()).h>
18
19#include <app/application_flavor.h>
20#include <wsutil/filesystem.h>
21#include <epan/prefs.h>
22#include <epan/prefs-int.h>
23#include <epan/column.h>
24#include <wsutil/value_string.h>
25
26#ifdef HAVE_PCAP_REMOTE
27#include "ui/capture_opts.h"
28#endif
29#include "ui/util.h"
30#include "ui/recent.h"
31#include "ui/recent_utils.h"
32#include "ui/packet_list_utils.h"
33#include "ui/simple_dialog.h"
34
35#include <wsutil/file_util.h>
36#include <wsutil/strtoi.h>
37
38#define RECENT_KEY_MAIN_TOOLBAR_SHOW"gui.toolbar_main_show" "gui.toolbar_main_show"
39#define RECENT_KEY_FILTER_TOOLBAR_SHOW"gui.filter_toolbar_show" "gui.filter_toolbar_show"
40#define RECENT_KEY_WIRELESS_TOOLBAR_SHOW"gui.wireless_toolbar_show" "gui.wireless_toolbar_show"
41#define RECENT_KEY_PACKET_LIST_SHOW"gui.packet_list_show" "gui.packet_list_show"
42#define RECENT_KEY_TREE_VIEW_SHOW"gui.tree_view_show" "gui.tree_view_show"
43#define RECENT_KEY_BYTE_VIEW_SHOW"gui.byte_view_show" "gui.byte_view_show"
44#define RECENT_KEY_PACKET_DIAGRAM_SHOW"gui.packet_diagram_show" "gui.packet_diagram_show"
45#define RECENT_KEY_STATUSBAR_SHOW"gui.statusbar_show" "gui.statusbar_show"
46#define RECENT_KEY_PACKET_LIST_COLORIZE"gui.packet_list_colorize" "gui.packet_list_colorize"
47#define RECENT_KEY_CAPTURE_AUTO_SCROLL"capture.auto_scroll" "capture.auto_scroll"
48#define RECENT_KEY_AGGREGATION_VIEW"capture.aggregation_view" "capture.aggregation_view"
49#define RECENT_GUI_TIME_FORMAT"gui.time_format" "gui.time_format"
50#define RECENT_GUI_TIME_PRECISION"gui.time_precision" "gui.time_precision"
51#define RECENT_GUI_SECONDS_FORMAT"gui.seconds_format" "gui.seconds_format"
52#define RECENT_GUI_ZOOM_LEVEL"gui.zoom_level" "gui.zoom_level"
53#define RECENT_GUI_BYTES_VIEW"gui.bytes_view" "gui.bytes_view"
54#define RECENT_GUI_BYTES_ENCODING"gui.bytes_encoding" "gui.bytes_encoding"
55#define RECENT_GUI_ALLOW_HOVER_SELECTION"gui.allow_hover_selection" "gui.allow_hover_selection"
56#define RECENT_GUI_PACKET_DIAGRAM_FIELD_VALUES"gui.packet_diagram_field_values" "gui.packet_diagram_field_values"
57#define RECENT_GUI_GEOMETRY_MAIN_X"gui.geometry_main_x" "gui.geometry_main_x"
58#define RECENT_GUI_GEOMETRY_MAIN_Y"gui.geometry_main_y" "gui.geometry_main_y"
59#define RECENT_GUI_GEOMETRY_MAIN_WIDTH"gui.geometry_main_width" "gui.geometry_main_width"
60#define RECENT_GUI_GEOMETRY_MAIN_HEIGHT"gui.geometry_main_height" "gui.geometry_main_height"
61#define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED"gui.geometry_main_maximized" "gui.geometry_main_maximized"
62#define RECENT_GUI_GEOMETRY_MAIN"gui.geometry_main" "gui.geometry_main"
63#define RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS"gui.geometry_leftalign_actions" "gui.geometry_leftalign_actions"
64#define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE"gui.geometry_main_upper_pane" "gui.geometry_main_upper_pane"
65#define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE"gui.geometry_main_lower_pane" "gui.geometry_main_lower_pane"
66#define RECENT_GUI_GEOMETRY_MAIN_MASTER_SPLIT"gui.geometry_main_master_split" "gui.geometry_main_master_split"
67#define RECENT_GUI_GEOMETRY_MAIN_EXTRA_SPLIT"gui.geometry_main_extra_split" "gui.geometry_main_extra_split"
68#define RECENT_LAST_USED_PROFILE"gui.last_used_profile" "gui.last_used_profile"
69#define RECENT_PROFILE_SWITCH_CHECK_COUNT"gui.profile_switch_check_count" "gui.profile_switch_check_count"
70#define RECENT_GUI_FILEOPEN_REMEMBERED_DIR"gui.fileopen_remembered_dir" "gui.fileopen_remembered_dir"
71#define RECENT_GUI_CONVERSATION_TABS"gui.conversation_tabs" "gui.conversation_tabs"
72#define RECENT_GUI_CONVERSATION_TABS_COLUMNS"gui.conversation_tabs_columns" "gui.conversation_tabs_columns"
73#define RECENT_GUI_ENDPOINT_TABS"gui.endpoint_tabs" "gui.endpoint_tabs"
74#define RECENT_GUI_ENDPOINT_TABS_COLUMNS"gui.endpoint_tabs_columns" "gui.endpoint_tabs_columns"
75#define RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES"gui.rlc_pdus_from_mac_frames" "gui.rlc_pdus_from_mac_frames"
76#define RECENT_GUI_CUSTOM_COLORS"gui.custom_colors" "gui.custom_colors"
77#define RECENT_GUI_TOOLBAR_SHOW"gui.additional_toolbar_show" "gui.additional_toolbar_show"
78#define RECENT_GUI_INTERFACE_TOOLBAR_SHOW"gui.interface_toolbar_show" "gui.interface_toolbar_show"
79#define RECENT_GUI_SEARCH_IN"gui.search_in" "gui.search_in"
80#define RECENT_GUI_SEARCH_CHAR_SET"gui.search_char_set" "gui.search_char_set"
81#define RECENT_GUI_SEARCH_CASE_SENSITIVE"gui.search_case_sensitive" "gui.search_case_sensitive"
82#define RECENT_GUI_SEARCH_REVERSE_DIR"gui.search_reverse_dir" "gui.search_reverse_dir"
83#define RECENT_GUI_SEARCH_MULTIPLE_OCCURS"gui.search_multiple_occurs" "gui.search_multiple_occurs"
84#define RECENT_GUI_SEARCH_TYPE"gui.search_type" "gui.search_type"
85#define RECENT_GUI_FOLLOW_SHOW"gui.follow_show" "gui.follow_show"
86#define RECENT_GUI_FOLLOW_DELTA"gui.follow_delta" "gui.follow_delta"
87#define RECENT_GUI_SHOW_BYTES_DECODE"gui.show_bytes_decode" "gui.show_bytes_decode"
88#define RECENT_GUI_SHOW_BYTES_SHOW"gui.show_bytes_show" "gui.show_bytes_show"
89#define RECENT_GUI_TSD_MA_WINDOW_SIZE"gui.tsd_ma_window_size" "gui.tsd_ma_window_size"
90#define RECENT_GUI_TSD_THROUGHPUT_SHOW"gui.tsd_throughput_show" "gui.tsd_throughput_show"
91#define RECENT_GUI_TSD_GOODPUT_SHOW"gui.tsd_goodput_show" "gui.tsd_goodput_show"
92#define RECENT_KEY_SIDEBAR_LEARN_VISIBLE"gui.welcome_page.sidebar.learn_visible" "gui.welcome_page.sidebar.learn_visible"
93#define RECENT_KEY_SIDEBAR_TIPS_VISIBLE"gui.welcome_page.sidebar.tips_visible" "gui.welcome_page.sidebar.tips_visible"
94#define RECENT_KEY_THEME_NAME"gui.theme_name" "gui.theme_name"
95#define RECENT_KEY_SIDEBAR_TIPS_EVENTS"gui.welcome_page.sidebar.tips_events" "gui.welcome_page.sidebar.tips_events"
96#define RECENT_KEY_SIDEBAR_TIPS_SPONSORSHIP"gui.welcome_page.sidebar.tips_sponsorship" "gui.welcome_page.sidebar.tips_sponsorship"
97#define RECENT_KEY_SIDEBAR_TIPS_TIPS"gui.welcome_page.sidebar.tips_tips" "gui.welcome_page.sidebar.tips_tips"
98#define RECENT_KEY_SIDEBAR_TIPS_AUTO_ADVANCE"gui.welcome_page.sidebar.tips_auto_advance" "gui.welcome_page.sidebar.tips_auto_advance"
99#define RECENT_KEY_SIDEBAR_TIPS_INTERVAL"gui.welcome_page.sidebar.tips_interval" "gui.welcome_page.sidebar.tips_interval"
100#define RECENT_KEY_SIDEBAR_TIPS_SLIDES_TEST"gui.welcome_page.sidebar.tips_slides_test" "gui.welcome_page.sidebar.tips_slides_test"
101
102#define RECENT_GUI_GEOMETRY"gui.geom." "gui.geom."
103
104#define RECENT_KEY_PRIVS_WARN_IF_ELEVATED"privs.warn_if_elevated" "privs.warn_if_elevated"
105#define RECENT_KEY_SYS_WARN_IF_NO_CAPTURE"sys.warn_if_no_capture" "sys.warn_if_no_capture"
106
107#define RECENT_FILE_NAME"recent" "recent"
108#define RECENT_COMMON_FILE_NAME"recent_common" "recent_common"
109
110recent_settings_t recent;
111
112static const value_string ts_type_values[] = {
113 { TS_RELATIVE, "RELATIVE" },
114 { TS_RELATIVE_CAP, "RELATIVE_CAP" },
115 { TS_ABSOLUTE, "ABSOLUTE" },
116 { TS_ABSOLUTE_WITH_YMD, "ABSOLUTE_WITH_YMD" },
117 { TS_ABSOLUTE_WITH_YDOY, "ABSOLUTE_WITH_YDOY" },
118 { TS_ABSOLUTE_WITH_YMD, "ABSOLUTE_WITH_DATE" }, /* Backward compatibility */
119 { TS_DELTA, "DELTA" },
120 { TS_DELTA_DIS, "DELTA_DIS" },
121 { TS_EPOCH, "EPOCH" },
122 { TS_UTC, "UTC" },
123 { TS_UTC_WITH_YMD, "UTC_WITH_YMD" },
124 { TS_UTC_WITH_YDOY, "UTC_WITH_YDOY" },
125 { TS_UTC_WITH_YMD, "UTC_WITH_DATE" }, /* Backward compatibility */
126 { 0, NULL((void*)0) }
127};
128
129/*
130 * NOTE: all values other than TS_PREC_AUTO are the number of digits
131 * of precision.
132 *
133 * We continue to use the old names for values where they may have
134 * been written to the recent file by previous releases. For other
135 * values, we just write it out numerically.
136 */
137static const value_string ts_precision_values[] = {
138 { TS_PREC_AUTO, "AUTO" },
139 { TS_PREC_FIXED_SEC, "SEC" },
140 { TS_PREC_FIXED_100_MSEC, "DSEC" },
141 { TS_PREC_FIXED_10_MSEC, "CSEC" },
142 { TS_PREC_FIXED_MSEC, "MSEC" },
143 { TS_PREC_FIXED_USEC, "USEC" },
144 { TS_PREC_FIXED_NSEC, "NSEC" },
145 { 0, NULL((void*)0) }
146};
147
148static const value_string ts_seconds_values[] = {
149 { TS_SECONDS_DEFAULT, "SECONDS" },
150 { TS_SECONDS_HOUR_MIN_SEC, "HOUR_MIN_SEC" },
151 { 0, NULL((void*)0) }
152};
153
154static const value_string bytes_view_type_values[] = {
155 { BYTES_HEX, "HEX" },
156 { BYTES_BITS, "BITS" },
157 { BYTES_DEC, "DEC" },
158 { BYTES_OCT, "OCT" },
159 { 0, NULL((void*)0) }
160};
161
162static const value_string bytes_encoding_type_values[] = {
163 { BYTES_ENC_FROM_PACKET, "FROM_PACKET" },
164 { BYTES_ENC_ASCII, "ASCII" },
165 { BYTES_ENC_EBCDIC, "EBCDIC" },
166 { 0, NULL((void*)0) }
167};
168
169static const value_string search_in_values[] = {
170 { SEARCH_IN_PACKET_LIST, "PACKET_LIST" },
171 { SEARCH_IN_PACKET_DETAILS, "PACKET_DETAILS" },
172 { SEARCH_IN_PACKET_BYTES, "PACKET_BYTES" },
173 { 0, NULL((void*)0) }
174};
175
176static const value_string search_char_set_values[] = {
177 { SEARCH_CHAR_SET_NARROW_AND_WIDE, "NARROW_AND_WIDE" },
178 { SEARCH_CHAR_SET_NARROW, "NARROW" },
179 { SEARCH_CHAR_SET_WIDE, "WIDE" },
180 { 0, NULL((void*)0) }
181};
182
183static const value_string search_type_values[] = {
184 { SEARCH_TYPE_DISPLAY_FILTER, "DISPLAY_FILTER" },
185 { SEARCH_TYPE_HEX_VALUE, "HEX_VALUE" },
186 { SEARCH_TYPE_STRING, "STRING" },
187 { SEARCH_TYPE_REGEX, "REGEX" },
188 { 0, NULL((void*)0) }
189};
190
191static const value_string bytes_show_values[] = {
192 { SHOW_ASCII, "ASCII" },
193 { SHOW_ASCII_CONTROL, "ASCII_CONTROL" },
194 { SHOW_CARRAY, "C_ARRAYS" },
195 { SHOW_EBCDIC, "EBCDIC" },
196 { SHOW_HEXDUMP, "HEX_DUMP" },
197 { SHOW_HTML, "HTML" },
198 { SHOW_IMAGE, "IMAGE" },
199 { SHOW_JSON, "JSON" },
200 { SHOW_RAW, "RAW" },
201 { SHOW_RUSTARRAY, "RUST_ARRAY" },
202 { SHOW_CODEC, "UTF-8" },
203 // Other codecs are generated at runtime
204 { SHOW_YAML, "YAML"},
205 { 0, NULL((void*)0) }
206};
207
208static const value_string follow_delta_values[] = {
209 { FOLLOW_DELTA_NONE, "NONE" },
210 { FOLLOW_DELTA_TURN, "TURN" },
211 { FOLLOW_DELTA_ALL, "ALL" },
212 { 0, NULL((void*)0) }
213};
214
215static const value_string show_bytes_decode_values[] = {
216 { DecodeAsNone, "NONE" },
217 { DecodeAsBASE64, "BASE64" },
218 { DecodeAsCompressed, "COMPRESSED" },
219 { DecodeAsHexDigits, "HEX_DIGITS" },
220 { DecodeAsPercentEncoding, "PERCENT_ENCODING" },
221 { DecodeAsQuotedPrintable, "QUOTED_PRINTABLE" },
222 { DecodeAsROT13, "ROT13"},
223 { 0, NULL((void*)0) }
224};
225
226static void
227free_col_width_data(void *data)
228{
229 col_width_data *cfmt = (col_width_data *)data;
230 g_free(cfmt);
231}
232
233void
234recent_free_column_width_info(recent_settings_t *rs)
235{
236 g_list_free_full(rs->col_width_list, free_col_width_data);
237 rs->col_width_list = NULL((void*)0);
238}
239
240/** Write the geometry values of a single window to the recent file.
241 *
242 * @param key unused
243 * @param value the geometry values
244 * @param rfh recent file handle (FILE)
245 */
246static void
247write_recent_geom(void *key _U___attribute__((unused)), void *value, void *rfh)
248{
249 window_geometry_t *geom = (window_geometry_t *)value;
250 FILE *rf = (FILE *)rfh;
251
252 fprintf(rf, "\n# Geometry and maximized state of %s window.\n", geom->key);
253 fprintf(rf, "# Decimal integers.\n");
254 fprintf(rf, RECENT_GUI_GEOMETRY"gui.geom." "%s.x: %d\n", geom->key, geom->x);
255 fprintf(rf, RECENT_GUI_GEOMETRY"gui.geom." "%s.y: %d\n", geom->key, geom->y);
256 fprintf(rf, RECENT_GUI_GEOMETRY"gui.geom." "%s.width: %d\n", geom->key,
257 geom->width);
258 fprintf(rf, RECENT_GUI_GEOMETRY"gui.geom." "%s.height: %d\n", geom->key,
259 geom->height);
260
261 fprintf(rf, "# true or false (case-insensitive).\n");
262 fprintf(rf, RECENT_GUI_GEOMETRY"gui.geom." "%s.maximized: %s\n", geom->key,
263 geom->maximized == true1 ? "true" : "false");
264
265 fprintf(rf, "# Qt Geometry State (hex byte string).\n");
266 fprintf(rf, RECENT_GUI_GEOMETRY"gui.geom." "%s.qt_geometry: %s\n", geom->key,
267 geom->qt_geom);
268}
269
270/* the geometry hashtable for all known window classes,
271 * the window name is the key, and the geometry struct is the value */
272static GHashTable *window_geom_hash;
273
274static GHashTable *window_splitter_hash;
275
276void
277window_geom_free(void *data)
278{
279 window_geometry_t *geom = (window_geometry_t*)data;
280 g_free(geom->key);
281 g_free(geom->qt_geom);
282 g_free(geom);
283}
284
285/* save the window and its current geometry into the geometry hashtable */
286void
287window_geom_save(const char *name, window_geometry_t *geom)
288{
289 char *key;
290 window_geometry_t *work;
291
292 /* init hashtable, if not already done */
293 if (!window_geom_hash) {
294 window_geom_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL((void*)0), window_geom_free);
295 }
296
297 /* g_malloc and insert the new one */
298 work = g_new(window_geometry_t, 1)((window_geometry_t *) g_malloc_n ((1), sizeof (window_geometry_t
)))
;
299 *work = *geom;
300 key = g_strdup(name)g_strdup_inline (name);
301 work->key = key;
302 g_hash_table_replace(window_geom_hash, key, work);
303}
304
305/* load the desired geometry for this window from the geometry hashtable */
306bool_Bool
307window_geom_load(const char *name,
308 window_geometry_t *geom)
309{
310 window_geometry_t *p;
311
312 /* init hashtable, if not already done */
313 if (!window_geom_hash) {
314 window_geom_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL((void*)0), window_geom_free);
315 }
316
317 p = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name);
318 if (p) {
319 *geom = *p;
320 return true1;
321 } else {
322 return false0;
323 }
324}
325
326/* save the window and its splitter state into the splitter hashtable */
327void
328window_splitter_save(const char *name, const char *splitter_state)
329{
330 /* init hashtable, if not already done */
331 if (!window_splitter_hash) {
332 window_splitter_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
333 }
334
335 g_hash_table_replace(window_splitter_hash, g_strdup(name)g_strdup_inline (name), g_strdup(splitter_state)g_strdup_inline (splitter_state));
336}
337
338/* save the window and its splitter state into the geometry hashtable */
339const char*
340window_splitter_load(const char *name)
341{
342 /* init hashtable, if not already done */
343 if (!window_splitter_hash) {
344 return NULL((void*)0);
345 }
346
347 return g_hash_table_lookup(window_splitter_hash, name);
348}
349
350
351/* parse values of particular types */
352static void
353parse_recent_boolean(const char *val_str, bool_Bool *valuep)
354{
355 if (g_ascii_strcasecmp(val_str, "true") == 0) {
356 *valuep = true1;
357 }
358 else {
359 *valuep = false0;
360 }
361}
362
363/** Read in a single geometry key value pair from the recent file.
364 *
365 * @param name the geom_name of the window
366 * @param key the subkey of this pair (e.g. "x")
367 * @param value the new value (e.g. "123")
368 */
369static void
370window_geom_recent_read_pair(const char *name,
371 const char *key,
372 const char *value)
373{
374 window_geometry_t geom;
375
376 if (strcmp(key, "splitter") == 0) {
377 window_splitter_save(name, value);
378 return;
379 }
380
381 /* find window geometry maybe already in hashtable */
382 if (!window_geom_load(name, &geom)) {
383 /* not in table, init geom with "basic" values */
384 geom.key = NULL((void*)0); /* Will be set in window_geom_save() */
385 geom.set_pos = false0;
386 geom.x = -1;
387 geom.y = -1;
388 geom.set_size = false0;
389 geom.width = -1;
390 geom.height = -1;
391 geom.qt_geom = NULL((void*)0);
392 }
393
394 if (strcmp(key, "x") == 0) {
395 geom.x = (int)strtol(value, NULL((void*)0), 10);
396 geom.set_pos = true1;
397 } else if (strcmp(key, "y") == 0) {
398 geom.y = (int)strtol(value, NULL((void*)0), 10);
399 geom.set_pos = true1;
400 } else if (strcmp(key, "width") == 0) {
401 geom.width = (int)strtol(value, NULL((void*)0), 10);
402 geom.set_size = true1;
403 } else if (strcmp(key, "height") == 0) {
404 geom.height = (int)strtol(value, NULL((void*)0), 10);
405 geom.set_size = true1;
406 } else if (strcmp(key, "maximized") == 0) {
407 parse_recent_boolean(value, &geom.maximized);
408 geom.set_maximized = true1;
409 } else if (strcmp(key, "qt_geometry") == 0) {
410 geom.qt_geom = g_strdup(value)g_strdup_inline (value);
411 } else {
412 /*
413 * Silently ignore the bogus key. We shouldn't abort here,
414 * as this could be due to a corrupt recent file.
415 *
416 * XXX - should we print a message about this?
417 */
418 return;
419 }
420
421 /* save / replace geometry in hashtable */
422 window_geom_save(name, &geom);
423}
424
425/** Write all geometry values of all windows to the recent file.
426 * Will call write_recent_geom() for every existing window type.
427 *
428 * @param rf recent file handle from caller
429 */
430static void
431window_geom_recent_write_all(FILE *rf)
432{
433 /* init hashtable, if not already done */
434 if (!window_geom_hash) {
435 window_geom_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL((void*)0), window_geom_free);
436 }
437
438 g_hash_table_foreach(window_geom_hash, write_recent_geom, rf);
439}
440
441/** Write all known window splitter states to the recent file.
442 *
443 * @param rf recent file handle from caller
444 */
445static void
446window_splitter_recent_write_all(FILE *rf)
447{
448 /* init hashtable, if not already done */
449 if (!window_splitter_hash) {
450 return;
451 }
452
453 GHashTableIter iter;
454 void *key, *value;
455 g_hash_table_iter_init(&iter, window_splitter_hash);
456 while (g_hash_table_iter_next(&iter, &key, &value)) {
457 fprintf(rf, "\n# Splitter state of %s window.\n", (char*)key);
458 fprintf(rf, "# Qt Splitter state (hex byte string).\n");
459 fprintf(rf, RECENT_GUI_GEOMETRY"gui.geom." "%s.splitter: %s\n", (char*)key,
460 (char*)value);
461 }
462}
463
464/* Global list of recent capture filters. */
465static GList *recent_cfilter_list;
466
467/*
468 * Per-interface lists of recent capture filters; stored in a hash
469 * table indexed by interface name.
470 */
471static GHashTable *per_interface_cfilter_lists_hash;
472
473/* XXX: use a preference for this setting! */
474/* N.B.: If we use a pref, we will read the recent_common file
475 * before the pref, so don't truncate the list when reading
476 * (see the similar #16782 for the recent files.)
477 */
478static unsigned cfilter_combo_max_recent = 20;
479
480/**
481 * Returns a list of recent capture filters.
482 *
483 * @param ifname interface name; NULL refers to the global list.
484 */
485GList *
486recent_get_cfilter_list(const char *ifname)
487{
488 if (ifname == NULL((void*)0))
489 return recent_cfilter_list;
490 if (per_interface_cfilter_lists_hash == NULL((void*)0)) {
491 /* No such lists exist. */
492 return NULL((void*)0);
493 }
494 return (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
495}
496
497/**
498 * Add a capture filter to the global recent capture filter list or
499 * the recent capture filter list for an interface.
500 *
501 * @param ifname interface name; NULL refers to the global list.
502 * @param s text of capture filter
503 */
504void
505recent_add_cfilter(const char *ifname, const char *s)
506{
507 GList *cfilter_list;
508 GList *li;
509 char *li_filter, *newfilter = NULL((void*)0);
510
511 /* Don't add empty filters to the list. */
512 if (s[0] == '\0')
513 return;
514
515 if (ifname == NULL((void*)0))
516 cfilter_list = recent_cfilter_list;
517 else {
518 /* If we don't yet have a hash table for per-interface recent
519 capture filter lists, create one. Have it free the new key
520 if we're updating an entry rather than creating it below. */
521 if (per_interface_cfilter_lists_hash == NULL((void*)0))
522 per_interface_cfilter_lists_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL((void*)0));
523 cfilter_list = (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
524 }
525
526 li = g_list_first(cfilter_list);
527 while (li) {
528 /* If the filter is already in the list, remove the old one and
529 * append the new one at the latest position (at g_list_append() below) */
530 li_filter = (char *)li->data;
531 if (strcmp(s, li_filter) == 0) {
532 /* No need to copy the string, we're just moving it. */
533 newfilter = li_filter;
534 cfilter_list = g_list_remove(cfilter_list, li->data);
535 break;
536 }
537 li = li->next;
538 }
539 if (newfilter == NULL((void*)0)) {
540 /* The filter wasn't already in the list; make a copy to add. */
541 newfilter = g_strdup(s)g_strdup_inline (s);
542 }
543 cfilter_list = g_list_prepend(cfilter_list, newfilter);
544
545 if (ifname == NULL((void*)0))
546 recent_cfilter_list = cfilter_list;
547 else
548 g_hash_table_insert(per_interface_cfilter_lists_hash, g_strdup(ifname)g_strdup_inline (ifname), cfilter_list);
549}
550
551#ifdef HAVE_PCAP_REMOTE
552/* XXX: use a preference for this setting! */
553/* N.B.: If we use a pref, we will read the recent_common file
554 * before the pref, so don't truncate the list when reading
555 * (see the similar #16782 for the recent files.)
556 */
557static unsigned remote_host_max_recent = 20;
558static GList *remote_host_list;
559
560int recent_get_remote_host_list_size(void)
561{
562 if (remote_host_list == NULL((void*)0)) {
563 /* No entries exist. */
564 return 0;
565 }
566 return g_list_length(remote_host_list);
567}
568
569static void
570free_remote_host(void *value)
571{
572 struct remote_host* rh = (struct remote_host*)value;
573
574 g_free(rh->r_host);
575 g_free(rh->remote_port);
576 g_free(rh->auth_username);
577 g_free(rh->auth_password);
578
579}
580
581static int
582remote_host_compare(const void *a, const void *b)
583{
584 const struct remote_host* rh_a = (const struct remote_host*)a;
585 const struct remote_host* rh_b = (const struct remote_host*)b;
586
587 /* We assume only one entry per host (the GUI assumes that too.) */
588 return g_strcmp0(rh_a->r_host, rh_b->r_host);
589}
590
591static void
592remote_host_reverse(void)
593{
594 if (remote_host_list) {
595 remote_host_list = g_list_reverse(remote_host_list);
596 }
597}
598
599void recent_add_remote_host(char *host _U___attribute__((unused)), struct remote_host *rh)
600{
601 GList* li = NULL((void*)0);
602 if (remote_host_list) {
603 li = g_list_find_custom(remote_host_list, rh, remote_host_compare);
604 if (li != NULL((void*)0)) {
605 free_remote_host(li->data);
606 remote_host_list = g_list_delete_link(remote_host_list, li);
607 }
608 }
609 remote_host_list = g_list_prepend(remote_host_list, rh);
610}
611
612void
613recent_remote_host_list_foreach(GFunc func, void *user_data)
614{
615 if (remote_host_list != NULL((void*)0)) {
616 g_list_foreach(remote_host_list, func, user_data);
617 }
618}
619
620static void
621recent_print_remote_host(void *value, void *user)
622{
623 FILE *rf = (FILE *)user;
624 struct remote_host_info *ri = (struct remote_host_info *)value;
625
626 fprintf (rf, RECENT_KEY_REMOTE_HOST"recent.remote_host" ": %s,%s,%d\n", ri->remote_host, ri->remote_port, ri->auth_type);
627}
628
629/**
630 * Write the contents of the remote_host_list to the 'recent' file.
631 *
632 * @param rf File to write to.
633 */
634static void
635capture_remote_combo_recent_write_all(FILE *rf)
636{
637 unsigned max_count = 0;
638 GList *li = g_list_first(remote_host_list);
639
640 /* write all non empty remote capture hosts to the recent file (until max count) */
641 while (li && (max_count++ <= remote_host_max_recent)) {
642 recent_print_remote_host(li->data, rf);
643 li = li->next;
644 }
645}
646
647
648void recent_free_remote_host_list(void)
649{
650 g_list_free_full(remote_host_list, free_remote_host);
651 remote_host_list = NULL((void*)0);
652}
653
654struct remote_host *
655recent_get_remote_host(const char *host)
656{
657 if (host == NULL((void*)0))
658 return NULL((void*)0);
659 for (GList* li = g_list_first(remote_host_list); li != NULL((void*)0); li = li->next) {
660 struct remote_host *rh = (struct remote_host*)li->data;
661 if (g_strcmp0(host, rh->r_host) == 0) {
662 return rh;
663 }
664 }
665 return NULL((void*)0);
666}
667
668/**
669 * Fill the remote_host_list with the entries stored in the 'recent' file.
670 *
671 * @param s String to be filled from the 'recent' file.
672 * @return True, if the list was written successfully, False otherwise.
673 */
674static bool_Bool
675capture_remote_combo_add_recent(const char *s)
676{
677 GList *vals = prefs_get_string_list (s);
678 GList *valp = vals;
679 capture_auth auth_type;
680 char *p;
681 struct remote_host *rh;
682
683 if (valp == NULL((void*)0))
684 return false0;
685
686 /* First value is the host */
687 if (recent_get_remote_host(valp->data)) {
688 /* Don't add it, it's already in the list (shouldn't happen). */
689 return false0; // Should this be true or false?
690 }
691 rh = (struct remote_host *) g_malloc (sizeof (*rh));
692
693 /* First value is the host */
694 rh->r_host = (char *)g_strdup ((const char *)valp->data)g_strdup_inline ((const char *)valp->data);
695 if (strlen(rh->r_host) == 0) {
696 /* Empty remote host */
697 g_free(rh->r_host);
698 g_free(rh);
699 return false0;
700 }
701 rh->auth_type = CAPTURE_AUTH_NULL;
702 valp = valp->next;
703
704 if (valp) {
705 /* Found value 2, this is the port number */
706 if (!strcmp((const char*)valp->data, "0")) {
707 /* Port 0 isn't valid, so leave port blank */
708 rh->remote_port = (char *)g_strdup ("")g_strdup_inline ("");
709 } else {
710 rh->remote_port = (char *)g_strdup ((const char *)valp->data)g_strdup_inline ((const char *)valp->data);
711 }
712 valp = valp->next;
713 } else {
714 /* Did not find a port number */
715 rh->remote_port = g_strdup ("")g_strdup_inline ("");
716 }
717
718 if (valp) {
719 /* Found value 3, this is the authentication type */
720 auth_type = (capture_auth)strtol((const char *)valp->data, &p, 0);
721 if (p != valp->data && *p == '\0') {
722 rh->auth_type = auth_type;
723 }
724 }
725
726 /* Do not store username and password */
727 rh->auth_username = g_strdup ("")g_strdup_inline ("");
728 rh->auth_password = g_strdup ("")g_strdup_inline ("");
729
730 prefs_clear_string_list(vals);
731
732 remote_host_list = g_list_prepend(remote_host_list, rh);
733 return true1;
734}
735#endif
736
737static void
738cfilter_recent_write_all_list(FILE *rf, const char *ifname, GList *cfilter_list)
739{
740 unsigned max_count = 0;
741 GList *li;
742 char *sanitized;
743
744 /* write all non empty capture filter strings to the recent file (until max count) */
745 li = g_list_first(cfilter_list);
746 while (li && (max_count++ <= cfilter_combo_max_recent) ) {
747 if (li->data && strlen((const char *)li->data)) {
748 sanitized = prefs_sanitize_string((char *)li->data);
749 if (ifname == NULL((void*)0))
750 fprintf (rf, RECENT_KEY_CAPTURE_FILTER"recent.capture_filter" ": %s\n", sanitized);
751 else
752 fprintf (rf, RECENT_KEY_CAPTURE_FILTER"recent.capture_filter" ".%s: %s\n", ifname, sanitized);
753 g_free(sanitized);
754 }
755 li = li->next;
756 }
757}
758
759static void
760cfilter_recent_write_all_hash_callback(void *key, void *value, void *user_data)
761{
762 cfilter_recent_write_all_list((FILE *)user_data, (const char *)key, (GList *)value);
763}
764
765/** Write all capture filter values to the recent file.
766 *
767 * @param rf recent file handle from caller
768 */
769static void
770cfilter_recent_write_all(FILE *rf)
771{
772 /* Write out the global list. */
773 cfilter_recent_write_all_list(rf, NULL((void*)0), recent_cfilter_list);
774
775 /* Write out all the per-interface lists. */
776 if (per_interface_cfilter_lists_hash != NULL((void*)0)) {
777 g_hash_table_foreach(per_interface_cfilter_lists_hash, cfilter_recent_write_all_hash_callback, (void *)rf);
778 }
779}
780
781/** Reverse the order of all the capture filter lists after
782 * reading recent_common (we want the latest first).
783 * Note this is O(N), whereas appending N items to a GList is O(N^2),
784 * since it doesn't have a pointer to the end like a GQueue.
785 */
786static void
787cfilter_recent_reverse_all(void)
788{
789 recent_cfilter_list = g_list_reverse(recent_cfilter_list);
790
791 /* Reverse all the per-interface lists. */
792 if (per_interface_cfilter_lists_hash != NULL((void*)0)) {
793 GHashTableIter iter;
794 void *key, *value;
795 g_hash_table_iter_init(&iter, per_interface_cfilter_lists_hash);
796 GList *li;
797 while (g_hash_table_iter_next(&iter, &key, &value)) {
798 li = (GList *)value;
799 li = g_list_reverse(li);
800 /* per_interface_cfilter_lists_hash was created without a
801 * value_destroy_func, so this is fine.
802 */
803 g_hash_table_iter_replace(&iter, li);
804 }
805 }
806}
807
808/* Write out recent settings of particular types. */
809static void
810write_recent_boolean(FILE *rf, const char *description, const char *name,
811 bool_Bool value)
812{
813 fprintf(rf, "\n# %s.\n", description);
814 fprintf(rf, "# true or false (case-insensitive).\n");
815 fprintf(rf, "%s: %s\n", name, value == true1 ? "true" : "false");
816}
817
818static void
819write_recent_double(FILE *rf, const char *description, const char *name,
820 double value)
821{
822 fprintf(rf, "\n# %s.\n", description);
823 char buf[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)];
824 fprintf(rf, "%s: %s\n", name, g_ascii_dtostr(buf, sizeof(buf), value));
825}
826
827static void
828write_recent_enum(FILE *rf, const char *description, const char *name,
829 const value_string *values, unsigned value)
830{
831 const char *if_invalid = NULL((void*)0);
832 const value_string *valp;
833 const char *str_value;
834
835 fprintf(rf, "\n# %s.\n", description);
836 fprintf(rf, "# One of: ");
837 valp = values;
838 while (valp->strptr != NULL((void*)0)) {
839 if (if_invalid == NULL((void*)0))
840 if_invalid = valp->strptr;
841 fprintf(rf, "%s", valp->strptr);
842 valp++;
843 if (valp->strptr != NULL((void*)0))
844 fprintf(rf, ", ");
845 }
846 fprintf(rf, "\n");
847 str_value = try_val_to_str(value, values);
848 if (str_value != NULL((void*)0))
849 fprintf(rf, "%s: %s\n", name, str_value);
850 else
851 fprintf(rf, "%s: %s\n", name, if_invalid != NULL((void*)0) ? if_invalid : "Unknown");
852}
853
854/* Attempt to write out "recent common" to the user's recent_common file.
855 If we got an error report it with a dialog box and return false,
856 otherwise return true. */
857bool_Bool
858write_recent(void)
859{
860 char *pf_dir_path;
861 char *rf_path;
862 FILE *rf;
863 char *string_list;
864
865 /* To do:
866 * - Split output lines longer than MAX_VAL_LEN
867 * - Create a function for the preference directory check/creation
868 * so that duplication can be avoided with filter.c
869 */
870
871 /* Create the directory that holds personal configuration files, if
872 necessary. */
873 if (create_persconffile_dir(application_configuration_environment_prefix(), &pf_dir_path) == -1) {
874 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK0x01,
875 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
876 g_strerror(errno(*__errno_location ())));
877 g_free(pf_dir_path);
878 return false0;
879 }
880
881 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME"recent_common", false0, application_configuration_environment_prefix());
882 if ((rf = ws_fopenfopen(rf_path, "w")) == NULL((void*)0)) {
883 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK0x01,
884 "Can't open recent file\n\"%s\": %s.", rf_path,
885 g_strerror(errno(*__errno_location ())));
886 g_free(rf_path);
887 return false0;
888 }
889 g_free(rf_path);
890
891 fprintf(rf, "# Common recent settings file for %s " VERSION"4.7.0" ".\n"
892 "#\n"
893 "# This file is regenerated each time %s is quit\n"
894 "# and when changing configuration profile.\n"
895 "# So be careful, if you want to make manual changes here.\n"
896 "\n"
897 "######## Recent capture files (latest last), cannot be altered through command line ########\n"
898 "\n",
899 application_flavor_name_proper(), application_flavor_name_proper());
900
901
902 menu_recent_file_write_all(rf);
903
904 fputs("\n"
905 "######## Recent capture filters (latest first), cannot be altered through command line ########\n"
906 "\n", rf);
907
908 cfilter_recent_write_all(rf);
909
910 fputs("\n"
911 "######## Recent display filters (latest last), cannot be altered through command line ########\n"
912 "\n", rf);
913
914 dfilter_recent_combo_write_all(rf);
915
916#ifdef HAVE_PCAP_REMOTE
917 fputs("\n"
918 "######## Recent remote hosts (latest first), cannot be altered through command line ########\n"
919 "\n", rf);
920
921 capture_remote_combo_recent_write_all(rf);
922#endif
923
924 fprintf(rf, "\n# Main window geometry.\n");
925 fprintf(rf, "# Decimal numbers.\n");
926 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X"gui.geometry_main_x" ": %d\n", recent.gui_geometry_main_x);
927 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y"gui.geometry_main_y" ": %d\n", recent.gui_geometry_main_y);
928 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH"gui.geometry_main_width" ": %d\n",
929 recent.gui_geometry_main_width);
930 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT"gui.geometry_main_height" ": %d\n",
931 recent.gui_geometry_main_height);
932
933 write_recent_boolean(rf, "Main window maximized",
934 RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED"gui.geometry_main_maximized",
935 recent.gui_geometry_main_maximized);
936
937 if (recent.gui_geometry_main != NULL((void*)0)) {
938 fprintf(rf, "\n# Main window geometry state.\n");
939 fprintf(rf, "# Hex byte string.\n");
940 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN"gui.geometry_main" ": %s\n",
941 recent.gui_geometry_main);
942 }
943
944 write_recent_boolean(rf, "Leftalign Action Buttons",
945 RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS"gui.geometry_leftalign_actions",
946 recent.gui_geometry_leftalign_actions);
947
948 fprintf(rf, "\n# Last used Configuration Profile.\n");
949 fprintf(rf, RECENT_LAST_USED_PROFILE"gui.last_used_profile" ": %s\n", get_profile_name());
950
951 fprintf(rf, "\n# Number of packets or events to check for automatic profile switching.\n");
952 fprintf(rf, "# Decimal number. Zero disables switching.\n");
953 const char * def_prefix = recent.gui_profile_switch_check_count == 1000 ? "#" : "";
954 fprintf(rf, "%s" RECENT_PROFILE_SWITCH_CHECK_COUNT"gui.profile_switch_check_count" ": %d\n", def_prefix,
955 recent.gui_profile_switch_check_count);
956
957 write_recent_boolean(rf, "Warn if running with elevated permissions (e.g. as root)",
958 RECENT_KEY_PRIVS_WARN_IF_ELEVATED"privs.warn_if_elevated",
959 recent.privs_warn_if_elevated);
960
961 write_recent_boolean(rf, "Warn if Wireshark is unable to capture",
962 RECENT_KEY_SYS_WARN_IF_NO_CAPTURE"sys.warn_if_no_capture",
963 recent.sys_warn_if_no_capture);
964
965 write_recent_enum(rf, "Find packet search in", RECENT_GUI_SEARCH_IN"gui.search_in", search_in_values,
966 recent.gui_search_in);
967 write_recent_enum(rf, "Find packet character set", RECENT_GUI_SEARCH_CHAR_SET"gui.search_char_set", search_char_set_values,
968 recent.gui_search_char_set);
969 write_recent_boolean(rf, "Find packet case sensitive search",
970 RECENT_GUI_SEARCH_CASE_SENSITIVE"gui.search_case_sensitive",
971 recent.gui_search_case_sensitive);
972 write_recent_boolean(rf, "Find packet search reverse direction",
973 RECENT_GUI_SEARCH_REVERSE_DIR"gui.search_reverse_dir",
974 recent.gui_search_reverse_dir);
975 write_recent_boolean(rf, "Find packet search multiple occurrences",
976 RECENT_GUI_SEARCH_MULTIPLE_OCCURS"gui.search_multiple_occurs",
977 recent.gui_search_multiple_occurs);
978 write_recent_enum(rf, "Find packet search type", RECENT_GUI_SEARCH_TYPE"gui.search_type", search_type_values,
979 recent.gui_search_type);
980
981 write_recent_boolean(rf, "Welcome page sidebar Learn section visible",
982 RECENT_KEY_SIDEBAR_LEARN_VISIBLE"gui.welcome_page.sidebar.learn_visible",
983 recent.gui_welcome_page_sidebar_learn_visible);
984
985 write_recent_boolean(rf, "Welcome page sidebar Tips section visible",
986 RECENT_KEY_SIDEBAR_TIPS_VISIBLE"gui.welcome_page.sidebar.tips_visible",
987 recent.gui_welcome_page_sidebar_tips_visible);
988
989 write_recent_boolean(rf, "Welcome page sidebar Tips event slides",
990 RECENT_KEY_SIDEBAR_TIPS_EVENTS"gui.welcome_page.sidebar.tips_events",
991 recent.gui_welcome_page_sidebar_tips_events);
992
993 write_recent_boolean(rf, "Welcome page sidebar Tips sponsorship slides",
994 RECENT_KEY_SIDEBAR_TIPS_SPONSORSHIP"gui.welcome_page.sidebar.tips_sponsorship",
995 recent.gui_welcome_page_sidebar_tips_sponsorship);
996
997 write_recent_boolean(rf, "Welcome page sidebar Tips tip-of-the-day slides",
998 RECENT_KEY_SIDEBAR_TIPS_TIPS"gui.welcome_page.sidebar.tips_tips",
999 recent.gui_welcome_page_sidebar_tips_tips);
1000
1001 write_recent_boolean(rf, "Welcome page sidebar Tips auto advance slides",
1002 RECENT_KEY_SIDEBAR_TIPS_AUTO_ADVANCE"gui.welcome_page.sidebar.tips_auto_advance",
1003 recent.gui_welcome_page_sidebar_tips_auto_advance);
1004
1005 fprintf(rf, "\n# Welcome page sidebar Tips slide auto-advance interval in seconds.\n");
1006 fprintf(rf, RECENT_KEY_SIDEBAR_TIPS_INTERVAL"gui.welcome_page.sidebar.tips_interval" ": %u\n",
1007 recent.gui_welcome_page_sidebar_tips_interval);
1008
1009 fprintf(rf, "\n# Active theme (directory name under resources/themes).\n");
1010 fprintf(rf, RECENT_KEY_THEME_NAME"gui.theme_name" ": %s\n",
1011 recent.gui_theme_name ? recent.gui_theme_name : "default");
1012
1013 write_recent_boolean(rf, "Welcome page sidebar Tips slides test",
1014 RECENT_KEY_SIDEBAR_TIPS_SLIDES_TEST"gui.welcome_page.sidebar.tips_slides_test",
1015 recent.gui_welcome_page_sidebar_tips_slides_test);
1016
1017 window_geom_recent_write_all(rf);
1018
1019 fprintf(rf, "\n# Custom colors.\n");
1020 fprintf(rf, "# List of custom colors selected in Qt color picker.\n");
1021 string_list = join_string_list(recent.custom_colors);
1022 fprintf(rf, RECENT_GUI_CUSTOM_COLORS"gui.custom_colors" ": %s\n", string_list);
1023 g_free(string_list);
1024
1025 fclose(rf);
1026
1027 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
1028 an error indication, or maybe write to a new recent file and
1029 rename that file on top of the old one only if there are not I/O
1030 errors. */
1031 return true1;
1032}
1033
1034
1035/* Attempt to Write out profile "recent" to the user's profile recent file.
1036 If we got an error report it with a dialog box and return false,
1037 otherwise return true. */
1038bool_Bool
1039write_profile_recent(void)
1040{
1041 char *pf_dir_path;
1042 char *rf_path;
1043 char *string_list;
1044 FILE *rf;
1045
1046 /* To do:
1047 * - Split output lines longer than MAX_VAL_LEN
1048 * - Create a function for the preference directory check/creation
1049 * so that duplication can be avoided with filter.c
1050 */
1051
1052 /* Create the directory that holds personal configuration files, if
1053 necessary. */
1054 if (create_persconffile_dir(application_configuration_environment_prefix(), &pf_dir_path) == -1) {
1055 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK0x01,
1056 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
1057 g_strerror(errno(*__errno_location ())));
1058 g_free(pf_dir_path);
1059 return false0;
1060 }
1061
1062 rf_path = get_persconffile_path(RECENT_FILE_NAME"recent", true1, application_configuration_environment_prefix());
1063 if ((rf = ws_fopenfopen(rf_path, "w")) == NULL((void*)0)) {
1064 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK0x01,
1065 "Can't open recent file\n\"%s\": %s.", rf_path,
1066 g_strerror(errno(*__errno_location ())));
1067 g_free(rf_path);
1068 return false0;
1069 }
1070 g_free(rf_path);
1071
1072 fprintf(rf, "# Recent settings file for %s " VERSION"4.7.0" ".\n"
1073 "#\n"
1074 "# This file is regenerated each time %s is quit\n"
1075 "# and when changing configuration profile.\n"
1076 "# So be careful, if you want to make manual changes here.\n"
1077 "\n",
1078 application_flavor_name_proper(), application_flavor_name_proper());
1079
1080 write_recent_boolean(rf, "Main Toolbar show (hide)",
1081 RECENT_KEY_MAIN_TOOLBAR_SHOW"gui.toolbar_main_show",
1082 recent.main_toolbar_show);
1083
1084 write_recent_boolean(rf, "Filter Toolbar show (hide)",
1085 RECENT_KEY_FILTER_TOOLBAR_SHOW"gui.filter_toolbar_show",
1086 recent.filter_toolbar_show);
1087
1088 write_recent_boolean(rf, "Wireless Settings Toolbar show (hide)",
1089 RECENT_KEY_WIRELESS_TOOLBAR_SHOW"gui.wireless_toolbar_show",
1090 recent.wireless_toolbar_show);
1091
1092 write_recent_boolean(rf, "Packet list show (hide)",
1093 RECENT_KEY_PACKET_LIST_SHOW"gui.packet_list_show",
1094 recent.packet_list_show);
1095
1096 write_recent_boolean(rf, "Tree view show (hide)",
1097 RECENT_KEY_TREE_VIEW_SHOW"gui.tree_view_show",
1098 recent.tree_view_show);
1099
1100 write_recent_boolean(rf, "Byte view show (hide)",
1101 RECENT_KEY_BYTE_VIEW_SHOW"gui.byte_view_show",
1102 recent.byte_view_show);
1103
1104 write_recent_boolean(rf, "Packet diagram show (hide)",
1105 RECENT_KEY_PACKET_DIAGRAM_SHOW"gui.packet_diagram_show",
1106 recent.packet_diagram_show);
1107
1108 write_recent_boolean(rf, "Statusbar show (hide)",
1109 RECENT_KEY_STATUSBAR_SHOW"gui.statusbar_show",
1110 recent.statusbar_show);
1111
1112 write_recent_boolean(rf, "Packet list colorize (hide)",
1113 RECENT_KEY_PACKET_LIST_COLORIZE"gui.packet_list_colorize",
1114 recent.packet_list_colorize);
1115
1116 write_recent_boolean(rf, "Auto scroll packet list when capturing",
1117 RECENT_KEY_CAPTURE_AUTO_SCROLL"capture.auto_scroll",
1118 recent.capture_auto_scroll);
1119
1120 write_recent_boolean(rf, "use as aggregation view",
1121 RECENT_KEY_AGGREGATION_VIEW"capture.aggregation_view",
1122 recent.aggregation_view);
1123
1124 write_recent_enum(rf, "Timestamp display format",
1125 RECENT_GUI_TIME_FORMAT"gui.time_format", ts_type_values,
1126 recent.gui_time_format);
1127
1128 /*
1129 * The value of this item is either TS_PREC_AUTO, which is a
1130 * negative number meaning "pick the display precision based
1131 * on the time stamp precision of the packet", or is a numerical
1132 * value giving the number of decimal places to display, from 0
1133 * to WS_TSPREC_MAX.
1134 *
1135 * It used to be that not all values between 0 and 9 (the maximum
1136 * precision back then) were supported, and that names were
1137 * written out to the recent file.
1138 *
1139 * For backwards compatibility with those older versions of
1140 * Wireshark, write out the names for those values, and the
1141 * raw number for other values.
1142 */
1143 {
1144 const char *if_invalid = NULL((void*)0);
1145 const value_string *valp;
1146 const char *str_value;
1147
1148 fprintf(rf, "\n# %s.\n", "Timestamp display precision");
1149 fprintf(rf, "# One of: ");
1150 valp = ts_precision_values;
1151 while (valp->strptr != NULL((void*)0)) {
1152 if (if_invalid == NULL((void*)0))
1153 if_invalid = valp->strptr;
1154 fprintf(rf, "%s", valp->strptr);
1155 valp++;
1156 if (valp->strptr != NULL((void*)0))
1157 fprintf(rf, ", ");
1158 }
1159 fprintf(rf, ", or a number between 0 and %d\n", WS_TSPREC_MAX9);
1160
1161 str_value = try_val_to_str(recent.gui_time_precision, ts_precision_values);
1162 if (str_value != NULL((void*)0))
1163 fprintf(rf, "%s: %s\n", RECENT_GUI_TIME_PRECISION"gui.time_precision", str_value);
1164 else {
1165 if (recent.gui_time_precision >= 0 && recent.gui_time_precision < WS_TSPREC_MAX9)
1166 fprintf(rf, "%s: %d\n", RECENT_GUI_TIME_PRECISION"gui.time_precision", recent.gui_time_precision);
1167 else
1168 fprintf(rf, "%s: %s\n", RECENT_GUI_TIME_PRECISION"gui.time_precision", if_invalid != NULL((void*)0) ? if_invalid : "Unknown");
1169 }
1170 }
1171
1172 write_recent_enum(rf, "Seconds display format",
1173 RECENT_GUI_SECONDS_FORMAT"gui.seconds_format", ts_seconds_values,
1174 recent.gui_seconds_format);
1175
1176 fprintf(rf, "\n# Zoom level.\n");
1177 fprintf(rf, "# A decimal number.\n");
1178 fprintf(rf, RECENT_GUI_ZOOM_LEVEL"gui.zoom_level" ": %d\n",
1179 recent.gui_zoom_level);
1180
1181 write_recent_enum(rf, "Bytes view display type",
1182 RECENT_GUI_BYTES_VIEW"gui.bytes_view", bytes_view_type_values,
1183 recent.gui_bytes_view);
1184
1185 write_recent_enum(rf, "Bytes view text encoding",
1186 RECENT_GUI_BYTES_ENCODING"gui.bytes_encoding", bytes_encoding_type_values,
1187 recent.gui_bytes_encoding);
1188
1189 write_recent_boolean(rf, "Packet diagram field values show (hide)",
1190 RECENT_GUI_PACKET_DIAGRAM_FIELD_VALUES"gui.packet_diagram_field_values",
1191 recent.gui_packet_diagram_field_values);
1192
1193 write_recent_boolean(rf, "Allow hover selection in byte view",
1194 RECENT_GUI_ALLOW_HOVER_SELECTION"gui.allow_hover_selection",
1195 recent.gui_allow_hover_selection);
1196
1197 write_recent_enum(rf, "Follow stream show as",
1198 RECENT_GUI_FOLLOW_SHOW"gui.follow_show", bytes_show_values,
1199 recent.gui_follow_show);
1200
1201 write_recent_enum(rf, "Follow stream delta times",
1202 RECENT_GUI_FOLLOW_DELTA"gui.follow_delta", follow_delta_values,
1203 recent.gui_follow_delta);
1204
1205 write_recent_enum(rf, "Show packet bytes decode as",
1206 RECENT_GUI_SHOW_BYTES_DECODE"gui.show_bytes_decode", show_bytes_decode_values,
1207 recent.gui_show_bytes_decode);
1208
1209 write_recent_enum(rf, "Show packet bytes show as",
1210 RECENT_GUI_SHOW_BYTES_SHOW"gui.show_bytes_show", bytes_show_values,
1211 recent.gui_show_bytes_show);
1212
1213 fprintf(rf, "\n# Main window upper (or leftmost) pane size.\n");
1214 fprintf(rf, "# Decimal number.\n");
1215 if (recent.gui_geometry_main_upper_pane != 0) {
1216 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE"gui.geometry_main_upper_pane" ": %d\n",
1217 recent.gui_geometry_main_upper_pane);
1218 }
1219 fprintf(rf, "\n# Main window middle pane size.\n");
1220 fprintf(rf, "# Decimal number.\n");
1221 if (recent.gui_geometry_main_lower_pane != 0) {
1222 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE"gui.geometry_main_lower_pane" ": %d\n",
1223 recent.gui_geometry_main_lower_pane);
1224 }
1225
1226 if (recent.gui_geometry_main_master_split != NULL((void*)0)) {
1227 fprintf(rf, "\n# Main window master splitter state.\n");
1228 fprintf(rf, "# Hex byte string.\n");
1229 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MASTER_SPLIT"gui.geometry_main_master_split" ": %s\n",
1230 recent.gui_geometry_main_master_split);
1231 }
1232
1233 if (recent.gui_geometry_main_extra_split != NULL((void*)0)) {
1234 fprintf(rf, "\n# Main window extra splitter state.\n");
1235 fprintf(rf, "# Hex byte string.\n");
1236 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_EXTRA_SPLIT"gui.geometry_main_extra_split" ": %s\n",
1237 recent.gui_geometry_main_extra_split);
1238 }
1239
1240 window_splitter_recent_write_all(rf);
1241
1242 fprintf(rf, "\n# Packet list column pixel widths.\n");
1243 fprintf(rf, "# Each pair of strings consists of a column format and its pixel width.\n");
1244 packet_list_recent_write_all(rf);
1245
1246 fprintf(rf, "\n# Open conversation dialog tabs.\n");
1247 fprintf(rf, "# List of conversation names, e.g. \"TCP\", \"IPv6\".\n");
1248 string_list = join_string_list(recent.conversation_tabs);
1249 fprintf(rf, RECENT_GUI_CONVERSATION_TABS"gui.conversation_tabs" ": %s\n", string_list);
1250 g_free(string_list);
1251
1252 fprintf(rf, "\n# Conversation dialog tabs columns.\n");
1253 fprintf(rf, "# List of conversation columns numbers.\n");
1254 string_list = join_string_list(recent.conversation_tabs_columns);
1255 fprintf(rf, RECENT_GUI_CONVERSATION_TABS_COLUMNS"gui.conversation_tabs_columns" ": %s\n", string_list);
1256 g_free(string_list);
1257
1258 fprintf(rf, "\n# Open endpoint dialog tabs.\n");
1259 fprintf(rf, "# List of endpoint names, e.g. \"TCP\", \"IPv6\".\n");
1260 string_list = join_string_list(recent.endpoint_tabs);
1261 fprintf(rf, RECENT_GUI_ENDPOINT_TABS"gui.endpoint_tabs" ": %s\n", string_list);
1262 g_free(string_list);
1263
1264 fprintf(rf, "\n# Endpoint dialog tabs columns.\n");
1265 fprintf(rf, "# List of endpoint columns numbers.\n");
1266 string_list = join_string_list(recent.endpoint_tabs_columns);
1267 fprintf(rf, RECENT_GUI_ENDPOINT_TABS_COLUMNS"gui.endpoint_tabs_columns" ": %s\n", string_list);
1268 g_free(string_list);
1269
1270 write_recent_boolean(rf, "For RLC stats, whether to use RLC PDUs found inside MAC frames",
1271 RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES"gui.rlc_pdus_from_mac_frames",
1272 recent.gui_rlc_use_pdus_from_mac);
1273
1274 if (get_last_open_dir() != NULL((void*)0)) {
1275 fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
1276 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR"gui.fileopen_remembered_dir" ": %s\n", get_last_open_dir());
1277 }
1278
1279 fprintf(rf, "\n# Additional Toolbars shown\n");
1280 fprintf(rf, "# List of additional toolbars to show.\n");
1281 string_list = join_string_list(recent.gui_additional_toolbars);
1282 fprintf(rf, RECENT_GUI_TOOLBAR_SHOW"gui.additional_toolbar_show" ": %s\n", string_list);
1283 g_free(string_list);
1284
1285 fprintf(rf, "\n# Interface Toolbars show.\n");
1286 fprintf(rf, "# List of interface toolbars to show.\n");
1287 string_list = join_string_list(recent.interface_toolbars);
1288 fprintf(rf, RECENT_GUI_INTERFACE_TOOLBAR_SHOW"gui.interface_toolbar_show" ": %s\n", string_list);
1289 g_free(string_list);
1290
1291 write_recent_double(rf, "TCP Stream Graphs Moving Average Window Size",
1292 RECENT_GUI_TSD_MA_WINDOW_SIZE"gui.tsd_ma_window_size",
1293 recent.gui_tsgd_ma_window_size);
1294 write_recent_boolean(rf, "TCP Stream Graphs Dialog Throughput show (hide)",
1295 RECENT_GUI_TSD_THROUGHPUT_SHOW"gui.tsd_throughput_show",
1296 recent.gui_tsgd_throughput_show);
1297 write_recent_boolean(rf, "TCP Stream Graphs Dialog Goodput show (hide)",
1298 RECENT_GUI_TSD_GOODPUT_SHOW"gui.tsd_goodput_show",
1299 recent.gui_tsgd_goodput_show);
1300
1301 fclose(rf);
1302
1303 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
1304 an error indication, or maybe write to a new recent file and
1305 rename that file on top of the old one only if there are not I/O
1306 errors. */
1307 return true1;
1308}
1309
1310/* set one user's recent common file key/value pair */
1311static prefs_set_pref_e
1312read_set_recent_common_pair_static(char *key, const char *value,
1313 void *private_data _U___attribute__((unused)),
1314 bool_Bool return_range_errors _U___attribute__((unused)))
1315{
1316 long num;
1317 char *p;
1318
1319 if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED"gui.geometry_main_maximized") == 0) {
1320 parse_recent_boolean(value, &recent.gui_geometry_main_maximized);
1321 } else if (strcmp(key, RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS"gui.geometry_leftalign_actions") == 0) {
1322 parse_recent_boolean(value, &recent.gui_geometry_leftalign_actions);
1323 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X"gui.geometry_main_x") == 0) {
1324 num = strtol(value, &p, 0);
1325 if (p == value || *p != '\0')
1326 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1327 recent.gui_geometry_main_x = (int)num;
1328 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y"gui.geometry_main_y") == 0) {
1329 num = strtol(value, &p, 0);
1330 if (p == value || *p != '\0')
1331 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1332 recent.gui_geometry_main_y = (int)num;
1333 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH"gui.geometry_main_width") == 0) {
1334 num = strtol(value, &p, 0);
1335 if (p == value || *p != '\0')
1336 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1337 if (num <= 0)
1338 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1339 recent.gui_geometry_main_width = (int)num;
1340 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT"gui.geometry_main_height") == 0) {
1341 num = strtol(value, &p, 0);
1342 if (p == value || *p != '\0')
1343 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1344 if (num <= 0)
1345 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1346 recent.gui_geometry_main_height = (int)num;
1347 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN"gui.geometry_main") == 0) {
1348 g_free(recent.gui_geometry_main);
1349 recent.gui_geometry_main = g_strdup(value)g_strdup_inline (value);
1350 } else if (strcmp(key, RECENT_LAST_USED_PROFILE"gui.last_used_profile") == 0) {
1351 if ((strcmp(value, DEFAULT_PROFILE"Default") != 0) && profile_exists(application_configuration_environment_prefix(), value, false0)) {
1352 set_profile_name (value);
1353 }
1354 } else if (strcmp(key, RECENT_PROFILE_SWITCH_CHECK_COUNT"gui.profile_switch_check_count") == 0) {
1355 num = strtol(value, &p, 0);
1356 if (p == value || *p != '\0')
1357 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1358 if (num <= 0)
1359 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1360 recent.gui_profile_switch_check_count = (int)num;
1361 } else if (strncmp(key, RECENT_GUI_GEOMETRY"gui.geom.", sizeof(RECENT_GUI_GEOMETRY"gui.geom.")-1) == 0) {
1362 /* now have something like "gui.geom.main.x", split it into win and sub_key */
1363 char *win = &key[sizeof(RECENT_GUI_GEOMETRY"gui.geom.")-1];
1364 char *sub_key = strchr(win, '.');
1365 if (sub_key) {
1366 *sub_key = '\0';
1367 sub_key++;
1368 window_geom_recent_read_pair(win, sub_key, value);
1369 }
1370 } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_ELEVATED"privs.warn_if_elevated") == 0) {
1371 parse_recent_boolean(value, &recent.privs_warn_if_elevated);
1372 } else if (strcmp(key, RECENT_KEY_SYS_WARN_IF_NO_CAPTURE"sys.warn_if_no_capture") == 0) {
1373 parse_recent_boolean(value, &recent.sys_warn_if_no_capture);
1374 } else if (strcmp(key, RECENT_GUI_SEARCH_IN"gui.search_in") == 0) {
1375 recent.gui_search_in = (search_in_type)str_to_val(value, search_in_values, SEARCH_IN_PACKET_LIST);
1376 } else if (strcmp(key, RECENT_GUI_SEARCH_CHAR_SET"gui.search_char_set") == 0) {
1377 recent.gui_search_char_set = (search_char_set_type)str_to_val(value, search_char_set_values, SEARCH_CHAR_SET_NARROW_AND_WIDE);
1378 } else if (strcmp(key, RECENT_GUI_SEARCH_CASE_SENSITIVE"gui.search_case_sensitive") == 0) {
1379 parse_recent_boolean(value, &recent.gui_search_case_sensitive);
1380 } else if (strcmp(key, RECENT_GUI_SEARCH_REVERSE_DIR"gui.search_reverse_dir") == 0) {
1381 parse_recent_boolean(value, &recent.gui_search_reverse_dir);
1382 } else if (strcmp(key, RECENT_GUI_SEARCH_MULTIPLE_OCCURS"gui.search_multiple_occurs") == 0) {
1383 parse_recent_boolean(value, &recent.gui_search_multiple_occurs);
1384 } else if (strcmp(key, RECENT_GUI_SEARCH_TYPE"gui.search_type") == 0) {
1385 recent.gui_search_type = (search_type_type)str_to_val(value, search_type_values, SEARCH_TYPE_DISPLAY_FILTER);
1386 } else if (strcmp(key, RECENT_GUI_CUSTOM_COLORS"gui.custom_colors") == 0) {
1387 recent.custom_colors = prefs_get_string_list(value);
1388 } else if (strcmp(key, RECENT_KEY_SIDEBAR_LEARN_VISIBLE"gui.welcome_page.sidebar.learn_visible") == 0) {
1389 parse_recent_boolean(value, &recent.gui_welcome_page_sidebar_learn_visible);
1390 } else if (strcmp(key, RECENT_KEY_SIDEBAR_TIPS_VISIBLE"gui.welcome_page.sidebar.tips_visible") == 0) {
1391 parse_recent_boolean(value, &recent.gui_welcome_page_sidebar_tips_visible);
1392 } else if (strcmp(key, RECENT_KEY_SIDEBAR_TIPS_EVENTS"gui.welcome_page.sidebar.tips_events") == 0) {
1393 parse_recent_boolean(value, &recent.gui_welcome_page_sidebar_tips_events);
1394 } else if (strcmp(key, RECENT_KEY_SIDEBAR_TIPS_SPONSORSHIP"gui.welcome_page.sidebar.tips_sponsorship") == 0) {
1395 parse_recent_boolean(value, &recent.gui_welcome_page_sidebar_tips_sponsorship);
1396 } else if (strcmp(key, RECENT_KEY_SIDEBAR_TIPS_TIPS"gui.welcome_page.sidebar.tips_tips") == 0) {
1397 parse_recent_boolean(value, &recent.gui_welcome_page_sidebar_tips_tips);
1398 } else if (strcmp(key, RECENT_KEY_SIDEBAR_TIPS_AUTO_ADVANCE"gui.welcome_page.sidebar.tips_auto_advance") == 0) {
1399 parse_recent_boolean(value, &recent.gui_welcome_page_sidebar_tips_auto_advance);
1400 } else if (strcmp(key, RECENT_KEY_SIDEBAR_TIPS_INTERVAL"gui.welcome_page.sidebar.tips_interval") == 0) {
1401 num = strtol(value, &p, 0);
1402 if (p == value || *p != '\0')
1403 return PREFS_SET_SYNTAX_ERR;
1404 if (num < 1)
1405 num = 8; // Default value
1406 recent.gui_welcome_page_sidebar_tips_interval = (unsigned)num;
1407 } else if (strcmp(key, RECENT_KEY_THEME_NAME"gui.theme_name") == 0) {
1408 g_free(recent.gui_theme_name);
1409 recent.gui_theme_name = (value && *value) ? g_strdup(value)g_strdup_inline (value) : NULL((void*)0);
1410 } else if (strcmp(key, RECENT_KEY_SIDEBAR_TIPS_SLIDES_TEST"gui.welcome_page.sidebar.tips_slides_test") == 0) {
1411 parse_recent_boolean(value, &recent.gui_welcome_page_sidebar_tips_slides_test);
1412 }
1413
1414 return PREFS_SET_OK;
1415}
1416
1417/* set one user's recent file key/value pair */
1418static prefs_set_pref_e
1419read_set_recent_pair_static(char *key, const char *value,
1420 void *private_data _U___attribute__((unused)),
1421 bool_Bool return_range_errors _U___attribute__((unused)))
1422{
1423 long num;
1424 int32_t num_int32;
1425 double val_as_dbl;
1426 char *p;
1427 GList *col_l, *col_l_elt;
1428 col_width_data *cfmt;
1429
1430 if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW"gui.toolbar_main_show") == 0) {
1431 parse_recent_boolean(value, &recent.main_toolbar_show);
1432 } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW"gui.filter_toolbar_show") == 0) {
1433 parse_recent_boolean(value, &recent.filter_toolbar_show);
1434 /* check both the old and the new keyword */
1435 } else if (strcmp(key, RECENT_KEY_WIRELESS_TOOLBAR_SHOW"gui.wireless_toolbar_show") == 0 || (strcmp(key, "gui.airpcap_toolbar_show") == 0)) {
1436 parse_recent_boolean(value, &recent.wireless_toolbar_show);
1437 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW"gui.packet_list_show") == 0) {
1438 parse_recent_boolean(value, &recent.packet_list_show);
1439 } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW"gui.tree_view_show") == 0) {
1440 parse_recent_boolean(value, &recent.tree_view_show);
1441 } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW"gui.byte_view_show") == 0) {
1442 parse_recent_boolean(value, &recent.byte_view_show);
1443 } else if (strcmp(key, RECENT_KEY_PACKET_DIAGRAM_SHOW"gui.packet_diagram_show") == 0) {
1444 parse_recent_boolean(value, &recent.packet_diagram_show);
1445 } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW"gui.statusbar_show") == 0) {
1446 parse_recent_boolean(value, &recent.statusbar_show);
1447 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_COLORIZE"gui.packet_list_colorize") == 0) {
1448 parse_recent_boolean(value, &recent.packet_list_colorize);
1449 } else if (strcmp(key, RECENT_KEY_CAPTURE_AUTO_SCROLL"capture.auto_scroll") == 0) {
1450 parse_recent_boolean(value, &recent.capture_auto_scroll);
1451 } else if (strcmp(key, RECENT_KEY_AGGREGATION_VIEW"capture.aggregation_view") == 0) {
1452 parse_recent_boolean(value, &recent.aggregation_view);
1453 } else if (strcmp(key, RECENT_GUI_TIME_FORMAT"gui.time_format") == 0) {
1454 recent.gui_time_format = (ts_type)str_to_val(value, ts_type_values,
1455 application_flavor_is_wireshark() ? TS_RELATIVE : TS_ABSOLUTE);
1456 } else if (strcmp(key, RECENT_GUI_TIME_PRECISION"gui.time_precision") == 0) {
1457 /*
1458 * The value of this item is either TS_PREC_AUTO, which is a
1459 * negative number meaning "pick the display precision based
1460 * on the time stamp precision of the packet", or is a numerical
1461 * value giving the number of decimal places to display, from 0
1462 * to WS_TSPREC_MAX.
1463 *
1464 * It used to be that not all values between 0 and 9 (the maximum
1465 * precision back then) were supported, and that names were
1466 * written out to the recent file.
1467 *
1468 * If the string value is a valid number in that range, use
1469 * that number, otherwise look it up in the table of names,
1470 * and, if that fails, set it to TS_PREC_AUTO.
1471 */
1472 if (ws_strtoi32(value, NULL((void*)0), &num_int32) && num_int32 >= 0 &&
1473 num_int32 <= WS_TSPREC_MAX9) {
1474 recent.gui_time_precision = num_int32;
1475 } else {
1476 recent.gui_time_precision =
1477 (ts_precision)str_to_val(value, ts_precision_values, TS_PREC_AUTO);
1478 }
1479 } else if (strcmp(key, RECENT_GUI_SECONDS_FORMAT"gui.seconds_format") == 0) {
1480 recent.gui_seconds_format =
1481 (ts_seconds_type)str_to_val(value, ts_seconds_values, TS_SECONDS_DEFAULT);
1482 } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL"gui.zoom_level") == 0) {
1483 num = strtol(value, &p, 0);
1484 if (p == value || *p != '\0')
1485 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1486 recent.gui_zoom_level = (int)num;
1487 } else if (strcmp(key, RECENT_GUI_BYTES_VIEW"gui.bytes_view") == 0) {
1488 recent.gui_bytes_view =
1489 (bytes_view_type)str_to_val(value, bytes_view_type_values, BYTES_HEX);
1490 } else if (strcmp(key, RECENT_GUI_BYTES_ENCODING"gui.bytes_encoding") == 0) {
1491 recent.gui_bytes_encoding =
1492 (bytes_encoding_type)str_to_val(value, bytes_encoding_type_values, BYTES_ENC_FROM_PACKET);
1493 } else if (strcmp(key, RECENT_GUI_PACKET_DIAGRAM_FIELD_VALUES"gui.packet_diagram_field_values") == 0) {
1494 parse_recent_boolean(value, &recent.gui_packet_diagram_field_values);
1495 } else if (strcmp(key, RECENT_GUI_ALLOW_HOVER_SELECTION"gui.allow_hover_selection") == 0) {
1496 parse_recent_boolean(value, &recent.gui_allow_hover_selection);
1497 } else if (strcmp(key, RECENT_GUI_FOLLOW_SHOW"gui.follow_show") == 0) {
1498 recent.gui_follow_show = (bytes_show_type)str_to_val(value, bytes_show_values, SHOW_ASCII);
1499 } else if (strcmp(key, RECENT_GUI_FOLLOW_DELTA"gui.follow_delta") == 0) {
1500 recent.gui_follow_delta = (follow_delta_type)str_to_val(value, follow_delta_values, FOLLOW_DELTA_NONE);
1501 } else if (strcmp(key, RECENT_GUI_SHOW_BYTES_DECODE"gui.show_bytes_decode") == 0) {
1502 recent.gui_show_bytes_decode = (bytes_decode_type)str_to_val(value, show_bytes_decode_values, DecodeAsNone);
1503 } else if (strcmp(key, RECENT_GUI_SHOW_BYTES_SHOW"gui.show_bytes_show") == 0) {
1504 recent.gui_show_bytes_show = (bytes_show_type)str_to_val(value, bytes_show_values, SHOW_ASCII);
1505 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE"gui.geometry_main_upper_pane") == 0) {
1506 num = strtol(value, &p, 0);
1507 if (p == value || *p != '\0')
1508 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1509 if (num <= 0)
1510 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1511 recent.gui_geometry_main_upper_pane = (int)num;
1512 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE"gui.geometry_main_lower_pane") == 0) {
1513 num = strtol(value, &p, 0);
1514 if (p == value || *p != '\0')
1515 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1516 if (num <= 0)
1517 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1518 recent.gui_geometry_main_lower_pane = (int)num;
1519 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MASTER_SPLIT"gui.geometry_main_master_split") == 0) {
1520 g_free(recent.gui_geometry_main_master_split);
1521 recent.gui_geometry_main_master_split = g_strdup(value)g_strdup_inline (value);
1522 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_EXTRA_SPLIT"gui.geometry_main_extra_split") == 0) {
1523 g_free(recent.gui_geometry_main_extra_split);
1524 recent.gui_geometry_main_extra_split = g_strdup(value)g_strdup_inline (value);
1525 } else if (strncmp(key, RECENT_GUI_GEOMETRY"gui.geom.", sizeof(RECENT_GUI_GEOMETRY"gui.geom.")-1) == 0) {
1526 /* now have something like "gui.geom.win.sub_key", split it into win and sub_key */
1527 char *win = &key[sizeof(RECENT_GUI_GEOMETRY"gui.geom.")-1];
1528 char *sub_key = strchr(win, '.');
1529 if (sub_key) {
1530 *sub_key = '\0';
1531 sub_key++;
1532 window_geom_recent_read_pair(win, sub_key, value);
1533 }
1534 } else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS"gui.conversation_tabs") == 0) {
1535 g_list_free_full(recent.conversation_tabs, g_free);
1536 recent.conversation_tabs = prefs_get_string_list(value);
1537 } else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS_COLUMNS"gui.conversation_tabs_columns") == 0) {
1538 g_list_free_full(recent.conversation_tabs_columns, g_free);
1539 recent.conversation_tabs_columns = prefs_get_string_list(value);
1540 } else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS"gui.endpoint_tabs") == 0) {
1541 g_list_free_full(recent.endpoint_tabs, g_free);
1542 recent.endpoint_tabs = prefs_get_string_list(value);
1543 } else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS_COLUMNS"gui.endpoint_tabs_columns") == 0) {
1544 g_list_free_full(recent.endpoint_tabs_columns, g_free);
1545 recent.endpoint_tabs_columns = prefs_get_string_list(value);
1546 } else if (strcmp(key, RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES"gui.rlc_pdus_from_mac_frames") == 0) {
1547 parse_recent_boolean(value, &recent.gui_rlc_use_pdus_from_mac);
1548 } else if (strcmp(key, RECENT_KEY_COL_WIDTH"column.width") == 0) {
1549 col_l = prefs_get_string_list(value);
1550 if (col_l == NULL((void*)0))
1551 return PREFS_SET_SYNTAX_ERR;
1552 if ((g_list_length(col_l) % 2) != 0) {
1553 /* A title didn't have a matching width. */
1554 prefs_clear_string_list(col_l);
1555 return PREFS_SET_SYNTAX_ERR;
1556 }
1557 recent_free_column_width_info(&recent);
1558 recent.col_width_list = NULL((void*)0);
1559 col_l_elt = g_list_first(col_l);
1560 while (col_l_elt) {
1561 cfmt = g_new(col_width_data, 1)((col_width_data *) g_malloc_n ((1), sizeof (col_width_data))
)
;
1562 /* Skip the column format, we don't use it anymore because the
1563 * column indices are in sync and the key since 4.4. Format is
1564 * still written for backwards compatibility.
1565 */
1566 col_l_elt = col_l_elt->next;
1567 cfmt->width = (int)strtol((const char *)col_l_elt->data, &p, 0);
1568 if (p == col_l_elt->data || (*p != '\0' && *p != ':')) {
1569 g_free(cfmt);
1570 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1571 }
1572
1573 if (*p == ':') {
1574 cfmt->xalign = *(++p);
1575 } else {
1576 cfmt->xalign = COLUMN_XALIGN_DEFAULT0;
1577 }
1578
1579 col_l_elt = col_l_elt->next;
1580 recent.col_width_list = g_list_append(recent.col_width_list, cfmt);
1581 }
1582 prefs_clear_string_list(col_l);
1583 } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR"gui.fileopen_remembered_dir") == 0) {
1584 g_free(recent.gui_fileopen_remembered_dir);
1585 recent.gui_fileopen_remembered_dir = g_strdup(value)g_strdup_inline (value);
1586 } else if (strcmp(key, RECENT_GUI_TOOLBAR_SHOW"gui.additional_toolbar_show") == 0) {
1587 recent.gui_additional_toolbars = prefs_get_string_list(value);
1588 } else if (strcmp(key, RECENT_GUI_INTERFACE_TOOLBAR_SHOW"gui.interface_toolbar_show") == 0) {
1589 recent.interface_toolbars = prefs_get_string_list(value);
1590 } else if (strcmp(key, RECENT_GUI_TSD_THROUGHPUT_SHOW"gui.tsd_throughput_show") == 0) {
1591 parse_recent_boolean(value, &recent.gui_tsgd_throughput_show);
1592 } else if (strcmp(key, RECENT_GUI_TSD_GOODPUT_SHOW"gui.tsd_goodput_show") == 0) {
1593 parse_recent_boolean(value, &recent.gui_tsgd_goodput_show);
1594 } else if (strcmp(key, RECENT_GUI_TSD_MA_WINDOW_SIZE"gui.tsd_ma_window_size") == 0) {
1595 val_as_dbl = g_ascii_strtod(value, &p);
1596 if (p == value || *p != '\0') {
1597 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1598 }
1599 if (val_as_dbl <= 0) {
1600 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1601 }
1602 recent.gui_tsgd_ma_window_size = val_as_dbl;
1603 } else {
1604 return PREFS_SET_NO_SUCH_PREF;
1605 }
1606
1607 return PREFS_SET_OK;
1608}
1609
1610
1611/* set one user's recent file key/value pair */
1612static prefs_set_pref_e
1613read_set_recent_pair_dynamic(char *key, const char *value,
1614 void *private_data _U___attribute__((unused)),
1615 bool_Bool return_range_errors _U___attribute__((unused)))
1616{
1617 if (!g_utf8_validate(value, -1, NULL((void*)0))) {
1618 return PREFS_SET_SYNTAX_ERR;
1619 }
1620 if (strcmp(key, RECENT_KEY_DISPLAY_FILTER"recent.display_filter") == 0) {
1621 dfilter_combo_add_recent(value);
1622 } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER"recent.capture_filter") == 0) {
1623 recent_add_cfilter(NULL((void*)0), value);
1624 } else if (g_str_has_prefix(key, RECENT_KEY_CAPTURE_FILTER ".")(__builtin_constant_p ("recent.capture_filter" ".")? __extension__
({ const char * const __str = (key); const char * const __prefix
= ("recent.capture_filter" "."); gboolean __result = (0); if
(__str == ((void*)0) || __prefix == ((void*)0)) __result = (
g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
key, "recent.capture_filter" ".") )
) {
1625 /* strrchr() can't fail - string has a prefix that ends with a "." */
1626 recent_add_cfilter(strrchr(key, '.') + 1, value);
1627#ifdef HAVE_PCAP_REMOTE
1628 } else if (strcmp(key, RECENT_KEY_REMOTE_HOST"recent.remote_host") == 0) {
1629 capture_remote_combo_add_recent(value);
1630#endif
1631 }
1632
1633 return PREFS_SET_OK;
1634}
1635
1636
1637/*
1638 * Given a string of the form "<recent name>:<recent value>", as might appear
1639 * as an argument to a "-o" option, parse it and set the recent value in
1640 * question. Return an indication of whether it succeeded or failed
1641 * in some fashion.
1642 */
1643int
1644recent_set_arg(char *prefarg)
1645{
1646 char *p, *colonp;
1647 int ret;
1648
1649 colonp = strchr(prefarg, ':');
1650 if (colonp == NULL((void*)0))
1651 return PREFS_SET_SYNTAX_ERR;
1652
1653 p = colonp;
1654 *p++ = '\0';
1655
1656 /*
1657 * Skip over any white space (there probably won't be any, but
1658 * as we allow it in the preferences file, we might as well
1659 * allow it here).
1660 */
1661 while (g_ascii_isspace(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
1662 p++;
1663 if (*p == '\0') {
1664 /*
1665 * Put the colon back, so if our caller uses, in an
1666 * error message, the string they passed us, the message
1667 * looks correct.
1668 */
1669 *colonp = ':';
1670 return PREFS_SET_SYNTAX_ERR;
1671 }
1672
1673 ret = read_set_recent_pair_static(prefarg, p, NULL((void*)0), true1);
1674 *colonp = ':'; /* put the colon back */
1675 return ret;
1676}
1677
1678
1679/* opens the user's recent common file and read the first part */
1680bool_Bool
1681recent_read_static(char **rf_path_return, int *rf_errno_return)
1682{
1683 char *rf_path;
1684 FILE *rf;
1685
1686 /* set defaults */
1687 recent.gui_geometry_main_x = 20;
1688 recent.gui_geometry_main_y = 20;
1689 recent.gui_geometry_main_width = DEF_WIDTH750;
1690 recent.gui_geometry_main_height = DEF_HEIGHT550;
1691 recent.gui_geometry_main_maximized= false0;
1692
1693 recent.gui_geometry_leftalign_actions = false0;
1694
1695 recent.privs_warn_if_elevated = true1;
1696 recent.sys_warn_if_no_capture = true1;
1697
1698 recent.col_width_list = NULL((void*)0);
1699 recent.gui_geometry_main = NULL((void*)0);
1700 recent.gui_geometry_main_master_split = NULL((void*)0);
1701 recent.gui_geometry_main_extra_split = NULL((void*)0);
1702 recent.gui_profile_switch_check_count = 1000;
1703 recent.gui_fileopen_remembered_dir = NULL((void*)0);
1704
1705 /* defaults for the welcome page sidebar */
1706 recent.gui_welcome_page_sidebar_learn_visible = true1;
1707 recent.gui_welcome_page_sidebar_tips_visible = true1;
1708 recent.gui_welcome_page_sidebar_tips_events = true1;
1709 recent.gui_welcome_page_sidebar_tips_sponsorship = true1;
1710 recent.gui_welcome_page_sidebar_tips_tips = true1;
1711 recent.gui_welcome_page_sidebar_tips_auto_advance = true1;
1712 recent.gui_welcome_page_sidebar_tips_interval = 8;
1713 recent.gui_welcome_page_sidebar_tips_slides_test = false0;
1714
1715 /* Construct the pathname of the user's recent common file. */
1716 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME"recent_common", false0, application_configuration_environment_prefix());
1717
1718 /* Read the user's recent common file, if it exists. */
1719 *rf_path_return = NULL((void*)0);
1720 if ((rf = ws_fopenfopen(rf_path, "r")) != NULL((void*)0)) {
1721 /* We succeeded in opening it; read it. */
1722 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL((void*)0));
1723
1724 fclose(rf);
1725 } else {
1726 /* We failed to open it. If we failed for some reason other than
1727 "it doesn't exist", return the errno and the pathname, so our
1728 caller can report the error. */
1729 if (errno(*__errno_location ()) != ENOENT2) {
1730 *rf_errno_return = errno(*__errno_location ());
1731 *rf_path_return = rf_path;
1732 return false0;
1733 }
1734 }
1735 g_free(rf_path);
1736 return true1;
1737}
1738
1739
1740
1741/* opens the user's recent file and read the first part */
1742bool_Bool
1743recent_read_profile_static(char **rf_path_return, int *rf_errno_return)
1744{
1745 char *rf_path, *rf_common_path;
1746 FILE *rf;
1747
1748 /* set defaults */
1749 recent.main_toolbar_show = true1;
1750 recent.filter_toolbar_show = true1;
1751 recent.wireless_toolbar_show = false0;
1752 recent.packet_list_show = true1;
1753 recent.tree_view_show = true1;
1754 recent.byte_view_show = true1;
1755 recent.packet_diagram_show = true1;
1756 recent.statusbar_show = true1;
1757 recent.packet_list_colorize = true1;
1758 recent.capture_auto_scroll = true1;
1759 recent.gui_time_format = TS_RELATIVE;
1760 recent.gui_time_precision = TS_PREC_AUTO;
1761 recent.gui_seconds_format = TS_SECONDS_DEFAULT;
1762 recent.gui_zoom_level = 0;
1763 recent.gui_bytes_view = BYTES_HEX;
1764 recent.gui_bytes_encoding = BYTES_ENC_FROM_PACKET;
1765 recent.gui_allow_hover_selection = true1;
1766 recent.gui_follow_show = SHOW_ASCII;
1767 recent.gui_follow_delta = FOLLOW_DELTA_NONE;
1768 recent.gui_show_bytes_decode = DecodeAsNone;
1769 recent.gui_show_bytes_show = SHOW_ASCII;
1770
1771 /* defaults for the TCP Stream Graph Dialog */
1772 recent.gui_tsgd_ma_window_size = 1.0;
1773 recent.gui_tsgd_throughput_show = true1;
1774 recent.gui_tsgd_goodput_show = false0;
1775
1776 /* pane size of zero will autodetect */
1777 recent.gui_geometry_main_upper_pane = 0;
1778 recent.gui_geometry_main_lower_pane = 0;
1779
1780 if (recent.gui_geometry_main) {
1
Assuming field 'gui_geometry_main' is null
2
Taking false branch
1781 g_free(recent.gui_geometry_main);
1782 recent.gui_geometry_main = NULL((void*)0);
1783 }
1784
1785 if (recent.gui_geometry_main_master_split) {
3
Assuming field 'gui_geometry_main_master_split' is null
4
Taking false branch
1786 g_free(recent.gui_geometry_main_master_split);
1787 recent.gui_geometry_main_master_split = NULL((void*)0);
1788 }
1789 if (recent.gui_geometry_main_extra_split) {
5
Assuming field 'gui_geometry_main_extra_split' is null
6
Taking false branch
1790 g_free(recent.gui_geometry_main_extra_split);
1791 recent.gui_geometry_main_extra_split = NULL((void*)0);
1792 }
1793
1794 if (recent.col_width_list) {
7
Assuming field 'col_width_list' is null
8
Taking false branch
1795 recent_free_column_width_info(&recent);
1796 }
1797
1798 if (recent.gui_fileopen_remembered_dir) {
9
Assuming field 'gui_fileopen_remembered_dir' is null
10
Taking false branch
1799 g_free (recent.gui_fileopen_remembered_dir);
1800 recent.gui_fileopen_remembered_dir = NULL((void*)0);
1801 }
1802
1803 if (recent.gui_additional_toolbars) {
11
Assuming field 'gui_additional_toolbars' is null
12
Taking false branch
1804 g_list_free_full (recent.gui_additional_toolbars, g_free);
1805 recent.gui_additional_toolbars = NULL((void*)0);
1806 }
1807
1808 if (recent.interface_toolbars) {
13
Assuming field 'interface_toolbars' is null
14
Taking false branch
1809 g_list_free_full (recent.interface_toolbars, g_free);
1810 recent.interface_toolbars = NULL((void*)0);
1811 }
1812
1813 /* Construct the pathname of the user's profile recent file. */
1814 rf_path = get_persconffile_path(RECENT_FILE_NAME"recent", true1, application_configuration_environment_prefix());
1815
1816 /* Read the user's recent file, if it exists. */
1817 *rf_path_return = NULL((void*)0);
1818 if ((rf = ws_fopenfopen(rf_path, "r")) != NULL((void*)0)) {
15
Taking true branch
1819 /* We succeeded in opening it; read it. */
1820 read_prefs_file(rf_path, rf, read_set_recent_pair_static, NULL((void*)0));
1821 fclose(rf);
1822
1823 /* XXX: The following code doesn't actually do anything since
1824 * the "recent common file" always exists. Presumably the
1825 * "if (!file_exists())" should actually be "if (file_exists())".
1826 * However, I've left the code as is because this
1827 * behaviour has existed for quite some time and I don't
1828 * know what's supposed to happen at this point.
1829 * ToDo: Determine if the "recent common file" should be read at this point
1830 */
1831 rf_common_path = get_persconffile_path(RECENT_COMMON_FILE_NAME"recent_common", false0, application_configuration_environment_prefix());
1832 if (!file_exists(rf_common_path)) {
16
Assuming the condition is true
17
Taking true branch
1833 /* Read older common settings from recent file */
1834 rf = ws_fopenfopen(rf_path, "r");
18
Assuming pointer value is null
19
Assuming that 'fopen' fails
20
Value assigned to 'rf'
1835 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL((void*)0));
1836 fclose(rf);
21
Null pointer passed to 1st parameter expecting 'nonnull'
1837 }
1838 g_free(rf_common_path);
1839 } else {
1840 /* We failed to open it. If we failed for some reason other than
1841 "it doesn't exist", return the errno and the pathname, so our
1842 caller can report the error. */
1843 if (errno(*__errno_location ()) != ENOENT2) {
1844 *rf_errno_return = errno(*__errno_location ());
1845 *rf_path_return = rf_path;
1846 return false0;
1847 }
1848 }
1849 g_free(rf_path);
1850 return true1;
1851}
1852
1853/* opens the user's recent file and read it out */
1854bool_Bool
1855recent_read_dynamic(char **rf_path_return, int *rf_errno_return)
1856{
1857 char *rf_path;
1858 FILE *rf;
1859
1860
1861 /* Construct the pathname of the user's recent common file. */
1862 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME"recent_common", false0, application_configuration_environment_prefix());
1863 if (!file_exists (rf_path)) {
1864 /* Recent common file does not exist, read from default recent */
1865 g_free (rf_path);
1866 rf_path = get_persconffile_path(RECENT_FILE_NAME"recent", false0, application_configuration_environment_prefix());
1867 }
1868
1869 /* Read the user's recent file, if it exists. */
1870 *rf_path_return = NULL((void*)0);
1871 if ((rf = ws_fopenfopen(rf_path, "r")) != NULL((void*)0)) {
1872 /* We succeeded in opening it; read it. */
1873 read_prefs_file(rf_path, rf, read_set_recent_pair_dynamic, NULL((void*)0));
1874#if 0
1875 /* set dfilter combobox to have an empty line */
1876 dfilter_combo_add_empty();
1877#endif
1878 /* We prepend new capture filters, so reverse them after adding
1879 * all to keep the latest first.
1880 */
1881 cfilter_recent_reverse_all();
1882#ifdef HAVE_PCAP_REMOTE
1883 remote_host_reverse();
1884#endif
1885 fclose(rf);
1886 } else {
1887 /* We failed to open it. If we failed for some reason other than
1888 "it doesn't exist", return the errno and the pathname, so our
1889 caller can report the error. */
1890 if (errno(*__errno_location ()) != ENOENT2) {
1891 *rf_errno_return = errno(*__errno_location ());
1892 *rf_path_return = rf_path;
1893 return false0;
1894 }
1895 }
1896 g_free(rf_path);
1897 return true1;
1898}
1899
1900void
1901recent_insert_column(int col)
1902{
1903 col_width_data *col_w;
1904
1905 col_w = g_new(col_width_data, 1)((col_width_data *) g_malloc_n ((1), sizeof (col_width_data))
)
;
1906 col_w->width = -1;
1907 col_w->xalign = COLUMN_XALIGN_DEFAULT0;
1908 recent.col_width_list = g_list_insert(recent.col_width_list, col_w, col);
1909}
1910
1911void
1912recent_remove_column(int col)
1913{
1914 GList *col_l = g_list_nth(recent.col_width_list, col);
1915 col_width_data *col_w;
1916
1917 if (!col_l) return;
1918
1919 col_w = (col_width_data*)col_l->data;
1920
1921 if (col_w) {
1922 free_col_width_data(col_w);
1923 }
1924
1925 recent.col_width_list = g_list_delete_link(recent.col_width_list, col_l);
1926}
1927
1928int
1929recent_get_column_width(int col)
1930{
1931 col_width_data *col_w;
1932
1933 col_w = g_list_nth_data(recent.col_width_list, col);
1934 if (col_w) {
1935 return col_w->width;
1936 } else {
1937 /* Make sure the recent column list isn't out of sync with the
1938 * number of columns (e.g., for a brand new profile.)
1939 */
1940 for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) {
1941 recent_insert_column(colnr);
1942 }
1943 }
1944
1945 return -1;
1946}
1947
1948void
1949recent_set_column_width(int col, int width)
1950{
1951 col_width_data *col_w;
1952
1953 col_w = g_list_nth_data(recent.col_width_list, col);
1954 if (col_w) {
1955 col_w->width = width;
1956 } else {
1957 /* Make sure the recent column list isn't out of sync with the
1958 * number of columns (e.g., for a brand new profile.)
1959 */
1960 for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) {
1961 recent_insert_column(colnr);
1962 }
1963 col_w = g_list_nth_data(recent.col_width_list, col);
1964 if (col_w) {
1965 col_w->width = width;
1966 }
1967 }
1968}
1969
1970char
1971recent_get_column_xalign(int col)
1972{
1973 col_width_data *col_w;
1974
1975 col_w = g_list_nth_data(recent.col_width_list, col);
1976 if (col_w) {
1977 return col_w->xalign;
1978 } else {
1979 /* Make sure the recent column list isn't out of sync with the
1980 * number of columns (e.g., for a brand new profile.)
1981 */
1982 for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) {
1983 recent_insert_column(colnr);
1984 }
1985 }
1986
1987 return COLUMN_XALIGN_DEFAULT0;
1988}
1989
1990void
1991recent_set_column_xalign(int col, char xalign)
1992{
1993 col_width_data *col_w;
1994
1995 col_w = g_list_nth_data(recent.col_width_list, col);
1996 if (col_w) {
1997 col_w->xalign = xalign;
1998 } else {
1999 /* Make sure the recent column list isn't out of sync with the
2000 * number of columns (e.g., for a brand new profile.)
2001 */
2002 for (unsigned colnr = g_list_length(recent.col_width_list); colnr < g_list_length(prefs.col_list); colnr++) {
2003 recent_insert_column(colnr);
2004 }
2005 col_w = g_list_nth_data(recent.col_width_list, col);
2006 if (col_w) {
2007 col_w->xalign = xalign;
2008 }
2009 }
2010}
2011
2012void
2013recent_init(void)
2014{
2015 memset(&recent, 0, sizeof(recent_settings_t));
2016}
2017
2018void
2019recent_cleanup(void)
2020{
2021 recent_free_column_width_info(&recent);
2022 g_free(recent.gui_geometry_main);
2023 g_free(recent.gui_geometry_main_master_split);
2024 g_free(recent.gui_geometry_main_extra_split);
2025 g_free(recent.gui_fileopen_remembered_dir);
2026 g_free(recent.gui_theme_name);
2027 g_list_free_full(recent.gui_additional_toolbars, g_free);
2028 g_list_free_full(recent.interface_toolbars, g_free);
2029 prefs_clear_string_list(recent.conversation_tabs);
2030 prefs_clear_string_list(recent.conversation_tabs_columns);
2031 prefs_clear_string_list(recent.endpoint_tabs);
2032 prefs_clear_string_list(recent.endpoint_tabs_columns);
2033 prefs_clear_string_list(recent.custom_colors);
2034}