From 579e7e19ce8e5f1a6e16b75f130ad4b001157ca5 Mon Sep 17 00:00:00 2001 From: Michal Labedzki Date: Sat, 18 Jan 2014 15:20:02 +0100 Subject: [PATCH] Wireshark: Add option to choose format type of capture file The best heuristic can fail, so add possibility to manually choose capture file format type, so not correctly recognize file format can be loaded in Wireshark. On the other side now it is possible to open capture file as file format to be dissected. Change-Id: I5a9f662b32ff7e042f753a92eaaa86c6e41f400a Reviewed-on: https://code.wireshark.org/review/16 Reviewed-by: Michal Labedzki Reviewed-by: Hadriel Kaplan Reviewed-by: Evan Huus Tested-by: Evan Huus --- capinfos.c | 3 +- capture.c | 4 +- capture_info.c | 2 +- captype.c | 3 +- editcap.c | 3 +- file.c | 10 +- file.h | 3 +- reordercap.c | 4 +- tfshark.c | 8 +- tshark.c | 10 +- ui/gtk/capture_file_dlg.c | 31 +++- ui/gtk/drag_and_drop.c | 4 +- ui/gtk/file_import_dlg.c | 2 +- ui/gtk/fileset_dlg.c | 2 +- ui/gtk/funnel_stat.c | 2 +- ui/gtk/main.c | 4 +- ui/gtk/main_menubar.c | 4 +- ui/qt/capture_file_dialog.cpp | 18 ++- ui/qt/capture_file_dialog.h | 5 +- ui/qt/main.cpp | 2 + ui/qt/main_window.cpp | 2 +- ui/qt/main_window_slots.cpp | 5 +- ui/tap_export_pdu.c | 2 +- ui/win32/file_dlg_win32.c | 2 +- wiretap/file_access.c | 272 ++++++++++++++++------------------ wiretap/merge.c | 2 +- wiretap/wtap.h | 23 ++- 27 files changed, 242 insertions(+), 190 deletions(-) diff --git a/capinfos.c b/capinfos.c index 0a600a08b4..3a1a726a23 100644 --- a/capinfos.c +++ b/capinfos.c @@ -1126,6 +1126,7 @@ main(int argc, char *argv[]) * Get credential information for later use. */ init_process_policies(); + init_open_routines(); #ifdef HAVE_PLUGINS if ((init_progfile_dir_error = init_progfile_dir(argv[0], main))) { @@ -1407,7 +1408,7 @@ main(int argc, char *argv[]) } #endif /* HAVE_LIBGCRYPT */ - wth = wtap_open_offline(argv[opt], &err, &err_info, FALSE); + wth = wtap_open_offline(argv[opt], WTAP_TYPE_AUTO, &err, &err_info, FALSE); if (!wth) { fprintf(stderr, "capinfos: Can't open %s: %s\n", argv[opt], diff --git a/capture.c b/capture.c index 9477919d2a..9e10692465 100644 --- a/capture.c +++ b/capture.c @@ -236,7 +236,7 @@ capture_input_read_all(capture_session *cap_session, gboolean is_tempfile, int err; /* Capture succeeded; attempt to open the capture file. */ - if (cf_open((capture_file *)cap_session->cf, capture_opts->save_file, is_tempfile, &err) != CF_OK) { + if (cf_open((capture_file *)cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, is_tempfile, &err) != CF_OK) { /* We're not doing a capture any more, so we don't have a save file. */ return FALSE; } @@ -362,7 +362,7 @@ capture_input_new_file(capture_session *cap_session, gchar *new_file) /* if we are in real-time mode, open the new file now */ if(capture_opts->real_time_mode) { /* Attempt to open the capture file and set up to read from it. */ - switch(cf_open((capture_file *)cap_session->cf, capture_opts->save_file, is_tempfile, &err)) { + switch(cf_open((capture_file *)cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, is_tempfile, &err)) { case CF_OK: break; case CF_ERROR: diff --git a/capture_info.c b/capture_info.c index ad1028ad3b..2f339b06c2 100644 --- a/capture_info.c +++ b/capture_info.c @@ -221,7 +221,7 @@ gboolean capture_info_new_file(const char *new_filename) wtap_close(info_data.wtap); } - info_data.wtap = wtap_open_offline(new_filename, &err, &err_info, FALSE); + info_data.wtap = wtap_open_offline(new_filename, WTAP_TYPE_AUTO, &err, &err_info, FALSE); if (!info_data.wtap) { err_msg = g_strdup_printf(cf_open_error_message(err, err_info, FALSE, WTAP_FILE_TYPE_SUBTYPE_UNKNOWN), new_filename); diff --git a/captype.c b/captype.c index 885cff4d18..42341e7b4f 100644 --- a/captype.c +++ b/captype.c @@ -112,6 +112,7 @@ main(int argc, char *argv[]) * Get credential information for later use. */ init_process_policies(); + init_open_routines(); #ifdef HAVE_PLUGINS if ((init_progfile_dir_error = init_progfile_dir(argv[0], main))) { @@ -143,7 +144,7 @@ main(int argc, char *argv[]) overall_error_status = 0; for (i = 1; i < argc; i++) { - wth = wtap_open_offline(argv[i], &err, &err_info, FALSE); + wth = wtap_open_offline(argv[i], WTAP_TYPE_AUTO, &err, &err_info, FALSE); if(wth) { printf("%s: %s\n", argv[i], wtap_file_type_subtype_short_string(wtap_file_type_subtype(wth))); diff --git a/editcap.c b/editcap.c index 48a1ab40aa..ebd0ce2896 100644 --- a/editcap.c +++ b/editcap.c @@ -884,6 +884,7 @@ main(int argc, char *argv[]) * Get credential information for later use. */ init_process_policies(); + init_open_routines(); #ifdef HAVE_PLUGINS /* Register wiretap plugins */ @@ -1148,7 +1149,7 @@ main(int argc, char *argv[]) exit(1); } - wth = wtap_open_offline(argv[optind], &err, &err_info, FALSE); + wth = wtap_open_offline(argv[optind], WTAP_TYPE_AUTO, &err, &err_info, FALSE); if (!wth) { fprintf(stderr, "editcap: Can't open %s: %s\n", argv[optind], diff --git a/file.c b/file.c index 87ec088311..9b2def0602 100644 --- a/file.c +++ b/file.c @@ -336,12 +336,12 @@ ws_epan_new(capture_file *cf) } cf_status_t -cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) +cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { wtap *wth; gchar *err_info; - wth = wtap_open_offline(fname, err, &err_info, TRUE); + wth = wtap_open_offline(fname, type, err, &err_info, TRUE); if (wth == NULL) goto fail; @@ -4336,7 +4336,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) wtap_close(cf->wth); /* Open the new file. */ - cf->wth = wtap_open_offline(fname, err, &err_info, TRUE); + cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE); if (cf->wth == NULL) { cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0); return CF_READ_ERROR; @@ -4770,7 +4770,7 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format, the wtap structure, the filename, and the "is temporary" status applies to the new file; just update that. */ wtap_close(cf->wth); - cf->wth = wtap_open_offline(fname, &err, &err_info, TRUE); + cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); if (cf->wth == NULL) { cf_open_failure_alert_box(fname, err, err_info, FALSE, 0); cf_close(cf); @@ -5212,7 +5212,7 @@ cf_reload(capture_file *cf) { filename = g_strdup(cf->filename); is_tempfile = cf->is_tempfile; cf->is_tempfile = FALSE; - if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) { + if (cf_open(cf, filename, WTAP_TYPE_AUTO, is_tempfile, &err) == CF_OK) { switch (cf_read(cf, TRUE)) { case CF_READ_OK: diff --git a/file.h b/file.h index e375a196f1..a3a0eab997 100644 --- a/file.h +++ b/file.h @@ -108,11 +108,12 @@ cf_callback_remove(cf_callback_t func); * * @param cf the capture file to be opened * @param fname the filename to be opened + * @param type WTAP_TYPE_AUTO for automatic or index to direct open routine * @param is_tempfile is this a temporary file? * @param err error code * @return one of cf_status_t */ -cf_status_t cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err); +cf_status_t cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err); /** * Close a capture file. diff --git a/reordercap.c b/reordercap.c index 57741e9cea..b9c0763f8a 100644 --- a/reordercap.c +++ b/reordercap.c @@ -221,8 +221,10 @@ int main(int argc, char *argv[]) exit(1); } + init_open_routines(); + /* Open infile */ - wth = wtap_open_offline(infile, &err, &err_info, TRUE); + wth = wtap_open_offline(infile, WTAP_TYPE_AUTO, &err, &err_info, TRUE); if (wth == NULL) { fprintf(stderr, "reordercap: Can't open %s: %s\n", infile, wtap_strerror(err)); diff --git a/tfshark.c b/tfshark.c index e691815035..2ac3499efd 100644 --- a/tfshark.c +++ b/tfshark.c @@ -906,6 +906,8 @@ main(int argc, char *argv[]) timestamp_set_precision(TS_PREC_AUTO); timestamp_set_seconds_type(TS_SECONDS_DEFAULT); + init_open_routines(); + #ifdef HAVE_PLUGINS /* Register all the plugin types we have. */ epan_register_plugin_types(); /* Types known to libwireshark */ @@ -1425,7 +1427,7 @@ main(int argc, char *argv[]) relinquish_special_privs_perm(); print_current_user(); - if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) { + if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) { epan_cleanup(); return 2; } @@ -2498,7 +2500,7 @@ write_finale(void) } cf_status_t -cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) +cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { #if USE_FTAP ftap *fth; @@ -2513,7 +2515,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) if (fth == NULL) goto fail; #else - wth = wtap_open_offline(fname, err, &err_info, perform_two_pass_analysis); + wth = wtap_open_offline(fname, type, err, &err_info, perform_two_pass_analysis); if (wth == NULL) goto fail; #endif diff --git a/tshark.c b/tshark.c index 85e4104dd3..b951e1c87d 100644 --- a/tshark.c +++ b/tshark.c @@ -1110,6 +1110,8 @@ main(int argc, char *argv[]) timestamp_set_precision(TS_PREC_AUTO); timestamp_set_seconds_type(TS_SECONDS_DEFAULT); + init_open_routines(); + #ifdef HAVE_PLUGINS /* Register all the plugin types we have. */ epan_register_plugin_types(); /* Types known to libwireshark */ @@ -1999,7 +2001,7 @@ main(int argc, char *argv[]) relinquish_special_privs_perm(); print_current_user(); - if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) { + if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) { epan_cleanup(); return 2; } @@ -2594,7 +2596,7 @@ capture_input_new_file(capture_session *cap_session, gchar *new_file) /* if we are in real-time mode, open the new file now */ if (do_dissection) { /* Attempt to open the capture file and set up to read from it. */ - switch(cf_open((capture_file *)cap_session->cf, capture_opts->save_file, is_tempfile, &err)) { + switch(cf_open((capture_file *)cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, is_tempfile, &err)) { case CF_OK: break; case CF_ERROR: @@ -3945,13 +3947,13 @@ write_finale(void) } cf_status_t -cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) +cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { wtap *wth; gchar *err_info; char err_msg[2048+1]; - wth = wtap_open_offline(fname, err, &err_info, perform_two_pass_analysis); + wth = wtap_open_offline(fname, type, err, &err_info, perform_two_pass_analysis); if (wth == NULL) goto fail; diff --git a/ui/gtk/capture_file_dlg.c b/ui/gtk/capture_file_dlg.c index 9e852629f2..e79e8deced 100644 --- a/ui/gtk/capture_file_dlg.c +++ b/ui/gtk/capture_file_dlg.c @@ -139,7 +139,7 @@ preview_set_filename(GtkWidget *prev, const gchar *cf_name) return NULL; } - wth = wtap_open_offline(cf_name, &err, &err_info, TRUE); + wth = wtap_open_offline(cf_name, WTAP_TYPE_AUTO, &err, &err_info, TRUE); if (wth == NULL) { label = (GtkWidget *)g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY); if (err == WTAP_ERR_FILE_UNKNOWN_FORMAT) { @@ -474,11 +474,14 @@ preview_new(void) /* Open a file */ static gboolean -gtk_open_file(GtkWidget *w, GString *file_name, GString *display_filter) +gtk_open_file(GtkWidget *w, GString *file_name, gint *type, GString *display_filter) { GtkWidget *file_open_w; GtkWidget *main_hb, *main_vb, *filter_hbox, *filter_bt, *filter_te; GtkWidget *m_resolv_cb, *n_resolv_cb, *t_resolv_cb, *e_resolv_cb, *prev; + GtkWidget *format_type_co; + GtkCellRenderer *cell; + gint i; /* No Apply button, and "OK" just sets our text widget, it doesn't activate it (i.e., it doesn't cause us to try to open the file). */ @@ -542,6 +545,21 @@ gtk_open_file(GtkWidget *w, GString *file_name, GString *display_filter) gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0); gtk_widget_show(main_vb); + format_type_co = gtk_combo_box_text_new(); + cell = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(format_type_co), cell, TRUE); + + gtk_widget_set_tooltip_text(format_type_co, "Format type of capture file"); + gtk_box_pack_start(GTK_BOX(main_vb), format_type_co, FALSE, FALSE, 0); + + gtk_combo_box_text_append_text((GtkComboBoxText *) format_type_co, (const gchar *) "Automatic"); + for (i = 0; open_routines[i].name != NULL; i += 1) { + gtk_combo_box_text_append_text((GtkComboBoxText *) format_type_co, open_routines[i].name); + } + + gtk_combo_box_set_active((GtkComboBox *) format_type_co, 0); + gtk_widget_show(format_type_co); + /* Filter row */ filter_hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1, FALSE); gtk_container_set_border_width(GTK_CONTAINER(filter_hbox), 0); @@ -639,6 +657,8 @@ gtk_open_file(GtkWidget *w, GString *file_name, GString *display_filter) else gbl_resolv_flags.use_external_net_name_resolver = FALSE; + *type = gtk_combo_box_get_active((GtkComboBox *) format_type_co); + /* We've crossed the Rubicon; get rid of the file selection box. */ window_destroy(GTK_WIDGET(file_open_w)); @@ -666,6 +686,7 @@ file_open_cmd(capture_file *cf, GtkWidget *w _U_) GString *display_filter = g_string_new(""); dfilter_t *rfcode = NULL; int err; + int type = WTAP_TYPE_AUTO; /* * Loop until the user either selects a file or gives up. @@ -674,7 +695,7 @@ file_open_cmd(capture_file *cf, GtkWidget *w _U_) #ifdef USE_WIN32_FILE_DIALOGS if (win32_open_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), file_name, display_filter)) { #else /* USE_WIN32_FILE_DIALOGS */ - if (gtk_open_file(top_level, file_name, display_filter)) { + if (gtk_open_file(top_level, file_name, &type, display_filter)) { #endif /* USE_WIN32_FILE_DIALOGS */ /* Only close the old file now that we know we want to open another one. */ @@ -690,7 +711,7 @@ file_open_cmd(capture_file *cf, GtkWidget *w _U_) } /* Try to open the capture file. */ - if (cf_open(&cfile, file_name->str, FALSE, &err) != CF_OK) { + if (cf_open(&cfile, file_name->str, type, FALSE, &err) != CF_OK) { /* We couldn't open it; don't dismiss the open dialog box, just leave it around so that the user can, after they dismiss the alert box popped up for the open error, @@ -971,7 +992,7 @@ file_merge_cmd(GtkWidget *w _U_) cf_close(&cfile); /* Try to open the merged capture file. */ - if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) { + if (cf_open(&cfile, tmpname, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) { /* We couldn't open it; fail. */ if (rfcode != NULL) dfilter_free(rfcode); diff --git a/ui/gtk/drag_and_drop.c b/ui/gtk/drag_and_drop.c index 93e438a698..78db218385 100644 --- a/ui/gtk/drag_and_drop.c +++ b/ui/gtk/drag_and_drop.c @@ -204,7 +204,7 @@ dnd_open_file_cmd(gchar *cf_names_freeme) if (in_file_count == 1) { /* open and read the capture file (this will close an existing file) */ - if (cf_open(&cfile, in_filenames[0], FALSE, &err) == CF_OK) { + if (cf_open(&cfile, in_filenames[0], WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { /* XXX - add this to the menu if the read fails? */ cf_read(&cfile, FALSE); add_menu_recent_capture_file(in_filenames[0]); @@ -219,7 +219,7 @@ dnd_open_file_cmd(gchar *cf_names_freeme) /* Merge succeeded; close the currently-open file and try to open the merged capture file. */ cf_close(&cfile); - if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) == CF_OK) { + if (cf_open(&cfile, tmpname, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) == CF_OK) { g_free(tmpname); cf_read(&cfile, FALSE); } else { diff --git a/ui/gtk/file_import_dlg.c b/ui/gtk/file_import_dlg.c index 5ad8a80ce5..a59ac082c2 100644 --- a/ui/gtk/file_import_dlg.c +++ b/ui/gtk/file_import_dlg.c @@ -541,7 +541,7 @@ file_import_open(text_import_info_t *info) write_failure_alert_box(capfile_name, err); } - if (cf_open(&cfile, capfile_name, TRUE /* temporary file */, &err) != CF_OK) { + if (cf_open(&cfile, capfile_name, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) { open_failure_alert_box(capfile_name, err, FALSE); goto end; } diff --git a/ui/gtk/fileset_dlg.c b/ui/gtk/fileset_dlg.c index fbfa866772..3123c226c4 100644 --- a/ui/gtk/fileset_dlg.c +++ b/ui/gtk/fileset_dlg.c @@ -79,7 +79,7 @@ fs_open_entry(fileset_entry *entry) /* close the old and open the new file */ cf_close(&cfile); - if (cf_open(&cfile, fname, FALSE, &err) == CF_OK) { + if (cf_open(&cfile, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { cf_read(&cfile, FALSE); } diff --git a/ui/gtk/funnel_stat.c b/ui/gtk/funnel_stat.c index cc0cde0026..313a38a1a5 100644 --- a/ui/gtk/funnel_stat.c +++ b/ui/gtk/funnel_stat.c @@ -518,7 +518,7 @@ static gboolean funnel_open_file(const char* fname, const char* filter, const ch } - if (cf_open(&cfile, fname, FALSE, &err) != CF_OK) { + if (cf_open(&cfile, fname, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) { *err_str = g_strerror(err); if (rfcode != NULL) dfilter_free(rfcode); return FALSE; diff --git a/ui/gtk/main.c b/ui/gtk/main.c index a5e706dc9d..8748f0500f 100644 --- a/ui/gtk/main.c +++ b/ui/gtk/main.c @@ -2523,6 +2523,8 @@ main(int argc, char *argv[]) g_free(init_progfile_dir_error); } + init_open_routines(); + #ifdef HAVE_PLUGINS /* Register all the plugin types we have. */ epan_register_plugin_types(); /* Types known to libwireshark */ @@ -3088,7 +3090,7 @@ main(int argc, char *argv[]) } } if (!rfilter_parse_failed) { - if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) { + if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { /* "cf_open()" succeeded, so it closed the previous capture file, and thus destroyed any previous read filter attached to "cf". */ diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c index e8b119e3b8..3d5f681001 100644 --- a/ui/gtk/main_menubar.c +++ b/ui/gtk/main_menubar.c @@ -4323,7 +4323,7 @@ menu_open_filename(gchar *cf_name) recent_files_list = (GList *)g_object_get_data(G_OBJECT(submenu_recent_files), "recent-files-list"); /* XXX: ask user to remove item, it's maybe only a temporary problem */ /* open and read the capture file (this will close an existing file) */ - if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) { + if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { cf_read(&cfile, FALSE); }else{ recent_files_list = remove_present_file_name(recent_files_list, cf_name); @@ -4351,7 +4351,7 @@ menu_open_recent_file_cmd(GtkAction *action) #endif /* open and read the capture file (this will close an existing file) */ - if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) { + if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { cf_read(&cfile, FALSE); } else { submenu_recent_files = gtk_ui_manager_get_widget(ui_manager_main_menubar, MENU_RECENT_FILES_PATH); diff --git a/ui/qt/capture_file_dialog.cpp b/ui/qt/capture_file_dialog.cpp index 68cd033e1d..bb78faf3fb 100644 --- a/ui/qt/capture_file_dialog.cpp +++ b/ui/qt/capture_file_dialog.cpp @@ -231,7 +231,7 @@ bool CaptureFileDialog::isCompressed() { return compressed_; } -int CaptureFileDialog::open(QString &file_name) { +int CaptureFileDialog::open(QString &file_name, unsigned int &type) { GString *fname = g_string_new(file_name.toUtf8().constData()); GString *dfilter = g_string_new(display_filter_.toUtf8().constData()); gboolean wof_status; @@ -239,6 +239,7 @@ int CaptureFileDialog::open(QString &file_name) { // XXX Add a widget->HWND routine to qt_ui_utils and use it instead. wof_status = win32_open_file((HWND)parentWidget()->effectiveWinId(), fname, dfilter); file_name = fname->str; + type = format_type_.currentIndex(); display_filter_ = dfilter->str; g_string_free(fname, TRUE); @@ -499,6 +500,15 @@ void CaptureFileDialog::addDisplayFilterEdit() { last_row_++; } +void CaptureFileDialog::addFormatTypeSelector(QVBoxLayout &v_box) { + format_type_.addItem("Automatic"); + for (int i = 0; open_routines[i].name != NULL; i += 1) { + format_type_.addItem(open_routines[i].name); + } + + v_box.addWidget(&format_type_, 0, Qt::AlignTop); +} + void CaptureFileDialog::addResolutionControls(QVBoxLayout &v_box) { mac_res_.setText(tr("&MAC name resolution")); mac_res_.setChecked(gbl_resolv_flags.mac_name); @@ -548,11 +558,12 @@ QDialogButtonBox *CaptureFileDialog::addHelpButton(topic_action_e help_topic) return button_box; } -int CaptureFileDialog::open(QString &file_name) { +int CaptureFileDialog::open(QString &file_name, unsigned int &type) { setWindowTitle(tr("Wireshark: Open Capture File")); setNameFilters(buildFileOpenTypeList()); setFileMode(QFileDialog::ExistingFile); + addFormatTypeSelector(left_v_box_); addDisplayFilterEdit(); addResolutionControls(left_v_box_); addPreview(right_v_box_); @@ -569,6 +580,7 @@ int CaptureFileDialog::open(QString &file_name) { if (QFileDialog::exec() && selectedFiles().length() > 0) { file_name = selectedFiles()[0]; + type = format_type_.currentIndex(); display_filter_.append(display_filter_edit_->text()); gbl_resolv_flags.mac_name = mac_res_.isChecked(); @@ -761,7 +773,7 @@ void CaptureFileDialog::preview(const QString & path) return; } - wth = wtap_open_offline(path.toUtf8().data(), &err, &err_info, TRUE); + wth = wtap_open_offline(path.toUtf8().data(), WTAP_TYPE_AUTO, &err, &err_info, TRUE); if (wth == NULL) { if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) { preview_format_.setText(tr("unknown file format")); diff --git a/ui/qt/capture_file_dialog.h b/ui/qt/capture_file_dialog.h index 54f9e1d341..becaed6a58 100644 --- a/ui/qt/capture_file_dialog.h +++ b/ui/qt/capture_file_dialog.h @@ -41,6 +41,7 @@ #include #include #include +#include class CaptureFileDialog : public QFileDialog { @@ -87,6 +88,7 @@ private: #if !defined(Q_OS_WIN) void addMergeControls(QVBoxLayout &v_box); + void addFormatTypeSelector(QVBoxLayout &v_box); void addDisplayFilterEdit(); void addPreview(QVBoxLayout &v_box); QString fileExtensionType(int et, bool extension_globs = true); @@ -110,6 +112,7 @@ private: QRadioButton merge_chrono_; QRadioButton merge_append_; + QComboBox format_type_; QHashtype_hash_; void addResolutionControls(QVBoxLayout &v_box); @@ -143,7 +146,7 @@ signals: public slots: int exec(); - int open(QString &file_name); + int open(QString &file_name, unsigned int &type); check_savability_t saveAs(QString &file_name, bool must_support_comments); check_savability_t exportSelectedPackets(QString &file_name, packet_range_t *range); int merge(QString &file_name); diff --git a/ui/qt/main.cpp b/ui/qt/main.cpp index 33c3f660f9..eb9cb47524 100644 --- a/ui/qt/main.cpp +++ b/ui/qt/main.cpp @@ -832,6 +832,8 @@ int main(int argc, char *argv[]) init_report_err(failure_alert_box, open_failure_alert_box, read_failure_alert_box, write_failure_alert_box); + init_open_routines(); + #ifdef HAVE_PLUGINS /* Register all the plugin types we have. */ epan_register_plugin_types(); /* Types known to libwireshark */ diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 165bfc6aec..136ad37c1c 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -643,7 +643,7 @@ void MainWindow::mergeCaptureFile() /* Try to open the merged capture file. */ cfile.window = this; - if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) { + if (cf_open(&cfile, tmpname, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) { /* We couldn't open it; fail. */ cfile.window = NULL; if (rfcode != NULL) diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 0d40c33855..0fc02c7e4e 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -102,6 +102,7 @@ void MainWindow::openCaptureFile(QString &cf_path, QString &display_filter) QString file_name = ""; dfilter_t *rfcode = NULL; int err; + unsigned int type; testCaptureFileClose(false); @@ -130,7 +131,7 @@ void MainWindow::openCaptureFile(QString &cf_path, QString &display_filter) break; } - if (open_dlg.open(file_name)) { + if (open_dlg.open(file_name, type)) { if (dfilter_compile(display_filter.toUtf8().constData(), &rfcode)) { cf_set_rfcode(&cfile, rfcode); } else { @@ -153,7 +154,7 @@ void MainWindow::openCaptureFile(QString &cf_path, QString &display_filter) /* Try to open the capture file. */ cfile.window = this; - if (cf_open(&cfile, cf_path.toUtf8().constData(), FALSE, &err) != CF_OK) { + if (cf_open(&cfile, cf_path.toUtf8().constData(), type, FALSE, &err) != CF_OK) { /* We couldn't open it; don't dismiss the open dialog box, just leave it around so that the user can, after they dismiss the alert box popped up for the open error, diff --git a/ui/tap_export_pdu.c b/ui/tap_export_pdu.c index 9362e6765e..1a7a66c074 100644 --- a/ui/tap_export_pdu.c +++ b/ui/tap_export_pdu.c @@ -162,7 +162,7 @@ exp_pdu_file_open(exp_pdu_t *exp_pdu_tap_data) remove_tap_listener(exp_pdu_tap_data); - if (cf_open(&cfile, capfile_name, TRUE /* temporary file */, &err) != CF_OK) { + if (cf_open(&cfile, capfile_name, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) { open_failure_alert_box(capfile_name, err, FALSE); goto end; } diff --git a/ui/win32/file_dlg_win32.c b/ui/win32/file_dlg_win32.c index b4d3996ea2..d6bc34825c 100644 --- a/ui/win32/file_dlg_win32.c +++ b/ui/win32/file_dlg_win32.c @@ -1157,7 +1157,7 @@ preview_set_file_info(HWND of_hwnd, gchar *preview_file) { return FALSE; } - wth = wtap_open_offline(preview_file, &err, &err_info, TRUE); + wth = wtap_open_offline(preview_file, WTAP_TYPE_AUTO, &err, &err_info, TRUE); if (cur_ctrl && wth == NULL) { if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) { SetWindowText(cur_ctrl, _T("unknown file format")); diff --git a/wiretap/file_access.c b/wiretap/file_access.c index 0ea55b42c8..97b9c7f5f6 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -301,149 +301,98 @@ GSList *wtap_get_all_file_extensions_list(void) * just overwrite the pointer. */ - -/* Files that have magic bytes in fixed locations. These - * are easy to identify. Only an open routine is needed. - */ -static const wtap_open_routine_t magic_number_open_routines_base[] = { - libpcap_open, - pcapng_open, - ngsniffer_open, - snoop_open, - iptrace_open, - netmon_open, - netxray_open, - radcom_open, - nettl_open, - visual_open, - _5views_open, - network_instruments_open, - peektagged_open, - dbs_etherwatch_open, - k12_open, - catapult_dct2000_open, - aethra_open, - btsnoop_open, - eyesdn_open, - tnef_open, +static struct open_info open_info_base[] = { + { "Pcap", OPEN_INFO_MAGIC, libpcap_open, "pcap" }, + { "PcapNG", OPEN_INFO_MAGIC, pcapng_open, "pcapng"}, + { "NgSniffer", OPEN_INFO_MAGIC, ngsniffer_open, NULL }, + { "Snoop", OPEN_INFO_MAGIC, snoop_open, NULL }, + { "IP Trace", OPEN_INFO_MAGIC, iptrace_open, NULL }, + { "Netmon", OPEN_INFO_MAGIC, netmon_open, NULL }, + { "Netxray", OPEN_INFO_MAGIC, netxray_open, NULL }, + { "Radcom", OPEN_INFO_MAGIC, radcom_open, NULL }, + { "Nettl", OPEN_INFO_MAGIC, nettl_open, NULL }, + { "Visual", OPEN_INFO_MAGIC, visual_open, NULL }, + { "5 Views", OPEN_INFO_MAGIC, _5views_open, NULL }, + { "Network Instruments", OPEN_INFO_MAGIC, network_instruments_open, NULL }, + { "Peek Tagged", OPEN_INFO_MAGIC, peektagged_open, NULL }, + { "DBS Etherwatch", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL }, + { "K12", OPEN_INFO_MAGIC, k12_open, NULL }, + { "Catapult DCT 2000", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL }, + { "Aethra", OPEN_INFO_MAGIC, aethra_open, NULL }, + { "BTSNOOP", OPEN_INFO_MAGIC, btsnoop_open, "log" }, + { "EYESDN", OPEN_INFO_MAGIC, eyesdn_open, NULL }, + { "TNEF", OPEN_INFO_MAGIC, tnef_open, NULL }, + { "MIME Files with Magic Bytes", OPEN_INFO_MAGIC, mime_file_open, NULL }, + { "Lanalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1" }, + /* + * PacketLogger must come before MPEG, because its files + * are sometimes grabbed by mpeg_open. + */ + { "Packet Logger", OPEN_INFO_HEURISTIC, packetlogger_open, "pklg" }, + /* Some MPEG files have magic numbers, others just have heuristics. */ + { "Mpeg", OPEN_INFO_HEURISTIC, mpeg_open, "mpg;mp3" }, + { "DCT3 Trace", OPEN_INFO_HEURISTIC, dct3trace_open, "xml" }, + { "Daintree SNA", OPEN_INFO_HEURISTIC, daintree_sna_open, "dcf" }, + { "Stanag 4607", OPEN_INFO_HEURISTIC, stanag4607_open, NULL }, + { "BER", OPEN_INFO_HEURISTIC, ber_open, NULL }, + /* I put NetScreen *before* erf, because there were some + * false positives with my test-files (Sake Blok, July 2007) + * + * I put VWR *after* ERF, because there were some cases where + * ERF files were misidentified as vwr files (Stephen + * Donnelly, August 2013; see bug 9054) + * + * I put VWR *after* Peek Classic, CommView, iSeries text, + * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler, + * because there were some cases where files of those types were + * misidentified as vwr files (Guy Harris, December 2013) + */ + { "Netscreen", OPEN_INFO_HEURISTIC, netscreen_open, "txt" }, + { "ERF", OPEN_INFO_HEURISTIC, erf_open, "erf" }, + { "IPfix", OPEN_INFO_HEURISTIC, ipfix_open, "pfx;ipfix" }, + { "K12 Text", OPEN_INFO_HEURISTIC, k12text_open, "txt" }, + { "Peek Classic", OPEN_INFO_HEURISTIC, peekclassic_open, "pkt;tpc;apc;wpz" }, + { "PPP Dump", OPEN_INFO_HEURISTIC, pppdump_open, NULL }, + { "iSeries", OPEN_INFO_HEURISTIC, iseries_open, "txt" }, + { "i4btrace", OPEN_INFO_HEURISTIC, i4btrace_open, NULL }, + { "Mp2t", OPEN_INFO_HEURISTIC, mp2t_open, "ts;mpg" }, + { "Csids", OPEN_INFO_HEURISTIC, csids_open, NULL }, + { "VMS", OPEN_INFO_HEURISTIC, vms_open, "txt" }, + { "Cosine", OPEN_INFO_HEURISTIC, cosine_open, "txt" }, + { "Hcidump", OPEN_INFO_HEURISTIC, hcidump_open, NULL }, + { "Commview", OPEN_INFO_HEURISTIC, commview_open, "ncf" }, + { "Nstrace", OPEN_INFO_HEURISTIC, nstrace_open, "txt" }, + /* ASCII trace files from Telnet sessions. */ + { "Ascend", OPEN_INFO_HEURISTIC, ascend_open, "txt" }, + { "Toshiba", OPEN_INFO_HEURISTIC, toshiba_open, "txt" }, + /* Extremely weak heuristics - put them at the end. */ + { "VWR", OPEN_INFO_HEURISTIC, vwr_open, "vwr" }, + { "Camins", OPEN_INFO_HEURISTIC, camins_open, "camins" }, + { NULL, 0, NULL, NULL} }; -#define N_MAGIC_FILE_TYPES (sizeof magic_number_open_routines_base / sizeof magic_number_open_routines_base[0]) +#define N_OPEN_INFO_ROUTINES ((sizeof open_info_base / sizeof open_info_base[0])) -static wtap_open_routine_t* magic_number_open_routines = NULL; +struct open_info *open_routines = NULL; -static GArray* magic_number_open_routines_arr = NULL; +static GArray *open_info_arr = NULL; -/* - * Initialize the magic-number open routines array if it has not been - * initialized yet. - */ -static void init_magic_number_open_routines(void) { +void init_open_routines(void) { - if (magic_number_open_routines_arr) return; + if (open_info_arr) return; - magic_number_open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t)); + open_info_arr = g_array_new(FALSE,TRUE,sizeof(struct open_info)); - g_array_append_vals(magic_number_open_routines_arr,magic_number_open_routines_base,N_MAGIC_FILE_TYPES); + g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES); - magic_number_open_routines = (wtap_open_routine_t*)(void *)magic_number_open_routines_arr->data; + open_routines = (struct open_info *) open_info_arr->data; } -void wtap_register_magic_number_open_routine(wtap_open_routine_t open_routine) { - init_magic_number_open_routines(); +void wtap_register_open_info(const struct open_info *oi) { + init_open_routines(); - g_array_append_val(magic_number_open_routines_arr,open_routine); + g_array_append_val(open_info_arr, oi); - magic_number_open_routines = (wtap_open_routine_t*)(void *)magic_number_open_routines_arr->data; -} - -/* Files that don't have magic bytes at a fixed location, - * but that instead require a heuristic of some sort to - * identify them. This includes ASCII trace files. - * - * Entries for the ASCII trace files that would be, for example, - * saved copies of a Telnet session to some box are put after - * most of the other entries, as we don't want to treat a capture - * of such a session as a trace file from such a session - * merely because it has the right text in it. They still - * appear before the *really* weak entries, such as the VWR entry. - */ -static const struct heuristic_open_info heuristic_open_info_base[] = { - { lanalyzer_open, "tr1", }, - /* - * PacketLogger must come before MPEG, because its files - * are sometimes grabbed by mpeg_open. - */ - { packetlogger_open, "pklg" }, - /* Some MPEG files have magic numbers, others just have heuristics. */ - { mpeg_open, "mpg;mp3" }, - { dct3trace_open, "xml" }, - { daintree_sna_open, "dcf" }, - { mime_file_open, NULL }, - { stanag4607_open, NULL }, - { ber_open, NULL }, - - /* I put NetScreen *before* erf, because there were some - * false positives with my test-files (Sake Blok, July 2007) - * - * I put VWR *after* ERF, because there were some cases where - * ERF files were misidentified as vwr files (Stephen - * Donnelly, August 2013; see bug 9054) - * - * I put VWR *after* Peek Classic, CommView, iSeries text, - * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler, - * because there were some cases where files of those types were - * misidentified as vwr files (Guy Harris, December 2013) - */ - { netscreen_open, "txt" }, - { erf_open, "erf" }, - { ipfix_open, "pfx;ipfix" }, - { k12text_open, "txt" }, - { peekclassic_open, "pkt;tpc;apc;wpz" }, - { pppdump_open, NULL }, - { iseries_open, "txt" }, - { i4btrace_open, NULL }, - { mp2t_open, "ts;mpg" }, - { csids_open, NULL }, - { vms_open, "txt" }, - { cosine_open, "txt" }, - { hcidump_open, NULL }, - { commview_open, "ncf" }, - { nstrace_open, "txt" }, - - /* ASCII trace files from Telnet sessions. */ - { ascend_open, "txt" }, - { toshiba_open, "txt" }, - - /* Extremely weak heuristics - put them at the end. */ - { vwr_open, "vwr" }, - { camins_open, "camins" }, -}; -#define N_HEURISTIC_FILE_TYPES (sizeof heuristic_open_info_base / sizeof heuristic_open_info_base[0]) - -static const struct heuristic_open_info* heuristic_open_info = NULL; - -static GArray* heuristic_open_info_arr = NULL; - -/* - * Initialize the heuristics array if it has not been initialized yet. - */ -static void init_heuristic_open_info(void) { - - if (heuristic_open_info_arr) return; - - heuristic_open_info_arr = g_array_new(FALSE,TRUE,sizeof(struct heuristic_open_info)); - - g_array_append_vals(heuristic_open_info_arr,heuristic_open_info_base,N_HEURISTIC_FILE_TYPES); - - heuristic_open_info = (const struct heuristic_open_info*)(void *)heuristic_open_info_arr->data; -} - -void wtap_register_heuristic_open_info(const struct heuristic_open_info *hi) { - init_heuristic_open_info(); - - g_array_append_val(heuristic_open_info_arr,*hi); - - heuristic_open_info = (const struct heuristic_open_info*)(void *)heuristic_open_info_arr->data; + open_routines = (struct open_info *) open_info_arr->data; } /* @@ -566,13 +515,13 @@ static gboolean heuristic_uses_extension(unsigned int i, const char *extension) /* * Does this file type *have* any extensions? */ - if (heuristic_open_info[i].extensions == NULL) + if (open_routines[i].extensions == NULL) return FALSE; /* no */ /* * Get a list of the extensions used by the specified file type. */ - extensions_set = g_strsplit(heuristic_open_info[i].extensions, ";", 0); + extensions_set = g_strsplit(open_routines[i].extensions, ";", 0); /* * Check each of them against the specified extension. @@ -595,7 +544,7 @@ static gboolean heuristic_uses_extension(unsigned int i, const char *extension) so that it can do sequential I/O to a capture file that's being written to as new packets arrive independently of random I/O done to display protocol trees for packets when they're selected. */ -wtap* wtap_open_offline(const char *filename, int *err, char **err_info, +wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_info, gboolean do_random) { int fd; @@ -719,8 +668,6 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, wth->tsprecision = WTAP_FILE_TSPREC_USEC; wth->priv = NULL; - init_magic_number_open_routines(); - init_heuristic_open_info(); if (wth->random_fh) { wth->fast_seek = g_ptr_array_new(); @@ -728,8 +675,35 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, file_set_random_access(wth->random_fh, TRUE, wth->fast_seek); } + if (type != 0 && type <= open_info_arr->len + 1) { + int result; + + if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { + /* I/O error - give up */ + wtap_close(wth); + return NULL; + } + + result = (*open_routines[type - 1].open_routine)(wth, err, err_info); + + switch (result) { + case -1: + /* I/O error - give up */ + wtap_close(wth); + return NULL; + + case 0: + /* No I/O error, but not that type of file */ + goto fail; + + case 1: + /* We found the file type */ + goto success; + } + } + /* Try all file types that support magic numbers */ - for (i = 0; i < magic_number_open_routines_arr->len; i++) { + for (i = 0; i < open_info_arr->len - 1; i++) { /* Seek back to the beginning of the file; the open routine for the previous file type may have left the file position somewhere other than the beginning, and the @@ -737,13 +711,15 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, to start reading at the beginning. Initialize the data offset while we're at it. */ + if (open_routines[i].type != OPEN_INFO_MAGIC) continue; + if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { /* I/O error - give up */ wtap_close(wth); return NULL; } - switch ((*magic_number_open_routines[i])(wth, err, err_info)) { + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { case -1: /* I/O error - give up */ @@ -764,8 +740,10 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, extension = get_file_extension(filename); if (extension != NULL) { /* Yes - try the heuristic types that use that extension first. */ - for (i = 0; i < heuristic_open_info_arr->len; i++) { + for (i = 0; i < open_info_arr->len - 1; i++) { + if (open_routines[i].type != OPEN_INFO_HEURISTIC) continue; /* Does this type use that extension? */ + if (heuristic_uses_extension(i, extension)) { /* Yes. */ if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { @@ -775,7 +753,7 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, return NULL; } - switch ((*heuristic_open_info[i].open_routine)(wth, + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { case -1: @@ -797,7 +775,8 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, } /* Now try the ones that don't use it. */ - for (i = 0; i < heuristic_open_info_arr->len; i++) { + for (i = 0; i < open_info_arr->len - 1; i++) { + if (open_routines[i].type != OPEN_INFO_HEURISTIC) continue; /* Does this type use that extension? */ if (!heuristic_uses_extension(i, extension)) { /* No. */ @@ -808,7 +787,7 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, return NULL; } - switch ((*heuristic_open_info[i].open_routine)(wth, + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { case -1: @@ -831,15 +810,16 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, g_free(extension); } else { /* No - try all the heuristics types in order. */ - for (i = 0; i < heuristic_open_info_arr->len; i++) { + for (i = 0; i < open_info_arr->len - 1; i++) { + if (open_routines[i].type != OPEN_INFO_HEURISTIC) continue; + if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) { /* I/O error - give up */ wtap_close(wth); return NULL; } - switch ((*heuristic_open_info[i].open_routine)(wth, - err, err_info)) { + switch ((*open_routines[i].open_routine)(wth, err, err_info)) { case -1: /* I/O error - give up */ @@ -857,6 +837,8 @@ wtap* wtap_open_offline(const char *filename, int *err, char **err_info, } } +fail: + /* Well, it's not one of the types of file we know about. */ wtap_close(wth); *err = WTAP_ERR_FILE_UNKNOWN_FORMAT; diff --git a/wiretap/merge.c b/wiretap/merge.c index 34f71ec7c5..547c60b814 100644 --- a/wiretap/merge.c +++ b/wiretap/merge.c @@ -62,7 +62,7 @@ merge_open_in_files(int in_file_count, char *const *in_file_names, for (i = 0; i < in_file_count; i++) { files[i].filename = in_file_names[i]; - files[i].wth = wtap_open_offline(in_file_names[i], err, err_info, FALSE); + files[i].wth = wtap_open_offline(in_file_names[i], WTAP_TYPE_AUTO, err, err_info, FALSE); files[i].data_offset = 0; files[i].state = PACKET_NOT_PRESENT; files[i].packet_num = 0; diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 1831565030..a5d8c51b4a 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1201,10 +1201,23 @@ typedef int (*wtap_open_routine_t)(struct wtap*, int *, char **); * the ones that don't, to handle the case where a file of one type * might be recognized by the heuristics for a different file type. */ -struct heuristic_open_info { +/*struct heuristic_open_info { wtap_open_routine_t open_routine; const char *extensions; }; +*/ +#define OPEN_INFO_MAGIC 0 +#define OPEN_INFO_HEURISTIC 1 + +WS_DLL_PUBLIC void init_open_routines(void); + +struct open_info { + const char *name; + int type; + wtap_open_routine_t open_routine; + const char *extensions; +}; +WS_DLL_PUBLIC struct open_info *open_routines; /* * Types of comments. @@ -1251,11 +1264,13 @@ struct file_type_subtype_info { int (*dump_open)(wtap_dumper *, int *); }; +#define WTAP_TYPE_AUTO 0 /** On failure, "wtap_open_offline()" returns NULL, and puts into the * "int" pointed to by its second argument: * * @param filename Name of the file to open + * @param type WTAP_TYPE_AUTO for automatic recognize file format or explicit choose format type * @param err a positive "errno" value if the capture file can't be opened; * a negative number, indicating the type of error, on other failures. * @param err_info for some errors, a string giving more details of @@ -1264,7 +1279,7 @@ struct file_type_subtype_info { * FALSE if not */ WS_DLL_PUBLIC -struct wtap* wtap_open_offline(const char *filename, int *err, +struct wtap* wtap_open_offline(const char *filename, unsigned int type, int *err, gchar **err_info, gboolean do_random); /** @@ -1471,10 +1486,14 @@ WS_DLL_PUBLIC void register_all_wiretap_modules(void); WS_DLL_PUBLIC void wtap_register_file_type_extension(const struct file_extension_info *ei); +#if 0 WS_DLL_PUBLIC void wtap_register_magic_number_open_routine(wtap_open_routine_t open_routine); WS_DLL_PUBLIC void wtap_register_heuristic_open_info(const struct heuristic_open_info *oi); +#endif +WS_DLL_PUBLIC +void wtap_register_open_info(const struct open_info *oi); WS_DLL_PUBLIC int wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi); WS_DLL_PUBLIC