diff options
-rw-r--r-- | epan/epan.h | 16 | ||||
-rw-r--r-- | epan/tap.h | 14 | ||||
-rw-r--r-- | ui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | ui/Makefile.common | 1 | ||||
-rw-r--r-- | ui/export_object.c | 192 | ||||
-rw-r--r-- | ui/export_object.h | 5 | ||||
-rw-r--r-- | ui/gtk/CMakeLists.txt | 2 | ||||
-rw-r--r-- | ui/gtk/Makefile.common | 4 | ||||
-rw-r--r-- | ui/gtk/export_object_dlg.c (renamed from ui/gtk/export_object.c) | 175 | ||||
-rw-r--r-- | ui/gtk/export_object_dlg.h (renamed from ui/gtk/export_object_gtk.h) | 6 | ||||
-rw-r--r-- | ui/gtk/libgtkui.vcproj | 8 | ||||
-rw-r--r-- | ui/gtk/main_menubar.c | 2 | ||||
-rw-r--r-- | ui/qt/QtShark.pro | 9 | ||||
-rw-r--r-- | ui/qt/export_dissection_dialog.cpp | 3 | ||||
-rw-r--r-- | ui/qt/export_object_dialog.cpp | 316 | ||||
-rw-r--r-- | ui/qt/export_object_dialog.h | 102 | ||||
-rw-r--r-- | ui/qt/export_object_dialog.ui | 156 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 12 | ||||
-rw-r--r-- | ui/qt/main_window.h | 3 | ||||
-rw-r--r-- | ui/qt/main_window.ui | 36 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 24 | ||||
-rw-r--r-- | wsutil/str_util.h | 16 |
22 files changed, 894 insertions, 209 deletions
diff --git a/epan/epan.h b/epan/epan.h index 24d751e3d1..c668fa0423 100644 --- a/epan/epan.h +++ b/epan/epan.h @@ -21,8 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef EPAN_H -#define EPAN_H +#ifndef __EPAN_H__ +#define __EPAN_H__ #ifdef __cplusplus extern "C" { @@ -47,16 +47,16 @@ typedef struct _epan_dissect_t epan_dissect_t; @b Sections: - \ref proto_pub */ -/* +/* Ref 1 Epan -Ethereal Packet ANalyzer (XXX - is this correct?) the packet analyzing engine. Source code can be found in the epan directory. +Ethereal Packet ANalyzer (XXX - is this correct?) the packet analyzing engine. Source code can be found in the epan directory. -Protocol-Tree - Keep data of the capture file protocol information. +Protocol-Tree - Keep data of the capture file protocol information. -Dissectors - The various protocol dissectors in epan/dissectors. +Dissectors - The various protocol dissectors in epan/dissectors. -Plugins - Some of the protocol dissectors are implemented as plugins. Source code can be found at plugins. +Plugins - Some of the protocol dissectors are implemented as plugins. Source code can be found at plugins. Display-Filters - the display filter engine at epan/dfilter @@ -191,4 +191,4 @@ epan_get_runtime_version_info(GString *str); } #endif /* __cplusplus */ -#endif /* EPAN_H */ +#endif /* __EPAN_H__ */ diff --git a/epan/tap.h b/epan/tap.h index 22d0fcd9ea..6c1b95ea11 100644 --- a/epan/tap.h +++ b/epan/tap.h @@ -22,11 +22,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef _TAP_H_ -#define _TAP_H_ +#ifndef __TAP_H__ +#define __TAP_H__ #include <epan/epan.h> +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + typedef void (*tap_reset_cb)(void *tapdata); typedef gboolean (*tap_packet_cb)(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data); typedef void (*tap_draw_cb)(void *tapdata); @@ -61,4 +65,8 @@ extern gboolean have_filtering_tap_listeners(void); extern guint union_of_tap_listener_flags(void); extern const void *fetch_tapped_data(int tap_id, int idx); -#endif +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TAP_H__ */ diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 8e092743ad..003ccc3fc1 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -24,6 +24,7 @@ set(COMMON_UI_SRC alert_box.c + export_object.c export_object_dicom.c export_object_http.c export_object_smb.c diff --git a/ui/Makefile.common b/ui/Makefile.common index 9a498c1e37..5a8c96d1da 100644 --- a/ui/Makefile.common +++ b/ui/Makefile.common @@ -45,6 +45,7 @@ GENERATOR_FILES = \ WIRESHARK_UI_SRC = \ alert_box.c \ + export_object.c \ export_object_dicom.c \ export_object_http.c \ export_object_smb.c \ diff --git a/ui/export_object.c b/ui/export_object.c new file mode 100644 index 0000000000..83a905b32a --- /dev/null +++ b/ui/export_object.c @@ -0,0 +1,192 @@ +/* export_object.c + * Common routines for tracking & saving objects found in streams of data + * Copyright 2007, Stephen Fisher (see AUTHORS file) + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include "config.h" + +#include <string.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <errno.h> + +#include <epan/packet_info.h> +#include <epan/tap.h> + +#include <wsutil/file_util.h> + +#include <ui/alert_box.h> + +#include "export_object.h" + +gboolean +eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry, gboolean show_err) +{ + int to_fd; + gint64 bytes_left; + int bytes_to_write; + ssize_t bytes_written; + guint8 *ptr; + int err; + + to_fd = ws_open(save_as_filename, O_WRONLY | O_CREAT | O_EXCL | + O_BINARY, 0644); + if(to_fd == -1) { /* An error occurred */ + if (show_err) + open_failure_alert_box(save_as_filename, errno, TRUE); + return FALSE; + } + + /* + * The third argument to _write() on Windows is an unsigned int, + * so, on Windows, that's the size of the third argument to + * ws_write(). + * + * The third argument to write() on UN*X is a size_t, although + * the return value is an ssize_t, so one probably shouldn't + * write more than the max value of an ssize_t. + * + * In either case, there's no guarantee that a gint64 such as + * payload_len can be passed to ws_write(), so we write in + * chunks of, at most 2^31 bytes. + */ + ptr = entry->payload_data; + bytes_left = entry->payload_len; + while (bytes_left != 0) { + if (bytes_left > 0x40000000) + bytes_to_write = 0x40000000; + else + bytes_to_write = (int)bytes_left; + bytes_written = ws_write(to_fd, ptr, bytes_to_write); + if(bytes_written <= 0) { + if (bytes_written < 0) + err = errno; + else + err = WTAP_ERR_SHORT_WRITE; + if (show_err) + write_failure_alert_box(save_as_filename, err); + ws_close(to_fd); + return FALSE; + } + bytes_left -= bytes_written; + ptr += bytes_written; + } + if (ws_close(to_fd) < 0) { + if (show_err) + write_failure_alert_box(save_as_filename, errno); + return FALSE; + } + + return TRUE; +} + + +#define HINIBBLE(x) (((x) >> 4) & 0xf) +#define LONIBBLE(x) ((x) & 0xf) +#define HEXTOASCII(x) (((x) < 10) ? ((x) + '0') : ((x) - 10 + 'a')) +#define MAXFILELEN 255 + +static GString *eo_rename(GString *gstr, int dup) +{ + GString *gstr_tmp; + gchar *tmp_ptr; + GString *ext_str; + + gstr_tmp = g_string_new("("); + g_string_append_printf (gstr_tmp, "%d)", dup); + if ( (tmp_ptr = strrchr(gstr->str, '.')) != NULL ) { + /* Retain the extension */ + ext_str = g_string_new(tmp_ptr); + gstr = g_string_truncate(gstr, gstr->len - ext_str->len); + if ( gstr->len >= (MAXFILELEN - (strlen(gstr_tmp->str) + ext_str->len)) ) + gstr = g_string_truncate(gstr, MAXFILELEN - (strlen(gstr_tmp->str) + ext_str->len)); + gstr = g_string_append(gstr, gstr_tmp->str); + gstr = g_string_append(gstr, ext_str->str); + g_string_free(ext_str, TRUE); + } + else { + if ( gstr->len >= (MAXFILELEN - strlen(gstr_tmp->str)) ) + gstr = g_string_truncate(gstr, MAXFILELEN - strlen(gstr_tmp->str)); + gstr = g_string_append(gstr, gstr_tmp->str); + } + g_string_free(gstr_tmp, TRUE); + return gstr; +} + +GString * +eo_massage_str(const gchar *in_str, gsize maxlen, int dup) +{ + gchar *tmp_ptr; + /* The characters in "reject" come from: + * http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx. + * Add to the list as necessary for other OS's. + */ + const gchar *reject = "<>:\"/\\|?*" + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; + GString *out_str; + GString *ext_str; + + out_str = g_string_new(""); + + /* Find all disallowed characters/bytes and replace them with %xx */ + while ( (tmp_ptr = strpbrk(in_str, reject)) != NULL ) { + out_str = g_string_append_len(out_str, in_str, tmp_ptr - in_str); + out_str = g_string_append_c(out_str, '%'); + out_str = g_string_append_c(out_str, HEXTOASCII(HINIBBLE(*tmp_ptr))); + out_str = g_string_append_c(out_str, HEXTOASCII(LONIBBLE(*tmp_ptr))); + in_str = tmp_ptr + 1; + } + out_str = g_string_append(out_str, in_str); + if ( out_str->len > maxlen ) { + if ( (tmp_ptr = strrchr(out_str->str, '.')) != NULL ) { + /* Retain the extension */ + ext_str = g_string_new(tmp_ptr); + out_str = g_string_truncate(out_str, maxlen - ext_str->len); + out_str = g_string_append(out_str, ext_str->str); + g_string_free(ext_str, TRUE); + } + else + out_str = g_string_truncate(out_str, maxlen); + } + if ( dup != 0 ) + out_str = eo_rename(out_str, dup); + return out_str; +} + +const char * +ct2ext(const char *content_type) +{ + /* TODO: Map the content type string to an extension string. If no match, + * return NULL. */ + return content_type; +} diff --git a/ui/export_object.h b/ui/export_object.h index 83379d39e6..d7711588cd 100644 --- a/ui/export_object.h +++ b/ui/export_object.h @@ -50,6 +50,11 @@ typedef struct _export_object_entry_t { void object_list_add_entry(export_object_list_t *object_list, export_object_entry_t *entry); export_object_entry_t *object_list_get_entry(export_object_list_t *object_list, int row); +gboolean eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry, gboolean show_err); +GString *eo_massage_str(const gchar *in_str, gsize maxlen, int dup); +const char *ct2ext(const char *content_type); + + /* Protocol specific */ gboolean eo_dicom_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data); diff --git a/ui/gtk/CMakeLists.txt b/ui/gtk/CMakeLists.txt index 28ee495379..4f0bb7563e 100644 --- a/ui/gtk/CMakeLists.txt +++ b/ui/gtk/CMakeLists.txt @@ -45,7 +45,7 @@ set(WIRESHARK_GTK_SRC drag_and_drop.c edit_packet_comment_dlg.c expert_comp_table.c - export_object.c + export_object_dlg.c export_sslkeys.c filter_autocomplete.c file_dlg.c diff --git a/ui/gtk/Makefile.common b/ui/gtk/Makefile.common index d45febca11..ea2cc7a7b0 100644 --- a/ui/gtk/Makefile.common +++ b/ui/gtk/Makefile.common @@ -64,7 +64,7 @@ WIRESHARK_GTK_SRC = \ drag_and_drop.c \ edit_packet_comment_dlg.c \ expert_comp_table.c \ - export_object.c \ + export_object_dlg.c \ export_sslkeys.c \ filter_autocomplete.c \ file_dlg.c \ @@ -252,7 +252,7 @@ noinst_HEADERS = \ expert_comp_dlg.h \ expert_comp_table.h \ expert_indicators.h \ - export_object_gtk.h \ + export_object_dlg.h \ export_sslkeys.h \ file_dlg.h \ file_import_dlg.h \ diff --git a/ui/gtk/export_object.c b/ui/gtk/export_object_dlg.c index 130bbb1cf6..5e5177a880 100644 --- a/ui/gtk/export_object.c +++ b/ui/gtk/export_object_dlg.c @@ -26,16 +26,6 @@ #include "config.h" -#include <string.h> - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - #include <gtk/gtk.h> #include <epan/packet_info.h> @@ -45,7 +35,6 @@ #include <wsutil/file_util.h> #include <wsutil/str_util.h> -#include <ui/alert_box.h> #include <ui/export_object.h> #include <ui/simple_dialog.h> @@ -55,7 +44,7 @@ #include "help_dlg.h" #include "main.h" #include "stock_icons.h" -#include "export_object_gtk.h" +#include "export_object_dlg.h" /* When a protocol needs intermediate data structures to construct the export objects, then it must specifiy a function that cleans up all @@ -143,78 +132,13 @@ eo_win_destroy_cb(GtkWindow *win _U_, gpointer data) if (eo_protocoldata_reset != NULL) eo_protocoldata_reset(); } -static gboolean -eo_save_entry(gchar *save_as_filename, export_object_entry_t *entry, gboolean show_err) -{ - int to_fd; - gint64 bytes_left; - int bytes_to_write; - ssize_t bytes_written; - guint8 *ptr; - int err; - - to_fd = ws_open(save_as_filename, O_WRONLY | O_CREAT | O_EXCL | - O_BINARY, 0644); - if(to_fd == -1) { /* An error occurred */ - if (show_err) - open_failure_alert_box(save_as_filename, errno, TRUE); - g_free(save_as_filename); - return FALSE; - } - - /* - * The third argument to _write() on Windows is an unsigned int, - * so, on Windows, that's the size of the third argument to - * ws_write(). - * - * The third argument to write() on UN*X is a size_t, although - * the return value is an ssize_t, so one probably shouldn't - * write more than the max value of an ssize_t. - * - * In either case, there's no guarantee that a gint64 such as - * payload_len can be passed to ws_write(), so we write in - * chunks of, at most 2^31 bytes. - */ - ptr = entry->payload_data; - bytes_left = entry->payload_len; - while (bytes_left != 0) { - if (bytes_left > 0x40000000) - bytes_to_write = 0x40000000; - else - bytes_to_write = (int)bytes_left; - bytes_written = ws_write(to_fd, ptr, bytes_to_write); - if(bytes_written <= 0) { - if (bytes_written < 0) - err = errno; - else - err = WTAP_ERR_SHORT_WRITE; - if (show_err) - write_failure_alert_box(save_as_filename, err); - ws_close(to_fd); - g_free(save_as_filename); - return FALSE; - } - bytes_left -= bytes_written; - ptr += bytes_written; - } - if (ws_close(to_fd) < 0) { - if (show_err) - write_failure_alert_box(save_as_filename, errno); - g_free(save_as_filename); - return FALSE; - } - - g_free(save_as_filename); - return TRUE; -} - - static void eo_save_clicked_cb(GtkWidget *widget _U_, gpointer arg) { GtkWidget *save_as_w; export_object_list_t *object_list = arg; export_object_entry_t *entry = NULL; + gchar *filename = NULL; entry = g_slist_nth_data(object_list->entries, object_list->row_selected); @@ -233,98 +157,20 @@ eo_save_clicked_cb(GtkWidget *widget _U_, gpointer arg) gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_as_w), entry->filename); - if(gtk_dialog_run(GTK_DIALOG(save_as_w)) == GTK_RESPONSE_ACCEPT) - eo_save_entry(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(save_as_w)), entry, TRUE); + if(gtk_dialog_run(GTK_DIALOG(save_as_w)) == GTK_RESPONSE_ACCEPT) { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(save_as_w)); + eo_save_entry(filename, entry, TRUE); + } + g_free(filename); window_destroy(save_as_w); } -#define HINIBBLE(x) (((x) >> 4) & 0xf) -#define LONIBBLE(x) ((x) & 0xf) -#define HEXTOASCII(x) (((x) < 10) ? ((x) + '0') : ((x) - 10 + 'a')) #define MAXFILELEN 255 - -static GString *eo_rename(GString *gstr, int dup) -{ - GString *gstr_tmp; - gchar *tmp_ptr; - GString *ext_str; - - gstr_tmp = g_string_new("("); - g_string_append_printf (gstr_tmp, "%d)", dup); - if ( (tmp_ptr = strrchr(gstr->str, '.')) != NULL ) { - /* Retain the extension */ - ext_str = g_string_new(tmp_ptr); - gstr = g_string_truncate(gstr, gstr->len - ext_str->len); - if ( gstr->len >= (MAXFILELEN - (strlen(gstr_tmp->str) + ext_str->len)) ) - gstr = g_string_truncate(gstr, MAXFILELEN - (strlen(gstr_tmp->str) + ext_str->len)); - gstr = g_string_append(gstr, gstr_tmp->str); - gstr = g_string_append(gstr, ext_str->str); - g_string_free(ext_str, TRUE); - } - else { - if ( gstr->len >= (MAXFILELEN - strlen(gstr_tmp->str)) ) - gstr = g_string_truncate(gstr, MAXFILELEN - strlen(gstr_tmp->str)); - gstr = g_string_append(gstr, gstr_tmp->str); - } - g_string_free(gstr_tmp, TRUE); - return gstr; -} - -static GString * -eo_massage_str(const gchar *in_str, gsize maxlen, int dup) -{ - gchar *tmp_ptr; - /* The characters in "reject" come from: - * http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx. - * Add to the list as necessary for other OS's. - */ - const gchar *reject = "<>:\"/\\|?*" - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" - "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" - "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; - GString *out_str; - GString *ext_str; - - out_str = g_string_new(""); - - /* Find all disallowed characters/bytes and replace them with %xx */ - while ( (tmp_ptr = strpbrk(in_str, reject)) != NULL ) { - out_str = g_string_append_len(out_str, in_str, tmp_ptr - in_str); - out_str = g_string_append_c(out_str, '%'); - out_str = g_string_append_c(out_str, HEXTOASCII(HINIBBLE(*tmp_ptr))); - out_str = g_string_append_c(out_str, HEXTOASCII(LONIBBLE(*tmp_ptr))); - in_str = tmp_ptr + 1; - } - out_str = g_string_append(out_str, in_str); - if ( out_str->len > maxlen ) { - if ( (tmp_ptr = strrchr(out_str->str, '.')) != NULL ) { - /* Retain the extension */ - ext_str = g_string_new(tmp_ptr); - out_str = g_string_truncate(out_str, maxlen - ext_str->len); - out_str = g_string_append(out_str, ext_str->str); - g_string_free(ext_str, TRUE); - } - else - out_str = g_string_truncate(out_str, maxlen); - } - if ( dup != 0 ) - out_str = eo_rename(out_str, dup); - return out_str; -} - -static const char * -ct2ext(const char *content_type) -{ - /* TODO: Map the content type string to an extension string. If no match, - * return NULL. */ - return content_type; -} - static void eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg) { - gchar *save_as_fullpath; + gchar *save_as_fullpath = NULL; export_object_list_t *object_list = arg; export_object_entry_t *entry; GtkWidget *save_in_w; @@ -347,6 +193,7 @@ eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg) save_in_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(save_in_w)); if ((strlen(save_in_path) < MAXFILELEN)) { do { + g_free(save_as_fullpath); if (entry->filename) safe_filename = eo_massage_str(entry->filename, MAXFILELEN - strlen(save_in_path), count); @@ -367,6 +214,8 @@ eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg) count = 0; if (!eo_save_entry(save_as_fullpath, entry, FALSE)) all_saved = FALSE; + g_free(save_as_fullpath); + save_as_fullpath = NULL; } else all_saved = FALSE; @@ -437,7 +286,7 @@ void object_list_add_entry(export_object_list_t *object_list, export_object_entr } export_object_entry_t *object_list_get_entry(export_object_list_t *object_list, int row) { - return g_slist_nth_data(object_list->entries, row); + return g_slist_nth_data(object_list->entries, row); } static void diff --git a/ui/gtk/export_object_gtk.h b/ui/gtk/export_object_dlg.h index e1a6bc1132..e45c7f8d95 100644 --- a/ui/gtk/export_object_gtk.h +++ b/ui/gtk/export_object_dlg.h @@ -24,12 +24,12 @@ * USA. */ -#ifndef __EXPORT_OBJECT_GTK_H__ -#define __EXPORT_OBJECT_GTK_H__ +#ifndef __EXPORT_OBJECT_DLG_H__ +#define __EXPORT_OBJECT_DLG_H__ /* Protocol specific */ void eo_dicom_cb(GtkWidget *widget _U_, gpointer data _U_); void eo_http_cb(GtkWidget *widget _U_, gpointer data _U_); void eo_smb_cb(GtkWidget *widget _U_, gpointer data _U_); -#endif /* __EXPORT_OBJECT_GTK_H__ */ +#endif /* __EXPORT_OBJECT_DLG_H__ */ diff --git a/ui/gtk/libgtkui.vcproj b/ui/gtk/libgtkui.vcproj index 61126533e6..ab5be3088c 100644 --- a/ui/gtk/libgtkui.vcproj +++ b/ui/gtk/libgtkui.vcproj @@ -145,11 +145,7 @@ > </File> <File - RelativePath=".\export_object.c" - > - </File> - <File - RelativePath=".\export_object_http.c" + RelativePath=".\export_object_dlg.c" > </File> <File @@ -783,7 +779,7 @@ > </File> <File - RelativePath=".\export_object.h" + RelativePath=".\export_object_dlg.h" > </File> <File diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c index a52e64ca82..671ae8d3f7 100644 --- a/ui/gtk/main_menubar.c +++ b/ui/gtk/main_menubar.c @@ -63,7 +63,7 @@ #include "ui/gtk/capture_dlg.h" #include "ui/gtk/capture_if_dlg.h" #include "ui/gtk/color_dlg.h" -#include "ui/gtk/export_object_gtk.h" +#include "ui/gtk/export_object_dlg.h" #include "ui/gtk/filter_dlg.h" #include "ui/gtk/profile_dlg.h" #include "ui/gtk/dlg_utils.h" diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro index 6441ab06c2..dec7b3d2d1 100644 --- a/ui/qt/QtShark.pro +++ b/ui/qt/QtShark.pro @@ -181,7 +181,8 @@ FORMS += main_window.ui \ import_text_dialog.ui \ file_set_dialog.ui \ packet_range_group_box.ui \ - packet_format_group_box.ui + packet_format_group_box.ui \ + export_object_dialog.ui win32 { ## These should be in config.pri ?? !isEmpty(PORTAUDIO_DIR) { @@ -206,7 +207,8 @@ win32 { ## These should be in config.pri ?? HEADERS += $$HEADERS_WS_C \ export_dissection_dialog.h \ - packet_format_group_box.h + packet_format_group_box.h \ + export_object_dialog.h win32 { OBJECTS_WS_C = $$SOURCES_WS_C @@ -413,4 +415,5 @@ SOURCES += \ syntax_line_edit.cpp \ wireshark_application.cpp \ export_dissection_dialog.cpp \ - packet_format_group_box.cpp + packet_format_group_box.cpp \ + export_object_dialog.cpp diff --git a/ui/qt/export_dissection_dialog.cpp b/ui/qt/export_dissection_dialog.cpp index c8c74a9e80..4f8c0f814e 100644 --- a/ui/qt/export_dissection_dialog.cpp +++ b/ui/qt/export_dissection_dialog.cpp @@ -42,7 +42,6 @@ #include <QDialogButtonBox> #include <QGridLayout> #include <QPushButton> -#include <QMessageBox> #include <QDebug> #endif // Q_WS_WIN @@ -114,8 +113,6 @@ ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *ca // Grow the dialog to account for the extra widgets. resize(width(), height() + (packet_range_group_box_.height() * 2 / 3)); - qDebug() << "FIX: ExportDissectionDialog help button"; - #else // Q_WS_WIN #endif // Q_WS_WIN } diff --git a/ui/qt/export_object_dialog.cpp b/ui/qt/export_object_dialog.cpp new file mode 100644 index 0000000000..49546de70f --- /dev/null +++ b/ui/qt/export_object_dialog.cpp @@ -0,0 +1,316 @@ +/* export_object_dialog.cpp + * + * $Id: main_window.h 45589 2012-10-16 18:14:16Z gerald $ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "export_object_dialog.h" +#include "ui_export_object_dialog.h" +#include "wireshark_application.h" + +#include <QDialogButtonBox> +#include <QPushButton> +#include <QMessageBox> +#include <QFileDialog> + +#include <ui/alert_box.h> + +#include <epan/filesystem.h> + +#include <wsutil/str_util.h> + +extern "C" { + +// object_list_add_entry and object_list_get_entry are defined in ui/export_object.h + +void object_list_add_entry(export_object_list_t *object_list, export_object_entry_t *entry) { + if (object_list && object_list->eod) object_list->eod->addObjectEntry(entry); +} + +export_object_entry_t *object_list_get_entry(export_object_list_t *object_list, int row) { + if (object_list && object_list->eod) return object_list->eod->objectEntry(row); + return NULL; +} + +// Called by taps + +/* Runs at the beginning of tapping only */ +static void +eo_reset(void *tapdata) +{ + export_object_list_t *object_list = (export_object_list_t *) tapdata; + if (object_list) object_list->eod->resetObjects(); +} + +} // extern "C" + +ExportObjectDialog::ExportObjectDialog(QWidget *parent, capture_file *cf, ObjectType object_type) : + QDialog(parent), + eo_ui_(new Ui::ExportObjectDialog), + cap_file_(cf), + save_bt_(NULL), + save_all_bt_(NULL), + tap_name_(NULL), + name_(NULL), + tap_packet_(NULL), + eo_protocoldata_resetfn_(NULL) +{ + QPushButton *close_bt; + + eo_ui_->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + +#if defined(Q_WS_MAC) + eo_ui_->progressLabel->setAttribute(Qt::WA_MacSmallSize, true); + eo_ui_->progressBar->setAttribute(Qt::WA_MacSmallSize, true); +#endif + + export_object_list_.eod = this; + + switch (object_type) { + case Dicom: + tap_name_ = "dicom_eo"; + name_ = "DICOM"; + tap_packet_ = eo_dicom_packet; + break; + case Http: + tap_name_ = "http_eo"; + name_ = "HTTP"; + tap_packet_ = eo_http_packet; + break; + case Smb: + tap_name_ = "smb_eo"; + name_ = "SMB"; + tap_packet_ = eo_smb_packet; + eo_protocoldata_resetfn_ = eo_smb_cleanup; + break; + } + + save_bt_ = eo_ui_->buttonBox->button(QDialogButtonBox::Save); + save_all_bt_ = eo_ui_->buttonBox->button(QDialogButtonBox::SaveAll); + close_bt = eo_ui_->buttonBox->button(QDialogButtonBox::Close); + + if (save_bt_) save_bt_->setEnabled(false); + if (save_all_bt_) save_all_bt_->setEnabled(false); + if (close_bt) close_bt->setDefault(true); + + connect(wsApp, SIGNAL(captureFileClosing(const capture_file*)), + this, SLOT(captureFileClosing(const capture_file*))); +} + +ExportObjectDialog::~ExportObjectDialog() +{ + delete eo_ui_; +} + +void ExportObjectDialog::show() +{ + GString *error_msg; + + if (!cap_file_) destroy(); // Assert? + + /* Data will be gathered via a tap callback */ + error_msg = register_tap_listener(tap_name_, (void *)&export_object_list_, NULL, 0, + eo_reset, + tap_packet_, + NULL); + + if (error_msg) { + QMessageBox::warning( + this, + tr("Tap registration error"), + QString("Unable to register ") + name_ + QString(" tap: ") + error_msg->str, + QMessageBox::Ok + ); + g_string_free(error_msg, TRUE); + return; + } + + QDialog::show(); + cf_retap_packets(cap_file_); + eo_ui_->progressFrame->hide(); + for (int i = 0; i < eo_ui_->objectTree->columnCount(); i++) + eo_ui_->objectTree->resizeColumnToContents(i); + +} + +void ExportObjectDialog::addObjectEntry(export_object_entry_t *entry) +{ + QTreeWidgetItem *entry_item; + gchar *size_str; + + if (!entry) return; + + size_str = format_size(entry->payload_len, format_size_unit_bytes|format_size_prefix_si); + + entry_item = new QTreeWidgetItem(eo_ui_->objectTree); + entry_item->setData(0, Qt::UserRole, qVariantFromValue(entry)); + + entry_item->setText(0, QString().setNum(entry->pkt_num)); + entry_item->setText(1, entry->hostname); + entry_item->setText(2, entry->content_type); + entry_item->setText(3, size_str); + entry_item->setText(2, entry->filename); + g_free(size_str); + // Not perfect but better than nothing. + entry_item->setTextAlignment(3, Qt::AlignRight); + + if (save_all_bt_) save_all_bt_->setEnabled(true); +} + +export_object_entry_t *ExportObjectDialog::objectEntry(int row) +{ + QTreeWidgetItem *item = eo_ui_->objectTree->topLevelItem(row); + + if (item) return item->data(0, Qt::UserRole).value<export_object_entry_t *>(); + + return NULL; +} + +void ExportObjectDialog::resetObjects() +{ + if (eo_protocoldata_resetfn_) eo_protocoldata_resetfn_(); + if (save_bt_) save_bt_->setEnabled(false); + if (save_all_bt_) save_all_bt_->setEnabled(false); +} + +void ExportObjectDialog::accept() +{ + // Don't close the dialog. +} + +void ExportObjectDialog::captureFileClosing(const capture_file *cf) +{ + if (cap_file_ && cf == cap_file_) { + close(); + } +} + +void ExportObjectDialog::on_buttonBox_helpRequested() +{ + wsApp->helpTopicAction(HELP_EXPORT_OBJECT_LIST); +} + +void ExportObjectDialog::on_objectTree_currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *previous) +{ + Q_UNUSED(previous); + + if (!item) { + if (save_bt_) save_bt_->setEnabled(false); + return; + } + + if (save_bt_) save_bt_->setEnabled(true); + + export_object_entry_t *entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>(); + if (entry && cap_file_) { + cf_goto_frame(cap_file_, entry->pkt_num); + } +} + +void ExportObjectDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + switch (eo_ui_->buttonBox->standardButton(button)) { + case QDialogButtonBox::Save: + saveCurrentEntry(); + break; + case QDialogButtonBox::SaveAll: + saveAllEntries(); + break; + default: // Help, Cancel + break; + } +} + +void ExportObjectDialog::saveCurrentEntry() +{ + QTreeWidgetItem *item = eo_ui_->objectTree->currentItem(); + export_object_entry_t *entry; + QDir path(wsApp->lastOpenDir()); + QString file_name; + + if (!item) return; + + entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>(); + if (!entry) return; + + file_name = QFileDialog::getSaveFileName(this, tr("Wireshark: Save Object As..."), + path.filePath(entry->filename)); + + if (file_name.length() > 0) { + eo_save_entry(file_name.toUtf8().constData(), entry, TRUE); + } +} + +#define MAXFILELEN 255 +void ExportObjectDialog::saveAllEntries() +{ + int i; + QTreeWidgetItem *item; + QDir path(wsApp->lastOpenDir()); + QString file_path; + bool all_saved = true; + + file_path = QFileDialog::getSaveFileName(this, tr("Wireshark: Save All Objects In..."), + path.canonicalPath(), QString(), NULL, + QFileDialog::ShowDirsOnly); + + if (file_path.length() < 1 || file_path.length() > MAXFILELEN) return; + + for (i = 0, item = eo_ui_->objectTree->topLevelItem(i); item != NULL; i++) { + int count = 0; + QString file_name; + export_object_entry_t *entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>(); + + if (!entry) continue; + + do { + GString *safe_filename; + + path.setCurrent(file_path); + if (entry->filename) + safe_filename = eo_massage_str(entry->filename, + MAXFILELEN - file_path.length(), count); + else { + char generic_name[256]; + const char *ext; + ext = ct2ext(entry->content_type); + g_snprintf(generic_name, sizeof(generic_name), + "object%u%s%s", entry->pkt_num, ext ? "." : "", + ext ? ext : ""); + safe_filename = eo_massage_str(generic_name, + MAXFILELEN - file_path.length(), count); + } + file_name = path.filePath(safe_filename->str); + g_string_free(safe_filename, TRUE); + } while (g_file_test(file_path.toUtf8().constData(), G_FILE_TEST_EXISTS) && ++count < 1000); + count = 0; + if (!eo_save_entry(file_path.toUtf8().constData(), entry, FALSE)) + all_saved = false; + } + if (!all_saved) { + QMessageBox::warning( + this, + tr("Object Export"), + tr("Some files could not be saved."), + QMessageBox::Ok + ); + } +} diff --git a/ui/qt/export_object_dialog.h b/ui/qt/export_object_dialog.h new file mode 100644 index 0000000000..9256dc4e41 --- /dev/null +++ b/ui/qt/export_object_dialog.h @@ -0,0 +1,102 @@ +/* export_object_dialog.h + * + * $Id: main_window.h 45589 2012-10-16 18:14:16Z gerald $ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef EXPORT_OBJECT_DIALOG_H +#define EXPORT_OBJECT_DIALOG_H + +#include "config.h" + +#include <glib.h> + +#include <file.h> + +#include <epan/packet_info.h> +#include <epan/prefs.h> +#include <epan/tap.h> + +#include <ui/export_object.h> + +#include <QDialog> +#include <QMetaType> +#include <QTreeWidgetItem> +#include <QAbstractButton> + +Q_DECLARE_METATYPE(export_object_entry_t *) + +namespace Ui { +class ExportObjectDialog; +} + +struct _export_object_list_t { + class ExportObjectDialog *eod; +}; + + +class ExportObjectDialog : public QDialog +{ + Q_OBJECT + +public: + enum ObjectType { Dicom, Http, Smb }; + + explicit ExportObjectDialog(QWidget *parent, capture_file *cf, ObjectType object_type); + ~ExportObjectDialog(); + + void show(); + + void addObjectEntry(export_object_entry_t *entry); + export_object_entry_t *objectEntry(int row); + void resetObjects(); + +private slots: + void accept(); + void captureFileClosing(const capture_file *cf); + void on_buttonBox_helpRequested(); + void on_objectTree_currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *previous); + void on_buttonBox_clicked(QAbstractButton *button); + +private: + void saveCurrentEntry(); + void saveAllEntries(); + + /* When a protocol needs intermediate data structures to construct the + export objects, then it must specifiy a function that cleans up all + those data structures. This function is passed to export_object_window + and called when tap reset or windows closes occurs. If no function is needed + a NULL value should be passed instead */ + typedef void (*eo_protocoldata_reset_cb)(void); + + Ui::ExportObjectDialog *eo_ui_; + capture_file *cap_file_; + + QPushButton *save_bt_; + QPushButton *save_all_bt_; + + export_object_list_t export_object_list_; + const gchar *tap_name_; + const gchar *name_; + tap_packet_cb tap_packet_; + eo_protocoldata_reset_cb eo_protocoldata_resetfn_; +}; + +#endif // EXPORT_OBJECT_DIALOG_H diff --git a/ui/qt/export_object_dialog.ui b/ui/qt/export_object_dialog.ui new file mode 100644 index 0000000000..f6e9681188 --- /dev/null +++ b/ui/qt/export_object_dialog.ui @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ExportObjectDialog</class> + <widget class="QDialog" name="ExportObjectDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>750</width> + <height>520</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTreeWidget" name="objectTree"> + <column> + <property name="text"> + <string>Packet</string> + </property> + </column> + <column> + <property name="text"> + <string>New Column</string> + </property> + </column> + <column> + <property name="text"> + <string>Content Type</string> + </property> + </column> + <column> + <property name="text"> + <string>Size</string> + </property> + </column> + <column> + <property name="text"> + <string>Filename</string> + </property> + </column> + </widget> + </item> + <item> + <widget class="QFrame" name="progressFrame"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="progressLabel"> + <property name="text"> + <string>Searching for objects</string> + </property> + </widget> + </item> + <item> + <widget class="QProgressBar" name="progressBar"> + <property name="styleSheet"> + <string notr="true">QProgressBar { width: 10em; }</string> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="value"> + <number>-1</number> + </property> + <property name="textVisible"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>387</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Save|QDialogButtonBox::SaveAll</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ExportObjectDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ExportObjectDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 65e9b9f324..cde782d8a0 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -104,8 +104,8 @@ MainWindow::MainWindow(QWidget *parent) : main_ui_->goToFrame->hide(); go_to_margins = main_ui_->goToHB->contentsMargins(); - go_to_margins.setTop(0); - go_to_margins.setBottom(0); +// go_to_margins.setTop(0); +// go_to_margins.setBottom(0); main_ui_->goToHB->setContentsMargins(go_to_margins); // XXX For some reason the cursor is drawn funny with an input mask set // https://bugreports.qt-project.org/browse/QTBUG-7174 @@ -202,8 +202,6 @@ MainWindow::MainWindow(QWidget *parent) : connect(proto_tree, SIGNAL(protoItemSelected(QString&)), main_ui_->statusBar, SLOT(pushFieldStatus(QString&))); - connect(proto_tree, SIGNAL(protoItemSelected(bool)), - main_ui_->actionViewExpandSubtrees, SLOT(setEnabled(bool))); connect(proto_tree, SIGNAL(protoItemSelected(field_info *)), this, SLOT(setMenusForSelectedTreeRow(field_info *))); @@ -1081,7 +1079,7 @@ void MainWindow::setMenusForCaptureFile(bool force_disable) main_ui_->menuFileExportPacketDissections->setEnabled(false); main_ui_->actionFileExportPacketBytes->setEnabled(false); main_ui_->actionFileExportSSLSessionKeys->setEnabled(false); - main_ui_->actionFileExportObjects->setEnabled(false); + main_ui_->menuFileExportObjects->setEnabled(false); main_ui_->actionViewReload->setEnabled(false); } else { main_ui_->actionFileMerge->setEnabled(cf_can_write_with_wiretap(cap_file_)); @@ -1122,7 +1120,7 @@ void MainWindow::setMenusForCaptureFile(bool force_disable) main_ui_->menuFileExportPacketDissections->setEnabled(true); main_ui_->actionFileExportPacketBytes->setEnabled(true); main_ui_->actionFileExportSSLSessionKeys->setEnabled(true); - main_ui_->actionFileExportObjects->setEnabled(true); + main_ui_->menuFileExportObjects->setEnabled(true); main_ui_->actionViewReload->setEnabled(true); } } @@ -1136,7 +1134,7 @@ void MainWindow::setMenusForCaptureInProgress(bool capture_in_progress) { main_ui_->menuFileExportPacketDissections->setEnabled(capture_in_progress); main_ui_->actionFileExportPacketBytes->setEnabled(capture_in_progress); main_ui_->actionFileExportSSLSessionKeys->setEnabled(capture_in_progress); - main_ui_->actionFileExportObjects->setEnabled(capture_in_progress); + main_ui_->menuFileExportObjects->setEnabled(capture_in_progress); main_ui_->menuFileSet->setEnabled(!capture_in_progress); main_ui_->actionFileQuit->setEnabled(true); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index a16c3e0b83..71e6d6af0d 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -169,6 +169,9 @@ private slots: void on_actionFileExportAsPSML_triggered(); void on_actionFileExportAsPDML_triggered(); void on_actionFileExportPacketBytes_triggered(); + void on_actionFileExportObjectsDICOM_triggered(); + void on_actionFileExportObjectsHTTP_triggered(); + void on_actionFileExportObjectsSMB_triggered(); void on_actionGoGoToPacket_triggered(); void resetPreviousFocus(); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 105e15f635..c4a01e3dfb 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -39,6 +39,12 @@ <item row="0" column="0"> <widget class="QFrame" name="goToFrame"> <layout class="QHBoxLayout" name="goToHB"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> <item> <spacer name="horizontalSpacer"> <property name="orientation"> @@ -122,6 +128,14 @@ <addaction name="actionFileExportAsPSML"/> <addaction name="actionFileExportAsPDML"/> </widget> + <widget class="QMenu" name="menuFileExportObjects"> + <property name="title"> + <string>Export Objects</string> + </property> + <addaction name="actionFileExportObjectsDICOM"/> + <addaction name="actionFileExportObjectsHTTP"/> + <addaction name="actionFileExportObjectsSMB"/> + </widget> <addaction name="actionFileOpen"/> <addaction name="menuOpenRecentCaptureFile"/> <addaction name="actionFileMerge"/> @@ -137,7 +151,7 @@ <addaction name="menuFileExportPacketDissections"/> <addaction name="actionFileExportPacketBytes"/> <addaction name="actionFileExportSSLSessionKeys"/> - <addaction name="actionFileExportObjects"/> + <addaction name="menuFileExportObjects"/> <addaction name="separator"/> <addaction name="actionFilePrint"/> <addaction name="separator"/> @@ -611,11 +625,6 @@ <string>Export SSL Session Keys...</string> </property> </action> - <action name="actionFileExportObjects"> - <property name="text"> - <string>Export Objects...</string> - </property> - </action> <action name="actionFilePrint"> <property name="text"> <string>&Print...</string> @@ -713,6 +722,21 @@ <string>As PDML XML...</string> </property> </action> + <action name="actionFileExportObjectsHTTP"> + <property name="text"> + <string>&HTTP...</string> + </property> + </action> + <action name="actionFileExportObjectsDICOM"> + <property name="text"> + <string>&DICOM...</string> + </property> + </action> + <action name="actionFileExportObjectsSMB"> + <property name="text"> + <string>&SMB...</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 450b3148fe..875c93bc30 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -60,6 +60,7 @@ #include "wireshark_application.h" #include "capture_file_dialog.h" +#include "export_object_dialog.h" // // Public slots @@ -573,8 +574,7 @@ void MainWindow::setMenusForSelectedTreeRow(field_info *fi) { // proto_can_match_selected(cf->finfo_selected, cf->edt)); // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/PrepareaFilter", // proto_can_match_selected(cf->finfo_selected, cf->edt)); -// set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ExpandSubtrees", -// cf->finfo_selected->tree_type != -1); + main_ui_->actionViewExpandSubtrees->setEnabled(cap_file_->finfo_selected->tree_type != -1); // prev_abbrev = g_object_get_data(G_OBJECT(ui_manager_tree_view_menu), "menu_abbrev"); // if (!prev_abbrev || (strcmp (prev_abbrev, abbrev) != 0)) { // /* No previous protocol or protocol changed - update Protocol Preferences menu */ @@ -610,7 +610,7 @@ void MainWindow::setMenusForSelectedTreeRow(field_info *fi) { // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/ApplyasColumn", FALSE); // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/ApplyAsFilter", FALSE); // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/PrepareaFilter", FALSE); -// set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ExpandSubtrees", FALSE); + main_ui_->actionViewExpandSubtrees->setEnabled(false); } } @@ -799,6 +799,24 @@ void MainWindow::on_actionFileExportSSLSessionKeys_triggered() } } +void MainWindow::on_actionFileExportObjectsDICOM_triggered() +{ + ExportObjectDialog *eod = new ExportObjectDialog(this, cap_file_, ExportObjectDialog::Dicom); + eod->show(); +} + +void MainWindow::on_actionFileExportObjectsHTTP_triggered() +{ + ExportObjectDialog *eod = new ExportObjectDialog(this, cap_file_, ExportObjectDialog::Http); + eod->show(); +} + +void MainWindow::on_actionFileExportObjectsSMB_triggered() +{ + ExportObjectDialog *eod = new ExportObjectDialog(this, cap_file_, ExportObjectDialog::Smb); + eod->show(); +} + // View Menu // Expand / collapse slots in proto_tree diff --git a/wsutil/str_util.h b/wsutil/str_util.h index c43e2e05de..302afd0096 100644 --- a/wsutil/str_util.h +++ b/wsutil/str_util.h @@ -25,6 +25,10 @@ #ifndef __STR_UTIL_H__ #define __STR_UTIL_H__ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + /** Convert all upper-case ASCII letters to their ASCII lower-case * equivalents, in place, with a simple non-locale-dependent * ASCII mapping (A-Z -> a-z). @@ -84,6 +88,13 @@ typedef enum { /* XXX format_size_prefix_default_for_this_particular_os ? */ } format_size_flags_e; +#ifdef __cplusplus +/* Should we just have separate unit and prefix enums instead? */ +format_size_flags_e operator|(format_size_flags_e lhs, format_size_flags_e rhs) { + return (format_size_flags_e) ((int)lhs| (int)rhs); +} +#endif /* __cplusplus */ + /** Given a size, return its value in a human-readable format * * Prefixes up to "T/Ti" (tera, tebi) are currently supported. @@ -95,4 +106,9 @@ typedef enum { */ gchar *format_size(gint64 size, format_size_flags_e flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + #endif /* __STR_UTIL_H__ */ |