diff options
author | Ulf Lamping <ulf.lamping@web.de> | 2004-06-21 16:45:07 +0000 |
---|---|---|
committer | Ulf Lamping <ulf.lamping@web.de> | 2004-06-21 16:45:07 +0000 |
commit | 5c061e582e8ac9f0e744cb0981f942197a925613 (patch) | |
tree | 1217e77a29ba40b20811eef4de8c737b5e82f50a | |
parent | c10d97d8e351193db5af5c9f2a79faae03a48a6a (diff) | |
download | wireshark-5c061e582e8ac9f0e744cb0981f942197a925613.tar.gz wireshark-5c061e582e8ac9f0e744cb0981f942197a925613.tar.bz2 wireshark-5c061e582e8ac9f0e744cb0981f942197a925613.zip |
if more than one file is (drag and) dropped into the program,
merge them together into a new temporary file
(and notice the user by a simple_dialog about it)
svn path=/trunk/; revision=11205
-rw-r--r-- | gtk/file_dlg.c | 19 | ||||
-rw-r--r-- | gtk/main.c | 240 | ||||
-rw-r--r-- | merge.c | 14 | ||||
-rw-r--r-- | merge.h | 10 |
4 files changed, 193 insertions, 90 deletions
diff --git a/gtk/file_dlg.c b/gtk/file_dlg.c index 28d0f42ba8..ca384e717c 100644 --- a/gtk/file_dlg.c +++ b/gtk/file_dlg.c @@ -1,7 +1,7 @@ /* file_dlg.c * Dialog boxes for handling files * - * $Id: file_dlg.c,v 1.120 2004/06/21 05:48:15 ulfl Exp $ + * $Id: file_dlg.c,v 1.121 2004/06/21 16:45:07 ulfl Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -56,6 +56,7 @@ #include "capture_dlg.h" #include "range_utils.h" #endif +#include "merge.h" static void file_open_ok_cb(GtkWidget *w, gpointer fs); @@ -921,9 +922,6 @@ file_merge_cmd_cb(GtkWidget *widget, gpointer data _U_) { } -extern gboolean -merge_two_files(char *out_filename, char *in_file0, char *in_file1, gboolean append, int *err); - static void file_merge_ok_cb(GtkWidget *w, gpointer fs) { gchar *cf_name, *rfilter, *s; @@ -932,6 +930,7 @@ file_merge_ok_cb(GtkWidget *w, gpointer fs) { dfilter_t *rfcode = NULL; int err; gboolean merge_ok; + char *in_filenames[2]; #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs))); @@ -964,15 +963,21 @@ file_merge_ok_cb(GtkWidget *w, gpointer fs) { rb = OBJECT_GET_DATA(w, E_MERGE_CHRONO_KEY); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) { /* chonological order */ - merge_ok = merge_two_files(cf_merged_name, cfile.filename, cf_name, FALSE, &err); + in_filenames[0] = cfile.filename; + in_filenames[1] = cf_name; + merge_ok = merge_n_files(cf_merged_name, 2, in_filenames, FALSE, &err); } else { rb = OBJECT_GET_DATA(w, E_MERGE_PREPEND_KEY); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) { /* prepend file */ - merge_ok = merge_two_files(cf_merged_name, cfile.filename, cf_name, TRUE, &err); + in_filenames[0] = cfile.filename; + in_filenames[1] = cf_name; + merge_ok = merge_n_files(cf_merged_name, 2, in_filenames, TRUE, &err); } else { /* append file */ - merge_ok = merge_two_files(cf_merged_name, cf_name, cfile.filename, TRUE, &err); + in_filenames[0] = cf_name; + in_filenames[1] = cfile.filename; + merge_ok = merge_n_files(cf_merged_name, 2, in_filenames, TRUE, &err); } } diff --git a/gtk/main.c b/gtk/main.c index 7ec18601f9..30b88bcb3d 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1,6 +1,6 @@ /* main.c * - * $Id: main.c,v 1.445 2004/06/20 15:57:11 ulfl Exp $ + * $Id: main.c,v 1.446 2004/06/21 16:45:07 ulfl Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -131,6 +131,7 @@ #include "recent.h" #include "follow_dlg.h" #include "font_utils.h" +#include "merge.h" /* @@ -1209,43 +1210,7 @@ register_ethereal_tap(char *cmd, void (*func)(char *arg)) enum { DND_TARGET_STRING, DND_TARGET_ROOTWIN, DND_TARGET_URL }; -void -dnd_open_file_cmd(gpointer cf_name) -{ - int err; - - - /* open and read the capture file (this will close an existing file) */ - if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) { - cf_read(&cfile); - add_menu_recent_capture_file(cf_name); - } else { - /* the capture file couldn't be read (doesn't exist, file format unknown, ...) */ - } - - g_free(cf_name); -} - -static void -dnd_open_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_) -{ - switch(btn) { - case(ESD_BTN_YES): - /* save file first */ - file_save_as_cmd(after_save_open_dnd_file, data); - break; - case(ESD_BTN_NO): - cf_close(&cfile); - dnd_open_file_cmd(data); - break; - case(ESD_BTN_CANCEL): - g_free(data); - break; - default: - g_assert_not_reached(); - } -} - +/* convert drag and drop URI to a local filename */ static gchar * dnd_uri2filename(gchar *cf_name) { @@ -1268,13 +1233,13 @@ dnd_uri2filename(gchar *cf_name) * we have to remove the file: to get a valid filename. */ if (strncmp("file:////", cf_name, 9) == 0) { - /* now becoming: //servername/sharename/dir1/dir2/capture-file.cap */ + /* win32 UNC: now becoming: //servername/sharename/dir1/dir2/capture-file.cap */ cf_name += 7; } else if (strncmp("file:///", cf_name, 8) == 0) { - /* now becoming: d:/dir1/dir2/capture-file.cap */ + /* win32 local: now becoming: d:/dir1/dir2/capture-file.cap */ cf_name += 8; } else if (strncmp("file:", cf_name, 5) == 0) { - /* now becoming: /dir1/dir2/capture-file.cap */ + /* unix local: now becoming: /dir1/dir2/capture-file.cap */ cf_name += 5; } @@ -1326,39 +1291,181 @@ dnd_uri2filename(gchar *cf_name) return cf_name; } -static void -dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_, -GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_) +static void +dnd_merge_files(int in_file_count, char **in_filenames) +{ + gchar *cf_merged_name; + gboolean merge_ok; + int err; + + + /*XXX should use temp file stuff in util routines? */ + cf_merged_name = g_strdup(tmpnam(NULL)); + + /* merge the files in chonological order */ + merge_ok = merge_n_files(cf_merged_name, in_file_count, in_filenames, FALSE, &err); + + if(!merge_ok) { + /* merge failed */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "An error occurred while merging the files: \"%s\".", + wtap_strerror(err)); + g_free(cf_merged_name); + return; + } + + cf_close(&cfile); + + /* Try to open the merged capture file. */ + if ((err = cf_open(cf_merged_name, TRUE /* temporary file */, &cfile)) != 0) { + /* We couldn't open it; don't dismiss the open dialog box, + just leave it around so that the user can, after they + dismiss the alert box popped up for the open error, + try again. */ + g_free(cf_merged_name); + return; + } + + switch (cf_read(&cfile)) { + + case READ_SUCCESS: + case READ_ERROR: + /* Just because we got an error, that doesn't mean we were unable + to read any of the file; we handle what we could get from the + file. */ + break; + + case READ_ABORTED: + /* The user bailed out of re-reading the capture file; the + capture file has been closed - just free the capture file name + string and return (without changing the last containing + directory). */ + g_free(cf_merged_name); + return; + } + + gtk_widget_grab_focus(packet_list); + + g_free(cf_merged_name); +} + +/* open/merge the dnd file */ +void +dnd_open_file_cmd(GtkSelectionData *selection_data) { - gchar *cf_name, *cf_name_ori; + int err; + gchar *cf_name, *cf_name_freeme; + int in_files; gpointer dialog; + GString *dialog_text; + int files_work; + char **in_filenames; - if (info == DND_TARGET_URL) { - /* DND_TARGET_URL on Win32: - * The selection_data->data is a single string, containing one or more URI's, - * seperated by CR/NL chars. The length of the whole field can be found - * in the selection_data->length field. As we can't handle more than one - * capture file at a time, we only try to load the first one. */ + + /* DND_TARGET_URL on Win32: + * The selection_data->data is a single string, containing one or more URI's, + * seperated by CR/NL chars. The length of the whole field can be found + * in the selection_data->length field. If it contains one file, simply open it, + * If it contains more than one file, ask to merge these files. */ + + /* the data string is not zero terminated -> make a zero terminated "copy" of it */ + cf_name_freeme = g_malloc(selection_data->length + 1); + memcpy(cf_name_freeme, selection_data->data, selection_data->length); + cf_name_freeme[selection_data->length] = '\0'; + + /* count the number of input files */ + cf_name = cf_name_freeme; + for(in_files = 0; (cf_name = strstr(cf_name, "\r\n")) != NULL; ) { + cf_name += 2; + in_files++; + } - /* XXX: how does this string look like on other platforms? */ + in_filenames = g_malloc(sizeof(char*) * in_files); - /* XXX: if more than one file is in the string, we might want to have - * a dialog box asking to merge these files together? */ + /* store the starts of the file entries in a gchar array */ + cf_name = cf_name_freeme; + in_filenames[0] = cf_name; + for(files_work = 1; (cf_name = strstr(cf_name, "\r\n")) != NULL && files_work < in_files; ) { + cf_name += 2; + in_filenames[files_work] = cf_name; + files_work++; + } + + /* replace trailing CR NL simply with zeroes (in place), so we get valid terminated strings */ + cf_name = cf_name_freeme; + g_strdelimit(cf_name, "\r\n", '\0'); + + /* convert all filenames from URI to local filename (in place) */ + for(files_work = 0; files_work < in_files; files_work++) { + in_filenames[files_work] = dnd_uri2filename(in_filenames[files_work]); + } - /* the name might not be zero terminated -> make a copy of it */ - cf_name_ori = g_strndup((gchar *)selection_data->data, selection_data->length); - cf_name = cf_name_ori; + switch(in_files) { + case(0): + /* shouldn't happen */ + break; + case(1): + /* open and read the capture file (this will close an existing file) */ + if ((err = cf_open(in_filenames[0], FALSE, &cfile)) == 0) { + cf_read(&cfile); + add_menu_recent_capture_file(in_filenames[0]); + } else { + /* the capture file couldn't be read (doesn't exist, file format unknown, ...) */ + } + break; + default: + /* build and show the info dialog */ + dialog_text = g_string_sized_new(200); + g_string_append(dialog_text, PRIMARY_TEXT_START + "Merging the following files:" PRIMARY_TEXT_END "\n\n"); + for(files_work = 0; files_work < in_files; files_work++) { + g_string_append(dialog_text, in_filenames[files_work]); + g_string_append(dialog_text, "\n"); + } + g_string_append(dialog_text, "\nThe packets in these files will be merged chronologically into a new temporary file."); + dialog = simple_dialog(ESD_TYPE_CONFIRMATION, + ESD_BTN_OK, + dialog_text->str); + g_string_free(dialog_text, TRUE); + + /* actually merge the files now */ + dnd_merge_files(in_files, in_filenames); + } + + g_free(in_filenames); + g_free(cf_name_freeme); +} - /* replace trailing CR NL simply with zeroes */ - g_strdelimit(cf_name, "\r\n", '\0'); +/* ask the user to save current unsaved file, before opening the dnd file */ +static void +dnd_save_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_) +{ + switch(btn) { + case(ESD_BTN_YES): + /* save file first */ + file_save_as_cmd(after_save_open_dnd_file, data); + break; + case(ESD_BTN_NO): + cf_close(&cfile); + dnd_open_file_cmd(data); + break; + case(ESD_BTN_CANCEL): + break; + default: + g_assert_not_reached(); + } +} - /* convert the URI to a local filename */ - cf_name = dnd_uri2filename(cf_name); - /* we need a clean name for later call to g_free() */ - cf_name = strdup(cf_name); - g_free(cf_name_ori); +/* we have received some drag and drop data */ +/* (as we only registered to "text/uri-list", we will only get a file list here) */ +static void +dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_, +GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_) +{ + gpointer dialog; + if (info == DND_TARGET_URL) { /* ask the user to save it's current capture file first */ if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) { /* user didn't saved his current file, ask him */ @@ -1366,14 +1473,15 @@ GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_) ESD_BTNS_YES_NO_CANCEL, PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n" "If you open a new capture file without saving, your current capture data will be discarded."); - simple_dialog_set_cb(dialog, dnd_open_file_answered_cb, cf_name); + simple_dialog_set_cb(dialog, dnd_save_file_answered_cb, selection_data); } else { /* unchanged file */ - dnd_open_file_cmd(cf_name); + dnd_open_file_cmd(selection_data); } } } +/* init the drag and drop functionality */ static void dnd_init(GtkWidget *w) { @@ -1,6 +1,6 @@ /* Combine two dump files, either by appending or by merging by timestamp * - * $Id: merge.c,v 1.4 2004/06/18 12:04:49 jmayer Exp $ + * $Id: merge.c,v 1.5 2004/06/21 16:45:06 ulfl Exp $ * * Written by Scott Renfro <scott@renfro.org> based on * editcap by Richard Sharpe and Guy Harris @@ -379,12 +379,10 @@ merge_open_in_files(int in_file_count, char *in_file_names[], merge_in_file_t *i * Convenience function: merge two files into one. */ gboolean -merge_two_files(char *out_filename, char *in_file0, char *in_file1, gboolean do_append, int *err) +merge_n_files(char *out_filename, int in_file_count, char **in_filenames, gboolean do_append, int *err) { extern char *optarg; extern int optind; - int in_file_count = 0; - char *in_filenames[2]; merge_in_file_t *in_files = NULL; merge_out_file_t out_file; gboolean ret; @@ -397,14 +395,6 @@ merge_two_files(char *out_filename, char *in_file0, char *in_file1, gboolean do_ out_file.snaplen = 0; /* no limit */ out_file.count = 1; /* frames output */ - /* check for proper args; at a minimum, must have an output - * filename and one input file - */ - in_file_count = 2; - - in_filenames[0] = in_file0; - in_filenames[1] = in_file1; - /* open the input files */ in_file_count = merge_open_in_files(in_file_count, in_filenames, &in_files, err); if (in_file_count < 2) { @@ -2,7 +2,7 @@ * Definitions for menu routines with toolkit-independent APIs but * toolkit-dependent implementations. * - * $Id: merge.h,v 1.2 2004/06/18 12:04:49 jmayer Exp $ + * $Id: merge.h,v 1.3 2004/06/21 16:45:06 ulfl Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -142,17 +142,17 @@ merge_append_files(int in_file_count, merge_in_file_t in_files[], merge_out_file /* - * Convenience function: merge two files into one. + * Convenience function: merge any number of input files into one. * * @param out_filename the output filename - * @param in_file0 first input filename - * @param in_file1 second input filename + * @param in_file_count number of input files + * @param in_filenames array of input filenames * @param do_append TRUE to append, FALSE to merge chronologically * @param err wiretap error, if failed * @return TRUE if function succeeded */ extern gboolean -merge_two_files(char *out_filename, char *in_file0, char *in_file1, gboolean do_append, int *err); +merge_n_files(char *out_filename, int in_file_count, char **in_filenames, gboolean do_append, int *err); #ifdef __cplusplus |