aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--debian/libwireshark0.symbols10
-rw-r--r--doc/tshark.pod13
-rw-r--r--docbook/release-notes.asciidoc1
-rw-r--r--epan/CMakeLists.txt1
-rw-r--r--epan/Makefile.am2
-rw-r--r--epan/dissectors/packet-dcm.c35
-rw-r--r--epan/dissectors/packet-http.c31
-rw-r--r--epan/dissectors/packet-imf.c32
-rw-r--r--epan/dissectors/packet-smb.c423
-rw-r--r--epan/dissectors/packet-tftp.c91
-rw-r--r--epan/export_object.c206
-rw-r--r--epan/export_object.h155
-rw-r--r--tshark.c16
-rw-r--r--ui/CMakeLists.txt7
-rw-r--r--ui/Makefile.am9
-rw-r--r--ui/cli/Makefile.am2
-rw-r--r--ui/cli/tap-exportobject.c279
-rw-r--r--ui/cli/tap-exportobject.h55
-rw-r--r--ui/export_object.h89
-rw-r--r--ui/export_object_dicom.c78
-rw-r--r--ui/export_object_http.c75
-rw-r--r--ui/export_object_imf.c75
-rw-r--r--ui/export_object_smb.c470
-rw-r--r--ui/export_object_tftp.c138
-rw-r--r--ui/export_object_ui.c (renamed from ui/export_object.c)87
-rw-r--r--ui/export_object_ui.h55
-rw-r--r--ui/gtk/export_object_dlg.c115
-rw-r--r--ui/gtk/export_object_dlg.h8
-rw-r--r--ui/gtk/main_menubar.c86
-rw-r--r--ui/qt/CMakeLists.txt2
-rw-r--r--ui/qt/Makefile.am2
-rw-r--r--ui/qt/export_object_action.cpp65
-rw-r--r--ui/qt/export_object_action.h64
-rw-r--r--ui/qt/export_object_dialog.cpp209
-rw-r--r--ui/qt/export_object_dialog.h28
-rw-r--r--ui/qt/main_window.cpp24
-rw-r--r--ui/qt/main_window.h8
-rw-r--r--ui/qt/main_window.ui30
-rw-r--r--ui/qt/main_window_slots.cpp36
40 files changed, 1846 insertions, 1267 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b0a2d8fd86..942bb3b180 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1385,6 +1385,7 @@ set(TSHARK_TAP_SRC
ui/cli/tap-comparestat.c
ui/cli/tap-diameter-avp.c
ui/cli/tap-expert.c
+ ui/cli/tap-exportobject.c
ui/cli/tap-endpoints.c
ui/cli/tap-follow.c
ui/cli/tap-funnel.c
diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols
index d4cb226876..02c88dab30 100644
--- a/debian/libwireshark0.symbols
+++ b/debian/libwireshark0.symbols
@@ -486,6 +486,10 @@ libwireshark.so.0 libwireshark0 #MINVER#
elem_tv_short@Base 1.9.1
elem_v@Base 1.9.1
elem_v_short@Base 1.9.1
+ eo_ct2ext@Base 2.3.0
+ eo_free_entry@Base 2.3.0
+ eo_iterate_tables@Base 2.3.0
+ eo_massage_str@Base 2.3.0
epan_cleanup@Base 1.9.1
epan_dissect_cleanup@Base 1.9.1
epan_dissect_fake_protocols@Base 1.9.1
@@ -719,6 +723,11 @@ libwireshark.so.0 libwireshark0 #MINVER#
get_dissector_table_selector_type@Base 1.9.1
get_dissector_table_ui_name@Base 1.9.1
get_ebcdic_string@Base 1.12.0~rc1
+ get_eo_by_name@Base 2.3.0
+ get_eo_packet_func@Base 2.3.0
+ get_eo_proto_id@Base 2.3.0
+ get_eo_reset_func@Base 2.3.0
+ get_eo_tap_listener_name@Base 2.3.0
get_eth_hashtable@Base 1.12.0~rc1
get_ether_name@Base 1.9.1
get_follow_address_func@Base 2.1.0
@@ -1210,6 +1219,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
register_depend_dissector@Base 2.1.0
register_dissector@Base 2.1.0
register_dissector_table@Base 1.9.1
+ register_export_object@Base 2.3.0
register_export_pdu_tap@Base 1.99.0
register_follow_stream@Base 2.1.0
register_final_registration_routine@Base 1.9.1
diff --git a/doc/tshark.pod b/doc/tshark.pod
index ac206fed1e..baa78e8cea 100644
--- a/doc/tshark.pod
+++ b/doc/tshark.pod
@@ -53,6 +53,7 @@ S<[ B<-y> E<lt>capture link typeE<gt> ]>
S<[ B<-Y> E<lt>displaY filterE<gt> ]>
S<[ B<-z> E<lt>statisticsE<gt> ]>
S<[ B<--capture-comment> E<lt>commentE<gt> ]>
+S<[ B<--export-objects> E<lt>protocolE<gt>,E<lt>destdirE<gt> ]>
S<[ E<lt>capture filterE<gt> ]>
B<tshark>
@@ -1569,6 +1570,18 @@ Add a capture comment to the output file.
This option is only available if a new output file in pcapng format is
created. Only one capture comment may be set per output file.
+=item --export-objects E<lt>protocolE<gt>,E<lt>destdirE<gt>
+
+Export all objects within a protocol into directory B<destdir>. The available
+values for B<protocol> can be listed with B<--export-objects help>.
+
+The objects are directly saved in the given directory. Filenames are dependent
+on the dissector, but typically it is named after the basename of a file.
+Duplicate files are not overwritten, instead an increasing number is appended
+before the file extension.
+
+This interface is subject to change, adding the possibility to filter on files.
+
=item --disable-protocol E<lt>proto_nameE<gt>
Disable dissection of proto_name.
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index 1bf32ac781..2b9b7d6110 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -37,6 +37,7 @@ since version 2.2.0:
* GTK+ is disabled by default in Autotools and CMake.
* SS7 Point Codes can now be resolved into names with a hosts-like file.
* Wireshark can now go fullscreen to have more room for packets.
+* TShark can now export objects like the other GUI interfaces.
//=== Removed Dissectors
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index 3bb415589c..f3c2f07fc4 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -112,6 +112,7 @@ set(LIBWIRESHARK_FILES
ex-opt.c
except.c
expert.c
+ export_object.c
exported_pdu.c
plugin_if.c
filter_expressions.c
diff --git a/epan/Makefile.am b/epan/Makefile.am
index 04965bb69e..de37f2fa53 100644
--- a/epan/Makefile.am
+++ b/epan/Makefile.am
@@ -75,6 +75,7 @@ LIBWIRESHARK_SRC = \
ex-opt.c \
except.c \
expert.c \
+ export_object.c \
exported_pdu.c \
plugin_if.c \
filter_expressions.c \
@@ -218,6 +219,7 @@ LIBWIRESHARK_INCLUDES = \
except.h \
exceptions.h \
expert.h \
+ export_object.h \
exported_pdu.h \
plugin_if.h \
filter_expressions.h \
diff --git a/epan/dissectors/packet-dcm.c b/epan/dissectors/packet-dcm.c
index ac501bf40f..fc7ee38fbd 100644
--- a/epan/dissectors/packet-dcm.c
+++ b/epan/dissectors/packet-dcm.c
@@ -221,6 +221,7 @@
#include <epan/expert.h>
#include <epan/tap.h>
#include <epan/reassemble.h>
+#include <epan/export_object.h>
#include "packet-tcp.h"
@@ -369,6 +370,38 @@ static const value_string dcm_assoc_item_type[] = {
{ 0, NULL }
};
+static gboolean
+dcm_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
+ const void *data)
+{
+ export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ const dicom_eo_t *eo_info = (const dicom_eo_t *)data;
+ export_object_entry_t *entry;
+
+ if (eo_info) { /* We have data waiting for us */
+ /*
+ Don't copy any data. dcm_export_create_object() is already g_malloc() the items
+ Still, the values will be freed when the export Object window is closed.
+ Therefore, strings and buffers must be copied
+ */
+ entry = g_new(export_object_entry_t, 1);
+
+ entry->pkt_num = pinfo->num;
+ entry->hostname = eo_info->hostname;
+ entry->content_type = eo_info->content_type;
+ entry->filename = g_path_get_basename(eo_info->filename);
+ entry->payload_len = eo_info->payload_len;
+ entry->payload_data = eo_info->payload_data;
+
+ object_list->add_entry(object_list->gui_data, entry);
+
+ return TRUE; /* State changed - window should be redrawn */
+ } else {
+ return FALSE; /* State unchanged - no window updates needed */
+ }
+}
+
+
/* ************************************************************************* */
/* Fragment items */
/* ************************************************************************* */
@@ -7175,7 +7208,7 @@ proto_register_dcm(void)
"When not set, the decoding may fail and the exports may become corrupt.",
&global_dcm_reassemble);
- dicom_eo_tap = register_tap("dicom_eo"); /* DICOM Export Object tap */
+ dicom_eo_tap = register_export_object(proto_dcm, dcm_eo_packet, NULL);
register_init_routine(&dcm_init);
register_cleanup_routine(&dcm_cleanup);
diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c
index 839f562908..194e0eeec0 100644
--- a/epan/dissectors/packet-http.c
+++ b/epan/dissectors/packet-http.c
@@ -43,6 +43,7 @@
#include <epan/to_str.h>
#include <epan/req_resp_hdrs.h>
#include <epan/proto_data.h>
+#include <epan/export_object.h>
#include <wsutil/base64.h>
#include "packet-http.h"
@@ -350,6 +351,34 @@ static dissector_table_t port_subdissector_table;
static dissector_table_t media_type_subdissector_table;
static heur_dissector_list_t heur_subdissector_list;
+
+static gboolean
+http_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
+{
+ export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ const http_eo_t *eo_info = (const http_eo_t *)data;
+ export_object_entry_t *entry;
+
+ if(eo_info) { /* We have data waiting for us */
+ /* These values will be freed when the Export Object window
+ * is closed. */
+ entry = g_new(export_object_entry_t, 1);
+
+ entry->pkt_num = pinfo->num;
+ entry->hostname = g_strdup(eo_info->hostname);
+ entry->content_type = g_strdup(eo_info->content_type);
+ entry->filename = g_path_get_basename(eo_info->filename);
+ entry->payload_len = eo_info->payload_len;
+ entry->payload_data = (guint8 *)g_memdup(eo_info->payload_data, eo_info->payload_len);
+
+ object_list->add_entry(object_list->gui_data, entry);
+
+ return TRUE; /* State changed - window should be redrawn */
+ } else {
+ return FALSE; /* State unchanged - no window updates needed */
+ }
+}
+
/* --- HTTP Status Codes */
/* Note: The reference for uncommented entries is RFC 2616 */
const value_string vals_http_status_code[] = {
@@ -3688,11 +3717,11 @@ proto_register_http(void)
* Register for tapping
*/
http_tap = register_tap("http"); /* HTTP statistics tap */
- http_eo_tap = register_tap("http_eo"); /* HTTP Export Object tap */
http_follow_tap = register_tap("http_follow"); /* HTTP Follow tap */
register_follow_stream(proto_http, "http_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter,
tcp_port_to_display, follow_tvb_tap_listener);
+ http_eo_tap = register_export_object(proto_http, http_eo_packet, NULL);
}
/*
diff --git a/epan/dissectors/packet-imf.c b/epan/dissectors/packet-imf.c
index bb6aeb1ff4..0998eac672 100644
--- a/epan/dissectors/packet-imf.c
+++ b/epan/dissectors/packet-imf.c
@@ -31,6 +31,7 @@
#include <wsutil/str_util.h>
#include <epan/tap.h>
+#include <epan/export_object.h>
#include "packet-ber.h"
#include "packet-http.h"
@@ -154,6 +155,35 @@ static dissector_handle_t imf_handle;
static expert_field ei_imf_unknown_param = EI_INIT;
+
+static gboolean
+imf_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
+{
+ export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ const imf_eo_t *eo_info = (const imf_eo_t *)data;
+ export_object_entry_t *entry;
+
+ if(eo_info) { /* We have data waiting for us */
+ /* These values will be freed when the Export Object window
+ * is closed. */
+ entry = g_new(export_object_entry_t, 1);
+
+ entry->pkt_num = pinfo->num;
+ entry->hostname = NULL;
+ entry->content_type = g_strdup("EML file");
+ entry->filename = g_strdup_printf("from_%s_subject_%s.eml", eo_info->sender_data, eo_info->subject_data);
+ entry->payload_len = eo_info->payload_len;
+ entry->payload_data = (guint8 *)g_memdup(eo_info->payload_data, eo_info->payload_len);
+
+ object_list->add_entry(object_list->gui_data, entry);
+
+ return TRUE; /* State changed - window should be redrawn */
+ } else {
+ return FALSE; /* State unchanged - no window updates needed */
+ }
+}
+
+
struct imf_field {
char *name; /* field name - in lower case for matching purposes */
int *hf_id; /* wireshark field */
@@ -1302,7 +1332,7 @@ proto_register_imf(void)
g_hash_table_insert(imf_field_table, (gpointer)f->name, (gpointer)f);
/* Register for tapping */
- imf_eo_tap = register_tap("imf_eo"); /* IMF Export Object tap */
+ imf_eo_tap = register_export_object(proto_imf, imf_eo_packet, NULL);
}
diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c
index fe9a8a614b..1e16747571 100644
--- a/epan/dissectors/packet-smb.c
+++ b/epan/dissectors/packet-smb.c
@@ -35,6 +35,7 @@
#include <epan/srt_table.h>
#include <epan/expert.h>
#include <epan/to_str.h>
+#include <epan/export_object.h>
#include "packet-windows-common.h"
#include "packet-smb.h"
@@ -968,6 +969,423 @@ smbstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const voi
}
/*
+ * Export object functionality
+ */
+/* These flags show what kind of data the object contains
+ (designed to be or'ed) */
+#define SMB_EO_CONTAINS_NOTHING 0x00
+#define SMB_EO_CONTAINS_READS 0x01
+#define SMB_EO_CONTAINS_WRITES 0x02
+#define SMB_EO_CONTAINS_READSANDWRITES 0x03
+#define LEGAL_FILENAME_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_.- /\\{}[]=()&%$!,;.+&%$~#@"
+
+static const value_string smb_eo_contains_string[] = {
+ {SMB_EO_CONTAINS_NOTHING, "" },
+ {SMB_EO_CONTAINS_READS, "R" },
+ {SMB_EO_CONTAINS_WRITES, "W" },
+ {SMB_EO_CONTAINS_READSANDWRITES, "R&W"},
+ {0, NULL}
+};
+
+/* Strings that describes the SMB object type */
+static const value_string smb_fid_types[] = {
+ {SMB_FID_TYPE_UNKNOWN,"UNKNOWN"},
+ {SMB_FID_TYPE_FILE,"FILE"},
+ {SMB_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
+ {SMB_FID_TYPE_PIPE,"PIPE (Not Implemented)"},
+ {0, NULL}
+};
+
+static const value_string smb2_fid_types[] = {
+ {SMB2_FID_TYPE_UNKNOWN,"UNKNOWN"},
+ {SMB2_FID_TYPE_FILE,"FILE"},
+ {SMB2_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
+ {SMB2_FID_TYPE_PIPE,"PIPE (Not Implemented)"},
+ {SMB2_FID_TYPE_OTHER,"OTHER (Not Implemented)"},
+ {0, NULL}
+};
+
+
+/* This struct contains the relationship between
+ the row# in the export_object window and the file being captured;
+ the row# in this GSList will match the row# in the entry list */
+
+typedef struct _active_file {
+ guint16 tid, uid, fid;
+ guint64 file_length; /* The last free reported offset. We treat it as the file length */
+ guint64 data_gathered; /* The actual total of data gathered */
+ guint8 flag_contains; /* What kind of data it contains */
+ GSList *free_chunk_list; /* A list of virtual "holes" in the file stream stored in memory */
+ gboolean is_out_of_memory; /* TRUE if we cannot allocate memory for this file */
+} active_file ;
+
+/* This is the GSList that will contain all the files that we are tracking */
+static GSList *GSL_active_files = NULL;
+
+/* We define a free chunk in a file as an start offset and end offset
+ Consider a free chunk as a "hole" in a file that we are capturing */
+typedef struct _free_chunk {
+ guint64 start_offset;
+ guint64 end_offset;
+} free_chunk;
+
+/* insert_chunk function will recalculate the free_chunk_list, the data_size,
+ the end_of_file, and the data_gathered as appropriate.
+ It will also insert the data chunk that is coming in the right
+ place of the file in memory.
+ HINTS:
+ file->data_gathered contains the real data gathered independently from the file length
+ file->file_length contains the length of the file in memory, i.e.,
+ the last offset captured. In most cases, the real
+ file length would be different.
+*/
+static void
+insert_chunk(active_file *file, export_object_entry_t *entry, const smb_eo_t *eo_info)
+{
+ gint nfreechunks = g_slist_length(file->free_chunk_list);
+ gint i;
+ free_chunk *current_free_chunk;
+ free_chunk *new_free_chunk;
+ guint64 chunk_offset = eo_info->smb_file_offset;
+ guint64 chunk_length = eo_info->payload_len;
+ guint64 chunk_end_offset = chunk_offset + chunk_length-1;
+ /* Size of file in memory */
+ guint64 calculated_size = chunk_offset + chunk_length;
+ gpointer dest_memory_addr;
+
+ /* Let's recalculate the file length and data gathered */
+ if ((file->data_gathered == 0) && (nfreechunks == 0)) {
+ /* If this is the first entry for this file, we first create an initial free chunk */
+ new_free_chunk = g_new(free_chunk, 1);
+ new_free_chunk->start_offset = 0;
+ new_free_chunk->end_offset = MAX(file->file_length, chunk_end_offset+1) - 1;
+ file->free_chunk_list = NULL;
+ file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
+ nfreechunks += 1;
+ } else {
+ if (chunk_end_offset > file->file_length-1) {
+ new_free_chunk = g_new(free_chunk, 1);
+ new_free_chunk->start_offset = file->file_length;
+ new_free_chunk->end_offset = chunk_end_offset;
+ file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
+ nfreechunks += 1;
+ }
+ }
+ file->file_length = MAX(file->file_length, chunk_end_offset+1);
+
+ /* Recalculate each free chunk according with the incoming data chunk */
+ for (i=0; i<nfreechunks; i++) {
+ current_free_chunk = (free_chunk *)g_slist_nth_data(file->free_chunk_list, i);
+ /* 1. data chunk before the free chunk? */
+ /* -> free chunk is not altered and no new data gathered */
+ if (chunk_end_offset<current_free_chunk->start_offset) {
+ continue;
+ }
+ /* 2. data chunk overlaps the first part of free_chunk */
+ /* -> free chunk shrinks from the beginning */
+ if (chunk_offset<=current_free_chunk->start_offset && chunk_end_offset>=current_free_chunk->start_offset && chunk_end_offset<current_free_chunk->end_offset) {
+ file->data_gathered += chunk_end_offset-current_free_chunk->start_offset+1;
+ current_free_chunk->start_offset=chunk_end_offset+1;
+ continue;
+ }
+ /* 3. data chunk overlaps completely the free chunk */
+ /* -> free chunk is removed */
+ if (chunk_offset<=current_free_chunk->start_offset && chunk_end_offset>=current_free_chunk->end_offset) {
+ file->data_gathered += current_free_chunk->end_offset-current_free_chunk->start_offset+1;
+ file->free_chunk_list = g_slist_remove(file->free_chunk_list, current_free_chunk);
+ nfreechunks -= 1;
+ if (nfreechunks == 0) { /* The free chunk list is empty */
+ g_slist_free(file->free_chunk_list);
+ file->free_chunk_list = NULL;
+ break;
+ }
+ i--;
+ continue;
+ }
+ /* 4. data chunk is inside the free chunk */
+ /* -> free chunk is split into two */
+ if (chunk_offset>current_free_chunk->start_offset && chunk_end_offset<current_free_chunk->end_offset) {
+ new_free_chunk = g_new(free_chunk, 1);
+ new_free_chunk->start_offset = chunk_end_offset + 1;
+ new_free_chunk->end_offset = current_free_chunk->end_offset;
+ current_free_chunk->end_offset = chunk_offset-1;
+ file->free_chunk_list = g_slist_insert(file->free_chunk_list, new_free_chunk, i + 1);
+ file->data_gathered += chunk_length;
+ continue;
+ }
+ /* 5.- data chunk overlaps the end part of free chunk */
+ /* -> free chunk shrinks from the end */
+ if (chunk_offset>current_free_chunk->start_offset && chunk_offset<=current_free_chunk->end_offset && chunk_end_offset>=current_free_chunk->end_offset) {
+ file->data_gathered += current_free_chunk->end_offset-chunk_offset+1;
+ current_free_chunk->end_offset = chunk_offset-1;
+ continue;
+ }
+ /* 6.- data chunk is after the free chunk */
+ /* -> free chunk is not altered and no new data gathered */
+ if (chunk_offset>current_free_chunk->end_offset) {
+ continue;
+ }
+ }
+
+ /* Now, let's insert the data chunk into memory
+ ...first, we shall be able to allocate the memory */
+ if (!entry->payload_data) {
+ /* This is a New file */
+ if (calculated_size > G_MAXSIZE) {
+ /*
+ * The argument to g_try_malloc() is
+ * a gsize, the maximum value of which is
+ * G_MAXSIZE. If the calculated size is
+ * bigger than that, we just say the attempt
+ * to allocate memory failed.
+ */
+ entry->payload_data = NULL;
+ } else {
+ entry->payload_data = (guint8 *)g_try_malloc((gsize)calculated_size);
+ entry->payload_len = calculated_size;
+ }
+ if (!entry->payload_data) {
+ /* Memory error */
+ file->is_out_of_memory = TRUE;
+ }
+ } else {
+ /* This is an existing file in memory */
+ if (calculated_size > (guint64) entry->payload_len &&
+ !file->is_out_of_memory) {
+ /* We need more memory */
+ if (calculated_size > G_MAXSIZE) {
+ /*
+ * As for g_try_malloc(), so for
+ * g_try_realloc().
+ */
+ dest_memory_addr = NULL;
+ } else {
+ dest_memory_addr = g_try_realloc(
+ entry->payload_data,
+ (gsize)calculated_size);
+ }
+ if (!dest_memory_addr) {
+ /* Memory error */
+ file->is_out_of_memory = TRUE;
+ /* We don't have memory for this file.
+ Free the current file content from memory */
+ g_free(entry->payload_data);
+ entry->payload_data = NULL;
+ entry->payload_len = 0;
+ } else {
+ entry->payload_data = (guint8 *)dest_memory_addr;
+ entry->payload_len = calculated_size;
+ }
+ }
+ }
+ /* ...then, put the chunk of the file in the right place */
+ if (!file->is_out_of_memory) {
+ dest_memory_addr = entry->payload_data + chunk_offset;
+ memmove(dest_memory_addr, eo_info->payload_data, eo_info->payload_len);
+ }
+}
+
+/* We use this function to obtain the index in the GSL of a given file */
+static int
+find_incoming_file(GSList *GSL_active_files_p, active_file *incoming_file)
+{
+ int i, row, last;
+ active_file *in_list_file;
+
+ row = -1;
+ last = g_slist_length(GSL_active_files_p) - 1;
+
+ /* We lookup in reverse order because it is more likely that the file
+ is one of the latest */
+ for (i=last; i>=0; i--) {
+ in_list_file = (active_file *)g_slist_nth_data(GSL_active_files_p, i);
+ /* The best-working criteria of two identical files is that the file
+ that is the same of the file that we are analyzing is the last one
+ in the list that has the same tid and the same fid */
+ /* note that we have excluded in_list_file->uid == incoming_file->uid
+ from the comparison, because a file can be opened by different
+ SMB users and it is still the same file */
+ if (in_list_file->tid == incoming_file->tid &&
+ in_list_file->fid == incoming_file->fid) {
+ row = i;
+ break;
+ }
+ }
+
+ return row;
+}
+
+static gboolean
+smb_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
+{
+ export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ const smb_eo_t *eo_info = (const smb_eo_t *)data;
+
+ export_object_entry_t *entry;
+ export_object_entry_t *current_entry;
+ active_file incoming_file;
+ gint active_row;
+ active_file *new_file;
+ active_file *current_file;
+ guint8 contains;
+ gboolean is_supported_filetype;
+ gfloat percent;
+
+ gchar *aux_smb_fid_type_string;
+
+ if (eo_info->smbversion==1) {
+ /* Is this an eo_smb supported file_type? (right now we only support FILE) */
+ is_supported_filetype = (eo_info->fid_type == SMB_FID_TYPE_FILE);
+ aux_smb_fid_type_string=g_strdup(try_val_to_str(eo_info->fid_type, smb_fid_types));
+
+ /* What kind of data this packet contains? */
+ switch(eo_info->cmd) {
+ case SMB_COM_READ_ANDX:
+ case SMB_COM_READ:
+ contains = SMB_EO_CONTAINS_READS;
+ break;
+ case SMB_COM_WRITE_ANDX:
+ case SMB_COM_WRITE:
+ contains = SMB_EO_CONTAINS_WRITES;
+ break;
+ default:
+ contains = SMB_EO_CONTAINS_NOTHING;
+ break;
+ }
+ } else {
+ /* Is this an eo_smb supported file_type? (right now we only support FILE) */
+ is_supported_filetype = (eo_info->fid_type == SMB2_FID_TYPE_FILE );
+ aux_smb_fid_type_string=g_strdup(try_val_to_str(eo_info->fid_type, smb2_fid_types));
+
+ /* What kind of data this packet contains? */
+ switch(eo_info->cmd) {
+ case SMB2_COM_READ:
+ contains = SMB_EO_CONTAINS_READS;
+ break;
+ case SMB2_COM_WRITE:
+ contains = SMB_EO_CONTAINS_WRITES;
+ break;
+ default:
+ contains = SMB_EO_CONTAINS_NOTHING;
+ break;
+ }
+ }
+
+
+ /* Is this data from an already tracked file or not? */
+ incoming_file.tid = eo_info->tid;
+ incoming_file.uid = eo_info->uid;
+ incoming_file.fid = eo_info->fid;
+ active_row = find_incoming_file(GSL_active_files, &incoming_file);
+
+ if (active_row == -1) { /* This is a new-tracked file */
+ /* Construct the entry in the list of active files */
+ entry = g_new(export_object_entry_t, 1);
+ entry->payload_data = NULL;
+ entry->payload_len = 0;
+ new_file = (active_file *)g_malloc(sizeof(active_file));
+ new_file->tid = incoming_file.tid;
+ new_file->uid = incoming_file.uid;
+ new_file->fid = incoming_file.fid;
+ new_file->file_length = eo_info->end_of_file;
+ new_file->flag_contains = contains;
+ new_file->free_chunk_list = NULL;
+ new_file->data_gathered = 0;
+ new_file->is_out_of_memory = FALSE;
+ entry->pkt_num = pinfo->num;
+
+ entry->hostname=g_filename_display_name(g_strcanon(eo_info->hostname,LEGAL_FILENAME_CHARS,'?'));
+ entry->filename=g_filename_display_name(g_strcanon(eo_info->filename,LEGAL_FILENAME_CHARS,'?'));
+
+ /* Insert the first chunk in the chunk list of this file */
+ if (is_supported_filetype) {
+ insert_chunk(new_file, entry, eo_info);
+ }
+
+ if (new_file->is_out_of_memory) {
+ entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
+ aux_smb_fid_type_string,
+ new_file->data_gathered,
+ new_file->file_length,
+ try_val_to_str(contains, smb_eo_contains_string));
+ } else {
+ if (new_file->file_length > 0) {
+ percent = (gfloat) (100*new_file->data_gathered/new_file->file_length);
+ } else {
+ percent = 0.0f;
+ }
+
+ entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
+ aux_smb_fid_type_string,
+ new_file->data_gathered,
+ new_file->file_length,
+ try_val_to_str(contains, smb_eo_contains_string),
+ percent);
+ }
+
+ object_list->add_entry(object_list->gui_data, entry);
+ GSL_active_files = g_slist_append(GSL_active_files, new_file);
+ }
+ else if (is_supported_filetype) {
+ current_file = (active_file *)g_slist_nth_data(GSL_active_files, active_row);
+ /* Recalculate the current file flags */
+ current_file->flag_contains = current_file->flag_contains|contains;
+ current_entry = object_list->get_entry(object_list->gui_data, active_row);
+
+ insert_chunk(current_file, current_entry, eo_info);
+
+ /* Modify the current_entry object_type string */
+ if (current_file->is_out_of_memory) {
+ current_entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
+ aux_smb_fid_type_string,
+ current_file->data_gathered,
+ current_file->file_length,
+ try_val_to_str(current_file->flag_contains, smb_eo_contains_string));
+ } else {
+ percent = (gfloat) (100*current_file->data_gathered/current_file->file_length);
+ current_entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
+ aux_smb_fid_type_string,
+ current_file->data_gathered,
+ current_file->file_length,
+ try_val_to_str(current_file->flag_contains, smb_eo_contains_string),
+ percent);
+ }
+ }
+
+ return TRUE; /* State changed - window should be redrawn */
+}
+
+/* This is the eo_reset_cb function that is used in the export_object module
+ to cleanup any previous private data of the export object functionality before perform
+ the eo_reset function or when the window closes */
+void
+smb_eo_cleanup(void)
+{
+ int i, last;
+ active_file *in_list_file;
+
+ /* Free any previous data structures used in previous invocation to the
+ export_object_smb function */
+ last = g_slist_length(GSL_active_files);
+ if (GSL_active_files) {
+ for (i=last-1; i>=0; i--) {
+ in_list_file = (active_file *)g_slist_nth_data(GSL_active_files, i);
+ if (in_list_file->free_chunk_list) {
+ g_slist_free(in_list_file->free_chunk_list);
+ in_list_file->free_chunk_list = NULL;
+ }
+ g_free(in_list_file);
+ }
+ g_slist_free(GSL_active_files);
+ GSL_active_files = NULL;
+ }
+}
+
+/*
* Macros for use in the main dissector routines for an SMB.
*/
@@ -20621,12 +21039,11 @@ proto_register_smb(void)
register_init_routine(smb_trans_reassembly_init);
smb_tap = register_tap("smb");
- /* Register the tap for the "Export Object" function */
- smb_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */
-
register_dissector("smb", dissect_smb, proto_smb);
register_srt_table(proto_smb, NULL, 3, smbstat_packet, smbstat_init, NULL);
+ /* Register the tap for the "Export Object" function */
+ smb_eo_tap = register_export_object(proto_smb, smb_eo_packet, smb_eo_cleanup);
}
void
diff --git a/epan/dissectors/packet-tftp.c b/epan/dissectors/packet-tftp.c
index b60c716222..ca108b0f57 100644
--- a/epan/dissectors/packet-tftp.c
+++ b/epan/dissectors/packet-tftp.c
@@ -46,6 +46,7 @@
#include <epan/expert.h>
#include <epan/prefs.h>
#include <epan/tap.h>
+#include <epan/export_object.h>
#include "packet-tftp.h"
@@ -140,6 +141,94 @@ static const value_string tftp_error_code_vals[] = {
static int tftp_eo_tap = -1;
+/* A list of block list entries to delete from cleanup callback when window is closed. */
+typedef struct eo_info_dynamic_t {
+ gchar *filename;
+ GSList *block_list;
+} eo_info_dynamic_t;
+static GSList *s_dynamic_info_list = NULL;
+
+/* Tap function */
+static gboolean
+tftp_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
+{
+ export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ const tftp_eo_t *eo_info = (const tftp_eo_t *)data;
+ export_object_entry_t *entry;
+
+ GSList *block_iterator;
+ guint payload_data_offset = 0;
+ eo_info_dynamic_t *dynamic_info;
+
+ /* These values will be freed when the Export Object window is closed. */
+ entry = g_new(export_object_entry_t, 1);
+
+ /* Remember which frame had the last block of the file */
+ entry->pkt_num = pinfo->num;
+
+ /* Copy filename */
+ entry->filename = g_path_get_basename(eo_info->filename);
+
+ /* Iterate over list of blocks and concatenate into contiguous memory */
+ entry->payload_len = eo_info->payload_len;
+ entry->payload_data = (guint8 *)g_try_malloc((gsize)entry->payload_len);
+ for (block_iterator = eo_info->block_list; block_iterator; block_iterator = block_iterator->next) {
+ file_block_t *block = (file_block_t*)block_iterator->data;
+ memcpy(entry->payload_data + payload_data_offset,
+ block->data,
+ block->length);
+ payload_data_offset += block->length;
+ }
+
+ /* These 2 fields not used */
+ entry->hostname = NULL;
+ entry->content_type = NULL;
+
+ /* Add to list of entries to be cleaned up. eo_info is only packet scope, so
+ need to make list only of block list now */
+ dynamic_info = g_new(eo_info_dynamic_t, 1);
+ dynamic_info->filename = eo_info->filename;
+ dynamic_info->block_list = eo_info->block_list;
+ s_dynamic_info_list = g_slist_append(s_dynamic_info_list, (eo_info_dynamic_t*)dynamic_info);
+
+ /* Pass out entry to the GUI */
+ object_list->add_entry(object_list->gui_data, entry);
+
+ return TRUE; /* State changed - window should be redrawn */
+}
+
+/* Clean up the stored parts of a single tapped entry */
+static void cleanup_tftp_eo(eo_info_dynamic_t *dynamic_info)
+{
+ GSList *block_iterator;
+ /* Free the filename */
+ g_free(dynamic_info->filename);
+
+ /* Walk list of block items */
+ for (block_iterator = dynamic_info->block_list; block_iterator; block_iterator = block_iterator->next) {
+ file_block_t *block = (file_block_t*)(block_iterator->data);
+ /* Free block data */
+ wmem_free(NULL, block->data);
+
+ /* Free block itself */
+ g_free(block);
+ }
+}
+
+/* Callback for freeing up data supplied with taps. The taps themselves only have
+ packet scope, so only store/free dynamic memory pointers */
+void tftp_eo_cleanup(void)
+{
+ /* Cleanup each entry in the global list */
+ GSList *dynamic_iterator;
+ for (dynamic_iterator = s_dynamic_info_list; dynamic_iterator; dynamic_iterator = dynamic_iterator->next) {
+ eo_info_dynamic_t *dynamic_info = (eo_info_dynamic_t*)dynamic_iterator->data;
+ cleanup_tftp_eo(dynamic_info);
+ }
+ /* List is empty again */
+ s_dynamic_info_list = NULL;
+}
+
static void
tftp_dissect_options(tvbuff_t *tvb, packet_info *pinfo, int offset,
proto_tree *tree, guint16 opcode, tftp_conv_info_t *tftp_info)
@@ -684,7 +773,7 @@ proto_register_tftp(void)
prefs_register_protocol(proto_tftp, apply_tftp_prefs);
/* Register the tap for the "Export Object" function */
- tftp_eo_tap = register_tap("tftp_eo"); /* TFTP Export Object tap */
+ tftp_eo_tap = register_export_object(proto_tftp, tftp_eo_packet, tftp_eo_cleanup);
}
void
diff --git a/epan/export_object.c b/epan/export_object.c
new file mode 100644
index 0000000000..5c7d38fb6e
--- /dev/null
+++ b/epan/export_object.c
@@ -0,0 +1,206 @@
+/* export_object.c
+ * GUI independent helper routines common to all export object taps.
+ *
+ * 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>
+
+#include "proto.h"
+#include "packet_info.h"
+#include "export_object.h"
+
+struct register_eo {
+ int proto_id; /* protocol id (0-indexed) */
+ const char* tap_listen_str; /* string used in register_tap_listener (NULL to use protocol name) */
+ tap_packet_cb eo_func; /* function to be called for new incoming packets for SRT */
+ export_object_gui_reset_cb reset_cb; /* function to parse parameters of optional arguments of tap string */
+};
+
+static GSList *registered_eo_tables = NULL;
+
+static gint
+insert_sorted_by_table_name(gconstpointer aparam, gconstpointer bparam)
+{
+ const register_eo_t *a = (const register_eo_t *)aparam;
+ const register_eo_t *b = (const register_eo_t *)bparam;
+
+ return g_ascii_strcasecmp(proto_get_protocol_filter_name(a->proto_id), proto_get_protocol_filter_name(b->proto_id));
+}
+
+int
+register_export_object(const int proto_id, tap_packet_cb export_packet_func, export_object_gui_reset_cb reset_cb)
+{
+ register_eo_t *table;
+ DISSECTOR_ASSERT(export_packet_func);
+
+ table = g_new(register_eo_t,1);
+
+ table->proto_id = proto_id;
+ table->tap_listen_str = g_strdup_printf("%s_eo", proto_get_protocol_filter_name(proto_id));
+ table->eo_func = export_packet_func;
+ table->reset_cb = reset_cb;
+
+ registered_eo_tables = g_slist_insert_sorted(registered_eo_tables, table, insert_sorted_by_table_name);
+ return register_tap(table->tap_listen_str);
+}
+
+int get_eo_proto_id(register_eo_t* eo)
+{
+ if (!eo) {
+ return -1;
+ }
+ return eo->proto_id;
+}
+
+const char* get_eo_tap_listener_name(register_eo_t* eo)
+{
+ return eo->tap_listen_str;
+}
+
+tap_packet_cb get_eo_packet_func(register_eo_t* eo)
+{
+ return eo->eo_func;
+}
+
+export_object_gui_reset_cb get_eo_reset_func(register_eo_t* eo)
+{
+ return eo->reset_cb;
+}
+
+register_eo_t* get_eo_by_name(const char* name)
+{
+ guint i, size = g_slist_length(registered_eo_tables);
+ register_eo_t* eo;
+ GSList *slist;
+
+ for (i = 0; i < size; i++) {
+ slist = g_slist_nth(registered_eo_tables, i);
+ eo = (register_eo_t*)slist->data;
+
+ if (strcmp(name, proto_get_protocol_filter_name(eo->proto_id)) == 0)
+ return eo;
+ }
+
+ return NULL;
+}
+
+void eo_iterate_tables(GFunc func, gpointer user_data)
+{
+ g_slist_foreach(registered_eo_tables, func, user_data);
+}
+
+static GString *eo_rename(GString *gstr, int dupn)
+{
+ GString *gstr_tmp;
+ gchar *tmp_ptr;
+ GString *ext_str;
+
+ gstr_tmp = g_string_new("(");
+ g_string_append_printf (gstr_tmp, "%d)", dupn);
+ 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 >= (EXPORT_OBJECT_MAXFILELEN - (strlen(gstr_tmp->str) + ext_str->len)) )
+ gstr = g_string_truncate(gstr, EXPORT_OBJECT_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 >= (EXPORT_OBJECT_MAXFILELEN - strlen(gstr_tmp->str)) )
+ gstr = g_string_truncate(gstr, EXPORT_OBJECT_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 dupn)
+{
+ 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);
+ g_string_append_printf(out_str, "%%%02x", *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 ( dupn != 0 )
+ out_str = eo_rename(out_str, dupn);
+ return out_str;
+}
+
+const char *
+eo_ct2ext(const char *content_type)
+{
+ /* TODO: Map the content type string to an extension string. If no match,
+ * return NULL. */
+ return content_type;
+}
+
+void eo_free_entry(export_object_entry_t *entry)
+{
+ g_free(entry->hostname);
+ g_free(entry->content_type);
+ g_free(entry->filename);
+ g_free(entry->payload_data);
+
+ g_free(entry);
+}
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/epan/export_object.h b/epan/export_object.h
new file mode 100644
index 0000000000..bd068e87c4
--- /dev/null
+++ b/epan/export_object.h
@@ -0,0 +1,155 @@
+/* export_object.h
+ * GUI independent helper routines common to all export object taps.
+ *
+ * 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_H__
+#define __EXPORT_OBJECT_H__
+
+#include "tap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _export_object_entry_t {
+ guint32 pkt_num;
+ gchar *hostname;
+ gchar *content_type;
+ gchar *filename;
+ /* We need to store a 64 bit integer to hold a file length
+ (was guint payload_len;) */
+ gint64 payload_len;
+ guint8 *payload_data;
+} export_object_entry_t;
+
+#define EXPORT_OBJECT_MAXFILELEN 255
+
+typedef void (*export_object_object_list_add_entry_cb)(void* gui_data, struct _export_object_entry_t *entry);
+typedef export_object_entry_t* (*export_object_object_list_get_entry_cb)(void* gui_data, int row);
+
+typedef struct _export_object_list_t {
+ export_object_object_list_add_entry_cb add_entry; //GUI specific handler for adding an object entry
+ export_object_object_list_get_entry_cb get_entry; //GUI specific handler for retrieving an object entry
+ void* gui_data; //GUI specific data (for UI representation)
+} export_object_list_t;
+
+/** Structure for information about a registered exported object */
+typedef struct register_eo register_eo_t;
+
+/* When a protocol needs intermediate data structures to construct the
+export objects, then it must specify 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 (*export_object_gui_reset_cb)(void);
+
+/** Register the export object handler for the Export Object windows.
+ *
+ * @param proto_id is the protocol with objects to export
+ * @param export_packet_func the tap processing function
+ * @param reset_cb handles clearing intermediate data structures constructed
+ * for exporting objects. If no function is needed a NULL value should be passed instead
+ * @return Tap id registered for the Export Object
+ */
+WS_DLL_PUBLIC int register_export_object(const int proto_id, tap_packet_cb export_packet_func, export_object_gui_reset_cb reset_cb);
+
+/** Get protocol ID from Export Object
+ *
+ * @param eo Registered Export Object
+ * @return protocol id of Export Object
+ */
+WS_DLL_PUBLIC int get_eo_proto_id(register_eo_t* eo);
+
+/** Get string for register_tap_listener call. Typically of the form <dissector_name>_eo
+ *
+ * @param eo Registered Export Object
+ * @return string for register_tap_listener call
+ */
+WS_DLL_PUBLIC const char* get_eo_tap_listener_name(register_eo_t* eo);
+
+/** Get tap function handler from Export Object
+ *
+ * @param eo Registered Export Object
+ * @return tap function handler of Export Object
+ */
+WS_DLL_PUBLIC tap_packet_cb get_eo_packet_func(register_eo_t* eo);
+
+/** Get tap reset function handler from Export Object
+ *
+ * @param eo Registered Export Object
+ * @return tap function handler of Export Object
+ */
+WS_DLL_PUBLIC export_object_gui_reset_cb get_eo_reset_func(register_eo_t* eo);
+
+/** Get Export Object by its short protocol name
+ *
+ * @param name short protocol name to fetch.
+ * @return Export Object handler pointer or NULL.
+ */
+WS_DLL_PUBLIC register_eo_t* get_eo_by_name(const char* name);
+
+/** Iterator to walk Export Object list and execute func
+ *
+ * @param func action to be performed on all Export Objects
+ * @param user_data any data needed to help perform function
+ */
+WS_DLL_PUBLIC void eo_iterate_tables(GFunc func, gpointer user_data);
+
+/** Find all disallowed characters/bytes and replace them with %xx
+ *
+ * @param in_str string to massage
+ * @param maxlen maximum size a string can be post massage
+ * @param dup return a copy of the massaged string (?)
+ * @return massaged string
+ */
+WS_DLL_PUBLIC GString *eo_massage_str(const gchar *in_str, gsize maxlen, int dup);
+
+/** Map the content type string to an extension string
+ *
+ * @param content_type content type to match with extension string
+ * @return extension string for content type
+ */
+WS_DLL_PUBLIC const char *eo_ct2ext(const char *content_type);
+
+/** Free the contents of export_object_entry_t structure
+ *
+ * @param entry export_object_entry_t structure to be freed
+ */
+WS_DLL_PUBLIC void eo_free_entry(export_object_entry_t *entry);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXPORT_OBJECT_H__ */
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/tshark.c b/tshark.c
index ff290c2f15..79bc27a81b 100644
--- a/tshark.c
+++ b/tshark.c
@@ -85,6 +85,7 @@
#include "ui/ui_util.h"
#include "ui/decode_as_utils.h"
#include "ui/cli/tshark-tap.h"
+#include "ui/cli/tap-exportobject.h"
#include "ui/tap_export_pdu.h"
#include "ui/dissect_opts.h"
#include "register.h"
@@ -396,6 +397,8 @@ print_usage(FILE *output)
fprintf(output, " --capture-comment <comment>\n");
fprintf(output, " add a capture comment to the newly created\n");
fprintf(output, " output file (only for pcapng)\n");
+ fprintf(output, " --export-objects <protocol>,<destdir> save exported objects for a protocol to\n");
+ fprintf(output, " a directory named \"destdir\"\n");
fprintf(output, "\n");
fprintf(output, "Miscellaneous:\n");
@@ -538,6 +541,7 @@ main(int argc, char *argv[])
{"version", no_argument, NULL, 'v'},
LONGOPT_CAPTURE_COMMON
LONGOPT_DISSECT_COMMON
+ {"export-objects", required_argument, NULL, LONGOPT_EXPORT_OBJECTS},
{0, 0, 0, 0 }
};
gboolean arg_error = FALSE;
@@ -1282,6 +1286,15 @@ main(int argc, char *argv[])
if (!dissect_opts_handle_opt(opt, optarg))
return 1;
break;
+ case LONGOPT_EXPORT_OBJECTS: /* --export-objects */
+ if (strcmp("help", optarg) == 0) {
+ fprintf(stderr, "tshark: The available export object types for the \"--export-objects\" option are:\n");
+ eo_list_object_types();
+ return 0;
+ }
+ if (!eo_tap_opt_add(optarg))
+ return 1;
+ break;
default:
case '?': /* Bad flag - print usage message */
switch(optopt) {
@@ -1572,6 +1585,9 @@ main(int argc, char *argv[])
of the filter. We can now process all the "-z" arguments. */
start_requested_stats();
+ /* We can also enable specified taps for export object */
+ start_exportobjects();
+
/* At this point MATE will have registered its field array so we can
check if the fields specified by the user are all good.
*/
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index 9b38bf9c93..5bd5ec051c 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -28,12 +28,7 @@ set(COMMON_UI_SRC
console.c
decode_as_utils.c
dissect_opts.c
- export_object.c
- export_object_dicom.c
- export_object_http.c
- export_object_imf.c
- export_object_smb.c
- export_object_tftp.c
+ export_object_ui.c
export_pdu_ui_utils.c
help_url.c
firewall_rules.c
diff --git a/ui/Makefile.am b/ui/Makefile.am
index 8359bf7358..3507f9acbd 100644
--- a/ui/Makefile.am
+++ b/ui/Makefile.am
@@ -55,12 +55,7 @@ WIRESHARK_UI_SRC = \
console.c \
decode_as_utils.c \
dissect_opts.c \
- export_object.c \
- export_object_dicom.c \
- export_object_http.c \
- export_object_imf.c \
- export_object_smb.c \
- export_object_tftp.c \
+ export_object_ui.c \
export_pdu_ui_utils.c \
firewall_rules.c \
iface_lists.c \
@@ -102,7 +97,7 @@ WIRESHARK_UI_INCLUDES = \
console.h \
decode_as_utils.h \
dissect_opts.h \
- export_object.h \
+ export_object_ui.h \
export_pdu_ui_utils.h \
last_open_dir.h \
file_dialog.h \
diff --git a/ui/cli/Makefile.am b/ui/cli/Makefile.am
index e5414985e4..a9f1c3aa32 100644
--- a/ui/cli/Makefile.am
+++ b/ui/cli/Makefile.am
@@ -47,7 +47,9 @@ TSHARK_TAP_SRC = \
tap-comparestat.c \
tap-diameter-avp.c \
tap-endpoints.c \
+ tap-endpoints.c \
tap-expert.c \
+ tap-exportobject.c \
tap-follow.c \
tap-funnel.c \
tap-gsm_astat.c \
diff --git a/ui/cli/tap-exportobject.c b/ui/cli/tap-exportobject.c
new file mode 100644
index 0000000000..7ea0f207b4
--- /dev/null
+++ b/ui/cli/tap-exportobject.c
@@ -0,0 +1,279 @@
+/* tap-exportobject.c
+ *
+ * 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 <glib.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+
+#include <wsutil/file_util.h>
+
+#include <epan/packet_info.h>
+#include <epan/packet.h>
+#include <epan/export_object.h>
+#include <ui/export_object_ui.h>
+#include "tap-exportobject.h"
+
+/* XXX - This is effectively a copy of eo_save_entry with the "GUI alerts"
+ * removed to accomodate tshark
+ */
+static gboolean
+local_eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry)
+{
+ int to_fd;
+ gint64 bytes_left;
+ int bytes_to_write;
+ ssize_t bytes_written;
+ guint8 *ptr;
+
+ to_fd = ws_open(save_as_filename, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0644);
+ if(to_fd == -1) { /* An error occurred */
+ 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) {
+ ws_close(to_fd);
+ return FALSE;
+ }
+ bytes_left -= bytes_written;
+ ptr += bytes_written;
+ }
+ if (ws_close(to_fd) < 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+typedef struct _export_object_list_gui_t {
+ GSList *entries;
+ register_eo_t* eo;
+} export_object_list_gui_t;
+
+static GHashTable* eo_opts = NULL;
+
+static void
+list_exportobject_protocol(gpointer data, gpointer user_data _U_)
+{
+ register_eo_t *eo = (register_eo_t*)data;
+
+ fprintf(stderr, " %s\n", proto_get_protocol_filter_name(get_eo_proto_id(eo)));
+}
+
+void eo_list_object_types(void)
+{
+ eo_iterate_tables(list_exportobject_protocol, NULL);
+}
+
+gboolean eo_tap_opt_add(const char *option_string)
+{
+ gchar** splitted;
+
+ if (!eo_opts)
+ eo_opts = g_hash_table_new(g_str_hash,g_str_equal);
+
+ splitted = g_strsplit(option_string, ",", 2);
+
+ if ((splitted[0] == NULL) || (splitted[1] == NULL) || (get_eo_by_name(splitted[0]) == NULL))
+ {
+ fprintf(stderr, "tshark: \"--export-objects\" are specified as: <protocol>,<destdir>\n");
+ fprintf(stderr, "tshark: The available export object types for the \"--export-objects\" option are:\n");
+ eo_list_object_types();
+ }
+ else
+ {
+ gchar* dir = (gchar*)g_hash_table_lookup(eo_opts, splitted[0]);
+
+ /* Since we're saving all objects from a protocol,
+ it can only be listed once */
+ if (dir == NULL) {
+ g_hash_table_insert(eo_opts, splitted[0], splitted[1]);
+
+ g_free(splitted);
+ return TRUE;
+ }
+ else
+ {
+ fprintf(stderr, "tshark: \"--export-objects\" already specified protocol '%s'\n", splitted[0]);
+ }
+ }
+
+ g_strfreev(splitted);
+ return FALSE;
+}
+
+static void
+object_list_add_entry(void *gui_data, export_object_entry_t *entry)
+{
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)gui_data;
+
+ object_list->entries = g_slist_append(object_list->entries, entry);
+}
+
+static export_object_entry_t*
+object_list_get_entry(void *gui_data, int row) {
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)gui_data;
+
+ return (export_object_entry_t *)g_slist_nth_data(object_list->entries, row);
+}
+
+/* This is just for writing Exported Objects to a file */
+static void
+eo_draw(void *tapdata)
+{
+ export_object_list_t *tap_object = (export_object_list_t *)tapdata;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)tap_object->gui_data;
+ GSList *slist = object_list->entries;
+ export_object_entry_t *entry;
+ gboolean all_saved = TRUE;
+ gchar* save_in_path = (gchar*)g_hash_table_lookup(eo_opts, proto_get_protocol_filter_name(get_eo_proto_id(object_list->eo)));
+ GString *safe_filename = NULL;
+ gchar *save_as_fullpath = NULL;
+ int count = 0;
+
+ if (!g_file_test(save_in_path, G_FILE_TEST_IS_DIR)) {
+ /* If the destination directory (or its parents) do not exist, create them. */
+ if (g_mkdir_with_parents(save_in_path, 0755) == -1) {
+ fprintf(stderr, "Failed to create export objects output directory \"%s\": %s\n",
+ save_in_path, g_strerror(errno));
+ return;
+ }
+ }
+
+ if ((strlen(save_in_path) < EXPORT_OBJECT_MAXFILELEN)) {
+ while (slist) {
+ entry = (export_object_entry_t *)slist->data;
+ do {
+ g_free(save_as_fullpath);
+ if (entry->filename) {
+ safe_filename = eo_massage_str(entry->filename,
+ EXPORT_OBJECT_MAXFILELEN - strlen(save_in_path), count);
+ } else {
+ char generic_name[EXPORT_OBJECT_MAXFILELEN+1];
+ const char *ext;
+ ext = eo_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,
+ EXPORT_OBJECT_MAXFILELEN - strlen(save_in_path), count);
+ }
+ save_as_fullpath = g_build_filename(save_in_path, safe_filename->str, NULL);
+ g_string_free(safe_filename, TRUE);
+ } while (g_file_test(save_as_fullpath, G_FILE_TEST_EXISTS) && ++count < 1000);
+ count = 0;
+ if (!local_eo_save_entry(save_as_fullpath, entry))
+ all_saved = FALSE;
+ g_free(save_as_fullpath);
+ save_as_fullpath = NULL;
+ slist = slist->next;
+ }
+ }
+ else
+ {
+ all_saved = FALSE;
+ }
+
+ if (!all_saved)
+ fprintf(stderr, "Export objects (%s): Some files could not be saved.\n",
+ proto_get_protocol_filter_name(get_eo_proto_id(object_list->eo)));
+}
+
+static void
+exportobject_handler(gpointer key, gpointer value _U_, gpointer user_data _U_)
+{
+ GString *error_msg;
+ export_object_list_t *tap_data;
+ export_object_list_gui_t *object_list;
+ register_eo_t* eo;
+
+ eo = get_eo_by_name((const char*)key);
+ if (eo == NULL)
+ {
+ fprintf(stderr, "tshark: \"--export-objects\" INTERNAL ERROR '%s' protocol not found\n", (const char*)key);
+ return;
+ }
+
+ tap_data = g_new0(export_object_list_t,1);
+ object_list = g_new0(export_object_list_gui_t,1);
+
+ tap_data->add_entry = object_list_add_entry;
+ tap_data->get_entry = object_list_get_entry;
+ tap_data->gui_data = (void*)object_list;
+
+ object_list->eo = eo;
+
+ /* Data will be gathered via a tap callback */
+ error_msg = register_tap_listener(get_eo_tap_listener_name(eo), tap_data, NULL, 0,
+ NULL, get_eo_packet_func(eo), eo_draw);
+
+ if (error_msg) {
+ fprintf(stderr, "tshark: Can't register %s tap: %s\n", (const char*)key, error_msg->str);
+ g_string_free(error_msg, TRUE);
+ g_free(tap_data);
+ g_free(object_list);
+ return;
+ }
+}
+
+void start_exportobjects(void)
+{
+ if (eo_opts != NULL)
+ g_hash_table_foreach(eo_opts, exportobject_handler, NULL);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/cli/tap-exportobject.h b/ui/cli/tap-exportobject.h
new file mode 100644
index 0000000000..25cfa333e3
--- /dev/null
+++ b/ui/cli/tap-exportobject.h
@@ -0,0 +1,55 @@
+/* tap-exportobject.h
+ *
+ * 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 __TAP_EXPORT_OBJECT_H__
+#define __TAP_EXPORT_OBJECT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define LONGOPT_EXPORT_OBJECTS 5001
+
+void eo_list_object_types(void);
+
+/* will be called by main each time a --export-objects option is found */
+gboolean eo_tap_opt_add(const char *optarg);
+
+void start_exportobjects(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TAP_EXPORT_OBJECT_H__ */
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */
diff --git a/ui/export_object.h b/ui/export_object.h
deleted file mode 100644
index af71eedbde..0000000000
--- a/ui/export_object.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* export_object.h
- * Common routines for tracking & saving objects found in streams of data
- * Copyright 2007, Stephen Fisher (see AUTHORS file)
- *
- * 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_H__
-#define __EXPORT_OBJECT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Common between protocols */
-
-struct _export_object_list_t;
-typedef struct _export_object_list_t export_object_list_t;
-
-typedef struct _export_object_entry_t {
- guint32 pkt_num;
- gchar *hostname;
- gchar *content_type;
- gchar *filename;
- /* We need to store a 64 bit integer to hold a file length
- (was guint payload_len;) */
- gint64 payload_len;
- guint8 *payload_data;
-} 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);
-gboolean eo_http_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data);
-gboolean eo_imf_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data);
-gboolean eo_smb_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data);
-gboolean eo_tftp_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data);
-
-void eo_smb_cleanup(void);
-void eo_tftp_cleanup(void);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __EXPORT_OBJECT_H__ */
-
-/*
- * Editor modelines
- *
- * Local Variables:
- * c-basic-offset: 4
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- *
- * ex: set shiftwidth=4 tabstop=8 expandtab:
- * :indentSize=4:tabSize=8:noTabs=true:
- */
diff --git a/ui/export_object_dicom.c b/ui/export_object_dicom.c
deleted file mode 100644
index 5404abb54f..0000000000
--- a/ui/export_object_dicom.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* export_object_dicom.c
- * Routines for tracking & saving objects found in DICOM streams
- * See also: export_object.c / export_object.h for common code
- * Copyright 2008, David Aggeler <david_aggeler@hispeed.ch>
- *
- * 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 <glib.h>
-
-#include <epan/dissectors/packet-dcm.h>
-
-#include <epan/packet.h>
-#include <epan/tap.h>
-
-#include "export_object.h"
-
-gboolean
-eo_dicom_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data)
-{
- export_object_list_t *object_list = (export_object_list_t *)tapdata;
- const dicom_eo_t *eo_info = (const dicom_eo_t *)data;
- export_object_entry_t *entry;
-
- if (eo_info) { /* We have data waiting for us */
- /*
- Don't copy any data. dcm_export_create_object() is already g_malloc() the items
- Still, the values will be freed when the export Object window is closed.
- Therefore, strings and buffers must be copied
- */
- entry = (export_object_entry_t *)g_malloc(sizeof(export_object_entry_t));
-
- entry->pkt_num = pinfo->num;
- entry->hostname = eo_info->hostname;
- entry->content_type = eo_info->content_type;
- entry->filename = g_strdup(g_path_get_basename(eo_info->filename));
- entry->payload_len = eo_info->payload_len;
- entry->payload_data = eo_info->payload_data;
-
- object_list_add_entry(object_list, entry);
-
- return TRUE; /* State changed - window should be redrawn */
- } else {
- return FALSE; /* State unchanged - no window updates needed */
- }
-}
-/*
- * Editor modelines
- *
- * Local Variables:
- * c-basic-offset: 4
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- *
- * ex: set shiftwidth=4 tabstop=8 expandtab:
- * :indentSize=4:tabSize=8:noTabs=true:
- */
diff --git a/ui/export_object_http.c b/ui/export_object_http.c
deleted file mode 100644
index 3b314c4fb5..0000000000
--- a/ui/export_object_http.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* export_object_http.c
- * Routines for tracking & saving objects found in HTTP streams
- * See also: export_object.c / export_object.h for common code
- * Copyright 2007, Stephen Fisher (see AUTHORS file)
- *
- * 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 <epan/dissectors/packet-http.h>
-#include <epan/tap.h>
-
-#include "export_object.h"
-
-
-gboolean
-eo_http_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data)
-{
- export_object_list_t *object_list = (export_object_list_t *)tapdata;
- const http_eo_t *eo_info = (const http_eo_t *)data;
- export_object_entry_t *entry;
-
- if(eo_info) { /* We have data waiting for us */
- /* These values will be freed when the Export Object window
- * is closed. */
- entry = (export_object_entry_t *)g_malloc(sizeof(export_object_entry_t));
-
- entry->pkt_num = pinfo->num;
- entry->hostname = g_strdup(eo_info->hostname);
- entry->content_type = g_strdup(eo_info->content_type);
- entry->filename = g_strdup(g_path_get_basename(eo_info->filename));
- entry->payload_len = eo_info->payload_len;
- entry->payload_data = (guint8 *)g_memdup(eo_info->payload_data,
- eo_info->payload_len);
-
- object_list_add_entry(object_list, entry);
-
- return TRUE; /* State changed - window should be redrawn */
- } else {
- return FALSE; /* State unchanged - no window updates needed */
- }
-}
-
-/*
- * Editor modelines
- *
- * Local Variables:
- * c-basic-offset: 4
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- *
- * ex: set shiftwidth=4 tabstop=8 expandtab:
- * :indentSize=4:tabSize=8:noTabs=true:
- */
diff --git a/ui/export_object_imf.c b/ui/export_object_imf.c
deleted file mode 100644
index 5e4e275691..0000000000
--- a/ui/export_object_imf.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* export_object_imf.c
- * Routines for tracking & saving objects found in IMF streams
- * See also: export_object.c / export_object.h for common code
- * Copyright 2016, Moshe Kaplan
- *
- * 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 <epan/dissectors/packet-imf.h>
-#include <epan/tap.h>
-
-#include "export_object.h"
-
-
-gboolean
-eo_imf_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data)
-{
- export_object_list_t *object_list = (export_object_list_t *)tapdata;
- const imf_eo_t *eo_info = (const imf_eo_t *)data;
- export_object_entry_t *entry;
-
- if(eo_info) { /* We have data waiting for us */
- /* These values will be freed when the Export Object window
- * is closed. */
- entry = (export_object_entry_t *)g_malloc(sizeof(export_object_entry_t));
-
- entry->pkt_num = pinfo->num;
- entry->hostname = NULL;
- entry->content_type = g_strdup("EML file");
- entry->filename = g_strdup_printf("from_%s_subject_%s.eml", eo_info->sender_data, eo_info->subject_data);
- entry->payload_len = eo_info->payload_len;
- entry->payload_data = (guint8 *)g_memdup(eo_info->payload_data,
- eo_info->payload_len);
-
- object_list_add_entry(object_list, entry);
-
- return TRUE; /* State changed - window should be redrawn */
- } else {
- return FALSE; /* State unchanged - no window updates needed */
- }
-}
-
-/*
- * Editor modelines
- *
- * Local Variables:
- * c-basic-offset: 4
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- *
- * ex: set shiftwidth=4 tabstop=8 expandtab:
- * :indentSize=4:tabSize=8:noTabs=true:
- */
diff --git a/ui/export_object_smb.c b/ui/export_object_smb.c
deleted file mode 100644
index 4ccd1c07f2..0000000000
--- a/ui/export_object_smb.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/* export_object_smb.c
- * Routines for tracking & saving objects (files) found in SMB streams
- * See also: export_object.c / export_object.h for common code
- * Initial file, prototypes and general structure initially copied
- * from export_object_http.c
- *
- * Copyright 2010, David Perez & Jose Pico from TADDONG S.L.
- *
- * 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 <epan/packet.h>
-#include <epan/dissectors/packet-smb2.h>
-#include <epan/tap.h>
-
-#include "export_object.h"
-
-
-/* These flags show what kind of data the object contains
- (designed to be or'ed) */
-#define SMB_EO_CONTAINS_NOTHING 0x00
-#define SMB_EO_CONTAINS_READS 0x01
-#define SMB_EO_CONTAINS_WRITES 0x02
-#define SMB_EO_CONTAINS_READSANDWRITES 0x03
-#define LEGAL_FILENAME_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_.- /\\{}[]=()&%$!,;.+&%$~#@"
-
-static const value_string smb_eo_contains_string[] = {
- {SMB_EO_CONTAINS_NOTHING, "" },
- {SMB_EO_CONTAINS_READS, "R" },
- {SMB_EO_CONTAINS_WRITES, "W" },
- {SMB_EO_CONTAINS_READSANDWRITES, "R&W"},
- {0, NULL}
-};
-
-/* Strings that describes the SMB object type */
-static const value_string smb_fid_types[] = {
- {SMB_FID_TYPE_UNKNOWN,"UNKNOWN"},
- {SMB_FID_TYPE_FILE,"FILE"},
- {SMB_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
- {SMB_FID_TYPE_PIPE,"PIPE (Not Implemented)"},
- {0, NULL}
-};
-
-static const value_string smb2_fid_types[] = {
- {SMB2_FID_TYPE_UNKNOWN,"UNKNOWN"},
- {SMB2_FID_TYPE_FILE,"FILE"},
- {SMB2_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
- {SMB2_FID_TYPE_PIPE,"PIPE (Not Implemented)"},
- {SMB2_FID_TYPE_OTHER,"OTHER (Not Implemented)"},
- {0, NULL}
-};
-
-/* This struct contains the relationship between
- the row# in the export_object window and the file being captured;
- the row# in this GSList will match the row# in the entry list */
-
-typedef struct _active_file {
- guint16 tid, uid, fid;
- guint64 file_length; /* The last free reported offset */
- /* We treat it as the file length */
- guint64 data_gathered; /* The actual total of data gathered */
- guint8 flag_contains; /* What kind of data it contains */
- GSList *free_chunk_list; /* A list of virtual "holes" in the */
- /* file stream stored in memory */
- gboolean is_out_of_memory; /* TRUE if we cannot allocate memory */
- /* memory for this file */
- } active_file ;
-
-/* This is the GSList that will contain all the files that we are tracking */
-static GSList *GSL_active_files = NULL;
-
-/* We define a free chunk in a file as an start offset and end offset
- Consider a free chunk as a "hole" in a file that we are capturing */
-typedef struct _free_chunk {
- guint64 start_offset;
- guint64 end_offset;
-} free_chunk;
-
-/* insert_chunk function will recalculate the free_chunk_list, the data_size,
- the end_of_file, and the data_gathered as appropriate.
- It will also insert the data chunk that is coming in the right
- place of the file in memory.
- HINTS:
- file->data_gathered contains the real data gathered independently
- from the file length
- file->file_length contains the length of the file in memory, i.e.,
- the last offset captured. In most cases, the real
- file length would be different.
-*/
-static void
-insert_chunk(active_file *file, export_object_entry_t *entry, const smb_eo_t *eo_info)
-{
- gint nfreechunks = g_slist_length(file->free_chunk_list);
- gint i;
- free_chunk *current_free_chunk;
- free_chunk *new_free_chunk;
- guint64 chunk_offset = eo_info->smb_file_offset;
- guint64 chunk_length = eo_info->payload_len;
- guint64 chunk_end_offset = chunk_offset + chunk_length-1;
-/* Size of file in memory */
- guint64 calculated_size = chunk_offset + chunk_length;
- gpointer dest_memory_addr;
-
- /* Let's recalculate the file length and data gathered */
- if ((file->data_gathered == 0) && (nfreechunks == 0)) {
- /* If this is the first entry for this file, we first
- create an initial free chunk */
- new_free_chunk = (free_chunk *)g_malloc(sizeof(free_chunk));
- new_free_chunk->start_offset = 0;
- new_free_chunk->end_offset = MAX(file->file_length, chunk_end_offset+1) - 1;
- file->free_chunk_list = NULL;
- file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
- nfreechunks += 1;
- } else {
- if (chunk_end_offset > file->file_length-1) {
- new_free_chunk = (free_chunk *)g_malloc(sizeof(free_chunk));
- new_free_chunk->start_offset = file->file_length;
- new_free_chunk->end_offset = chunk_end_offset;
- file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
- nfreechunks += 1;
- }
- }
- file->file_length = MAX(file->file_length, chunk_end_offset+1);
-
- /* Recalculate each free chunk according with the incoming data chunk */
- for (i=0; i<nfreechunks; i++) {
- current_free_chunk = (free_chunk *)g_slist_nth_data(file->free_chunk_list, i);
- /* 1. data chunk before the free chunk? */
- /* -> free chunk is not altered and no new data gathered */
- if (chunk_end_offset<current_free_chunk->start_offset) {
- continue;
- }
- /* 2. data chunk overlaps the first part of free_chunk */
- /* -> free chunk shrinks from the beginning */
- if (chunk_offset<=current_free_chunk->start_offset && chunk_end_offset>=current_free_chunk->start_offset && chunk_end_offset<current_free_chunk->end_offset) {
- file->data_gathered += chunk_end_offset-current_free_chunk->start_offset+1;
- current_free_chunk->start_offset=chunk_end_offset+1;
- continue;
- }
- /* 3. data chunk overlaps completely the free chunk */
- /* -> free chunk is removed */
- if (chunk_offset<=current_free_chunk->start_offset && chunk_end_offset>=current_free_chunk->end_offset) {
- file->data_gathered += current_free_chunk->end_offset-current_free_chunk->start_offset+1;
- file->free_chunk_list = g_slist_remove(file->free_chunk_list, current_free_chunk);
- nfreechunks -= 1;
- if (nfreechunks == 0) { /* The free chunk list is empty */
- g_slist_free(file->free_chunk_list);
- file->free_chunk_list = NULL;
- break;
- }
- i--;
- continue;
- }
- /* 4. data chunk is inside the free chunk */
- /* -> free chunk is split into two */
- if (chunk_offset>current_free_chunk->start_offset && chunk_end_offset<current_free_chunk->end_offset) {
- new_free_chunk = (free_chunk *)g_malloc(sizeof(free_chunk));
- new_free_chunk->start_offset = chunk_end_offset + 1;
- new_free_chunk->end_offset = current_free_chunk->end_offset;
- current_free_chunk->end_offset = chunk_offset-1;
- file->free_chunk_list = g_slist_insert(file->free_chunk_list, new_free_chunk, i + 1);
- file->data_gathered += chunk_length;
- continue;
- }
- /* 5.- data chunk overlaps the end part of free chunk */
- /* -> free chunk shrinks from the end */
- if (chunk_offset>current_free_chunk->start_offset && chunk_offset<=current_free_chunk->end_offset && chunk_end_offset>=current_free_chunk->end_offset) {
- file->data_gathered += current_free_chunk->end_offset-chunk_offset+1;
- current_free_chunk->end_offset = chunk_offset-1;
- continue;
- }
- /* 6.- data chunk is after the free chunk */
- /* -> free chunk is not altered and no new data gathered */
- if (chunk_offset>current_free_chunk->end_offset) {
- continue;
- }
- }
-
- /* Now, let's insert the data chunk into memory
- ...first, we shall be able to allocate the memory */
- if (!entry->payload_data) {
- /* This is a New file */
- if (calculated_size > G_MAXSIZE) {
- /*
- * The argument to g_try_malloc() is
- * a gsize, the maximum value of which is
- * G_MAXSIZE. If the calculated size is
- * bigger than that, we just say the attempt
- * to allocate memory failed.
- */
- entry->payload_data = NULL;
- } else {
- entry->payload_data = (guint8 *)g_try_malloc((gsize)calculated_size);
- entry->payload_len = calculated_size;
- }
- if (!entry->payload_data) {
- /* Memory error */
- file->is_out_of_memory = TRUE;
- }
- } else {
- /* This is an existing file in memory */
- if (calculated_size > (guint64) entry->payload_len &&
- !file->is_out_of_memory) {
- /* We need more memory */
- if (calculated_size > G_MAXSIZE) {
- /*
- * As for g_try_malloc(), so for
- * g_try_realloc().
- */
- dest_memory_addr = NULL;
- } else {
- dest_memory_addr = g_try_realloc(
- entry->payload_data,
- (gsize)calculated_size);
- }
- if (!dest_memory_addr) {
- /* Memory error */
- file->is_out_of_memory = TRUE;
- /* We don't have memory for this file.
- Free the current file content from memory */
- g_free(entry->payload_data);
- entry->payload_data = NULL;
- entry->payload_len = 0;
- } else {
- entry->payload_data = (guint8 *)dest_memory_addr;
- entry->payload_len = calculated_size;
- }
- }
- }
- /* ...then, put the chunk of the file in the right place */
- if (!file->is_out_of_memory) {
- dest_memory_addr = entry->payload_data + chunk_offset;
- memmove(dest_memory_addr, eo_info->payload_data, eo_info->payload_len);
- }
-}
-
-/* We use this function to obtain the index in the GSL of a given file */
-static int
-find_incoming_file(GSList *GSL_active_files_p, active_file *incoming_file)
-{
- int i, row, last;
- active_file *in_list_file;
-
- row = -1;
- last = g_slist_length(GSL_active_files_p) - 1;
-
- /* We lookup in reverse order because it is more likely that the file
- is one of the latest */
- for (i=last; i>=0; i--) {
- in_list_file = (active_file *)g_slist_nth_data(GSL_active_files_p, i);
- /* The best-working criteria of two identical files is that the file
- that is the same of the file that we are analyzing is the last one
- in the list that has the same tid and the same fid */
- /* note that we have excluded in_list_file->uid == incoming_file->uid
- from the comparison, because a file can be opened by different
- SMB users and it is still the same file */
- if (in_list_file->tid == incoming_file->tid &&
- in_list_file->fid == incoming_file->fid) {
- row = i;
- break;
- }
- }
-
- return row;
-}
-
-/* This is the function answering to the registered tap listener call */
-gboolean
-eo_smb_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
-{
- export_object_list_t *object_list = (export_object_list_t *)tapdata;
- const smb_eo_t *eo_info = (const smb_eo_t *)data;
-
- export_object_entry_t *entry;
- export_object_entry_t *current_entry;
- active_file incoming_file;
- gint active_row;
- active_file *new_file;
- active_file *current_file;
- guint8 contains;
- gboolean is_supported_filetype;
- gfloat percent;
-
- gchar *aux_smb_fid_type_string;
-
- if (eo_info->smbversion==1) {
- /* Is this an eo_smb supported file_type? (right now we only support FILE) */
- is_supported_filetype = (eo_info->fid_type == SMB_FID_TYPE_FILE);
- aux_smb_fid_type_string=g_strdup(try_val_to_str(eo_info->fid_type, smb_fid_types));
-
- /* What kind of data this packet contains? */
- switch(eo_info->cmd) {
- case SMB_COM_READ_ANDX:
- case SMB_COM_READ:
- contains = SMB_EO_CONTAINS_READS;
- break;
- case SMB_COM_WRITE_ANDX:
- case SMB_COM_WRITE:
- contains = SMB_EO_CONTAINS_WRITES;
- break;
- default:
- contains = SMB_EO_CONTAINS_NOTHING;
- break;
- }
- } else {
- /* Is this an eo_smb supported file_type? (right now we only support FILE) */
- is_supported_filetype = (eo_info->fid_type == SMB2_FID_TYPE_FILE );
- aux_smb_fid_type_string=g_strdup(try_val_to_str(eo_info->fid_type, smb2_fid_types));
-
- /* What kind of data this packet contains? */
- switch(eo_info->cmd) {
- case SMB2_COM_READ:
- contains = SMB_EO_CONTAINS_READS;
- break;
- case SMB2_COM_WRITE:
- contains = SMB_EO_CONTAINS_WRITES;
- break;
- default:
- contains = SMB_EO_CONTAINS_NOTHING;
- break;
- }
- }
-
-
- /* Is this data from an already tracked file or not? */
- incoming_file.tid = eo_info->tid;
- incoming_file.uid = eo_info->uid;
- incoming_file.fid = eo_info->fid;
- active_row = find_incoming_file(GSL_active_files, &incoming_file);
-
- if (active_row == -1) { /* This is a new-tracked file */
- /* Construct the entry in the list of active files */
- entry = (export_object_entry_t *)g_malloc(sizeof(export_object_entry_t));
- entry->payload_data = NULL;
- entry->payload_len = 0;
- new_file = (active_file *)g_malloc(sizeof(active_file));
- new_file->tid = incoming_file.tid;
- new_file->uid = incoming_file.uid;
- new_file->fid = incoming_file.fid;
- new_file->file_length = eo_info->end_of_file;
- new_file->flag_contains = contains;
- new_file->free_chunk_list = NULL;
- new_file->data_gathered = 0;
- new_file->is_out_of_memory = FALSE;
- entry->pkt_num = pinfo->num;
-
- entry->hostname=g_filename_display_name(g_strcanon(eo_info->hostname,LEGAL_FILENAME_CHARS,'?'));
- entry->filename=g_filename_display_name(g_strcanon(eo_info->filename,LEGAL_FILENAME_CHARS,'?'));
-
- /* Insert the first chunk in the chunk list of this file */
- if (is_supported_filetype) {
- insert_chunk(new_file, entry, eo_info);
- }
-
- if (new_file->is_out_of_memory) {
- entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
- aux_smb_fid_type_string,
- new_file->data_gathered,
- new_file->file_length,
- try_val_to_str(contains, smb_eo_contains_string));
- } else {
- if (new_file->file_length > 0) {
- percent = (gfloat) (100*new_file->data_gathered/new_file->file_length);
- } else {
- percent = 0.0f;
- }
-
- entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
- aux_smb_fid_type_string,
- new_file->data_gathered,
- new_file->file_length,
- try_val_to_str(contains, smb_eo_contains_string),
- percent);
- }
-
- object_list_add_entry(object_list, entry);
- GSL_active_files = g_slist_append(GSL_active_files, new_file);
- }
- else if (is_supported_filetype) {
- current_file = (active_file *)g_slist_nth_data(GSL_active_files, active_row);
- /* Recalculate the current file flags */
- current_file->flag_contains = current_file->flag_contains|contains;
- current_entry = object_list_get_entry(object_list, active_row);
-
- insert_chunk(current_file, current_entry, eo_info);
-
- /* Modify the current_entry object_type string */
- if (current_file->is_out_of_memory) {
- current_entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
- aux_smb_fid_type_string,
- current_file->data_gathered,
- current_file->file_length,
- try_val_to_str(current_file->flag_contains, smb_eo_contains_string));
- } else {
- percent = (gfloat) (100*current_file->data_gathered/current_file->file_length);
- current_entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
- aux_smb_fid_type_string,
- current_file->data_gathered,
- current_file->file_length,
- try_val_to_str(current_file->flag_contains, smb_eo_contains_string),
- percent);
- }
- }
-
- return TRUE; /* State changed - window should be redrawn */
-}
-
-
-/* This is the eo_protocoldata_reset function that is used in the export_object module
- to cleanup any previous private data of the export object functionality before perform
- the eo_reset function or when the window closes */
-void
-eo_smb_cleanup(void)
-{
- int i, last;
- active_file *in_list_file;
-
- /* Free any previous data structures used in previous invocation to the
- export_object_smb function */
- last = g_slist_length(GSL_active_files);
- if (GSL_active_files) {
- for (i=last-1; i>=0; i--) {
- in_list_file = (active_file *)g_slist_nth_data(GSL_active_files, i);
- if (in_list_file->free_chunk_list) {
- g_slist_free(in_list_file->free_chunk_list);
- in_list_file->free_chunk_list = NULL;
- }
- g_free(in_list_file);
- }
- g_slist_free(GSL_active_files);
- GSL_active_files = NULL;
- }
-}
-
-/*
- * Editor modelines
- *
- * Local Variables:
- * c-basic-offset: 4
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- *
- * ex: set shiftwidth=4 tabstop=8 expandtab:
- * :indentSize=4:tabSize=8:noTabs=true:
- */
diff --git a/ui/export_object_tftp.c b/ui/export_object_tftp.c
deleted file mode 100644
index 11547aca38..0000000000
--- a/ui/export_object_tftp.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* export_object_tftp.c
- * Routines for aving objects (files) found in TFTP sessions
- * See also: export_object.c / export_object.h for common code
- * Initial file, prototypes and general structure initially copied
- * from export_object_smb.c
- *
- * Martin Mathieson
- *
- * 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 <epan/packet.h>
-#include <epan/dissectors/packet-tftp.h>
-#include <epan/tap.h>
-
-#include "export_object.h"
-
-/* A list of block list entries to delete from cleanup callback when window is closed. */
-typedef struct eo_info_dynamic_t {
- gchar *filename;
- GSList *block_list;
-} eo_info_dynamic_t;
-static GSList *s_dynamic_info_list = NULL;
-
-/* Tap function */
-gboolean
-eo_tftp_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data)
-{
- export_object_list_t *object_list = (export_object_list_t *)tapdata;
- const tftp_eo_t *eo_info = (const tftp_eo_t *)data;
- export_object_entry_t *entry;
-
- GSList *block_iterator;
- guint payload_data_offset = 0;
- eo_info_dynamic_t *dynamic_info;
-
- /* These values will be freed when the Export Object window is closed. */
- entry = (export_object_entry_t*)g_malloc(sizeof(export_object_entry_t));
-
- /* Remember which frame had the last block of the file */
- entry->pkt_num = pinfo->num;
-
- /* Copy filename */
- entry->filename = g_strdup(g_path_get_basename(eo_info->filename));
-
- /* Iterate over list of blocks and concatenate into contiguous memory */
- entry->payload_len = eo_info->payload_len;
- entry->payload_data = (guint8 *)g_try_malloc((gsize)entry->payload_len);
- for (block_iterator = eo_info->block_list; block_iterator; block_iterator = block_iterator->next) {
- file_block_t *block = (file_block_t*)block_iterator->data;
- memcpy(entry->payload_data + payload_data_offset,
- block->data,
- block->length);
- payload_data_offset += block->length;
- }
-
- /* These 2 fields not used */
- entry->hostname = NULL;
- entry->content_type = NULL;
-
- /* Add to list of entries to be cleaned up. eo_info is only packet scope, so
- need to make list only of block list now */
- dynamic_info = (eo_info_dynamic_t*)g_malloc(sizeof(eo_info_dynamic_t));
- dynamic_info->filename = eo_info->filename;
- dynamic_info->block_list = eo_info->block_list;
- s_dynamic_info_list = g_slist_append(s_dynamic_info_list, (eo_info_dynamic_t*)dynamic_info);
-
- /* Pass out entry to the GUI */
- object_list_add_entry(object_list, entry);
-
- return TRUE; /* State changed - window should be redrawn */
-}
-
-/* Clean up the stored parts of a single tapped entry */
-static void cleanup_tftp_eo(eo_info_dynamic_t *dynamic_info)
-{
- GSList *block_iterator;
- /* Free the filename */
- g_free(dynamic_info->filename);
-
- /* Walk list of block items */
- for (block_iterator = dynamic_info->block_list; block_iterator; block_iterator = block_iterator->next) {
- file_block_t *block = (file_block_t*)(block_iterator->data);
- /* Free block data */
- wmem_free(NULL, block->data);
-
- /* Free block itself */
- g_free(block);
- }
-}
-
-/* Callback for freeing up data supplied with taps. The taps themselves only have
- packet scope, so only store/free dynamic memory pointers */
-void eo_tftp_cleanup(void)
-{
- /* Cleanup each entry in the global list */
- GSList *dynamic_iterator;
- for (dynamic_iterator = s_dynamic_info_list; dynamic_iterator; dynamic_iterator = dynamic_iterator->next) {
- eo_info_dynamic_t *dynamic_info = (eo_info_dynamic_t*)dynamic_iterator->data;
- cleanup_tftp_eo(dynamic_info);
- }
- /* List is empty again */
- s_dynamic_info_list = NULL;
-}
-
-/*
- * Editor modelines
- *
- * Local Variables:
- * c-basic-offset: 4
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- *
- * ex: set shiftwidth=4 tabstop=8 expandtab:
- * :indentSize=4:tabSize=8:noTabs=true:
- */
diff --git a/ui/export_object.c b/ui/export_object_ui.c
index 67e883f056..2db2fe5516 100644
--- a/ui/export_object.c
+++ b/ui/export_object_ui.c
@@ -1,4 +1,4 @@
-/* export_object.c
+/* export_object_ui.c
* Common routines for tracking & saving objects found in streams of data
* Copyright 2007, Stephen Fisher (see AUTHORS file)
*
@@ -39,7 +39,7 @@
#include <ui/alert_box.h>
-#include "export_object.h"
+#include "export_object_ui.h"
gboolean
eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry, gboolean show_err)
@@ -102,89 +102,6 @@ eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry, gbool
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 dupn)
-{
- GString *gstr_tmp;
- gchar *tmp_ptr;
- GString *ext_str;
-
- gstr_tmp = g_string_new("(");
- g_string_append_printf (gstr_tmp, "%d)", dupn);
- 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 dupn)
-{
- 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 ( dupn != 0 )
- out_str = eo_rename(out_str, dupn);
- 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;
-}
-
/*
* Editor modelines
*
diff --git a/ui/export_object_ui.h b/ui/export_object_ui.h
new file mode 100644
index 0000000000..a1cbf81b58
--- /dev/null
+++ b/ui/export_object_ui.h
@@ -0,0 +1,55 @@
+/* export_object_ui.h
+ * Common routines for tracking & saving objects found in streams of data
+ * Copyright 2007, Stephen Fisher (see AUTHORS file)
+ *
+ * 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_UI_H__
+#define __EXPORT_OBJECT_UI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <epan/export_object.h>
+
+/* Common between protocols */
+
+gboolean eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry, gboolean show_err);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EXPORT_OBJECT_UI_H__ */
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/gtk/export_object_dlg.c b/ui/gtk/export_object_dlg.c
index ee1c3af8b3..ba7ce9c136 100644
--- a/ui/gtk/export_object_dlg.c
+++ b/ui/gtk/export_object_dlg.c
@@ -32,7 +32,7 @@
#include <wsutil/str_util.h>
-#include <ui/export_object.h>
+#include <ui/export_object_ui.h>
#include <ui/simple_dialog.h>
#include "dlg_utils.h"
@@ -43,13 +43,6 @@
#include "stock_icons.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
-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);
-
enum {
EO_PKT_NUM_COLUMN,
EO_HOSTNAME_COLUMN,
@@ -59,22 +52,23 @@ enum {
EO_NUM_COLUMNS /* must be last */
};
-struct _export_object_list_t {
+typedef struct _export_object_list_gui_t {
GSList *entries;
GtkWidget *tree, *dlg;
GtkTreeView *tree_view;
GtkTreeIter *iter;
GtkTreeStore *store;
gint row_selected;
-};
+} export_object_list_gui_t;
-static eo_protocoldata_reset_cb eo_protocoldata_reset = NULL;
+static export_object_gui_reset_cb eo_protocoldata_reset = NULL;
static void
eo_remember_this_row(GtkTreeModel *model _U_, GtkTreePath *path,
GtkTreeIter *iter _U_, gpointer arg)
{
- export_object_list_t *object_list = (export_object_list_t *)arg;
+ export_object_list_t *tap_object = (export_object_list_t *)arg;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)tap_object->gui_data;
export_object_entry_t *entry;
gint *path_index;
@@ -102,23 +96,19 @@ eo_remember_row_num(GtkTreeSelection *sel, gpointer data)
static void
eo_win_destroy_cb(GtkWindow *win _U_, gpointer data)
{
- export_object_list_t *object_list = (export_object_list_t *)data;
+ export_object_list_t *tap_object = (export_object_list_t *)data;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)tap_object->gui_data;
export_object_entry_t *entry;
GSList *slist = object_list->entries;
- remove_tap_listener(object_list);
+ remove_tap_listener(tap_object);
/* Free the GSList attributes */
while(slist) {
entry = (export_object_entry_t *)slist->data;
-
- g_free(entry->hostname);
- g_free(entry->content_type);
- g_free(entry->filename);
- wmem_free(wmem_file_scope(), entry->payload_data);
+ eo_free_entry(entry);
slist = slist->next;
- wmem_free(wmem_file_scope(), entry);
}
/* Free the GSList elements */
@@ -130,7 +120,7 @@ eo_win_destroy_cb(GtkWindow *win _U_, gpointer data)
}
static char *
-gtk_eo_save_object_as_file(export_object_list_t *object_list, char *auxfilename)
+gtk_eo_save_object_as_file(export_object_list_gui_t *object_list, char *auxfilename)
{
GtkWidget *save_as_w;
char *pathname;
@@ -156,7 +146,8 @@ gtk_eo_save_object_as_file(export_object_list_t *object_list, char *auxfilename)
static void
eo_save_clicked_cb(GtkWidget *widget _U_, gpointer arg)
{
- export_object_list_t *object_list = (export_object_list_t *)arg;
+ export_object_list_t *tap_object = (export_object_list_t *)arg;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)tap_object->gui_data;
export_object_entry_t *entry;
GString *safe_filename = NULL;
char *pathname;
@@ -193,12 +184,12 @@ eo_save_clicked_cb(GtkWidget *widget _U_, gpointer arg)
g_string_free(safe_filename, TRUE);
}
-#define MAXFILELEN 255
static void
eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg)
{
gchar *save_as_fullpath = NULL;
- export_object_list_t *object_list = (export_object_list_t *)arg;
+ export_object_list_t *tap_object = (export_object_list_t *)arg;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)tap_object->gui_data;
export_object_entry_t *entry;
GtkWidget *save_in_w;
GSList *slist = object_list->entries;
@@ -216,21 +207,21 @@ eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg)
entry = (export_object_entry_t *)slist->data;
save_in_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(save_in_w));
- if ((strlen(save_in_path) < MAXFILELEN)) {
+ if ((strlen(save_in_path) < EXPORT_OBJECT_MAXFILELEN)) {
do {
g_free(save_as_fullpath);
if (entry->filename) {
safe_filename = eo_massage_str(entry->filename,
- MAXFILELEN - strlen(save_in_path), count);
+ EXPORT_OBJECT_MAXFILELEN - strlen(save_in_path), count);
} else {
- char generic_name[MAXFILELEN+1];
+ char generic_name[EXPORT_OBJECT_MAXFILELEN+1];
const char *ext;
- ext = ct2ext(entry->content_type);
+ ext = eo_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 - strlen(save_in_path), count);
+ EXPORT_OBJECT_MAXFILELEN - strlen(save_in_path), count);
}
save_as_fullpath = g_build_filename(
save_in_path, safe_filename->str, NULL);
@@ -260,7 +251,8 @@ eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg)
static void
eo_reset(void *tapdata)
{
- export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ export_object_list_t *tap_object = (export_object_list_t *)tapdata;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)tap_object->gui_data;
object_list->entries = NULL;
object_list->iter = NULL;
@@ -272,7 +264,8 @@ eo_reset(void *tapdata)
static void
eo_draw(void *tapdata)
{
- export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ export_object_list_t *tap_object = (export_object_list_t *)tapdata;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)tap_object->gui_data;
export_object_entry_t *eo_entry;
gchar *size_str;
@@ -305,17 +298,23 @@ eo_draw(void *tapdata)
}
}
-void object_list_add_entry(export_object_list_t *object_list, export_object_entry_t *entry)
+static void
+object_list_add_entry(void *gui_data, export_object_entry_t *entry)
{
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)gui_data;
+
object_list->entries = g_slist_append(object_list->entries, entry);
}
-export_object_entry_t *object_list_get_entry(export_object_list_t *object_list, int row) {
+static export_object_entry_t*
+object_list_get_entry(void *gui_data, int row) {
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)gui_data;
+
return (export_object_entry_t *)g_slist_nth_data(object_list->entries, row);
}
static void
-export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_packet, eo_protocoldata_reset_cb eo_protocoldata_resetfn)
+export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_packet, export_object_gui_reset_cb eo_protocoldata_resetfn)
{
GtkWidget *sw;
GtkCellRenderer *renderer;
@@ -323,17 +322,23 @@ export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_
GtkTreeSelection *selection;
GtkWidget *vbox, *bbox, *help_bt, *cancel_bt, *save_bt, *save_all_bt;
GString *error_msg;
- export_object_list_t *object_list;
+ export_object_list_t *tap_data;
+ export_object_list_gui_t *object_list;
gchar *window_title;
/* Initialize the pointer to the private data clearing function */
eo_protocoldata_reset = eo_protocoldata_resetfn;
/* Initialize our object list structure */
- object_list = g_new0(export_object_list_t,1);
+ tap_data = g_new0(export_object_list_t,1);
+ object_list = g_new0(export_object_list_gui_t,1);
+
+ tap_data->add_entry = object_list_add_entry;
+ tap_data->get_entry = object_list_get_entry;
+ tap_data->gui_data = (void*)object_list;
/* Data will be gathered via a tap callback */
- error_msg = register_tap_listener(tapname, object_list, NULL, 0,
+ error_msg = register_tap_listener(tapname, tap_data, NULL, 0,
eo_reset,
tap_packet,
eo_draw);
@@ -342,6 +347,7 @@ export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Can't register %s tap: %s\n", name, error_msg->str);
g_string_free(error_msg, TRUE);
+ g_free(tap_data);
g_free(object_list);
return;
}
@@ -425,7 +431,7 @@ export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_
gtk_container_add(GTK_CONTAINER(sw), object_list->tree);
selection = gtk_tree_view_get_selection(object_list->tree_view);
- g_signal_connect(selection, "changed", G_CALLBACK(eo_remember_row_num), object_list);
+ g_signal_connect(selection, "changed", G_CALLBACK(eo_remember_row_num), tap_data);
bbox = dlg_button_row_new(GTK_STOCK_HELP, WIRESHARK_STOCK_SAVE_ALL, GTK_STOCK_SAVE_AS, GTK_STOCK_CANCEL, NULL);
@@ -436,13 +442,12 @@ export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_
/* Save All button */
save_all_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_SAVE_ALL);
- g_signal_connect(save_all_bt, "clicked", G_CALLBACK(eo_save_all_clicked_cb),
- object_list);
+ g_signal_connect(save_all_bt, "clicked", G_CALLBACK(eo_save_all_clicked_cb), tap_data);
gtk_widget_set_tooltip_text(save_all_bt, "Save all listed objects with their displayed filenames.");
/* Save As button */
save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE_AS);
- g_signal_connect(save_bt, "clicked", G_CALLBACK(eo_save_clicked_cb), object_list);
+ g_signal_connect(save_bt, "clicked", G_CALLBACK(eo_save_clicked_cb), tap_data);
gtk_widget_set_tooltip_text(save_bt, "Saves the currently selected content to a file.");
/* Cancel button */
@@ -455,8 +460,7 @@ export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_
/* Setup cancel/delete/destroy signal handlers */
g_signal_connect(object_list->dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
- g_signal_connect(object_list->dlg, "destroy",
- G_CALLBACK(eo_win_destroy_cb), object_list);
+ g_signal_connect(object_list->dlg, "destroy", G_CALLBACK(eo_win_destroy_cb), tap_data);
window_set_cancel_button(object_list->dlg, cancel_bt,
window_cancel_button_cb);
@@ -467,30 +471,9 @@ export_object_window(const gchar *tapname, const gchar *name, tap_packet_cb tap_
cf_retap_packets(&cfile);
}
-void
-eo_dicom_cb(GtkWidget *widget _U_, gpointer data _U_)
-{
- export_object_window("dicom_eo", "DICOM", eo_dicom_packet, NULL);
-}
-
-void
-eo_http_cb(GtkWidget *widget _U_, gpointer data _U_)
-{
- export_object_window("http_eo", "HTTP", eo_http_packet, NULL);
-}
-
-void
-eo_smb_cb(GtkWidget *widget _U_, gpointer data _U_)
-{
- /* Call the export_object window */
- export_object_window("smb_eo", "SMB", eo_smb_packet, eo_smb_cleanup);
-}
-
-void
-eo_tftp_cb(GtkWidget *widget _U_, gpointer data _U_)
+void exportobject_cb(register_eo_t *eo)
{
- /* Call the export_object window */
- export_object_window("tftp_eo", "TFTP", eo_tftp_packet, eo_tftp_cleanup);
+ export_object_window(get_eo_tap_listener_name(eo), proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo))), get_eo_packet_func(eo), get_eo_reset_func(eo));
}
/*
diff --git a/ui/gtk/export_object_dlg.h b/ui/gtk/export_object_dlg.h
index 73fae69a34..72121df593 100644
--- a/ui/gtk/export_object_dlg.h
+++ b/ui/gtk/export_object_dlg.h
@@ -25,10 +25,8 @@
#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_);
-void eo_tftp_cb(GtkWidget *widget _U_, gpointer data _U_);
+#include <epan/export_object.h>
+
+void exportobject_cb(register_eo_t *eo);
#endif /* __EXPORT_OBJECT_DLG_H__ */
diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c
index 0b8aeacc60..907f65285d 100644
--- a/ui/gtk/main_menubar.c
+++ b/ui/gtk/main_menubar.c
@@ -34,6 +34,7 @@
#include <epan/column.h>
#include <epan/stats_tree_priv.h>
#include <epan/plugin_if.h>
+#include <epan/export_object.h>
#include "globals.h"
#include <epan/color_filters.h>
@@ -821,11 +822,8 @@ static const char *ui_desc_menubar =
" <menuitem name='ExportSelectedPacketBytes' action='/File/ExportSelectedPacketBytes'/>\n"
" <menuitem name='ExportPDUs' action='/File/ExportPDUs'/>\n"
" <menuitem name='ExportSSLSessionKeys' action='/File/ExportSSLSessionKeys'/>\n"
-" <menu name= 'ExportObjects' action='/File/ExportObjects'>\n"
-" <menuitem name='HTTP' action='/File/ExportObjects/HTTP'/>\n"
-" <menuitem name='DICOM' action='/File/ExportObjects/DICOM'/>\n"
-" <menuitem name='SMB' action='/File/ExportObjects/SMB'/>\n"
-" <menuitem name='TFTP' action='/File/ExportObjects/TFTP'/>\n"
+" <menu name= 'ExportObjectsMenu' action='/File/ExportObjects'>\n"
+" <placeholder name='ExportObjects'/>\n"
" </menu>\n"
" <separator/>\n"
" <menuitem name='Print' action='/File/Print'/>\n"
@@ -1280,10 +1278,6 @@ static const GtkActionEntry main_menu_bar_entries[] = {
NULL, NULL, G_CALLBACK(export_pdml_cmd_cb) },
{ "/File/ExportPacketDissections/JSON", NULL, "as \"_JSON\" file...",
NULL, NULL, G_CALLBACK(export_json_cmd_cb) },
- { "/File/ExportObjects/HTTP", NULL, "_HTTP", NULL, NULL, G_CALLBACK(eo_http_cb) },
- { "/File/ExportObjects/DICOM", NULL, "_DICOM", NULL, NULL, G_CALLBACK(eo_dicom_cb) },
- { "/File/ExportObjects/SMB", NULL, "_SMB/SMB2", NULL, NULL, G_CALLBACK(eo_smb_cb) },
- { "/File/ExportObjects/TFTP", NULL, "_TFTP", NULL, NULL, G_CALLBACK(eo_tftp_cb) },
{ "/Edit/Copy", NULL, "Copy", NULL, NULL, NULL },
@@ -2810,6 +2804,73 @@ menu_hostlist_list(capture_file *cf)
conversation_table_iterate_tables(add_hostlist_menuitem, &conv_data);
}
+typedef struct {
+ guint merge_id;
+ GtkActionGroup *action_group;
+ int counter;
+} eo_menu_t;
+
+static void
+menu_exportobject_cb(GtkAction *action _U_, gpointer user_data)
+{
+ register_eo_t *eo = (register_eo_t*)user_data;
+
+ exportobject_cb(eo);
+}
+
+static void
+add_export_object_menuitem(gpointer data, gpointer user_data)
+{
+ register_eo_t *eo = (register_eo_t*)data;
+ eo_menu_t *eo_menu_data = (eo_menu_t*)user_data;
+ gchar *action_name;
+ GtkAction *action;
+
+ action_name = g_strdup_printf ("exportobject-%u", eo_menu_data->counter);
+ /*g_warning("action_name %s, filter_entry->name %s",action_name,filter_entry->name);*/
+ action = (GtkAction *)g_object_new (GTK_TYPE_ACTION,
+ "name", action_name,
+ "label", proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo))),
+ "sensitive", TRUE,
+ NULL);
+ g_signal_connect (action, "activate",
+ G_CALLBACK (menu_exportobject_cb), eo);
+ gtk_action_group_add_action (eo_menu_data->action_group, action);
+ g_object_unref (action);
+
+ gtk_ui_manager_add_ui (ui_manager_main_menubar, eo_menu_data->merge_id,
+ "/Menubar/FileMenu/ExportObjectsMenu/ExportObjects",
+ action_name,
+ action_name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+ g_free(action_name);
+ eo_menu_data->counter++;
+}
+
+static void
+menu_export_object_list(void)
+{
+ GtkWidget *submenu_export_object;
+ eo_menu_t eo_data;
+
+ eo_data.merge_id = gtk_ui_manager_new_merge_id (ui_manager_main_menubar);
+
+ eo_data.action_group = gtk_action_group_new ("exportobject-list-group");
+
+ submenu_export_object = gtk_ui_manager_get_widget(ui_manager_main_menubar, "/Menubar/FileMenu/ExportObjects");
+ if(!submenu_export_object){
+ g_warning("menu_export_object_list: No submenu_exportobject_list found, path= /Menubar/FileMenu/ExportObjects");
+ }
+
+ gtk_ui_manager_insert_action_group (ui_manager_main_menubar, eo_data.action_group, 0);
+ g_object_set_data (G_OBJECT (ui_manager_main_menubar),
+ "exportobject-list-merge-id", GUINT_TO_POINTER (eo_data.merge_id));
+
+ eo_data.counter = 0;
+ eo_iterate_tables(add_export_object_menuitem, &eo_data);
+}
+
static void
menu_conversation_display_filter_cb(GtkAction *action _U_, gpointer data)
{
@@ -3253,6 +3314,7 @@ menus_init(void)
menu_dissector_filter(&cfile);
menu_conversation_list(&cfile);
menu_hostlist_list(&cfile);
+ menu_export_object_list();
/* Add additional entries which may have been introduced by dissectors and/or plugins */
ws_menubar_external_menus();
@@ -4396,7 +4458,7 @@ set_menus_for_capture_file(capture_file *cf)
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportPacketDissections", FALSE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportSelectedPacketBytes", FALSE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportSSLSessionKeys", FALSE);
- set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportObjects", FALSE);
+ set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportObjectsMenu", FALSE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportPDUs", FALSE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/Reload", FALSE);
} else {
@@ -4415,7 +4477,7 @@ set_menus_for_capture_file(capture_file *cf)
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportPacketDissections", TRUE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportSelectedPacketBytes", TRUE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportSSLSessionKeys", TRUE);
- set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportObjects", TRUE);
+ set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportObjectsMenu", TRUE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportPDUs", TRUE);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/Reload", TRUE);
}
@@ -4441,7 +4503,7 @@ set_menus_for_capture_in_progress(gboolean capture_in_progress)
capture_in_progress);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportSSLSessionKeys",
capture_in_progress);
- set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportObjects",
+ set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/ExportObjectsMenu",
capture_in_progress);
set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/FileMenu/Set",
!capture_in_progress);
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 3cd9d2e503..9899ad7477 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -60,6 +60,7 @@ set(WIRESHARK_QT_HEADERS
endpoint_dialog.h
expert_info_dialog.h
export_dissection_dialog.h
+ export_object_action.h
export_object_dialog.h
export_pdu_dialog.h
field_filter_edit.h
@@ -227,6 +228,7 @@ set(WIRESHARK_QT_SRC
enabled_protocols_dialog.cpp
endpoint_dialog.cpp
export_dissection_dialog.cpp
+ export_object_action.cpp
export_object_dialog.cpp
export_pdu_dialog.cpp
field_filter_edit.cpp
diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am
index f543f42c0a..bb83a45a6a 100644
--- a/ui/qt/Makefile.am
+++ b/ui/qt/Makefile.am
@@ -190,6 +190,7 @@ MOC_HDRS = \
endpoint_dialog.h \
expert_info_dialog.h \
export_dissection_dialog.h \
+ export_object_action.h \
export_object_dialog.h \
export_pdu_dialog.h \
field_filter_edit.h \
@@ -471,6 +472,7 @@ WIRESHARK_QT_SRC = \
enabled_protocols_dialog.cpp \
endpoint_dialog.cpp \
export_dissection_dialog.cpp \
+ export_object_action.cpp \
export_object_dialog.cpp \
export_pdu_dialog.cpp \
field_filter_edit.cpp \
diff --git a/ui/qt/export_object_action.cpp b/ui/qt/export_object_action.cpp
new file mode 100644
index 0000000000..7b9363ba72
--- /dev/null
+++ b/ui/qt/export_object_action.cpp
@@ -0,0 +1,65 @@
+/* conversation_colorize_action.cpp
+ *
+ * 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 <glib.h>
+#include <epan/packet_info.h>
+#include <epan/proto_data.h>
+#include <epan/packet.h>
+#include <wsutil/utf8_entities.h>
+#include "export_object_action.h"
+
+#include <QMenu>
+
+#include "qt_ui_utils.h"
+
+ExportObjectAction::ExportObjectAction(QObject *parent, register_eo_t *eo) :
+ QAction(parent),
+ eo_(eo)
+{
+ if (eo_) {
+ setText( QString("%1%2").arg(proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)))).arg(UTF8_HORIZONTAL_ELLIPSIS));
+ }
+}
+
+void ExportObjectAction::captureFileOpened()
+{
+ setEnabled(true);
+}
+
+void ExportObjectAction::captureFileClosed()
+{
+ setEnabled(false);
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/export_object_action.h b/ui/qt/export_object_action.h
new file mode 100644
index 0000000000..5328f24b31
--- /dev/null
+++ b/ui/qt/export_object_action.h
@@ -0,0 +1,64 @@
+/* export_object_action.h
+ *
+ * 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 EXPORTOBJECTACTION_H
+#define EXPORTOBJECTACTION_H
+
+#include "config.h"
+
+#include <glib.h>
+#include <epan/packet_info.h>
+#include <epan/export_object.h>
+
+#include <QAction>
+
+// Actions for "Export Objects" menu items.
+
+class ExportObjectAction : public QAction
+{
+ Q_OBJECT
+public:
+ ExportObjectAction(QObject *parent, register_eo_t *eo = NULL);
+
+ register_eo_t* exportObject() {return eo_;}
+
+public slots:
+ void captureFileOpened();
+ void captureFileClosed();
+
+private:
+ register_eo_t *eo_;
+};
+
+#endif // EXPORTOBJECTACTION_H
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/export_object_dialog.cpp b/ui/qt/export_object_dialog.cpp
index 29126334ca..8592332feb 100644
--- a/ui/qt/export_object_dialog.cpp
+++ b/ui/qt/export_object_dialog.cpp
@@ -28,6 +28,7 @@
#include <wsutil/filesystem.h>
#include <wsutil/str_util.h>
+#include "qt_ui_utils.h"
#include "wireshark_application.h"
#include <QDialogButtonBox>
@@ -37,14 +38,21 @@
extern "C" {
-// object_list_add_entry and object_list_get_entry are defined in ui/export_object.h
+static void
+object_list_add_entry(void *gui_data, export_object_entry_t *entry) {
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)gui_data;
-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);
+ 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);
+static export_object_entry_t*
+object_list_get_entry(void *gui_data, int row) {
+ export_object_list_gui_t *object_list = (export_object_list_gui_t*)gui_data;
+
+ if (object_list && object_list->eod)
+ return object_list->eod->objectEntry(row);
+
return NULL;
}
@@ -54,21 +62,94 @@ export_object_entry_t *object_list_get_entry(export_object_list_t *object_list,
static void
eo_reset(void *tapdata)
{
- export_object_list_t *object_list = (export_object_list_t *) tapdata;
+ export_object_list_t *tap_object = (export_object_list_t *)tapdata;
+ export_object_list_gui_t *object_list = (export_object_list_gui_t *)tap_object->gui_data;
if (object_list && object_list->eod) object_list->eod->resetObjects();
}
} // extern "C"
-ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, ObjectType object_type) :
+
+enum {
+ COL_PACKET,
+ COL_HOSTNAME,
+ COL_CONTENT_TYPE,
+ COL_SIZE,
+ COL_FILENAME
+};
+
+enum {
+ export_object_row_type_ = 1000
+};
+
+class ExportObjectTreeWidgetItem : public QTreeWidgetItem
+{
+public:
+ ExportObjectTreeWidgetItem(QTreeWidget *parent, export_object_entry_t *entry) :
+ QTreeWidgetItem (parent, export_object_row_type_),
+ entry_(entry)
+ {
+ // Not perfect but better than nothing.
+ setTextAlignment(COL_SIZE, Qt::AlignRight);
+ }
+ ~ExportObjectTreeWidgetItem() {
+ eo_free_entry(entry_);
+ }
+
+ export_object_entry_t *entry() { return entry_; }
+
+ virtual QVariant data(int column, int role) const {
+ if (!entry_ || role != Qt::DisplayRole) {
+ return QTreeWidgetItem::data(column, role);
+ }
+
+ switch (column) {
+ case COL_PACKET:
+ return QString::number(entry_->pkt_num);
+ case COL_HOSTNAME:
+ return entry_->hostname;
+ case COL_CONTENT_TYPE:
+ return entry_->content_type;
+ case COL_SIZE:
+ return file_size_to_qstring(entry_->payload_len);
+ case COL_FILENAME:
+ return entry_->filename;
+ default:
+ break;
+ }
+ return QTreeWidgetItem::data(column, role);
+ }
+
+ bool operator< (const QTreeWidgetItem &other) const
+ {
+ if (!entry_ || other.type() != export_object_row_type_) {
+ return QTreeWidgetItem::operator< (other);
+ }
+
+ const ExportObjectTreeWidgetItem *other_row = static_cast<const ExportObjectTreeWidgetItem *>(&other);
+
+ switch (treeWidget()->sortColumn()) {
+ case COL_PACKET:
+ return entry_->pkt_num < other_row->entry_->pkt_num;
+ case COL_SIZE:
+ return entry_->payload_len < other_row->entry_->payload_len;
+ default:
+ break;
+ }
+
+ return QTreeWidgetItem::operator< (other);
+ }
+
+private:
+ export_object_entry_t *entry_;
+};
+
+ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, register_eo_t* eo) :
WiresharkDialog(parent, cf),
eo_ui_(new Ui::ExportObjectDialog),
save_bt_(NULL),
save_all_bt_(NULL),
- tap_name_(NULL),
- name_(NULL),
- tap_packet_(NULL),
- eo_protocoldata_resetfn_(NULL)
+ eo_(eo)
{
QPushButton *close_bt;
@@ -80,42 +161,17 @@ ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, ObjectT
eo_ui_->progressBar->setAttribute(Qt::WA_MacSmallSize, true);
#endif
- export_object_list_.eod = this;
+ eo_gui_data_.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 Imf:
- tap_name_ = "imf_eo";
- name_ = "IMF";
- tap_packet_ = eo_imf_packet;
- break;
- case Smb:
- tap_name_ = "smb_eo";
- name_ = "SMB";
- tap_packet_ = eo_smb_packet;
- eo_protocoldata_resetfn_ = eo_smb_cleanup;
- break;
- case Tftp:
- tap_name_ = "tftp_eo";
- name_ = "TFTP";
- tap_packet_ = eo_tftp_packet;
- break;
- }
+ export_object_list_.add_entry = object_list_add_entry;
+ export_object_list_.get_entry = object_list_get_entry;
+ export_object_list_.gui_data = (void*)&eo_gui_data_;
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);
- setWindowTitle(wsApp->windowTitleString(QStringList() << tr("Export") << tr("%1 object list").arg(name_)));
+ setWindowTitle(wsApp->windowTitleString(QStringList() << tr("Export") << tr("%1 object list").arg(proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo))))));
if (save_bt_) save_bt_->setEnabled(false);
if (save_all_bt_) save_all_bt_->setEnabled(false);
@@ -131,46 +187,37 @@ ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, ObjectT
ExportObjectDialog::~ExportObjectDialog()
{
delete eo_ui_;
- export_object_list_.eod = NULL;
+ eo_gui_data_.eod = NULL;
removeTapListeners();
}
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(4, entry->filename);
- g_free(size_str);
- // Not perfect but better than nothing.
- entry_item->setTextAlignment(3, Qt::AlignRight);
+ new ExportObjectTreeWidgetItem(eo_ui_->objectTree, entry);
if (save_all_bt_) save_all_bt_->setEnabled(true);
}
export_object_entry_t *ExportObjectDialog::objectEntry(int row)
{
- QTreeWidgetItem *item = eo_ui_->objectTree->topLevelItem(row);
+ QTreeWidgetItem *cur_ti = eo_ui_->objectTree->topLevelItem(row);
+ ExportObjectTreeWidgetItem *eo_ti = dynamic_cast<ExportObjectTreeWidgetItem *>(cur_ti);
- if (item) return item->data(0, Qt::UserRole).value<export_object_entry_t *>();
+ if (eo_ti) {
+ return eo_ti->entry();
+ }
return NULL;
}
void ExportObjectDialog::resetObjects()
{
- if (eo_protocoldata_resetfn_) eo_protocoldata_resetfn_();
+ export_object_gui_reset_cb reset_cb = get_eo_reset_func(eo_);
+ if (reset_cb)
+ reset_cb();
+
if (save_bt_) save_bt_->setEnabled(false);
if (save_all_bt_) save_all_bt_->setEnabled(false);
}
@@ -178,9 +225,9 @@ void ExportObjectDialog::resetObjects()
void ExportObjectDialog::show()
{
/* Data will be gathered via a tap callback */
- if (!registerTapListener(tap_name_, &export_object_list_, NULL, 0,
+ if (!registerTapListener(get_eo_tap_listener_name(eo_), &export_object_list_, NULL, 0,
eo_reset,
- tap_packet_,
+ get_eo_packet_func(eo_),
NULL)) {
return;
}
@@ -191,6 +238,8 @@ void ExportObjectDialog::show()
for (int i = 0; i < eo_ui_->objectTree->columnCount(); i++)
eo_ui_->objectTree->resizeColumnToContents(i);
+ eo_ui_->objectTree->setSortingEnabled(true);
+ eo_ui_->objectTree->sortByColumn(COL_PACKET, Qt::AscendingOrder);
}
void ExportObjectDialog::accept()
@@ -217,7 +266,13 @@ void ExportObjectDialog::on_objectTree_currentItemChanged(QTreeWidgetItem *item,
if (save_bt_) save_bt_->setEnabled(true);
- export_object_entry_t *entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>();
+ ExportObjectTreeWidgetItem *eo_ti = dynamic_cast<ExportObjectTreeWidgetItem *>(item);
+
+ if (!eo_ti) {
+ return;
+ }
+
+ export_object_entry_t *entry = eo_ti->entry();
if (entry && !file_closed_) {
cf_goto_frame(cap_file_.capFile(), entry->pkt_num);
}
@@ -244,10 +299,15 @@ void ExportObjectDialog::saveCurrentEntry()
QDir path(wsApp->lastOpenDir());
QString file_name;
- if (!item) return;
+ ExportObjectTreeWidgetItem *eo_ti = dynamic_cast<ExportObjectTreeWidgetItem *>(item);
+ if (!eo_ti) {
+ return;
+ }
- entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>();
- if (!entry) return;
+ entry = eo_ti->entry();
+ if (!entry) {
+ return;
+ }
file_name = QFileDialog::getSaveFileName(this, wsApp->windowTitleString(tr("Save Object As" UTF8_HORIZONTAL_ELLIPSIS)),
path.filePath(entry->filename));
@@ -257,7 +317,6 @@ void ExportObjectDialog::saveCurrentEntry()
}
}
-#define MAXFILELEN 255
void ExportObjectDialog::saveAllEntries()
{
int i;
@@ -280,13 +339,17 @@ void ExportObjectDialog::saveAllEntries()
save_in_dir.canonicalPath(),
QFileDialog::ShowDirsOnly);
- if (save_in_path.length() < 1 || save_in_path.length() > MAXFILELEN) return;
+ if (save_in_path.length() < 1 || save_in_path.length() > EXPORT_OBJECT_MAXFILELEN) return;
for (i = 0; (item = eo_ui_->objectTree->topLevelItem(i)) != NULL; i++) {
int count = 0;
gchar *save_as_fullpath = NULL;
- export_object_entry_t *entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>();
+ ExportObjectTreeWidgetItem *eo_ti = dynamic_cast<ExportObjectTreeWidgetItem *>(item);
+ if (!eo_ti) {
+ continue;
+ }
+ export_object_entry_t *entry = eo_ti->entry();
if (!entry) continue;
do {
@@ -295,16 +358,16 @@ void ExportObjectDialog::saveAllEntries()
g_free(save_as_fullpath);
if (entry->filename)
safe_filename = eo_massage_str(entry->filename,
- MAXFILELEN - save_in_path.length(), count);
+ EXPORT_OBJECT_MAXFILELEN - save_in_path.length(), count);
else {
char generic_name[256];
const char *ext;
- ext = ct2ext(entry->content_type);
+ ext = eo_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 - save_in_path.length(), count);
+ EXPORT_OBJECT_MAXFILELEN - save_in_path.length(), count);
}
save_as_fullpath = g_build_filename(save_in_path.toUtf8().constData(),
safe_filename->str, NULL);
diff --git a/ui/qt/export_object_dialog.h b/ui/qt/export_object_dialog.h
index 9084017a80..e400a128b8 100644
--- a/ui/qt/export_object_dialog.h
+++ b/ui/qt/export_object_dialog.h
@@ -31,25 +31,22 @@
#include <epan/packet_info.h>
#include <epan/prefs.h>
#include <epan/tap.h>
+#include <epan/export_object.h>
-#include <ui/export_object.h>
+#include <ui/export_object_ui.h>
#include "wireshark_dialog.h"
-#include <QMetaType>
-
class QTreeWidgetItem;
class QAbstractButton;
-Q_DECLARE_METATYPE(export_object_entry_t *)
-
namespace Ui {
class ExportObjectDialog;
}
-struct _export_object_list_t {
+typedef struct _export_object_list_gui_t {
class ExportObjectDialog *eod;
-};
+} export_object_list_gui_t;
class ExportObjectDialog : public WiresharkDialog
@@ -57,9 +54,7 @@ class ExportObjectDialog : public WiresharkDialog
Q_OBJECT
public:
- enum ObjectType { Dicom, Http, Imf, Smb, Tftp };
-
- explicit ExportObjectDialog(QWidget &parent, CaptureFile &cf, ObjectType object_type);
+ explicit ExportObjectDialog(QWidget &parent, CaptureFile &cf, register_eo_t* eo);
~ExportObjectDialog();
@@ -81,23 +76,14 @@ 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_;
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_;
+ export_object_list_gui_t eo_gui_data_;
+ register_eo_t* eo_;
};
#endif // EXPORT_OBJECT_DIALOG_H
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 169fb943f4..8ed0f6a087 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -30,6 +30,7 @@
#include <epan/prefs.h>
#include <epan/stats_tree_priv.h>
#include <epan/plugin_if.h>
+#include <epan/export_object.h>
#include "ui/commandline.h"
@@ -54,6 +55,7 @@
#include "capture_interfaces_dialog.h"
#endif
#include "conversation_colorize_action.h"
+#include "export_object_action.h"
#include "display_filter_edit.h"
#include "export_dissection_dialog.h"
#include "file_set_dialog.h"
@@ -347,6 +349,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addDynamicMenus()));
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addExternalMenus()));
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(initConversationMenus()));
+ connect(wsApp, SIGNAL(appInitialized()), this, SLOT(initExportObjectsMenus()));
connect(wsApp, SIGNAL(profileChanging()), this, SLOT(saveWindowGeometry()));
connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(layoutPanes()));
@@ -1927,6 +1930,27 @@ void MainWindow::initConversationMenus()
connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered()));
}
+void MainWindow::addExportObjectsMenuItem(gpointer data, gpointer user_data)
+{
+ register_eo_t *eo = (register_eo_t*)data;
+ MainWindow *window = (MainWindow*)user_data;
+
+ ExportObjectAction *export_action = new ExportObjectAction(window->main_ui_->menuFileExportObjects, eo);
+ window->main_ui_->menuFileExportObjects->addAction(export_action);
+
+ //initially disable until a file is loaded (then file signals will take over)
+ export_action->setEnabled(false);
+
+ connect(&window->capture_file_, SIGNAL(captureFileOpened()), export_action, SLOT(captureFileOpened()));
+ connect(&window->capture_file_, SIGNAL(captureFileClosed()), export_action, SLOT(captureFileClosed()));
+ connect(export_action, SIGNAL(triggered()), window, SLOT(applyExportObject()));
+}
+
+void MainWindow::initExportObjectsMenus()
+{
+ eo_iterate_tables(addExportObjectsMenuItem, this);
+}
+
// Titlebar
void MainWindow::setTitlebarForCaptureFile()
{
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 5320fc7f13..cda9116ebb 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -292,6 +292,8 @@ private slots:
void initViewColorizeMenu();
void initConversationMenus();
+ static void addExportObjectsMenuItem(gpointer data, gpointer user_data);
+ void initExportObjectsMenus();
// in main_window_slots.cpp
/**
@@ -387,11 +389,6 @@ private slots:
void on_actionFileExportAsPDML_triggered();
void on_actionFileExportAsJSON_triggered();
void on_actionFileExportPacketBytes_triggered();
- void on_actionFileExportObjectsDICOM_triggered();
- void on_actionFileExportObjectsHTTP_triggered();
- void on_actionFileExportObjectsIMF_triggered();
- void on_actionFileExportObjectsSMB_triggered();
- void on_actionFileExportObjectsTFTP_triggered();
void on_actionFilePrint_triggered();
void on_actionFileExportPDU_triggered();
@@ -489,6 +486,7 @@ private slots:
void on_actionAnalyzePAFOrNotSelected_triggered();
void applyConversationFilter();
+ void applyExportObject();
void on_actionAnalyzeEnabledProtocols_triggered();
void on_actionAnalyzeDecodeAs_triggered();
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 7c4085d6af..a72b241d7e 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -178,11 +178,6 @@
<property name="title">
<string>Export Objects</string>
</property>
- <addaction name="actionFileExportObjectsDICOM"/>
- <addaction name="actionFileExportObjectsHTTP"/>
- <addaction name="actionFileExportObjectsIMF"/>
- <addaction name="actionFileExportObjectsSMB"/>
- <addaction name="actionFileExportObjectsTFTP"/>
</widget>
<addaction name="actionFileOpen"/>
<addaction name="menuOpenRecentCaptureFile"/>
@@ -1245,26 +1240,6 @@
<string>As JSON…</string>
</property>
</action>
- <action name="actionFileExportObjectsHTTP">
- <property name="text">
- <string>&amp;HTTP…</string>
- </property>
- </action>
- <action name="actionFileExportObjectsIMF">
- <property name="text">
- <string>&amp;IMF…</string>
- </property>
- </action>
- <action name="actionFileExportObjectsDICOM">
- <property name="text">
- <string>&amp;DICOM…</string>
- </property>
- </action>
- <action name="actionFileExportObjectsSMB">
- <property name="text">
- <string>&amp;SMB…</string>
- </property>
- </action>
<action name="actionEditCopyDescription">
<property name="text">
<string>Description</string>
@@ -2076,11 +2051,6 @@
<string>Show or hide the display filter toolbar</string>
</property>
</action>
- <action name="actionFileExportObjectsTFTP">
- <property name="text">
- <string>&amp;TFTP</string>
- </property>
- </action>
<action name="actionStatisticsConversations">
<property name="text">
<string>Conversations</string>
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index 1b2ac37c11..dfdc8ac433 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -43,6 +43,7 @@
#include "ui/commandline.h"
#include "epan/color_filters.h"
+#include "epan/export_object.h"
#include "wsutil/file_util.h"
#include "wsutil/filesystem.h"
@@ -102,6 +103,7 @@
#include "dissector_tables_dialog.h"
#include "endpoint_dialog.h"
#include "expert_info_dialog.h"
+#include "export_object_action.h"
#include "export_object_dialog.h"
#include "export_pdu_dialog.h"
#ifdef HAVE_EXTCAP
@@ -1863,36 +1865,11 @@ void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
}
}
-void MainWindow::on_actionFileExportObjectsDICOM_triggered()
-{
- new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Dicom);
-}
-
void MainWindow::on_actionStatisticsHpfeeds_triggered()
{
openStatisticsTreeDialog("hpfeeds");
}
-void MainWindow::on_actionFileExportObjectsHTTP_triggered()
-{
- new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Http);
-}
-
-void MainWindow::on_actionFileExportObjectsIMF_triggered()
-{
- new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Imf);
-}
-
-void MainWindow::on_actionFileExportObjectsSMB_triggered()
-{
- new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Smb);
-}
-
-void MainWindow::on_actionFileExportObjectsTFTP_triggered()
-{
- new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Tftp);
-}
-
void MainWindow::on_actionFilePrint_triggered()
{
PrintDialog pdlg(this, capture_file_.capFile());
@@ -2645,6 +2622,15 @@ void MainWindow::applyConversationFilter()
}
}
+void MainWindow::applyExportObject()
+{
+ ExportObjectAction *export_action = qobject_cast<ExportObjectAction*>(sender());
+ if (!export_action)
+ return;
+
+ new ExportObjectDialog(*this, capture_file_, export_action->exportObject());
+}
+
// XXX We could probably create the analyze and prepare actions
// dynamically using FilterActions and consolidate the methods
// below into one callback.