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