From Davide Schiera and Giorgio Tino: Add initial WPA/WPA2 decryption
[obnox/wireshark/wip.git] / gtk / main.c
1 /* main.c
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10  *                              needed by dissect routines
11  * Jeff Foster,    2001/03/12,  added support tabbed hex display windowss
12  *
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <gtk/gtk.h>
34 #include <gdk/gdkkeysyms.h>
35
36 #include <string.h>
37 #include <ctype.h>
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #ifdef NEED_STRERROR_H
44 #include "strerror.h"
45 #endif
46
47 #ifdef NEED_GETOPT_H
48 #include "getopt.h"
49 #endif
50
51 #ifdef _WIN32 /* Needed for console I/O */
52 #include <fcntl.h>
53 #include <conio.h>
54 #endif
55
56 #ifdef HAVE_LIBPORTAUDIO
57 #include <portaudio.h>
58 #endif /* HAVE_LIBPORTAUDIO */
59
60 #include <epan/epan.h>
61 #include <epan/filesystem.h>
62 #include <epan/privileges.h>
63 #include <epan/epan_dissect.h>
64 #include <epan/timestamp.h>
65 #include <epan/packet.h>
66 #include <epan/plugins.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/strutil.h>
69 #include <epan/addr_resolv.h>
70 #include <epan/emem.h>
71 #include <epan/ex-opt.h>
72 #include <epan/funnel.h>
73 #include <epan/expert.h>
74
75 /* general (not GTK specific) */
76 #include "file.h"
77 #include "summary.h"
78 #include "filters.h"
79 #include "disabled_protos.h"
80 #include <epan/prefs.h>
81 #include "filter_dlg.h"
82 #include "layout_prefs.h"
83 #include "color.h"
84 #include "color_filters.h"
85 #include "print.h"
86 #include "simple_dialog.h"
87 #include "register.h"
88 #include <epan/prefs-int.h>
89 #include "ringbuffer.h"
90 #include "../ui_util.h"
91 #include <epan/tap.h>
92 #include <epan/stat_cmd_args.h>
93 #include "util.h"
94 #include "clopts_common.h"
95 #include "cmdarg_err.h"
96 #include "version_info.h"
97 #include "merge.h"
98 #include "u3.h"
99
100
101 #ifdef HAVE_LIBPCAP
102 #include "capture-pcap-util.h"
103 #include "capture.h"
104 #include "capture_sync.h"
105 #endif
106
107 #ifdef _WIN32
108 #include "capture-wpcap.h"
109 #include "capture_wpcap_packet.h"
110 #include <tchar.h> /* Needed for Unicode */
111 #if GTK_MAJOR_VERSION >= 2
112 #include <commctrl.h>
113 #endif /* GTK_MAJOR_VERSION >= 2 */
114 #endif /* _WIN32 */
115
116 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
117 #include "ethclist.h"
118 #endif
119
120 /* GTK related */
121 #include "statusbar.h"
122 #include "alert_box.h"
123 #if 0
124 #include "dlg_utils.h"
125 #endif
126 #include "file_dlg.h"
127 #include "gtkglobals.h"
128 #include "colors.h"
129 #include "gui_utils.h"
130 #include "compat_macros.h"
131
132 #include "main.h"
133 #include "menu.h"
134 #include "../main_window.h"
135 #include "../menu.h"
136 #include "capture_file_dlg.h"
137 #include <epan/column.h>
138 #include "proto_draw.h"
139 #include "keys.h"
140 #include "packet_win.h"
141 #include "toolbar.h"
142 #include "find_dlg.h"
143 #include "packet_list.h"
144 #include "recent.h"
145 #include "follow_dlg.h"
146 #include "font_utils.h"
147 #include "about_dlg.h"
148 #include "help_dlg.h"
149 #include "decode_as_dlg.h"
150 #include "webbrowser.h"
151 #include "capture_dlg.h"
152 #include "capture_ui_utils.h"
153 #include "log.h"
154 #include "../epan/emem.h"
155 #include "file_util.h"
156 #include "../image/wsicon16.xpm"
157 #include "../image/wsicon32.xpm"
158 #include "../image/wsicon48.xpm"
159 #include "../image/wsicon64.xpm"
160 #include "../image/wsiconcap16.xpm"
161 #include "../image/wsiconcap32.xpm"
162 #include "../image/wsiconcap48.xpm"
163
164 #ifdef HAVE_AIRPCAP
165 #include <airpcap.h>
166 #include "airpcap_loader.h"
167 #include "airpcap_dlg.h"
168 #include "airpcap_gui_utils.h"
169
170 #include "./gtk/toolbar.h"
171
172 #include "./image/toolbar/wep_closed_24.xpm"
173 #endif
174
175 #ifdef  HAVE_AIRPDCAP
176 /*      Davide Schiera (2006-11-22): including AirPDcap project                                                 */
177 #include "..\airpdcap\airpdcap_ws.h"
178 /* Davide Schiera (2006-11-22) ----------------------------------------------   */
179 #endif
180
181 /*
182  * Files under personal and global preferences directories in which
183  * GTK settings for Wireshark are stored.
184  */
185 #define RC_FILE "gtkrc"
186
187 #ifdef HAVE_LIBPCAP
188 #define DEF_READY_MESSAGE " Ready to load or capture"
189 #else
190 #define DEF_READY_MESSAGE " Ready to load file"
191 #endif
192
193 capture_file cfile;
194 GtkWidget   *main_display_filter_widget=NULL;
195 GtkWidget   *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
196 static GtkWidget   *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
197 static GtkWidget   *main_first_pane, *main_second_pane;
198 static GtkWidget   *status_pane;
199 static GtkWidget   *menubar, *main_vbox, *main_tb, *pkt_scrollw, *stat_hbox, *filter_tb;
200
201 #ifdef HAVE_AIRPCAP
202 GtkWidget *airpcap_tb;
203 static GtkWidget *driver_warning_dialog;
204 static int    airpcap_dll_ret_val = -1;
205 #endif
206
207 static GtkWidget        *info_bar;
208 static GtkWidget    *packets_bar = NULL;
209 static GtkWidget    *welcome_pane;
210 static guint            main_ctx, file_ctx, help_ctx;
211 static guint        packets_ctx;
212 static gchar        *packets_str = NULL;
213 GString *comp_info_str, *runtime_info_str;
214 gboolean have_capture_file = FALSE; /* XXX - is there an aquivalent in cfile? */
215
216 #ifdef _WIN32
217 static gboolean has_console;    /* TRUE if app has console */
218 static void destroy_console(void);
219 #endif
220 static void console_log_handler(const char *log_domain,
221     GLogLevelFlags log_level, const char *message, gpointer user_data);
222
223 #ifdef HAVE_LIBPCAP
224 static gboolean list_link_layer_types;
225 capture_options global_capture_opts;
226 capture_options *capture_opts = &global_capture_opts;
227 #endif
228
229 gboolean block_toolbar_signals = FALSE;
230
231 static void create_main_window(gint, gint, gint, e_prefs*);
232 static void show_main_window(gboolean);
233 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
234 static void main_save_window_geometry(GtkWidget *widget);
235
236 #define E_DFILTER_CM_KEY          "display_filter_combo"
237 #define E_DFILTER_FL_KEY          "display_filter_list"
238
239 /* Match selected byte pattern */
240 static void
241 match_selected_cb_do(gpointer data, int action, gchar *text)
242 {
243     GtkWidget           *filter_te;
244     char                *cur_filter, *new_filter;
245
246     if (!text)
247         return;
248     g_assert(data);
249     filter_te = OBJECT_GET_DATA(data, E_DFILTER_TE_KEY);
250     g_assert(filter_te);
251
252     cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
253
254     switch (action&MATCH_SELECTED_MASK) {
255
256     case MATCH_SELECTED_REPLACE:
257         new_filter = g_strdup(text);
258         break;
259
260     case MATCH_SELECTED_AND:
261         if ((!cur_filter) || (0 == strlen(cur_filter)))
262             new_filter = g_strdup(text);
263         else
264             new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
265         break;
266
267     case MATCH_SELECTED_OR:
268         if ((!cur_filter) || (0 == strlen(cur_filter)))
269             new_filter = g_strdup(text);
270         else
271             new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
272         break;
273
274     case MATCH_SELECTED_NOT:
275         new_filter = g_strconcat("!(", text, ")", NULL);
276         break;
277
278     case MATCH_SELECTED_AND_NOT:
279         if ((!cur_filter) || (0 == strlen(cur_filter)))
280             new_filter = g_strconcat("!(", text, ")", NULL);
281         else
282             new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
283         break;
284
285     case MATCH_SELECTED_OR_NOT:
286         if ((!cur_filter) || (0 == strlen(cur_filter)))
287             new_filter = g_strconcat("!(", text, ")", NULL);
288         else
289             new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
290         break;
291
292     default:
293         g_assert_not_reached();
294         new_filter = NULL;
295         break;
296     }
297
298     /* Free up the copy we got of the old filter text. */
299     g_free(cur_filter);
300
301     /* create a new one and set the display filter entry accordingly */
302     gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
303
304     /* Run the display filter so it goes in effect. */
305     if (action&MATCH_SELECTED_APPLY_NOW)
306         main_filter_packets(&cfile, new_filter, FALSE);
307
308     /* Free up the new filter text. */
309     g_free(new_filter);
310 }
311
312 void
313 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
314 {
315     char *filter;
316
317     if (cfile.finfo_selected) {
318         filter = proto_construct_match_selected_string(cfile.finfo_selected,
319                                                        cfile.edt);
320         if (filter != NULL)
321             match_selected_cb_do((data ? data : w), action, filter);
322     }
323 }
324
325
326 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
327 {
328     gchar *selected_proto_url;
329     gchar *proto_abbrev = data;
330
331
332     switch(btn) {
333     case(ESD_BTN_OK):
334         if (cfile.finfo_selected) {
335             /* open wiki page using the protocol abbreviation */
336             selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
337             browser_open_url(selected_proto_url);
338             g_free(selected_proto_url);
339         }
340         break;
341     case(ESD_BTN_CANCEL):
342         break;
343     default:
344         g_assert_not_reached();
345     }
346 }
347
348
349 void
350 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
351 {
352     int field_id;
353     const gchar *proto_abbrev;
354     gpointer  dialog;
355
356
357     if (cfile.finfo_selected) {
358         /* convert selected field to protocol abbreviation */
359         /* XXX - could this conversion be simplified? */
360         field_id = cfile.finfo_selected->hfinfo->id;
361         /* if the selected field isn't a protocol, get it's parent */
362         if(!proto_registrar_is_protocol(field_id)) {
363             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
364         }
365
366         proto_abbrev = proto_registrar_get_abbrev(field_id);
367
368         /* ask the user if the wiki page really should be opened */
369         dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
370                     PRIMARY_TEXT_START "Open Wireshark Wiki page of protocol \"%s\"?" PRIMARY_TEXT_END "\n"
371                     "\n"
372                     "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
373                     "\n"
374                     "The Wireshark Wiki is a collaborative approach to provide information\n"
375                     "about Wireshark in several ways (not limited to protocol specifics).\n"
376                     "\n"
377                     "This Wiki is new, so the page of the selected protocol\n"
378                     "may not exist and/or may not contain valuable information.\n"
379                     "\n"
380                     "As everyone can edit the Wiki and add new content (or extend existing),\n"
381                     "you are encouraged to add information if you can.\n"
382                     "\n"
383                     "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
384                     "\n"
385                     "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
386                     "which will save you a lot of editing and will give a consistent look over the pages.",
387                     proto_abbrev, proto_abbrev);
388         simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer) proto_abbrev);
389     }
390 }
391
392
393 void
394 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
395 {
396     int field_id;
397     const gchar *proto_abbrev;
398     gchar *selected_proto_url;
399
400
401     if (cfile.finfo_selected) {
402         /* convert selected field to protocol abbreviation */
403         /* XXX - could this conversion be simplified? */
404         field_id = cfile.finfo_selected->hfinfo->id;
405         /* if the selected field isn't a protocol, get it's parent */
406         if(!proto_registrar_is_protocol(field_id)) {
407             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
408         }
409
410         proto_abbrev = proto_registrar_get_abbrev(field_id);
411
412         /* open reference page using the protocol abbreviation */
413         selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s.html", proto_abbrev[0], proto_abbrev);
414         browser_open_url(selected_proto_url);
415         g_free(selected_proto_url);
416     }
417 }
418
419 static gchar *
420 get_text_from_packet_list(gpointer data)
421 {
422     gint        row = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_ROW_KEY));
423     gint        column = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_COL_KEY));
424     frame_data *fdata = (frame_data *)packet_list_get_row_data(row);
425     epan_dissect_t *edt;
426     gchar      *buf=NULL;
427     int         len;
428     int         err;
429     gchar       *err_info;
430
431     if (fdata != NULL) {
432         if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
433                        cfile.pd, fdata->cap_len, &err, &err_info)) {
434             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
435                           cf_read_error_message(err, err_info), cfile.filename);
436             return NULL;
437         }
438
439         edt = epan_dissect_new(FALSE, FALSE);
440         epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
441                          &cfile.cinfo);
442         epan_dissect_fill_in_columns(edt);
443
444         if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
445             strlen(cfile.cinfo.col_expr_val[column]) != 0) {
446             len = strlen(cfile.cinfo.col_expr[column]) +
447                   strlen(cfile.cinfo.col_expr_val[column]) + 5;
448             buf = ep_alloc0(len);
449             g_snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
450                      cfile.cinfo.col_expr_val[column]);
451         }
452
453         epan_dissect_free(edt);
454     }
455
456     return buf;
457 }
458
459 void
460 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
461 {
462     match_selected_cb_do(data,
463         action,
464         get_text_from_packet_list(data));
465 }
466
467 /* This function allows users to right click in the details window and copy the text
468  * information to the operating systems clipboard.
469  *
470  * We first check to see if a string representation is setup in the tree and then
471  * read the string. If not available then we try to grab the value. If all else
472  * fails we display a message to the user to indicate the copy could not be completed.
473  */
474 void
475 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_)
476 {
477         GString *gtk_text_str = g_string_new("");
478     char labelstring[256];
479     char *stringpointer = labelstring;
480
481     if (cfile.finfo_selected->rep->representation != 0) {
482         g_string_sprintfa(gtk_text_str, "%s", cfile.finfo_selected->rep->representation);   /* Get the represented data */
483     }
484     if (gtk_text_str->len == 0) {                                                           /* If no representation then... */
485         proto_item_fill_label(cfile.finfo_selected, stringpointer);                         /* Try to read the value */
486         g_string_sprintfa(gtk_text_str, "%s", stringpointer);
487     }
488     if (gtk_text_str->len == 0) {                                                           /* Could not get item so display error msg */
489         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
490     }
491     else
492     {
493         copy_to_clipboard(gtk_text_str);                     /* Copy string to clipboard */
494     }
495     g_string_free(gtk_text_str, TRUE);                       /* Free the memory */
496 }
497
498
499 /* XXX: use a preference for this setting! */
500 static guint dfilter_combo_max_recent = 10;
501
502 /* add a display filter to the combo box */
503 /* Note: a new filter string will replace an old identical one */
504 static gboolean
505 dfilter_combo_add(GtkWidget *filter_cm, char *s) {
506   GList     *li;
507   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
508
509
510   /* GtkCombos don't let us get at their list contents easily, so we maintain
511      our own filter list, and feed it to gtk_combo_set_popdown_strings when
512      a new filter is added. */
513     li = g_list_first(dfilter_list);
514     while (li) {
515         /* If the filter is already in the list, remove the old one and
516                  * append the new one at the latest position (at g_list_append() below) */
517                 if (li->data && strcmp(s, li->data) == 0) {
518           dfilter_list = g_list_remove(dfilter_list, li->data);
519                   break;
520                 }
521       li = li->next;
522     }
523
524     dfilter_list = g_list_append(dfilter_list, s);
525     OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
526     gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), dfilter_list);
527     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), g_list_last(dfilter_list)->data);
528
529     return TRUE;
530 }
531
532
533 /* write all non empty display filters (until maximum count)
534  * of the combo box GList to the user's recent file */
535 void
536 dfilter_recent_combo_write_all(FILE *rf) {
537   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
538   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
539   GList     *li;
540   guint      max_count = 0;
541
542
543   /* write all non empty display filter strings to the recent file (until max count) */
544   li = g_list_first(dfilter_list);
545   while ( li && (max_count++ <= dfilter_combo_max_recent) ) {
546     if (strlen(li->data)) {
547       fprintf (rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", (char *)li->data);
548     }
549     li = li->next;
550   }
551 }
552
553 /* empty the combobox entry field */
554 void
555 dfilter_combo_add_empty(void) {
556   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
557
558   gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), "");
559 }
560
561
562 /* add a display filter coming from the user's recent file to the dfilter combo box */
563 gboolean
564 dfilter_combo_add_recent(gchar *s) {
565   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
566   char      *dup;
567
568   dup = g_strdup(s);
569   if (!dfilter_combo_add(filter_cm, dup)) {
570     g_free(dup);
571     return FALSE;
572   }
573
574   return TRUE;
575 }
576
577
578 /* call cf_filter_packets() and add this filter string to the recent filter list */
579 gboolean
580 main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
581 {
582   GtkCombo  *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
583   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
584   GList     *li;
585   gboolean   add_filter = TRUE;
586   gboolean   free_filter = TRUE;
587   char      *s;
588   cf_status_t cf_status;
589
590   /* we'll crash later on if dftext is NULL */
591   g_assert(dftext != NULL);
592
593   s = g_strdup(dftext);
594
595   /* GtkCombos don't let us get at their list contents easily, so we maintain
596      our own filter list, and feed it to gtk_combo_set_popdown_strings when
597      a new filter is added. */
598   cf_status = cf_filter_packets(cf, s, force);
599   if (cf_status == CF_OK) {
600     li = g_list_first(dfilter_list);
601     while (li) {
602       if (li->data && strcmp(s, li->data) == 0)
603         add_filter = FALSE;
604       li = li->next;
605     }
606
607     if (add_filter) {
608       /* trim list size first */
609       while (g_list_length(dfilter_list) >= dfilter_combo_max_recent) {
610         dfilter_list = g_list_remove(dfilter_list, g_list_first(dfilter_list)->data);
611       }
612
613       free_filter = FALSE;
614       dfilter_list = g_list_append(dfilter_list, s);
615       OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
616       gtk_combo_set_popdown_strings(filter_cm, dfilter_list);
617       gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(dfilter_list)->data);
618     }
619   }
620   if (free_filter)
621     g_free(s);
622
623   return (cf_status == CF_OK);
624 }
625
626
627 /* Run the current display filter on the current packet set, and
628    redisplay. */
629 static void
630 filter_activate_cb(GtkWidget *w _U_, gpointer data)
631 {
632   const char *s;
633
634   s = gtk_entry_get_text(GTK_ENTRY(data));
635
636   main_filter_packets(&cfile, s, FALSE);
637 }
638
639 /* redisplay with no display filter */
640 static void
641 filter_reset_cb(GtkWidget *w, gpointer data _U_)
642 {
643   GtkWidget *filter_te = NULL;
644
645   if ((filter_te = OBJECT_GET_DATA(w, E_DFILTER_TE_KEY))) {
646     gtk_entry_set_text(GTK_ENTRY(filter_te), "");
647   }
648   main_filter_packets(&cfile, "", FALSE);
649 }
650
651 /* mark as reference time frame */
652 static void
653 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
654   if (row == -1)
655     return;
656   if (set) {
657     frame->flags.ref_time=1;
658   } else {
659     frame->flags.ref_time=0;
660   }
661   cf_reftime_packets(&cfile);
662 }
663
664
665 GtkWidget *reftime_dialog = NULL;
666
667 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
668 {
669     switch(btn) {
670     case(ESD_BTN_YES):
671         timestamp_set_type(TS_RELATIVE);
672         recent.gui_time_format  = TS_RELATIVE;
673         cf_change_time_formats(&cfile);
674         break;
675     case(ESD_BTN_NO):
676         break;
677     default:
678         g_assert_not_reached();
679     }
680
681     if (cfile.current_frame) {
682       /* XXX hum, should better have a "cfile->current_row" here ... */
683       set_frame_reftime(!cfile.current_frame->flags.ref_time,
684                      cfile.current_frame,
685                      packet_list_find_row_from_data(cfile.current_frame));
686     }
687 }
688
689
690 void
691 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
692 {
693
694   switch(action){
695   case REFTIME_TOGGLE:
696     if (cfile.current_frame) {
697         if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
698             reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
699                 PRIMARY_TEXT_START "Switch to the appropriate Time Display Format?" PRIMARY_TEXT_END "\n\n"
700                 "Time References don't work well with the currently selected Time Display Format.\n\n"
701                 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?");
702             simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
703         } else {
704             /* XXX hum, should better have a "cfile->current_row" here ... */
705             set_frame_reftime(!cfile.current_frame->flags.ref_time,
706                               cfile.current_frame,
707                               packet_list_find_row_from_data(cfile.current_frame));
708         }
709     }
710     break;
711   case REFTIME_FIND_NEXT:
712     find_previous_next_frame_with_filter("frame.ref_time", FALSE);
713     break;
714   case REFTIME_FIND_PREV:
715     find_previous_next_frame_with_filter("frame.ref_time", TRUE);
716     break;
717   }
718 }
719
720 void
721 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
722 {
723     find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
724 }
725
726 void
727 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
728 {
729     find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
730 }
731
732 #if GTK_MAJOR_VERSION < 2
733 static void
734 tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_,
735                         gpointer user_data _U_)
736 #else
737 static void
738 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
739 #endif
740 {
741     field_info   *finfo;
742     gchar        *help_str = NULL;
743     gchar         len_str[2+10+1+5+1]; /* ", {N} bytes\0",
744                                           N < 4294967296 */
745     gboolean      has_blurb = FALSE;
746     guint         length = 0, byte_len;
747     GtkWidget    *byte_view;
748     const guint8 *byte_data;
749 #if GTK_MAJOR_VERSION >= 2
750     GtkTreeModel *model;
751     GtkTreeIter   iter;
752 #endif
753
754 #if GTK_MAJOR_VERSION >= 2
755     /* if nothing is selected */
756     if (!gtk_tree_selection_get_selected(sel, &model, &iter))
757     {
758         /*
759          * Which byte view is displaying the current protocol tree
760          * row's data?
761          */
762         byte_view = get_notebook_bv_ptr(byte_nb_ptr);
763         if (byte_view == NULL)
764             return;     /* none */
765
766         byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
767         if (byte_data == NULL)
768             return;     /* none */
769
770         cf_unselect_field(&cfile);
771         packet_hex_print(byte_view, byte_data,
772                          cfile.current_frame, NULL, byte_len);
773         return;
774     }
775     gtk_tree_model_get(model, &iter, 1, &finfo, -1);
776 #else
777     g_assert(node);
778     finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
779 #endif
780     if (!finfo) return;
781
782     set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
783
784     byte_view = get_notebook_bv_ptr(byte_nb_ptr);
785     byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
786     g_assert(byte_data != NULL);
787
788     cfile.finfo_selected = finfo;
789     set_menus_for_selected_tree_row(&cfile);
790
791     if (finfo->hfinfo) {
792         if (finfo->hfinfo->blurb != NULL &&
793             finfo->hfinfo->blurb[0] != '\0') {
794             has_blurb = TRUE;
795             length = strlen(finfo->hfinfo->blurb);
796         } else {
797             length = strlen(finfo->hfinfo->name);
798         }
799         if (finfo->length == 0) {
800             len_str[0] = '\0';
801         } else if (finfo->length == 1) {
802             strcpy (len_str, ", 1 byte");
803         } else {
804             g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo->length);
805         }
806         statusbar_pop_field_msg();      /* get rid of current help msg */
807         if (length) {
808             help_str = g_strdup_printf("%s (%s)%s",
809                     (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
810                     finfo->hfinfo->abbrev, len_str);
811             statusbar_push_field_msg(help_str);
812             g_free(help_str);
813         } else {
814             /*
815              * Don't show anything if the field name is zero-length;
816              * the pseudo-field for "proto_tree_add_text()" is such
817              * a field, and we don't want "Text (text)" showing up
818              * on the status line if you've selected such a field.
819              *
820              * XXX - there are zero-length fields for which we *do*
821              * want to show the field name.
822              *
823              * XXX - perhaps the name and abbrev field should be null
824              * pointers rather than null strings for that pseudo-field,
825              * but we'd have to add checks for null pointers in some
826              * places if we did that.
827              *
828              * Or perhaps protocol tree items added with
829              * "proto_tree_add_text()" should have -1 as the field index,
830              * with no pseudo-field being used, but that might also
831              * require special checks for -1 to be added.
832              */
833             statusbar_push_field_msg("");
834         }
835     }
836
837     packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
838                      byte_len);
839 }
840
841 #if GTK_MAJOR_VERSION < 2
842 static void
843 tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
844                           gpointer user_data _U_)
845 {
846         GtkWidget       *byte_view;
847         const guint8    *data;
848         guint           len;
849
850         /*
851          * Which byte view is displaying the current protocol tree
852          * row's data?
853          */
854         byte_view = get_notebook_bv_ptr(byte_nb_ptr);
855         if (byte_view == NULL)
856                 return; /* none */
857
858         data = get_byte_view_data_and_length(byte_view, &len);
859         if (data == NULL)
860                 return; /* none */
861
862         cf_unselect_field(&cfile);
863         packet_hex_print(byte_view, data, cfile.current_frame, NULL, len);
864 }
865 #endif
866
867 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
868   if (cfile.edt->tree)
869     collapse_all_tree(cfile.edt->tree, tree_view);
870 }
871
872 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
873   if (cfile.edt->tree)
874     expand_all_tree(cfile.edt->tree, tree_view);
875 }
876
877 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
878 #if GTK_MAJOR_VERSION < 2
879   GtkCTreeNode *node;
880 #else
881   GtkTreePath  *path;
882 #endif
883
884 #if GTK_MAJOR_VERSION < 2
885   node = gtk_ctree_find_by_row_data(GTK_CTREE(tree_view), NULL, cfile.finfo_selected);
886   if(node) {
887     /* the mouse position is at an entry, expand that one */
888   gtk_ctree_expand_recursive(GTK_CTREE(tree_view), node);
889   }
890 #else
891   path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
892   if(path) {
893     /* the mouse position is at an entry, expand that one */
894   gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
895   gtk_tree_path_free(path);
896   }
897 #endif
898 }
899
900 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
901   if (cfile.edt->tree) {
902     guint32 tmp = g_resolv_flags;
903     g_resolv_flags = RESOLV_ALL;
904     proto_tree_draw(cfile.edt->tree, tree_view);
905     g_resolv_flags = tmp;
906   }
907 }
908
909 /*
910  * Push a message referring to file access onto the statusbar.
911  */
912 void
913 statusbar_push_file_msg(gchar *msg)
914 {
915     /*g_warning("statusbar_push: %s", msg);*/
916         gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
917 }
918
919 /*
920  * Pop a message referring to file access off the statusbar.
921  */
922 void
923 statusbar_pop_file_msg(void)
924 {
925     /*g_warning("statusbar_pop");*/
926         gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
927 }
928
929 /*
930  * XXX - do we need multiple statusbar contexts?
931  */
932
933 /*
934  * Push a message referring to the currently-selected field onto the statusbar.
935  */
936 void
937 statusbar_push_field_msg(gchar *msg)
938 {
939         gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
940 }
941
942 /*
943  * Pop a message referring to the currently-selected field off the statusbar.
944  */
945 void
946 statusbar_pop_field_msg(void)
947 {
948         gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
949 }
950
951 /*
952  * update the packets statusbar to the current values
953  */
954 void packets_bar_update(void)
955 {
956
957     if(packets_bar) {
958         /* remove old status */
959         if(packets_str) {
960             g_free(packets_str);
961                 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
962         }
963
964         /* do we have any packets? */
965         if(cfile.count) {
966             if(cfile.drops_known) {
967                 packets_str = g_strdup_printf(" P: %u D: %u M: %u Drops: %u",
968                     cfile.count, cfile.displayed_count, cfile.marked_count, cfile.drops);
969             } else {
970                 packets_str = g_strdup_printf(" P: %u D: %u M: %u",
971                     cfile.count, cfile.displayed_count, cfile.marked_count);
972             }
973         } else {
974             packets_str = g_strdup(" No Packets");
975         }
976             gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str);
977     }
978 }
979
980 void
981 main_set_for_capture_file(gboolean have_capture_file_in)
982 {
983     have_capture_file = have_capture_file_in;
984
985     main_widgets_show_or_hide();
986 }
987
988 gboolean
989 main_do_quit(void)
990 {
991         /* get the current geometry, before writing it to disk */
992         main_save_window_geometry(top_level);
993
994         /* write user's recent file to disk
995          * It is no problem to write this file, even if we do not quit */
996         write_recent();
997
998         /* XXX - should we check whether the capture file is an
999            unsaved temporary file for a live capture and, if so,
1000            pop up a "do you want to exit without saving the capture
1001            file?" dialog, and then just return, leaving said dialog
1002            box to forcibly quit if the user clicks "OK"?
1003
1004            If so, note that this should be done in a subroutine that
1005            returns TRUE if we do so, and FALSE otherwise, and if it
1006            returns TRUE we should return TRUE without nuking anything.
1007
1008            Note that, if we do that, we might also want to check if
1009            an "Update list of packets in real time" capture is in
1010            progress and, if so, ask whether they want to terminate
1011            the capture and discard it, and return TRUE, before nuking
1012            any child capture, if they say they don't want to do so. */
1013
1014 #ifdef HAVE_LIBPCAP
1015         /* Nuke any child capture in progress. */
1016         capture_kill_child(capture_opts);
1017 #endif
1018
1019         /* Are we in the middle of reading a capture? */
1020         if (cfile.state == FILE_READ_IN_PROGRESS) {
1021                 /* Yes, so we can't just close the file and quit, as
1022                    that may yank the rug out from under the read in
1023                    progress; instead, just set the state to
1024                    "FILE_READ_ABORTED" and return - the code doing the read
1025                    will check for that and, if it sees that, will clean
1026                    up and quit. */
1027                 cfile.state = FILE_READ_ABORTED;
1028
1029                 /* Say that the window should *not* be deleted;
1030                    that'll be done by the code that cleans up. */
1031                 return TRUE;
1032         } else {
1033                 /* Close any capture file we have open; on some OSes, you
1034                    can't unlink a temporary capture file if you have it
1035                    open.
1036                    "cf_close()" will unlink it after closing it if
1037                    it's a temporary file.
1038
1039                    We do this here, rather than after the main loop returns,
1040                    as, after the main loop returns, the main window may have
1041                    been destroyed (if this is called due to a "destroy"
1042                    even on the main window rather than due to the user
1043                    selecting a menu item), and there may be a crash
1044                    or other problem when "cf_close()" tries to
1045                    clean up stuff in the main window.
1046
1047                    XXX - is there a better place to put this?
1048                    Or should we have a routine that *just* closes the
1049                    capture file, and doesn't do anything with the UI,
1050                    which we'd call here, and another routine that
1051                    calls that routine and also cleans up the UI, which
1052                    we'd call elsewhere? */
1053                 cf_close(&cfile);
1054
1055                 /* Exit by leaving the main loop, so that any quit functions
1056                    we registered get called. */
1057                 gtk_main_quit();
1058
1059                 /* Say that the window should be deleted. */
1060                 return FALSE;
1061         }
1062 }
1063
1064 static gboolean
1065 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1066 {
1067   gpointer dialog;
1068
1069   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1070 #if GTK_MAJOR_VERSION >= 2
1071     gtk_window_present(GTK_WINDOW(top_level));
1072 #endif
1073     /* user didn't saved his current file, ask him */
1074     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1075                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1076                 "If you quit the program without saving, your capture data will be discarded.");
1077     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1078     return TRUE;
1079   } else {
1080     /* unchanged file, just exit */
1081     /* "main_do_quit()" indicates whether the main window should be deleted. */
1082     return main_do_quit();
1083   }
1084 }
1085
1086
1087
1088 static void
1089 main_load_window_geometry(GtkWidget *widget)
1090 {
1091     window_geometry_t geom;
1092
1093     geom.set_pos        = prefs.gui_geometry_save_position;
1094     geom.x              = recent.gui_geometry_main_x;
1095     geom.y              = recent.gui_geometry_main_y;
1096     geom.set_size       = prefs.gui_geometry_save_size;
1097     if (recent.gui_geometry_main_width > 0 &&
1098         recent.gui_geometry_main_height > 0) {
1099         geom.width          = recent.gui_geometry_main_width;
1100         geom.height         = recent.gui_geometry_main_height;
1101         geom.set_maximized  = prefs.gui_geometry_save_maximized;
1102     } else {
1103         /* We assume this means the width and height weren't set in
1104            the "recent" file (or that there is no "recent" file),
1105            and weren't set to a default value, so we don't set the
1106            size.  (The "recent" file code rejects non-positive width
1107            and height values.) */
1108        geom.set_size = FALSE;
1109     }
1110     geom.maximized      = recent.gui_geometry_main_maximized;
1111
1112     window_set_geometry(widget, &geom);
1113
1114     if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1115         gtk_paned_set_position(GTK_PANED(main_first_pane),  recent.gui_geometry_main_upper_pane);
1116     if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane)
1117         gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1118     if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_status_pane)
1119         gtk_paned_set_position(GTK_PANED(status_pane),      recent.gui_geometry_status_pane);
1120 }
1121
1122
1123 static void
1124 main_save_window_geometry(GtkWidget *widget)
1125 {
1126     window_geometry_t geom;
1127
1128     window_get_geometry(widget, &geom);
1129
1130     if (prefs.gui_geometry_save_position) {
1131         recent.gui_geometry_main_x = geom.x;
1132             recent.gui_geometry_main_y = geom.y;
1133     }
1134
1135     if (prefs.gui_geometry_save_size) {
1136         recent.gui_geometry_main_width  = geom.width,
1137         recent.gui_geometry_main_height = geom.height;
1138     }
1139
1140 #if GTK_MAJOR_VERSION >= 2
1141     if(prefs.gui_geometry_save_maximized) {
1142         recent.gui_geometry_main_maximized = geom.maximized;
1143     }
1144
1145     recent.gui_geometry_main_upper_pane     = gtk_paned_get_position(GTK_PANED(main_first_pane));
1146     recent.gui_geometry_main_lower_pane     = gtk_paned_get_position(GTK_PANED(main_second_pane));
1147     recent.gui_geometry_status_pane         = gtk_paned_get_position(GTK_PANED(status_pane));
1148 #endif
1149 }
1150
1151 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1152 {
1153     switch(btn) {
1154     case(ESD_BTN_SAVE):
1155         /* save file first */
1156         file_save_as_cmd(after_save_exit, NULL);
1157         break;
1158     case(ESD_BTN_DONT_SAVE):
1159         main_do_quit();
1160         break;
1161     case(ESD_BTN_CANCEL):
1162         break;
1163     default:
1164         g_assert_not_reached();
1165     }
1166 }
1167
1168 void
1169 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1170 {
1171   gpointer dialog;
1172
1173   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1174     /* user didn't saved his current file, ask him */
1175     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1176                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1177                 "If you quit the program without saving, your capture data will be discarded.");
1178     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1179   } else {
1180     /* unchanged file, just exit */
1181     main_do_quit();
1182   }
1183 }
1184
1185 static void
1186 print_usage(gboolean print_ver) {
1187
1188   FILE *output;
1189
1190 #ifdef _WIN32
1191   create_console();
1192 #endif
1193
1194   if (print_ver) {
1195     output = stdout;
1196     fprintf(output, "Wireshark " VERSION "%s\n"
1197         "Interactively dump and analyze network traffic.\n"
1198         "See http://www.wireshark.org for more information.\n"
1199         "\n"
1200         "%s",
1201         svnversion, get_copyright_info());
1202   } else {
1203     output = stderr;
1204   }
1205   fprintf(output, "\n");
1206   fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1207   fprintf(output, "\n");
1208
1209 #ifdef HAVE_LIBPCAP
1210   fprintf(output, "Capture interface:\n");
1211   fprintf(output, "  -i <interface>           name or idx of interface (def: first non-loopback)\n");
1212   fprintf(output, "  -f <capture filter>      packet filter in libpcap filter syntax\n");
1213   fprintf(output, "  -s <snaplen>             packet snapshot length (def: 65535)\n");
1214   fprintf(output, "  -p                       don't capture in promiscuous mode\n");
1215   fprintf(output, "  -k                       start capturing immediately (def: do nothing)\n");
1216   fprintf(output, "  -Q                       quit Wireshark after capturing\n");
1217   fprintf(output, "  -S                       update packet display when new packets are captured\n");
1218   fprintf(output, "  -l                       turn on automatic scrolling while -S is in use\n");
1219 #ifdef _WIN32
1220   fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
1221 #endif
1222   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
1223   fprintf(output, "  -D                       print list of interfaces and exit\n");
1224   fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
1225   fprintf(output, "\n");
1226   fprintf(output, "Capture stop conditions:\n");
1227   fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
1228   fprintf(output, "  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds\n");
1229   fprintf(output, "                           filesize:NUM - stop this file after NUM KB\n");
1230   fprintf(output, "                              files:NUM - stop after NUM files\n");
1231   /*fprintf(output, "\n");*/
1232   fprintf(output, "Capture output:\n");
1233   fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1234   fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
1235   fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
1236 #endif  /* HAVE_LIBPCAP */
1237
1238   /*fprintf(output, "\n");*/
1239   fprintf(output, "Input file:\n");
1240   fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
1241
1242   fprintf(output, "\n");
1243   fprintf(output, "Processing:\n");
1244   fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
1245   fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
1246   fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
1247
1248   fprintf(output, "\n");
1249   fprintf(output, "User interface:\n");
1250   fprintf(output, "  -g <packet number>       go to specified packet number after \"-r\"\n");
1251   fprintf(output, "  -m <font>                set the font name used for most text\n");
1252   fprintf(output, "  -t ad|a|r|d|e            output format of time stamps (def: r: rel. to first)\n");
1253   fprintf(output, "  -X <key>:<value>         eXtension options, see man page for details\n");
1254   fprintf(output, "  -z <statistics>          show various statistics, see man page for details\n");
1255
1256   fprintf(output, "\n");
1257   fprintf(output, "Output:\n");
1258   fprintf(output, "  -w <outfile|->           set the output filename (or '-' for stdout)\n");
1259
1260   fprintf(output, "\n");
1261   fprintf(output, "Miscellaneous:\n");
1262   fprintf(output, "  -h                       display this help and exit\n");
1263   fprintf(output, "  -v                       display version info and exit\n");
1264   fprintf(output, "  -o <name>:<value> ...    override preference or recent setting\n");
1265 #ifndef _WIN32
1266   fprintf(output, "  --display=DISPLAY        X display to use\n");
1267 #endif
1268
1269 #ifdef _WIN32
1270   destroy_console();
1271 #endif
1272 }
1273
1274 static void
1275 show_version(void)
1276 {
1277 #ifdef _WIN32
1278   create_console();
1279 #endif
1280
1281   printf(PACKAGE " " VERSION "%s\n"
1282          "\n"
1283          "%s"
1284          "\n"
1285          "%s"
1286          "\n"
1287          "%s",
1288       svnversion, get_copyright_info(), comp_info_str->str,
1289       runtime_info_str->str);
1290
1291 #ifdef _WIN32
1292   destroy_console();
1293 #endif
1294 }
1295
1296 /*
1297  * Report an error in command-line arguments.
1298  * Creates a console on Windows.
1299  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1300  * terminal isn't the standard error?
1301  */
1302 void
1303 cmdarg_err(const char *fmt, ...)
1304 {
1305   va_list ap;
1306
1307 #ifdef _WIN32
1308   create_console();
1309 #endif
1310   va_start(ap, fmt);
1311   fprintf(stderr, "wireshark: ");
1312   vfprintf(stderr, fmt, ap);
1313   fprintf(stderr, "\n");
1314   va_end(ap);
1315 }
1316
1317 /*
1318  * Report additional information for an error in command-line arguments.
1319  * Creates a console on Windows.
1320  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1321  * terminal isn't the standard error?
1322  */
1323 void
1324 cmdarg_err_cont(const char *fmt, ...)
1325 {
1326   va_list ap;
1327
1328 #ifdef _WIN32
1329   create_console();
1330 #endif
1331   va_start(ap, fmt);
1332   vfprintf(stderr, fmt, ap);
1333   fprintf(stderr, "\n");
1334   va_end(ap);
1335 }
1336
1337 #if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
1338 /*
1339    Once every 3 seconds we get a callback here which we use to update
1340    the tap extensions. Since Gtk1 is single threaded we dont have to
1341    worry about any locking or critical regions.
1342  */
1343 static gint
1344 update_cb(gpointer data _U_)
1345 {
1346         draw_tap_listeners(FALSE);
1347         return 1;
1348 }
1349 #else
1350
1351 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1352    use threads all updte_thread_mutex can be dropped and protect/unprotect
1353    would just be empty functions.
1354
1355    This allows gtk2-rpcstat.c and friends to be copied unmodified to
1356    gtk1-wireshark and it will just work.
1357  */
1358 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1359 gpointer
1360 update_thread(gpointer data _U_)
1361 {
1362     while(1){
1363         GTimeVal tv1, tv2;
1364         g_get_current_time(&tv1);
1365         g_static_mutex_lock(&update_thread_mutex);
1366         gdk_threads_enter();
1367         draw_tap_listeners(FALSE);
1368         gdk_threads_leave();
1369         g_static_mutex_unlock(&update_thread_mutex);
1370         g_thread_yield();
1371         g_get_current_time(&tv2);
1372         if( ((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) >
1373             (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1374             g_usleep(((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) -
1375                      (tv2.tv_sec * 1000000 + tv2.tv_usec));
1376         }
1377     }
1378     return NULL;
1379 }
1380 #endif
1381 void
1382 protect_thread_critical_region(void)
1383 {
1384 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1385     g_static_mutex_lock(&update_thread_mutex);
1386 #endif
1387 }
1388 void
1389 unprotect_thread_critical_region(void)
1390 {
1391 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1392     g_static_mutex_unlock(&update_thread_mutex);
1393 #endif
1394 }
1395
1396 /* Set the file name in the status line, in the name for the main window,
1397    and in the name for the main window's icon. */
1398 static void
1399 set_display_filename(capture_file *cf)
1400 {
1401   const gchar *name_ptr;
1402   gchar       *status_msg;
1403   gchar       *size_str;
1404   gchar       *win_name;
1405
1406   name_ptr = cf_get_display_name(cf);
1407
1408   if (!cf->is_tempfile && cf->filename) {
1409     /* Add this filename to the list of recent files in the "Recent Files" submenu */
1410     add_menu_recent_capture_file(cf->filename);
1411   }
1412
1413   /* convert file size */
1414   if (cf->f_datalen/1024/1024 > 10) {
1415     size_str = g_strdup_printf("%lld MB", cf->f_datalen/1024/1024);
1416   } else if (cf->f_datalen/1024 > 10) {
1417     size_str = g_strdup_printf("%lld KB", cf->f_datalen/1024);
1418   } else {
1419     size_str = g_strdup_printf("%lld Bytes", cf->f_datalen);
1420   }
1421
1422   /* statusbar */
1423 #if 0
1424   /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1425   status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu [Expert: %s]",
1426     (cf->filename) ? cf->filename : "", size_str,
1427     (long)cf->elapsed_time.secs/3600,
1428     (long)cf->elapsed_time.secs%3600/60,
1429     (long)cf->elapsed_time.secs%60,
1430     val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1431 #endif
1432   status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu",
1433     (cf->filename) ? cf->filename : "", size_str,
1434     (long)cf->elapsed_time.secs/3600,
1435     (long)cf->elapsed_time.secs%3600/60,
1436     (long)cf->elapsed_time.secs%60);
1437   g_free(size_str);
1438   statusbar_push_file_msg(status_msg);
1439   g_free(status_msg);
1440
1441   /* window title */
1442   win_name = g_strdup_printf("%s - Wireshark", name_ptr);
1443   set_main_window_name(win_name);
1444   g_free(win_name);
1445 }
1446
1447 GtkWidget           *close_dlg = NULL;
1448
1449 static void
1450 main_cf_cb_file_closing(capture_file *cf)
1451 {
1452
1453     /* if we have more than 10000 packets, show a splash screen while closing */
1454     /* XXX - don't know a better way to decide wether to show or not,
1455      * as most of the time is spend in a single eth_clist_clear function,
1456      * so we can't use a progress bar here! */
1457     if(cf->count > 10000) {
1458         close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1459                                   "%sClosing file!%s\n\nPlease wait ...",
1460                                   simple_dialog_primary_start(),
1461                                   simple_dialog_primary_end());
1462 #if GTK_MAJOR_VERSION >= 2
1463         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1464 #else
1465         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER);
1466 #endif
1467     }
1468
1469     /* Destroy all windows, which refer to the
1470        capture file we're closing. */
1471     destroy_packet_wins();
1472     file_save_as_destroy();
1473
1474     /* Clear any file-related status bar messages.
1475        XXX - should be "clear *ALL* file-related status bar messages;
1476        will there ever be more than one on the stack? */
1477     statusbar_pop_file_msg();
1478
1479     /* Restore the standard title bar message. */
1480     set_main_window_name("The Wireshark Network Analyzer");
1481
1482     /* Disable all menu items that make sense only if you have a capture. */
1483     set_menus_for_capture_file(FALSE);
1484     set_menus_for_unsaved_capture_file(FALSE);
1485     set_menus_for_captured_packets(FALSE);
1486     set_menus_for_selected_packet(cf);
1487     set_menus_for_capture_in_progress(FALSE);
1488     set_menus_for_selected_tree_row(cf);
1489
1490     /* Set up main window for no capture file. */
1491     main_set_for_capture_file(FALSE);
1492
1493     main_window_update();
1494 }
1495
1496 static void
1497 main_cf_cb_file_closed(capture_file *cf _U_)
1498 {
1499   if(close_dlg != NULL) {
1500     splash_destroy(close_dlg);
1501     close_dlg = NULL;
1502   }
1503
1504   /* go back to "No packets" */
1505   packets_bar_update();
1506 }
1507
1508 static void
1509 main_cf_cb_file_read_start(capture_file *cf)
1510 {
1511   const gchar *name_ptr;
1512   gchar       *load_msg;
1513
1514   name_ptr = get_basename(cf->filename);
1515
1516   load_msg = g_strdup_printf(" Loading: %s", name_ptr);
1517   statusbar_push_file_msg(load_msg);
1518   g_free(load_msg);
1519
1520   /* Set up main window for a capture file. */
1521   main_set_for_capture_file(TRUE);
1522 }
1523
1524 static void
1525 main_cf_cb_file_read_finished(capture_file *cf)
1526 {
1527     statusbar_pop_file_msg();
1528     set_display_filename(cf);
1529
1530     /* Enable menu items that make sense if you have a capture file you've
1531      finished reading. */
1532     set_menus_for_capture_file(TRUE);
1533     set_menus_for_unsaved_capture_file(!cf->user_saved);
1534
1535     /* Enable menu items that make sense if you have some captured packets. */
1536     set_menus_for_captured_packets(TRUE);
1537 }
1538
1539 #if GTK_MAJOR_VERSION >= 2
1540 GList *icon_list_create(
1541     const char **icon16_xpm,
1542     const char **icon32_xpm,
1543     const char **icon48_xpm,
1544     const char **icon64_xpm)
1545 {
1546   GList *icon_list = NULL;
1547   GdkPixbuf * pixbuf16;
1548   GdkPixbuf * pixbuf32;
1549   GdkPixbuf * pixbuf48;
1550   GdkPixbuf * pixbuf64;
1551
1552
1553   if(icon16_xpm != NULL) {
1554       pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1555       g_assert(pixbuf16);
1556       icon_list = g_list_append(icon_list, pixbuf16);
1557   }
1558
1559   if(icon32_xpm != NULL) {
1560       pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1561       g_assert(pixbuf32);
1562       icon_list = g_list_append(icon_list, pixbuf32);
1563   }
1564
1565   if(icon48_xpm != NULL) {
1566       pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1567       g_assert(pixbuf48);
1568       icon_list = g_list_append(icon_list, pixbuf48);
1569   }
1570
1571   if(icon64_xpm != NULL) {
1572       pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1573       g_assert(pixbuf64);
1574       icon_list = g_list_append(icon_list, pixbuf64);
1575   }
1576
1577   return icon_list;
1578 }
1579 #endif
1580
1581 #ifdef HAVE_LIBPCAP
1582 static void
1583 main_cf_cb_live_capture_prepared(capture_options *capture_opts)
1584 {
1585     gchar *title;
1586 #if GTK_MAJOR_VERSION >= 2
1587     static GList *icon_list = NULL;
1588 #endif
1589
1590
1591     if(capture_opts->iface) {
1592         title = g_strdup_printf("%s: Capturing - Wireshark",
1593                             get_interface_descriptive_name(capture_opts->iface));
1594     } else {
1595         title = g_strdup_printf("Capturing - Wireshark");
1596     }
1597     set_main_window_name(title);
1598     g_free(title);
1599
1600 #if GTK_MAJOR_VERSION >= 2
1601     if(icon_list == NULL) {
1602         icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1603     }
1604     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1605 #endif
1606
1607     /* Disable menu items that make no sense if you're currently running
1608        a capture. */
1609     set_menus_for_capture_in_progress(TRUE);
1610
1611     /* update statusbar */
1612     statusbar_push_file_msg("Waiting for capture input data ...");
1613
1614     /* Don't set up main window for a capture file. */
1615     main_set_for_capture_file(FALSE);
1616 }
1617
1618 static void
1619 main_cf_cb_live_capture_update_started(capture_options *capture_opts)
1620 {
1621     gchar *capture_msg;
1622     gchar *title;
1623
1624     /* We've done this in "prepared" above, but it will be cleared while
1625        switching to the next multiple file. */
1626     if(capture_opts->iface) {
1627         title = g_strdup_printf("%s: Capturing - Wireshark",
1628                             get_interface_descriptive_name(capture_opts->iface));
1629     } else {
1630         title = g_strdup_printf("Capturing - Wireshark");
1631     }
1632     set_main_window_name(title);
1633     g_free(title);
1634
1635     set_menus_for_capture_in_progress(TRUE);
1636
1637     /* Enable menu items that make sense if you have some captured
1638        packets (yes, I know, we don't have any *yet*). */
1639     set_menus_for_captured_packets(TRUE);
1640
1641     statusbar_pop_file_msg();
1642
1643     if(capture_opts->iface) {
1644         capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1645             get_interface_descriptive_name(capture_opts->iface),
1646             (capture_opts->save_file) ? capture_opts->save_file : "");
1647     } else {
1648         capture_msg = g_strdup_printf(" <live capture in progress> to file: %s",
1649             (capture_opts->save_file) ? capture_opts->save_file : "");
1650     }
1651
1652     statusbar_push_file_msg(capture_msg);
1653
1654     g_free(capture_msg);
1655
1656     /* Set up main window for a capture file. */
1657     main_set_for_capture_file(TRUE);
1658 }
1659
1660 static void
1661 main_cf_cb_live_capture_update_continue(capture_file *cf)
1662 {
1663     gchar *capture_msg;
1664
1665
1666     statusbar_pop_file_msg();
1667
1668 #if 0
1669     /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1670     if (cf->f_datalen/1024/1024 > 10) {
1671         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld MB [Expert: %s]",
1672             get_interface_descriptive_name(capture_opts->iface),
1673             capture_opts->save_file,
1674             cf->f_datalen/1024/1024,
1675             val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1676     } else if (cf->f_datalen/1024 > 10) {
1677         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld KB [Expert: %s]",
1678             get_interface_descriptive_name(capture_opts->iface),
1679             capture_opts->save_file,
1680             cf->f_datalen/1024,
1681             val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1682     } else {
1683         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld Bytes [Expert: %s]",
1684             get_interface_descriptive_name(capture_opts->iface),
1685             capture_opts->save_file,
1686             cf->f_datalen,
1687             val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1688     }
1689 #endif
1690     if (cf->f_datalen/1024/1024 > 10) {
1691         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld MB",
1692             get_interface_descriptive_name(capture_opts->iface),
1693             capture_opts->save_file,
1694             cf->f_datalen/1024/1024);
1695     } else if (cf->f_datalen/1024 > 10) {
1696         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld KB",
1697             get_interface_descriptive_name(capture_opts->iface),
1698             capture_opts->save_file,
1699             cf->f_datalen/1024);
1700     } else {
1701         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld Bytes",
1702             get_interface_descriptive_name(capture_opts->iface),
1703             capture_opts->save_file,
1704             cf->f_datalen);
1705     }
1706
1707     statusbar_push_file_msg(capture_msg);
1708 }
1709
1710 GtkWidget * stop_dlg = NULL;
1711
1712 static void
1713 main_cf_cb_live_capture_update_finished(capture_file *cf)
1714 {
1715 #if GTK_MAJOR_VERSION >= 2
1716     static GList *icon_list = NULL;
1717 #endif
1718
1719     if(stop_dlg != NULL) {
1720                 simple_dialog_close(stop_dlg);
1721                 stop_dlg = NULL;
1722         }
1723
1724     /* Pop the "<live capture in progress>" message off the status bar. */
1725     statusbar_pop_file_msg();
1726
1727     set_display_filename(cf);
1728
1729     /* Enable menu items that make sense if you're not currently running
1730      a capture. */
1731     set_menus_for_capture_in_progress(FALSE);
1732
1733     /* Enable menu items that make sense if you have a capture file
1734      you've finished reading. */
1735     set_menus_for_capture_file(TRUE);
1736     set_menus_for_unsaved_capture_file(!cf->user_saved);
1737
1738     /* Set up main window for a capture file. */
1739     main_set_for_capture_file(TRUE);
1740
1741 #if GTK_MAJOR_VERSION >= 2
1742     if(icon_list == NULL) {
1743         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1744     }
1745     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1746 #endif
1747
1748     if(capture_opts->quit_after_cap) {
1749         /* command line asked us to quit after the capture */
1750         /* don't pop up a dialog to ask for unsaved files etc. */
1751         main_do_quit();
1752     }
1753 }
1754
1755 static void
1756 main_cf_cb_live_capture_fixed_started(capture_options *capture_opts)
1757 {
1758     gchar *capture_msg;
1759
1760
1761     /* Enable menu items that make sense if you have some captured
1762        packets (yes, I know, we don't have any *yet*). */
1763     /*set_menus_for_captured_packets(TRUE);*/
1764
1765     statusbar_pop_file_msg();
1766
1767     capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1768         get_interface_descriptive_name(capture_opts->iface),
1769         (capture_opts->save_file) ? capture_opts->save_file : "");
1770
1771     statusbar_push_file_msg(capture_msg);
1772     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, " P: 0");
1773
1774     g_free(capture_msg);
1775
1776     /* Don't set up main window for a capture file. */
1777     main_set_for_capture_file(FALSE);
1778 }
1779
1780 static void
1781 main_cf_cb_live_capture_fixed_continue(capture_file *cf)
1782 {
1783     gchar *capture_msg;
1784
1785
1786         gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1787
1788     capture_msg = g_strdup_printf(" P: %u",
1789         cf_get_packet_count(cf));
1790
1791     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, capture_msg);
1792
1793     g_free(capture_msg);
1794 }
1795
1796 static void
1797 main_cf_cb_live_capture_fixed_finished(capture_file *cf _U_)
1798 {
1799 #if GTK_MAJOR_VERSION >= 2
1800     static GList *icon_list = NULL;
1801 #endif
1802
1803     if(stop_dlg != NULL) {
1804                 simple_dialog_close(stop_dlg);
1805                 stop_dlg = NULL;
1806         }
1807
1808     /* Pop the "<live capture in progress>" message off the status bar. */
1809     statusbar_pop_file_msg();
1810
1811     /* Pop the "<capturing>" message off the status bar */
1812         gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1813
1814     /*set_display_filename(cf);*/
1815
1816     /* Enable menu items that make sense if you're not currently running
1817      a capture. */
1818     set_menus_for_capture_in_progress(FALSE);
1819
1820     /* Restore the standard title bar message */
1821     /* (just in case we have trouble opening the capture file). */
1822     set_main_window_name("The Wireshark Network Analyzer");
1823
1824 #if GTK_MAJOR_VERSION >= 2
1825     if(icon_list == NULL) {
1826         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1827     }
1828     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1829 #endif
1830
1831     /* We don't have loaded the capture file, this will be done later.
1832      * For now we still have simply a blank screen. */
1833
1834     if(capture_opts->quit_after_cap) {
1835         /* command line asked us to quit after the capture */
1836         /* don't pop up a dialog to ask for unsaved files etc. */
1837         main_do_quit();
1838     }
1839 }
1840
1841 static void
1842 main_cf_cb_live_capture_stopping(capture_file *cf _U_)
1843 {
1844     /* Beware: this state won't be called, if the capture child
1845      * closes the capturing on it's own! */
1846 #if 0
1847     /* XXX - the time to stop the capture has been reduced (this was only a
1848      * problem on Win32 because of the capture piping), so showing a splash
1849      * isn't really necessary any longer. Unfortunately, the GTKClist packet
1850      * list seems to have problems updating after the dialog is closed, so
1851      * this was disabled here. */
1852     stop_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE, "%sCapture stop!%s\n\nPlease wait ...",
1853                 simple_dialog_primary_start(), simple_dialog_primary_end());
1854 #if GTK_MAJOR_VERSION >= 2
1855     gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1856 #else
1857     gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER);
1858 #endif
1859 #endif
1860 }
1861
1862 #endif
1863
1864 static void
1865 main_cf_cb_packet_selected(gpointer data)
1866 {
1867     capture_file *cf = data;
1868
1869     /* Display the GUI protocol tree and hex dump.
1870       XXX - why do we dump core if we call "proto_tree_draw()"
1871       before calling "add_byte_views()"? */
1872     add_main_byte_views(cf->edt);
1873     main_proto_tree_draw(cf->edt->tree);
1874
1875     /* The user is searching for a string in the data or a hex value,
1876      * highlight the field that is found in the tree and hex displays. */
1877 #if GTK_MAJOR_VERSION < 2
1878     if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1879             highlight_field(cf->edt->tvb, cfile.search_pos,
1880                                     (GtkCTree *)tree_view, cf->edt->tree);
1881 #else
1882     if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1883             highlight_field(cf->edt->tvb, cfile.search_pos,
1884                                     (GtkTreeView *)tree_view, cf->edt->tree);
1885 #endif
1886                     cfile.search_pos = 0; /* Reset the position */
1887     }
1888
1889     /* A packet is selected. */
1890     set_menus_for_selected_packet(cf);
1891 }
1892
1893 static void
1894 main_cf_cb_packet_unselected(capture_file *cf)
1895 {
1896     /* Clear out the display of that packet. */
1897     clear_tree_and_hex_views();
1898
1899     /* No packet is selected. */
1900     set_menus_for_selected_packet(cf);
1901 }
1902
1903 static void
1904 main_cf_cb_field_unselected(capture_file *cf)
1905 {
1906     statusbar_pop_field_msg();
1907     set_menus_for_selected_tree_row(cf);
1908 }
1909
1910 static void
1911 main_cf_cb_file_safe_started(gchar * filename)
1912 {
1913     const gchar  *name_ptr;
1914     gchar        *save_msg;
1915
1916     name_ptr = get_basename(filename);
1917
1918     save_msg = g_strdup_printf(" Saving: %s...", name_ptr);
1919
1920     statusbar_push_file_msg(save_msg);
1921     g_free(save_msg);
1922 }
1923
1924 static void
1925 main_cf_cb_file_safe_finished(gpointer data _U_)
1926 {
1927     /* Pop the "Saving:" message off the status bar. */
1928     statusbar_pop_file_msg();
1929 }
1930
1931 static void
1932 main_cf_cb_file_safe_failed(gpointer data _U_)
1933 {
1934     /* Pop the "Saving:" message off the status bar. */
1935     statusbar_pop_file_msg();
1936 }
1937
1938 static void
1939 main_cf_cb_file_safe_reload_finished(gpointer data _U_)
1940 {
1941     set_menus_for_unsaved_capture_file(FALSE);
1942 }
1943
1944 static void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1945 {
1946     switch(event) {
1947     case(cf_cb_file_closing):
1948         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1949         main_cf_cb_file_closing(data);
1950         break;
1951     case(cf_cb_file_closed):
1952         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1953         main_cf_cb_file_closed(data);
1954         break;
1955     case(cf_cb_file_read_start):
1956         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
1957         main_cf_cb_file_read_start(data);
1958         break;
1959     case(cf_cb_file_read_finished):
1960         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1961         main_cf_cb_file_read_finished(data);
1962         break;
1963 #ifdef HAVE_LIBPCAP
1964     case(cf_cb_live_capture_prepared):
1965         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1966         main_cf_cb_live_capture_prepared(data);
1967         break;
1968     case(cf_cb_live_capture_update_started):
1969         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1970         main_cf_cb_live_capture_update_started(data);
1971         break;
1972     case(cf_cb_live_capture_update_continue):
1973         /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1974         main_cf_cb_live_capture_update_continue(data);
1975         break;
1976     case(cf_cb_live_capture_update_finished):
1977         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1978         main_cf_cb_live_capture_update_finished(data);
1979         break;
1980     case(cf_cb_live_capture_fixed_started):
1981         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1982         main_cf_cb_live_capture_fixed_started(data);
1983         break;
1984     case(cf_cb_live_capture_fixed_continue):
1985         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");
1986         main_cf_cb_live_capture_fixed_continue(data);
1987         break;
1988     case(cf_cb_live_capture_fixed_finished):
1989         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1990         main_cf_cb_live_capture_fixed_finished(data);
1991         break;
1992     case(cf_cb_live_capture_stopping):
1993         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1994         main_cf_cb_live_capture_stopping(data);
1995         break;
1996 #endif
1997     case(cf_cb_packet_selected):
1998         main_cf_cb_packet_selected(data);
1999         break;
2000     case(cf_cb_packet_unselected):
2001         main_cf_cb_packet_unselected(data);
2002         break;
2003     case(cf_cb_field_unselected):
2004         main_cf_cb_field_unselected(data);
2005         break;
2006     case(cf_cb_file_safe_started):
2007         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
2008         main_cf_cb_file_safe_started(data);
2009         break;
2010     case(cf_cb_file_safe_finished):
2011         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
2012         main_cf_cb_file_safe_finished(data);
2013         break;
2014     case(cf_cb_file_safe_reload_finished):
2015         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
2016         main_cf_cb_file_safe_reload_finished(data);
2017         break;
2018     case(cf_cb_file_safe_failed):
2019         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
2020         main_cf_cb_file_safe_failed(data);
2021         break;
2022     default:
2023         g_warning("main_cf_callback: event %u unknown", event);
2024         g_assert_not_reached();
2025     }
2026 }
2027
2028 static void
2029 get_gui_compiled_info(GString *str)
2030 {
2031   get_epan_compiled_version_info(str);
2032
2033   g_string_append(str, ", ");
2034 #ifdef HAVE_LIBPORTAUDIO
2035 #ifdef PORTAUDIO_API_1
2036   g_string_append(str, "with PortAudio <= V18");
2037 #else /* PORTAUDIO_API_1 */
2038   g_string_append(str, "with PortAudio ");
2039   g_string_append(str, Pa_GetVersionText());
2040 #endif /* PORTAUDIO_API_1 */
2041 #else /* HAVE_LIBPORTAUDIO */
2042   g_string_append(str, "without PortAudio");
2043 #endif /* HAVE_LIBPORTAUDIO */
2044
2045   g_string_append(str, ", ");
2046 #ifdef HAVE_AIRPCAP
2047   get_compiled_airpcap_version(str);
2048 #else
2049   g_string_append(str, "without AirPcap");
2050 #endif
2051 }
2052
2053 static void
2054 get_gui_runtime_info(GString *str
2055 #ifndef HAVE_AIRPCAP
2056         _U_
2057 #endif
2058 )
2059 {
2060 #ifdef HAVE_AIRPCAP
2061   g_string_append(str, ", ");
2062   get_runtime_airpcap_version(str);
2063 #endif
2064 }
2065
2066 /* And now our feature presentation... [ fade to music ] */
2067 int
2068 main(int argc, char *argv[])
2069 {
2070   char                *init_progfile_dir_error;
2071   char                *s;
2072   int                  i;
2073   int                  opt;
2074   extern char         *optarg;
2075   gboolean             arg_error = FALSE;
2076
2077 #ifdef _WIN32
2078   WSADATA              wsaData;
2079 #endif  /* _WIN32 */
2080
2081   char                *rf_path;
2082   int                  rf_open_errno;
2083   char                *gpf_path, *pf_path;
2084   char                *cf_path, *df_path;
2085   char                *gdp_path, *dp_path;
2086   int                  gpf_open_errno, gpf_read_errno;
2087   int                  pf_open_errno, pf_read_errno;
2088   int                  cf_open_errno, df_open_errno;
2089   int                  gdp_open_errno, gdp_read_errno;
2090   int                  dp_open_errno, dp_read_errno;
2091   int                  err;
2092 #ifdef HAVE_LIBPCAP
2093   gboolean             start_capture = FALSE;
2094 #else
2095   gboolean             capture_option_specified = FALSE;
2096 #endif
2097   gint                 pl_size = 280, tv_size = 95, bv_size = 75;
2098   gchar               *rc_file, *cf_name = NULL, *rfilter = NULL;
2099   dfilter_t           *rfcode = NULL;
2100   gboolean             rfilter_parse_failed = FALSE;
2101   e_prefs             *prefs;
2102   char                 badopt;
2103   GtkWidget           *splash_win = NULL;
2104   GLogLevelFlags       log_flags;
2105   guint                go_to_packet = 0;
2106   int                  optind_initial;
2107   int                  status;
2108
2109 #ifdef HAVE_AIRPCAP
2110   char                  err_str[AIRPCAP_ERRBUF_SIZE];
2111   gchar                 *cant_get_if_list_errstr;
2112 #endif
2113
2114 #define OPTSTRING_INIT "a:b:c:Df:g:Hhi:klLm:nN:o:pQr:R:Ss:t:vw:X:y:z:"
2115
2116 #if defined HAVE_LIBPCAP && defined _WIN32
2117 #define OPTSTRING_WIN32 "B:"
2118 #else
2119 #define OPTSTRING_WIN32 ""
2120 #endif
2121
2122   char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
2123     OPTSTRING_INIT OPTSTRING_WIN32;
2124
2125 #ifdef  HAVE_AIRPDCAP
2126         /*      Davide Schiera (2006-11-18): init AirPDcap context                                                              */
2127         AirPDcapInitContext(&airpdcap_ctx);
2128         /* Davide Schiera (2006-11-18) -------------------------------------------      */
2129 #endif
2130
2131   /*
2132    * Attempt to get the pathname of the executable file.
2133    */
2134   init_progfile_dir_error = init_progfile_dir(argv[0]);
2135
2136   /*
2137    * Get credential information for later use.
2138    */
2139   get_credential_info();
2140
2141   /* initialize the funnel mini-api */
2142   initialize_funnel_ops();
2143
2144 #ifdef _WIN32
2145   /* Load wpcap if possible. Do this before collecting the run-time version information */
2146   load_wpcap();
2147
2148   /* ... and also load the packet.dll from wpcap */
2149   wpcap_packet_load();
2150
2151 #ifdef HAVE_AIRPCAP
2152    /* Load the airpcap.dll.  This must also be done before collecting
2153     * run-time version information. */
2154   airpcap_dll_ret_val = load_airpcap();
2155
2156   switch (airpcap_dll_ret_val) {
2157   case AIRPCAP_DLL_OK:
2158     /* load the airpcap interfaces */
2159     airpcap_if_list = get_airpcap_interface_list(&err, err_str);
2160
2161     if (airpcap_if_list == NULL && err == CANT_GET_AIRPCAP_INTERFACE_LIST) {
2162       cant_get_if_list_errstr = cant_get_airpcap_if_list_error_message(err_str);
2163       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", cant_get_if_list_errstr);
2164       g_free(cant_get_if_list_errstr);
2165     }
2166     /* select the first ad default (THIS SHOULD BE CHANGED) */
2167     airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2168     break;
2169
2170 #if 0
2171     /*
2172      * XXX - Maybe we need to warn the user if one of the following happens???
2173      */
2174     case AIRPCAP_DLL_OLD:
2175       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2176       break;
2177
2178     case AIRPCAP_DLL_ERROR:
2179       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2180       break;
2181
2182     case AIRPCAP_DLL_NOT_FOUND:
2183       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2184       break;
2185 #endif
2186   }
2187 #endif /* HAVE_AIRPCAP */
2188
2189   /* Start windows sockets */
2190   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2191 #endif  /* _WIN32 */
2192
2193   /* Assemble the compile-time version information string */
2194   comp_info_str = g_string_new("Compiled ");
2195
2196   g_string_append(comp_info_str, "with ");
2197   g_string_sprintfa(comp_info_str,
2198 #ifdef GTK_MAJOR_VERSION
2199                     "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2200                     GTK_MICRO_VERSION);
2201 #else
2202                     "GTK+ (version unknown)");
2203 #endif
2204   g_string_append(comp_info_str, ", ");
2205
2206   get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2207
2208   /* Assemble the run-time version information string */
2209   runtime_info_str = g_string_new("Running ");
2210   get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2211
2212
2213   /* "pre-scan" the command line parameters, if we have "console only"
2214      parameters.  We do this so we don't start GTK+ if we're only showing
2215      command-line help or version information.
2216
2217      XXX - this pre-scan is doen before we start GTK+, so we haven't
2218      run gtk_init() on the arguments.  That means that GTK+ arguments
2219      have not been removed from the argument list; those arguments
2220      begin with "--", and will be treated as an error by getopt().
2221
2222      We thus ignore errors - *and* set "opterr" to 0 to suppress the
2223      error messages. */
2224   opterr = 0;
2225   optind_initial = optind;
2226   while ((opt = getopt(argc, argv, optstring)) != -1) {
2227     switch (opt) {
2228       case 'h':        /* Print help and exit */
2229         print_usage(TRUE);
2230         exit(0);
2231         break;
2232       case 'v':        /* Show version and exit */
2233         show_version();
2234         exit(0);
2235         break;
2236       case 'X':
2237           /*
2238            *  Extension command line options have to be processed before
2239            *  we call epan_init() as they are supposed to be used by dissectors
2240            *  or taps very early in the registration process.
2241            */
2242           ex_opt_add(optarg);
2243           break;
2244       case '?':        /* Ignore errors - the "real" scan will catch them. */
2245         break;
2246     }
2247   }
2248
2249   /* Set getopt index back to initial value, so it will start with the
2250      first command line parameter again.  Also reset opterr to 1, so that
2251      error messages are printed by getopt().
2252
2253      XXX - this seems to work on most platforms, but time will tell.
2254      The Single UNIX Specification says "The getopt() function need
2255      not be reentrant", so this isn't guaranteed to work.  The Mac
2256      OS X 10.4[.x] getopt() man page says
2257
2258        In order to use getopt() to evaluate multiple sets of arguments, or to
2259        evaluate a single set of arguments multiple times, the variable optreset
2260        must be set to 1 before the second and each additional set of calls to
2261        getopt(), and the variable optind must be reinitialized.
2262
2263            ...
2264
2265        The optreset variable was added to make it possible to call the getopt()
2266        function multiple times.  This is an extension to the IEEE Std 1003.2
2267        (``POSIX.2'') specification.
2268
2269      which I think comes from one of the other BSDs.
2270
2271      XXX - if we want to control all the command-line option errors, so
2272      that we can display them where we choose (e.g., in a window), we'd
2273      want to leave opterr as 0, and produce our own messages using optopt.
2274      We'd have to check the value of optopt to see if it's a valid option
2275      letter, in which case *presumably* the error is "this option requires
2276      an argument but none was specified", or not a valid option letter,
2277      in which case *presumably* the error is "this option isn't valid".
2278      Some versions of getopt() let you supply a option string beginning
2279      with ':', which means that getopt() will return ':' rather than '?'
2280      for "this option requires an argument but none was specified", but
2281      not all do. */
2282   optind = optind_initial;
2283   opterr = 1;
2284
2285   /* Set the current locale according to the program environment.
2286    * We haven't localized anything, but some GTK widgets are localized
2287    * (the file selection dialogue, for example).
2288    * This also sets the C-language locale to the native environment. */
2289   gtk_set_locale();
2290
2291   /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2292   gtk_init (&argc, &argv);
2293
2294   cf_callback_add(main_cf_callback, NULL);
2295
2296 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
2297   /* initialize our GTK eth_clist_type */
2298   init_eth_clist_type();
2299 #endif
2300
2301   /* Arrange that if we have no console window, and a GLib message logging
2302      routine is called to log a message, we pop up a console window.
2303
2304      We do that by inserting our own handler for all messages logged
2305      to the default domain; that handler pops up a console if necessary,
2306      and then calls the default handler. */
2307
2308   /* We might want to have component specific log levels later ... */
2309
2310   log_flags =
2311                     G_LOG_LEVEL_ERROR|
2312                     G_LOG_LEVEL_CRITICAL|
2313                     G_LOG_LEVEL_WARNING|
2314                     G_LOG_LEVEL_MESSAGE|
2315                     G_LOG_LEVEL_INFO|
2316                     G_LOG_LEVEL_DEBUG|
2317                     G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2318
2319   g_log_set_handler(NULL,
2320                     log_flags,
2321                     console_log_handler, NULL /* user_data */);
2322   g_log_set_handler(LOG_DOMAIN_MAIN,
2323                     log_flags,
2324                     console_log_handler, NULL /* user_data */);
2325
2326 #ifdef HAVE_LIBPCAP
2327   g_log_set_handler(LOG_DOMAIN_CAPTURE,
2328                     log_flags,
2329                     console_log_handler, NULL /* user_data */);
2330   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2331                     log_flags,
2332                     console_log_handler, NULL /* user_data */);
2333
2334   /* Set the initial values in the capture_opts. This might be overwritten
2335      by preference settings and then again by the command line parameters. */
2336   capture_opts_init(capture_opts, &cfile);
2337
2338   capture_opts->snaplen             = MIN_PACKET_SIZE;
2339   capture_opts->has_ring_num_files  = TRUE;
2340 #endif
2341
2342   /* We won't come till here, if we had a "console only" command line parameter. */
2343   splash_win = splash_new("Loading Wireshark ...");
2344   if (init_progfile_dir_error != NULL) {
2345     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2346         "Can't get pathname of Wireshark: %s.\n"
2347         "It won't be possible to capture traffic.\n"
2348         "Report this to the Wireshark developers.",
2349         init_progfile_dir_error);
2350     g_free(init_progfile_dir_error);
2351   }
2352
2353   splash_update(splash_win, "Init dissectors ...");
2354
2355   /* Register all dissectors; we must do this before checking for the
2356      "-G" flag, as the "-G" flag dumps information registered by the
2357      dissectors, and we must do it before we read the preferences, in
2358      case any dissectors register preferences. */
2359   epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
2360             failure_alert_box,open_failure_alert_box,read_failure_alert_box);
2361
2362   splash_update(splash_win, "Init tap listeners ...");
2363
2364   /* Register all tap listeners; we do this before we parse the arguments,
2365      as the "-z" argument can specify a registered tap. */
2366
2367   /* we register the plugin taps before the other taps because
2368           stats_tree taps plugins will be registered as tap listeners
2369           by stats_tree_stat.c and need to registered before that */
2370
2371 #ifdef HAVE_PLUGINS
2372   register_all_plugin_tap_listeners();
2373 #endif
2374
2375   register_all_tap_listeners();
2376
2377   splash_update(splash_win, "Loading module preferences ...");
2378
2379   /* Now register the preferences for any non-dissector modules.
2380      We must do that before we read the preferences as well. */
2381   prefs_register_modules();
2382
2383   /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2384 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
2385   {
2386       GThread *ut;
2387       g_thread_init(NULL);
2388       gdk_threads_init();
2389       ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2390       g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2391   }
2392 #else  /* _WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
2393   /* this is to keep tap extensions updating once every 3 seconds */
2394   gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
2395 #endif /* !_WIN32 && GTK2 && G_THREADS_ENABLED */
2396
2397 #if HAVE_GNU_ADNS
2398   gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
2399 #endif
2400
2401   splash_update(splash_win, "Loading configuration files ...");
2402
2403   /* Read the preference files. */
2404   prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
2405                      &pf_open_errno, &pf_read_errno, &pf_path);
2406
2407   if (gpf_path != NULL) {
2408     if (gpf_open_errno != 0) {
2409       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2410         "Could not open global preferences file\n\"%s\": %s.", gpf_path,
2411         strerror(gpf_open_errno));
2412     }
2413     if (gpf_read_errno != 0) {
2414       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2415         "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
2416         strerror(gpf_read_errno));
2417     }
2418   }
2419   if (pf_path != NULL) {
2420     if (pf_open_errno != 0) {
2421       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2422         "Could not open your preferences file\n\"%s\": %s.", pf_path,
2423         strerror(pf_open_errno));
2424     }
2425     if (pf_read_errno != 0) {
2426       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2427         "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
2428         strerror(pf_read_errno));
2429     }
2430     g_free(pf_path);
2431     pf_path = NULL;
2432   }
2433
2434 #ifdef _WIN32
2435   /* if the user wants a console to be always there, well, we should open one for him */
2436   if (prefs->gui_console_open == console_open_always) {
2437     create_console();
2438   }
2439 #endif
2440
2441   /* Fill in capture options with values from the preferences */
2442   prefs_to_capture_opts();
2443
2444   /* Read the capture filter file. */
2445   read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
2446   if (cf_path != NULL) {
2447       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2448         "Could not open your capture filter file\n\"%s\": %s.", cf_path,
2449         strerror(cf_open_errno));
2450       g_free(cf_path);
2451   }
2452
2453   /* Read the display filter file. */
2454   read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
2455   if (df_path != NULL) {
2456       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2457         "Could not open your display filter file\n\"%s\": %s.", df_path,
2458         strerror(df_open_errno));
2459       g_free(df_path);
2460   }
2461
2462   /* Read the disabled protocols file. */
2463   read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
2464                             &dp_path, &dp_open_errno, &dp_read_errno);
2465   if (gdp_path != NULL) {
2466     if (gdp_open_errno != 0) {
2467       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2468         "Could not open global disabled protocols file\n\"%s\": %s.",
2469         gdp_path, strerror(gdp_open_errno));
2470     }
2471     if (gdp_read_errno != 0) {
2472       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2473         "I/O error reading global disabled protocols file\n\"%s\": %s.",
2474         gdp_path, strerror(gdp_read_errno));
2475     }
2476     g_free(gdp_path);
2477   }
2478   if (dp_path != NULL) {
2479     if (dp_open_errno != 0) {
2480       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2481         "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
2482         strerror(dp_open_errno));
2483     }
2484     if (dp_read_errno != 0) {
2485       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2486         "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
2487         strerror(dp_read_errno));
2488     }
2489     g_free(dp_path);
2490   }
2491
2492   /* Read the (static part) of the recent file. Only the static part of it will be read, */
2493   /* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
2494   /* We have to do this already here, so command line parameters can overwrite these values. */
2495   recent_read_static(&rf_path, &rf_open_errno);
2496
2497   init_cap_file(&cfile);
2498
2499   /* Now get our args */
2500   while ((opt = getopt(argc, argv, optstring)) != -1) {
2501     switch (opt) {
2502       /*** capture option specific ***/
2503       case 'a':        /* autostop criteria */
2504       case 'b':        /* Ringbuffer option */
2505       case 'c':        /* Capture xxx packets */
2506       case 'f':        /* capture filter */
2507       case 'k':        /* Start capture immediately */
2508       case 'H':        /* Hide capture info dialog box */
2509       case 'i':        /* Use interface xxx */
2510       case 'p':        /* Don't capture in promiscuous mode */
2511       case 'Q':        /* Quit after capture (just capture to file) */
2512       case 's':        /* Set the snapshot (capture) length */
2513       case 'S':        /* "Sync" mode: used for following file ala tail -f */
2514       case 'w':        /* Write to capture file xxx */
2515       case 'y':        /* Set the pcap data link type */
2516 #ifdef _WIN32
2517       case 'B':        /* Buffer size */
2518 #endif /* _WIN32 */
2519 #ifdef HAVE_LIBPCAP
2520         status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
2521         if(status != 0) {
2522             exit(status);
2523         }
2524 #else
2525         capture_option_specified = TRUE;
2526         arg_error = TRUE;
2527 #endif
2528         break;
2529
2530       /*** all non capture option specific ***/
2531       case 'D':        /* Print a list of capture devices and exit */
2532 #ifdef HAVE_LIBPCAP
2533         capture_opts_list_interfaces();
2534         exit(0);
2535 #else
2536         capture_option_specified = TRUE;
2537         arg_error = TRUE;
2538 #endif
2539         break;
2540       case 'g':        /* Go to packet */
2541         go_to_packet = get_positive_int(optarg, "go to packet");
2542         break;
2543       case 'l':        /* Automatic scrolling in live capture mode */
2544 #ifdef HAVE_LIBPCAP
2545         auto_scroll_live = TRUE;
2546 #else
2547         capture_option_specified = TRUE;
2548         arg_error = TRUE;
2549 #endif
2550         break;
2551       case 'L':        /* Print list of link-layer types and exit */
2552 #ifdef HAVE_LIBPCAP
2553         list_link_layer_types = TRUE;
2554 #else
2555         capture_option_specified = TRUE;
2556         arg_error = TRUE;
2557 #endif
2558         break;
2559       case 'm':        /* Fixed-width font for the display */
2560         if (prefs->PREFS_GUI_FONT_NAME != NULL)
2561           g_free(prefs->PREFS_GUI_FONT_NAME);
2562         prefs->PREFS_GUI_FONT_NAME = g_strdup(optarg);
2563         break;
2564       case 'n':        /* No name resolution */
2565         g_resolv_flags = RESOLV_NONE;
2566         break;
2567       case 'N':        /* Select what types of addresses/port #s to resolve */
2568         if (g_resolv_flags == RESOLV_ALL)
2569           g_resolv_flags = RESOLV_NONE;
2570         badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2571         if (badopt != '\0') {
2572           cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2573                         badopt);
2574           exit(1);
2575         }
2576         break;
2577       case 'o':        /* Override preference from command line */
2578         switch (prefs_set_pref(optarg)) {
2579         case PREFS_SET_OK:
2580           break;
2581         case PREFS_SET_SYNTAX_ERR:
2582           cmdarg_err("Invalid -o flag \"%s\"", optarg);
2583           exit(1);
2584           break;
2585         case PREFS_SET_NO_SUCH_PREF:
2586           /* not a preference, might be a recent setting */
2587           switch (recent_set_arg(optarg)) {
2588             case PREFS_SET_OK:
2589               break;
2590             case PREFS_SET_SYNTAX_ERR:
2591               /* shouldn't happen, checked already above */
2592               cmdarg_err("Invalid -o flag \"%s\"", optarg);
2593               exit(1);
2594               break;
2595             case PREFS_SET_NO_SUCH_PREF:
2596             case PREFS_SET_OBSOLETE:
2597               cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2598                     optarg);
2599               exit(1);
2600               break;
2601             default:
2602               g_assert_not_reached();
2603             }
2604           break;
2605         case PREFS_SET_OBSOLETE:
2606           cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2607                         optarg);
2608           exit(1);
2609           break;
2610         default:
2611           g_assert_not_reached();
2612         }
2613         break;
2614       case 'r':        /* Read capture file xxx */
2615         /* We may set "last_open_dir" to "cf_name", and if we change
2616            "last_open_dir" later, we free the old value, so we have to
2617            set "cf_name" to something that's been allocated. */
2618 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2619         /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2620         cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2621 #else
2622         cf_name = g_strdup(optarg);
2623 #endif
2624         break;
2625       case 'R':        /* Read file filter */
2626         rfilter = optarg;
2627         break;
2628       case 't':        /* Time stamp type */
2629         if (strcmp(optarg, "r") == 0)
2630           timestamp_set_type(TS_RELATIVE);
2631         else if (strcmp(optarg, "a") == 0)
2632           timestamp_set_type(TS_ABSOLUTE);
2633         else if (strcmp(optarg, "ad") == 0)
2634           timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2635         else if (strcmp(optarg, "d") == 0)
2636           timestamp_set_type(TS_DELTA);
2637         else if (strcmp(optarg, "e") == 0)
2638           timestamp_set_type(TS_EPOCH);
2639         else {
2640           cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2641           cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2642           cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2643           exit(1);
2644         }
2645         break;
2646       case 'X':
2647           /* ext ops were already processed just ignore them this time*/
2648           break;
2649       case 'z':
2650         /* We won't call the init function for the stat this soon
2651            as it would disallow MATE's fields (which are registered
2652            by the preferences set callback) from being used as
2653            part of a tap filter.  Instead, we just add the argument
2654            to a list of stat arguments. */
2655         if (!process_stat_cmd_arg(optarg)) {
2656           cmdarg_err("Invalid -z argument.");
2657           cmdarg_err_cont("  -z argument must be one of :");
2658           list_stat_cmd_args();
2659           exit(1);
2660         }
2661         break;
2662       default:
2663       case '?':        /* Bad flag - print usage message */
2664         arg_error = TRUE;
2665         break;
2666     }
2667   }
2668   argc -= optind;
2669   argv += optind;
2670   if (argc >= 1) {
2671     if (cf_name != NULL) {
2672       /*
2673        * Input file name specified with "-r" *and* specified as a regular
2674        * command-line argument.
2675        */
2676       cmdarg_err("File name specified both with -r and regular argument");
2677       arg_error = TRUE;
2678     } else {
2679       /*
2680        * Input file name not specified with "-r", and a command-line argument
2681        * was specified; treat it as the input file name.
2682        *
2683        * Yes, this is different from tshark, where non-flag command-line
2684        * arguments are a filter, but this works better on GUI desktops
2685        * where a command can be specified to be run to open a particular
2686        * file - yes, you could have "-r" as the last part of the command,
2687        * but that's a bit ugly.
2688        */
2689 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2690       /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2691       cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2692 #else
2693       cf_name = g_strdup(argv[0]);
2694 #endif
2695     }
2696     argc--;
2697     argv++;
2698   }
2699
2700
2701
2702   if (argc != 0) {
2703     /*
2704      * Extra command line arguments were specified; complain.
2705      */
2706     cmdarg_err("Invalid argument: %s", argv[0]);
2707     arg_error = TRUE;
2708   }
2709
2710   if (arg_error) {
2711 #ifndef HAVE_LIBPCAP
2712     if (capture_option_specified) {
2713       cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2714     }
2715 #endif
2716     print_usage(FALSE);
2717     exit(1);
2718   }
2719
2720 #ifdef HAVE_LIBPCAP
2721   if (start_capture && list_link_layer_types) {
2722     /* Specifying *both* is bogus. */
2723     cmdarg_err("You can't specify both -L and a live capture.");
2724     exit(1);
2725   }
2726
2727   if (list_link_layer_types) {
2728     /* We're supposed to list the link-layer types for an interface;
2729        did the user also specify a capture file to be read? */
2730     if (cf_name) {
2731       /* Yes - that's bogus. */
2732       cmdarg_err("You can't specify -L and a capture file to be read.");
2733       exit(1);
2734     }
2735     /* No - did they specify a ring buffer option? */
2736     if (capture_opts->multi_files_on) {
2737       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2738       exit(1);
2739     }
2740   } else {
2741     /* We're supposed to do a live capture; did the user also specify
2742        a capture file to be read? */
2743     if (start_capture && cf_name) {
2744       /* Yes - that's bogus. */
2745       cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2746       exit(1);
2747     }
2748
2749     /* No - was the ring buffer option specified and, if so, does it make
2750        sense? */
2751     if (capture_opts->multi_files_on) {
2752       /* Ring buffer works only under certain conditions:
2753          a) ring buffer does not work with temporary files;
2754          b) real_time_mode and multi_files_on are mutually exclusive -
2755             real_time_mode takes precedence;
2756          c) it makes no sense to enable the ring buffer if the maximum
2757             file size is set to "infinite". */
2758       if (capture_opts->save_file == NULL) {
2759         cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2760         capture_opts->multi_files_on = FALSE;
2761       }
2762 /*      if (capture_opts->real_time_mode) {
2763         cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2764         capture_opts->multi_files_on = FALSE;
2765       }*/
2766       if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
2767         cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2768 /* XXX - this must be redesigned as the conditions changed */
2769 /*      capture_opts->multi_files_on = FALSE;*/
2770       }
2771     }
2772   }
2773
2774   if (start_capture || list_link_layer_types) {
2775     /* Did the user specify an interface to use? */
2776     if (!capture_opts_trim_iface(capture_opts,
2777         (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
2778         exit(2);
2779     }
2780   }
2781
2782   if (list_link_layer_types) {
2783     status = capture_opts_list_link_layer_types(capture_opts);
2784     exit(status);
2785   }
2786
2787   capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
2788   capture_opts_trim_ring_num_files(capture_opts);
2789 #endif /* HAVE_LIBPCAP */
2790
2791   /* Notify all registered modules that have had any of their preferences
2792      changed either from one of the preferences file or from the command
2793      line that their preferences have changed. */
2794   prefs_apply_all();
2795
2796   /* disabled protocols as per configuration file */
2797   if (gdp_path == NULL && dp_path == NULL) {
2798     set_disabled_protos_list();
2799   }
2800
2801   /* Build the column format array */
2802   col_setup(&cfile.cinfo, prefs->num_cols);
2803   for (i = 0; i < cfile.cinfo.num_cols; i++) {
2804     cfile.cinfo.col_fmt[i] = get_column_format(i);
2805     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
2806     cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
2807       NUM_COL_FMTS);
2808     get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
2809     cfile.cinfo.col_data[i] = NULL;
2810     if (cfile.cinfo.col_fmt[i] == COL_INFO)
2811       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
2812     else
2813       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2814     cfile.cinfo.col_fence[i] = 0;
2815     cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2816     cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
2817   }
2818
2819   for (i = 0; i < cfile.cinfo.num_cols; i++) {
2820       int j;
2821
2822       for (j = 0; j < NUM_COL_FMTS; j++) {
2823          if (!cfile.cinfo.fmt_matx[i][j])
2824              continue;
2825
2826          if (cfile.cinfo.col_first[j] == -1)
2827              cfile.cinfo.col_first[j] = i;
2828          cfile.cinfo.col_last[j] = i;
2829       }
2830   }
2831
2832   /* read in rc file from global and personal configuration paths. */
2833   rc_file = get_datafile_path(RC_FILE);
2834   gtk_rc_parse(rc_file);
2835   rc_file = get_persconffile_path(RC_FILE, FALSE);
2836   gtk_rc_parse(rc_file);
2837
2838   font_init();
2839
2840   /* close the splash screen, as we are going to open the main window now */
2841   splash_destroy(splash_win);
2842
2843   /************************************************************************/
2844   /* Everything is prepared now, preferences and command line was read in */
2845
2846   /* Pop up the main window. */
2847   create_main_window(pl_size, tv_size, bv_size, prefs);
2848
2849   /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2850   recent_read_dynamic(&rf_path, &rf_open_errno);
2851   color_filters_enable(recent.packet_list_colorize);
2852
2853   /* rearrange all the widgets as we now have all recent settings ready for this */
2854   main_widgets_rearrange();
2855
2856   /* Fill in column titles.  This must be done after the top level window
2857      is displayed.
2858
2859      XXX - is that still true, with fixed-width columns? */
2860   packet_list_set_column_titles();
2861
2862   menu_recent_read_finished();
2863
2864   switch (user_font_apply()) {
2865   case FA_SUCCESS:
2866       break;
2867   case FA_FONT_NOT_RESIZEABLE:
2868       /* "user_font_apply()" popped up an alert box. */
2869       /* turn off zooming - font can't be resized */
2870   case FA_FONT_NOT_AVAILABLE:
2871       /* XXX - did we successfully load the un-zoomed version earlier?
2872       If so, this *probably* means the font is available, but not at
2873       this particular zoom level, but perhaps some other failure
2874       occurred; I'm not sure you can determine which is the case,
2875       however. */
2876       /* turn off zooming - zoom level is unavailable */
2877   default:
2878       /* in any other case than FA_SUCCESS, turn off zooming */
2879       recent.gui_zoom_level = 0;
2880       /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2881   }
2882
2883   dnd_init(top_level);
2884
2885   colors_init();
2886   color_filters_init();
2887   decode_as_init();
2888
2889   /* the window can be sized only, if it's not already shown, so do it now! */
2890   main_load_window_geometry(top_level);
2891
2892   /* If we were given the name of a capture file, read it in now;
2893      we defer it until now, so that, if we can't open it, and pop
2894      up an alert box, the alert box is more likely to come up on
2895      top of the main window - but before the preference-file-error
2896      alert box, so, if we get one of those, it's more likely to come
2897      up on top of us. */
2898   if (cf_name) {
2899     show_main_window(TRUE);
2900     if (rfilter != NULL) {
2901       if (!dfilter_compile(rfilter, &rfcode)) {
2902         bad_dfilter_alert_box(rfilter);
2903         rfilter_parse_failed = TRUE;
2904       }
2905     }
2906     if (!rfilter_parse_failed) {
2907       if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2908         /* "cf_open()" succeeded, so it closed the previous
2909            capture file, and thus destroyed any previous read filter
2910            attached to "cf". */
2911
2912         cfile.rfcode = rfcode;
2913         /* Open stat windows; we do so after creating the main window,
2914            to avoid GTK warnings, and after successfully opening the
2915            capture file, so we know we have something to compute stats
2916            on, and after registering all dissectors, so that MATE will
2917            have registered its field array and we can have a tap filter
2918            with one of MATE's late-registered fields as part of the
2919            filter. */
2920         start_requested_stats();
2921
2922         /* Read the capture file. */
2923         switch (cf_read(&cfile)) {
2924
2925         case CF_READ_OK:
2926         case CF_READ_ERROR:
2927           /* Just because we got an error, that doesn't mean we were unable
2928              to read any of the file; we handle what we could get from the
2929              file. */
2930           /* if the user told us to jump to a specific packet, do it now */
2931           if(go_to_packet != 0) {
2932             cf_goto_frame(&cfile, go_to_packet);
2933           }
2934           break;
2935
2936         case CF_READ_ABORTED:
2937           /* Exit now. */
2938           gtk_exit(0);
2939           break;
2940         }
2941         /* Save the name of the containing directory specified in the
2942            path name, if any; we can write over cf_name, which is a
2943            good thing, given that "get_dirname()" does write over its
2944            argument. */
2945         s = get_dirname(cf_name);
2946         /* we might already set this from the recent file, don't overwrite this */
2947         if(get_last_open_dir() == NULL)
2948           set_last_open_dir(s);
2949         g_free(cf_name);
2950         cf_name = NULL;
2951       } else {
2952         if (rfcode != NULL)
2953           dfilter_free(rfcode);
2954         cfile.rfcode = NULL;
2955     show_main_window(FALSE);
2956         set_menus_for_capture_in_progress(FALSE);
2957       }
2958     }
2959   } else {
2960 #ifdef HAVE_LIBPCAP
2961     if (start_capture) {
2962       if (capture_opts->save_file != NULL) {
2963         /* Save the directory name for future file dialogs. */
2964         /* (get_dirname overwrites filename) */
2965         s = get_dirname(g_strdup(capture_opts->save_file));
2966         set_last_open_dir(s);
2967         g_free(s);
2968       }
2969       /* "-k" was specified; start a capture. */
2970       show_main_window(TRUE);
2971       if (capture_start(capture_opts)) {
2972         /* The capture started.  Open stat windows; we do so after creating
2973            the main window, to avoid GTK warnings, and after successfully
2974            opening the capture file, so we know we have something to compute
2975            stats on, and after registering all dissectors, so that MATE will
2976            have registered its field array and we can have a tap filter with
2977            one of MATE's late-registered fields as part of the filter. */
2978         start_requested_stats();
2979       }
2980     }
2981     else {
2982       show_main_window(FALSE);
2983       set_menus_for_capture_in_progress(FALSE);
2984     }
2985
2986     /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2987     if (!start_capture && strlen(capture_opts->cfilter) == 0) {
2988       g_free(capture_opts->cfilter);
2989       capture_opts->cfilter = g_strdup(get_conn_cfilter());
2990     }
2991 #else /* HAVE_LIBPCAP */
2992     show_main_window(FALSE);
2993     set_menus_for_capture_in_progress(FALSE);
2994 #endif /* HAVE_LIBPCAP */
2995   }
2996
2997   /* register our pid if we are being run from a U3 device */
2998   u3_register_pid();
2999
3000   /* we'll enter the GTK loop now and hand the control over to GTK ... */
3001   gtk_main();
3002   /* ... back from GTK, we're going down now! */
3003
3004   /* deregister our pid */
3005   u3_deregister_pid();
3006
3007   epan_cleanup();
3008   g_free(rc_file);
3009
3010 #ifdef  HAVE_AIRPDCAP
3011         /*      Davide Schiera (2006-11-18): destroy AirPDcap context                                                   */
3012         AirPDcapDestroyContext(&airpdcap_ctx);
3013         /* Davide Schiera (2006-11-18) -------------------------------------------      */
3014 #endif
3015
3016 #ifdef _WIN32
3017   /* hide the (unresponsive) main window, while asking the user to close the console window */
3018   gtk_widget_hide(top_level);
3019
3020   /* Shutdown windows sockets */
3021   WSACleanup();
3022
3023   /* For some unknown reason, the "atexit()" call in "create_console()"
3024      doesn't arrange that "destroy_console()" be called when we exit,
3025      so we call it here if a console was created. */
3026   destroy_console();
3027 #endif
3028
3029   gtk_exit(0);
3030
3031   /* This isn't reached, but we need it to keep GCC from complaining
3032      that "main()" returns without returning a value - it knows that
3033      "exit()" never returns, but it doesn't know that "gtk_exit()"
3034      doesn't, as GTK+ doesn't declare it with the attribute
3035      "noreturn". */
3036   return 0;     /* not reached */
3037 }
3038
3039 #ifdef _WIN32
3040
3041 /* We build this as a GUI subsystem application on Win32, so
3042    "WinMain()", not "main()", gets called.
3043
3044    Hack shamelessly stolen from the Win32 port of the GIMP. */
3045 #ifdef __GNUC__
3046 #define _stdcall  __attribute__((stdcall))
3047 #endif
3048
3049 int _stdcall
3050 WinMain (struct HINSTANCE__ *hInstance,
3051          struct HINSTANCE__ *hPrevInstance,
3052          char               *lpszCmdLine,
3053          int                 nCmdShow)
3054 {
3055 #if GTK_MAJOR_VERSION >= 2
3056   INITCOMMONCONTROLSEX comm_ctrl;
3057
3058   /* Initialize our controls. Required for native Windows file dialogs. */
3059   memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3060   comm_ctrl.dwSize = sizeof(comm_ctrl);
3061   /* Includes the animate, header, hot key, list view, progress bar,
3062    * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3063    * up-down controls
3064    */
3065   comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3066   InitCommonControlsEx(&comm_ctrl);
3067
3068   /* RichEd20.DLL is needed for filter entries. */
3069   LoadLibrary(_T("riched20.dll"));
3070 #endif /* GTK_MAJOR_VERSION >= 2 */
3071
3072   has_console = FALSE;
3073   return main (__argc, __argv);
3074 }
3075
3076 /*
3077  * If this application has no console window to which its standard output
3078  * would go, create one.
3079  */
3080 void
3081 create_console(void)
3082 {
3083   if (!has_console) {
3084     /* We have no console to which to print the version string, so
3085        create one and make it the standard input, output, and error. */
3086     if (!AllocConsole())
3087       return;   /* couldn't create console */
3088     eth_freopen("CONIN$", "r", stdin);
3089     eth_freopen("CONOUT$", "w", stdout);
3090     eth_freopen("CONOUT$", "w", stderr);
3091
3092     /* Well, we have a console now. */
3093     has_console = TRUE;
3094
3095     /* Now register "destroy_console()" as a routine to be called just
3096        before the application exits, so that we can destroy the console
3097        after the user has typed a key (so that the console doesn't just
3098        disappear out from under them, giving the user no chance to see
3099        the message(s) we put in there). */
3100     atexit(destroy_console);
3101
3102     SetConsoleTitle(_T("Wireshark Debug Console"));
3103   }
3104 }
3105
3106 static void
3107 destroy_console(void)
3108 {
3109   if (has_console) {
3110     printf("\n\nPress any key to exit\n");
3111     _getch();
3112     FreeConsole();
3113   }
3114 }
3115 #endif /* _WIN32 */
3116
3117
3118 /* This routine should not be necessary, at least as I read the GLib
3119    source code, as it looks as if GLib is, on Win32, *supposed* to
3120    create a console window into which to display its output.
3121
3122    That doesn't happen, however.  I suspect there's something completely
3123    broken about that code in GLib-for-Win32, and that it may be related
3124    to the breakage that forces us to just call "printf()" on the message
3125    rather than passing the message on to "g_log_default_handler()"
3126    (which is the routine that does the aforementioned non-functional
3127    console window creation). */
3128 static void
3129 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3130                     const char *message, gpointer user_data _U_)
3131 {
3132   time_t curr;
3133   struct tm *today;
3134   const char *level;
3135
3136
3137   /* ignore log message, if log_level isn't interesting.
3138      If preferences aren't loaded yet, display message anyway */
3139   if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3140      prefs.console_log_level != 0) {
3141     return;
3142   }
3143
3144   /* create a "timestamp" */
3145   time(&curr);
3146   today = localtime(&curr);
3147
3148 #ifdef _WIN32
3149   if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3150     /* the user wants a console or the application will terminate immediately */
3151     create_console();
3152   }
3153   if (has_console) {
3154     /* For some unknown reason, the above doesn't appear to actually cause
3155        anything to be sent to the standard output, so we'll just splat the
3156        message out directly, just to make sure it gets out. */
3157 #endif
3158     switch(log_level & G_LOG_LEVEL_MASK) {
3159     case G_LOG_LEVEL_ERROR:
3160         level = "Err ";
3161         break;
3162     case G_LOG_LEVEL_CRITICAL:
3163         level = "Crit";
3164         break;
3165     case G_LOG_LEVEL_WARNING:
3166         level = "Warn";
3167         break;
3168     case G_LOG_LEVEL_MESSAGE:
3169         level = "Msg ";
3170         break;
3171     case G_LOG_LEVEL_INFO:
3172         level = "Info";
3173         break;
3174     case G_LOG_LEVEL_DEBUG:
3175         level = "Dbg ";
3176         break;
3177     default:
3178         fprintf(stderr, "unknown log_level %u\n", log_level);
3179         level = NULL;
3180         g_assert_not_reached();
3181     }
3182
3183     fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3184             today->tm_hour, today->tm_min, today->tm_sec,
3185             log_domain != NULL ? log_domain : "",
3186             level, message);
3187 #ifdef _WIN32
3188     if(log_level & G_LOG_LEVEL_ERROR) {
3189         /* wait for a key press before the following error handler will terminate the program
3190            this way the user at least can read the error message */
3191         printf("\n\nPress any key to exit\n");
3192         _getch();
3193     }
3194   } else {
3195     g_log_default_handler(log_domain, log_level, message, user_data);
3196   }
3197 #endif
3198 }
3199
3200
3201 static GtkWidget *info_bar_new(void)
3202 {
3203     /* tip: tooltips don't work on statusbars! */
3204     info_bar = gtk_statusbar_new();
3205     main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
3206     file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
3207     help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
3208 #if GTK_MAJOR_VERSION >= 2
3209     gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
3210 #endif
3211     gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
3212
3213     return info_bar;
3214 }
3215
3216 static GtkWidget *packets_bar_new(void)
3217 {
3218     /* tip: tooltips don't work on statusbars! */
3219     packets_bar = gtk_statusbar_new();
3220     packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
3221     packets_bar_update();
3222
3223     return packets_bar;
3224 }
3225
3226
3227 /*
3228  * Helper for main_widgets_rearrange()
3229  */
3230 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3231     gtk_container_remove(GTK_CONTAINER(data), widget);
3232 }
3233
3234 static GtkWidget *main_widget_layout(gint layout_content)
3235 {
3236     switch(layout_content) {
3237     case(layout_pane_content_none):
3238         return NULL;
3239         break;
3240     case(layout_pane_content_plist):
3241         return pkt_scrollw;
3242         break;
3243     case(layout_pane_content_pdetails):
3244         return tv_scrollw;
3245         break;
3246     case(layout_pane_content_pbytes):
3247         return byte_nb_ptr;
3248         break;
3249     default:
3250         g_assert_not_reached();
3251         return NULL;
3252     }
3253 }
3254
3255
3256 /*
3257  * Rearrange the main window widgets
3258  */
3259 void main_widgets_rearrange(void) {
3260     GtkWidget *first_pane_widget1, *first_pane_widget2;
3261     GtkWidget *second_pane_widget1, *second_pane_widget2;
3262     gboolean split_top_left;
3263
3264     /* be a bit faster */
3265     gtk_widget_hide(main_vbox);
3266
3267     /* be sure, we don't loose a widget while rearranging */
3268     gtk_widget_ref(menubar);
3269     gtk_widget_ref(main_tb);
3270     gtk_widget_ref(filter_tb);
3271
3272 #ifdef HAVE_AIRPCAP
3273     gtk_widget_ref(airpcap_tb);
3274 #endif
3275
3276     gtk_widget_ref(pkt_scrollw);
3277     gtk_widget_ref(tv_scrollw);
3278     gtk_widget_ref(byte_nb_ptr);
3279     gtk_widget_ref(stat_hbox);
3280     gtk_widget_ref(info_bar);
3281     gtk_widget_ref(packets_bar);
3282     gtk_widget_ref(status_pane);
3283     gtk_widget_ref(main_pane_v1);
3284     gtk_widget_ref(main_pane_v2);
3285     gtk_widget_ref(main_pane_h1);
3286     gtk_widget_ref(main_pane_h2);
3287     gtk_widget_ref(welcome_pane);
3288
3289     /* empty all containers participating */
3290     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
3291     gtk_container_foreach(GTK_CONTAINER(stat_hbox),     foreach_remove_a_child, stat_hbox);
3292     gtk_container_foreach(GTK_CONTAINER(status_pane),   foreach_remove_a_child, status_pane);
3293     gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
3294     gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
3295     gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
3296     gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
3297
3298     /* add the menubar always at the top */
3299     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3300
3301     /* main toolbar */
3302     gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3303
3304     /* filter toolbar in toolbar area */
3305     if (!prefs.filter_toolbar_show_in_statusbar) {
3306         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3307     }
3308
3309 #ifdef HAVE_AIRPCAP
3310     /* airpcap toolbar */
3311     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3312 #endif
3313
3314     /* fill the main layout panes */
3315     switch(prefs.gui_layout_type) {
3316     case(layout_type_5):
3317         main_first_pane  = main_pane_v1;
3318         main_second_pane = main_pane_v2;
3319         split_top_left = FALSE;
3320         break;
3321     case(layout_type_2):
3322         main_first_pane  = main_pane_v1;
3323         main_second_pane = main_pane_h1;
3324         split_top_left = FALSE;
3325         break;
3326     case(layout_type_1):
3327         main_first_pane  = main_pane_v1;
3328         main_second_pane = main_pane_h1;
3329         split_top_left = TRUE;
3330         break;
3331     case(layout_type_4):
3332         main_first_pane  = main_pane_h1;
3333         main_second_pane = main_pane_v1;
3334         split_top_left = FALSE;
3335         break;
3336     case(layout_type_3):
3337         main_first_pane  = main_pane_h1;
3338         main_second_pane = main_pane_v1;
3339         split_top_left = TRUE;
3340         break;
3341     case(layout_type_6):
3342         main_first_pane  = main_pane_h1;
3343         main_second_pane = main_pane_h2;
3344         split_top_left = FALSE;
3345         break;
3346     default:
3347         main_first_pane = NULL;
3348         main_second_pane = NULL;
3349         split_top_left = FALSE;
3350         g_assert_not_reached();
3351     }
3352     if (split_top_left) {
3353         first_pane_widget1 = main_second_pane;
3354         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3355         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3356         first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3357     } else {
3358         first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3359         first_pane_widget2 = main_second_pane;
3360         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3361         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3362     }
3363     if (first_pane_widget1 != NULL)
3364         gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3365     if (first_pane_widget2 != NULL)
3366         gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3367     if (second_pane_widget1 != NULL)
3368         gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3369     if (second_pane_widget2 != NULL)
3370         gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3371
3372     gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3373
3374     /* welcome pane */
3375     gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3376
3377     /* statusbar hbox */
3378     gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
3379
3380     /* filter toolbar in statusbar hbox */
3381     if (prefs.filter_toolbar_show_in_statusbar) {
3382         gtk_box_pack_start(GTK_BOX(stat_hbox), filter_tb, FALSE, TRUE, 1);
3383     }
3384
3385 #ifdef HAVE_AIRPCAP
3386     /* airpcap toolbar */
3387     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3388 #endif
3389
3390     /* statusbar */
3391     gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane, TRUE, TRUE, 0);
3392     gtk_paned_pack1(GTK_PANED(status_pane), info_bar, FALSE, FALSE);
3393     gtk_paned_pack2(GTK_PANED(status_pane), packets_bar, FALSE, FALSE);
3394
3395     /* hide widgets on users recent settings */
3396     main_widgets_show_or_hide();
3397
3398     gtk_widget_show(main_vbox);
3399 }
3400
3401 static void
3402 is_widget_visible(GtkWidget *widget, gpointer data)
3403 {
3404     gboolean *is_visible = data;
3405
3406     if (!*is_visible) {
3407         if (GTK_WIDGET_VISIBLE(widget))
3408             *is_visible = TRUE;
3409     }
3410 }
3411
3412
3413 #ifdef SHOW_WELCOME_PAGE
3414 /* XXX - There seems to be some disagreement about if and how this feature should be implemented.
3415    As I currently don't have the time to continue this, it's temporarily disabled. - ULFL */
3416 GtkWidget *
3417 welcome_item(gchar *stock_item, gchar * label, gchar * message, GtkSignalFunc callback, void *callback_data)
3418 {
3419     GtkWidget *w, *item_hb;
3420 #if GTK_MAJOR_VERSION >= 2
3421     gchar *formatted_message;
3422 #endif
3423
3424
3425     item_hb = gtk_hbox_new(FALSE, 1);
3426
3427     w = BUTTON_NEW_FROM_STOCK(stock_item);
3428     WIDGET_SET_SIZE(w, 60, 60);
3429 #if GTK_MAJOR_VERSION >= 2
3430     gtk_button_set_label(GTK_BUTTON(w), label);
3431 #endif
3432     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 0);
3433     SIGNAL_CONNECT(w, "clicked", callback, callback_data);
3434
3435     w = gtk_label_new(message);
3436         gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3437 #if GTK_MAJOR_VERSION >= 2
3438     formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", message);
3439     gtk_label_set_markup(GTK_LABEL(w), formatted_message);
3440     g_free(formatted_message);
3441 #endif
3442
3443     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 10);
3444
3445     return item_hb;
3446 }
3447
3448
3449 /* XXX - the layout has to be improved */
3450 GtkWidget *
3451 welcome_new(void)
3452 {
3453     GtkWidget *welcome_scrollw, *welcome_hb, *welcome_vb, *item_hb;
3454     GtkWidget *w, *icon;
3455     gchar * message;
3456
3457
3458     welcome_scrollw = scrolled_window_new(NULL, NULL);
3459
3460     welcome_hb = gtk_hbox_new(FALSE, 1);
3461         /*gtk_container_border_width(GTK_CONTAINER(welcome_hb), 20);*/
3462
3463     welcome_vb = gtk_vbox_new(FALSE, 1);
3464
3465     item_hb = gtk_hbox_new(FALSE, 1);
3466
3467     icon = xpm_to_widget_from_parent(top_level, wsicon64_xpm);
3468     gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 5);
3469
3470 #if GTK_MAJOR_VERSION < 2
3471     message = "Welcome to Wireshark!";
3472 #else
3473     message = "<span weight=\"bold\" size=\"25000\">" "Welcome to Wireshark!" "</span>";
3474 #endif
3475     w = gtk_label_new(message);
3476 #if GTK_MAJOR_VERSION >= 2
3477     gtk_label_set_markup(GTK_LABEL(w), message);
3478 #endif
3479     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3480     gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
3481
3482     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3483
3484     w = gtk_label_new("What would you like to do?");
3485     gtk_box_pack_start(GTK_BOX(welcome_vb), w, FALSE, FALSE, 10);
3486     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
3487
3488 #ifdef HAVE_LIBPCAP
3489     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
3490         "Capture",
3491         "Capture live data from your network",
3492         GTK_SIGNAL_FUNC(capture_prep_cb), NULL);
3493     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3494 #endif
3495
3496     item_hb = welcome_item(GTK_STOCK_OPEN,
3497         "Open",
3498         "Open a previously captured file",
3499         GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
3500     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3501
3502 #if (GLIB_MAJOR_VERSION >= 2)
3503     item_hb = welcome_item(GTK_STOCK_HOME,
3504         "Home",
3505         "Visit the Wireshark homepage",
3506         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
3507     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3508
3509     item_hb = welcome_item(WIRESHARK_STOCK_WEB_SUPPORT,
3510         "User's Guide",
3511         "Open the Wireshark User's Guide",
3512         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
3513     gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
3514 #endif
3515
3516     /* the end */
3517     w = gtk_label_new("");
3518     gtk_box_pack_start(GTK_BOX(welcome_vb), w, TRUE, TRUE, 0);
3519
3520     w = gtk_label_new("");
3521     gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
3522
3523     gtk_box_pack_start(GTK_BOX(welcome_hb), welcome_vb, TRUE, TRUE, 0);
3524
3525     w = gtk_label_new("");
3526     gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
3527
3528     gtk_widget_show_all(welcome_hb);
3529
3530     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
3531                                           welcome_hb);
3532     gtk_widget_show_all(welcome_scrollw);
3533
3534     return welcome_scrollw;
3535 }
3536 #else
3537 static GtkWidget *
3538 welcome_new(void)
3539 {
3540     /* this is just a dummy to fill up window space, simply showing nothing */
3541     return scrolled_window_new(NULL, NULL);
3542 }
3543 #endif
3544
3545
3546
3547 /*
3548  * XXX - this doesn't appear to work with the paned widgets in
3549  * GTK+ 1.2[.x]; if you hide one of the panes, the splitter remains
3550  * and the other pane doesn't grow to take up the rest of the pane.
3551  * It does appear to work with GTK+ 2.x.
3552  */
3553 void
3554 main_widgets_show_or_hide(void)
3555 {
3556     gboolean main_second_pane_show;
3557
3558     if (recent.main_toolbar_show) {
3559         gtk_widget_show(main_tb);
3560     } else {
3561         gtk_widget_hide(main_tb);
3562     }
3563
3564     /*
3565      * Show the status hbox if either:
3566      *
3567      *    1) we're showing the filter toolbar and we want it in the status
3568      *       line
3569      *
3570      * or
3571      *
3572      *    2) we're showing the status bar.
3573      */
3574     if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
3575          recent.statusbar_show) {
3576         gtk_widget_show(stat_hbox);
3577     } else {
3578         gtk_widget_hide(stat_hbox);
3579     }
3580
3581     if (recent.statusbar_show) {
3582         gtk_widget_show(status_pane);
3583     } else {
3584         gtk_widget_hide(status_pane);
3585     }
3586
3587     if (recent.filter_toolbar_show) {
3588         gtk_widget_show(filter_tb);
3589     } else {
3590         gtk_widget_hide(filter_tb);
3591     }
3592
3593 #ifdef HAVE_AIRPCAP
3594     if (recent.airpcap_toolbar_show) {
3595         gtk_widget_show(airpcap_tb);
3596     } else {
3597         gtk_widget_hide(airpcap_tb);
3598     }
3599 #endif
3600
3601     if (recent.packet_list_show && have_capture_file) {
3602         gtk_widget_show(pkt_scrollw);
3603     } else {
3604         gtk_widget_hide(pkt_scrollw);
3605     }
3606
3607     if (recent.tree_view_show && have_capture_file) {
3608         gtk_widget_show(tv_scrollw);
3609     } else {
3610         gtk_widget_hide(tv_scrollw);
3611     }
3612
3613     if (recent.byte_view_show && have_capture_file) {
3614         gtk_widget_show(byte_nb_ptr);
3615     } else {
3616         gtk_widget_hide(byte_nb_ptr);
3617     }
3618
3619     if (have_capture_file) {
3620         gtk_widget_show(main_first_pane);
3621     } else {
3622         gtk_widget_hide(main_first_pane);
3623     }
3624
3625     /*
3626      * Is anything in "main_second_pane" visible?
3627      * If so, show it, otherwise hide it.
3628      */
3629     main_second_pane_show = FALSE;
3630     gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3631                           &main_second_pane_show);
3632     if (main_second_pane_show) {
3633         gtk_widget_show(main_second_pane);
3634     } else {
3635         gtk_widget_hide(main_second_pane);
3636     }
3637
3638     if (!have_capture_file) {
3639         if(welcome_pane) {
3640             gtk_widget_show(welcome_pane);
3641         }
3642     } else {
3643         gtk_widget_hide(welcome_pane);
3644     }
3645
3646     /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3647     packet_list_freeze ();
3648     packet_list_thaw ();
3649 }
3650
3651
3652 #if GTK_MAJOR_VERSION >= 2
3653 /* called, when the window state changes (minimized, maximized, ...) */
3654 static int
3655 window_state_event_cb (GtkWidget *widget _U_,
3656                        GdkEvent *event,
3657                        gpointer  data _U_)
3658 {
3659     GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3660
3661     if( (event->type) == (GDK_WINDOW_STATE)) {
3662         if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3663             /* we might have dialogs popped up while we where iconified,
3664                show em now */
3665             display_queued_messages();
3666         }
3667     }
3668     return FALSE;
3669 }
3670 #endif
3671
3672 #ifdef HAVE_AIRPCAP
3673 /*
3674  * Changed callback for the channel combobox
3675  */
3676 static void
3677 airpcap_toolbar_channel_changed_cb(GtkWidget *w _U_, gpointer data)
3678 {
3679   gchar ebuf[AIRPCAP_ERRBUF_SIZE];
3680   PAirpcapHandle ad;
3681   const gchar *s;
3682   int ch_num;
3683
3684   s = gtk_entry_get_text(GTK_ENTRY(data));
3685
3686   if ((data != NULL) && (w != NULL) ) {
3687     s = gtk_entry_get_text(GTK_ENTRY(data));
3688     if ((g_strcasecmp("",s))) {
3689       sscanf(s,"%d",&ch_num);
3690       if (airpcap_if_active != NULL) {
3691         ad = airpcap_if_open(get_airpcap_name_from_description(airpcap_if_list, airpcap_if_active->description), ebuf);
3692
3693         if(ad) {
3694           airpcap_if_set_device_channel(ad,ch_num);
3695           airpcap_if_active->channel = ch_num;
3696           airpcap_if_close(ad);
3697         }
3698       }
3699     }
3700   }
3701 }
3702
3703 /*
3704  * Callback for the wrong crc combo
3705  */
3706 static void
3707 airpcap_toolbar_wrong_crc_combo_cb(GtkWidget *entry, gpointer user_data)
3708 {
3709   gchar ebuf[AIRPCAP_ERRBUF_SIZE];
3710   PAirpcapHandle ad;
3711
3712   if( !block_toolbar_signals && (airpcap_if_active != NULL)) {
3713     ad = airpcap_if_open(get_airpcap_name_from_description(airpcap_if_list,airpcap_if_active->description), ebuf);
3714
3715     if (ad) {
3716       airpcap_if_active->CrcValidationOn = airpcap_get_validation_type(gtk_entry_get_text(GTK_ENTRY(entry)));
3717       airpcap_if_set_fcs_validation(ad,airpcap_if_active->CrcValidationOn);
3718       /* Save configuration */
3719       if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
3720         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
3721       }
3722       airpcap_if_close(ad);
3723     }
3724   }
3725 }
3726
3727 void
3728 airpcap_toolbar_encryption_cb(GtkWidget *entry, gpointer user_data)
3729 {
3730   /* We need to directly access the .ddl functions here... */
3731   gchar ebuf[AIRPCAP_ERRBUF_SIZE];
3732   PAirpcapHandle ad;
3733
3734  gint n = 0;
3735   gint i = 0;
3736   airpcap_if_info_t* curr_if = NULL;
3737
3738   /* Apply changes to the current adapter */
3739   if( (airpcap_if_active != NULL)) {
3740     ad = airpcap_if_open(get_airpcap_name_from_description(airpcap_if_list,airpcap_if_active->description), ebuf);
3741
3742     if(ad) {
3743       if(airpcap_if_active->DecryptionOn == AIRPCAP_DECRYPTION_ON) {
3744         airpcap_if_active->DecryptionOn = AIRPCAP_DECRYPTION_OFF;
3745         airpcap_if_set_decryption_state(ad,airpcap_if_active->DecryptionOn);
3746         /* Save configuration */
3747         if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
3748           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
3749         }
3750         airpcap_if_close(ad);
3751       } else {
3752         airpcap_if_active->DecryptionOn = AIRPCAP_DECRYPTION_ON;
3753         airpcap_if_set_decryption_state(ad,airpcap_if_active->DecryptionOn);
3754         /* Save configuration */
3755         if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
3756           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
3757         }
3758         airpcap_if_close(ad);
3759       }
3760     }
3761   } else {
3762     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No active AirPcap Adapter selected!");
3763     return;
3764   }
3765
3766   n = g_list_length(airpcap_if_list);
3767
3768   /* The same kind of settings should be propagated to all the adapters */
3769   /* Apply this change to all the adapters !!! */
3770   for(i = 0; i < n; i++) {
3771     curr_if = (airpcap_if_info_t*)g_list_nth_data(airpcap_if_list,i);
3772
3773     if( (curr_if != NULL) && (curr_if != airpcap_if_selected) ) {
3774       ad = airpcap_if_open(get_airpcap_name_from_description(airpcap_if_list,curr_if->description), ebuf);
3775       if(ad) {
3776         curr_if->DecryptionOn = airpcap_if_selected->DecryptionOn;
3777         airpcap_if_set_decryption_state(ad,curr_if->DecryptionOn);
3778         /* Save configuration for the curr_if */
3779         if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
3780           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
3781         }
3782         airpcap_if_close(ad);
3783       }
3784     }
3785   }
3786 }
3787
3788 /*
3789  * Callback for the Advanced Wireless Settings button
3790  */
3791 static void
3792 toolbar_display_airpcap_advanced_cb(GtkWidget *w, gpointer data)
3793 {
3794     int *from_widget;
3795
3796     from_widget = (gint*)g_malloc(sizeof(gint));
3797     *from_widget = AIRPCAP_ADVANCED_FROM_TOOLBAR;
3798     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_ADVANCED_FROM_KEY,from_widget);
3799
3800     display_airpcap_advanced_cb(w,data);
3801 }
3802
3803 /*
3804  * Callback for the Decryption Key Management button
3805  */
3806 static void
3807 toolbar_display_airpcap_key_management_cb(GtkWidget *w, gpointer data)
3808 {
3809     int *from_widget;
3810
3811     from_widget = (gint*)g_malloc(sizeof(gint));
3812     *from_widget = AIRPCAP_ADVANCED_FROM_TOOLBAR;
3813     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_ADVANCED_FROM_KEY,from_widget);
3814
3815     display_airpcap_key_management_cb(w,data);
3816 }
3817 #endif /* HAVE_AIRPCAP */
3818
3819 #if GTK_MAJOR_VERSION >= 2
3820 static int
3821 top_level_key_pressed_cb(GtkCTree *ctree _U_, GdkEventKey *event, gpointer user_data _U_)
3822 {
3823     if (event->keyval == GDK_F8) {
3824         packet_list_next();
3825         return TRUE;
3826     } else if (event->keyval == GDK_F7) {
3827         packet_list_prev();
3828         return TRUE;
3829     /*
3830      * A comment in gdkkeysyms.h says that it's autogenerated from
3831      * freedesktop.org/x.org's keysymdef.h.  Although the GDK docs
3832      * don't explicitly say so, isprint() should work as expected
3833      * for values < 127.
3834      */
3835     } else if (isascii(event->keyval) && isprint(event->keyval)) {
3836         /* Forward the keypress on to the display filter entry */
3837         if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3838             gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3839             gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3840         }
3841         return FALSE;
3842     }
3843     return FALSE;
3844 }
3845 #endif
3846
3847 static void
3848 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
3849 {
3850     GtkWidget
3851                   *filter_bt, *filter_cm, *filter_te,
3852                   *filter_add_expr_bt,
3853                   *filter_apply,
3854                   *filter_reset;
3855     GList         *dfilter_list = NULL;
3856     GtkTooltips   *tooltips;
3857
3858     GtkAccelGroup *accel;
3859     gchar         *title;
3860
3861 #ifdef HAVE_AIRPCAP
3862     GtkWidget *advanced_bt,
3863                   *key_management_bt,
3864                   *interface_lb,
3865                   *channel_lb,
3866                   *channel_cm,
3867                   *wrong_crc_lb,
3868                   *wrong_crc_cm;
3869
3870     GtkWidget *enable_decryption_lb;
3871     GtkWidget *enable_decryption_cb;
3872     GList     *enable_decryption_cb_items = NULL;
3873     GtkWidget *enable_decryption_en;
3874
3875     GList         *channel_list = NULL;
3876     GList         *linktype_list = NULL;
3877     GList         *link_list = NULL;
3878     GtkTooltips   *airpcap_tooltips;
3879     gchar         *if_label_text;
3880     gint          *from_widget = NULL;
3881 #endif
3882
3883     /* Display filter construct dialog has an Apply button, and "OK" not
3884        only sets our text widget, it activates it (i.e., it causes us to
3885        filter the capture). */
3886     static construct_args_t args = {
3887         "Wireshark: Display Filter",
3888         TRUE,
3889         TRUE,
3890         FALSE
3891     };
3892
3893     /* use user-defined title if preference is set */
3894     title = create_user_window_title("The Wireshark Network Analyzer");
3895
3896     /* Main window */
3897     top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3898     g_free(title);
3899
3900     tooltips = gtk_tooltips_new();
3901
3902 #ifdef HAVE_AIRPCAP
3903     airpcap_tooltips = gtk_tooltips_new();
3904 #endif
3905
3906 #ifdef _WIN32
3907 #if GTK_MAJOR_VERSION < 2
3908     /* has to be done, after top_level window is created */
3909     app_font_gtk1_init(top_level);
3910 #endif
3911 #endif
3912
3913     gtk_widget_set_name(top_level, "main window");
3914     SIGNAL_CONNECT(top_level, "delete_event", main_window_delete_event_cb,
3915                    NULL);
3916 #if GTK_MAJOR_VERSION >= 2
3917     SIGNAL_CONNECT(GTK_OBJECT(top_level), "window_state_event",
3918                          G_CALLBACK (window_state_event_cb), NULL);
3919     SIGNAL_CONNECT(GTK_OBJECT(top_level), "key-press-event",
3920                          G_CALLBACK (top_level_key_pressed_cb), NULL );
3921 #endif
3922
3923     gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
3924
3925     /* Container for menu bar, toolbar(s), paned windows and progress/info box */
3926     main_vbox = gtk_vbox_new(FALSE, 1);
3927     gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
3928     gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3929     gtk_widget_show(main_vbox);
3930
3931     /* Menu bar */
3932     menubar = main_menu_new(&accel);
3933     gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3934     gtk_widget_show(menubar);
3935
3936     /* Main Toolbar */
3937     main_tb = toolbar_new();
3938     gtk_widget_show (main_tb);
3939
3940     /* Packet list */
3941     pkt_scrollw = packet_list_new(prefs);
3942     WIDGET_SET_SIZE(packet_list, -1, pl_size);
3943     gtk_widget_show(pkt_scrollw);
3944
3945     /* Tree view */
3946     tv_scrollw = main_tree_view_new(prefs, &tree_view);
3947     WIDGET_SET_SIZE(tv_scrollw, -1, tv_size);
3948     gtk_widget_show(tv_scrollw);
3949
3950 #if GTK_MAJOR_VERSION < 2
3951     SIGNAL_CONNECT(tree_view, "tree-select-row", tree_view_select_row_cb, NULL);
3952     SIGNAL_CONNECT(tree_view, "tree-unselect-row", tree_view_unselect_row_cb,
3953                    NULL);
3954 #else
3955     SIGNAL_CONNECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
3956                    "changed", tree_view_selection_changed_cb, NULL);
3957 #endif
3958     SIGNAL_CONNECT(tree_view, "button_press_event", popup_menu_handler,
3959                    OBJECT_GET_DATA(popup_menu_object, PM_TREE_VIEW_KEY));
3960     gtk_widget_show(tree_view);
3961
3962     /* Byte view. */
3963     byte_nb_ptr = byte_view_new();
3964     WIDGET_SET_SIZE(byte_nb_ptr, -1, bv_size);
3965     gtk_widget_show(byte_nb_ptr);
3966
3967     SIGNAL_CONNECT(byte_nb_ptr, "button_press_event", popup_menu_handler,
3968                    OBJECT_GET_DATA(popup_menu_object, PM_HEXDUMP_KEY));
3969
3970
3971     /* Panes for the packet list, tree, and byte view */
3972     main_pane_v1 = gtk_vpaned_new();
3973     gtk_widget_show(main_pane_v1);
3974     main_pane_v2 = gtk_vpaned_new();
3975     gtk_widget_show(main_pane_v2);
3976     main_pane_h1 = gtk_hpaned_new();
3977     gtk_widget_show(main_pane_h1);
3978     main_pane_h2 = gtk_hpaned_new();
3979     gtk_widget_show(main_pane_h2);
3980
3981 #ifdef HAVE_AIRPCAP
3982     /* airpcap toolbar */
3983 #if GTK_MAJOR_VERSION < 2
3984     airpcap_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
3985                                GTK_TOOLBAR_BOTH);
3986 #else
3987     airpcap_tb = gtk_toolbar_new();
3988     gtk_toolbar_set_orientation(GTK_TOOLBAR(airpcap_tb),
3989                                 GTK_ORIENTATION_HORIZONTAL);
3990 #endif /* GTK_MAJOR_VERSION */
3991     gtk_widget_show(airpcap_tb);
3992
3993     /* Interface Label */
3994     if(airpcap_if_active != NULL) {
3995         if_label_text = g_strdup_printf("%s %s\t","Current Wireless Interface: #",airpcap_get_if_string_number(airpcap_if_active));
3996         interface_lb = gtk_label_new(if_label_text);
3997         g_free(if_label_text);
3998     } else {
3999         interface_lb = gtk_label_new("No Wireless Interface Found  ");
4000     }
4001
4002     /* Add the label to the toolbar */
4003     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), interface_lb,
4004                               "Current Wireless Interface", "Private");
4005     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_INTERFACE_KEY,interface_lb);
4006     gtk_widget_show(interface_lb);
4007     gtk_toolbar_insert_space(GTK_TOOLBAR(airpcap_tb),1);
4008
4009
4010     /* Create the "802.11 Channel:" label */
4011     channel_lb = gtk_label_new(" 802.11 Channel: ");
4012     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_LABEL_KEY,channel_lb);
4013     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_lb,
4014                               "Current 802.11 Channel", "Private");
4015     gtk_widget_show(channel_lb);
4016
4017     WIDGET_SET_SIZE(channel_lb, 100, 28);
4018
4019     /* Create the channel combo box */
4020     channel_cm = gtk_combo_new();
4021     gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(channel_cm)->entry),FALSE);
4022     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_KEY,channel_cm);
4023
4024     channel_list = g_list_append(channel_list, "1");
4025     channel_list = g_list_append(channel_list, "2");
4026     channel_list = g_list_append(channel_list, "3");
4027     channel_list = g_list_append(channel_list, "4");
4028     channel_list = g_list_append(channel_list, "5");
4029     channel_list = g_list_append(channel_list, "6");
4030     channel_list = g_list_append(channel_list, "7");
4031     channel_list = g_list_append(channel_list, "8");
4032     channel_list = g_list_append(channel_list, "9");
4033     channel_list = g_list_append(channel_list, "10");
4034     channel_list = g_list_append(channel_list, "11");
4035     channel_list = g_list_append(channel_list, "12");
4036     channel_list = g_list_append(channel_list, "13");
4037     channel_list = g_list_append(channel_list, "14");
4038
4039     gtk_combo_set_popdown_strings( GTK_COMBO(channel_cm), channel_list) ;
4040
4041     gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(channel_cm)->entry),
4042                 "Change the 802.11 RF channel", NULL);
4043
4044     WIDGET_SET_SIZE(channel_cm, 90, 28);
4045
4046     if(airpcap_if_active != NULL)
4047         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_cm)->entry), airpcap_get_channel_name(airpcap_if_active->channel));
4048     else
4049         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_cm)->entry),"");
4050
4051     /* callback for channel combo box */
4052     SIGNAL_CONNECT(GTK_COMBO(channel_cm)->entry,"changed",airpcap_toolbar_channel_changed_cb,GTK_COMBO(channel_cm)->entry);
4053     gtk_widget_show(channel_cm);
4054
4055     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_cm,
4056                               "802.11 Channel", "Private");
4057
4058     gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4059
4060     /* Wrong CRC Label */
4061     wrong_crc_lb = gtk_label_new(" FCS Filter: ");
4062     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_FCS_FILTER_LABEL_KEY,wrong_crc_lb);
4063     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), wrong_crc_lb,
4064                               "", "Private");
4065     gtk_widget_show(wrong_crc_lb);
4066
4067     /* Wrong CRC combo */
4068     wrong_crc_cm = gtk_combo_new();
4069     gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(wrong_crc_cm)->entry),FALSE);
4070     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_FCS_FILTER_KEY,wrong_crc_cm);
4071     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), wrong_crc_cm,
4072                               "", "Private");
4073
4074     WIDGET_SET_SIZE(wrong_crc_cm, 100, -1);
4075
4076     linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_ALL);
4077     linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_CORRECT);
4078     linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_CORRUPT);
4079
4080     gtk_combo_set_popdown_strings( GTK_COMBO(wrong_crc_cm), linktype_list) ;
4081     gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(wrong_crc_cm)->entry),
4082         "Select the 802.11 FCS filter that the wireless adapter will apply.",
4083         NULL);
4084
4085     if(airpcap_if_active != NULL)
4086         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(wrong_crc_cm)->entry), airpcap_get_validation_name(airpcap_if_active->CrcValidationOn));
4087     else
4088         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(wrong_crc_cm)->entry),"");
4089
4090     SIGNAL_CONNECT(GTK_COMBO(wrong_crc_cm)->entry,"changed",airpcap_toolbar_wrong_crc_combo_cb,airpcap_tb);
4091     gtk_widget_show(wrong_crc_cm);
4092
4093     gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4094
4095     /* Decryption mode combo box */
4096     enable_decryption_lb = gtk_label_new ("Decryption Mode: ");
4097     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_DECRYPTION_LABEL_KEY,enable_decryption_lb);
4098     gtk_widget_set_name (enable_decryption_lb, "enable_decryption_lb");
4099     gtk_widget_show (enable_decryption_lb);
4100     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), enable_decryption_lb,
4101     NULL, "Private");
4102
4103     enable_decryption_cb = gtk_combo_new ();
4104     gtk_widget_set_name (enable_decryption_cb, "enable_decryption_cb");
4105     gtk_widget_show (enable_decryption_cb);
4106     WIDGET_SET_SIZE (enable_decryption_cb, 83, -1);
4107     update_decryption_mode_list(enable_decryption_cb);
4108
4109     enable_decryption_en = GTK_COMBO (enable_decryption_cb)->entry;
4110     gtk_widget_set_name (enable_decryption_en, "enable_decryption_en");
4111     gtk_widget_show (enable_decryption_en);
4112     gtk_editable_set_editable (GTK_EDITABLE (enable_decryption_en), FALSE);
4113     GTK_WIDGET_UNSET_FLAGS (enable_decryption_en, GTK_CAN_FOCUS);
4114
4115     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), enable_decryption_cb,
4116         "Choose a Decryption Mode", "Private");
4117
4118     /* Set current decryption mode!!!! */
4119     update_decryption_mode_cm(enable_decryption_cb);
4120     SIGNAL_CONNECT (enable_decryption_en, "changed",on_enable_decryption_en_changed, airpcap_tb);
4121     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_DECRYPTION_KEY,enable_decryption_cb);
4122
4123     gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4124
4125     /* Advanced button */
4126     advanced_bt = gtk_button_new_with_label("Wireless Settings...");
4127     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_ADVANCED_KEY,advanced_bt);
4128
4129     SIGNAL_CONNECT(advanced_bt, "clicked", toolbar_display_airpcap_advanced_cb, airpcap_tb);
4130     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), advanced_bt,
4131         "Set Advanced Wireless Settings", "Private");
4132     gtk_widget_show(advanced_bt);
4133
4134     /* Key Management button */
4135     key_management_bt = gtk_button_new_with_label("Decryption Keys...");
4136     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_KEY_MANAGEMENT_KEY,key_management_bt);
4137
4138     SIGNAL_CONNECT(key_management_bt, "clicked", toolbar_display_airpcap_key_management_cb, airpcap_tb);
4139     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), key_management_bt,
4140                               "Manage Decryption Keys", "Private");
4141     gtk_widget_show(key_management_bt);
4142
4143     /* select the default interface */
4144     airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
4145
4146     /* If no airpcap interface is present, gray everything */
4147     if(airpcap_if_active == NULL) {
4148         if(airpcap_if_list == NULL) {
4149             /*No airpcap device found */
4150                         airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
4151                         //recent.airpcap_toolbar_show = TRUE;
4152         } else {
4153             /* default adapter is not airpcap... or is airpcap but is not found*/
4154             airpcap_set_toolbar_stop_capture(airpcap_if_active);
4155                         airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
4156                         //recent.airpcap_toolbar_show = TRUE;
4157         }
4158     } else {
4159         airpcap_set_toolbar_stop_capture(airpcap_if_active);
4160                 //recent.airpcap_toolbar_show = TRUE;
4161     }
4162 #endif
4163
4164     /* filter toolbar */
4165 #if GTK_MAJOR_VERSION < 2
4166     filter_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
4167                                GTK_TOOLBAR_BOTH);
4168 #else
4169     filter_tb = gtk_toolbar_new();
4170     gtk_toolbar_set_orientation(GTK_TOOLBAR(filter_tb),
4171                                 GTK_ORIENTATION_HORIZONTAL);
4172 #endif /* GTK_MAJOR_VERSION */
4173     gtk_widget_show(filter_tb);
4174
4175     /* Create the "Filter:" button */
4176     filter_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
4177     SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
4178     gtk_widget_show(filter_bt);
4179     OBJECT_SET_DATA(top_level, E_FILT_BT_PTR_KEY, filter_bt);
4180
4181     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_bt,
4182         "Open the \"Display Filter\" dialog, to edit/apply filters", "Private");
4183
4184     /* Create the filter combobox */
4185     filter_cm = gtk_combo_new();
4186     dfilter_list = NULL;
4187     gtk_combo_disable_activate(GTK_COMBO(filter_cm));
4188     gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
4189     OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
4190     filter_te = GTK_COMBO(filter_cm)->entry;
4191     main_display_filter_widget=filter_te;
4192     OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
4193     OBJECT_SET_DATA(filter_te, E_DFILTER_CM_KEY, filter_cm);
4194     OBJECT_SET_DATA(top_level, E_DFILTER_CM_KEY, filter_cm);
4195     SIGNAL_CONNECT(filter_te, "activate", filter_activate_cb, filter_te);
4196     SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
4197     WIDGET_SET_SIZE(filter_cm, 400, -1);
4198     gtk_widget_show(filter_cm);
4199     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_cm,
4200         NULL, NULL);
4201     /* setting a tooltip for a combobox will do nothing, so add it to the corresponding text entry */
4202     gtk_tooltips_set_tip(tooltips, filter_te,
4203         "Enter a display filter, or choose one of your recently used filters. "
4204         "The background color of this field is changed by a continuous syntax check (green is valid, red is invalid).",
4205         NULL);
4206
4207     /* Create the "Add Expression..." button, to pop up a dialog
4208        for constructing filter comparison expressions. */
4209     filter_add_expr_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_ADD_EXPRESSION);
4210     OBJECT_SET_DATA(filter_tb, E_FILT_FILTER_TE_KEY, filter_te);
4211     SIGNAL_CONNECT(filter_add_expr_bt, "clicked", filter_add_expr_bt_cb, filter_tb);
4212     gtk_widget_show(filter_add_expr_bt);
4213     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_add_expr_bt,
4214         "Add an expression to this filter string", "Private");
4215
4216     /* Create the "Clear" button */
4217     filter_reset = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLEAR);
4218     OBJECT_SET_DATA(filter_reset, E_DFILTER_TE_KEY, filter_te);
4219     SIGNAL_CONNECT(filter_reset, "clicked", filter_reset_cb, NULL);
4220     gtk_widget_show(filter_reset);
4221     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_reset,
4222         "Clear this filter string and update the display", "Private");
4223
4224     /* Create the "Apply" button */
4225     filter_apply = BUTTON_NEW_FROM_STOCK(GTK_STOCK_APPLY);
4226     OBJECT_SET_DATA(filter_apply, E_DFILTER_CM_KEY, filter_cm);
4227     SIGNAL_CONNECT(filter_apply, "clicked", filter_activate_cb, filter_te);
4228     gtk_widget_show(filter_apply);
4229     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_apply,
4230         "Apply this filter string to the display", "Private");
4231
4232     /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
4233      * of any widget that ends up calling a callback which needs
4234      * that text entry pointer */
4235     set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
4236     set_menu_object_data("/Analyze/Display Filters...", E_FILT_TE_PTR_KEY,
4237                          filter_te);
4238     set_menu_object_data("/Analyze/Follow TCP Stream", E_DFILTER_TE_KEY,
4239                          filter_te);
4240     set_menu_object_data("/Analyze/Follow SSL Stream", E_DFILTER_TE_KEY,
4241                          filter_te);
4242     set_menu_object_data("/Analyze/Apply as Filter/Selected", E_DFILTER_TE_KEY,
4243                          filter_te);
4244     set_menu_object_data("/Analyze/Apply as Filter/Not Selected", E_DFILTER_TE_KEY,
4245                          filter_te);
4246     set_menu_object_data("/Analyze/Apply as Filter/... and Selected", E_DFILTER_TE_KEY,
4247                          filter_te);
4248     set_menu_object_data("/Analyze/Apply as Filter/... or Selected", E_DFILTER_TE_KEY,
4249                          filter_te);
4250     set_menu_object_data("/Analyze/Apply as Filter/... and not Selected", E_DFILTER_TE_KEY,
4251                          filter_te);
4252     set_menu_object_data("/Analyze/Apply as Filter/... or not Selected", E_DFILTER_TE_KEY,
4253                          filter_te);
4254     set_menu_object_data("/Analyze/Prepare a Filter/Selected", E_DFILTER_TE_KEY,
4255                          filter_te);
4256     set_menu_object_data("/Analyze/Prepare a Filter/Not Selected", E_DFILTER_TE_KEY,
4257                          filter_te);
4258     set_menu_object_data("/Analyze/Prepare a Filter/... and Selected", E_DFILTER_TE_KEY,
4259                          filter_te);
4260     set_menu_object_data("/Analyze/Prepare a Filter/... or Selected", E_DFILTER_TE_KEY,
4261                          filter_te);
4262     set_menu_object_data("/Analyze/Prepare a Filter/... and not Selected", E_DFILTER_TE_KEY,
4263                          filter_te);
4264     set_menu_object_data("/Analyze/Prepare a Filter/... or not Selected", E_DFILTER_TE_KEY,
4265                          filter_te);
4266     set_menu_object_data("/Conversation Filter/Ethernet", E_DFILTER_TE_KEY,
4267                          filter_te);
4268     set_menu_object_data("/Conversation Filter/IP", E_DFILTER_TE_KEY,
4269                          filter_te);
4270     set_menu_object_data("/Conversation Filter/TCP", E_DFILTER_TE_KEY,
4271                          filter_te);
4272     set_menu_object_data("/Conversation Filter/UDP", E_DFILTER_TE_KEY,
4273                          filter_te);
4274     set_menu_object_data("/Conversation Filter/PN-CBA Server", E_DFILTER_TE_KEY,
4275                          filter_te);
4276     set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
4277     OBJECT_SET_DATA(popup_menu_object, E_DFILTER_TE_KEY, filter_te);
4278     OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_KEY, packet_list);
4279
4280     /* info (main) statusbar */
4281     info_bar = info_bar_new();
4282     gtk_widget_show(info_bar);
4283
4284     /* packets statusbar */
4285     packets_bar = packets_bar_new();
4286     gtk_widget_show(packets_bar);
4287
4288     /* Filter/status hbox */
4289     stat_hbox = gtk_hbox_new(FALSE, 1);
4290     gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
4291     gtk_widget_show(stat_hbox);
4292
4293     /* Pane for the statusbar */
4294     status_pane = gtk_hpaned_new();
4295     gtk_widget_show(status_pane);
4296
4297     /* Pane for the welcome screen */
4298     welcome_pane = welcome_new();
4299     gtk_widget_show(welcome_pane);
4300 }
4301
4302 #ifdef HAVE_AIRPCAP
4303 static void
4304 driver_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
4305 {
4306     gboolean r;
4307
4308     r = simple_dialog_check_get(dialog);
4309     recent.airpcap_driver_check_show = !r;
4310 }
4311 #endif
4312
4313 static void
4314 show_main_window(gboolean doing_work)
4315 {
4316   main_set_for_capture_file(doing_work);
4317
4318   /*** we have finished all init things, show the main window ***/
4319   gtk_widget_show(top_level);
4320
4321   /* the window can be maximized only, if it's visible, so do it after show! */
4322   main_load_window_geometry(top_level);
4323
4324   /* process all pending GUI events before continue */
4325   while (gtk_events_pending()) gtk_main_iteration();
4326
4327   /* Pop up any queued-up alert boxes. */
4328   display_queued_messages();
4329
4330 #ifdef HAVE_AIRPCAP
4331   /*
4332    * This will read the decryption keys from the preferences file, and will
4333    * store them into the registry...
4334    */
4335   if(!airpcap_check_decryption_keys(airpcap_if_list)) {
4336     /* Ask the user what to do ...*/
4337     airpcap_keys_check_w(NULL,NULL);
4338   } else {
4339     /* Keys from lists are equals, or wireshark has got no keys */
4340     airpcap_load_decryption_keys(airpcap_if_list);
4341   }
4342
4343   switch (airpcap_dll_ret_val) {
4344
4345   case AIRPCAP_DLL_OK:
4346     break;
4347
4348   case AIRPCAP_DLL_OLD:
4349     if(recent.airpcap_driver_check_show) {
4350       driver_warning_dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
4351                         "WARNING: The version of AirPcap on this system\n"
4352                         "does not support driver-level decryption.  Please\n"
4353                         "download a more recent version from\n" "http://www.cacetech.com/support/downloads.htm \n");
4354       simple_dialog_check_set(driver_warning_dialog,"Don't show this message again.");
4355       simple_dialog_set_cb(driver_warning_dialog, driver_warning_dialog_cb, (gpointer) driver_warning_dialog);
4356     }
4357     break;
4358
4359 #if 0
4360   /*
4361    * XXX - Maybe we need to warn the user if one of the following happens???
4362    */
4363   case AIRPCAP_DLL_ERROR:
4364     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
4365     break;
4366
4367   case AIRPCAP_DLL_NOT_FOUND:
4368     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
4369     break;
4370 #endif
4371   }
4372 #endif /* HAVE_AIRPCAP */
4373 }
4374
4375 /* Fill in capture options with values from the preferences */
4376 void
4377 prefs_to_capture_opts(void)
4378 {
4379 #ifdef HAVE_LIBPCAP
4380   /* Set promiscuous mode from the preferences setting. */
4381   /* the same applies to other preferences settings as well. */
4382     capture_opts->promisc_mode   = prefs.capture_prom_mode;
4383     capture_opts->show_info      = prefs.capture_show_info;
4384     capture_opts->real_time_mode = prefs.capture_real_time;
4385     auto_scroll_live             = prefs.capture_auto_scroll;
4386 #endif /* HAVE_LIBPCAP */
4387
4388   /* Set the name resolution code's flags from the preferences. */
4389   g_resolv_flags = prefs.name_resolve;
4390 }