2 * Dialog boxes for handling capture files
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include "packet-range.h"
34 #include <epan/filesystem.h>
37 #include "gtkglobals.h"
38 #include <epan/addr_resolv.h>
40 #include "filter_dlg.h"
41 #include "gui_utils.h"
42 #include "alert_box.h"
43 #include "simple_dialog.h"
45 #include "dlg_utils.h"
47 #include "capture_file_dlg.h"
49 #include "compat_macros.h"
50 #include <epan/prefs.h>
53 #include "../ui_util.h"
54 #include "color_filters.h"
55 #include "gtk/color_dlg.h"
57 #include "capture_dlg.h"
59 #include "range_utils.h"
62 #include <wiretap/file_util.h>
69 #include <gdk/gdkwin32.h>
71 #include "win32-file-dlg.h"
74 static void file_open_ok_cb(GtkWidget *w, gpointer fs);
75 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
76 static void file_merge_ok_cb(GtkWidget *w, gpointer fs);
77 static void file_merge_destroy_cb(GtkWidget *win, gpointer user_data);
78 static void select_file_type_cb(GtkWidget *w, gpointer data);
79 static void file_save_as_ok_cb(GtkWidget *w, gpointer fs);
80 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
81 static void file_color_import_ok_cb(GtkWidget *w, gpointer filter_list);
82 static void file_color_import_destroy_cb(GtkWidget *win, gpointer user_data);
83 static void file_color_export_ok_cb(GtkWidget *w, gpointer filter_list);
84 static void file_color_export_destroy_cb(GtkWidget *win, gpointer user_data);
85 static void set_file_type_list(GtkWidget *option_menu);
87 #define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
88 #define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
89 #define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
91 #define E_MERGE_PREPEND_KEY "merge_dlg_prepend_key"
92 #define E_MERGE_CHRONO_KEY "merge_dlg_chrono_key"
93 #define E_MERGE_APPEND_KEY "merge_dlg_append_key"
96 #define PREVIEW_TABLE_KEY "preview_table_key"
97 #define PREVIEW_FILENAME_KEY "preview_filename_key"
98 #define PREVIEW_FORMAT_KEY "preview_format_key"
99 #define PREVIEW_SIZE_KEY "preview_size_key"
100 #define PREVIEW_ELAPSED_KEY "preview_elapsed_key"
101 #define PREVIEW_PACKETS_KEY "preview_packets_key"
102 #define PREVIEW_FIRST_KEY "preview_first_key"
106 * Keep a static pointer to the current "Save Capture File As" window, if
107 * any, so that if somebody tries to do "File:Save" or "File:Save As"
108 * while there's already a "Save Capture File As" window up, we just pop
109 * up the existing one, rather than creating a new one.
111 static GtkWidget *file_save_as_w;
113 /* XXX - can we make these not be static? */
114 static packet_range_t range;
115 static gboolean color_selected;
117 static GtkWidget *cfselect_cb;
118 static GtkWidget *ft_om;
119 static GtkWidget *range_tb;
121 #define PREVIEW_STR_MAX 200
124 /* set a new filename for the preview widget */
126 preview_set_filename(GtkWidget *prev, const gchar *cf_name)
132 gchar string_buff[PREVIEW_STR_MAX];
136 /* init preview labels */
137 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FILENAME_KEY);
138 gtk_label_set_text(GTK_LABEL(label), "-");
139 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
140 gtk_label_set_text(GTK_LABEL(label), "-");
141 label = g_object_get_data(G_OBJECT(prev), PREVIEW_SIZE_KEY);
142 gtk_label_set_text(GTK_LABEL(label), "-");
143 label = g_object_get_data(G_OBJECT(prev), PREVIEW_ELAPSED_KEY);
144 gtk_label_set_text(GTK_LABEL(label), "-");
145 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
146 gtk_label_set_text(GTK_LABEL(label), "-");
147 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FIRST_KEY);
148 gtk_label_set_text(GTK_LABEL(label), "-");
154 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FILENAME_KEY);
155 gtk_label_set_text(GTK_LABEL(label), get_basename(cf_name));
157 if (test_for_directory(cf_name) == EISDIR) {
158 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
159 gtk_label_set_text(GTK_LABEL(label), "directory");
163 wth = wtap_open_offline(cf_name, &err, &err_info, TRUE);
165 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
166 if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
167 gtk_label_set_text(GTK_LABEL(label), "unknown file format");
169 gtk_label_set_text(GTK_LABEL(label), "error opening file");
174 /* Find the size of the file. */
175 filesize = wtap_file_size(wth, &err);
176 if (filesize == -1) {
177 gtk_label_set_text(GTK_LABEL(label), "error getting file size");
181 g_snprintf(string_buff, PREVIEW_STR_MAX, "%" G_GINT64_MODIFIER "d bytes", filesize);
182 label = g_object_get_data(G_OBJECT(prev), PREVIEW_SIZE_KEY);
183 gtk_label_set_text(GTK_LABEL(label), string_buff);
186 g_snprintf(string_buff, PREVIEW_STR_MAX, "%s", wtap_file_type_string(wtap_file_type(wth)));
187 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
188 gtk_label_set_text(GTK_LABEL(label), string_buff);
194 /* do a preview run on the currently selected capture file */
196 preview_do(GtkWidget *prev, wtap *wth)
199 unsigned int elapsed_time;
205 const struct wtap_pkthdr *phdr;
206 double start_time = 0; /* seconds, with nsec resolution */
207 double stop_time = 0; /* seconds, with nsec resolution */
209 unsigned int packets = 0;
210 gboolean is_breaked = FALSE;
211 gchar string_buff[PREVIEW_STR_MAX];
217 while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
218 phdr = wtap_phdr(wth);
219 cur_time = wtap_nstime_to_sec(&phdr->ts);
221 start_time = cur_time;
222 stop_time = cur_time;
224 if (cur_time < start_time) {
225 start_time = cur_time;
227 if (cur_time > stop_time){
228 stop_time = cur_time;
233 /* do we have a timeout? */
235 if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
243 g_snprintf(string_buff, PREVIEW_STR_MAX, "error after reading %u packets", packets);
244 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
245 gtk_label_set_text(GTK_LABEL(label), string_buff);
252 g_snprintf(string_buff, PREVIEW_STR_MAX, "more than %u packets (preview timeout)", packets);
254 g_snprintf(string_buff, PREVIEW_STR_MAX, "%u", packets);
256 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
257 gtk_label_set_text(GTK_LABEL(label), string_buff);
260 ti_time = (long)start_time;
261 ti_tm = localtime( &ti_time );
263 g_snprintf(string_buff, PREVIEW_STR_MAX,
264 "%04d-%02d-%02d %02d:%02d:%02d",
265 ti_tm->tm_year + 1900,
272 g_snprintf(string_buff, PREVIEW_STR_MAX, "?");
274 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FIRST_KEY);
275 gtk_label_set_text(GTK_LABEL(label), string_buff);
278 elapsed_time = (unsigned int)(stop_time-start_time);
279 if(elapsed_time/86400) {
280 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u days %02u:%02u:%02u",
281 elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
283 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u:%02u:%02u",
284 elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
287 g_snprintf(string_buff, PREVIEW_STR_MAX, "unknown");
289 label = g_object_get_data(G_OBJECT(prev), PREVIEW_ELAPSED_KEY);
290 gtk_label_set_text(GTK_LABEL(label), string_buff);
296 /* as the dialog layout will look very ugly when using the file chooser preview mechanism,
297 simply use the same layout as in GTK2.0 */
298 /* GTK_CHECK_VERSION(2,4,0) */
300 update_preview_cb (GtkFileChooser *file_chooser, gpointer data)
302 GtkWidget *prev = GTK_WIDGET (data);
304 gboolean have_preview;
306 cf_name = gtk_file_chooser_get_preview_filename (file_chooser);
308 have_preview = preview_set_filename(prev, cf_name);
313 gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
318 /* the filename text entry changed */
320 file_open_entry_changed(GtkWidget *w _U_, gpointer file_sel)
322 GtkWidget *prev = g_object_get_data(G_OBJECT(file_sel), PREVIEW_TABLE_KEY);
323 const gchar* cf_name;
324 gboolean have_preview;
327 /* get the filename */
328 #if GTK_CHECK_VERSION(2,4,0)
329 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_sel));
331 cf_name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_sel));
334 /* set the filename to the preview */
335 wth = preview_set_filename(prev, cf_name);
336 have_preview = (wth != NULL);
338 /* make the preview widget sensitive */
339 gtk_widget_set_sensitive(prev, have_preview);
341 /* make the open/save/... dialog button sensitive */
342 #if GTK_CHECK_VERSION(2,4,0)
343 gtk_dialog_set_response_sensitive(file_sel, GTK_RESPONSE_ACCEPT, have_preview);
345 gtk_widget_set_sensitive(GTK_FILE_SELECTION(file_sel)->ok_button, have_preview);
348 /* do the actual preview */
350 preview_do(prev, wth);
354 /* copied from summary_dlg.c */
356 add_string_to_table_sensitive(GtkWidget *list, guint *row, const gchar *title, const gchar *value, gboolean sensitive)
361 if(strlen(value) != 0) {
362 indent = g_strdup_printf(" %s", title);
364 indent = g_strdup(title);
366 label = gtk_label_new(indent);
368 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
369 gtk_widget_set_sensitive(label, sensitive);
370 gtk_table_attach_defaults(GTK_TABLE(list), label, 0, 1, *row, *row+1);
372 label = gtk_label_new(value);
373 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
374 gtk_widget_set_sensitive(label, sensitive);
375 gtk_table_attach_defaults(GTK_TABLE(list), label, 1, 2, *row, *row+1);
383 add_string_to_table(GtkWidget *list, guint *row, const gchar *title, const gchar *value)
385 return add_string_to_table_sensitive(list, row, title, value, TRUE);
393 GtkWidget *table, *label;
396 table = gtk_table_new(1, 2, FALSE);
397 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
398 gtk_table_set_row_spacings(GTK_TABLE(table), 3);
401 label = add_string_to_table(table, &row, "Filename:", "-");
402 WIDGET_SET_SIZE(label, DEF_WIDTH/3, -1);
403 g_object_set_data(G_OBJECT(table), PREVIEW_FILENAME_KEY, label);
404 label = add_string_to_table(table, &row, "Format:", "-");
405 g_object_set_data(G_OBJECT(table), PREVIEW_FORMAT_KEY, label);
406 label = add_string_to_table(table, &row, "Size:", "-");
407 g_object_set_data(G_OBJECT(table), PREVIEW_SIZE_KEY, label);
408 label = add_string_to_table(table, &row, "Packets:", "-");
409 g_object_set_data(G_OBJECT(table), PREVIEW_PACKETS_KEY, label);
410 label = add_string_to_table(table, &row, "First Packet:", "-");
411 g_object_set_data(G_OBJECT(table), PREVIEW_FIRST_KEY, label);
412 label = add_string_to_table(table, &row, "Elapsed time:", "-");
413 g_object_set_data(G_OBJECT(table), PREVIEW_ELAPSED_KEY, label);
419 * Keep a static pointer to the current "Open Capture File" window, if
420 * any, so that if somebody tries to do "File:Open" while there's already
421 * an "Open Capture File" window up, we just pop up the existing one,
422 * rather than creating a new one.
424 static GtkWidget *file_open_w;
428 file_open_cmd(GtkWidget *w)
431 win32_open_file(GDK_WINDOW_HWND(top_level->window));
433 GtkWidget *main_hb, *main_vb, *filter_hbox, *filter_bt, *filter_te,
434 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb, *prev;
435 GtkTooltips *tooltips = gtk_tooltips_new();
436 /* No Apply button, and "OK" just sets our text widget, it doesn't
437 activate it (i.e., it doesn't cause us to try to open the file). */
438 static construct_args_t args = {
439 "Wireshark: Read Filter",
445 if (file_open_w != NULL) {
446 /* There's already an "Open Capture File" dialog box; reactivate it. */
447 reactivate_window(file_open_w);
451 file_open_w = file_selection_new("Wireshark: Open Capture File",
452 FILE_SELECTION_OPEN);
453 #if GTK_CHECK_VERSION(2,4,0)
454 /* it's annoying, that the file chooser dialog is already shown here,
455 so we cannot use the correct gtk_window_set_default_size() to resize it */
456 WIDGET_SET_SIZE(GTK_WINDOW(file_open_w), DEF_WIDTH, DEF_HEIGHT);
458 gtk_window_set_default_size(GTK_WINDOW(file_open_w), DEF_WIDTH, DEF_HEIGHT);
461 switch (prefs.gui_fileopen_style) {
463 case FO_STYLE_LAST_OPENED:
464 /* The user has specified that we should start out in the last directory
465 we looked in. If we've already opened a file, use its containing
466 directory, if we could determine it, as the directory, otherwise
467 use the "last opened" directory saved in the preferences file if
469 /* This is now the default behaviour in file_selection_new() */
472 case FO_STYLE_SPECIFIED:
473 /* The user has specified that we should always start out in a
474 specified directory; if they've specified that directory,
475 start out by showing the files in that dir. */
476 if (prefs.gui_fileopen_dir[0] != '\0')
477 file_selection_set_current_folder(file_open_w, prefs.gui_fileopen_dir);
482 main_hb = gtk_hbox_new(FALSE, 3);
483 file_selection_set_extra_widget(file_open_w, main_hb);
484 gtk_widget_show(main_hb);
486 /* Container for each row of widgets */
487 main_vb = gtk_vbox_new(FALSE, 3);
488 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
489 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
490 gtk_widget_show(main_vb);
493 filter_hbox = gtk_hbox_new(FALSE, 1);
494 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
495 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
496 gtk_widget_show(filter_hbox);
498 filter_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
499 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
500 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
501 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
502 gtk_widget_show(filter_bt);
503 gtk_tooltips_set_tip(tooltips, filter_bt,
504 "Open the \"Display Filter\" dialog, to edit/apply filters", NULL);
506 filter_te = gtk_entry_new();
507 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
508 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
509 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
510 gtk_widget_show(filter_te);
511 gtk_tooltips_set_tip(tooltips, filter_te, "Enter a display filter.", NULL);
513 #if GTK_CHECK_VERSION(2,4,0)
514 g_object_set_data(G_OBJECT(file_open_w), E_RFILTER_TE_KEY, filter_te);
516 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
517 E_RFILTER_TE_KEY, filter_te);
520 /* resolve buttons */
521 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _MAC name resolution", accel_group);
522 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
523 g_resolv_flags & RESOLV_MAC);
524 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
525 #if GTK_CHECK_VERSION(2,4,0)
526 g_object_set_data(G_OBJECT(file_open_w),
527 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
529 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
530 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
532 gtk_widget_show(m_resolv_cb);
534 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _network name resolution", accel_group);
535 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
536 g_resolv_flags & RESOLV_NETWORK);
537 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
538 gtk_widget_show(n_resolv_cb);
539 #if GTK_CHECK_VERSION(2,4,0)
540 g_object_set_data(G_OBJECT(file_open_w), E_FILE_N_RESOLVE_KEY, n_resolv_cb);
542 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
543 E_FILE_N_RESOLVE_KEY, n_resolv_cb);
546 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _transport name resolution", accel_group);
547 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
548 g_resolv_flags & RESOLV_TRANSPORT);
549 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
550 gtk_widget_show(t_resolv_cb);
551 #if GTK_CHECK_VERSION(2,4,0)
552 g_object_set_data(G_OBJECT(file_open_w), E_FILE_T_RESOLVE_KEY, t_resolv_cb);
554 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
555 E_FILE_T_RESOLVE_KEY, t_resolv_cb);
559 SIGNAL_CONNECT(file_open_w, "destroy", file_open_destroy_cb, NULL);
562 prev = preview_new();
563 g_object_set_data(G_OBJECT(file_open_w), PREVIEW_TABLE_KEY, prev);
564 gtk_widget_show_all(prev);
565 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
567 #if GTK_CHECK_VERSION(2,4,0)
568 SIGNAL_CONNECT(GTK_FILE_CHOOSER(file_open_w), "selection-changed",
569 file_open_entry_changed, file_open_w);
570 file_open_entry_changed(file_open_w, file_open_w);
572 g_object_set_data(G_OBJECT(file_open_w), E_DFILTER_TE_KEY,
573 g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
574 if (gtk_dialog_run(GTK_DIALOG(file_open_w)) == GTK_RESPONSE_ACCEPT)
576 file_open_ok_cb(file_open_w, file_open_w);
578 else window_destroy(file_open_w);
579 #else /* GTK_CHECK_VERSION(2,4,0) */
580 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->selection_entry, "changed",
581 file_open_entry_changed, file_open_w);
583 /* Connect the ok_button to file_open_ok_cb function and pass along a
584 pointer to the file selection box widget */
585 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->ok_button, "clicked",
586 file_open_ok_cb, file_open_w);
588 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
589 E_DFILTER_TE_KEY, g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
591 /* Connect the cancel_button to destroy the widget */
592 window_set_cancel_button(file_open_w,
593 GTK_FILE_SELECTION(file_open_w)->cancel_button, window_cancel_button_cb);
595 SIGNAL_CONNECT(file_open_w, "delete_event", window_delete_event_cb, NULL);
597 gtk_widget_show(file_open_w);
598 window_present(file_open_w);
599 #endif /* GTK_CHECK_VERSION(2,4,0) */
603 static void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
607 /* save file first */
608 file_save_as_cmd(after_save_open_dialog, data);
610 case(ESD_BTN_DONT_SAVE):
614 case(ESD_BTN_CANCEL):
617 g_assert_not_reached();
622 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
625 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
626 /* user didn't saved his current file, ask him */
627 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
628 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
629 "If you open a new capture file without saving, your capture data will be discarded.");
630 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
632 /* unchanged file, just open a new one */
633 file_open_cmd(widget);
637 /* user pressed "open" button */
639 file_open_ok_cb(GtkWidget *w, gpointer fs) {
641 const gchar *rfilter;
642 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
643 dfilter_t *rfcode = NULL;
646 #if GTK_CHECK_VERSION(2,4,0)
647 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
649 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
651 filter_te = g_object_get_data(G_OBJECT(w), E_RFILTER_TE_KEY);
652 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
653 if (!dfilter_compile(rfilter, &rfcode)) {
654 bad_dfilter_alert_box(rfilter);
659 /* Perhaps the user specified a directory instead of a file.
660 Check whether they did. */
661 if (test_for_directory(cf_name) == EISDIR) {
662 /* It's a directory - set the file selection box to display that
663 directory, don't try to open the directory as a capture file. */
664 set_last_open_dir(cf_name);
666 file_selection_set_current_folder(fs, get_last_open_dir());
670 /* Try to open the capture file. */
671 if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) {
672 /* We couldn't open it; don't dismiss the open dialog box,
673 just leave it around so that the user can, after they
674 dismiss the alert box popped up for the open error,
677 dfilter_free(rfcode);
679 #if GTK_CHECK_VERSION(2,4,0)
680 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
681 * as this will prevent the user from closing the now existing error
682 * message, simply close the dialog (this is the best we can do here). */
684 window_destroy(file_open_w);
689 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
690 it closed the previous capture file, and thus destroyed any
691 previous read filter attached to "cf"). */
692 cfile.rfcode = rfcode;
694 /* Set the global resolving variable */
695 g_resolv_flags = prefs.name_resolve;
696 m_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_M_RESOLVE_KEY);
697 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)))
698 g_resolv_flags |= RESOLV_MAC;
700 g_resolv_flags &= ~RESOLV_MAC;
701 n_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_N_RESOLVE_KEY);
702 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)))
703 g_resolv_flags |= RESOLV_NETWORK;
705 g_resolv_flags &= ~RESOLV_NETWORK;
706 t_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_T_RESOLVE_KEY);
707 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)))
708 g_resolv_flags |= RESOLV_TRANSPORT;
710 g_resolv_flags &= ~RESOLV_TRANSPORT;
712 /* We've crossed the Rubicon; get rid of the file selection box. */
713 window_destroy(GTK_WIDGET (fs));
715 switch (cf_read(&cfile)) {
719 /* Just because we got an error, that doesn't mean we were unable
720 to read any of the file; we handle what we could get from the
724 case CF_READ_ABORTED:
725 /* The user bailed out of re-reading the capture file; the
726 capture file has been closed - just free the capture file name
727 string and return (without changing the last containing
733 /* Save the name of the containing directory specified in the path name,
734 if any; we can write over cf_name, which is a good thing, given that
735 "get_dirname()" does write over its argument. */
736 s = get_dirname(cf_name);
737 set_last_open_dir(s);
738 gtk_widget_grab_focus(packet_list);
744 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
746 /* Note that we no longer have a "Open Capture File" dialog box. */
751 * Keep a static pointer to the current "Merge Capture File" window, if
752 * any, so that if somebody tries to do "File:Merge" while there's already
753 * an "Merge Capture File" window up, we just pop up the existing one,
754 * rather than creating a new one.
756 static GtkWidget *file_merge_w;
758 /* Merge existing with another file */
760 file_merge_cmd(GtkWidget *w)
763 win32_merge_file(GDK_WINDOW_HWND(top_level->window));
764 packet_list_freeze();
767 GtkWidget *main_hb, *main_vb, *ft_hb, *ft_lb, *filter_hbox,
768 *filter_bt, *filter_te, *prepend_rb, *chrono_rb,
770 GtkTooltips *tooltips = gtk_tooltips_new();
771 /* No Apply button, and "OK" just sets our text widget, it doesn't
772 activate it (i.e., it doesn't cause us to try to open the file). */
773 static construct_args_t args = {
774 "Wireshark: Read Filter",
780 if (file_merge_w != NULL) {
781 /* There's already an "Merge Capture File" dialog box; reactivate it. */
782 reactivate_window(file_merge_w);
786 /* Default to saving all packets, in the file's current format. */
787 filetype = cfile.cd_t;
789 file_merge_w = file_selection_new("Wireshark: Merge with Capture File",
790 FILE_SELECTION_OPEN);
791 #if GTK_CHECK_VERSION(2,4,0)
792 /* it's annoying, that the file chooser dialog is already shown here,
793 so we cannot use the correct gtk_window_set_default_size() to resize it */
794 WIDGET_SET_SIZE(GTK_WINDOW(file_merge_w), DEF_WIDTH, DEF_HEIGHT);
796 gtk_window_set_default_size(GTK_WINDOW(file_merge_w), DEF_WIDTH, DEF_HEIGHT);
799 switch (prefs.gui_fileopen_style) {
801 case FO_STYLE_LAST_OPENED:
802 /* The user has specified that we should start out in the last directory
803 we looked in. If we've already opened a file, use its containing
804 directory, if we could determine it, as the directory, otherwise
805 use the "last opened" directory saved in the preferences file if
807 /* This is now the default behaviour in file_selection_new() */
810 case FO_STYLE_SPECIFIED:
811 /* The user has specified that we should always start out in a
812 specified directory; if they've specified that directory,
813 start out by showing the files in that dir. */
814 if (prefs.gui_fileopen_dir[0] != '\0')
815 file_selection_set_current_folder(file_merge_w, prefs.gui_fileopen_dir);
819 main_hb = gtk_hbox_new(FALSE, 3);
820 file_selection_set_extra_widget(file_merge_w, main_hb);
821 gtk_widget_show(main_hb);
823 /* Container for each row of widgets */
824 main_vb = gtk_vbox_new(FALSE, 3);
825 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
826 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
827 gtk_widget_show(main_vb);
831 ft_hb = gtk_hbox_new(FALSE, 3);
832 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
833 gtk_widget_show(ft_hb);
835 ft_lb = gtk_label_new("Merged output file type:");
836 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
837 gtk_widget_show(ft_lb);
839 ft_om = gtk_option_menu_new();
841 /* Generate the list of file types we can save. */
842 set_file_type_list(ft_om);
843 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
844 gtk_widget_show(ft_om);
846 filter_hbox = gtk_hbox_new(FALSE, 1);
847 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
848 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
849 gtk_widget_show(filter_hbox);
851 filter_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
852 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
853 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
854 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
855 gtk_widget_show(filter_bt);
856 gtk_tooltips_set_tip(tooltips, filter_bt,
857 "Open the \"Display Filter\" dialog, to edit/apply filters", NULL);
859 filter_te = gtk_entry_new();
860 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
861 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
862 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
863 gtk_widget_show(filter_te);
864 gtk_tooltips_set_tip(tooltips, filter_te, "Enter a display filter.", NULL);
866 #if GTK_CHECK_VERSION(2,4,0)
867 g_object_set_data(G_OBJECT(file_merge_w), E_RFILTER_TE_KEY, filter_te);
869 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_merge_w)->ok_button),
870 E_RFILTER_TE_KEY, filter_te);
873 prepend_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "Prepend packets to existing file", accel_group);
874 gtk_tooltips_set_tip(tooltips, prepend_rb,
875 "The resulting file contains the packets from the selected, followed by the packets from the currently loaded file,"
876 " the packet timestamps will be ignored.", NULL);
877 gtk_box_pack_start(GTK_BOX(main_vb), prepend_rb, FALSE, FALSE, 0);
878 #if GTK_CHECK_VERSION(2,4,0)
879 g_object_set_data(G_OBJECT(file_merge_w),
880 E_MERGE_PREPEND_KEY, prepend_rb);
882 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_merge_w)->ok_button),
883 E_MERGE_PREPEND_KEY, prepend_rb);
885 gtk_widget_show(prepend_rb);
887 chrono_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(prepend_rb, "Merge packets chronologically", accel_group);
888 gtk_tooltips_set_tip(tooltips, chrono_rb,
889 "The resulting file contains all the packets from the currently loaded and the selected file,"
890 " sorted by the packet timestamps.", NULL);
891 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chrono_rb), TRUE);
892 gtk_box_pack_start(GTK_BOX(main_vb), chrono_rb, FALSE, FALSE, 0);
893 gtk_widget_show(chrono_rb);
894 #if GTK_CHECK_VERSION(2,4,0)
895 g_object_set_data(G_OBJECT(file_merge_w), E_MERGE_CHRONO_KEY, chrono_rb);
897 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_merge_w)->ok_button),
898 E_MERGE_CHRONO_KEY, chrono_rb);
901 append_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(prepend_rb, "Append packets to existing file", accel_group);
902 gtk_tooltips_set_tip(tooltips, append_rb,
903 "The resulting file contains the packets from the currently loaded, followed by the packets from the selected file,"
904 " the packet timestamps will be ignored.", NULL);
905 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(append_rb),
906 g_resolv_flags & RESOLV_TRANSPORT);
907 gtk_box_pack_start(GTK_BOX(main_vb), append_rb, FALSE, FALSE, 0);
908 gtk_widget_show(append_rb);
909 #if GTK_CHECK_VERSION(2,4,0)
910 g_object_set_data(G_OBJECT(file_merge_w), E_MERGE_APPEND_KEY, append_rb);
912 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_merge_w)->ok_button),
913 E_MERGE_APPEND_KEY, append_rb);
917 SIGNAL_CONNECT(file_merge_w, "destroy", file_merge_destroy_cb, NULL);
920 prev = preview_new();
921 g_object_set_data(G_OBJECT(file_merge_w), PREVIEW_TABLE_KEY, prev);
922 gtk_widget_show_all(prev);
923 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
925 #if GTK_CHECK_VERSION(2,4,0)
926 SIGNAL_CONNECT(GTK_FILE_CHOOSER(file_merge_w), "selection-changed",
927 file_open_entry_changed, file_merge_w);
928 file_open_entry_changed(file_merge_w, file_merge_w);
930 g_object_set_data(G_OBJECT(file_merge_w), E_DFILTER_TE_KEY,
931 g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
932 if (gtk_dialog_run(GTK_DIALOG(file_merge_w)) == GTK_RESPONSE_ACCEPT)
934 file_merge_ok_cb(file_merge_w, file_merge_w);
936 else window_destroy(file_merge_w);
937 #else /* GTK_CHECK_VERSION(2,4,0) */
938 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_merge_w)->selection_entry, "changed",
939 file_open_entry_changed, file_merge_w);
941 /* Connect the ok_button to file_merge_ok_cb function and pass along a
942 pointer to the file selection box widget */
943 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_merge_w)->ok_button, "clicked",
944 file_merge_ok_cb, file_merge_w);
946 g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_merge_w)->ok_button),
947 E_DFILTER_TE_KEY, g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
949 /* Connect the cancel_button to destroy the widget */
950 window_set_cancel_button(file_merge_w,
951 GTK_FILE_SELECTION(file_merge_w)->cancel_button, window_cancel_button_cb);
953 SIGNAL_CONNECT(file_merge_w, "delete_event", window_delete_event_cb, NULL);
955 gtk_widget_show(file_merge_w);
956 window_present(file_merge_w);
957 #endif /* GTK_CHECK_VERSION(2,4,0) */
961 static void file_merge_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
965 /* save file first */
966 file_save_as_cmd(after_save_merge_dialog, data);
968 case(ESD_BTN_CANCEL):
971 g_assert_not_reached();
976 file_merge_cmd_cb(GtkWidget *widget, gpointer data _U_) {
979 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
980 /* user didn't saved his current file, ask him */
981 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
982 PRIMARY_TEXT_START "Save the capture file before merging to another one?" PRIMARY_TEXT_END "\n\n"
983 "A temporary capture file can't be merged.");
984 simple_dialog_set_cb(dialog, file_merge_answered_cb, widget);
986 /* unchanged file, just start to merge */
987 file_merge_cmd(widget);
993 file_merge_ok_cb(GtkWidget *w, gpointer fs) {
995 const gchar *rfilter;
996 GtkWidget *filter_te, *rb;
997 dfilter_t *rfcode = NULL;
999 cf_status_t merge_status;
1000 char *in_filenames[2];
1003 #if GTK_CHECK_VERSION(2,4,0)
1004 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1006 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1008 filter_te = g_object_get_data(G_OBJECT(w), E_RFILTER_TE_KEY);
1009 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
1010 if (!dfilter_compile(rfilter, &rfcode)) {
1011 bad_dfilter_alert_box(rfilter);
1016 /* Perhaps the user specified a directory instead of a file.
1017 Check whether they did. */
1018 if (test_for_directory(cf_name) == EISDIR) {
1019 /* It's a directory - set the file selection box to display that
1020 directory, don't try to open the directory as a capture file. */
1021 set_last_open_dir(cf_name);
1023 file_selection_set_current_folder(fs, get_last_open_dir());
1027 /* merge or append the two files */
1028 rb = g_object_get_data(G_OBJECT(w), E_MERGE_CHRONO_KEY);
1030 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
1031 /* chronological order */
1032 in_filenames[0] = cfile.filename;
1033 in_filenames[1] = cf_name;
1034 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, FALSE);
1036 rb = g_object_get_data(G_OBJECT(w), E_MERGE_PREPEND_KEY);
1037 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
1039 in_filenames[0] = cf_name;
1040 in_filenames[1] = cfile.filename;
1041 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype,
1045 in_filenames[0] = cfile.filename;
1046 in_filenames[1] = cf_name;
1047 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype,
1054 if (merge_status != CF_OK) {
1056 dfilter_free(rfcode);
1063 /* We've crossed the Rubicon; get rid of the file selection box. */
1064 window_destroy(GTK_WIDGET (fs));
1066 /* Try to open the merged capture file. */
1067 if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
1068 /* We couldn't open it; don't dismiss the open dialog box,
1069 just leave it around so that the user can, after they
1070 dismiss the alert box popped up for the open error,
1073 dfilter_free(rfcode);
1075 #if GTK_CHECK_VERSION(2,4,0)
1076 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1077 * as this will prevent the user from closing the now existing error
1078 * message, simply close the dialog (this is the best we can do here). */
1080 window_destroy(file_open_w);
1086 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
1087 it closed the previous capture file, and thus destroyed any
1088 previous read filter attached to "cf"). */
1089 cfile.rfcode = rfcode;
1091 switch (cf_read(&cfile)) {
1095 /* Just because we got an error, that doesn't mean we were unable
1096 to read any of the file; we handle what we could get from the
1100 case CF_READ_ABORTED:
1101 /* The user bailed out of re-reading the capture file; the
1102 capture file has been closed - just free the capture file name
1103 string and return (without changing the last containing
1108 /* Save the name of the containing directory specified in the path name,
1109 if any; we can write over cf_merged_name, which is a good thing, given that
1110 "get_dirname()" does write over its argument. */
1111 s = get_dirname(tmpname);
1112 set_last_open_dir(s);
1113 gtk_widget_grab_focus(packet_list);
1117 file_merge_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1119 /* Note that we no longer have a "Merge Capture File" dialog box. */
1120 file_merge_w = NULL;
1124 static void file_close_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1128 /* save file first */
1129 file_save_as_cmd(after_save_close_file, NULL);
1131 case(ESD_BTN_DONT_SAVE):
1134 case(ESD_BTN_CANCEL):
1137 g_assert_not_reached();
1143 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
1146 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1147 /* user didn't saved his current file, ask him */
1148 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1149 PRIMARY_TEXT_START "Save capture file before closing it?" PRIMARY_TEXT_END "\n\n"
1150 "If you close without saving, your capture data will be discarded.");
1152 simple_dialog_set_cb(dialog, file_close_answered_cb, NULL);
1154 /* unchanged file, just close it */
1160 file_save_cmd_cb(GtkWidget *w, gpointer data) {
1161 /* If the file's already been saved, do nothing. */
1162 if (cfile.user_saved)
1165 /* Do a "Save As". */
1166 file_save_as_cmd_cb(w, data);
1170 can_save_with_wiretap(int ft)
1172 /* To save a file with Wiretap, Wiretap has to handle that format,
1173 and its code to handle that format must be able to write a file
1174 with this file's encapsulation type. */
1175 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
1179 /* Generate a list of the file types we can save this file as, by
1180 checking what Wiretap supports. */
1182 set_file_type_list(GtkWidget *option_menu)
1184 GtkWidget *ft_menu, *ft_menu_item;
1187 gint item_to_select;
1189 /* Default to the first supported file type, if the file's current
1190 type isn't supported. */
1191 item_to_select = -1;
1193 ft_menu = gtk_menu_new();
1195 /* Check all file types. */
1197 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1198 if (can_save_with_wiretap(ft)) {
1199 /* OK, we can write it out in this type. */
1200 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
1201 if (ft == filetype) {
1202 /* Default to the same format as the file, if it's supported. */
1203 item_to_select = index;
1205 SIGNAL_CONNECT(ft_menu_item, "activate", select_file_type_cb,
1206 GINT_TO_POINTER(ft));
1207 gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
1208 gtk_widget_show(ft_menu_item);
1213 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
1214 if (item_to_select >= 0) {
1215 /* Select the current File format in the menu */
1216 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
1217 select_file_type_cb(NULL, GINT_TO_POINTER(filetype));
1221 * Manually call the signal handler to activate the first menu item
1222 * since gtk_option_menu_set_history() doesn't do it for us. The first two
1223 * entries in the wiretap file types are placeholders so we start at #2, which
1224 * is the normal libpcap format.
1226 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), 0);
1227 select_file_type_cb(NULL, GINT_TO_POINTER(WTAP_FILE_PCAP));
1232 select_file_type_cb(GtkWidget *w _U_, gpointer data)
1234 int new_filetype = GPOINTER_TO_INT(data);
1235 GtkWidget *compressed_cb;
1237 if (filetype != new_filetype) {
1238 filetype = new_filetype;
1239 compressed_cb = g_object_get_data(G_OBJECT(file_save_as_w), "compressed");
1241 gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(new_filetype));
1247 * Update various dynamic parts of the range controls; called from outside
1248 * the file dialog code whenever the packet counts change.
1251 file_save_update_dynamics(void)
1253 if (file_save_as_w == NULL) {
1254 /* We don't currently have a "Save As..." dialog box up. */
1258 range_update_dynamics(range_tb);
1262 action_after_save_e action_after_save_g;
1263 gpointer action_after_save_data_g;
1267 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
1270 win32_save_as_file(GDK_WINDOW_HWND(top_level->window), action_after_save, action_after_save_data);
1272 GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr, *compressed_cb;
1273 GtkTooltips *tooltips;
1275 if (file_save_as_w != NULL) {
1276 /* There's already an "Save Capture File As" dialog box; reactivate it. */
1277 reactivate_window(file_save_as_w);
1281 /* Default to saving all packets, in the file's current format. */
1282 filetype = cfile.cd_t;
1284 /* init the packet range */
1285 packet_range_init(&range);
1287 /* Enable tooltips */
1288 tooltips = gtk_tooltips_new();
1290 /* build the file selection */
1291 file_save_as_w = file_selection_new ("Wireshark: Save Capture File As",
1292 FILE_SELECTION_SAVE);
1294 /* as the dialog might already be gone, when using this values, we cannot
1295 * set data to the dialog object, but keep global values */
1296 action_after_save_g = action_after_save;
1297 action_after_save_data_g = action_after_save_data;
1299 /* Container for each row of widgets */
1301 main_vb = gtk_vbox_new(FALSE, 5);
1302 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1303 file_selection_set_extra_widget(file_save_as_w, main_vb);
1304 gtk_widget_show(main_vb);
1306 /*** Packet Range frame ***/
1307 range_fr = gtk_frame_new("Packet Range");
1308 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
1309 gtk_widget_show(range_fr);
1312 range_tb = range_new(&range);
1313 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
1314 gtk_widget_show(range_tb);
1317 ft_hb = gtk_hbox_new(FALSE, 3);
1318 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
1319 gtk_widget_show(ft_hb);
1321 ft_lb = gtk_label_new("File type:");
1322 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
1323 gtk_widget_show(ft_lb);
1325 ft_om = gtk_option_menu_new();
1327 /* Generate the list of file types we can save. */
1328 set_file_type_list(ft_om);
1329 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1330 gtk_widget_show(ft_om);
1332 /* dynamic values in the range frame */
1333 range_update_dynamics(range_tb);
1336 compressed_cb = gtk_check_button_new_with_label("Compress with gzip");
1337 gtk_container_add(GTK_CONTAINER(ft_hb), compressed_cb);
1338 /* XXX - disable output compression for now, as this doesn't work with the
1339 * current optimization to simply copy a capture file if it's using the same
1340 * encapsulation ... */
1341 /* the rest of the implementation is just working fine :-( */
1342 /*gtk_widget_show(compressed_cb);*/
1343 g_object_set_data(G_OBJECT(file_save_as_w), "compressed", compressed_cb);
1344 gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(cfile.cd_t));
1346 SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
1348 #if GTK_CHECK_VERSION(2,4,0)
1349 if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) == GTK_RESPONSE_ACCEPT) {
1350 file_save_as_ok_cb(file_save_as_w, file_save_as_w);
1352 window_destroy(file_save_as_w);
1354 #else /* GTK_CHECK_VERSION(2,4,0) */
1355 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
1356 pointer to the file selection box widget */
1357 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_save_as_w)->ok_button, "clicked",
1358 file_save_as_ok_cb, file_save_as_w);
1360 window_set_cancel_button(file_save_as_w,
1361 GTK_FILE_SELECTION(file_save_as_w)->cancel_button, window_cancel_button_cb);
1363 SIGNAL_CONNECT(file_save_as_w, "delete_event", window_delete_event_cb, NULL);
1365 gtk_widget_show(file_save_as_w);
1366 window_present(file_save_as_w);
1367 #endif /* GTK_CHECK_VERSION(2,4,0) */
1372 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1374 file_save_as_cmd(after_save_no_action, NULL);
1378 /* all tests ok, we only have to save the file */
1379 /* (and probably continue with a pending operation) */
1381 file_save_as_cb(GtkWidget *w _U_, gpointer fs) {
1384 GtkWidget *compressed_cb;
1387 #if GTK_CHECK_VERSION(2,4,0)
1388 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1390 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1393 compressed_cb = g_object_get_data(G_OBJECT(file_save_as_w), "compressed");
1395 /* XXX - if the user requests to save to an already existing filename, */
1396 /* ask in a dialog if that's intended */
1397 /* currently, cf_save() will simply deny it */
1399 /* Write out the packets (all, or only the ones from the current
1400 range) to the file with the specified name. */
1401 if (cf_save(&cfile, cf_name, &range, filetype,
1402 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressed_cb))) != CF_OK) {
1403 /* The write failed; don't dismiss the open dialog box,
1404 just leave it around so that the user can, after they
1405 dismiss the alert box popped up for the error, try again. */
1407 #if GTK_CHECK_VERSION(2,4,0)
1408 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1409 * as this will prevent the user from closing the now existing error
1410 * message, simply close the dialog (this is the best we can do here). */
1412 window_destroy(GTK_WIDGET (fs));
1414 gtk_widget_show(GTK_WIDGET (fs));
1419 /* The write succeeded; get rid of the file selection box. */
1420 /* cf_save() might already closed our dialog! */
1422 window_destroy(GTK_WIDGET (fs));
1424 /* Save the directory name for future file dialogs. */
1425 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1426 set_last_open_dir(dirname);
1429 /* we have finished saving, do we have pending things to do? */
1430 switch(action_after_save_g) {
1431 case(after_save_no_action):
1433 case(after_save_open_dialog):
1434 file_open_cmd(action_after_save_data_g);
1436 case(after_save_open_recent_file):
1437 menu_open_recent_file_cmd(action_after_save_data_g);
1439 case(after_save_open_dnd_file):
1440 dnd_open_file_cmd(action_after_save_data_g);
1442 case(after_save_merge_dialog):
1443 file_merge_cmd(action_after_save_data_g);
1446 case(after_save_capture_dialog):
1447 capture_start_confirmed();
1450 case(after_save_close_file):
1453 case(after_save_exit):
1457 g_assert_not_reached();
1460 action_after_save_g = after_save_no_action;
1464 static void file_save_as_exists_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1468 #if GTK_CHECK_VERSION(2,4,0)
1469 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data)));
1471 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(data)));
1477 eth_unlink(cf_name);
1478 file_save_as_cb(NULL, data);
1480 case(ESD_BTN_CANCEL):
1481 #if GTK_CHECK_VERSION(2,4,0)
1482 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1483 * as this will prevent the user from closing the now existing error
1484 * message, simply close the dialog (this is the best we can do here). */
1486 window_destroy(file_save_as_w);
1488 gtk_widget_show(file_save_as_w);
1492 g_assert_not_reached();
1497 /* user pressed "Save" dialog "Ok" button */
1499 file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
1503 #if GTK_CHECK_VERSION(2,4,0)
1504 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1506 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1509 /* Perhaps the user specified a directory instead of a file.
1510 Check whether they did. */
1511 if (test_for_directory(cf_name) == EISDIR) {
1512 /* It's a directory - set the file selection box to display that
1513 directory, and leave the selection box displayed. */
1514 set_last_open_dir(cf_name);
1516 file_selection_set_current_folder(fs, get_last_open_dir());
1520 /* Check whether the range is valid. */
1521 if (!range_check_validity(&range)) {
1522 /* The range isn't valid; don't dismiss the open dialog box,
1523 just leave it around so that the user can, after they
1524 dismiss the alert box popped up for the error, try again. */
1526 #if GTK_CHECK_VERSION(2,4,0)
1527 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1528 * as this will prevent the user from closing the now existing error
1529 * message, simply close the dialog (this is the best we can do here). */
1531 window_destroy(GTK_WIDGET (fs));
1533 gtk_widget_show(GTK_WIDGET (fs));
1539 * Check that the from file is not the same as to file
1540 * We do it here so we catch all cases ...
1541 * Unfortunately, the file requester gives us an absolute file
1542 * name and the read file name may be relative (if supplied on
1543 * the command line). From Joerg Mayer.
1545 if (files_identical(cfile.filename, cf_name)) {
1546 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1547 "%sCapture file: \"%s\" identical to loaded file!%s\n\n"
1548 "Please choose a different filename.",
1549 simple_dialog_primary_start(), cf_name, simple_dialog_primary_end());
1551 #if GTK_CHECK_VERSION(2,4,0)
1552 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1553 * as this will prevent the user from closing the now existing error
1554 * message, simply close the dialog (this is the best we can do here). */
1556 window_destroy(GTK_WIDGET (fs));
1558 gtk_widget_show(GTK_WIDGET (fs));
1563 /* don't show the dialog while saving (or asking) */
1564 gtk_widget_hide(GTK_WIDGET (fs));
1566 /* it the file doesn't exist, simply try to save it */
1567 if (!file_exists(cf_name)) {
1568 file_save_as_cb(NULL, fs);
1573 /* the file exists, ask the user to remove it first */
1574 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
1575 PRIMARY_TEXT_START "A file named \"%s\" already exists."
1576 PRIMARY_TEXT_END "\n\n"
1577 "Do you want to replace it with the capture you are saving?", cf_name);
1578 simple_dialog_set_cb(dialog, file_save_as_exists_answered_cb, fs);
1584 file_save_as_destroy(void)
1587 window_destroy(file_save_as_w);
1591 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1593 /* Note that we no longer have a "Save Capture File As" dialog box. */
1594 file_save_as_w = NULL;
1597 /* Reload a file using the current read and display filters */
1599 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1603 /******************** Color Filters *********************************/
1605 * Keep a static pointer to the current "Color Export" window, if
1606 * any, so that if somebody tries to do "Export"
1607 * while there's already a "Color Export" window up, we just pop
1608 * up the existing one, rather than creating a new one.
1610 static GtkWidget *file_color_import_w;
1612 /* sets the file path to the global color filter file.
1613 WARNING: called by both the import and the export dialog.
1616 color_global_cb(GtkWidget *widget _U_, gpointer data)
1618 GtkWidget *fs_widget = data;
1621 /* decide what file to open (from dfilter code) */
1622 path = get_datafile_path("colorfilters");
1624 #if GTK_CHECK_VERSION(2,4,0)
1625 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fs_widget), path);
1627 file_selection_set_current_folder(fs_widget, path);
1629 g_free((gchar *)path);
1632 /* Import color filters */
1634 file_color_import_cmd_cb(GtkWidget *color_filters, gpointer filter_list _U_)
1637 win32_import_color_file(GDK_WINDOW_HWND(top_level->window), color_filters);
1639 GtkWidget *main_vb, *cfglobal_but;
1641 /* No Apply button, and "OK" just sets our text widget, it doesn't
1642 activate it (i.e., it doesn't cause us to try to open the file). */
1644 if (file_color_import_w != NULL) {
1645 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1646 reactivate_window(file_color_import_w);
1650 file_color_import_w = file_selection_new("Wireshark: Import Color Filters",
1651 FILE_SELECTION_OPEN);
1653 /* Container for each row of widgets */
1654 main_vb = gtk_vbox_new(FALSE, 3);
1655 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1656 file_selection_set_extra_widget(file_color_import_w, main_vb);
1657 gtk_widget_show(main_vb);
1660 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1661 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1662 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_import_w);
1663 gtk_widget_show(cfglobal_but);
1665 SIGNAL_CONNECT(file_color_import_w, "destroy", file_color_import_destroy_cb, NULL);
1667 #if GTK_CHECK_VERSION(2,4,0)
1669 if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) == GTK_RESPONSE_ACCEPT)
1671 file_color_import_ok_cb(file_color_import_w, color_filters);
1673 else window_destroy(file_color_import_w);
1674 #else /* GTK_CHECK_VERSION(2,4,0) */
1675 /* Connect the ok_button to file_open_ok_cb function and pass along a
1676 pointer to the file selection box widget */
1677 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_color_import_w)->ok_button, "clicked",
1678 file_color_import_ok_cb, color_filters);
1680 window_set_cancel_button(file_color_import_w,
1681 GTK_FILE_SELECTION(file_color_import_w)->cancel_button, window_cancel_button_cb);
1683 SIGNAL_CONNECT(file_color_import_w, "delete_event", window_delete_event_cb, NULL);
1686 gtk_widget_show(file_color_import_w);
1687 window_present(file_color_import_w);
1688 #endif /* GTK_CHECK_VERSION(2,4,0) */
1693 file_color_import_ok_cb(GtkWidget *w, gpointer color_filters) {
1695 GtkWidget *fs = gtk_widget_get_toplevel(w);
1697 #if GTK_CHECK_VERSION(2,4,0)
1698 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1700 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1702 /* Perhaps the user specified a directory instead of a file.
1703 Check whether they did. */
1704 if (test_for_directory(cf_name) == EISDIR) {
1705 /* It's a directory - set the file selection box to display that
1706 directory, don't try to open the directory as a color filter file. */
1707 set_last_open_dir(cf_name);
1709 file_selection_set_current_folder(fs, get_last_open_dir());
1713 /* Try to open the color filter file. */
1715 if (!color_filters_import(cf_name, color_filters)) {
1716 /* We couldn't open it; don't dismiss the open dialog box,
1717 just leave it around so that the user can, after they
1718 dismiss the alert box popped up for the open error,
1721 #if GTK_CHECK_VERSION(2,4,0)
1722 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1723 * as this will prevent the user from closing the now existing error
1724 * message, simply close the dialog (this is the best we can do here). */
1726 window_destroy(GTK_WIDGET (fs));
1731 /* We've crossed the Rubicon; get rid of the file selection box. */
1732 window_destroy(GTK_WIDGET (fs));
1734 /* Save the name of the containing directory specified in the path name,
1735 if any; we can write over cf_name, which is a good thing, given that
1736 "get_dirname()" does write over its argument. */
1737 s = get_dirname(cf_name);
1738 set_last_open_dir(s);
1739 gtk_widget_grab_focus(packet_list);
1745 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1747 /* Note that we no longer have a "Open Capture File" dialog box. */
1748 file_color_import_w = NULL;
1751 static GtkWidget *file_color_export_w;
1753 * Set the "Export only selected filters" toggle button as appropriate for
1754 * the current output file type and count of selected filters.
1756 * Called when the "Export" dialog box is created and when the selected
1760 color_set_export_selected_sensitive(GtkWidget * cfselect_cb)
1762 if (file_color_export_w == NULL) {
1763 /* We don't currently have an "Export" dialog box up. */
1767 /* We can request that only the selected filters be saved only if
1768 there *are* selected filters. */
1769 if (color_selected_count() != 0)
1770 gtk_widget_set_sensitive(cfselect_cb, TRUE);
1772 /* Force the "Export only selected filters" toggle to "false", turn
1773 off the flag it controls. */
1774 color_selected = FALSE;
1775 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfselect_cb), FALSE);
1776 gtk_widget_set_sensitive(cfselect_cb, FALSE);
1781 color_toggle_selected_cb(GtkWidget *widget, gpointer data _U_)
1783 color_selected = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1787 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer filter_list)
1790 win32_export_color_file(GDK_WINDOW_HWND(top_level->window), filter_list);
1792 GtkWidget *main_vb, *cfglobal_but;
1794 if (file_color_export_w != NULL) {
1795 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1796 reactivate_window(file_color_export_w);
1800 /* Default to saving all packets, in the file's current format. */
1801 color_selected = FALSE;
1802 filetype = cfile.cd_t;
1804 file_color_export_w = file_selection_new("Wireshark: Export Color Filters",
1805 FILE_SELECTION_SAVE);
1807 /* Container for each row of widgets */
1808 main_vb = gtk_vbox_new(FALSE, 3);
1809 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1810 file_selection_set_extra_widget(file_color_export_w, main_vb);
1811 gtk_widget_show(main_vb);
1813 cfselect_cb = gtk_check_button_new_with_label("Export only selected filters");
1814 gtk_container_add(GTK_CONTAINER(main_vb), cfselect_cb);
1815 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfselect_cb), FALSE);
1816 SIGNAL_CONNECT(cfselect_cb, "toggled", color_toggle_selected_cb, NULL);
1817 gtk_widget_show(cfselect_cb);
1818 color_set_export_selected_sensitive(cfselect_cb);
1820 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1821 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1822 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_export_w);
1823 gtk_widget_show(cfglobal_but);
1825 SIGNAL_CONNECT(file_color_export_w, "destroy", file_color_export_destroy_cb, NULL);
1827 #if GTK_CHECK_VERSION(2,4,0)
1828 if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) == GTK_RESPONSE_ACCEPT)
1830 file_color_export_ok_cb(file_color_export_w, filter_list);
1832 else window_destroy(file_color_export_w);
1833 #else /* GTK_CHECK_VERSION(2,4,0) */
1834 /* Connect the ok_button to file_export_ok_cb function and pass along a
1835 pointer to the file selection box widget */
1836 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_color_export_w)->ok_button, "clicked",
1837 file_color_export_ok_cb, filter_list);
1839 window_set_cancel_button(file_color_export_w,
1840 GTK_FILE_SELECTION(file_color_export_w)->cancel_button, window_cancel_button_cb);
1842 SIGNAL_CONNECT(file_color_export_w, "delete_event", window_delete_event_cb, NULL);
1845 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), "");
1847 gtk_widget_show(file_color_export_w);
1848 window_present(file_color_export_w);
1849 #endif /* GTK_CHECK_VERSION(2,4,0) */
1854 file_color_export_ok_cb(GtkWidget *w, gpointer filter_list) {
1857 GtkWidget *fs = gtk_widget_get_toplevel(w);
1859 #if GTK_CHECK_VERSION(2,4,0)
1860 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1862 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1865 /* Perhaps the user specified a directory instead of a file.
1866 Check whether they did. */
1867 if (test_for_directory(cf_name) == EISDIR) {
1868 /* It's a directory - set the file selection box to display that
1869 directory, and leave the selection box displayed. */
1870 set_last_open_dir(cf_name);
1872 file_selection_set_current_folder(fs, get_last_open_dir());
1876 /* Write out the filters (all, or only the ones that are currently
1877 displayed or selected) to the file with the specified name. */
1879 if (!color_filters_export(cf_name, filter_list, color_selected))
1881 /* The write failed; don't dismiss the open dialog box,
1882 just leave it around so that the user can, after they
1883 dismiss the alert box popped up for the error, try again. */
1885 #if GTK_CHECK_VERSION(2,4,0)
1886 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1887 * as this will prevent the user from closing the now existing error
1888 * message, simply close the dialog (this is the best we can do here). */
1890 window_destroy(GTK_WIDGET (fs));
1895 /* The write succeeded; get rid of the file selection box. */
1896 window_destroy(GTK_WIDGET (fs));
1898 /* Save the directory name for future file dialogs. */
1899 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1900 set_last_open_dir(dirname);
1905 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1907 file_color_export_w = NULL;