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