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