NetFlow: Fix a preference description.
[metze/wireshark/wip.git] / wireshark-qt.cpp
1 /* wireshark-qt.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <config.h>
23
24 #include <glib.h>
25
26 #ifdef Q_OS_UNIX
27 #include <signal.h>
28 #endif
29
30 #include <locale.h>
31
32 #ifdef HAVE_GETOPT_H
33 #include <getopt.h>
34 #endif
35
36 #ifndef HAVE_GETOPT_LONG
37 #include "wsutil/wsgetopt.h"
38 #endif
39
40 #include <wsutil/clopts_common.h>
41 #include <wsutil/cmdarg_err.h>
42 #include <wsutil/crash_info.h>
43 #include <wsutil/filesystem.h>
44 #include <wsutil/privileges.h>
45 #ifdef HAVE_PLUGINS
46 #include <wsutil/plugins.h>
47 #endif
48 #include <wsutil/report_err.h>
49 #include <wsutil/unicode-utils.h>
50 #include <ws_version_info.h>
51
52 #include <epan/addr_resolv.h>
53 #include <epan/ex-opt.h>
54 #include <epan/tap.h>
55 #include <epan/stat_tap_ui.h>
56 #include <epan/column.h>
57 #include <epan/disabled_protos.h>
58 #include <epan/prefs.h>
59
60 #ifdef HAVE_KERBEROS
61 #include <epan/packet.h>
62 #include <epan/asn1.h>
63 #include <epan/dissectors/packet-kerberos.h>
64 #endif
65
66 #ifdef HAVE_PLUGINS
67 #include <codecs/codecs.h>
68 #endif
69
70 #ifdef HAVE_EXTCAP
71 #include <extcap.h>
72 #endif
73
74 /* general (not Qt specific) */
75 #include "file.h"
76 #include "epan/color_filters.h"
77 #include "log.h"
78
79 #include "epan/rtd_table.h"
80 #include "epan/srt_table.h"
81
82 #include "ui/alert_box.h"
83 #include "ui/console.h"
84 #include "ui/iface_lists.h"
85 #include "ui/language.h"
86 #include "ui/persfilepath_opt.h"
87 #include "ui/recent.h"
88 #include "ui/simple_dialog.h"
89 #include "ui/util.h"
90 #include "ui/commandline.h"
91 #include "ui/capture_ui_utils.h"
92
93 #include "ui/qt/conversation_dialog.h"
94 #include "ui/qt/color_utils.h"
95 #include "ui/qt/coloring_rules_dialog.h"
96 #include "ui/qt/endpoint_dialog.h"
97 #include "ui/qt/main_window.h"
98 #include "ui/qt/response_time_delay_dialog.h"
99 #include "ui/qt/service_response_time_dialog.h"
100 #include "ui/qt/simple_dialog.h"
101 #include "ui/qt/simple_statistics_dialog.h"
102 #include "ui/qt/splash_overlay.h"
103 #include "ui/qt/wireshark_application.h"
104
105 #include "caputils/capture-pcap-util.h"
106
107 #ifdef _WIN32
108 #  include "caputils/capture-wpcap.h"
109 #  include "caputils/capture_wpcap_packet.h"
110 #  include <tchar.h> /* Needed for Unicode */
111 #  include <wsutil/file_util.h>
112 #  include <wsutil/os_version_info.h>
113 #endif /* _WIN32 */
114
115 #ifdef HAVE_AIRPCAP
116 #  include <caputils/airpcap.h>
117 #  include <caputils/airpcap_loader.h>
118 //#  include "airpcap_dlg.h"
119 //#  include "airpcap_gui_utils.h"
120 #endif
121
122 #include "epan/crypt/airpdcap_ws.h"
123
124 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
125 #include <QTextCodec>
126 #endif
127
128 /* update the main window */
129 void main_window_update(void)
130 {
131     WiresharkApplication::processEvents();
132 }
133
134 #ifdef HAVE_LIBPCAP
135
136 /* quit a nested main window */
137 void main_window_nested_quit(void)
138 {
139 //    if (gtk_main_level() > 0)
140     wsApp->quit();
141 }
142
143 /* quit the main window */
144 void main_window_quit(void)
145 {
146     wsApp->quit();
147 }
148
149 #endif /* HAVE_LIBPCAP */
150
151 /*
152  * Report an error in command-line arguments.
153  * Creates a console on Windows.
154  */
155 // xxx copied from ../gtk/main.c
156 static void
157 wireshark_cmdarg_err(const char *fmt, va_list ap)
158 {
159 #ifdef _WIN32
160     create_console();
161 #endif
162     fprintf(stderr, "wireshark: ");
163     vfprintf(stderr, fmt, ap);
164     fprintf(stderr, "\n");
165 }
166
167 /*
168  * Report additional information for an error in command-line arguments.
169  * Creates a console on Windows.
170  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
171  * terminal isn't the standard error?
172  */
173 // xxx copied from ../gtk/main.c
174 static void
175 wireshark_cmdarg_err_cont(const char *fmt, va_list ap)
176 {
177 #ifdef _WIN32
178     create_console();
179 #endif
180     vfprintf(stderr, fmt, ap);
181     fprintf(stderr, "\n");
182 }
183
184 // xxx based from ../gtk/main.c:get_gtk_compiled_info
185 void
186 get_wireshark_qt_compiled_info(GString *str)
187 {
188     g_string_append(str, "with ");
189     g_string_append_printf(str,
190 #ifdef QT_VERSION
191                     "Qt %s", QT_VERSION_STR);
192 #else
193                     "Qt (version unknown)");
194 #endif
195
196     /* Capture libraries */
197     g_string_append(str, ", ");
198     get_compiled_caplibs_version(str);
199 }
200
201 // xxx copied from ../gtk/main.c
202 void
203 get_gui_compiled_info(GString *str)
204 {
205     epan_get_compiled_version_info(str);
206
207     g_string_append(str, ", ");
208 #ifdef QT_MULTIMEDIA_LIB
209     g_string_append(str, "with QtMultimedia");
210 #else
211     g_string_append(str, "without QtMultimedia");
212 #endif
213
214     g_string_append(str, ", ");
215 #ifdef HAVE_AIRPCAP
216     get_compiled_airpcap_version(str);
217 #else
218     g_string_append(str, "without AirPcap");
219 #endif
220 }
221
222 // xxx copied from ../gtk/main.c
223 void
224 get_wireshark_runtime_info(GString *str)
225 {
226 #ifdef HAVE_LIBPCAP
227     /* Capture libraries */
228     g_string_append(str, ", ");
229     get_runtime_caplibs_version(str);
230 #endif
231
232     /* stuff used by libwireshark */
233     epan_get_runtime_version_info(str);
234
235 #ifdef HAVE_AIRPCAP
236     g_string_append(str, ", ");
237     get_runtime_airpcap_version(str);
238 #endif
239 }
240
241 #ifdef HAVE_LIBPCAP
242 /*  Check if there's something important to tell the user during startup.
243  *  We want to do this *after* showing the main window so that any windows
244  *  we pop up will be above the main window.
245  */
246 static void
247 check_and_warn_user_startup(const QString &cf_name)
248 {
249 #ifndef _WIN32
250     Q_UNUSED(cf_name)
251 #endif
252     gchar               *cur_user, *cur_group;
253
254     /* Tell the user not to run as root. */
255     if (running_with_special_privs() && recent.privs_warn_if_elevated) {
256         cur_user = get_cur_username();
257         cur_group = get_cur_groupname();
258         simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
259         "Running as user \"%s\" and group \"%s\".\n"
260         "This could be dangerous.\n\n"
261         "If you're running Wireshark this way in order to perform live capture, "
262         "you may want to be aware that there is a better way documented at\n"
263         "https://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
264         g_free(cur_user);
265         g_free(cur_group);
266     }
267
268 #ifdef _WIN32
269     /* Warn the user if npf.sys isn't loaded. */
270     if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
271         simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
272         "The NPF driver isn't running. You may have trouble\n"
273         "capturing or listing interfaces.");
274     }
275 #endif
276
277 }
278 #endif
279
280 #ifdef _WIN32
281 // Try to avoid library search path collisions. QCoreApplication will
282 // search QT_INSTALL_PREFIX/plugins for platform DLLs before searching
283 // the application directory. If
284 //
285 // - You have Qt version 5.x.y installed in the default location
286 //   (C:\Qt\5.x) on your machine.
287 //
288 // and
289 //
290 // - You install Wireshark that was built on a machine with Qt version
291 //   5.x.z installed in the default location.
292 //
293 // Qt5Core.dll will load qwindows.dll from your local C:\Qt\5.x\...\plugins
294 // directory. This may not be compatible with qwindows.dll from that
295 // same path on the build machine. At any rate, loading DLLs from paths
296 // you don't control is ill-advised. We work around this by removing every
297 // path except our application directory.
298
299 static inline void
300 reset_library_path(void)
301 {
302     QString app_path = QDir(get_progfile_dir()).path();
303     foreach (QString path, QCoreApplication::libraryPaths()) {
304         QCoreApplication::removeLibraryPath(path);
305     }
306     QCoreApplication::addLibraryPath(app_path);
307 }
308 #endif
309
310 /* And now our feature presentation... [ fade to music ] */
311 int main(int argc, char *qt_argv[])
312 {
313     MainWindow *main_w;
314
315 #ifdef _WIN32
316     int                  opt;
317 #endif
318     int                  ret_val;
319     char               **argv = qt_argv;
320
321 #ifdef _WIN32
322     WSADATA              wsaData;
323 #endif  /* _WIN32 */
324
325     char                *rf_path;
326     int                  rf_open_errno;
327     char                *gdp_path, *dp_path;
328 #ifdef HAVE_LIBPCAP
329     gchar               *err_str;
330     int                  status;
331 #else
332 #ifdef _WIN32
333 #ifdef HAVE_AIRPCAP
334     gchar               *err_str;
335 #endif
336 #endif
337 #endif
338     GString             *comp_info_str = NULL;
339     GString             *runtime_info_str = NULL;
340
341     QString              dfilter, read_filter;
342
343     cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
344
345     // In Qt 5, C strings are treated always as UTF-8 when converted to
346     // QStrings; in Qt 4, the codec must be set to make that happen
347 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
348     // Hopefully we won't have to use QString::fromUtf8() in as many places.
349     QTextCodec *utf8codec = QTextCodec::codecForName("UTF-8");
350     QTextCodec::setCodecForCStrings(utf8codec);
351     // XXX - QObject doesn't *have* a tr method in 5.0, as far as I can see...
352     QTextCodec::setCodecForTr(utf8codec);
353 #endif
354
355     /* Set the C-language locale to the native environment. */
356     setlocale(LC_ALL, "");
357
358 #ifdef _WIN32
359     // QCoreApplication clobbers argv. Let's have a local copy.
360     argv = (char **) g_malloc(sizeof(char *) * argc);
361     for (opt = 0; opt < argc; opt++) {
362         argv[opt] = qt_argv[opt];
363     }
364     arg_list_utf_16to8(argc, argv);
365     create_app_running_mutex();
366 #endif /* _WIN32 */
367
368     /*
369      * Get credential information for later use, and drop privileges
370      * before doing anything else.
371      * Let the user know if anything happened.
372      */
373     init_process_policies();
374     relinquish_special_privs_perm();
375
376     /*
377      * Attempt to get the pathname of the executable file.
378      */
379     /* init_progfile_dir_error = */ init_progfile_dir(argv[0],
380         (int (*)(int, char **)) get_gui_compiled_info);
381     g_log(NULL, G_LOG_LEVEL_DEBUG, "progfile_dir: %s", get_progfile_dir());
382
383 #ifdef _WIN32
384     ws_init_dll_search_path();
385     /* Load wpcap if possible. Do this before collecting the run-time version information */
386     load_wpcap();
387
388     /* ... and also load the packet.dll from wpcap */
389     wpcap_packet_load();
390
391 #ifdef HAVE_AIRPCAP
392     /* Load the airpcap.dll.  This must also be done before collecting
393      * run-time version information. */
394     load_airpcap();
395 #if 0
396     airpcap_dll_ret_val = load_airpcap();
397
398     switch (airpcap_dll_ret_val) {
399     case AIRPCAP_DLL_OK:
400         /* load the airpcap interfaces */
401         g_airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
402
403         if (g_airpcap_if_list == NULL || g_list_length(g_airpcap_if_list) == 0){
404             if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
405                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters.");
406                 g_free(err_str);
407             }
408             airpcap_if_active = NULL;
409
410         } else {
411
412             /* select the first ad default (THIS SHOULD BE CHANGED) */
413             airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
414         }
415         break;
416     /*
417      * XXX - Maybe we need to warn the user if one of the following happens???
418      */
419     case AIRPCAP_DLL_OLD:
420         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
421         break;
422
423     case AIRPCAP_DLL_ERROR:
424         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
425         break;
426
427     case AIRPCAP_DLL_NOT_FOUND:
428         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
429         break;
430     }
431 #endif
432 #endif /* HAVE_AIRPCAP */
433 #endif /* _WIN32 */
434
435     /* Get the compile-time version information string */
436     comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
437                                               get_gui_compiled_info);
438
439     /* Assemble the run-time version information string */
440     runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info);
441
442     profile_store_persconffiles(TRUE);
443
444     /* Read the profile independent recent file.  We have to do this here so we can */
445     /* set the profile before it can be set from the command line parameter */
446     if (!recent_read_static(&rf_path, &rf_open_errno)) {
447         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
448                       "Could not open common recent file\n\"%s\": %s.",
449                       rf_path, strerror(rf_open_errno));
450         g_free(rf_path);
451     }
452
453     commandline_early_options(argc, argv, comp_info_str, runtime_info_str);
454
455 #ifdef _WIN32
456     reset_library_path();
457 #endif
458
459     /* Create The Wireshark app */
460     WiresharkApplication ws_app(argc, qt_argv);
461
462     /* initialize the funnel mini-api */
463     // xxx qtshark
464     //initialize_funnel_ops();
465
466     AirPDcapInitContext(&airpdcap_ctx);
467
468     QString cf_name;
469     unsigned int in_file_type = WTAP_TYPE_AUTO;
470
471     /* Add it to the information to be reported on a crash. */
472     ws_add_crash_info("Wireshark %s\n"
473            "\n"
474            "%s"
475            "\n"
476            "%s",
477         get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
478     g_string_free(comp_info_str, TRUE);
479     g_string_free(runtime_info_str, TRUE);
480
481 #ifdef _WIN32
482     /* Start windows sockets */
483     WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
484 #endif  /* _WIN32 */
485
486     /* Read the profile dependent (static part) of the recent file. */
487     /* Only the static part of it will be read, as we don't have the gui now to fill the */
488     /* recent lists which is done in the dynamic part. */
489     /* We have to do this already here, so command line parameters can overwrite these values. */
490     if (!recent_read_profile_static(&rf_path, &rf_open_errno)) {
491         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
492                       "Could not open recent file\n\"%s\": %s.",
493                       rf_path, g_strerror(rf_open_errno));
494         g_free(rf_path);
495     }
496     wsApp->applyCustomColorsFromRecent();
497
498     // Initialize our language
499     read_language_prefs();
500     wsApp->loadLanguage(language);
501
502     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", language);
503
504     // Init the main window (and splash)
505     main_w = new(MainWindow);
506     main_w->show();
507     // We may not need a queued connection here but it would seem to make sense
508     // to force the issue.
509     main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)),
510             main_w, SLOT(openCaptureFile(QString,QString,unsigned int)));
511
512     /* Init the "Open file" dialog directory */
513     /* (do this after the path settings are processed) */
514     if (recent.gui_fileopen_remembered_dir &&
515         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
516       wsApp->setLastOpenDir(recent.gui_fileopen_remembered_dir);
517     } else {
518       wsApp->setLastOpenDir(get_persdatafile_dir());
519     }
520
521 #ifdef Q_OS_UNIX
522     // Replicates behavior in gtk_init();
523     signal(SIGPIPE, SIG_IGN);
524 #endif
525
526     set_console_log_handler();
527
528 #ifdef HAVE_LIBPCAP
529     /* Set the initial values in the capture options. This might be overwritten
530        by preference settings and then again by the command line parameters. */
531     capture_opts_init(&global_capture_opts);
532 #endif
533
534     init_report_err(vfailure_alert_box, open_failure_alert_box,
535                     read_failure_alert_box, write_failure_alert_box);
536
537     init_open_routines();
538
539 #ifdef HAVE_PLUGINS
540     /* Register all the plugin types we have. */
541     epan_register_plugin_types(); /* Types known to libwireshark */
542     wtap_register_plugin_types(); /* Types known to libwiretap */
543     codec_register_plugin_types(); /* Types known to libwscodecs */
544
545     /* Scan for plugins.  This does *not* call their registration routines;
546        that's done later. */
547     scan_plugins(REPORT_LOAD_FAILURE);
548
549     /* Register all libwiretap plugin modules. */
550     register_all_wiretap_modules();
551
552     /* Register all audio codec plugins. */
553     register_all_codecs();
554 #endif
555
556     /* Register all dissectors; we must do this before checking for the
557        "-G" flag, as the "-G" flag dumps information registered by the
558        dissectors, and we must do it before we read the preferences, in
559        case any dissectors register preferences. */
560     if (!epan_init(register_all_protocols,register_all_protocol_handoffs,
561                    splash_update, NULL)) {
562         SimpleDialog::displayQueuedMessages(main_w);
563         return 2;
564     }
565
566     splash_update(RA_LISTENERS, NULL, NULL);
567
568     /* Register all tap listeners; we do this before we parse the arguments,
569        as the "-z" argument can specify a registered tap. */
570
571     /* we register the plugin taps before the other taps because
572             stats_tree taps plugins will be registered as tap listeners
573             by stats_tree_stat.c and need to registered before that */
574 #ifdef HAVE_PLUGINS
575     register_all_plugin_tap_listeners();
576 #endif
577
578 #ifdef HAVE_EXTCAP
579     extcap_register_preferences();
580 #endif
581
582     register_all_tap_listeners();
583     conversation_table_set_gui_info(init_conversation_table);
584     hostlist_table_set_gui_info(init_endpoint_table);
585     srt_table_iterate_tables(register_service_response_tables, NULL);
586     rtd_table_iterate_tables(register_response_time_delay_tables, NULL);
587     new_stat_tap_iterate_tables(register_simple_stat_tables, NULL);
588
589     if (ex_opt_count("read_format") > 0) {
590         in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
591     }
592
593     splash_update(RA_PREFERENCES, NULL, NULL);
594
595     global_commandline_info.prefs_p = ws_app.readConfigurationFiles(&gdp_path, &dp_path, false);
596
597     /* Now get our args */
598     commandline_other_options(argc, argv, TRUE);
599
600     /* Convert some command-line parameters to QStrings */
601     if (global_commandline_info.cf_name != NULL)
602         cf_name = QString(global_commandline_info.cf_name);
603     if (global_commandline_info.rfilter != NULL)
604         read_filter = QString(global_commandline_info.rfilter);
605     if (global_commandline_info.dfilter != NULL)
606         dfilter = QString(global_commandline_info.dfilter);
607
608     /* Removed thread code:
609      * https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=9e277ae6154fd04bf6a0a34ec5655a73e5a736a3
610      */
611
612     timestamp_set_type(recent.gui_time_format);
613     timestamp_set_precision(recent.gui_time_precision);
614     timestamp_set_seconds_type (recent.gui_seconds_format);
615
616 #ifdef HAVE_LIBPCAP
617     splash_update(RA_INTERFACES, NULL, NULL);
618
619     fill_in_local_interfaces(main_window_update);
620
621     if (global_commandline_info.start_capture || global_commandline_info.list_link_layer_types) {
622         /* We're supposed to do a live capture or get a list of link-layer
623            types for a live capture device; if the user didn't specify an
624            interface to use, pick a default. */
625         status = capture_opts_default_iface_if_necessary(&global_capture_opts,
626         ((global_commandline_info.prefs_p->capture_device) && (*global_commandline_info.prefs_p->capture_device != '\0')) ? get_if_name(global_commandline_info.prefs_p->capture_device) : NULL);
627         if (status != 0) {
628             exit(status);
629         }
630     }
631
632     if (global_commandline_info.list_link_layer_types) {
633         /* Get the list of link-layer types for the capture devices. */
634         if_capabilities_t *caps;
635         guint i;
636         interface_t device;
637         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
638
639             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
640             if (device.selected) {
641 #if defined(HAVE_PCAP_CREATE)
642                 caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, NULL, &err_str, main_window_update);
643 #else
644                 caps = capture_get_if_capabilities(device.name, FALSE, NULL, &err_str,main_window_update);
645 #endif
646                 if (caps == NULL) {
647                     cmdarg_err("%s", err_str);
648                     g_free(err_str);
649                     exit(2);
650                 }
651             if (caps->data_link_types == NULL) {
652                 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
653                 exit(2);
654             }
655 #ifdef _WIN32
656             create_console();
657 #endif /* _WIN32 */
658 #if defined(HAVE_PCAP_CREATE)
659             capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
660 #else
661             capture_opts_print_if_capabilities(caps, device.name, FALSE);
662 #endif
663 #ifdef _WIN32
664             destroy_console();
665 #endif /* _WIN32 */
666             free_if_capabilities(caps);
667             }
668         }
669         exit(0);
670     }
671
672     capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
673     capture_opts_trim_ring_num_files(&global_capture_opts);
674 #endif /* HAVE_LIBPCAP */
675
676     /* Notify all registered modules that have had any of their preferences
677        changed either from one of the preferences file or from the command
678        line that their preferences have changed. */
679     prefs_apply_all();
680     wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
681
682 #ifdef HAVE_LIBPCAP
683     if ((global_capture_opts.num_selected == 0) &&
684             (prefs.capture_device != NULL)) {
685         guint i;
686         interface_t device;
687         for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
688             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
689             if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
690                 device.selected = TRUE;
691                 global_capture_opts.num_selected++;
692                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
693                 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
694                 break;
695             }
696         }
697     }
698 #endif
699
700     /* disabled protocols as per configuration file */
701     if (gdp_path == NULL && dp_path == NULL) {
702         set_disabled_protos_list();
703         set_disabled_heur_dissector_list();
704     }
705
706     if(global_commandline_info.disable_protocol_slist) {
707         GSList *proto_disable;
708         for (proto_disable = global_commandline_info.disable_protocol_slist; proto_disable != NULL; proto_disable = g_slist_next(proto_disable))
709         {
710             proto_disable_proto_by_name((char*)proto_disable->data);
711         }
712     }
713
714     if(global_commandline_info.enable_heur_slist) {
715         GSList *heur_enable;
716         for (heur_enable = global_commandline_info.enable_heur_slist; heur_enable != NULL; heur_enable = g_slist_next(heur_enable))
717         {
718             proto_enable_heuristic_by_name((char*)heur_enable->data, TRUE);
719         }
720     }
721
722     if(global_commandline_info.disable_heur_slist) {
723         GSList *heur_disable;
724         for (heur_disable = global_commandline_info.disable_heur_slist; heur_disable != NULL; heur_disable = g_slist_next(heur_disable))
725         {
726             proto_enable_heuristic_by_name((char*)heur_disable->data, FALSE);
727         }
728     }
729
730     build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE);
731     wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above.
732     wsApp->emitAppSignal(WiresharkApplication::RecentFilesRead); // Must be emitted after PreferencesChanged.
733
734     wsApp->setMonospaceFont(prefs.gui_qt_font_name);
735
736     /* For update of WindowTitle (When use gui.window_title preference) */
737     main_w->setWSWindowTitle();
738 ////////
739
740     /* Read the dynamic part of the recent file, as we have the gui now ready for
741        it. */
742     if (!recent_read_dynamic(&rf_path, &rf_open_errno)) {
743         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
744                       "Could not open recent file\n\"%s\": %s.",
745                       rf_path, g_strerror(rf_open_errno));
746         g_free(rf_path);
747     }
748
749     packet_list_enable_color(recent.packet_list_colorize);
750
751     g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: fetch recent color settings");
752     packet_list_enable_color(TRUE);
753
754 ////////
755
756
757 ////////
758     gchar* err_msg = NULL;
759     if (!color_filters_init(&err_msg, color_filter_add_cb)) {
760         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
761         g_free(err_msg);
762     }
763
764 ////////
765
766 #ifdef HAVE_LIBPCAP
767     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
768     if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
769         global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
770     }
771 #else /* HAVE_LIBPCAP */
772     ////////
773 #endif /* HAVE_LIBPCAP */
774
775     wsApp->allSystemsGo();
776     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
777     SimpleDialog::displayQueuedMessages(main_w);
778
779     /* User could specify filename, or display filter, or both */
780     if (!dfilter.isEmpty())
781         main_w->filterPackets(dfilter, false);
782     if (!cf_name.isEmpty()) {
783         if (main_w->openCaptureFile(cf_name, read_filter, in_file_type)) {
784
785             /* Open stat windows; we do so after creating the main window,
786                to avoid Qt warnings, and after successfully opening the
787                capture file, so we know we have something to compute stats
788                on, and after registering all dissectors, so that MATE will
789                have registered its field array and we can have a tap filter
790                with one of MATE's late-registered fields as part of the
791                filter. */
792             start_requested_stats();
793
794             if(global_commandline_info.go_to_packet != 0) {
795                 /* Jump to the specified frame number, kept for backward
796                    compatibility. */
797                 cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet);
798             } else if (global_commandline_info.jfilter != NULL) {
799                 dfilter_t *jump_to_filter = NULL;
800                 /* try to compile given filter */
801                 if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) {
802                     // Similar code in MainWindow::mergeCaptureFile().
803                     QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
804                                          QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
805                                                  .arg(global_commandline_info.jfilter, err_msg),
806                                          QMessageBox::Ok);
807                     g_free(err_msg);
808                 } else {
809                     /* Filter ok, jump to the first packet matching the filter
810                        conditions. Default search direction is forward, but if
811                        option d was given, search backwards */
812                     cf_find_packet_dfilter(CaptureFile::globalCapFile(), jump_to_filter, global_commandline_info.jump_backwards);
813                 }
814             }
815         }
816     }
817 #ifdef HAVE_LIBPCAP
818     else {
819         if (global_commandline_info.start_capture) {
820             if (global_capture_opts.save_file != NULL) {
821                 /* Save the directory name for future file dialogs. */
822                 /* (get_dirname overwrites filename) */
823                 gchar *s = g_strdup(global_capture_opts.save_file);
824                 set_last_open_dir(get_dirname(s));
825                 g_free(s);
826             }
827             /* "-k" was specified; start a capture. */
828 //            show_main_window(FALSE);
829             check_and_warn_user_startup(cf_name);
830
831             /* If no user interfaces were specified on the command line,
832                copy the list of selected interfaces to the set of interfaces
833                to use for this capture. */
834             if (global_capture_opts.ifaces->len == 0)
835                 collect_ifaces(&global_capture_opts);
836             CaptureFile::globalCapFile()->window = main_w;
837             if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) {
838                 /* The capture started.  Open stat windows; we do so after creating
839                    the main window, to avoid GTK warnings, and after successfully
840                    opening the capture file, so we know we have something to compute
841                    stats on, and after registering all dissectors, so that MATE will
842                    have registered its field array and we can have a tap filter with
843                    one of MATE's late-registered fields as part of the filter. */
844                 start_requested_stats();
845             }
846         }
847     /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
848         if (!global_commandline_info.start_capture && !global_capture_opts.default_options.cfilter) {
849             global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
850         }
851     }
852 #endif /* HAVE_LIBPCAP */
853
854     profile_store_persconffiles(FALSE);
855
856     ret_val = wsApp->exec();
857
858     epan_cleanup();
859
860 #ifdef HAVE_EXTCAP
861     extcap_cleanup();
862 #endif
863
864     AirPDcapDestroyContext(&airpdcap_ctx);
865
866 #ifdef _WIN32
867     /* Shutdown windows sockets */
868     WSACleanup();
869
870     /* For some unknown reason, the "atexit()" call in "create_console()"
871        doesn't arrange that "destroy_console()" be called when we exit,
872        so we call it here if a console was created. */
873     destroy_console();
874 #endif /* _WIN32 */
875
876     return ret_val;
877 }
878
879 /*
880  * Editor modelines
881  *
882  * Local Variables:
883  * c-basic-offset: 4
884  * tab-width: 8
885  * indent-tabs-mode: nil
886  * End:
887  *
888  * ex: set shiftwidth=4 tabstop=8 expandtab:
889  * :indentSize=4:tabSize=8:noTabs=true:
890  */