nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 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 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23  
24 #include "config.h"
25  
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29  
30 #include "capture_opts.h"
31 #include <wsutil/filesystem.h>
32 #include <epan/prefs.h>
33 #include <epan/prefs-int.h>
34 #include <epan/column.h>
35 #include <epan/value_string.h>
36  
37 #include "ui/last_open_dir.h"
38 #include "ui/recent.h"
39 #include "ui/recent_utils.h"
40 #include "ui/simple_dialog.h"
41  
42 #include <wsutil/file_util.h>
43  
44 #define RECENT_KEY_MAIN_TOOLBAR_SHOW "gui.toolbar_main_show"
45 #define RECENT_KEY_FILTER_TOOLBAR_SHOW "gui.filter_toolbar_show"
46 #define RECENT_KEY_WIRELESS_TOOLBAR_SHOW "gui.wireless_toolbar_show"
47 #define RECENT_KEY_DRIVER_CHECK_SHOW "gui.airpcap_driver_check_show"
48 #define RECENT_KEY_PACKET_LIST_SHOW "gui.packet_list_show"
49 #define RECENT_KEY_TREE_VIEW_SHOW "gui.tree_view_show"
50 #define RECENT_KEY_BYTE_VIEW_SHOW "gui.byte_view_show"
51 #define RECENT_KEY_STATUSBAR_SHOW "gui.statusbar_show"
52 #define RECENT_KEY_PACKET_LIST_COLORIZE "gui.packet_list_colorize"
53 #define RECENT_GUI_TIME_FORMAT "gui.time_format"
54 #define RECENT_GUI_TIME_PRECISION "gui.time_precision"
55 #define RECENT_GUI_SECONDS_FORMAT "gui.seconds_format"
56 #define RECENT_GUI_ZOOM_LEVEL "gui.zoom_level"
57 #define RECENT_GUI_BYTES_VIEW "gui.bytes_view"
58 #define RECENT_GUI_GEOMETRY_MAIN_X "gui.geometry_main_x"
59 #define RECENT_GUI_GEOMETRY_MAIN_Y "gui.geometry_main_y"
60 #define RECENT_GUI_GTK_GEOMETRY_MAIN_X "gui.gtk.geometry_main_x"
61 #define RECENT_GUI_GTK_GEOMETRY_MAIN_Y "gui.gtk.geometry_main_y"
62 #define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width"
63 #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height"
64 #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized"
65 #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
66 #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
67 #define RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT "gui.geometry_status_pane"
68 #define RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT "gui.geometry_status_pane_right"
69 #define RECENT_GUI_GEOMETRY_WLAN_STATS_PANE "gui.geometry_status_wlan_stats_pane"
70 #define RECENT_LAST_USED_PROFILE "gui.last_used_profile"
71 #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
72 #define RECENT_GUI_CONVERSATION_TABS "gui.conversation_tabs"
73 #define RECENT_GUI_ENDPOINT_TABS "gui.endpoint_tabs"
74 #define RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES "gui.rlc_pdus_from_mac_frames"
75 #define RECENT_GUI_CUSTOM_COLORS "gui.custom_colors"
76  
77 #define RECENT_GUI_GEOMETRY "gui.geom."
78  
79 #define RECENT_KEY_PRIVS_WARN_IF_ELEVATED "privs.warn_if_elevated"
80 #define RECENT_KEY_PRIVS_WARN_IF_NO_NPF "privs.warn_if_no_npf"
81  
82 #define RECENT_FILE_NAME "recent"
83 #define RECENT_COMMON_FILE_NAME "recent_common"
84  
85 recent_settings_t recent;
86  
87 static const value_string ts_type_values[] = {
88 { TS_RELATIVE, "RELATIVE" },
89 { TS_ABSOLUTE, "ABSOLUTE" },
90 { TS_ABSOLUTE_WITH_YMD, "ABSOLUTE_WITH_YMD" },
91 { TS_ABSOLUTE_WITH_YDOY, "ABSOLUTE_WITH_YDOY" },
92 { TS_ABSOLUTE_WITH_YMD, "ABSOLUTE_WITH_DATE" }, /* Backward compability */
93 { TS_DELTA, "DELTA" },
94 { TS_DELTA_DIS, "DELTA_DIS" },
95 { TS_EPOCH, "EPOCH" },
96 { TS_UTC, "UTC" },
97 { TS_UTC_WITH_YMD, "UTC_WITH_YMD" },
98 { TS_UTC_WITH_YDOY, "UTC_WITH_YDOY" },
99 { TS_UTC_WITH_YMD, "UTC_WITH_DATE" }, /* Backward compability */
100 { 0, NULL }
101 };
102  
103 static const value_string ts_precision_values[] = {
104 { TS_PREC_AUTO, "AUTO" },
105 { TS_PREC_FIXED_SEC, "SEC" },
106 { TS_PREC_FIXED_DSEC, "DSEC" },
107 { TS_PREC_FIXED_CSEC, "CSEC" },
108 { TS_PREC_FIXED_MSEC, "MSEC" },
109 { TS_PREC_FIXED_USEC, "USEC" },
110 { TS_PREC_FIXED_NSEC, "NSEC" },
111 { 0, NULL }
112 };
113  
114 static const value_string ts_seconds_values[] = {
115 { TS_SECONDS_DEFAULT, "SECONDS" },
116 { TS_SECONDS_HOUR_MIN_SEC, "HOUR_MIN_SEC" },
117 { 0, NULL }
118 };
119  
120 static void
121 free_col_width_info(recent_settings_t *rs)
122 {
123 col_width_data *cfmt;
124  
125 while (rs->col_width_list != NULL) {
126 cfmt = (col_width_data *)rs->col_width_list->data;
127 g_free(cfmt->cfield);
128 g_free(cfmt);
129 rs->col_width_list = g_list_remove_link(rs->col_width_list, rs->col_width_list);
130 }
131 g_list_free(rs->col_width_list);
132 rs->col_width_list = NULL;
133 }
134  
135 /** Write the geometry values of a single window to the recent file.
136 *
137 * @param key unused
138 * @param value the geometry values
139 * @param rfh recent file handle (FILE)
140 */
141 static void
142 write_recent_geom(gpointer key _U_, gpointer value, gpointer rfh)
143 {
144 window_geometry_t *geom = (window_geometry_t *)value;
145 FILE *rf = (FILE *)rfh;
146  
147 fprintf(rf, "\n# Geometry and maximized state of %s window.\n", geom->key);
148 fprintf(rf, "# Decimal integers.\n");
149 fprintf(rf, RECENT_GUI_GEOMETRY "%s.x: %d\n", geom->key, geom->x);
150 fprintf(rf, RECENT_GUI_GEOMETRY "%s.y: %d\n", geom->key, geom->y);
151 fprintf(rf, RECENT_GUI_GEOMETRY "%s.width: %d\n", geom->key,
152 geom->width);
153 fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key,
154 geom->height);
155  
156 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
157 fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key,
158 geom->maximized == TRUE ? "TRUE" : "FALSE");
159  
160 }
161  
162 /* the geometry hashtable for all known window classes,
163 * the window name is the key, and the geometry struct is the value */
164 static GHashTable *window_geom_hash = NULL;
165  
166 /* save the window and its current geometry into the geometry hashtable */
167 void
168 window_geom_save(const gchar *name, window_geometry_t *geom)
169 {
170 gchar *key;
171 window_geometry_t *work;
172  
173 /* init hashtable, if not already done */
174 if (!window_geom_hash) {
175 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
176 }
177 /* if we have an old one, remove and free it first */
178 work = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name);
179 if (work) {
180 g_hash_table_remove(window_geom_hash, name);
181 g_free(work->key);
182 g_free(work);
183 }
184  
185 /* g_malloc and insert the new one */
186 work = (window_geometry_t *)g_malloc(sizeof(window_geometry_t));
187 *work = *geom;
188 key = g_strdup(name);
189 work->key = key;
190 g_hash_table_insert(window_geom_hash, key, work);
191 }
192  
193 /* load the desired geometry for this window from the geometry hashtable */
194 gboolean
195 window_geom_load(const gchar *name,
196 window_geometry_t *geom)
197 {
198 window_geometry_t *p;
199  
200 /* init hashtable, if not already done */
201 if (!window_geom_hash) {
202 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
203 }
204  
205 p = (window_geometry_t *)g_hash_table_lookup(window_geom_hash, name);
206 if (p) {
207 *geom = *p;
208 return TRUE;
209 } else {
210 return FALSE;
211 }
212 }
213  
214 /* parse values of particular types */
215 static void
216 parse_recent_boolean(const gchar *val_str, gboolean *valuep)
217 {
218 if (g_ascii_strcasecmp(val_str, "true") == 0) {
219 *valuep = TRUE;
220 }
221 else {
222 *valuep = FALSE;
223 }
224 }
225  
226 /** Read in a single geometry key value pair from the recent file.
227 *
228 * @param name the geom_name of the window
229 * @param key the subkey of this pair (e.g. "x")
230 * @param value the new value (e.g. "123")
231 */
232 static void
233 window_geom_recent_read_pair(const char *name,
234 const char *key,
235 const char *value)
236 {
237 window_geometry_t geom;
238  
239 /* find window geometry maybe already in hashtable */
240 if (!window_geom_load(name, &geom)) {
241 /* not in table, init geom with "basic" values */
242 geom.key = NULL; /* Will be set in window_geom_save() */
243 geom.set_pos = FALSE;
244 geom.x = -1;
245 geom.y = -1;
246 geom.set_size = FALSE;
247 geom.width = -1;
248 geom.height = -1;
249  
250 geom.set_maximized = FALSE;/* this is valid in GTK2 only */
251 geom.maximized = FALSE; /* this is valid in GTK2 only */
252 }
253  
254 if (strcmp(key, "x") == 0) {
255 geom.x = (gint)strtol(value, NULL, 10);
256 geom.set_pos = TRUE;
257 } else if (strcmp(key, "y") == 0) {
258 geom.y = (gint)strtol(value, NULL, 10);
259 geom.set_pos = TRUE;
260 } else if (strcmp(key, "width") == 0) {
261 geom.width = (gint)strtol(value, NULL, 10);
262 geom.set_size = TRUE;
263 } else if (strcmp(key, "height") == 0) {
264 geom.height = (gint)strtol(value, NULL, 10);
265 geom.set_size = TRUE;
266 } else if (strcmp(key, "maximized") == 0) {
267 parse_recent_boolean(value, &geom.maximized);
268 geom.set_maximized = TRUE;
269 } else {
270 /*
271 * Silently ignore the bogus key. We shouldn't abort here,
272 * as this could be due to a corrupt recent file.
273 *
274 * XXX - should we print a message about this?
275 */
276 return;
277 }
278  
279 /* save / replace geometry in hashtable */
280 window_geom_save(name, &geom);
281 }
282  
283 /** Write all geometry values of all windows to the recent file.
284 * Will call write_recent_geom() for every existing window type.
285 *
286 * @param rf recent file handle from caller
287 */
288 static void
289 window_geom_recent_write_all(FILE *rf)
290 {
291 /* init hashtable, if not already done */
292 if (!window_geom_hash) {
293 window_geom_hash = g_hash_table_new(g_str_hash, g_str_equal);
294 }
295  
296 g_hash_table_foreach(window_geom_hash, write_recent_geom, rf);
297 }
298  
299 /* Global list of recent capture filters. */
300 static GList *recent_cfilter_list;
301  
302 /*
303 * Per-interface lists of recent capture filters; stored in a hash
304 * table indexed by interface name.
305 */
306 static GHashTable *per_interface_cfilter_lists_hash;
307  
308 /* XXX: use a preference for this setting! */
309 static guint cfilter_combo_max_recent = 20;
310  
311 /**
312 * Returns a list of recent capture filters.
313 *
314 * @param ifname interface name; NULL refers to the global list.
315 */
316 GList *
317 recent_get_cfilter_list(const gchar *ifname)
318 {
319 if (ifname == NULL)
320 return recent_cfilter_list;
321 if (per_interface_cfilter_lists_hash == NULL) {
322 /* No such lists exist. */
323 return NULL;
324 }
325 return (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
326 }
327  
328 /**
329 * Add a capture filter to the global recent capture filter list or
330 * the recent capture filter list for an interface.
331 *
332 * @param ifname interface name; NULL refers to the global list.
333 * @param s text of capture filter
334 */
335 void
336 recent_add_cfilter(const gchar *ifname, const gchar *s)
337 {
338 GList *cfilter_list;
339 GList *li;
340 gchar *li_filter, *newfilter = NULL;
341  
342 /* Don't add empty filters to the list. */
343 if (s[0] == '\0')
344 return;
345  
346 if (ifname == NULL)
347 cfilter_list = recent_cfilter_list;
348 else {
349 /* If we don't yet have a hash table for per-interface recent
350 capture filter lists, create one. Have it free the new key
351 if we're updating an entry rather than creating it below. */
352 if (per_interface_cfilter_lists_hash == NULL)
353 per_interface_cfilter_lists_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
354 cfilter_list = (GList *)g_hash_table_lookup(per_interface_cfilter_lists_hash, ifname);
355 }
356  
357 li = g_list_first(cfilter_list);
358 while (li) {
359 /* If the filter is already in the list, remove the old one and
360 * append the new one at the latest position (at g_list_append() below) */
361 li_filter = (char *)li->data;
362 if (strcmp(s, li_filter) == 0) {
363 /* No need to copy the string, we're just moving it. */
364 newfilter = li_filter;
365 cfilter_list = g_list_remove(cfilter_list, li->data);
366 break;
367 }
368 li = li->next;
369 }
370 if (newfilter == NULL) {
371 /* The filter wasn't already in the list; make a copy to add. */
372 newfilter = g_strdup(s);
373 }
374 cfilter_list = g_list_append(cfilter_list, newfilter);
375  
376 if (ifname == NULL)
377 recent_cfilter_list = cfilter_list;
378 else
379 g_hash_table_insert(per_interface_cfilter_lists_hash, g_strdup(ifname), cfilter_list);
380 }
381  
382 #ifdef HAVE_PCAP_REMOTE
383 static GHashTable *remote_host_list=NULL;
384  
385 int recent_get_remote_host_list_size(void)
386 {
387 return g_hash_table_size (remote_host_list);
388 }
389  
390 void recent_add_remote_host(gchar *host, struct remote_host *rh)
391 {
392 if (remote_host_list == NULL) {
393 remote_host_list = g_hash_table_new (g_str_hash, g_str_equal);
394 }
395 g_hash_table_insert (remote_host_list, g_strdup(host), rh);
396 }
397  
398 static gboolean
399 free_remote_host (gpointer key _U_, gpointer value, gpointer user _U_)
400 {
401 struct remote_host *rh = value;
402  
403 g_free (rh->r_host);
404 g_free (rh->remote_port);
405 g_free (rh->auth_username);
406 g_free (rh->auth_password);
407  
408 return TRUE;
409 }
410  
411 GHashTable *get_remote_host_list(void)
412 {
413 return remote_host_list;
414 }
415  
416 static void
417 recent_print_remote_host (gpointer key _U_, gpointer value, gpointer user)
418 {
419 FILE *rf = user;
420 struct remote_host_info *ri = value;
421  
422 fprintf (rf, RECENT_KEY_REMOTE_HOST ": %s,%s,%d\n", ri->remote_host, ri->remote_port, ri->auth_type);
423 }
424  
425 void
426 capture_remote_combo_recent_write_all(FILE *rf)
427 {
428 if (remote_host_list && g_hash_table_size (remote_host_list) > 0) {
429 /* Write all remote interfaces to the recent file */
430 g_hash_table_foreach (remote_host_list, recent_print_remote_host, rf);
431 }
432 }
433  
434  
435 void free_remote_host_list(void)
436 {
437 g_hash_table_foreach_remove(remote_host_list, free_remote_host, NULL);
438 }
439  
440 struct remote_host *
441 recent_get_remote_host(const gchar *host)
442 {
443 if (host == NULL)
444 return NULL;
445 if (remote_host_list == NULL) {
446 /* No such host exist. */
447 return NULL;
448 }
449 return (struct remote_host *)g_hash_table_lookup(remote_host_list, host);
450 }
451  
452 gboolean
453 capture_remote_combo_add_recent(const gchar *s)
454 {
455 GList *vals = prefs_get_string_list (s);
456 GList *valp = vals;
457 gint auth_type;
458 char *p;
459 struct remote_host *rh;
460  
461 if (valp == NULL)
462 return FALSE;
463  
464 if (remote_host_list == NULL) {
465 remote_host_list = g_hash_table_new (g_str_hash, g_str_equal);
466 }
467  
468 rh = g_malloc (sizeof (*rh));
469  
470 /* First value is the host */
471 rh->r_host = g_strdup (valp->data);
472 if (strlen(rh->r_host) == 0) {
473 /* Empty remote host */
474 g_free(rh->r_host);
475 g_free(rh);
476 return FALSE;
477 }
478 rh->auth_type = CAPTURE_AUTH_NULL;
479 valp = valp->next;
480  
481 if (valp) {
482 /* Found value 2, this is the port number */
483 rh->remote_port = g_strdup (valp->data);
484 valp = valp->next;
485 } else {
486 /* Did not find a port number */
487 rh->remote_port = g_strdup ("");
488 }
489  
490 if (valp) {
491 /* Found value 3, this is the authentication type */
492 auth_type = strtol(valp->data, &p, 0);
493 if (p != valp->data && *p == '\0') {
494 rh->auth_type = auth_type;
495 }
496 }
497  
498 /* Do not store username and password */
499 rh->auth_username = g_strdup ("");
500 rh->auth_password = g_strdup ("");
501  
502 prefs_clear_string_list(vals);
503  
504 g_hash_table_insert (remote_host_list, g_strdup(rh->r_host), rh);
505  
506 return TRUE;
507 }
508 #endif
509  
510 static void
511 cfilter_recent_write_all_list(FILE *rf, const gchar *ifname, GList *cfilter_list)
512 {
513 guint max_count = 0;
514 GList *li;
515  
516 /* write all non empty capture filter strings to the recent file (until max count) */
517 li = g_list_first(cfilter_list);
518 while (li && (max_count++ <= cfilter_combo_max_recent) ) {
519 if (li->data && strlen((const char *)li->data)) {
520 if (ifname == NULL)
521 fprintf (rf, RECENT_KEY_CAPTURE_FILTER ": %s\n", (char *)li->data);
522 else
523 fprintf (rf, RECENT_KEY_CAPTURE_FILTER ".%s: %s\n", ifname, (char *)li->data);
524 }
525 li = li->next;
526 }
527 }
528  
529 static void
530 cfilter_recent_write_all_hash_callback(gpointer key, gpointer value, gpointer user_data)
531 {
532 cfilter_recent_write_all_list((FILE *)user_data, (const gchar *)key, (GList *)value);
533 }
534  
535 /** Write all capture filter values to the recent file.
536 *
537 * @param rf recent file handle from caller
538 */
539 static void
540 cfilter_recent_write_all(FILE *rf)
541 {
542 /* Write out the global list. */
543 cfilter_recent_write_all_list(rf, NULL, recent_cfilter_list);
544  
545 /* Write out all the per-interface lists. */
546 if (per_interface_cfilter_lists_hash != NULL) {
547 g_hash_table_foreach(per_interface_cfilter_lists_hash, cfilter_recent_write_all_hash_callback, (gpointer)rf);
548 }
549 }
550  
551 /* Write out recent settings of particular types. */
552 static void
553 write_recent_boolean(FILE *rf, const char *description, const char *name,
554 gboolean value)
555 {
556 fprintf(rf, "\n# %s.\n", description);
557 fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
558 fprintf(rf, "%s: %s\n", name, value == TRUE ? "TRUE" : "FALSE");
559 }
560  
561 static void
562 write_recent_enum(FILE *rf, const char *description, const char *name,
563 const value_string *values, guint value)
564 {
565 const char *if_invalid = NULL;
566 const value_string *valp;
567  
568 fprintf(rf, "\n# %s.\n", description);
569 fprintf(rf, "# One of: ");
570 valp = values;
571 while (valp->strptr != NULL) {
572 if (if_invalid == NULL)
573 if_invalid = valp->strptr;
574 fprintf(rf, "%s", valp->strptr);
575 valp++;
576 if (valp->strptr != NULL)
577 fprintf(rf, ", ");
578 }
579 fprintf(rf, "\n");
580 fprintf(rf, "%s: %s\n", name,
581 val_to_str(value, values, if_invalid != NULL ? if_invalid : "Unknown"));
582 }
583  
584 /* Attempt to write out "recent common" to the user's recent common file.
585 If we got an error report it with a dialog box and return FALSE,
586 otherwise return TRUE. */
587 gboolean
588 write_recent(void)
589 {
590 char *pf_dir_path;
591 char *rf_path;
592 FILE *rf;
593 char *string_list;
594  
595 /* To do:
596 * - Split output lines longer than MAX_VAL_LEN
597 * - Create a function for the preference directory check/creation
598 * so that duplication can be avoided with filter.c
599 */
600  
601 /* Create the directory that holds personal configuration files, if
602 necessary. */
603 if (create_persconffile_dir(&pf_dir_path) == -1) {
604 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
605 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
606 g_strerror(errno));
607 g_free(pf_dir_path);
608 return FALSE;
609 }
610  
611 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
612 if ((rf = ws_fopen(rf_path, "w")) == NULL) {
613 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
614 "Can't open recent file\n\"%s\": %s.", rf_path,
615 g_strerror(errno));
616 g_free(rf_path);
617 return FALSE;
618 }
619 g_free(rf_path);
620  
621 fputs("# Recent settings file for Wireshark " VERSION ".\n"
622 "#\n"
623 "# This file is regenerated each time Wireshark is quit.\n"
624 "# So be careful, if you want to make manual changes here.\n"
625 "\n"
626 "######## Recent capture files (latest last), cannot be altered through command line ########\n"
627 "\n", rf);
628  
629 menu_recent_file_write_all(rf);
630  
631 fputs("\n"
632 "######## Recent capture filters (latest last), cannot be altered through command line ########\n"
633 "\n", rf);
634  
635 cfilter_recent_write_all(rf);
636  
637 fputs("\n"
638 "######## Recent display filters (latest last), cannot be altered through command line ########\n"
639 "\n", rf);
640  
641 dfilter_recent_combo_write_all(rf);
642  
643 #ifdef HAVE_PCAP_REMOTE
644 fputs("\n"
645 "######## Recent remote hosts, cannot be altered through command line ########\n"
646 "\n", rf);
647  
648 capture_remote_combo_recent_write_all(rf);
649 #endif
650  
651 fprintf(rf, "\n# Main window geometry.\n");
652 fprintf(rf, "# Decimal numbers.\n");
653 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
654 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
655 fprintf(rf, RECENT_GUI_GTK_GEOMETRY_MAIN_X ": %d\n", recent.gui_gtk_geometry_main_x);
656 fprintf(rf, RECENT_GUI_GTK_GEOMETRY_MAIN_Y ": %d\n", recent.gui_gtk_geometry_main_y);
657 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
658 recent.gui_geometry_main_width);
659 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
660 recent.gui_geometry_main_height);
661  
662 write_recent_boolean(rf, "Main window maximized",
663 RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED,
664 recent.gui_geometry_main_maximized);
665  
666 fprintf(rf, "\n# Statusbar left pane size.\n");
667 fprintf(rf, "# Decimal number.\n");
668 if (recent.gui_geometry_status_pane_left != 0) {
669 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT ": %d\n",
670 recent.gui_geometry_status_pane_left);
671 }
672 fprintf(rf, "\n# Statusbar middle pane size.\n");
673 fprintf(rf, "# Decimal number.\n");
674 if (recent.gui_geometry_status_pane_right != 0) {
675 fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT ": %d\n",
676 recent.gui_geometry_status_pane_right);
677 }
678  
679 fprintf(rf, "\n# Last used Configuration Profile.\n");
680 fprintf(rf, RECENT_LAST_USED_PROFILE ": %s\n", get_profile_name());
681  
682 fprintf(rf, "\n# WLAN statistics upper pane size.\n");
683 fprintf(rf, "# Decimal number.\n");
684 fprintf(rf, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE ": %d\n",
685 recent.gui_geometry_wlan_stats_pane);
686  
687 write_recent_boolean(rf, "Warn if running with elevated permissions (e.g. as root)",
688 RECENT_KEY_PRIVS_WARN_IF_ELEVATED,
689 recent.privs_warn_if_elevated);
690  
691 write_recent_boolean(rf, "Warn if npf.sys isn't loaded on Windows >= 6.0",
692 RECENT_KEY_PRIVS_WARN_IF_NO_NPF,
693 recent.privs_warn_if_no_npf);
694  
695 window_geom_recent_write_all(rf);
696  
697 fprintf(rf, "\n# Custom colors.\n");
698 fprintf(rf, "# List of custom colors selected in Qt color picker.\n");
699 string_list = join_string_list(recent.custom_colors);
700 fprintf(rf, RECENT_GUI_CUSTOM_COLORS ": %s\n", string_list);
701 g_free(string_list);
702  
703 fclose(rf);
704  
705 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
706 an error indication, or maybe write to a new recent file and
707 rename that file on top of the old one only if there are not I/O
708 errors. */
709 return TRUE;
710 }
711  
712  
713 /* Attempt to Write out profile "recent" to the user's profile recent file.
714 If we got an error report it with a dialog box and return FALSE,
715 otherwise return TRUE. */
716 gboolean
717 write_profile_recent(void)
718 {
719 char *pf_dir_path;
720 char *rf_path;
721 char *string_list;
722 FILE *rf;
723  
724 /* To do:
725 * - Split output lines longer than MAX_VAL_LEN
726 * - Create a function for the preference directory check/creation
727 * so that duplication can be avoided with filter.c
728 */
729  
730 /* Create the directory that holds personal configuration files, if
731 necessary. */
732 if (create_persconffile_dir(&pf_dir_path) == -1) {
733 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
734 "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
735 g_strerror(errno));
736 g_free(pf_dir_path);
737 return FALSE;
738 }
739  
740 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
741 if ((rf = ws_fopen(rf_path, "w")) == NULL) {
742 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
743 "Can't open recent file\n\"%s\": %s.", rf_path,
744 g_strerror(errno));
745 g_free(rf_path);
746 return FALSE;
747 }
748 g_free(rf_path);
749  
750 fputs("# Recent settings file for Wireshark " VERSION ".\n"
751 "#\n"
752 "# This file is regenerated each time Wireshark is quit\n"
753 "# and when changing configuration profile.\n"
754 "# So be careful, if you want to make manual changes here.\n"
755 "\n", rf);
756  
757 write_recent_boolean(rf, "Main Toolbar show (hide)",
758 RECENT_KEY_MAIN_TOOLBAR_SHOW,
759 recent.main_toolbar_show);
760  
761 write_recent_boolean(rf, "Filter Toolbar show (hide)",
762 RECENT_KEY_FILTER_TOOLBAR_SHOW,
763 recent.filter_toolbar_show);
764  
765 write_recent_boolean(rf, "Wireless Settings Toolbar show (hide)",
766 RECENT_KEY_WIRELESS_TOOLBAR_SHOW,
767 recent.wireless_toolbar_show);
768  
769 #ifdef HAVE_AIRPCAP
770 write_recent_boolean(rf, "Show (hide) old AirPcap driver warning dialog box",
771 RECENT_KEY_DRIVER_CHECK_SHOW,
772 recent.airpcap_driver_check_show);
773 #endif
774  
775 write_recent_boolean(rf, "Packet list show (hide)",
776 RECENT_KEY_PACKET_LIST_SHOW,
777 recent.packet_list_show);
778  
779 write_recent_boolean(rf, "Tree view show (hide)",
780 RECENT_KEY_TREE_VIEW_SHOW,
781 recent.tree_view_show);
782  
783 write_recent_boolean(rf, "Byte view show (hide)",
784 RECENT_KEY_BYTE_VIEW_SHOW,
785 recent.byte_view_show);
786  
787 write_recent_boolean(rf, "Statusbar show (hide)",
788 RECENT_KEY_STATUSBAR_SHOW,
789 recent.statusbar_show);
790  
791 write_recent_boolean(rf, "Packet list colorize (hide)",
792 RECENT_KEY_PACKET_LIST_COLORIZE,
793 recent.packet_list_colorize);
794  
795 write_recent_enum(rf, "Timestamp display format",
796 RECENT_GUI_TIME_FORMAT, ts_type_values,
797 recent.gui_time_format);
798  
799 write_recent_enum(rf, "Timestamp display precision",
800 RECENT_GUI_TIME_PRECISION, ts_precision_values,
801 recent.gui_time_precision);
802  
803 write_recent_enum(rf, "Seconds display format",
804 RECENT_GUI_SECONDS_FORMAT, ts_seconds_values,
805 recent.gui_seconds_format);
806  
807 fprintf(rf, "\n# Zoom level.\n");
808 fprintf(rf, "# A decimal number.\n");
809 fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
810 recent.gui_zoom_level);
811  
812 fprintf(rf, "\n# Bytes view.\n");
813 fprintf(rf, "# A decimal number.\n");
814 fprintf(rf, RECENT_GUI_BYTES_VIEW ": %d\n",
815 recent.gui_bytes_view);
816  
817 fprintf(rf, "\n# Main window upper (or leftmost) pane size.\n");
818 fprintf(rf, "# Decimal number.\n");
819 if (recent.gui_geometry_main_upper_pane != 0) {
820 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
821 recent.gui_geometry_main_upper_pane);
822 }
823 fprintf(rf, "\n# Main window middle pane size.\n");
824 fprintf(rf, "# Decimal number.\n");
825 if (recent.gui_geometry_main_lower_pane != 0) {
826 fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
827 recent.gui_geometry_main_lower_pane);
828 }
829  
830 fprintf(rf, "\n# Packet list column pixel widths.\n");
831 fprintf(rf, "# Each pair of strings consists of a column format and its pixel width.\n");
832 packet_list_recent_write_all(rf);
833  
834 fprintf(rf, "\n# Open conversation dialog tabs.\n");
835 fprintf(rf, "# List of conversation names, e.g. \"TCP\", \"IPv6\".\n");
836 string_list = join_string_list(recent.conversation_tabs);
837 fprintf(rf, RECENT_GUI_CONVERSATION_TABS ": %s\n", string_list);
838 g_free(string_list);
839  
840 fprintf(rf, "\n# Open endpoint dialog tabs.\n");
841 fprintf(rf, "# List of endpoint names, e.g. \"TCP\", \"IPv6\".\n");
842 string_list = join_string_list(recent.endpoint_tabs);
843 fprintf(rf, RECENT_GUI_ENDPOINT_TABS ": %s\n", string_list);
844 g_free(string_list);
845  
846 write_recent_boolean(rf, "For RLC stats, whether to use RLC PDUs found inside MAC frames",
847 RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES,
848 recent.gui_rlc_use_pdus_from_mac);
849  
850 if (get_last_open_dir() != NULL) {
851 fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
852 fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", get_last_open_dir());
853 }
854  
855 fclose(rf);
856  
857 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
858 an error indication, or maybe write to a new recent file and
859 rename that file on top of the old one only if there are not I/O
860 errors. */
861 return TRUE;
862 }
863  
864 /* set one user's recent common file key/value pair */
865 static prefs_set_pref_e
866 read_set_recent_common_pair_static(gchar *key, const gchar *value,
867 void *private_data _U_,
868 gboolean return_range_errors _U_)
869 {
870 long num;
871 char *p;
872  
873 if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
874 parse_recent_boolean(value, &recent.gui_geometry_main_maximized);
875 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
876 num = strtol(value, &p, 0);
877 if (p == value || *p != '\0')
878 return PREFS_SET_SYNTAX_ERR; /* number was bad */
879 recent.gui_geometry_main_x = (gint)num;
880 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
881 num = strtol(value, &p, 0);
882 if (p == value || *p != '\0')
883 return PREFS_SET_SYNTAX_ERR; /* number was bad */
884 recent.gui_geometry_main_y = (gint)num;
885 } else if (strcmp(key, RECENT_GUI_GTK_GEOMETRY_MAIN_X) == 0) {
886 num = strtol(value, &p, 0);
887 if (p == value || *p != '\0')
888 return PREFS_SET_SYNTAX_ERR; /* number was bad */
889 recent.gui_gtk_geometry_main_x = (gint)num;
890 } else if (strcmp(key, RECENT_GUI_GTK_GEOMETRY_MAIN_Y) == 0) {
891 num = strtol(value, &p, 0);
892 if (p == value || *p != '\0')
893 return PREFS_SET_SYNTAX_ERR; /* number was bad */
894 recent.gui_gtk_geometry_main_y = (gint)num;
895 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
896 num = strtol(value, &p, 0);
897 if (p == value || *p != '\0')
898 return PREFS_SET_SYNTAX_ERR; /* number was bad */
899 if (num <= 0)
900 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
901 recent.gui_geometry_main_width = (gint)num;
902 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
903 num = strtol(value, &p, 0);
904 if (p == value || *p != '\0')
905 return PREFS_SET_SYNTAX_ERR; /* number was bad */
906 if (num <= 0)
907 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
908 recent.gui_geometry_main_height = (gint)num;
909 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_RIGHT) == 0) {
910 num = strtol(value, &p, 0);
911 if (p == value || *p != '\0')
912 return PREFS_SET_SYNTAX_ERR; /* number was bad */
913 if (num <= 0)
914 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
915 recent.gui_geometry_status_pane_right = (gint)num;
916 recent.has_gui_geometry_status_pane = TRUE;
917 } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT) == 0) {
918 num = strtol(value, &p, 0);
919 if (p == value || *p != '\0')
920 return PREFS_SET_SYNTAX_ERR; /* number was bad */
921 if (num <= 0)
922 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
923 recent.gui_geometry_status_pane_left = (gint)num;
924 recent.has_gui_geometry_status_pane = TRUE;
925 } else if (strcmp(key, RECENT_LAST_USED_PROFILE) == 0) {
926 if ((strcmp(value, DEFAULT_PROFILE) != 0) && profile_exists (value, FALSE)) {
927 set_profile_name (value);
928 }
929 } else if (strcmp(key, RECENT_GUI_GEOMETRY_WLAN_STATS_PANE) == 0) {
930 num = strtol(value, &p, 0);
931 if (p == value || *p != '\0')
932 return PREFS_SET_SYNTAX_ERR; /* number was bad */
933 if (num <= 0)
934 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
935 recent.gui_geometry_wlan_stats_pane = (gint)num;
936 } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
937 /* now have something like "gui.geom.main.x", split it into win and sub_key */
938 char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1];
939 char *sub_key = strchr(win, '.');
940 if (sub_key) {
941 *sub_key = '\0';
942 sub_key++;
943 window_geom_recent_read_pair(win, sub_key, value);
944 }
945 } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_ELEVATED) == 0) {
946 parse_recent_boolean(value, &recent.privs_warn_if_elevated);
947 } else if (strcmp(key, RECENT_KEY_PRIVS_WARN_IF_NO_NPF) == 0) {
948 parse_recent_boolean(value, &recent.privs_warn_if_no_npf);
949 } else if (strcmp(key, RECENT_GUI_CUSTOM_COLORS) == 0) {
950 recent.custom_colors = prefs_get_string_list(value);
951 }
952  
953 return PREFS_SET_OK;
954 }
955  
956 /* set one user's recent file key/value pair */
957 static prefs_set_pref_e
958 read_set_recent_pair_static(gchar *key, const gchar *value,
959 void *private_data _U_,
960 gboolean return_range_errors _U_)
961 {
962 long num;
963 char *p;
964 GList *col_l, *col_l_elt;
965 col_width_data *cfmt;
966 const gchar *cust_format = col_format_to_string(COL_CUSTOM);
967 int cust_format_len = (int) strlen(cust_format);
968  
969 if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
970 parse_recent_boolean(value, &recent.main_toolbar_show);
971 } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW) == 0) {
972 parse_recent_boolean(value, &recent.filter_toolbar_show);
973 /* check both the old and the new keyword */
974 } else if (strcmp(key, RECENT_KEY_WIRELESS_TOOLBAR_SHOW) == 0 || (strcmp(key, "gui.airpcap_toolbar_show") == 0)) {
975 parse_recent_boolean(value, &recent.wireless_toolbar_show);
976 } else if (strcmp(key, RECENT_KEY_DRIVER_CHECK_SHOW) == 0) {
977 parse_recent_boolean(value, &recent.airpcap_driver_check_show);
978 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW) == 0) {
979 parse_recent_boolean(value, &recent.packet_list_show);
980 } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW) == 0) {
981 parse_recent_boolean(value, &recent.tree_view_show);
982 } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW) == 0) {
983 parse_recent_boolean(value, &recent.byte_view_show);
984 } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW) == 0) {
985 parse_recent_boolean(value, &recent.statusbar_show);
986 } else if (strcmp(key, RECENT_KEY_PACKET_LIST_COLORIZE) == 0) {
987 parse_recent_boolean(value, &recent.packet_list_colorize);
988 } else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
989 recent.gui_time_format =
990 (ts_type)str_to_val(value, ts_type_values, TS_RELATIVE);
991 } else if (strcmp(key, RECENT_GUI_TIME_PRECISION) == 0) {
992 recent.gui_time_precision =
993 (ts_precision)str_to_val(value, ts_precision_values, TS_PREC_AUTO);
994 } else if (strcmp(key, RECENT_GUI_SECONDS_FORMAT) == 0) {
995 recent.gui_seconds_format =
996 (ts_seconds_type)str_to_val(value, ts_seconds_values, TS_SECONDS_DEFAULT);
997 } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
998 num = strtol(value, &p, 0);
999 if (p == value || *p != '\0')
1000 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1001 recent.gui_zoom_level = (gint)num;
1002 } else if (strcmp(key, RECENT_GUI_BYTES_VIEW) == 0) {
1003 num = strtol(value, &p, 0);
1004 if (p == value || *p != '\0')
1005 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1006 recent.gui_bytes_view = (bytes_view_type)num;
1007 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
1008 parse_recent_boolean(value, &recent.gui_geometry_main_maximized);
1009 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
1010 num = strtol(value, &p, 0);
1011 if (p == value || *p != '\0')
1012 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1013 if (num <= 0)
1014 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1015 recent.gui_geometry_main_upper_pane = (gint)num;
1016 recent.has_gui_geometry_main_upper_pane = TRUE;
1017 } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
1018 num = strtol(value, &p, 0);
1019 if (p == value || *p != '\0')
1020 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1021 if (num <= 0)
1022 return PREFS_SET_SYNTAX_ERR; /* number must be positive */
1023 recent.gui_geometry_main_lower_pane = (gint)num;
1024 recent.has_gui_geometry_main_lower_pane = TRUE;
1025 } else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS) == 0) {
1026 recent.conversation_tabs = prefs_get_string_list(value);
1027 } else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS) == 0) {
1028 recent.endpoint_tabs = prefs_get_string_list(value);
1029 } else if (strcmp(key, RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES) == 0) {
1030 parse_recent_boolean(value, &recent.gui_rlc_use_pdus_from_mac);
1031 } else if (strcmp(key, RECENT_KEY_COL_WIDTH) == 0) {
1032 col_l = prefs_get_string_list(value);
1033 if (col_l == NULL)
1034 return PREFS_SET_SYNTAX_ERR;
1035 if ((g_list_length(col_l) % 2) != 0) {
1036 /* A title didn't have a matching width. */
1037 prefs_clear_string_list(col_l);
1038 return PREFS_SET_SYNTAX_ERR;
1039 }
1040 /* Check to make sure all column formats are valid. */
1041 col_l_elt = g_list_first(col_l);
1042 while (col_l_elt) {
1043 /* Make sure the format isn't empty. */
1044 if (strcmp((const char *)col_l_elt->data, "") == 0) {
1045 /* It is. */
1046 prefs_clear_string_list(col_l);
1047 return PREFS_SET_SYNTAX_ERR;
1048 }
1049  
1050 /* Check the format. */
1051 if (strncmp((const char *)col_l_elt->data, cust_format, cust_format_len) != 0) {
1052 if (get_column_format_from_str((const gchar *)col_l_elt->data) == -1) {
1053 /* It's not a valid column format. */
1054 prefs_clear_string_list(col_l);
1055 return PREFS_SET_SYNTAX_ERR;
1056 }
1057 }
1058  
1059 /* Go past the format. */
1060 col_l_elt = col_l_elt->next;
1061  
1062 /* Go past the width. */
1063 col_l_elt = col_l_elt->next;
1064 }
1065 free_col_width_info(&recent);
1066 recent.col_width_list = NULL;
1067 col_l_elt = g_list_first(col_l);
1068 while (col_l_elt) {
1069 gchar *fmt = g_strdup((const gchar *)col_l_elt->data);
1070 cfmt = (col_width_data *) g_malloc(sizeof(col_width_data));
1071 if (strncmp(fmt, cust_format, cust_format_len) != 0) {
1072 cfmt->cfmt = get_column_format_from_str(fmt);
1073 cfmt->cfield = NULL;
1074 } else {
1075 cfmt->cfmt = COL_CUSTOM;
1076 cfmt->cfield = g_strdup(&fmt[cust_format_len+1]); /* add 1 for ':' */
1077 }
1078 g_free (fmt);
1079 if (cfmt->cfmt == -1) {
1080 g_free(cfmt->cfield);
1081 g_free(cfmt);
1082 return PREFS_SET_SYNTAX_ERR; /* string was bad */
1083 }
1084  
1085 col_l_elt = col_l_elt->next;
1086 cfmt->width = (gint)strtol((const char *)col_l_elt->data, &p, 0);
1087 if (p == col_l_elt->data || (*p != '\0' && *p != ':')) {
1088 g_free(cfmt->cfield);
1089 g_free(cfmt);
1090 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1091 }
1092  
1093 if (*p == ':') {
1094 cfmt->xalign = *(++p);
1095 } else {
1096 cfmt->xalign = COLUMN_XALIGN_DEFAULT;
1097 }
1098  
1099 col_l_elt = col_l_elt->next;
1100 recent.col_width_list = g_list_append(recent.col_width_list, cfmt);
1101 }
1102 prefs_clear_string_list(col_l);
1103 } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
1104 if (recent.gui_fileopen_remembered_dir) {
1105 g_free (recent.gui_fileopen_remembered_dir);
1106 }
1107 recent.gui_fileopen_remembered_dir = g_strdup(value);
1108 }
1109  
1110 return PREFS_SET_OK;
1111 }
1112  
1113  
1114 /* set one user's recent file key/value pair */
1115 static prefs_set_pref_e
1116 read_set_recent_pair_dynamic(gchar *key, const gchar *value,
1117 void *private_data _U_,
1118 gboolean return_range_errors _U_)
1119 {
1120 if (!g_utf8_validate(value, -1, NULL)) {
1121 return PREFS_SET_SYNTAX_ERR;
1122 }
1123 if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
1124 add_menu_recent_capture_file(value);
1125 } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
1126 dfilter_combo_add_recent(value);
1127 } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) {
1128 recent_add_cfilter(NULL, value);
1129 } else if (g_str_has_prefix(key, RECENT_KEY_CAPTURE_FILTER ".")) {
1130 /* strrchr() can't fail - string has a prefix that ends with a "." */
1131 recent_add_cfilter(strrchr(key, '.') + 1, value);
1132 #ifdef HAVE_PCAP_REMOTE
1133 } else if (strcmp(key, RECENT_KEY_REMOTE_HOST) == 0) {
1134 capture_remote_combo_add_recent(value);
1135 #endif
1136 }
1137  
1138 return PREFS_SET_OK;
1139 }
1140  
1141  
1142 /*
1143 * Given a string of the form "<recent name>:<recent value>", as might appear
1144 * as an argument to a "-o" option, parse it and set the recent value in
1145 * question. Return an indication of whether it succeeded or failed
1146 * in some fashion.
1147 */
1148 int
1149 recent_set_arg(char *prefarg)
1150 {
1151 gchar *p, *colonp;
1152 int ret;
1153  
1154 colonp = strchr(prefarg, ':');
1155 if (colonp == NULL)
1156 return PREFS_SET_SYNTAX_ERR;
1157  
1158 p = colonp;
1159 *p++ = '\0';
1160  
1161 /*
1162 * Skip over any white space (there probably won't be any, but
1163 * as we allow it in the preferences file, we might as well
1164 * allow it here).
1165 */
1166 while (g_ascii_isspace(*p))
1167 p++;
1168 if (*p == '\0') {
1169 /*
1170 * Put the colon back, so if our caller uses, in an
1171 * error message, the string they passed us, the message
1172 * looks correct.
1173 */
1174 *colonp = ':';
1175 return PREFS_SET_SYNTAX_ERR;
1176 }
1177  
1178 ret = read_set_recent_pair_static(prefarg, p, NULL, TRUE);
1179 *colonp = ':'; /* put the colon back */
1180 return ret;
1181 }
1182  
1183  
1184 /* opens the user's recent common file and read the first part */
1185 gboolean
1186 recent_read_static(char **rf_path_return, int *rf_errno_return)
1187 {
1188 char *rf_path;
1189 FILE *rf;
1190  
1191 /* set defaults */
1192 recent.gui_geometry_main_x = 20;
1193 recent.gui_geometry_main_y = 20;
1194 recent.gui_gtk_geometry_main_x = 20;
1195 recent.gui_gtk_geometry_main_y = 20;
1196 recent.gui_geometry_main_width = DEF_WIDTH;
1197 recent.gui_geometry_main_height = DEF_HEIGHT;
1198 recent.gui_geometry_main_maximized= FALSE;
1199  
1200 recent.gui_geometry_status_pane_left = (DEF_WIDTH/3);
1201 recent.gui_geometry_status_pane_right = (DEF_WIDTH/3);
1202 recent.gui_geometry_wlan_stats_pane = 200;
1203  
1204 recent.privs_warn_if_elevated = TRUE;
1205 recent.privs_warn_if_no_npf = TRUE;
1206  
1207 recent.col_width_list = NULL;
1208 recent.gui_fileopen_remembered_dir = NULL;
1209  
1210 /* Construct the pathname of the user's recent common file. */
1211 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1212  
1213 /* Read the user's recent common file, if it exists. */
1214 *rf_path_return = NULL;
1215 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1216 /* We succeeded in opening it; read it. */
1217 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL);
1218  
1219 fclose(rf);
1220 } else {
1221 /* We failed to open it. If we failed for some reason other than
1222 "it doesn't exist", return the errno and the pathname, so our
1223 caller can report the error. */
1224 if (errno != ENOENT) {
1225 *rf_errno_return = errno;
1226 *rf_path_return = rf_path;
1227 return FALSE;
1228 }
1229 }
1230 g_free(rf_path);
1231 return TRUE;
1232 }
1233  
1234  
1235  
1236 /* opens the user's recent file and read the first part */
1237 gboolean
1238 recent_read_profile_static(char **rf_path_return, int *rf_errno_return)
1239 {
1240 char *rf_path, *rf_common_path;
1241 FILE *rf;
1242  
1243 /* set defaults */
1244 recent.main_toolbar_show = TRUE;
1245 recent.filter_toolbar_show = TRUE;
1246 recent.wireless_toolbar_show = FALSE;
1247 recent.airpcap_driver_check_show = TRUE;
1248 recent.packet_list_show = TRUE;
1249 recent.tree_view_show = TRUE;
1250 recent.byte_view_show = TRUE;
1251 recent.statusbar_show = TRUE;
1252 recent.packet_list_colorize = TRUE;
1253 recent.gui_time_format = TS_RELATIVE;
1254 recent.gui_time_precision = TS_PREC_AUTO;
1255 recent.gui_seconds_format = TS_SECONDS_DEFAULT;
1256 recent.gui_zoom_level = 0;
1257 recent.gui_bytes_view = BYTES_HEX;
1258  
1259 /* pane size of zero will autodetect */
1260 recent.gui_geometry_main_upper_pane = 0;
1261 recent.gui_geometry_main_lower_pane = 0;
1262  
1263 recent.has_gui_geometry_main_upper_pane = TRUE;
1264 recent.has_gui_geometry_main_lower_pane = TRUE;
1265 recent.has_gui_geometry_status_pane = TRUE;
1266  
1267 if (recent.col_width_list) {
1268 free_col_width_info(&recent);
1269 }
1270  
1271 if (recent.gui_fileopen_remembered_dir) {
1272 g_free (recent.gui_fileopen_remembered_dir);
1273 recent.gui_fileopen_remembered_dir = NULL;
1274 }
1275  
1276 /* Construct the pathname of the user's profile recent file. */
1277 rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
1278  
1279 /* Read the user's recent file, if it exists. */
1280 *rf_path_return = NULL;
1281 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1282 /* We succeeded in opening it; read it. */
1283 read_prefs_file(rf_path, rf, read_set_recent_pair_static, NULL);
1284 fclose(rf);
1285  
1286 /* XXX: The following code doesn't actually do anything since
1287 * the "recent common file" always exists. Presumably the
1288 * "if (!file_exists())" should actually be "if (file_exists())".
1289 * However, I've left the code as is because this
1290 * behaviour has existed for quite some time and I don't
1291 * know what's supposed to happen at this point.
1292 * ToDo: Determine if the "recent common file" should be read at this point
1293 */
1294 rf_common_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1295 if (!file_exists(rf_common_path)) {
1296 /* Read older common settings from recent file */
1297 rf = ws_fopen(rf_path, "r");
1298 read_prefs_file(rf_path, rf, read_set_recent_common_pair_static, NULL);
1299 fclose(rf);
1300 }
1301 g_free(rf_common_path);
1302 } else {
1303 /* We failed to open it. If we failed for some reason other than
1304 "it doesn't exist", return the errno and the pathname, so our
1305 caller can report the error. */
1306 if (errno != ENOENT) {
1307 *rf_errno_return = errno;
1308 *rf_path_return = rf_path;
1309 return FALSE;
1310 }
1311 }
1312 g_free(rf_path);
1313 return TRUE;
1314 }
1315  
1316 /* opens the user's recent file and read it out */
1317 gboolean
1318 recent_read_dynamic(char **rf_path_return, int *rf_errno_return)
1319 {
1320 char *rf_path;
1321 FILE *rf;
1322  
1323  
1324 /* Construct the pathname of the user's recent common file. */
1325 rf_path = get_persconffile_path(RECENT_COMMON_FILE_NAME, FALSE);
1326 if (!file_exists (rf_path)) {
1327 /* Recent common file does not exist, read from default recent */
1328 g_free (rf_path);
1329 rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
1330 }
1331  
1332 /* Read the user's recent file, if it exists. */
1333 *rf_path_return = NULL;
1334 if ((rf = ws_fopen(rf_path, "r")) != NULL) {
1335 /* We succeeded in opening it; read it. */
1336 read_prefs_file(rf_path, rf, read_set_recent_pair_dynamic, NULL);
1337 #if 0
1338 /* set dfilter combobox to have an empty line */
1339 dfilter_combo_add_empty();
1340 #endif
1341 fclose(rf);
1342 } else {
1343 /* We failed to open it. If we failed for some reason other than
1344 "it doesn't exist", return the errno and the pathname, so our
1345 caller can report the error. */
1346 if (errno != ENOENT) {
1347 *rf_errno_return = errno;
1348 *rf_path_return = rf_path;
1349 return FALSE;
1350 }
1351 }
1352 g_free(rf_path);
1353 return TRUE;
1354 }
1355  
1356 gint
1357 recent_get_column_width(gint col)
1358 {
1359 GList *col_l;
1360 col_width_data *col_w;
1361 gint cfmt;
1362 const gchar *cfield = NULL;
1363  
1364 cfmt = get_column_format(col);
1365 if (cfmt == COL_CUSTOM) {
1366 cfield = get_column_custom_fields(col);
1367 }
1368  
1369 col_l = g_list_first(recent.col_width_list);
1370 while (col_l) {
1371 col_w = (col_width_data *) col_l->data;
1372 if (col_w->cfmt == cfmt) {
1373 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1374 return col_w->width;
1375 }
1376 }
1377 col_l = col_l->next;
1378 }
1379  
1380 return -1;
1381 }
1382  
1383 void
1384 recent_set_column_width(gint col, gint width)
1385 {
1386 GList *col_l;
1387 col_width_data *col_w;
1388 gint cfmt;
1389 const gchar *cfield = NULL;
1390 gboolean found = FALSE;
1391  
1392 cfmt = get_column_format(col);
1393 if (cfmt == COL_CUSTOM) {
1394 cfield = get_column_custom_fields(col);
1395 }
1396  
1397 col_l = g_list_first(recent.col_width_list);
1398 while (col_l) {
1399 col_w = (col_width_data *) col_l->data;
1400 if (col_w->cfmt == cfmt) {
1401 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1402 col_w->width = width;
1403 found = TRUE;
1404 break;
1405 }
1406 }
1407 col_l = col_l->next;
1408 }
1409  
1410 if (!found) {
1411 col_w = (col_width_data *) g_malloc(sizeof(col_width_data));
1412 col_w->cfmt = cfmt;
1413 if (cfield) {
1414 col_w->cfield = g_strdup(cfield);
1415 } else {
1416 col_w->cfield = NULL;
1417 }
1418 col_w->width = width;
1419 col_w->xalign = COLUMN_XALIGN_DEFAULT;
1420 recent.col_width_list = g_list_append(recent.col_width_list, col_w);
1421 }
1422 }
1423  
1424 gchar
1425 recent_get_column_xalign(gint col)
1426 {
1427 GList *col_l;
1428 col_width_data *col_w;
1429 gint cfmt;
1430 const gchar *cfield = NULL;
1431  
1432 cfmt = get_column_format(col);
1433 if (cfmt == COL_CUSTOM) {
1434 cfield = get_column_custom_fields(col);
1435 }
1436  
1437 col_l = g_list_first(recent.col_width_list);
1438 while (col_l) {
1439 col_w = (col_width_data *) col_l->data;
1440 if (col_w->cfmt == cfmt) {
1441 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1442 return col_w->xalign;
1443 }
1444 }
1445 col_l = col_l->next;
1446 }
1447  
1448 return 0;
1449 }
1450  
1451 void
1452 recent_set_column_xalign(gint col, gchar xalign)
1453 {
1454 GList *col_l;
1455 col_width_data *col_w;
1456 gint cfmt;
1457 const gchar *cfield = NULL;
1458 gboolean found = FALSE;
1459  
1460 cfmt = get_column_format(col);
1461 if (cfmt == COL_CUSTOM) {
1462 cfield = get_column_custom_fields(col);
1463 }
1464  
1465 col_l = g_list_first(recent.col_width_list);
1466 while (col_l) {
1467 col_w = (col_width_data *) col_l->data;
1468 if (col_w->cfmt == cfmt) {
1469 if (cfmt != COL_CUSTOM || strcmp (cfield, col_w->cfield) == 0) {
1470 col_w->xalign = xalign;
1471 found = TRUE;
1472 break;
1473 }
1474 }
1475 col_l = col_l->next;
1476 }
1477  
1478 if (!found) {
1479 col_w = (col_width_data *) g_malloc(sizeof(col_width_data));
1480 col_w->cfmt = cfmt;
1481 if (cfield) {
1482 col_w->cfield = g_strdup(cfield);
1483 } else {
1484 col_w->cfield = NULL;
1485 }
1486 col_w->width = 40;
1487 col_w->xalign = xalign;
1488 recent.col_width_list = g_list_append(recent.col_width_list, col_w);
1489 }
1490 }
1491  
1492 /*
1493 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1494 *
1495 * Local Variables:
1496 * c-basic-offset: 2
1497 * tab-width: 8
1498 * indent-tabs-mode: nil
1499 * End:
1500 *
1501 * ex: set shiftwidth=2 tabstop=8 expandtab:
1502 * :indentSize=2:tabSize=8:noTabs=true:
1503 */