In a source file that defines external functions, the header file that
[metze/wireshark/wip.git] / ui / qt / wireshark_application.cpp
1 /* wireshark_application.cpp
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "wireshark_application.h"
25
26 #include "wsutil/filesystem.h"
27
28 #include "epan/disabled_protos.h"
29 #include "epan/tap.h"
30 #include "epan/timestamp.h"
31
32 #include "ui/decode_as_utils.h"
33 #include "ui/preference_utils.h"
34 #include "ui/recent.h"
35 #include "ui/simple_dialog.h"
36 #include "ui/util.h"
37
38 #include "qt_ui_utils.h"
39
40 #include "capture.h"
41 #include "color_filters.h"
42 #include "filters.h"
43 #include "log.h"
44 #include "recent_file_status.h"
45
46 #include "ui/capture_globals.h"
47 #include "ui/software_update.h"
48 #include "ui/last_open_dir.h"
49 #include "ui/recent_utils.h"
50
51 #ifdef _WIN32
52 #  include "ui/win32/console_win32.h"
53 #endif /* _WIN32 */
54
55 #include <QDesktopServices>
56 #include <QDir>
57 #include <QEvent>
58 #include <QFileOpenEvent>
59 #include <QFontMetrics>
60 #include <QTimer>
61 #include <QUrl>
62
63 #ifdef Q_OS_WIN
64 #include <QDebug>
65 #include <QLibrary>
66 #endif
67
68 WiresharkApplication *wsApp = NULL;
69
70 // XXX - Copied from ui/gtk/file_dlg.c
71
72 // MUST be UTF-8
73 static char *last_open_dir = NULL;
74 static bool updated_last_open_dir = FALSE;
75 static QList<recent_item_status *> recent_items;
76
77 void
78 topic_action(topic_action_e action)
79 {
80     if (wsApp) wsApp->helpTopicAction(action);
81 }
82
83 extern "C" char *
84 get_last_open_dir(void)
85 {
86     return last_open_dir;
87 }
88
89 void
90 set_last_open_dir(const char *dirname)
91 {
92     if (wsApp) wsApp->setLastOpenDir(dirname);
93 }
94
95 /*
96  * Add the capture filename to the application-wide "Recent Files" list.
97  * Contrary to the name this isn't limited to the "recent" menu.
98  */
99 /*
100  * XXX - We might want to call SHAddToRecentDocs under Windows 7:
101  * http://stackoverflow.com/questions/437212/how-do-you-register-a-most-recently-used-list-with-windows-in-preparation-for-win
102  */
103 extern "C" void
104 add_menu_recent_capture_file(const gchar *cf_name) {
105     QString normalized_cf_name = QString::fromUtf8(cf_name);
106 //    QDir cf_path;
107
108 //    cf_path.setPath(normalized_cf_name);
109 //    normalized_cf_name = cf_path.absolutePath();
110     normalized_cf_name = QDir::cleanPath(normalized_cf_name);
111     normalized_cf_name = QDir::toNativeSeparators(normalized_cf_name);
112
113     recent_item_status *ri;
114
115     /* Iterate through the recent items list, removing duplicate entries and every
116      * item above count_max
117      */
118     unsigned int cnt = 1;
119     foreach (ri, wsApp->recentItems()) {
120         /* if this element string is one of our special items (separator, ...) or
121          * already in the list or
122          * this element is above maximum count (too old), remove it
123          */
124         if (ri->filename.length() < 1 ||
125 #ifdef _WIN32
126             /* do a case insensitive compare on win32 */
127             ri->filename.compare(normalized_cf_name, Qt::CaseInsensitive) == 0 ||
128 #else   /* _WIN32 */
129             /* do a case sensitive compare on unix */
130             ri->filename.compare(normalized_cf_name) == 0 ||
131 #endif
132             cnt >= prefs.gui_recent_files_count_max) {
133             wsApp->recentItems().removeOne(ri);
134             delete(ri);
135             cnt--;
136         }
137         cnt++;
138     }
139     wsApp->addRecentItem(normalized_cf_name, 0, false);
140 }
141
142 /* write all capture filenames of the menu to the user's recent file */
143 extern "C" void menu_recent_file_write_all(FILE *rf) {
144
145     /* we have to iterate backwards through the children's list,
146      * so we get the latest item last in the file.
147      */
148     QListIterator<recent_item_status *> rii(recent_items);
149     rii.toBack();
150     while (rii.hasPrevious()) {
151         QString cf_name;
152         /* get capture filename from the menu item label */
153         cf_name = rii.previous()->filename;
154         if (cf_name != NULL) {
155 //            if(u3_active())
156 //                fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", u3_contract_device_path(cf_name));
157 //            else
158                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name.toUtf8().constData());
159         }
160     }
161 }
162
163 void WiresharkApplication::refreshRecentFiles(void) {
164     recent_item_status *ri;
165     RecentFileStatus *rf_status;
166     QThread *rf_thread;
167
168     foreach (ri, recent_items) {
169         if (ri->in_thread) {
170             continue;
171         }
172
173         rf_thread = new QThread;
174         rf_status = new RecentFileStatus(ri->filename);
175
176         rf_status->moveToThread(rf_thread);
177
178         connect(rf_thread, SIGNAL(started()), rf_status, SLOT(start()));
179
180         connect(rf_status, SIGNAL(statusFound(QString, qint64, bool)), this, SLOT(itemStatusFinished(QString, qint64, bool)));
181         connect(rf_status, SIGNAL(finished()), rf_thread, SLOT(quit()));
182         connect(rf_status, SIGNAL(finished()), rf_status, SLOT(deleteLater()));
183
184         rf_thread->start();
185     }
186 }
187
188 void WiresharkApplication::updateTaps()
189 {
190     draw_tap_listeners(FALSE);
191 }
192
193 void WiresharkApplication::captureCallback(int event _U_, capture_session *cap_session _U_)
194 {
195 #ifdef HAVE_LIBPCAP
196     switch(event) {
197     case(capture_cb_capture_prepared):
198         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
199         emit captureCapturePrepared(cap_session);
200         break;
201     case(capture_cb_capture_update_started):
202         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
203         emit captureCaptureUpdateStarted(cap_session);
204         break;
205     case(capture_cb_capture_update_continue):
206         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");
207         emit captureCaptureUpdateContinue(cap_session);
208         break;
209     case(capture_cb_capture_update_finished):
210         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
211         emit captureCaptureUpdateFinished(cap_session);
212         break;
213     case(capture_cb_capture_fixed_started):
214         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
215         emit captureCaptureFixedStarted(cap_session);
216         break;
217     case(capture_cb_capture_fixed_continue):
218         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
219         break;
220     case(capture_cb_capture_fixed_finished):
221         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
222         emit captureCaptureFixedFinished(cap_session);
223         break;
224     case(capture_cb_capture_stopping):
225         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
226         /* Beware: this state won't be called, if the capture child
227          * closes the capturing on it's own! */
228         emit captureCaptureStopping(cap_session);
229         break;
230     case(capture_cb_capture_failed):
231         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture failed");
232         emit captureCaptureFailed(cap_session);
233         break;
234     default:
235         g_warning("main_capture_callback: event %u unknown", event);
236         g_assert_not_reached();
237     }
238 #endif // HAVE_LIBPCAP
239 }
240
241 void WiresharkApplication::captureFileCallback(int event, void * data)
242 {
243     capture_file *cf = (capture_file *) data;
244
245     switch(event) {
246
247     case(cf_cb_file_opened):
248         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Opened");
249         emit captureFileOpened(cf);
250         break;
251     case(cf_cb_file_closing):
252         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
253         emit captureFileClosing(cf);
254         break;
255     case(cf_cb_file_closed):
256         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
257         emit captureFileClosed(cf);
258         break;
259     case(cf_cb_file_read_started):
260         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
261         emit captureFileReadStarted(cf);
262         break;
263     case(cf_cb_file_read_finished):
264         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
265         emit captureFileReadFinished(cf);
266         break;
267     case(cf_cb_file_reload_started):
268         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload started");
269         emit captureFileReadStarted(cf);
270         break;
271     case(cf_cb_file_reload_finished):
272         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
273         emit captureFileReadFinished(cf);
274         break;
275
276     case(cf_cb_packet_selected):
277     case(cf_cb_packet_unselected):
278     case(cf_cb_field_unselected):
279         // Pure signals and slots
280         break;
281
282 //    case(cf_cb_file_save_started): // data = string
283 //        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
284 //        break;
285 //    case(cf_cb_file_save_finished):
286 //        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
287 //        break;
288 //    case(cf_cb_file_save_failed):
289 //        g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
290 //        break;
291     default:
292         g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: main_cf_callback %d %p", event, data);
293 //        g_warning("main_cf_callback: event %u unknown", event);
294 //        g_assert_not_reached();
295     }
296 }
297
298 QDir WiresharkApplication::lastOpenDir() {
299     return QDir(last_open_dir);
300 }
301
302 void WiresharkApplication::setLastOpenDir(QString *dir_str) {
303     setLastOpenDir(dir_str->toUtf8().constData());
304 }
305
306 void WiresharkApplication::helpTopicAction(topic_action_e action)
307 {
308     char *url;
309
310     url = topic_action_url(action);
311
312     if(url != NULL) {
313         QDesktopServices::openUrl(QUrl(url));
314         g_free(url);
315     }
316 }
317
318 void WiresharkApplication::setMonospaceFont(const char *font_string) {
319
320     if (font_string && strlen(font_string) > 0) {
321         mono_regular_font_.fromString(font_string);
322         mono_bold_font_ = QFont(mono_regular_font_);
323         mono_bold_font_.setBold(true);
324         return;
325     }
326
327     // http://en.wikipedia.org/wiki/Category:Monospaced_typefaces
328     const char *win_default_font = "Consolas";
329     const char *win_alt_font = "Lucida Console";
330     const char *osx_default_font = "Menlo";
331     const char *osx_alt_font = "Monaco";
332     const char *x11_default_font = "Bitstream Vera Sans Mono";
333     const QStringList x11_alt_fonts = QStringList() << "Liberation Mono" << "DejaVu Sans Mono";
334     const QStringList fallback_fonts = QStringList() << "Lucida Sans Typewriter" << "Inconsolata" << "Droid Sans Mono" << "Andale Mono" << "Courier New" << "monospace";
335     QStringList substitutes;
336     int font_size_adjust = 0;
337
338     // Try to pick the latest, shiniest fixed-width font for our OS.
339 #if defined(Q_OS_WIN)
340     const char *default_font = win_default_font;
341     substitutes << win_alt_font << osx_default_font << osx_alt_font << x11_default_font << x11_alt_fonts << fallback_fonts;
342     font_size_adjust = 2;
343 #elif defined(Q_OS_MAC)
344     const char *default_font = osx_default_font;
345     substitutes << osx_alt_font << win_default_font << win_alt_font << x11_default_font << x11_alt_fonts << fallback_fonts;
346 #else
347     const char *default_font = x11_default_font;
348     substitutes << x11_alt_fonts << win_default_font << win_alt_font << osx_default_font << osx_alt_font << fallback_fonts;
349 #endif
350
351     mono_regular_font_.setFamily(default_font);
352     mono_regular_font_.insertSubstitutions(default_font, substitutes);
353     mono_regular_font_.setPointSize(wsApp->font().pointSize() + font_size_adjust);
354     mono_regular_font_.setBold(false);
355
356     mono_bold_font_ = QFont(mono_regular_font_);
357     mono_bold_font_.setBold(true);
358
359     g_free(prefs.gui_qt_font_name);
360     prefs.gui_qt_font_name = g_strdup(mono_regular_font_.toString().toUtf8().constData());
361 }
362
363 int WiresharkApplication::monospaceTextSize(const char *str, bool bold)
364 {
365     QFontMetrics *fm;
366
367     if (bold)
368         fm = new QFontMetrics(mono_bold_font_);
369     else
370         fm = new QFontMetrics(mono_regular_font_);
371
372     return fm->width(str);
373 }
374
375 QFont WiresharkApplication::monospaceFont(bool bold)
376 {
377     return bold ? mono_bold_font_ : mono_regular_font_;
378 }
379
380 void WiresharkApplication::setConfigurationProfile(const gchar *profile_name)
381 {
382     char  *gdp_path, *dp_path;
383     char  *rf_path;
384     int    rf_open_errno;
385
386     /* First check if profile exists */
387     if (!profile_exists(profile_name, FALSE)) {
388         if (profile_exists(profile_name, TRUE)) {
389             char  *pf_dir_path, *pf_dir_path2, *pf_filename;
390             /* Copy from global profile */
391             if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
392                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
393                     "Can't create directory\n\"%s\":\n%s.",
394                     pf_dir_path, g_strerror(errno));
395
396                 g_free(pf_dir_path);
397             }
398
399             if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
400                     &pf_dir_path, &pf_dir_path2) == -1) {
401                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
402                     "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
403                     pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
404
405                 g_free(pf_filename);
406                 g_free(pf_dir_path);
407                 g_free(pf_dir_path2);
408             }
409         } else {
410             /* No personal and no global profile exists */
411             return;
412         }
413     }
414
415     /* Then check if changing to another profile */
416     if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
417         return;
418     }
419
420     /* Get the current geometry, before writing it to disk */
421 //    main_save_window_geometry(top_level);
422
423     if (profile_exists(get_profile_name(), FALSE)) {
424         /* Write recent file for profile we are leaving, if it still exists */
425         write_profile_recent();
426     }
427
428     /* Set profile name and update the status bar */
429     set_profile_name (profile_name);
430     emit configurationProfileChanged(profile_name);
431
432     /* Reset current preferences and apply the new */
433     prefs_reset();
434 //    menu_prefs_reset();
435
436     (void) readConfigurationFiles (&gdp_path, &dp_path);
437
438     recent_read_profile_static(&rf_path, &rf_open_errno);
439     if (rf_path != NULL && rf_open_errno != 0) {
440         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
441             "Could not open common recent file\n\"%s\": %s.",
442             rf_path, g_strerror(rf_open_errno));
443     }
444     if (recent.gui_fileopen_remembered_dir &&
445         test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
446         set_last_open_dir(recent.gui_fileopen_remembered_dir);
447     }
448     timestamp_set_type (recent.gui_time_format);
449     timestamp_set_seconds_type (recent.gui_seconds_format);
450     color_filters_enable(recent.packet_list_colorize);
451     tap_update_timer_.setInterval(prefs.tap_update_interval);
452
453     prefs_to_capture_opts();
454     prefs_apply_all();
455     emit filterExpressionsChanged();
456 //    macros_post_update();
457
458     /* Enable all protocols and disable from the disabled list */
459     proto_enable_all();
460     if (gdp_path == NULL && dp_path == NULL) {
461         set_disabled_protos_list();
462     }
463
464     /* Reload color filters */
465     color_filters_reload();
466
467 //    user_font_apply();
468
469     /* Update menus with new recent values */
470 //    menu_recent_read_finished();
471 }
472
473 void WiresharkApplication::setLastOpenDir(const char *dir_name)
474 {
475     qint64 len;
476     gchar *new_last_open_dir;
477
478     if (dir_name) {
479         len = strlen(dir_name);
480         if (dir_name[len-1] == G_DIR_SEPARATOR) {
481             new_last_open_dir = g_strconcat(dir_name, (char *)NULL);
482         }
483         else {
484             new_last_open_dir = g_strconcat(dir_name,
485                                             G_DIR_SEPARATOR_S, (char *)NULL);
486         }
487
488         if (last_open_dir == NULL ||
489             strcmp(last_open_dir, new_last_open_dir) != 0)
490             updated_last_open_dir = TRUE;
491     }
492     else {
493         new_last_open_dir = NULL;
494         if (last_open_dir != NULL)
495             updated_last_open_dir = TRUE;
496     }
497
498     g_free(last_open_dir);
499     last_open_dir = new_last_open_dir;
500 }
501
502 bool WiresharkApplication::event(QEvent *event)
503 {
504     if (event->type() == QEvent::FileOpen) {
505         QFileOpenEvent *foe = static_cast<QFileOpenEvent *>(event);
506         if (foe && foe->file().length() > 0) {
507             QString cf_path(foe->file());
508             if (initialized_) {
509                 emit openCaptureFile(cf_path);
510             } else {
511                 pending_open_files_.append(cf_path);
512             }
513         }
514         return true;
515     }
516     return QApplication::event(event);
517 }
518
519 void WiresharkApplication::clearRecentItems() {
520     recent_item_status *ri;
521
522     foreach (ri, recent_items) {
523         recent_items.removeOne(ri);
524         delete(ri);
525     }
526     emit updateRecentItemStatus(NULL, 0, false);
527 }
528
529 void WiresharkApplication::cleanup()
530 {
531     software_update_cleanup();
532     /* write user's recent file to disk
533      * It is no problem to write this file, even if we do not quit */
534     write_profile_recent();
535     write_recent();
536 }
537
538 void WiresharkApplication::itemStatusFinished(const QString &filename, qint64 size, bool accessible) {
539     recent_item_status *ri;
540     RecentFileStatus *rf_status = qobject_cast<RecentFileStatus *>(QObject::sender());
541
542 //    g_log(NULL, G_LOG_LEVEL_DEBUG, "rf isf %d", recent_items.count());
543     foreach (ri, recent_items) {
544         if (filename == ri->filename && (size != ri->size || accessible != ri->accessible)) {
545             ri->size = size;
546             ri->accessible = accessible;
547             ri->in_thread = false;
548
549 //            g_log(NULL, G_LOG_LEVEL_DEBUG, "rf update %s", filename.toUtf8().constData());
550             emit updateRecentItemStatus(filename, size, accessible);
551         }
552     }
553
554     if (rf_status) {
555         rf_status->quit();
556     }
557 }
558
559 WiresharkApplication::WiresharkApplication(int &argc,  char **argv) :
560     QApplication(argc, argv),
561     initialized_(false)
562 {
563     wsApp = this;
564
565     Q_INIT_RESOURCE(about);
566     Q_INIT_RESOURCE(display_filter);
567     Q_INIT_RESOURCE(i18n);
568     Q_INIT_RESOURCE(layout);
569     Q_INIT_RESOURCE(status);
570     Q_INIT_RESOURCE(toolbar);
571     Q_INIT_RESOURCE(welcome);
572
573 #ifdef Q_OS_WIN
574     /* RichEd20.DLL is needed for native file dialog filter entries. */
575     if (QLibrary::isLibrary("riched20.dll")) {
576         QLibrary riched20("riched20.dll");
577         riched20.load();
578         if (!riched20.isLoaded()) {
579             qDebug() << riched20.errorString();
580         }
581     }
582 #endif // Q_OS_WIN
583
584     setAttribute(Qt::AA_DontShowIconsInMenus, true);
585
586     recent_timer_.setParent(this);
587     connect(&recent_timer_, SIGNAL(timeout()), this, SLOT(refreshRecentFiles()));
588     recent_timer_.start(2000);
589
590     tap_update_timer_.setParent(this);
591     tap_update_timer_.setInterval(TAP_UPDATE_DEFAULT_INTERVAL);
592     connect(this, SIGNAL(appInitialized()), &tap_update_timer_, SLOT(start()));
593     connect(&tap_update_timer_, SIGNAL(timeout()), this, SLOT(updateTaps()));
594
595     connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(cleanup()));
596 }
597
598 void WiresharkApplication::registerUpdate(register_action_e action, const char *message)
599 {
600     emit splashUpdate(action, message);
601 }
602
603 void WiresharkApplication::emitAppSignal(AppSignal signal)
604 {
605     switch (signal) {
606     case ColumnsChanged:
607         emit columnsChanged();
608         break;
609     case FilterExpressionsChanged:
610         emit filterExpressionsChanged();
611     case PreferencesChanged:
612         emit preferencesChanged();
613         break;
614     case PacketDissectionChanged:
615         emit packetDissectionChanged();
616         break;
617     case StaticRecentFilesRead:
618         emit recentFilesRead();
619         break;
620     default:
621         break;
622     }
623 }
624
625 void WiresharkApplication::allSystemsGo()
626 {    
627     initialized_ = true;
628     emit appInitialized();
629     while (pending_open_files_.length() > 0) {
630         emit openCaptureFile(pending_open_files_.front());
631         pending_open_files_.pop_front();
632     }
633     software_update_init();
634 }
635
636 e_prefs * WiresharkApplication::readConfigurationFiles(char **gdp_path, char **dp_path)
637 {
638     int                  gpf_open_errno, gpf_read_errno;
639     int                  cf_open_errno, df_open_errno;
640     int                  gdp_open_errno, gdp_read_errno;
641     int                  dp_open_errno, dp_read_errno;
642     char                *gpf_path, *pf_path;
643     char                *cf_path, *df_path;
644     int                  pf_open_errno, pf_read_errno;
645     e_prefs             *prefs_p;
646
647     /* load the decode as entries of this profile */
648     load_decode_as_entries();
649
650     /* Read the preference files. */
651     prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
652                          &pf_open_errno, &pf_read_errno, &pf_path);
653
654     if (gpf_path != NULL) {
655         if (gpf_open_errno != 0) {
656             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
657                           "Could not open global preferences file\n\"%s\": %s.", gpf_path,
658                           g_strerror(gpf_open_errno));
659         }
660         if (gpf_read_errno != 0) {
661             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
662                           "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
663                           g_strerror(gpf_read_errno));
664         }
665     }
666     if (pf_path != NULL) {
667         if (pf_open_errno != 0) {
668             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
669                           "Could not open your preferences file\n\"%s\": %s.", pf_path,
670                           g_strerror(pf_open_errno));
671         }
672         if (pf_read_errno != 0) {
673             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
674                           "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
675                           g_strerror(pf_read_errno));
676         }
677         g_free(pf_path);
678         pf_path = NULL;
679     }
680
681 #ifdef _WIN32
682     /* if the user wants a console to be always there, well, we should open one for him */
683     if (prefs_p->gui_console_open == console_open_always) {
684         create_console();
685     }
686 #endif
687
688     /* Read the capture filter file. */
689     read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
690     if (cf_path != NULL) {
691         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
692                       "Could not open your capture filter file\n\"%s\": %s.", cf_path,
693                       g_strerror(cf_open_errno));
694         g_free(cf_path);
695     }
696
697     /* Read the display filter file. */
698     read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
699     if (df_path != NULL) {
700         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
701                       "Could not open your display filter file\n\"%s\": %s.", df_path,
702                       g_strerror(df_open_errno));
703         g_free(df_path);
704     }
705
706     /* Read the disabled protocols file. */
707     read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
708                               dp_path, &dp_open_errno, &dp_read_errno);
709     if (*gdp_path != NULL) {
710         if (gdp_open_errno != 0) {
711             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
712                           "Could not open global disabled protocols file\n\"%s\": %s.",
713                           *gdp_path, g_strerror(gdp_open_errno));
714         }
715         if (gdp_read_errno != 0) {
716             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
717                           "I/O error reading global disabled protocols file\n\"%s\": %s.",
718                           *gdp_path, g_strerror(gdp_read_errno));
719         }
720         g_free(*gdp_path);
721         *gdp_path = NULL;
722     }
723     if (*dp_path != NULL) {
724         if (dp_open_errno != 0) {
725             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
726                           "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
727                           g_strerror(dp_open_errno));
728         }
729         if (dp_read_errno != 0) {
730             simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
731                           "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
732                           g_strerror(dp_read_errno));
733         }
734         g_free(*dp_path);
735         *dp_path = NULL;
736     }
737
738     return prefs_p;
739 }
740
741 QList<recent_item_status *> WiresharkApplication::recentItems() const {
742     return recent_items;
743 }
744
745 void WiresharkApplication::addRecentItem(const QString &filename, qint64 size, bool accessible) {
746     recent_item_status *ri = new(recent_item_status);
747
748     ri->filename = filename;
749     ri->size = size;
750     ri->accessible = accessible;
751     ri->in_thread = false;
752     recent_items.prepend(ri);
753
754     itemStatusFinished(filename, size, accessible);
755 }
756
757 /*
758  * Editor modelines
759  *
760  * Local Variables:
761  * c-basic-offset: 4
762  * tab-width: 8
763  * indent-tabs-mode: nil
764  * End:
765  *
766  * ex: set shiftwidth=4 tabstop=8 expandtab:
767  * :indentSize=4:tabSize=8:noTabs=true:
768  */