Bug Summary

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