### Bug Summary

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

### Annotated Source Code

Press '?' to see keyboard shortcuts

Show analyzer invocation
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=gnu11 -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-03-08-100350-3621-1 -x c /builds/wireshark/wireshark/ui/recent.c

Keyboard shortcuts:

- Use 'j/k' keys for keyboard navigation
- Use 'Shift+S' to show/hide relevant lines
- Use '?' to toggle this window

Close
Show only relevant lines Show control flow arrows

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