Have a routine to do all the work of initializing libwiretap.
[metze/wireshark/wip.git] / ui / gtk / main.c
1 /* main.c
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * Richard Sharpe, 13-Feb-1999, added support for initializing structures
8  *                              needed by dissect routines
9  * Jeff Foster,    2001/03/12,  added support tabbed hex display windowss
10  *
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 #include <config.h>
28
29 #include <gtk/gtk.h>
30 #include <gdk/gdkkeysyms.h>
31 #if GTK_CHECK_VERSION(3,0,0)
32 # include <gdk/gdkkeysyms-compat.h>
33 #endif
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <locale.h>
38
39 #ifdef HAVE_GETOPT_H
40 #include <getopt.h>
41 #endif
42
43 #ifdef HAVE_EXTCAP
44 #include <extcap.h>
45 #endif
46
47 #ifdef HAVE_LIBPORTAUDIO
48 #include <portaudio.h>
49 #endif /* HAVE_LIBPORTAUDIO */
50
51 #include <wsutil/copyright_info.h>
52 #include <wsutil/crash_info.h>
53 #include <wsutil/filesystem.h>
54 #include <wsutil/file_util.h>
55 #include <wsutil/privileges.h>
56 #include <wsutil/report_err.h>
57 #include <ws_version_info.h>
58
59 #include <wiretap/merge.h>
60
61 #include <epan/addr_resolv.h>
62 #include <epan/column.h>
63 #include <epan/disabled_protos.h>
64 #include <epan/epan.h>
65 #include <epan/decode_as.h>
66 #include <epan/proto.h>
67 #include <epan/epan_dissect.h>
68 #include <epan/dfilter/dfilter.h>
69 #include <epan/strutil.h>
70 #include <epan/ex-opt.h>
71 #include <epan/funnel.h>
72 #include <epan/expert.h>
73 #include <epan/prefs.h>
74 #include <epan/prefs-int.h>
75 #include <epan/tap.h>
76 #include <epan/stat_tap_ui.h>
77 #include <epan/uat.h>
78 #include <epan/print.h>
79 #include <epan/timestamp.h>
80 #include <epan/conversation_table.h>
81
82 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
83 #include <epan/asn1.h>
84 #include <epan/dissectors/packet-kerberos.h>
85 #endif
86
87 #include <wsutil/cmdarg_err.h>
88 #include <wsutil/plugins.h>
89
90 /* general (not GTK specific) */
91 #include "../../file.h"
92 #include "../../frame_tvbuff.h"
93 #include "../../summary.h"
94 #include <epan/color_filters.h>
95 #include "../../register.h"
96 #include "../../ringbuffer.h"
97 #include "../../log.h"
98
99 #include "gtk_iface_monitor.h"
100
101 #include "ui/alert_box.h"
102 #include "ui/console.h"
103 #include "ui/decode_as_utils.h"
104 #include "filter_files.h"
105 #include "ui/main_statusbar.h"
106 #include "ui/persfilepath_opt.h"
107 #include "ui/preference_utils.h"
108 #include "ui/recent.h"
109 #include "ui/recent_utils.h"
110 #include "ui/software_update.h"
111 #include "ui/ui_util.h"
112 #include "ui/util.h"
113 #include "ui/dissect_opts.h"
114 #include "ui/commandline.h"
115
116 #ifdef HAVE_LIBPCAP
117 #include "ui/capture_ui_utils.h"
118 #include "ui/capture_globals.h"
119 #include "ui/iface_lists.h"
120 #endif
121
122 #include "codecs/codecs.h"
123
124 #include "caputils/capture-pcap-util.h"
125
126 #ifdef HAVE_LIBPCAP
127 #include "caputils/capture_ifinfo.h"
128 #include "ui/capture.h"
129 #include <capchild/capture_sync.h>
130 #endif
131
132 #ifdef _WIN32
133 #include "caputils/capture-wpcap.h"
134 #include "caputils/capture_wpcap_packet.h"
135 #include <tchar.h> /* Needed for Unicode */
136 #include <wsutil/os_version_info.h>
137 #include <wsutil/unicode-utils.h>
138 #include <commctrl.h>
139 #include <shellapi.h>
140 #endif /* _WIN32 */
141
142 /* GTK related */
143 #include "ui/gtk/file_dlg.h"
144 #include "ui/gtk/gtkglobals.h"
145 #include "ui/gtk/color_utils.h"
146 #include "ui/gtk/gui_utils.h"
147 #include "ui/gtk/color_dlg.h"
148 #include "ui/gtk/filter_dlg.h"
149 #include "ui/gtk/fileset_dlg.h"
150 #include "ui/gtk/uat_gui.h"
151 #include "ui/gtk/main.h"
152 #include "ui/gtk/main_80211_toolbar.h"
153 #include "ui/gtk/main_airpcap_toolbar.h"
154 #include "ui/gtk/main_filter_toolbar.h"
155 #include "ui/gtk/main_titlebar.h"
156 #include "ui/gtk/menus.h"
157 #include "ui/gtk/main_menubar_private.h"
158 #include "ui/gtk/macros_dlg.h"
159 #include "ui/gtk/main_statusbar_private.h"
160 #include "ui/gtk/main_toolbar.h"
161 #include "ui/gtk/main_toolbar_private.h"
162 #include "ui/gtk/main_welcome.h"
163 #include "ui/gtk/main_welcome_private.h"
164 #include "ui/gtk/drag_and_drop.h"
165 #include "ui/gtk/capture_file_dlg.h"
166 #include "ui/gtk/packet_panes.h"
167 #include "ui/gtk/keys.h"
168 #include "ui/gtk/packet_win.h"
169 #include "ui/gtk/stock_icons.h"
170 #include "ui/gtk/find_dlg.h"
171 #include "ui/gtk/font_utils.h"
172 #include "ui/gtk/about_dlg.h"
173 #include "ui/gtk/help_dlg.h"
174 #include "ui/gtk/decode_as_dlg.h"
175 #include "ui/gtk/webbrowser.h"
176 #include "ui/gtk/capture_dlg.h"
177 #include "ui/gtk/capture_if_dlg.h"
178 #include "ui/gtk/tap_param_dlg.h"
179 #include "ui/gtk/prefs_column.h"
180 #include "ui/gtk/prefs_dlg.h"
181 #include "ui/gtk/packet_list.h"
182 #include "ui/gtk/filter_expression_save_dlg.h"
183 #include "ui/gtk/conversations_table.h"
184 #include "ui/gtk/hostlist_table.h"
185 #include "ui/gtk/service_response_time_table.h"
186 #include "ui/gtk/response_time_delay_table.h"
187 #include "ui/gtk/simple_stattable.h"
188 #include "simple_dialog.h"
189 #ifdef HAVE_GDK_GRESOURCE
190 #include "wireshark-gresources.h"
191 #else
192 #include "ui/gtk/pixbuf-csource.h"
193 #endif
194
195 #include "ui/gtk/old-gtk-compat.h"
196
197 #ifdef HAVE_AIRPCAP
198 #include <caputils/airpcap.h>
199 #include <caputils/airpcap_loader.h>
200 #include "airpcap_dlg.h"
201 #include "airpcap_gui_utils.h"
202 #endif
203
204 #include <epan/crypt/airpdcap_ws.h>
205
206
207 #ifdef HAVE_GTKOSXAPPLICATION
208 #include <gtkmacintegration/gtkosxapplication.h>
209 #endif
210
211 /*
212  * Files under personal and global preferences directories in which
213  * GTK settings for Wireshark are stored.
214  */
215 #define RC_FILE "gtkrc"
216
217 #ifdef HAVE_LIBPCAP
218 capture_session global_capture_session;
219 info_data_t global_info_data;
220 #endif
221
222 capture_file cfile;
223
224 static gboolean capture_stopping;
225
226 /* "exported" main widgets */
227 GtkWidget   *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
228
229 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
230 static GtkWidget   *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
231 static GtkWidget   *main_first_pane, *main_second_pane;
232
233 /* internally used widgets */
234 static GtkWidget   *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
235
236 GtkWidget *wireless_tb;
237 #ifdef HAVE_AIRPCAP
238 int    airpcap_dll_ret_val = -1;
239 #endif
240
241 static gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
242
243 static guint  tap_update_timer_id;
244
245 static void create_main_window(gint, gint, gint, e_prefs*);
246 static void show_main_window(gboolean);
247 static void main_save_window_geometry(GtkWidget *widget);
248
249
250 /* Match selected byte pattern */
251 static void
252 match_selected_cb_do(GtkWidget *filter_te, int action, gchar *text)
253 {
254     char       *cur_filter, *new_filter;
255
256     if ((!text) || (0 == strlen(text))) {
257         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
258         return;
259     }
260
261     g_assert(filter_te);
262
263     cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
264
265     switch (action&MATCH_SELECTED_MASK) {
266
267     case MATCH_SELECTED_REPLACE:
268         new_filter = g_strdup(text);
269         break;
270
271     case MATCH_SELECTED_AND:
272         if ((!cur_filter) || (0 == strlen(cur_filter)))
273             new_filter = g_strdup(text);
274         else
275             new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
276         break;
277
278     case MATCH_SELECTED_OR:
279         if ((!cur_filter) || (0 == strlen(cur_filter)))
280             new_filter = g_strdup(text);
281         else
282             new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
283         break;
284
285     case MATCH_SELECTED_NOT:
286         new_filter = g_strconcat("!(", text, ")", NULL);
287         break;
288
289     case MATCH_SELECTED_AND_NOT:
290         if ((!cur_filter) || (0 == strlen(cur_filter)))
291             new_filter = g_strconcat("!(", text, ")", NULL);
292         else
293             new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
294         break;
295
296     case MATCH_SELECTED_OR_NOT:
297         if ((!cur_filter) || (0 == strlen(cur_filter)))
298             new_filter = g_strconcat("!(", text, ")", NULL);
299         else
300             new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
301         break;
302
303     default:
304         g_assert_not_reached();
305         new_filter = NULL;
306         break;
307     }
308
309     /* Free up the copy we got of the old filter text. */
310     g_free(cur_filter);
311
312     /* Don't change the current display filter if we only want to copy the filter */
313     if (action&MATCH_SELECTED_COPY_ONLY) {
314         GString *gtk_text_str = g_string_new("");
315         g_string_append(gtk_text_str, new_filter);
316         copy_to_clipboard(gtk_text_str);
317         g_string_free(gtk_text_str, TRUE);
318     } else {
319         /* create a new one and set the display filter entry accordingly */
320         gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
321
322         /* Run the display filter so it goes in effect. */
323         if (action&MATCH_SELECTED_APPLY_NOW)
324             main_filter_packets(&cfile, new_filter, FALSE);
325     }
326
327     /* Free up the new filter text. */
328     g_free(new_filter);
329 }
330
331 void
332 match_selected_ptree_cb(gpointer data, MATCH_SELECTED_E action)
333 {
334     char *filter = NULL;
335
336     if (cfile.finfo_selected) {
337         filter = proto_construct_match_selected_string(cfile.finfo_selected,
338                                                        cfile.edt);
339         match_selected_cb_do((GtkWidget *)g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY), action, filter);
340         wmem_free(NULL, filter);
341     }
342 }
343
344 void
345 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
346 {
347     char *filter = NULL;
348     gchar *err_msg = NULL;
349
350     if (cfile.finfo_selected) {
351         filter = proto_construct_match_selected_string(cfile.finfo_selected,
352                                                        cfile.edt);
353         if ((!filter) || (0 == strlen(filter))) {
354             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
355                 "Could not acquire information to build a filter!\n"
356                 "Try expanding or choosing another item.");
357             return;
358         }
359
360         if (filt_nr==0) {
361             color_display_with_filter(filter);
362         } else {
363             if (filt_nr==255) {
364                 if (!color_filters_reset_tmp(&err_msg)) {
365                     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
366                     g_free(err_msg);
367                 }
368             } else {
369                 if (!color_filters_set_tmp(filt_nr,filter, FALSE, &err_msg)) {
370                     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
371                     g_free(err_msg);
372                 }
373
374             }
375             packet_list_colorize_packets();
376         }
377         wmem_free(NULL, filter);
378     }
379 }
380
381
382 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
383 {
384     gchar *selected_proto_url;
385     gchar *proto_abbrev = (gchar *)data;
386
387
388     switch(btn) {
389     case(ESD_BTN_OK):
390         if (cfile.finfo_selected) {
391             /* open wiki page using the protocol abbreviation */
392             selected_proto_url = g_strdup_printf("https://wiki.wireshark.org/Protocols/%s", proto_abbrev);
393             browser_open_url(selected_proto_url);
394             g_free(selected_proto_url);
395         }
396         break;
397     case(ESD_BTN_CANCEL):
398         break;
399     default:
400         g_assert_not_reached();
401     }
402 }
403
404
405 void
406 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
407 {
408     int field_id;
409     const gchar *proto_abbrev;
410     gpointer  dialog;
411
412
413     if (cfile.finfo_selected) {
414         /* convert selected field to protocol abbreviation */
415         /* XXX - could this conversion be simplified? */
416         field_id = cfile.finfo_selected->hfinfo->id;
417         /* if the selected field isn't a protocol, get its parent */
418         if(!proto_registrar_is_protocol(field_id)) {
419             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
420         }
421
422         proto_abbrev = proto_registrar_get_abbrev(field_id);
423
424         /* ask the user if the wiki page really should be opened */
425         dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
426                 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
427                 "\n"
428                 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
429                 "\n"
430                 "The Wireshark Wiki is a collaborative approach to provide information "
431                 "about Wireshark in several ways (not limited to protocol specifics).\n"
432                 "\n"
433                 "This Wiki is new, so the page of the selected protocol "
434                 "may not exist and/or may not contain valuable information.\n"
435                 "\n"
436                 "As everyone can edit the Wiki and add new content (or extend existing), "
437                 "you are encouraged to add information if you can.\n"
438                 "\n"
439                 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
440                 "\n"
441                 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
442                 "which will save you a lot of editing and will give a consistent look over the pages.",
443                 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
444         simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
445     }
446 }
447
448 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
449 {
450     gchar *selected_proto_url;
451     gchar *proto_abbrev = (gchar *)data;
452
453     switch(btn) {
454     case(ESD_BTN_OK):
455         if (cfile.finfo_selected) {
456             /* open reference page using the protocol abbreviation */
457             selected_proto_url = g_strdup_printf("https://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
458             browser_open_url(selected_proto_url);
459             g_free(selected_proto_url);
460         }
461         break;
462     case(ESD_BTN_CANCEL):
463         break;
464     default:
465         g_assert_not_reached();
466     }
467 }
468
469 void
470 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
471 {
472     int field_id;
473     const gchar *proto_abbrev;
474     gpointer  dialog;
475
476
477     if (cfile.finfo_selected) {
478         /* convert selected field to protocol abbreviation */
479         /* XXX - could this conversion be simplified? */
480         field_id = cfile.finfo_selected->hfinfo->id;
481         /* if the selected field isn't a protocol, get its parent */
482         if(!proto_registrar_is_protocol(field_id)) {
483             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
484         }
485
486         proto_abbrev = proto_registrar_get_abbrev(field_id);
487
488         /* ask the user if the wiki page really should be opened */
489         dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
490                 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
491                 "\n"
492                 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
493                 "\n",
494                 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
495         simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
496     }
497 }
498
499 static gboolean
500 is_address_column (gint column)
501 {
502     if (((cfile.cinfo.columns[column].col_fmt == COL_DEF_SRC) ||
503          (cfile.cinfo.columns[column].col_fmt == COL_RES_SRC) ||
504          (cfile.cinfo.columns[column].col_fmt == COL_DEF_DST) ||
505          (cfile.cinfo.columns[column].col_fmt == COL_RES_DST)) &&
506         strlen(cfile.cinfo.col_expr.col_expr_val[column]))
507     {
508         return TRUE;
509     }
510
511     return FALSE;
512 }
513
514 GList *
515 get_ip_address_list_from_packet_list_row(gpointer data)
516 {
517     gint    row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
518     gint    column = packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
519     gint    col;
520     frame_data *fdata;
521     GList      *addr_list = NULL;
522
523     fdata = (frame_data *) packet_list_get_row_data(row);
524
525     if (fdata != NULL) {
526         epan_dissect_t edt;
527
528         if (!cf_read_record(&cfile, fdata))
529             return NULL; /* error reading the frame */
530
531         epan_dissect_init(&edt, cfile.epan, FALSE, FALSE);
532         col_custom_prime_edt(&edt, &cfile.cinfo);
533
534         epan_dissect_run(&edt, cfile.cd_t, &cfile.phdr,
535             frame_tvbuff_new_buffer(fdata, &cfile.buf), fdata, &cfile.cinfo);
536         epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
537
538         /* First check selected column */
539         if (is_address_column (column)) {
540             addr_list = g_list_append (addr_list, g_strdup(cfile.cinfo.col_expr.col_expr_val[column]));
541         }
542
543         for (col = 0; col < cfile.cinfo.num_cols; col++) {
544             /* Then check all columns except the selected */
545             if ((col != column) && (is_address_column (col))) {
546                 addr_list = g_list_append (addr_list, g_strdup(cfile.cinfo.col_expr.col_expr_val[col]));
547             }
548         }
549
550         epan_dissect_cleanup(&edt);
551     }
552
553     return addr_list;
554 }
555
556 static gchar *
557 get_filter_from_packet_list_row_and_column(gpointer data)
558 {
559     gint    row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
560     gint    column = packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
561     frame_data *fdata;
562     gchar      *buf=NULL;
563
564     fdata = (frame_data *) packet_list_get_row_data(row);
565
566     if (fdata != NULL) {
567         epan_dissect_t edt;
568
569         if (!cf_read_record(&cfile, fdata))
570             return NULL; /* error reading the record */
571         /* proto tree, visible. We need a proto tree if there's custom columns */
572         epan_dissect_init(&edt, cfile.epan, have_custom_cols(&cfile.cinfo), FALSE);
573         col_custom_prime_edt(&edt, &cfile.cinfo);
574
575         epan_dissect_run(&edt, cfile.cd_t, &cfile.phdr,
576                          frame_tvbuff_new_buffer(fdata, &cfile.buf),
577                          fdata, &cfile.cinfo);
578         epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
579
580         if ((cfile.cinfo.columns[column].col_custom_occurrence) ||
581             (strchr (cfile.cinfo.col_expr.col_expr_val[column], ',') == NULL))
582         {
583             /* Only construct the filter when a single occurrence is displayed
584              * otherwise we might end up with a filter like "ip.proto==1,6".
585              *
586              * Or do we want to be able to filter on multiple occurrences so that
587              * the filter might be calculated as "ip.proto==1 && ip.proto==6"
588              * instead?
589              */
590             if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
591                 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
592                 /* leak a little; is there a safe wmem_ scope here? */
593                 if (cfile.cinfo.columns[column].col_fmt == COL_CUSTOM) {
594                     header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.columns[column].col_custom_fields);
595                     if (hfi && hfi->parent == -1) {
596                         /* Protocol only */
597                         buf = g_strdup(cfile.cinfo.col_expr.col_expr[column]);
598                     } else if (hfi && IS_FT_STRING(hfi->type)) {
599                         /* Custom string, add quotes */
600                         buf = g_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
601                                                cfile.cinfo.col_expr.col_expr_val[column]);
602                     }
603                 }
604                 if (buf == NULL) {
605                     buf = g_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
606                                            cfile.cinfo.col_expr.col_expr_val[column]);
607                 }
608             }
609         }
610
611         epan_dissect_cleanup(&edt);
612     }
613
614     return buf;
615 }
616
617 void
618 match_selected_plist_cb(gpointer data, MATCH_SELECTED_E action)
619 {
620     char *filter;
621
622     filter = get_filter_from_packet_list_row_and_column((GtkWidget *)data);
623
624     match_selected_cb_do((GtkWidget *)g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY),
625         action, filter);
626
627     g_free(filter);
628 }
629
630 /* This function allows users to right click in the details window and copy the text
631  * information to the operating systems clipboard.
632  *
633  * We first check to see if a string representation is setup in the tree and then
634  * read the string. If not available then we try to grab the value. If all else
635  * fails we display a message to the user to indicate the copy could not be completed.
636  */
637 void
638 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
639 {
640     GString *gtk_text_str = g_string_new("");
641     char labelstring[ITEM_LABEL_LENGTH];
642     char *stringpointer = labelstring;
643
644     switch(action)
645     {
646     case COPY_SELECTED_DESCRIPTION:
647         if (cfile.finfo_selected->rep &&
648             strlen(cfile.finfo_selected->rep->representation) > 0) {
649             g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
650         }
651         break;
652     case COPY_SELECTED_FIELDNAME:
653         if (cfile.finfo_selected->hfinfo->abbrev != 0) {
654             g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
655         }
656         break;
657     case COPY_SELECTED_VALUE:
658         if (cfile.edt !=0 ) {
659             gchar* field_str = get_node_field_value(cfile.finfo_selected, cfile.edt);
660             g_string_append(gtk_text_str, field_str);
661             g_free(field_str);
662         }
663         break;
664     default:
665         break;
666     }
667
668     if (gtk_text_str->len == 0) {
669         /* If no representation then... Try to read the value */
670         proto_item_fill_label(cfile.finfo_selected, stringpointer);
671         g_string_append(gtk_text_str, stringpointer);
672     }
673
674     if (gtk_text_str->len == 0) {
675         /* Could not get item so display error msg */
676         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
677     } else {
678         /* Copy string to clipboard */
679         copy_to_clipboard(gtk_text_str);
680     }
681     g_string_free(gtk_text_str, TRUE);                       /* Free the memory */
682 }
683
684
685 /* mark as reference time frame */
686 void
687 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
688     if (row == -1)
689         return;
690     if (set) {
691         frame->flags.ref_time=1;
692         cfile.ref_time_count++;
693     } else {
694         frame->flags.ref_time=0;
695         cfile.ref_time_count--;
696     }
697     cf_reftime_packets(&cfile);
698     if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
699         packet_list_freeze();
700         cfile.displayed_count--;
701         packet_list_recreate_visible_rows();
702         packet_list_thaw();
703     }
704     packet_list_queue_draw();
705 }
706
707
708 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
709 {
710     switch(btn) {
711     case(ESD_BTN_YES):
712         timestamp_set_type(TS_RELATIVE);
713         recent.gui_time_format  = TS_RELATIVE;
714         cf_timestamp_auto_precision(&cfile);
715         packet_list_queue_draw();
716         break;
717     case(ESD_BTN_NO):
718         break;
719     default:
720         g_assert_not_reached();
721     }
722
723     if (cfile.current_frame) {
724       set_frame_reftime(!cfile.current_frame->flags.ref_time,
725       cfile.current_frame, cfile.current_row);
726     }
727 }
728
729
730 void
731 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
732 {
733     static GtkWidget *reftime_dialog = NULL;
734
735     switch(action){
736     case REFTIME_TOGGLE:
737         if (cfile.current_frame) {
738             if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
739                 reftime_dialog = (GtkWidget *)simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
740                     "%sSwitch to the appropriate Time Display Format?%s\n\n"
741                     "Time References don't work well with the currently selected Time Display Format.\n\n"
742                     "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
743                     simple_dialog_primary_start(), simple_dialog_primary_end());
744                 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
745             } else {
746                 set_frame_reftime(!cfile.current_frame->flags.ref_time,
747                                   cfile.current_frame, cfile.current_row);
748             }
749         }
750         break;
751     case REFTIME_FIND_NEXT:
752         cf_find_packet_time_reference(&cfile, SD_FORWARD);
753         break;
754     case REFTIME_FIND_PREV:
755         cf_find_packet_time_reference(&cfile, SD_BACKWARD);
756         break;
757     }
758 }
759
760 void
761 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
762 {
763     cf_find_packet_marked(&cfile, SD_FORWARD);
764 }
765
766 void
767 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
768 {
769     cf_find_packet_marked(&cfile, SD_BACKWARD);
770 }
771
772 static void
773 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
774 {
775     field_info   *finfo;
776     gchar         len_str[2+10+1+5+1]; /* ", {N} bytes\0",
777                                           N < 4294967296 */
778     gboolean      has_blurb = FALSE;
779     guint         length = 0, byte_len;
780     GtkWidget    *byte_view;
781     const guint8 *byte_data;
782     gint          finfo_length;
783     GtkTreeModel *model;
784     GtkTreeIter   iter;
785
786     /* if nothing is selected */
787     if (!gtk_tree_selection_get_selected(sel, &model, &iter))
788     {
789         /*
790          * Which byte view is displaying the current protocol tree
791          * row's data?
792          */
793         byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
794         if (byte_view == NULL)
795             return; /* none */
796
797         byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
798         if (byte_data == NULL)
799             return; /* none */
800
801         cf_unselect_field(&cfile);
802         packet_hex_print(byte_view, byte_data,
803                          cfile.current_frame, NULL, byte_len);
804         return;
805     }
806     gtk_tree_model_get(model, &iter, 1, &finfo, -1);
807     if (!finfo) return;
808
809     set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
810
811     byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
812     byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
813     g_assert(byte_data != NULL);
814
815     cfile.finfo_selected = finfo;
816     set_menus_for_selected_tree_row(&cfile);
817
818     if (finfo->hfinfo) {
819         if (finfo->hfinfo->blurb != NULL &&
820             finfo->hfinfo->blurb[0] != '\0') {
821             has_blurb = TRUE;
822             length = (guint) strlen(finfo->hfinfo->blurb);
823         } else {
824             length = (guint) strlen(finfo->hfinfo->name);
825         }
826         finfo_length = finfo->length + finfo->appendix_length;
827
828         if (finfo_length == 0) {
829             len_str[0] = '\0';
830         } else if (finfo_length == 1) {
831             g_strlcpy (len_str, ", 1 byte", sizeof len_str);
832         } else {
833             g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
834         }
835         statusbar_pop_field_msg(); /* get rid of current help msg */
836         if (length) {
837             statusbar_push_field_msg(" %s (%s)%s",
838                     (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
839                     finfo->hfinfo->abbrev, len_str);
840         } else {
841             /*
842              * Don't show anything if the field name is zero-length;
843              * the pseudo-field for text-only items is such
844              * a field, and we don't want "Text (text)" showing up
845              * on the status line if you've selected such a field.
846              *
847              * XXX - there are zero-length fields for which we *do*
848              * want to show the field name.
849              *
850              * XXX - perhaps the name and abbrev field should be null
851              * pointers rather than null strings for that pseudo-field,
852              * but we'd have to add checks for null pointers in some
853              * places if we did that.
854              *
855              * Or perhaps text-only items should have -1 as the field
856              * index, with no pseudo-field being used, but that might
857              * also require special checks for -1 to be added.
858              */
859             statusbar_push_field_msg("%s", "");
860         }
861     }
862     packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
863                      byte_len);
864 }
865
866 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_)
867 {
868     if (cfile.edt->tree)
869         collapse_all_tree(cfile.edt->tree, tree_view_gbl);
870 }
871
872 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_)
873 {
874     if (cfile.edt->tree)
875         expand_all_tree(cfile.edt->tree, tree_view_gbl);
876 }
877
878 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
879 {
880     if (cfile.finfo_selected) {
881         column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
882                                 cfile.finfo_selected->hfinfo->abbrev,0);
883         /* Recreate the packet list according to new preferences */
884         packet_list_recreate ();
885         if (!prefs.gui_use_pref_save) {
886             prefs_main_write();
887         }
888         cfile.columns_changed = FALSE; /* Reset value */
889     }
890 }
891
892 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_)
893 {
894     GtkTreePath  *path;
895
896     path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
897     if(path) {
898         /* the mouse position is at an entry, expand that one */
899         gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
900         gtk_tree_path_free(path);
901     }
902 }
903
904 void collapse_tree_cb(GtkWidget *widget _U_, gpointer data _U_)
905 {
906     GtkTreePath  *path;
907
908     path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
909     if(path) {
910         /* the mouse position is at an entry, expand that one */
911
912         tree_collapse_path_all(GTK_TREE_VIEW(tree_view_gbl), path);
913         gtk_tree_path_free(path);
914     }
915 }
916
917 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_)
918 {
919     static const e_addr_resolve resolv_flags = {
920         TRUE,   /* mac_name */
921         TRUE,   /* network_name */
922         TRUE,   /* transport_name */
923         TRUE,   /* dns_pkt_addr_resolution */
924         TRUE,   /* use_external_net_name_resolver */
925         FALSE,  /* load_hosts_file_from_profile_only */
926         FALSE,  /* vlan_name */
927         FALSE,  /* ss7pc_name */
928     };
929
930     if (cfile.edt->tree) {
931         proto_tree_draw_resolve(cfile.edt->tree, tree_view_gbl, &resolv_flags);
932     }
933 }
934
935 /* Update main window items based on whether there's a capture in progress. */
936 static void
937 main_set_for_capture_in_progress(gboolean capture_in_progress)
938 {
939     set_menus_for_capture_in_progress(capture_in_progress);
940
941 #ifdef HAVE_LIBPCAP
942     set_toolbar_for_capture_in_progress(capture_in_progress);
943
944     set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
945 #endif
946 }
947
948 /* Update main window items based on whether we have a capture file. */
949 static void
950 main_set_for_capture_file(gboolean have_capture_file_in)
951 {
952     have_capture_file = have_capture_file_in;
953
954     main_widgets_show_or_hide();
955 }
956
957 /* Update main window items based on whether we have captured packets. */
958 static void
959 main_set_for_captured_packets(gboolean have_captured_packets)
960 {
961     set_menus_for_captured_packets(have_captured_packets);
962     set_toolbar_for_captured_packets(have_captured_packets);
963 }
964
965 /* Update main window items based on whether we have a packet history. */
966 void
967 main_set_for_packet_history(gboolean back_history, gboolean forward_history)
968 {
969     set_menus_for_packet_history(back_history, forward_history);
970     set_toolbar_for_packet_history(back_history, forward_history);
971 }
972
973 gboolean
974 main_do_quit(void)
975 {
976     /* get the current geometry, before writing it to disk */
977     main_save_window_geometry(top_level);
978
979     /* write user's recent file to disk
980      * It is no problem to write this file, even if we do not quit */
981     write_profile_recent();
982     write_recent();
983
984     /* XXX - should we check whether the capture file is an
985        unsaved temporary file for a live capture and, if so,
986        pop up a "do you want to exit without saving the capture
987        file?" dialog, and then just return, leaving said dialog
988        box to forcibly quit if the user clicks "OK"?
989
990        If so, note that this should be done in a subroutine that
991        returns TRUE if we do so, and FALSE otherwise, and if it
992        returns TRUE we should return TRUE without nuking anything.
993
994        Note that, if we do that, we might also want to check if
995        an "Update list of packets in real time" capture is in
996        progress and, if so, ask whether they want to terminate
997        the capture and discard it, and return TRUE, before nuking
998        any child capture, if they say they don't want to do so. */
999
1000 #ifdef HAVE_LIBPCAP
1001     /* Nuke any child capture in progress. */
1002     capture_kill_child(&global_capture_session);
1003 #endif
1004
1005     /* Are we in the middle of reading a capture? */
1006     if (cfile.state == FILE_READ_IN_PROGRESS) {
1007         /* Yes, so we can't just close the file and quit, as
1008            that may yank the rug out from under the read in
1009            progress; instead, just set the state to
1010            "FILE_READ_ABORTED" and return - the code doing the read
1011            will check for that and, if it sees that, will clean
1012            up and quit. */
1013         cfile.state = FILE_READ_ABORTED;
1014
1015         /* Say that the window should *not* be deleted;
1016            that'll be done by the code that cleans up. */
1017         return TRUE;
1018     } else {
1019         /* Close any capture file we have open; on some OSes, you
1020            can't unlink a temporary capture file if you have it
1021            open.
1022            "cf_close()" will unlink it after closing it if
1023            it's a temporary file.
1024
1025            We do this here, rather than after the main loop returns,
1026            as, after the main loop returns, the main window may have
1027            been destroyed (if this is called due to a "destroy"
1028            even on the main window rather than due to the user
1029            selecting a menu item), and there may be a crash
1030            or other problem when "cf_close()" tries to
1031            clean up stuff in the main window.
1032
1033            XXX - is there a better place to put this?
1034            Or should we have a routine that *just* closes the
1035            capture file, and doesn't do anything with the UI,
1036            which we'd call here, and another routine that
1037            calls that routine and also cleans up the UI, which
1038            we'd call elsewhere? */
1039         cf_close(&cfile);
1040
1041         /* Exit by leaving the main loop, so that any quit functions
1042            we registered get called. */
1043         gtk_main_quit();
1044
1045         /* Say that the window should be deleted. */
1046         return FALSE;
1047     }
1048 }
1049
1050 static gboolean
1051 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1052 {
1053     /* If we're in the middle of stopping a capture, don't do anything;
1054        the user can try deleting the window after the capture stops. */
1055     if (capture_stopping)
1056         return TRUE;
1057
1058     /* If there's unsaved data, let the user save it first.
1059        If they cancel out of it, don't quit. */
1060     if (do_file_close(&cfile, TRUE, " before quitting"))
1061         return main_do_quit();
1062     else
1063         return TRUE; /* will this keep the window from being deleted? */
1064 }
1065
1066
1067 static void
1068 main_pane_load_window_geometry(void)
1069 {
1070     if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1071         gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1072     if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1073         gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1074     }
1075 }
1076
1077
1078 static void
1079 main_load_window_geometry(GtkWidget *widget)
1080 {
1081     window_geometry_t geom;
1082
1083     geom.set_pos        = prefs.gui_geometry_save_position;
1084     geom.x              = recent.gui_gtk_geometry_main_x;
1085     geom.y              = recent.gui_gtk_geometry_main_y;
1086     geom.set_size       = prefs.gui_geometry_save_size;
1087     geom.set_maximized  = FALSE;
1088     if (recent.gui_geometry_main_width > 0 &&
1089         recent.gui_geometry_main_height > 0) {
1090         geom.width          = recent.gui_geometry_main_width;
1091         geom.height         = recent.gui_geometry_main_height;
1092         geom.set_maximized  = prefs.gui_geometry_save_maximized;
1093     } else {
1094         /* We assume this means the width and height weren't set in
1095            the "recent" file (or that there is no "recent" file),
1096            and weren't set to a default value, so we don't set the
1097            size.  (The "recent" file code rejects non-positive width
1098            and height values.) */
1099        geom.set_size = FALSE;
1100     }
1101     geom.maximized      = recent.gui_geometry_main_maximized;
1102
1103     window_set_geometry(widget, &geom);
1104
1105     main_pane_load_window_geometry();
1106     statusbar_load_window_geometry();
1107 }
1108
1109
1110 static void
1111 main_save_window_geometry(GtkWidget *widget)
1112 {
1113     window_geometry_t geom;
1114
1115     window_get_geometry(widget, &geom);
1116
1117     if (prefs.gui_geometry_save_position) {
1118         recent.gui_gtk_geometry_main_x = geom.x;
1119         recent.gui_gtk_geometry_main_y = geom.y;
1120     }
1121
1122     if (prefs.gui_geometry_save_size) {
1123         recent.gui_geometry_main_width  = geom.width;
1124         recent.gui_geometry_main_height = geom.height;
1125     }
1126
1127     if(prefs.gui_geometry_save_maximized) {
1128         recent.gui_geometry_main_maximized = geom.maximized;
1129     }
1130
1131     recent.gui_geometry_main_upper_pane     = gtk_paned_get_position(GTK_PANED(main_first_pane));
1132     recent.gui_geometry_main_lower_pane     = gtk_paned_get_position(GTK_PANED(main_second_pane));
1133     statusbar_save_window_geometry();
1134 }
1135
1136 void
1137 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1138 {
1139     /* If there's unsaved data, let the user save it first. */
1140     if (do_file_close(&cfile, TRUE, " before quitting"))
1141         main_do_quit();
1142 }
1143
1144 /*
1145  * Report an error in command-line arguments.
1146  * Creates a console on Windows.
1147  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1148  * terminal isn't the standard error?
1149  */
1150 static void
1151 wireshark_cmdarg_err(const char *fmt, va_list ap)
1152 {
1153 #ifdef _WIN32
1154     create_console();
1155 #endif
1156     fprintf(stderr, "wireshark: ");
1157     vfprintf(stderr, fmt, ap);
1158     fprintf(stderr, "\n");
1159 }
1160
1161 /*
1162  * Report additional information for an error in command-line arguments.
1163  * Creates a console on Windows.
1164  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1165  * terminal isn't the standard error?
1166  */
1167 static void
1168 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
1169 {
1170 #ifdef _WIN32
1171     create_console();
1172 #endif
1173     vfprintf(stderr, fmt, ap);
1174     fprintf(stderr, "\n");
1175 }
1176
1177 /*
1178    Once every 3 seconds we get a callback here which we use to update
1179    the tap extensions.
1180  */
1181 static gboolean
1182 tap_update_cb(gpointer data _U_)
1183 {
1184     draw_tap_listeners(FALSE);
1185     return TRUE;
1186 }
1187
1188 /*
1189  * Periodically process outstanding hostname lookups. If we have new items,
1190  * redraw the packet list and tree view.
1191  */
1192
1193 static gboolean
1194 resolv_update_cb(gpointer data _U_)
1195 {
1196     /* Anything new show up? */
1197     if (host_name_lookup_process()) {
1198         if (gtk_widget_get_window(pkt_scrollw))
1199             gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE);
1200         if (gtk_widget_get_window(tv_scrollw))
1201             gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE);
1202     }
1203
1204     /* Always check. Even if we don't do async lookups we could still get
1205         passive updates, e.g. from DNS packets. */
1206     return TRUE;
1207 }
1208
1209
1210 /* Update various parts of the main window for a capture file "unsaved
1211    changes" change - update the title to reflect whether there are
1212    unsaved changes or not, and update the menus and toolbar to
1213    enable or disable the "Save" operation. */
1214 void
1215 main_update_for_unsaved_changes(capture_file *cf)
1216 {
1217     set_titlebar_for_capture_file(cf);
1218     set_menus_for_capture_file(cf);
1219     set_toolbar_for_capture_file(cf);
1220 }
1221
1222 #ifdef HAVE_LIBPCAP
1223 void
1224 main_auto_scroll_live_changed(gboolean auto_scroll_live_in)
1225 {
1226     /* Update menubar and toolbar */
1227     menu_auto_scroll_live_changed(auto_scroll_live_in);
1228     toolbar_auto_scroll_live_changed(auto_scroll_live_in);
1229
1230     /* change auto scroll state */
1231     auto_scroll_live  = auto_scroll_live_in;
1232 }
1233 #endif
1234
1235 void
1236 main_colorize_changed(gboolean packet_list_colorize)
1237 {
1238     /* Update menubar and toolbar */
1239     menu_colorize_changed(packet_list_colorize);
1240     toolbar_colorize_changed(packet_list_colorize);
1241
1242     /* change colorization */
1243     if(packet_list_colorize != recent.packet_list_colorize) {
1244         recent.packet_list_colorize = packet_list_colorize;
1245         packet_list_enable_color(packet_list_colorize);
1246         packet_list_colorize_packets();
1247     }
1248 }
1249
1250 static GtkWidget           *close_dlg = NULL;
1251
1252 static void
1253 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1254 {
1255     recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1256 }
1257
1258 #ifdef _WIN32
1259 static void
1260 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1261 {
1262     recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1263 }
1264 #endif
1265
1266 static void
1267 main_cf_cb_file_closing(capture_file *cf)
1268 {
1269     /* if we have more than 10000 packets, show a splash screen while closing */
1270     /* XXX - don't know a better way to decide whether to show or not,
1271      * as most of the time is spend in various calls that destroy various
1272      * data structures, so it wouldn't be easy to use a progress bar,
1273      * rather than, say, a progress spinner, here! */
1274     if(cf->count > 10000) {
1275         close_dlg = (GtkWidget *)simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1276                                   "%sClosing file!%s\n\nPlease wait ...",
1277                                   simple_dialog_primary_start(),
1278                                   simple_dialog_primary_end());
1279         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1280     }
1281     /* Clear maunally resolved addresses */
1282     manually_resolve_cleanup();
1283     /* Destroy all windows that refer to the
1284        capture file we're closing. */
1285     destroy_packet_wins();
1286
1287     /* Update the titlebar to reflect the lack of a capture file. */
1288     set_titlebar_for_capture_file(NULL);
1289
1290     /* Disable all menu and toolbar items that make sense only if
1291        you have a capture. */
1292     set_menus_for_capture_file(NULL);
1293     set_toolbar_for_capture_file(NULL);
1294     main_set_for_captured_packets(FALSE);
1295     set_menus_for_selected_packet(cf);
1296     main_set_for_capture_in_progress(FALSE);
1297     set_capture_if_dialog_for_capture_in_progress(FALSE);
1298     set_menus_for_selected_tree_row(cf);
1299
1300     /* Set up main window for no capture file. */
1301     main_set_for_capture_file(FALSE);
1302
1303     main_window_update();
1304
1305 }
1306
1307 static void
1308 main_cf_cb_file_closed(capture_file *cf _U_)
1309 {
1310     if(close_dlg != NULL) {
1311         splash_destroy(close_dlg);
1312         close_dlg = NULL;
1313     }
1314 }
1315
1316
1317 static void
1318 main_cf_cb_file_read_started(capture_file *cf _U_)
1319 {
1320     tap_param_dlg_update();
1321
1322     /* Set up main window for a capture file. */
1323     main_set_for_capture_file(TRUE);
1324 }
1325
1326 static void
1327 main_cf_cb_file_read_finished(capture_file *cf)
1328 {
1329     gchar *dir_path;
1330
1331     if (!cf->is_tempfile && cf->filename) {
1332         /* Add this filename to the list of recent files in the "Recent Files" submenu */
1333         add_menu_recent_capture_file(cf->filename);
1334
1335         /* Remember folder for next Open dialog and save it in recent */
1336         dir_path = g_strdup(cf->filename);
1337         set_last_open_dir(get_dirname(dir_path));
1338         g_free(dir_path);
1339     }
1340
1341     /* Update the appropriate parts of the main window. */
1342     main_update_for_unsaved_changes(cf);
1343
1344     /* Enable menu items that make sense if you have some captured packets. */
1345     main_set_for_captured_packets(TRUE);
1346 }
1347
1348 static void
1349 main_cf_cb_file_rescan_finished(capture_file *cf)
1350 {
1351     gchar *dir_path;
1352
1353     if (!cf->is_tempfile && cf->filename) {
1354         /* Add this filename to the list of recent files in the "Recent Files" submenu */
1355         add_menu_recent_capture_file(cf->filename);
1356
1357         /* Remember folder for next Open dialog and save it in recent */
1358         dir_path = g_strdup(cf->filename);
1359         set_last_open_dir(get_dirname(dir_path));
1360         g_free(dir_path);
1361     }
1362
1363     /* Update the appropriate parts of the main window. */
1364     main_update_for_unsaved_changes(cf);
1365 }
1366
1367 #ifdef HAVE_LIBPCAP
1368 static GList *icon_list_create(
1369 #ifdef HAVE_GDK_GRESOURCE
1370     const gchar *icon16_path,
1371     const gchar *icon32_path,
1372     const gchar *icon48_path,
1373     const gchar *icon64_path)
1374 #else
1375     const guint8 *icon16_pb,
1376     const guint8 *icon32_pb,
1377     const guint8 *icon48_pb,
1378     const guint8 *icon64_pb)
1379 #endif
1380 {
1381     GList *icon_list = NULL;
1382     GdkPixbuf *pixbuf16 = NULL;
1383     GdkPixbuf *pixbuf32 = NULL;
1384     GdkPixbuf *pixbuf48 = NULL;
1385     GdkPixbuf *pixbuf64 = NULL;
1386
1387 #ifdef HAVE_GDK_GRESOURCE
1388     if (icon16_path != NULL)
1389         pixbuf16 = ws_gdk_pixbuf_new_from_resource(icon16_path);
1390     if (icon32_path != NULL)
1391         pixbuf32 = ws_gdk_pixbuf_new_from_resource(icon32_path);
1392     if (icon48_path != NULL)
1393         pixbuf48 = ws_gdk_pixbuf_new_from_resource(icon48_path);
1394     if (icon64_path != NULL)
1395         pixbuf64 = ws_gdk_pixbuf_new_from_resource(icon64_path);
1396 #else
1397     if (icon16_pb != NULL)
1398         pixbuf16 = gdk_pixbuf_new_from_inline(-1, icon16_pb, FALSE, NULL);
1399     if (icon32_pb != NULL)
1400         pixbuf32 = gdk_pixbuf_new_from_inline(-1, icon32_pb, FALSE, NULL);
1401     if (icon48_pb != NULL)
1402         pixbuf48 = gdk_pixbuf_new_from_inline(-1, icon48_pb, FALSE, NULL);
1403     if (icon64_pb != NULL)
1404         pixbuf64 = gdk_pixbuf_new_from_inline(-1, icon64_pb, FALSE, NULL);
1405 #endif
1406
1407     if (pixbuf16 != NULL)
1408         icon_list = g_list_append(icon_list, pixbuf16);
1409     if (pixbuf32 != NULL)
1410         icon_list = g_list_append(icon_list, pixbuf32);
1411     if (pixbuf48 != NULL)
1412         icon_list = g_list_append(icon_list, pixbuf48);
1413     if (pixbuf64 != NULL)
1414         icon_list = g_list_append(icon_list, pixbuf64);
1415
1416     return icon_list;
1417 }
1418
1419 static void
1420 main_capture_cb_capture_prepared(capture_session *cap_session)
1421 {
1422     static GList *icon_list = NULL;
1423
1424     set_titlebar_for_capture_in_progress((capture_file *)cap_session->cf);
1425
1426     if(icon_list == NULL) {
1427 #ifdef HAVE_GDK_GRESOURCE
1428         icon_list = icon_list_create("/org/wireshark/image/wsiconcap16.png",
1429                                         "/org/wireshark/image/wsiconcap32.png",
1430                                         "/org/wireshark/image/wsiconcap48.png",
1431                                         "/org/wireshark/image/wsiconcap64.png");
1432 #else
1433         icon_list = icon_list_create(wsiconcap_16_pb_data,
1434                                         wsiconcap_32_pb_data,
1435                                         wsiconcap_48_pb_data,
1436                                         wsiconcap_64_pb_data);
1437 #endif
1438     }
1439     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1440
1441     /* Disable menu items that make no sense if you're currently running
1442        a capture. */
1443     main_set_for_capture_in_progress(TRUE);
1444     set_capture_if_dialog_for_capture_in_progress(TRUE);
1445
1446     /* Don't set up main window for a capture file. */
1447     main_set_for_capture_file(FALSE);
1448 }
1449
1450 static void
1451 main_capture_cb_capture_update_started(capture_session *cap_session)
1452 {
1453     /* We've done this in "prepared" above, but it will be cleared while
1454        switching to the next multiple file. */
1455     set_titlebar_for_capture_in_progress((capture_file *)cap_session->cf);
1456
1457     main_set_for_capture_in_progress(TRUE);
1458     set_capture_if_dialog_for_capture_in_progress(TRUE);
1459
1460     /* Enable menu items that make sense if you have some captured
1461        packets (yes, I know, we don't have any *yet*). */
1462     main_set_for_captured_packets(TRUE);
1463
1464     /* Set up main window for a capture file. */
1465     main_set_for_capture_file(TRUE);
1466 }
1467
1468 static void
1469 main_capture_cb_capture_update_finished(capture_session *cap_session)
1470 {
1471     capture_file *cf = (capture_file *)cap_session->cf;
1472     static GList *icon_list = NULL;
1473
1474     /* The capture isn't stopping any more - it's stopped. */
1475     capture_stopping = FALSE;
1476
1477     if (!cf->is_tempfile && cf->filename) {
1478         /* Add this filename to the list of recent files in the "Recent Files" submenu */
1479         add_menu_recent_capture_file(cf->filename);
1480     }
1481
1482     /* Enable menu items that make sense if you're not currently running
1483      a capture. */
1484     main_set_for_capture_in_progress(FALSE);
1485     set_capture_if_dialog_for_capture_in_progress(FALSE);
1486
1487     /* Update the main window as appropriate. This has to occur AFTER
1488      * main_set_for_capture_in_progress() or else some of the menus are
1489      * incorrectly disabled (see bug
1490      * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8108) */
1491     main_update_for_unsaved_changes(cf);
1492
1493     /* Set up main window for a capture file. */
1494     main_set_for_capture_file(TRUE);
1495
1496     if(icon_list == NULL) {
1497 #ifdef HAVE_GDK_GRESOURCE
1498         icon_list = icon_list_create("/org/wireshark/image/wsicon16.png",
1499                                         "/org/wireshark/image/wsicon32.png",
1500                                         "/org/wireshark/image/wsicon48.png",
1501                                         "/org/wireshark/image/wsicon64.png");
1502 #else
1503         icon_list = icon_list_create(wsicon_16_pb_data,
1504                                         wsicon_32_pb_data,
1505                                         wsicon_48_pb_data,
1506                                         wsicon_64_pb_data);
1507 #endif
1508     }
1509     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1510
1511     if(global_commandline_info.quit_after_cap) {
1512         /* command line asked us to quit after the capture */
1513         /* don't pop up a dialog to ask for unsaved files etc. */
1514         main_do_quit();
1515     }
1516 }
1517
1518 static void
1519 main_capture_cb_capture_fixed_started(capture_session *cap_session _U_)
1520 {
1521     /* Don't set up main window for a capture file. */
1522     main_set_for_capture_file(FALSE);
1523 }
1524
1525 static void
1526 main_capture_cb_capture_fixed_finished(capture_session *cap_session _U_)
1527 {
1528 #if 0
1529     capture_file *cf = (capture_file *)cap_session->cf;
1530 #endif
1531     static GList *icon_list = NULL;
1532
1533     /* The capture isn't stopping any more - it's stopped. */
1534     capture_stopping = FALSE;
1535
1536     /*set_titlebar_for_capture_file(cf);*/
1537
1538     /* Enable menu items that make sense if you're not currently running
1539      a capture. */
1540     main_set_for_capture_in_progress(FALSE);
1541     set_capture_if_dialog_for_capture_in_progress(FALSE);
1542
1543     /* Restore the standard title bar message */
1544     /* (just in case we have trouble opening the capture file). */
1545     set_titlebar_for_capture_file(NULL);
1546
1547     if(icon_list == NULL) {
1548 #ifdef HAVE_GDK_GRESOURCE
1549         icon_list = icon_list_create("/org/wireshark/image/wsicon16.png",
1550                                         "/org/wireshark/image/wsicon32.png",
1551                                         "/org/wireshark/image/wsicon48.png",
1552                                         "/org/wireshark/image/wsicon64.png");
1553 #else
1554         icon_list = icon_list_create(wsicon_16_pb_data,
1555                                         wsicon_32_pb_data,
1556                                         wsicon_48_pb_data,
1557                                         wsicon_64_pb_data);
1558 #endif
1559     }
1560     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1561
1562     /* We don't have loaded the capture file, this will be done later.
1563      * For now we still have simply a blank screen. */
1564
1565     if(global_commandline_info.quit_after_cap) {
1566         /* command line asked us to quit after the capture */
1567         /* don't pop up a dialog to ask for unsaved files etc. */
1568         main_do_quit();
1569     }
1570 }
1571
1572 static void
1573 main_capture_cb_capture_stopping(capture_session *cap_session _U_)
1574 {
1575     capture_stopping = TRUE;
1576     set_menus_for_capture_stopping();
1577 #ifdef HAVE_LIBPCAP
1578     set_toolbar_for_capture_stopping();
1579
1580     set_capture_if_dialog_for_capture_stopping();
1581 #endif
1582 }
1583
1584 static void
1585 main_capture_cb_capture_failed(capture_session *cap_session _U_)
1586 {
1587     static GList *icon_list = NULL;
1588
1589     /* Capture isn't stopping any more. */
1590     capture_stopping = FALSE;
1591
1592     /* the capture failed before the first packet was captured
1593        reset title, menus and icon */
1594     set_titlebar_for_capture_file(NULL);
1595
1596     main_set_for_capture_in_progress(FALSE);
1597     set_capture_if_dialog_for_capture_in_progress(FALSE);
1598
1599     main_set_for_capture_file(FALSE);
1600
1601     if(icon_list == NULL) {
1602 #ifdef HAVE_GDK_GRESOURCE
1603         icon_list = icon_list_create("/org/wireshark/image/wsicon16.png",
1604                                         "/org/wireshark/image/wsicon32.png",
1605                                         "/org/wireshark/image/wsicon48.png",
1606                                         "/org/wireshark/image/wsicon64.png");
1607 #else
1608         icon_list = icon_list_create(wsicon_16_pb_data,
1609                                         wsicon_32_pb_data,
1610                                         wsicon_48_pb_data,
1611                                         wsicon_64_pb_data);
1612 #endif
1613     }
1614     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1615
1616
1617     if(global_commandline_info.quit_after_cap) {
1618         /* command line asked us to quit after the capture */
1619         /* don't pop up a dialog to ask for unsaved files etc. */
1620         main_do_quit();
1621     }
1622 }
1623 #endif  /* HAVE_LIBPCAP */
1624
1625 static void
1626 main_cf_cb_packet_selected(gpointer data)
1627 {
1628     capture_file *cf = (capture_file *)data;
1629
1630     /* Display the GUI protocol tree and packet bytes.
1631       XXX - why do we dump core if we call "proto_tree_draw()"
1632       before calling "add_byte_views()"? */
1633     add_byte_views(cf->edt, tree_view_gbl, byte_nb_ptr_gbl);
1634     proto_tree_draw(cf->edt->tree, tree_view_gbl);
1635
1636     /* Note: Both string and hex value searches in the packet data produce a non-zero
1637        search_pos if successful */
1638     if(cf->search_in_progress &&
1639       (cf->search_pos != 0 || (cf->string && cf->decode_data))) {
1640         highlight_field(cf->edt->tvb, cf->search_pos,
1641                         (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1642     }
1643
1644     /* A packet is selected. */
1645     set_menus_for_selected_packet(cf);
1646 }
1647
1648 static void
1649 main_cf_cb_packet_unselected(capture_file *cf)
1650 {
1651     /* No packet is being displayed; clear the hex dump pane by getting
1652        rid of all the byte views. */
1653     while (gtk_notebook_get_nth_page(GTK_NOTEBOOK(byte_nb_ptr_gbl), 0) != NULL)
1654         gtk_notebook_remove_page(GTK_NOTEBOOK(byte_nb_ptr_gbl), 0);
1655
1656     /* Add a placeholder byte view so that there's at least something
1657        displayed in the byte view notebook. */
1658     add_byte_tab(byte_nb_ptr_gbl, "", NULL, NULL, tree_view_gbl);
1659
1660     /* And clear the protocol tree display as well. */
1661     proto_tree_draw(NULL, tree_view_gbl);
1662
1663     /* No packet is selected. */
1664     set_menus_for_selected_packet(cf);
1665 }
1666
1667 static void
1668 main_cf_cb_field_unselected(capture_file *cf)
1669 {
1670     set_menus_for_selected_tree_row(cf);
1671 }
1672
1673 static void
1674 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1675 {
1676     capture_file *cf = (capture_file *)data;
1677     switch(event) {
1678     case(cf_cb_file_opened):
1679         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Opened");
1680         fileset_file_opened(cf);
1681         break;
1682     case(cf_cb_file_closing):
1683         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1684         main_cf_cb_file_closing(cf);
1685         break;
1686     case(cf_cb_file_closed):
1687         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1688         main_cf_cb_file_closed(cf);
1689         fileset_file_closed();
1690         break;
1691     case(cf_cb_file_read_started):
1692         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1693         main_cf_cb_file_read_started(cf);
1694         break;
1695     case(cf_cb_file_read_finished):
1696         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1697         main_cf_cb_file_read_finished(cf);
1698         break;
1699     case(cf_cb_file_reload_started):
1700         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload started");
1701         main_cf_cb_file_read_started(cf);
1702         break;
1703     case(cf_cb_file_reload_finished):
1704         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1705         main_cf_cb_file_read_finished(cf);
1706         break;
1707     case(cf_cb_file_rescan_started):
1708         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan started");
1709         break;
1710     case(cf_cb_file_rescan_finished):
1711         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan finished");
1712         main_cf_cb_file_rescan_finished(cf);
1713         break;
1714     case(cf_cb_file_retap_started):
1715         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Retap started");
1716         break;
1717     case(cf_cb_file_retap_finished):
1718         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Retap finished");
1719         break;
1720     case(cf_cb_file_fast_save_finished):
1721         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Fast save finished");
1722         main_cf_cb_file_rescan_finished(cf);
1723         break;
1724     case(cf_cb_packet_selected):
1725         main_cf_cb_packet_selected(cf);
1726         break;
1727     case(cf_cb_packet_unselected):
1728         main_cf_cb_packet_unselected(cf);
1729         break;
1730     case(cf_cb_field_unselected):
1731         main_cf_cb_field_unselected(cf);
1732         break;
1733     case(cf_cb_file_save_started):
1734         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1735         break;
1736     case(cf_cb_file_save_finished):
1737         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1738         break;
1739     case(cf_cb_file_save_failed):
1740         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1741         break;
1742     case(cf_cb_file_save_stopped):
1743         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save stopped");
1744         break;
1745     case(cf_cb_file_export_specified_packets_started):
1746         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets started");
1747         break;
1748     case(cf_cb_file_export_specified_packets_finished):
1749         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets finished");
1750         break;
1751     case(cf_cb_file_export_specified_packets_failed):
1752         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets failed");
1753         break;
1754     case(cf_cb_file_export_specified_packets_stopped):
1755         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets stopped");
1756         break;
1757     default:
1758         g_warning("main_cf_callback: event %u unknown", event);
1759         g_assert_not_reached();
1760     }
1761 }
1762
1763 #ifdef HAVE_LIBPCAP
1764 static void
1765 main_capture_callback(gint event, capture_session *cap_session, gpointer user_data _U_)
1766 {
1767 #ifdef HAVE_GTKOSXAPPLICATION
1768     GtkosxApplication *theApp;
1769 #endif
1770     switch(event) {
1771     case(capture_cb_capture_prepared):
1772         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1773         main_capture_cb_capture_prepared(cap_session);
1774         break;
1775     case(capture_cb_capture_update_started):
1776         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1777         main_capture_cb_capture_update_started(cap_session);
1778 #ifdef HAVE_GTKOSXAPPLICATION
1779         theApp = (GtkosxApplication *)g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
1780 #ifdef HAVE_GDK_GRESOURCE
1781         gtkosx_application_set_dock_icon_pixbuf(theApp, ws_gdk_pixbuf_new_from_resource("/org/wireshark/image/wsicon48.png"));
1782 #else
1783         gtkosx_application_set_dock_icon_pixbuf(theApp, gdk_pixbuf_new_from_inline(-1, wsicon_48_pb_data, FALSE, NULL));
1784 #endif
1785 #endif
1786         break;
1787     case(capture_cb_capture_update_continue):
1788         /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1789         break;
1790     case(capture_cb_capture_update_finished):
1791         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1792         main_capture_cb_capture_update_finished(cap_session);
1793         break;
1794     case(capture_cb_capture_fixed_started):
1795         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1796         main_capture_cb_capture_fixed_started(cap_session);
1797         break;
1798     case(capture_cb_capture_fixed_continue):
1799         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1800         break;
1801     case(capture_cb_capture_fixed_finished):
1802         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1803         main_capture_cb_capture_fixed_finished(cap_session);
1804         break;
1805     case(capture_cb_capture_stopping):
1806         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1807         /* Beware: this state won't be called, if the capture child
1808          * closes the capturing on its own! */
1809 #ifdef HAVE_GTKOSXAPPLICATION
1810         theApp = (GtkosxApplication *)g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
1811 #ifdef HAVE_GDK_GRESOURCE
1812         gtkosx_application_set_dock_icon_pixbuf(theApp, ws_gdk_pixbuf_new_from_resource("/org/wireshark/image/wsicon64.png"));
1813 #else
1814         gtkosx_application_set_dock_icon_pixbuf(theApp, gdk_pixbuf_new_from_inline(-1, wsicon_64_pb_data, FALSE, NULL));
1815 #endif
1816 #endif
1817         main_capture_cb_capture_stopping(cap_session);
1818         break;
1819     case(capture_cb_capture_failed):
1820         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture failed");
1821         main_capture_cb_capture_failed(cap_session);
1822         break;
1823     default:
1824         g_warning("main_capture_callback: event %u unknown", event);
1825         g_assert_not_reached();
1826     }
1827 }
1828 #endif
1829
1830 void
1831 get_wireshark_gtk_compiled_info(GString *str)
1832 {
1833     g_string_append(str, "with ");
1834     g_string_append_printf(str,
1835 #ifdef GTK_MAJOR_VERSION
1836                            "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1837                            GTK_MICRO_VERSION);
1838 #else
1839                            "GTK+ (version unknown)");
1840 #endif
1841
1842     /* Cairo */
1843     g_string_append(str, ", with Cairo ");
1844     g_string_append(str, CAIRO_VERSION_STRING);
1845
1846     /* Pango */
1847     g_string_append(str, ", with Pango ");
1848     g_string_append(str, PANGO_VERSION_STRING);
1849
1850     /* Capture libraries */
1851     g_string_append(str, ", ");
1852     get_compiled_caplibs_version(str);
1853 }
1854
1855 void
1856 get_gui_compiled_info(GString *str)
1857 {
1858     epan_get_compiled_version_info(str);
1859
1860     g_string_append(str, ", ");
1861 #ifdef HAVE_LIBPORTAUDIO
1862 #ifdef PORTAUDIO_API_1
1863     g_string_append(str, "with PortAudio <= V18");
1864 #else /* PORTAUDIO_API_1 */
1865     g_string_append(str, "with ");
1866     g_string_append(str, Pa_GetVersionText());
1867 #endif /* PORTAUDIO_API_1 */
1868 #else /* HAVE_LIBPORTAUDIO */
1869     g_string_append(str, "without PortAudio");
1870 #endif /* HAVE_LIBPORTAUDIO */
1871
1872     g_string_append(str, ", ");
1873 #ifdef HAVE_AIRPCAP
1874     get_compiled_airpcap_version(str);
1875 #else
1876     g_string_append(str, "without AirPcap");
1877 #endif
1878
1879     codec_get_compiled_version_info(str);
1880 }
1881
1882 void
1883 get_wireshark_runtime_info(GString *str)
1884 {
1885 #ifdef HAVE_LIBPCAP
1886     /* Capture libraries */
1887     g_string_append(str, ", ");
1888     get_runtime_caplibs_version(str);
1889 #endif
1890
1891     /* stuff used by libwireshark */
1892     epan_get_runtime_version_info(str);
1893
1894 #ifdef HAVE_AIRPCAP
1895     g_string_append(str, ", ");
1896     get_runtime_airpcap_version(str);
1897 #endif
1898 }
1899
1900 static e_prefs *
1901 read_configuration_files(char **gdp_path, char **dp_path)
1902 {
1903     int                  gpf_open_errno, gpf_read_errno;
1904     int                  cf_open_errno, df_open_errno;
1905     int                  gdp_open_errno, gdp_read_errno;
1906     int                  dp_open_errno, dp_read_errno;
1907     char                *gpf_path, *pf_path;
1908     char                *cf_path, *df_path;
1909     int                  pf_open_errno, pf_read_errno;
1910     e_prefs             *prefs_p;
1911
1912     /* load the decode as entries of this profile */
1913     load_decode_as_entries();
1914
1915     /* Read the preference files. */
1916     prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1917                          &pf_open_errno, &pf_read_errno, &pf_path);
1918
1919     if (gpf_path != NULL) {
1920         if (gpf_open_errno != 0) {
1921             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1922                           "Could not open global preferences file\n\"%s\": %s.",
1923                           gpf_path, g_strerror(gpf_open_errno));
1924         }
1925         if (gpf_read_errno != 0) {
1926             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1927                           "I/O error reading global preferences file\n\"%s\": %s.",
1928                           gpf_path, g_strerror(gpf_read_errno));
1929         }
1930     }
1931     if (pf_path != NULL) {
1932         if (pf_open_errno != 0) {
1933             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1934                           "Could not open your preferences file\n\"%s\": %s.",
1935                           pf_path, g_strerror(pf_open_errno));
1936         }
1937         if (pf_read_errno != 0) {
1938             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1939                           "I/O error reading your preferences file\n\"%s\": %s.",
1940                           pf_path, g_strerror(pf_read_errno));
1941         }
1942         g_free(pf_path);
1943         pf_path = NULL;
1944     }
1945
1946 #ifdef _WIN32
1947     /* if the user wants a console to be always there, well, we should open one for him */
1948     if (prefs_p->gui_console_open == console_open_always) {
1949         create_console();
1950     }
1951 #endif
1952
1953     /* Read the capture filter file. */
1954     read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1955     if (cf_path != NULL) {
1956         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1957                       "Could not open your capture filter file\n\"%s\": %s.",
1958                       cf_path, g_strerror(cf_open_errno));
1959         g_free(cf_path);
1960     }
1961
1962     /* Read the display filter file. */
1963     read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1964     if (df_path != NULL) {
1965         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1966                       "Could not open your display filter file\n\"%s\": %s.",
1967                       df_path, g_strerror(df_open_errno));
1968         g_free(df_path);
1969     }
1970
1971     /* Read the disabled protocols file. */
1972     read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1973                               dp_path, &dp_open_errno, &dp_read_errno);
1974     read_disabled_heur_dissector_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1975                               dp_path, &dp_open_errno, &dp_read_errno);
1976     if (*gdp_path != NULL) {
1977         if (gdp_open_errno != 0) {
1978             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1979                           "Could not open global disabled protocols file\n\"%s\": %s.",
1980                           *gdp_path, g_strerror(gdp_open_errno));
1981         }
1982         if (gdp_read_errno != 0) {
1983             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1984                           "I/O error reading global disabled protocols file\n\"%s\": %s.",
1985                           *gdp_path, g_strerror(gdp_read_errno));
1986         }
1987         g_free(*gdp_path);
1988         *gdp_path = NULL;
1989     }
1990     if (*dp_path != NULL) {
1991         if (dp_open_errno != 0) {
1992             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1993                           "Could not open your disabled protocols file\n\"%s\": %s.",
1994                           *dp_path, g_strerror(dp_open_errno));
1995         }
1996         if (dp_read_errno != 0) {
1997             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1998                           "I/O error reading your disabled protocols file\n\"%s\": %s.",
1999                           *dp_path, g_strerror(dp_read_errno));
2000         }
2001         g_free(*dp_path);
2002         *dp_path = NULL;
2003     }
2004
2005     return prefs_p;
2006 }
2007
2008 /*  Check if there's something important to tell the user during startup.
2009  *  We want to do this *after* showing the main window so that any windows
2010  *  we pop up will be above the main window.
2011  */
2012 static void
2013 #ifdef _WIN32
2014 check_and_warn_user_startup(gchar *cf_name)
2015 #else
2016 check_and_warn_user_startup(gchar *cf_name _U_)
2017 #endif
2018 {
2019     gchar               *cur_user, *cur_group;
2020     gpointer             priv_warning_dialog;
2021
2022     /* Tell the user not to run as root. */
2023     if (running_with_special_privs() && recent.privs_warn_if_elevated) {
2024         cur_user = get_cur_username();
2025         cur_group = get_cur_groupname();
2026         priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2027         "Running as user \"%s\" and group \"%s\".\n"
2028         "This could be dangerous.\n\n"
2029         "If you're running Wireshark this way in order to perform live capture, "
2030         "you may want to be aware that there is a better way documented at\n"
2031         "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
2032         g_free(cur_user);
2033         g_free(cur_group);
2034         simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2035         simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2036     }
2037
2038 #ifdef _WIN32
2039     /* Warn the user if npf.sys isn't loaded. */
2040     if (!get_stdin_capture() && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
2041         priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2042         "The NPF driver isn't running.  You may have trouble\n"
2043         "capturing or listing interfaces.");
2044         simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2045         simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2046     }
2047 #endif
2048
2049 }
2050
2051 /* And now our feature presentation... [ fade to music ] */
2052 int
2053 main(int argc, char *argv[])
2054 {
2055     char                *init_progfile_dir_error;
2056     char                *s;
2057
2058     extern int           info_update_freq;  /* Found in about_dlg.c. */
2059     const gchar         *filter;
2060
2061 #ifdef _WIN32
2062     WSADATA              wsaData;
2063 #endif  /* _WIN32 */
2064
2065     char                *rf_path;
2066     int                  rf_open_errno;
2067     char                *gdp_path, *dp_path;
2068     int                  err;
2069 #ifdef HAVE_LIBPCAP
2070     gchar               *err_str;
2071     int                  status;
2072 #else
2073 #ifdef _WIN32
2074 #ifdef HAVE_AIRPCAP
2075     gchar               *err_str;
2076 #endif
2077 #endif
2078 #endif
2079     gint                 pl_size = 280, tv_size = 95, bv_size = 75;
2080     gchar               *rc_file;
2081     dfilter_t           *rfcode = NULL;
2082     gchar               *err_msg = NULL;
2083     gboolean             rfilter_parse_failed = FALSE;
2084     GtkWidget           *splash_win = NULL;
2085     dfilter_t           *jump_to_filter = NULL;
2086     unsigned int         in_file_type = WTAP_TYPE_AUTO;
2087 #ifdef HAVE_GTKOSXAPPLICATION
2088     GtkosxApplication   *theApp;
2089 #endif
2090     GString             *comp_info_str = NULL;
2091     GString             *runtime_info_str = NULL;
2092
2093 #ifdef HAVE_GDK_GRESOURCE
2094     main_register_resource();
2095 #endif
2096
2097     cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
2098
2099     /* Set the current locale according to the program environment.
2100      * We haven't localized anything, but some GTK widgets are localized
2101      * (the file selection dialogue, for example).
2102      * This also sets the C-language locale to the native environment. */
2103     setlocale(LC_ALL, "");
2104 #ifdef _WIN32
2105     arg_list_utf_16to8(argc, argv);
2106     create_app_running_mutex();
2107 #endif /* _WIN32 */
2108
2109     /*
2110      * Get credential information for later use, and drop privileges
2111      * before doing anything else.
2112      * Let the user know if anything happened.
2113      */
2114     init_process_policies();
2115     relinquish_special_privs_perm();
2116
2117     /*
2118      * Attempt to get the pathname of the executable file.
2119      */
2120     init_progfile_dir_error = init_progfile_dir(argv[0], main);
2121
2122     /* initialize the funnel mini-api */
2123     initialize_funnel_ops();
2124
2125     AirPDcapInitContext(&airpdcap_ctx);
2126
2127 #ifdef _WIN32
2128     /* Load wpcap if possible. Do this before collecting the run-time version information */
2129     load_wpcap();
2130
2131     /* ... and also load the packet.dll from wpcap */
2132     wpcap_packet_load();
2133
2134 #ifdef HAVE_AIRPCAP
2135     /* Load the airpcap.dll.  This must also be done before collecting
2136      * run-time version information. */
2137     airpcap_dll_ret_val = load_airpcap();
2138
2139     switch (airpcap_dll_ret_val) {
2140         case AIRPCAP_DLL_OK:
2141             /* load the airpcap interfaces */
2142             g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2143
2144             if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
2145                 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2146                     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
2147                     g_free(err_str);
2148                 }
2149             airpcap_if_active = NULL;
2150
2151             } else {
2152
2153                 /* select the first ad default (THIS SHOULD BE CHANGED) */
2154                 airpcap_if_active = airpcap_get_default_if(g_airpcap_if_list);
2155             }
2156         break;
2157 #if 0
2158         /*
2159          * XXX - Maybe we need to warn the user if one of the following happens???
2160          */
2161         case AIRPCAP_DLL_OLD:
2162             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2163         break;
2164
2165         case AIRPCAP_DLL_ERROR:
2166             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2167         break;
2168
2169         case AIRPCAP_DLL_NOT_FOUND:
2170             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2171         break;
2172 #endif
2173     }
2174 #endif /* HAVE_AIRPCAP */
2175 #endif  /* _WIN32 */
2176
2177     /* Get the compile-time version information string */
2178     comp_info_str = get_compiled_version_info(get_wireshark_gtk_compiled_info,
2179                                               get_gui_compiled_info);
2180
2181     /* Get the run-time version information string */
2182     runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
2183
2184     /* Add it to the information to be reported on a crash. */
2185     ws_add_crash_info("Wireshark %s\n"
2186         "\n"
2187         "%s"
2188         "\n"
2189         "%s",
2190         get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
2191
2192 #ifdef _WIN32
2193     /* Start windows sockets */
2194     WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2195 #endif  /* _WIN32 */
2196
2197     profile_store_persconffiles (TRUE);
2198
2199     /* Read the profile independent recent file.  We have to do this here so we can */
2200     /* set the profile before it can be set from the command line parameter */
2201     recent_read_static(&rf_path, &rf_open_errno);
2202     if (rf_path != NULL && rf_open_errno != 0) {
2203         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2204                       "Could not open common recent file\n\"%s\": %s.",
2205                       rf_path, g_strerror(rf_open_errno));
2206     }
2207
2208     commandline_early_options(argc, argv, comp_info_str, runtime_info_str);
2209
2210     /* Init the "Open file" dialog directory */
2211     /* (do this after the path settings are processed) */
2212
2213     /* Read the profile dependent (static part) of the recent file. */
2214     /* Only the static part of it will be read, as we don't have the gui now to fill the */
2215     /* recent lists which is done in the dynamic part. */
2216     /* We have to do this already here, so command line parameters can overwrite these values. */
2217     if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
2218         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2219                       "Could not open recent file\n\"%s\": %s.",
2220                       rf_path, g_strerror(rf_open_errno));
2221         g_free(rf_path);
2222     }
2223
2224     if (recent.gui_fileopen_remembered_dir &&
2225         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
2226         set_last_open_dir(recent.gui_fileopen_remembered_dir);
2227     } else {
2228         set_last_open_dir(get_persdatafile_dir());
2229     }
2230
2231 #if !GLIB_CHECK_VERSION(2,31,0)
2232     g_thread_init(NULL);
2233 #endif
2234
2235     /* Disable liboverlay scrollbar which broke Wireshark on Ubuntu */
2236 #if !GTK_CHECK_VERSION(3,16,0)
2237     if (NULL == g_getenv("LIBOVERLAY_SCROLLBAR")) {
2238         g_setenv("LIBOVERLAY_SCROLLBAR", "0", FALSE);
2239     }
2240 #endif
2241
2242     /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2243     gtk_init (&argc, &argv);
2244
2245     cf_callback_add(main_cf_callback, NULL);
2246 #ifdef HAVE_LIBPCAP
2247     capture_callback_add(main_capture_callback, NULL);
2248 #endif
2249
2250     cf_callback_add(statusbar_cf_callback, NULL);
2251 #ifdef HAVE_LIBPCAP
2252     capture_callback_add(statusbar_capture_callback, NULL);
2253 #endif
2254
2255     cf_callback_add(welcome_cf_callback, NULL);
2256 #ifdef HAVE_LIBPCAP
2257     capture_callback_add(welcome_capture_callback, NULL);
2258 #endif
2259
2260     set_console_log_handler();
2261
2262 #ifdef HAVE_LIBPCAP
2263     /* Set the initial values in the capture options. This might be overwritten
2264        by preference settings and then again by the command line parameters. */
2265     capture_opts_init(&global_capture_opts);
2266
2267     capture_session_init(&global_capture_session, &cfile);
2268 #endif
2269
2270     init_report_err(vfailure_alert_box, open_failure_alert_box,
2271                     read_failure_alert_box, write_failure_alert_box);
2272
2273     /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2274     filter = get_conn_cfilter();
2275     if ( *filter != '\0' ) {
2276         info_update_freq = 1000;  /* Milliseconds */
2277     }
2278
2279     /* We won't come till here, if we had a "console only" command line parameter. */
2280     splash_win = splash_new("Loading Wireshark ...");
2281     if (init_progfile_dir_error != NULL) {
2282         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2283                       "Can't get pathname of Wireshark: %s.\n"
2284                       "It won't be possible to capture traffic.\n"
2285                       "Report this to the Wireshark developers.",
2286                       init_progfile_dir_error);
2287         g_free(init_progfile_dir_error);
2288     }
2289
2290     wtap_init();
2291
2292 #ifdef HAVE_PLUGINS
2293     /* Register all the plugin types we have. */
2294     epan_register_plugin_types(); /* Types known to libwireshark */
2295     codec_register_plugin_types(); /* Types known to libwscodecs */
2296
2297     /* Scan for plugins.  This does *not* call their registration routines;
2298        that's done later. */
2299     scan_plugins(REPORT_LOAD_FAILURE);
2300
2301     /* Register all libwiretap plugin modules. */
2302     register_all_wiretap_modules();
2303 #endif
2304
2305     /* Register all audio codec plugins. */
2306     register_all_codecs();
2307
2308     splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2309
2310     /* Register all dissectors; we must do this before checking for the
2311        "-G" flag, as the "-G" flag dumps information registered by the
2312        dissectors, and we must do it before we read the preferences, in
2313        case any dissectors register preferences. */
2314     if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
2315                    splash_update, (gpointer) splash_win))
2316       return 2;
2317
2318     splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2319
2320     /* Register all tap listeners; we do this before we parse the arguments,
2321        as the "-z" argument can specify a registered tap. */
2322
2323     /* we register the plugin taps before the other taps because
2324        stats_tree taps plugins will be registered as tap listeners
2325        by stats_tree_stat.c and need to registered before that */
2326
2327 #ifdef HAVE_PLUGINS
2328     register_all_plugin_tap_listeners();
2329 #endif
2330
2331 #ifdef HAVE_EXTCAP
2332     extcap_register_preferences();
2333 #endif
2334
2335     register_all_tap_listeners();
2336     conversation_table_set_gui_info(init_conversation_table);
2337     hostlist_table_set_gui_info(init_hostlist_table);
2338     srt_table_iterate_tables(register_service_response_tables, NULL);
2339     rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
2340     new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
2341
2342     splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2343
2344     global_commandline_info.prefs_p = read_configuration_files (&gdp_path, &dp_path);
2345     /* Removed thread code:
2346      * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
2347      */
2348
2349     splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2350     cap_file_init(&cfile);
2351
2352     /* Fill in capture options with values from the preferences */
2353     prefs_to_capture_opts();
2354
2355 /*#ifdef HAVE_LIBPCAP
2356     fill_in_local_interfaces();
2357 #endif*/
2358
2359     /* Now get our args */
2360     commandline_other_options(argc, argv, TRUE);
2361
2362 #ifdef HAVE_LIBPCAP
2363     splash_update(RA_INTERFACES, NULL, (gpointer)splash_win);
2364
2365     fill_in_local_interfaces(main_window_update);
2366
2367     if (global_commandline_info.start_capture || global_commandline_info.list_link_layer_types) {
2368         /* We're supposed to do a live capture or get a list of link-layer
2369            types for a live capture device; if the user didn't specify an
2370            interface to use, pick a default. */
2371         status = capture_opts_default_iface_if_necessary(&global_capture_opts,
2372         ((global_commandline_info.prefs_p->capture_device) && (*global_commandline_info.prefs_p->capture_device != '\0')) ? get_if_name(global_commandline_info.prefs_p->capture_device) : NULL);
2373         if (status != 0) {
2374             exit(status);
2375         }
2376     }
2377
2378     if (global_commandline_info.list_link_layer_types) {
2379         /* Get the list of link-layer types for the capture devices. */
2380         if_capabilities_t *caps;
2381         guint i;
2382         interface_t device;
2383         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2384
2385             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2386             if (device.selected) {
2387                 gchar* auth_str = NULL;
2388 #ifdef HAVE_PCAP_REMOTE
2389                 if (device.remote_opts.remote_host_opts.auth_type == CAPTURE_AUTH_PWD) {
2390                     auth_str = g_strdup_printf("%s:%s", device.remote_opts.remote_host_opts.auth_username,
2391                                                device.remote_opts.remote_host_opts.auth_password);
2392                 }
2393 #endif
2394 #if defined(HAVE_PCAP_CREATE)
2395                 caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, auth_str, &err_str, main_window_update);
2396 #else
2397                 caps = capture_get_if_capabilities(device.name, FALSE, auth_str, &err_str,main_window_update);
2398 #endif
2399                 g_free(auth_str);
2400                 if (caps == NULL) {
2401                     cmdarg_err("%s", err_str);
2402                     g_free(err_str);
2403                     exit(2);
2404                 }
2405             if (caps->data_link_types == NULL) {
2406                 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
2407                 exit(2);
2408             }
2409 #ifdef _WIN32
2410             create_console();
2411 #endif /* _WIN32 */
2412 #if defined(HAVE_PCAP_CREATE)
2413             capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
2414 #else
2415             capture_opts_print_if_capabilities(caps, device.name, FALSE);
2416 #endif
2417 #ifdef _WIN32
2418             destroy_console();
2419 #endif /* _WIN32 */
2420             free_if_capabilities(caps);
2421             }
2422         }
2423         exit(0);
2424     }
2425   capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2426   capture_opts_trim_ring_num_files(&global_capture_opts);
2427 #endif /* HAVE_LIBPCAP */
2428
2429     /* Notify all registered modules that have had any of their preferences
2430        changed either from one of the preferences file or from the command
2431        line that their preferences have changed. */
2432     prefs_apply_all();
2433
2434 #ifdef HAVE_LIBPCAP
2435     if ((global_capture_opts.num_selected == 0) &&
2436         ((prefs.capture_device != NULL) &&
2437          (global_commandline_info.prefs_p != NULL) &&
2438          (*global_commandline_info.prefs_p->capture_device != '\0'))) {
2439         guint i;
2440         interface_t device;
2441         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2442             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2443             if (!device.hidden && strstr(prefs.capture_device, device.name) != NULL) {
2444                 device.selected = TRUE;
2445                 global_capture_opts.num_selected++;
2446                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
2447                 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
2448                 break;
2449             }
2450         }
2451     }
2452     if (global_capture_opts.num_selected == 0 && global_capture_opts.all_ifaces->len == 1) {
2453         interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, 0);
2454         device.selected = TRUE;
2455         global_capture_opts.num_selected++;
2456         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, 0);
2457         g_array_insert_val(global_capture_opts.all_ifaces, 0, device);
2458     }
2459 #endif
2460
2461     /* disabled protocols as per configuration file */
2462     if (gdp_path == NULL && dp_path == NULL) {
2463         set_disabled_protos_list();
2464         set_disabled_heur_dissector_list();
2465     }
2466
2467     if(global_dissect_options.disable_protocol_slist) {
2468         GSList *proto_disable;
2469         for (proto_disable = global_dissect_options.disable_protocol_slist; proto_disable != NULL; proto_disable = g_slist_next(proto_disable))
2470         {
2471             proto_disable_proto_by_name((char*)proto_disable->data);
2472         }
2473     }
2474
2475     if(global_dissect_options.disable_heur_slist) {
2476         GSList *heur_enable;
2477         for (heur_enable = global_dissect_options.disable_heur_slist; heur_enable != NULL; heur_enable = g_slist_next(heur_enable))
2478         {
2479             proto_enable_heuristic_by_name((char*)heur_enable->data, TRUE);
2480         }
2481     }
2482
2483     if(global_dissect_options.disable_heur_slist) {
2484         GSList *heur_disable;
2485         for (heur_disable = global_dissect_options.disable_heur_slist; heur_disable != NULL; heur_disable = g_slist_next(heur_disable))
2486         {
2487             proto_enable_heuristic_by_name((char*)heur_disable->data, FALSE);
2488         }
2489     }
2490
2491     build_column_format_array(&cfile.cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
2492
2493     /* read in rc file from global and personal configuration paths. */
2494     rc_file = get_datafile_path(RC_FILE);
2495 #if GTK_CHECK_VERSION(3,0,0)
2496     /* XXX resolve later */
2497 #else
2498     gtk_rc_parse(rc_file);
2499     g_free(rc_file);
2500     rc_file = get_persconffile_path(RC_FILE, FALSE);
2501     gtk_rc_parse(rc_file);
2502 #endif
2503     g_free(rc_file);
2504
2505     font_init();
2506
2507     macros_init();
2508
2509     stock_icons_init();
2510
2511     /* close the splash screen, as we are going to open the main window now */
2512     splash_destroy(splash_win);
2513
2514     /************************************************************************/
2515     /* Everything is prepared now, preferences and command line was read in */
2516
2517     /* Pop up the main window. */
2518     create_main_window(pl_size, tv_size, bv_size, global_commandline_info.prefs_p);
2519
2520     /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2521     if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
2522         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2523                       "Could not open recent file\n\"%s\": %s.",
2524                       rf_path, g_strerror(rf_open_errno));
2525         g_free(rf_path);
2526     }
2527
2528     packet_list_enable_color(recent.packet_list_colorize);
2529
2530     /* rearrange all the widgets as we now have all recent settings ready for this */
2531     main_widgets_rearrange();
2532
2533     /* Fill in column titles.  This must be done after the top level window
2534      is displayed.
2535
2536      XXX - is that still true, with fixed-width columns? */
2537
2538     menu_recent_read_finished();
2539 #ifdef HAVE_LIBPCAP
2540     main_auto_scroll_live_changed(auto_scroll_live);
2541 #endif
2542
2543     switch (user_font_apply()) {
2544         case FA_SUCCESS:
2545             break;
2546         case FA_ZOOMED_TOO_FAR:
2547             /* The zoom level is too big for this font; turn off zooming. */
2548             recent.gui_zoom_level = 0;
2549             break;
2550         case FA_FONT_NOT_AVAILABLE:
2551             /* XXX - did we successfully load the un-zoomed version earlier?
2552              If so, this *probably* means the font is available, but not at
2553              this particular zoom level, but perhaps some other failure
2554              occurred; I'm not sure you can determine which is the case,
2555              however. */
2556             /* turn off zooming - zoom level is unavailable */
2557         default:
2558             /* in any other case than FA_SUCCESS, turn off zooming */
2559             recent.gui_zoom_level = 0;
2560             /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2561             break;
2562     }
2563
2564     dnd_init(top_level);
2565
2566     if (!color_filters_init(&err_msg, color_filter_add_cb)) {
2567         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
2568         g_free(err_msg);
2569     }
2570 #ifdef HAVE_LIBPCAP
2571     capture_filter_init();
2572 #endif
2573
2574     /* the window can be sized only, if it's not already shown, so do it now! */
2575     main_load_window_geometry(top_level);
2576
2577     g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2578
2579     /* this is to keep tap extensions updating once every 3 seconds */
2580     tap_update_timer_id = g_timeout_add(global_commandline_info.prefs_p->tap_update_interval, tap_update_cb, NULL);
2581
2582     /* If we were given the name of a capture file, read it in now;
2583      we defer it until now, so that, if we can't open it, and pop
2584      up an alert box, the alert box is more likely to come up on
2585      top of the main window - but before the preference-file-error
2586      alert box, so, if we get one of those, it's more likely to come
2587      up on top of us. */
2588     if (global_commandline_info.cf_name) {
2589         show_main_window(TRUE);
2590         check_and_warn_user_startup(global_commandline_info.cf_name);
2591         if (global_commandline_info.rfilter != NULL) {
2592             if (!dfilter_compile(global_commandline_info.rfilter, &rfcode, &err_msg)) {
2593                 bad_dfilter_alert_box(top_level, global_commandline_info.rfilter, err_msg);
2594                 g_free(err_msg);
2595                 rfilter_parse_failed = TRUE;
2596             }
2597         }
2598         if (ex_opt_count("read_format") > 0) {
2599             in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
2600         }
2601         if (!rfilter_parse_failed) {
2602             if (cf_open(&cfile, global_commandline_info.cf_name, in_file_type, FALSE, &err) == CF_OK) {
2603                 /* "cf_open()" succeeded, so it closed the previous
2604                  capture file, and thus destroyed any previous read filter
2605                  attached to "cf". */
2606
2607                 cfile.rfcode = rfcode;
2608                 /* Open stat windows; we do so after creating the main window,
2609                    to avoid GTK warnings, and after successfully opening the
2610                    capture file, so we know we have something to compute stats
2611                    on, and after registering all dissectors, so that MATE will
2612                    have registered its field array and we can have a tap filter
2613                    with one of MATE's late-registered fields as part of the
2614                    filter. */
2615                 start_requested_stats();
2616
2617                 /* Read the capture file. */
2618                 switch (cf_read(&cfile, FALSE)) {
2619
2620                     case CF_READ_OK:
2621                     case CF_READ_ERROR:
2622                         /* Just because we got an error, that doesn't mean we were unable
2623                            to read any of the file; we handle what we could get from the
2624                            file. */
2625                         /* if the user told us to jump to a specific packet, do it now */
2626                         if(global_commandline_info.go_to_packet != 0) {
2627                             /* Jump to the specified frame number, kept for backward
2628                                compatibility. */
2629                             cf_goto_frame(&cfile, global_commandline_info.go_to_packet);
2630                         } else if (global_commandline_info.jfilter != NULL) {
2631                             /* try to compile given filter */
2632                             if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) {
2633                                 bad_dfilter_alert_box(top_level, global_commandline_info.jfilter, err_msg);
2634                                 g_free(err_msg);
2635                             } else {
2636                             /* Filter ok, jump to the first packet matching the filter
2637                                conditions. Default search direction is forward, but if
2638                                option d was given, search backwards */
2639                             cf_find_packet_dfilter(&cfile, jump_to_filter, global_commandline_info.jump_backwards);
2640                             }
2641                         }
2642                         break;
2643
2644                     case CF_READ_ABORTED:
2645                         /* Exit now. */
2646                         exit(0);
2647                         break;
2648                 }
2649
2650                 /* If the filename is not the absolute path, prepend the current dir. This happens
2651                    when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
2652                 if (!g_path_is_absolute(global_commandline_info.cf_name)) {
2653                     char *old_cf_name = global_commandline_info.cf_name;
2654                     char *pwd = g_get_current_dir();
2655                     global_commandline_info.cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, global_commandline_info.cf_name);
2656                     g_free(old_cf_name);
2657                     g_free(pwd);
2658                 }
2659
2660                 /* Save the name of the containing directory specified in the
2661                    path name, if any; we can write over cf_name, which is a
2662                    good thing, given that "get_dirname()" does write over its
2663                    argument. */
2664                 s = get_dirname(global_commandline_info.cf_name);
2665                 set_last_open_dir(s);
2666                 g_free(global_commandline_info.cf_name);
2667                 global_commandline_info.cf_name = NULL;
2668             } else {
2669                 if (rfcode != NULL)
2670                     dfilter_free(rfcode);
2671                 cfile.rfcode = NULL;
2672                 show_main_window(FALSE);
2673                 /* Don't call check_and_warn_user_startup(): we did it above */
2674                 main_set_for_capture_in_progress(FALSE);
2675                 set_capture_if_dialog_for_capture_in_progress(FALSE);
2676             }
2677         }
2678     } else {
2679 #ifdef HAVE_LIBPCAP
2680         if (global_commandline_info.start_capture) {
2681             if (global_capture_opts.save_file != NULL) {
2682                 /* Save the directory name for future file dialogs. */
2683                 /* (get_dirname overwrites filename) */
2684                 s = g_strdup(global_capture_opts.save_file);
2685                 set_last_open_dir(get_dirname(s));
2686                 g_free(s);
2687             }
2688             /* "-k" was specified; start a capture. */
2689             show_main_window(FALSE);
2690             check_and_warn_user_startup(global_commandline_info.cf_name);
2691
2692             /* If no user interfaces were specified on the command line,
2693                copy the list of selected interfaces to the set of interfaces
2694                to use for this capture. */
2695             if (global_capture_opts.ifaces->len == 0)
2696                 collect_ifaces(&global_capture_opts);
2697             if (capture_start(&global_capture_opts, &global_capture_session, &global_info_data,main_window_update)) {
2698                 /* The capture started.  Open stat windows; we do so after creating
2699                    the main window, to avoid GTK warnings, and after successfully
2700                    opening the capture file, so we know we have something to compute
2701                    stats on, and after registering all dissectors, so that MATE will
2702                    have registered its field array and we can have a tap filter with
2703                    one of MATE's late-registered fields as part of the filter. */
2704                 start_requested_stats();
2705             }
2706         } else {
2707             show_main_window(FALSE);
2708             check_and_warn_user_startup(global_commandline_info.cf_name);
2709             main_set_for_capture_in_progress(FALSE);
2710             set_capture_if_dialog_for_capture_in_progress(FALSE);
2711         }
2712     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
2713         if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
2714             global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
2715         }
2716 #else /* HAVE_LIBPCAP */
2717         show_main_window(FALSE);
2718         check_and_warn_user_startup(global_commandline_info.cf_name);
2719         main_set_for_capture_in_progress(FALSE);
2720         set_capture_if_dialog_for_capture_in_progress(FALSE);
2721 #endif /* HAVE_LIBPCAP */
2722     }
2723
2724     if (global_commandline_info.dfilter) {
2725         GtkWidget *filter_te;
2726         filter_te = gtk_bin_get_child(GTK_BIN(g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY)));
2727         gtk_entry_set_text(GTK_ENTRY(filter_te), global_commandline_info.dfilter);
2728
2729         /* Run the display filter so it goes in effect. */
2730         main_filter_packets(&cfile, global_commandline_info.dfilter, FALSE);
2731     }
2732
2733     profile_store_persconffiles (FALSE);
2734
2735 #ifdef HAVE_GTKOSXAPPLICATION
2736     theApp = (GtkosxApplication *)g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
2737 #ifdef HAVE_GDK_GRESOURCE
2738     gtkosx_application_set_dock_icon_pixbuf(theApp, ws_gdk_pixbuf_new_from_resource("/org/wireshark/image/wsicon64.png"));
2739 #else
2740     gtkosx_application_set_dock_icon_pixbuf(theApp, gdk_pixbuf_new_from_inline(-1, wsicon_64_pb_data, FALSE, NULL));
2741 #endif
2742     gtkosx_application_ready(theApp);
2743 #endif
2744
2745     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2746
2747 #ifdef HAVE_LIBPCAP
2748     gtk_iface_mon_start();
2749 #endif
2750
2751     software_update_init();
2752
2753     /* we'll enter the GTK loop now and hand the control over to GTK ... */
2754     gtk_main();
2755     /* ... back from GTK, we're going down now! */
2756
2757 #ifdef HAVE_LIBPCAP
2758     gtk_iface_mon_stop();
2759 #endif
2760
2761     epan_cleanup();
2762
2763 #ifdef HAVE_EXTCAP
2764     extcap_cleanup();
2765 #endif
2766
2767     AirPDcapDestroyContext(&airpdcap_ctx);
2768
2769 #ifdef HAVE_GTKOSXAPPLICATION
2770     g_object_unref(theApp);
2771 #endif
2772
2773 #ifdef _WIN32
2774     /* hide the (unresponsive) main window, while asking the user to close the console window */
2775     if (G_IS_OBJECT(top_level))
2776         gtk_widget_hide(top_level);
2777
2778     software_update_cleanup();
2779
2780     /* Shutdown windows sockets */
2781     WSACleanup();
2782
2783     /* For some unknown reason, the "atexit()" call in "create_console()"
2784        doesn't arrange that "destroy_console()" be called when we exit,
2785        so we call it here if a console was created. */
2786     destroy_console();
2787 #endif
2788
2789 #ifdef HAVE_GDK_GRESOURCE
2790     main_unregister_resource();
2791 #endif
2792
2793     exit(0);
2794 }
2795
2796 #ifdef _WIN32
2797
2798 /* We build this as a GUI subsystem application on Win32, so
2799    "WinMain()", not "main()", gets called.
2800
2801    Hack shamelessly stolen from the Win32 port of the GIMP. */
2802 #ifdef __GNUC__
2803 #define _stdcall  __attribute__((stdcall))
2804 #endif
2805
2806 int _stdcall
2807 WinMain (struct HINSTANCE__ *hInstance,
2808          struct HINSTANCE__ *hPrevInstance,
2809          char               *lpszCmdLine,
2810          int                 nCmdShow)
2811 {
2812     INITCOMMONCONTROLSEX comm_ctrl;
2813
2814     /*
2815      * Initialize our DLL search path. MUST be called before LoadLibrary
2816      * or g_module_open.
2817      */
2818     ws_init_dll_search_path();
2819
2820     /* Initialize our controls. Required for native Windows file dialogs. */
2821     memset (&comm_ctrl, 0, sizeof(comm_ctrl));
2822     comm_ctrl.dwSize = sizeof(comm_ctrl);
2823     /* Includes the animate, header, hot key, list view, progress bar,
2824      * status bar, tab, tooltip, toolbar, trackbar, tree view, and
2825      * up-down controls
2826      */
2827     comm_ctrl.dwICC = ICC_WIN95_CLASSES;
2828     InitCommonControlsEx(&comm_ctrl);
2829
2830     /* RichEd20.DLL is needed for native file dialog filter entries. */
2831     ws_load_library("riched20.dll");
2832
2833     set_has_console(FALSE);
2834     set_console_wait(FALSE);
2835     return main (__argc, __argv);
2836 }
2837
2838 #endif /* _WIN32 */
2839
2840
2841
2842
2843 /*
2844  * Helper for main_widgets_rearrange()
2845  */
2846 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
2847     gtk_container_remove(GTK_CONTAINER(data), widget);
2848 }
2849
2850 static GtkWidget *main_widget_layout(gint layout_content)
2851 {
2852     switch(layout_content) {
2853     case(layout_pane_content_none):
2854         return NULL;
2855     case(layout_pane_content_plist):
2856         return pkt_scrollw;
2857     case(layout_pane_content_pdetails):
2858         return tv_scrollw;
2859     case(layout_pane_content_pbytes):
2860         return byte_nb_ptr_gbl;
2861     default:
2862         g_assert_not_reached();
2863         return NULL;
2864     }
2865 }
2866
2867 /*
2868  * Rearrange the main window widgets
2869  */
2870 void main_widgets_rearrange(void) {
2871     GtkWidget *first_pane_widget1, *first_pane_widget2;
2872     GtkWidget *second_pane_widget1, *second_pane_widget2;
2873     gboolean split_top_left = FALSE;
2874
2875     /* be a bit faster */
2876     gtk_widget_hide(main_vbox);
2877
2878     /* be sure we don't lose a widget while rearranging */
2879     g_object_ref(G_OBJECT(menubar));
2880     g_object_ref(G_OBJECT(main_tb));
2881     g_object_ref(G_OBJECT(filter_tb));
2882     g_object_ref(G_OBJECT(wireless_tb));
2883     g_object_ref(G_OBJECT(pkt_scrollw));
2884     g_object_ref(G_OBJECT(tv_scrollw));
2885     g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
2886     g_object_ref(G_OBJECT(statusbar));
2887     g_object_ref(G_OBJECT(main_pane_v1));
2888     g_object_ref(G_OBJECT(main_pane_v2));
2889     g_object_ref(G_OBJECT(main_pane_h1));
2890     g_object_ref(G_OBJECT(main_pane_h2));
2891     g_object_ref(G_OBJECT(welcome_pane));
2892
2893     /* empty all containers participating */
2894     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
2895     gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
2896     gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
2897     gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
2898     gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
2899
2900     statusbar_widgets_emptying(statusbar);
2901
2902     /* add the menubar always at the top */
2903     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
2904
2905     /* main toolbar */
2906     gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
2907
2908     /* filter toolbar in toolbar area */
2909     if (!prefs.filter_toolbar_show_in_statusbar) {
2910         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
2911     }
2912
2913     /* airpcap toolbar */
2914     gtk_box_pack_start(GTK_BOX(main_vbox), wireless_tb, FALSE, TRUE, 1);
2915
2916     /* fill the main layout panes */
2917     switch(prefs.gui_layout_type) {
2918     case(layout_type_5):
2919         main_first_pane  = main_pane_v1;
2920         main_second_pane = main_pane_v2;
2921         split_top_left = FALSE;
2922         break;
2923     case(layout_type_2):
2924         main_first_pane  = main_pane_v1;
2925         main_second_pane = main_pane_h1;
2926         split_top_left = FALSE;
2927         break;
2928     case(layout_type_1):
2929         main_first_pane  = main_pane_v1;
2930         main_second_pane = main_pane_h1;
2931         split_top_left = TRUE;
2932         break;
2933     case(layout_type_4):
2934         main_first_pane  = main_pane_h1;
2935         main_second_pane = main_pane_v1;
2936         split_top_left = FALSE;
2937         break;
2938     case(layout_type_3):
2939         main_first_pane  = main_pane_h1;
2940         main_second_pane = main_pane_v1;
2941         split_top_left = TRUE;
2942         break;
2943     case(layout_type_6):
2944         main_first_pane  = main_pane_h1;
2945         main_second_pane = main_pane_h2;
2946         split_top_left = FALSE;
2947         break;
2948     default:
2949         main_first_pane = NULL;
2950         main_second_pane = NULL;
2951         g_assert_not_reached();
2952     }
2953     if (split_top_left) {
2954         first_pane_widget1 = main_second_pane;
2955         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
2956         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
2957         first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
2958     } else {
2959         first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
2960         first_pane_widget2 = main_second_pane;
2961         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
2962         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
2963     }
2964     if (first_pane_widget1 != NULL)
2965         gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
2966     if (first_pane_widget2 != NULL)
2967         gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
2968     if (second_pane_widget1 != NULL)
2969         gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
2970     if (second_pane_widget2 != NULL)
2971         gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
2972
2973     gtk_box_pack_start(GTK_BOX(main_vbox), main_first_pane, TRUE, TRUE, 0);
2974
2975     /* welcome pane */
2976     gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
2977
2978     /* statusbar */
2979     gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
2980
2981     /* filter toolbar in statusbar hbox */
2982     if (prefs.filter_toolbar_show_in_statusbar) {
2983         gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
2984     }
2985
2986     /* statusbar widgets */
2987     statusbar_widgets_pack(statusbar);
2988
2989     /* hide widgets on users recent settings */
2990     main_widgets_show_or_hide();
2991
2992     gtk_widget_show(main_vbox);
2993 }
2994
2995 static void
2996 is_widget_visible(GtkWidget *widget, gpointer data)
2997 {
2998     gboolean *is_visible = ( gboolean *)data;
2999
3000     if (!*is_visible) {
3001         if (gtk_widget_get_visible(widget))
3002             *is_visible = TRUE;
3003     }
3004 }
3005
3006
3007 void
3008 main_widgets_show_or_hide(void)
3009 {
3010     gboolean main_second_pane_show;
3011
3012     if (recent.main_toolbar_show) {
3013         gtk_widget_show(main_tb);
3014     } else {
3015         gtk_widget_hide(main_tb);
3016     }
3017
3018     statusbar_widgets_show_or_hide(statusbar);
3019
3020     if (recent.filter_toolbar_show) {
3021         gtk_widget_show(filter_tb);
3022     } else {
3023         gtk_widget_hide(filter_tb);
3024     }
3025
3026     if (recent.wireless_toolbar_show) {
3027         gtk_widget_show(wireless_tb);
3028     } else {
3029         gtk_widget_hide(wireless_tb);
3030     }
3031
3032     if (recent.packet_list_show && have_capture_file) {
3033         gtk_widget_show(pkt_scrollw);
3034     } else {
3035         gtk_widget_hide(pkt_scrollw);
3036     }
3037
3038     if (recent.tree_view_show && have_capture_file) {
3039         gtk_widget_show(tv_scrollw);
3040     } else {
3041         gtk_widget_hide(tv_scrollw);
3042     }
3043
3044     if (recent.byte_view_show && have_capture_file) {
3045         gtk_widget_show(byte_nb_ptr_gbl);
3046     } else {
3047         gtk_widget_hide(byte_nb_ptr_gbl);
3048     }
3049
3050     if (have_capture_file) {
3051         gtk_widget_show(main_first_pane);
3052     } else {
3053         gtk_widget_hide(main_first_pane);
3054     }
3055
3056     /*
3057      * Is anything in "main_second_pane" visible?
3058      * If so, show it, otherwise hide it.
3059      */
3060     main_second_pane_show = FALSE;
3061     gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3062                           &main_second_pane_show);
3063     if (main_second_pane_show) {
3064         gtk_widget_show(main_second_pane);
3065     } else {
3066         gtk_widget_hide(main_second_pane);
3067     }
3068
3069     if (!have_capture_file) {
3070         if(welcome_pane) {
3071             gtk_widget_show(welcome_pane);
3072         }
3073     } else {
3074         gtk_widget_hide(welcome_pane);
3075     }
3076 }
3077
3078
3079 /* called, when the window state changes (minimized, maximized, ...) */
3080 static gboolean
3081 window_state_event_cb (GtkWidget *widget _U_,
3082                        GdkEvent *event,
3083                        gpointer  data _U_)
3084 {
3085     GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3086
3087     if( (event->type) == (GDK_WINDOW_STATE)) {
3088         if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3089             /* we might have dialogs popped up while we where iconified,
3090                show em now */
3091             display_queued_messages();
3092         }
3093     }
3094     return FALSE;
3095 }
3096
3097
3098
3099 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3100 static gboolean
3101 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3102 {
3103     if (event->keyval == GDK_F8) {
3104         packet_list_next();
3105         return TRUE;
3106     } else if (event->keyval == GDK_F7) {
3107         packet_list_prev();
3108         return TRUE;
3109     } else if (event->state & NO_SHIFT_MOD_MASK) {
3110         return FALSE; /* Skip control, alt, and other modifiers */
3111     /*
3112      * A comment in gdkkeysyms.h says that it's autogenerated from
3113      * freedesktop.org/x.org's keysymdef.h.  Although the GDK docs
3114      * don't explicitly say so, g_ascii_isprint() should work as expected
3115      * for values < 127.
3116      */
3117     } else if (event->keyval < 256 && g_ascii_isprint(event->keyval)) {
3118         /* Forward the keypress on to the display filter entry */
3119         if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3120             gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3121             gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3122         }
3123         return FALSE;
3124     }
3125     return FALSE;
3126 }
3127
3128 static void
3129 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p
3130 #if !defined(HAVE_IGE_MAC_INTEGRATION) && !defined (HAVE_GTKOSXAPPLICATION)
3131                     _U_
3132 #endif
3133                     )
3134 {
3135     GtkAccelGroup *accel;
3136
3137     /* Main window */
3138     top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
3139     set_titlebar_for_capture_file(NULL);
3140
3141     gtk_widget_set_name(top_level, "main window");
3142     g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3143                    NULL);
3144     g_signal_connect(G_OBJECT(top_level), "window_state_event",
3145                          G_CALLBACK(window_state_event_cb), NULL);
3146     g_signal_connect(G_OBJECT(top_level), "key-press-event",
3147                          G_CALLBACK(top_level_key_pressed_cb), NULL );
3148
3149     /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3150     main_vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 1, FALSE);
3151
3152     gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
3153     gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3154     gtk_widget_show(main_vbox);
3155
3156     /* Menu bar */
3157     menubar = main_menu_new(&accel);
3158
3159 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3160     /* Mac OS X native menus are created and displayed by main_menu_new() */
3161     if(!prefs_p->gui_macosx_style) {
3162 #endif
3163     gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3164     gtk_widget_show(menubar);
3165 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3166     } else {
3167     gtk_widget_hide(menubar);
3168     }
3169 #endif
3170
3171     /* Main Toolbar */
3172     main_tb = toolbar_new();
3173     gtk_widget_show (main_tb);
3174
3175     /* Filter toolbar */
3176     filter_tb = filter_toolbar_new();
3177
3178     /* Packet list */
3179     pkt_scrollw = packet_list_create();
3180     gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3181     gtk_widget_show_all(pkt_scrollw);
3182
3183     /* Tree view */
3184     tv_scrollw = proto_tree_view_new(&tree_view_gbl);
3185     gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3186     gtk_widget_show(tv_scrollw);
3187
3188     g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3189                    "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3190     g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3191                    g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3192     gtk_widget_show(tree_view_gbl);
3193
3194     /* Byte view. */
3195     byte_nb_ptr_gbl = byte_view_new();
3196     gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3197     gtk_widget_show(byte_nb_ptr_gbl);
3198
3199     g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3200                    g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3201
3202     /* Panes for the packet list, tree, and byte view */
3203     main_pane_v1 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3204     gtk_widget_show(main_pane_v1);
3205     main_pane_v2 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3206     gtk_widget_show(main_pane_v2);
3207     main_pane_h1 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3208     gtk_widget_show(main_pane_h1);
3209     main_pane_h2 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3210     gtk_widget_show(main_pane_h2);
3211 #ifdef HAVE_AIRPCAP
3212     wireless_tb = airpcap_toolbar_new();
3213 #else
3214     wireless_tb = ws80211_toolbar_new();
3215 #endif
3216     gtk_widget_show(wireless_tb);
3217
3218     /* status bar */
3219     statusbar = statusbar_new();
3220     gtk_widget_show(statusbar);
3221
3222     /* Pane for the welcome screen */
3223     welcome_pane = welcome_new();
3224     gtk_widget_show(welcome_pane);
3225 }
3226
3227 static void
3228 show_main_window(gboolean doing_work)
3229 {
3230     main_set_for_capture_file(doing_work);
3231
3232     /*** we have finished all init things, show the main window ***/
3233     gtk_widget_show(top_level);
3234
3235     /* the window can be maximized only, if it's visible, so do it after show! */
3236     main_load_window_geometry(top_level);
3237
3238     /* process all pending GUI events before continue */
3239     while (gtk_events_pending()) gtk_main_iteration();
3240
3241     /* Pop up any queued-up alert boxes. */
3242     display_queued_messages();
3243
3244     /* Move the main window to the front, in case it isn't already there */
3245     gdk_window_raise(gtk_widget_get_window(top_level));
3246
3247 #ifdef HAVE_AIRPCAP
3248     airpcap_toolbar_show(wireless_tb);
3249 #endif /* HAVE_AIRPCAP */
3250 }
3251
3252 static void copy_global_profile (const gchar *profile_name)
3253 {
3254     char  *pf_dir_path, *pf_dir_path2, *pf_filename;
3255
3256     if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
3257         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3258             "Can't create directory\n\"%s\":\n%s.",
3259             pf_dir_path, g_strerror(errno));
3260
3261         g_free(pf_dir_path);
3262     }
3263
3264     if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
3265             &pf_dir_path, &pf_dir_path2) == -1) {
3266         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3267             "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
3268             pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
3269
3270         g_free(pf_filename);
3271         g_free(pf_dir_path);
3272         g_free(pf_dir_path2);
3273     }
3274 }
3275
3276 /* Change configuration profile */
3277 void change_configuration_profile (const gchar *profile_name)
3278 {
3279     char  *gdp_path, *dp_path;
3280     char  *rf_path;
3281     int    rf_open_errno;
3282     gchar* err_msg = NULL;
3283
3284     /* First check if profile exists */
3285     if (!profile_exists(profile_name, FALSE)) {
3286         if (profile_exists(profile_name, TRUE)) {
3287            /* Copy from global profile */
3288             copy_global_profile (profile_name);
3289         } else {
3290             /* No personal and no global profile exists */
3291             return;
3292         }
3293     }
3294
3295     /* Then check if changing to another profile */
3296     if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
3297         return;
3298     }
3299
3300     /* Get the current geometry, before writing it to disk */
3301     main_save_window_geometry(top_level);
3302
3303     if (profile_exists(get_profile_name(), FALSE)) {
3304         /* Write recent file for profile we are leaving, if it still exists */
3305         write_profile_recent();
3306     }
3307
3308     /* Set profile name and update the status bar */
3309     set_profile_name (profile_name);
3310     profile_bar_update ();
3311
3312     /* Reset current preferences and apply the new */
3313     prefs_reset();
3314     menu_prefs_reset();
3315
3316     (void) read_configuration_files (&gdp_path, &dp_path);
3317
3318     if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
3319         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3320             "Could not open common recent file\n\"%s\": %s.",
3321             rf_path, g_strerror(rf_open_errno));
3322         g_free(rf_path);
3323     }
3324     if (recent.gui_fileopen_remembered_dir &&
3325         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
3326         set_last_open_dir(recent.gui_fileopen_remembered_dir);
3327     }
3328     timestamp_set_type (recent.gui_time_format);
3329     timestamp_set_seconds_type (recent.gui_seconds_format);
3330     packet_list_enable_color(recent.packet_list_colorize);
3331
3332     prefs_to_capture_opts();
3333     prefs_apply_all();
3334 #ifdef HAVE_LIBPCAP
3335     update_local_interfaces();
3336 #endif
3337     macros_post_update();
3338
3339     /* Update window view and redraw the toolbar */
3340     main_titlebar_update();
3341     filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE);
3342     toolbar_redraw_all();
3343
3344     /* Enable all protocols and disable from the disabled list */
3345     proto_enable_all();
3346     if (gdp_path == NULL && dp_path == NULL) {
3347         set_disabled_protos_list();
3348         set_disabled_heur_dissector_list();
3349     }
3350
3351     /* Reload color filters */
3352     if (!color_filters_reload(&err_msg, color_filter_add_cb)) {
3353         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
3354         g_free(err_msg);
3355     }
3356
3357     /* Reload list of interfaces on welcome page */
3358     welcome_if_panel_reload();
3359
3360     /* Recreate the packet list according to new preferences */
3361     packet_list_recreate ();
3362     cfile.columns_changed = FALSE; /* Reset value */
3363     user_font_apply();
3364
3365     /* Update menus with new recent values */
3366     menu_recent_read_finished();
3367
3368     /* Reload pane geometry, must be done after recreating the list */
3369     main_pane_load_window_geometry();
3370 }
3371
3372 void
3373 main_fields_changed (void)
3374 {
3375     gchar* err_msg = NULL;
3376
3377     /* Reload color filters */
3378     if (!color_filters_reload(&err_msg, color_filter_add_cb)) {
3379         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
3380         g_free(err_msg);
3381     }
3382
3383     /* Syntax check filter */
3384     filter_te_syntax_check_cb(main_display_filter_widget, NULL);
3385     if (cfile.dfilter) {
3386         /* Check if filter is still valid */
3387         dfilter_t *dfp = NULL;
3388         if (!dfilter_compile(cfile.dfilter, &dfp, NULL)) {
3389             /* Not valid.  Enable 'Apply' button and remove dfilter. */
3390             g_signal_emit_by_name(G_OBJECT(main_display_filter_widget), "changed");
3391             g_free(cfile.dfilter);
3392             cfile.dfilter = NULL;
3393         }
3394         dfilter_free(dfp);
3395     }
3396
3397     if (have_custom_cols(&cfile.cinfo)) {
3398         /* Recreate packet list according to new/changed/deleted fields */
3399         packet_list_recreate();
3400     } else if (cfile.state != FILE_CLOSED) {
3401         /* Redissect packets if we have any */
3402         redissect_packets();
3403     }
3404     destroy_packet_wins(); /* TODO: close windows until we can recreate */
3405
3406     proto_free_deregistered_fields();
3407 }
3408
3409 /** redissect packets and update UI */
3410 void redissect_packets(void)
3411 {
3412     cf_redissect_packets(&cfile);
3413     status_expert_update();
3414 }
3415
3416 /*
3417  * Editor modelines
3418  *
3419  * Local Variables:
3420  * c-basic-offset: 4
3421  * tab-width: 8
3422  * indent-tabs-mode: nil
3423  * End:
3424  *
3425  * ex: set shiftwidth=4 tabstop=8 expandtab:
3426  * :indentSize=4:tabSize=8:noTabs=true:
3427  */