rename kill_capture_child to capture_kill_child to have a common prefix
split drag and drop support out of main.c into new file drag_and_drop.c, to reduce the size of main.c a bit. Hopefully this won't break unix builds because of missing #include's, I will keep an eye on the buildbot svn path=/trunk/; revision=13308
This commit is contained in:
parent
244c060b45
commit
a1a2ae3180
|
@ -316,7 +316,7 @@ capture_stop(capture_options *capture_opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
kill_capture_child(capture_options *capture_opts)
|
capture_kill_child(capture_options *capture_opts)
|
||||||
{
|
{
|
||||||
if (capture_opts->sync_mode) {
|
if (capture_opts->sync_mode) {
|
||||||
sync_pipe_kill(capture_opts);
|
sync_pipe_kill(capture_opts);
|
||||||
|
|
|
@ -102,7 +102,7 @@ extern int capture_start(capture_options *capture_opts, gboolean *stats_known,
|
||||||
extern void capture_stop(capture_options *capture_opts);
|
extern void capture_stop(capture_options *capture_opts);
|
||||||
|
|
||||||
/** Terminate the capture child cleanly when exiting. */
|
/** Terminate the capture child cleanly when exiting. */
|
||||||
extern void kill_capture_child(capture_options *capture_opts);
|
extern void capture_kill_child(capture_options *capture_opts);
|
||||||
|
|
||||||
/** Do the low-level work of a capture. */
|
/** Do the low-level work of a capture. */
|
||||||
extern int capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats);
|
extern int capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats);
|
||||||
|
|
|
@ -642,7 +642,7 @@ sync_pipe_input_cb(gint source, gpointer user_data)
|
||||||
case CF_READ_ABORTED:
|
case CF_READ_ABORTED:
|
||||||
/* Kill the child capture process; the user wants to exit, and we
|
/* Kill the child capture process; the user wants to exit, and we
|
||||||
shouldn't just leave it running. */
|
shouldn't just leave it running. */
|
||||||
kill_capture_child(capture_opts);
|
capture_kill_child(capture_opts);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ ETHEREAL_GTK_SRC = \
|
||||||
decode_as_dcerpc.c \
|
decode_as_dcerpc.c \
|
||||||
dfilter_expr_dlg.c \
|
dfilter_expr_dlg.c \
|
||||||
dlg_utils.c \
|
dlg_utils.c \
|
||||||
|
drag_and_drop.c \
|
||||||
ethereal-tap-register.c \
|
ethereal-tap-register.c \
|
||||||
file_dlg.c \
|
file_dlg.c \
|
||||||
filter_dlg.c \
|
filter_dlg.c \
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
/* dnd.c
|
||||||
|
* Drag and Drop
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_IO_H
|
||||||
|
#include <io.h> /* open/close on win32 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
#include "gtkglobals.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "file_dlg.h"
|
||||||
|
#include "../menu.h"
|
||||||
|
#include "compat_macros.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include "simple_dialog.h"
|
||||||
|
#include <epan/prefs.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
enum { DND_TARGET_STRING, DND_TARGET_ROOTWIN, DND_TARGET_URL };
|
||||||
|
|
||||||
|
/* convert drag and drop URI to a local filename */
|
||||||
|
static gchar *
|
||||||
|
dnd_uri2filename(gchar *cf_name)
|
||||||
|
{
|
||||||
|
gchar *src, *dest;
|
||||||
|
gint ret;
|
||||||
|
guint i;
|
||||||
|
gchar esc[3];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove URI header.
|
||||||
|
* On win32 (at least WinXP), this string looks like (UNC or local filename):
|
||||||
|
* file:////servername/sharename/dir1/dir2/capture-file.cap
|
||||||
|
* or
|
||||||
|
* file:///d:/dir1/dir2/capture-file.cap
|
||||||
|
* we have to remove the prefix to get a valid filename.
|
||||||
|
*
|
||||||
|
* On UNIX (at least KDE 3.0 Konqueror), this string looks like:
|
||||||
|
* file:/dir1/dir2/capture-file.cap
|
||||||
|
* we have to remove the file: to get a valid filename.
|
||||||
|
*/
|
||||||
|
if (strncmp("file:////", cf_name, 9) == 0) {
|
||||||
|
/* win32 UNC: now becoming: //servername/sharename/dir1/dir2/capture-file.cap */
|
||||||
|
cf_name += 7;
|
||||||
|
} else if (strncmp("file:///", cf_name, 8) == 0) {
|
||||||
|
/* win32 local: now becoming: d:/dir1/dir2/capture-file.cap */
|
||||||
|
cf_name += 8;
|
||||||
|
} else if (strncmp("file:", cf_name, 5) == 0) {
|
||||||
|
/* unix local: now becoming: /dir1/dir2/capture-file.cap */
|
||||||
|
cf_name += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unescape the escaped URI characters (spaces, ...)
|
||||||
|
*
|
||||||
|
* we have to replace escaped chars to their equivalents,
|
||||||
|
* e.g. %20 (always a two digit hexstring) -> ' '
|
||||||
|
* the percent character '%' is escaped be a double one "%%"
|
||||||
|
*
|
||||||
|
* we do this conversation "in place" as the result is always
|
||||||
|
* equal or smaller in size.
|
||||||
|
*/
|
||||||
|
src = cf_name;
|
||||||
|
dest = cf_name;
|
||||||
|
while (*src) {
|
||||||
|
if (*src == '%') {
|
||||||
|
src++;
|
||||||
|
if (*src == '%') {
|
||||||
|
/* this is an escaped '%' char (was: "%%") */
|
||||||
|
*dest = *src;
|
||||||
|
src++;
|
||||||
|
dest++;
|
||||||
|
} else {
|
||||||
|
/* convert escaped hexnumber to unscaped character */
|
||||||
|
esc[0] = src[0];
|
||||||
|
esc[1] = src[1];
|
||||||
|
esc[2] = '\0';
|
||||||
|
ret = sscanf(esc, "%x", &i);
|
||||||
|
if (ret == 1) {
|
||||||
|
src+=2;
|
||||||
|
*dest = (gchar) i;
|
||||||
|
dest++;
|
||||||
|
} else {
|
||||||
|
/* somethings wrong, just jump over that char
|
||||||
|
* this will result in a wrong string, but we might get
|
||||||
|
* user feedback and can fix it later ;-) */
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*dest = *src;
|
||||||
|
src++;
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dest = '\0';
|
||||||
|
|
||||||
|
return cf_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dnd_merge_files(int in_file_count, char **in_filenames)
|
||||||
|
{
|
||||||
|
int out_fd;
|
||||||
|
gboolean merge_ok;
|
||||||
|
int err;
|
||||||
|
char tmpname[128+1];
|
||||||
|
|
||||||
|
|
||||||
|
out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
|
||||||
|
|
||||||
|
/* merge the files in chonological order */
|
||||||
|
merge_ok = cf_merge_files(tmpname, out_fd, in_file_count, in_filenames,
|
||||||
|
WTAP_FILE_PCAP, FALSE);
|
||||||
|
|
||||||
|
if (!merge_ok) {
|
||||||
|
/* merge failed */
|
||||||
|
close(out_fd); /* XXX - isn't it already closed? */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cf_close(&cfile);
|
||||||
|
|
||||||
|
/* Try to open the merged capture file. */
|
||||||
|
if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
|
||||||
|
/* We couldn't open it; don't dismiss the open dialog box,
|
||||||
|
just leave it around so that the user can, after they
|
||||||
|
dismiss the alert box popped up for the open error,
|
||||||
|
try again. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cf_read(&cfile)) {
|
||||||
|
|
||||||
|
case CF_READ_OK:
|
||||||
|
case CF_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 CF_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). */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_grab_focus(packet_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open/merge the dnd file */
|
||||||
|
void
|
||||||
|
dnd_open_file_cmd(GtkSelectionData *selection_data)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
gchar *cf_name, *cf_name_freeme;
|
||||||
|
int in_files;
|
||||||
|
gpointer dialog;
|
||||||
|
GString *dialog_text;
|
||||||
|
int files_work;
|
||||||
|
char **in_filenames;
|
||||||
|
|
||||||
|
|
||||||
|
/* 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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_filenames = g_malloc(sizeof(char*) * in_files);
|
||||||
|
|
||||||
|
/* 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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(in_files) {
|
||||||
|
case(0):
|
||||||
|
/* shouldn't happen */
|
||||||
|
break;
|
||||||
|
case(1):
|
||||||
|
/* open and read the capture file (this will close an existing file) */
|
||||||
|
if (cf_open(&cfile, in_filenames[0], FALSE, &err) == CF_OK) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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_SAVE):
|
||||||
|
/* save file first */
|
||||||
|
file_save_as_cmd(after_save_open_dnd_file, data);
|
||||||
|
break;
|
||||||
|
case(ESD_BTN_DONT_SAVE):
|
||||||
|
cf_close(&cfile);
|
||||||
|
dnd_open_file_cmd(data);
|
||||||
|
break;
|
||||||
|
case(ESD_BTN_CANCEL):
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
|
||||||
|
ESD_BTNS_SAVE_DONTSAVE_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_save_file_answered_cb, selection_data);
|
||||||
|
} else {
|
||||||
|
/* unchanged file */
|
||||||
|
dnd_open_file_cmd(selection_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init the drag and drop functionality */
|
||||||
|
void
|
||||||
|
dnd_init(GtkWidget *w)
|
||||||
|
{
|
||||||
|
/* we are only interested in the URI list containing filenames */
|
||||||
|
static GtkTargetEntry target_entry[] = {
|
||||||
|
/*{"STRING", 0, DND_TARGET_STRING},*/
|
||||||
|
/*{"text/plain", 0, DND_TARGET_STRING},*/
|
||||||
|
{"text/uri-list", 0, DND_TARGET_URL}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* set this window as a dnd destination */
|
||||||
|
gtk_drag_dest_set(
|
||||||
|
w, GTK_DEST_DEFAULT_ALL, target_entry,
|
||||||
|
sizeof(target_entry) / sizeof(GtkTargetEntry),
|
||||||
|
(GdkDragAction)(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
|
||||||
|
|
||||||
|
/* get notified, if some dnd coming in */
|
||||||
|
gtk_signal_connect(GTK_OBJECT(w), "drag_data_received",
|
||||||
|
GTK_SIGNAL_FUNC(dnd_data_received), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
292
gtk/main.c
292
gtk/main.c
|
@ -881,7 +881,7 @@ main_do_quit(void)
|
||||||
|
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
/* Nuke any child capture in progress. */
|
/* Nuke any child capture in progress. */
|
||||||
kill_capture_child(capture_opts);
|
capture_kill_child(capture_opts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Are we in the middle of reading a capture? */
|
/* Are we in the middle of reading a capture? */
|
||||||
|
@ -1326,296 +1326,6 @@ register_ethereal_tap(char *cmd, void (*func)(char *arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum { DND_TARGET_STRING, DND_TARGET_ROOTWIN, DND_TARGET_URL };
|
|
||||||
|
|
||||||
/* convert drag and drop URI to a local filename */
|
|
||||||
static gchar *
|
|
||||||
dnd_uri2filename(gchar *cf_name)
|
|
||||||
{
|
|
||||||
gchar *src, *dest;
|
|
||||||
gint ret;
|
|
||||||
guint i;
|
|
||||||
gchar esc[3];
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove URI header.
|
|
||||||
* On win32 (at least WinXP), this string looks like (UNC or local filename):
|
|
||||||
* file:////servername/sharename/dir1/dir2/capture-file.cap
|
|
||||||
* or
|
|
||||||
* file:///d:/dir1/dir2/capture-file.cap
|
|
||||||
* we have to remove the prefix to get a valid filename.
|
|
||||||
*
|
|
||||||
* On UNIX (at least KDE 3.0 Konqueror), this string looks like:
|
|
||||||
* file:/dir1/dir2/capture-file.cap
|
|
||||||
* we have to remove the file: to get a valid filename.
|
|
||||||
*/
|
|
||||||
if (strncmp("file:////", cf_name, 9) == 0) {
|
|
||||||
/* win32 UNC: now becoming: //servername/sharename/dir1/dir2/capture-file.cap */
|
|
||||||
cf_name += 7;
|
|
||||||
} else if (strncmp("file:///", cf_name, 8) == 0) {
|
|
||||||
/* win32 local: now becoming: d:/dir1/dir2/capture-file.cap */
|
|
||||||
cf_name += 8;
|
|
||||||
} else if (strncmp("file:", cf_name, 5) == 0) {
|
|
||||||
/* unix local: now becoming: /dir1/dir2/capture-file.cap */
|
|
||||||
cf_name += 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* unescape the escaped URI characters (spaces, ...)
|
|
||||||
*
|
|
||||||
* we have to replace escaped chars to their equivalents,
|
|
||||||
* e.g. %20 (always a two digit hexstring) -> ' '
|
|
||||||
* the percent character '%' is escaped be a double one "%%"
|
|
||||||
*
|
|
||||||
* we do this conversation "in place" as the result is always
|
|
||||||
* equal or smaller in size.
|
|
||||||
*/
|
|
||||||
src = cf_name;
|
|
||||||
dest = cf_name;
|
|
||||||
while (*src) {
|
|
||||||
if (*src == '%') {
|
|
||||||
src++;
|
|
||||||
if (*src == '%') {
|
|
||||||
/* this is an escaped '%' char (was: "%%") */
|
|
||||||
*dest = *src;
|
|
||||||
src++;
|
|
||||||
dest++;
|
|
||||||
} else {
|
|
||||||
/* convert escaped hexnumber to unscaped character */
|
|
||||||
esc[0] = src[0];
|
|
||||||
esc[1] = src[1];
|
|
||||||
esc[2] = '\0';
|
|
||||||
ret = sscanf(esc, "%x", &i);
|
|
||||||
if (ret == 1) {
|
|
||||||
src+=2;
|
|
||||||
*dest = (gchar) i;
|
|
||||||
dest++;
|
|
||||||
} else {
|
|
||||||
/* somethings wrong, just jump over that char
|
|
||||||
* this will result in a wrong string, but we might get
|
|
||||||
* user feedback and can fix it later ;-) */
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*dest = *src;
|
|
||||||
src++;
|
|
||||||
dest++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*dest = '\0';
|
|
||||||
|
|
||||||
return cf_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dnd_merge_files(int in_file_count, char **in_filenames)
|
|
||||||
{
|
|
||||||
int out_fd;
|
|
||||||
gboolean merge_ok;
|
|
||||||
int err;
|
|
||||||
char tmpname[128+1];
|
|
||||||
|
|
||||||
|
|
||||||
out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
|
|
||||||
|
|
||||||
/* merge the files in chonological order */
|
|
||||||
merge_ok = cf_merge_files(tmpname, out_fd, in_file_count, in_filenames,
|
|
||||||
WTAP_FILE_PCAP, FALSE);
|
|
||||||
|
|
||||||
if (!merge_ok) {
|
|
||||||
/* merge failed */
|
|
||||||
close(out_fd); /* XXX - isn't it already closed? */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cf_close(&cfile);
|
|
||||||
|
|
||||||
/* Try to open the merged capture file. */
|
|
||||||
if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
|
|
||||||
/* We couldn't open it; don't dismiss the open dialog box,
|
|
||||||
just leave it around so that the user can, after they
|
|
||||||
dismiss the alert box popped up for the open error,
|
|
||||||
try again. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cf_read(&cfile)) {
|
|
||||||
|
|
||||||
case CF_READ_OK:
|
|
||||||
case CF_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 CF_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). */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_grab_focus(packet_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* open/merge the dnd file */
|
|
||||||
void
|
|
||||||
dnd_open_file_cmd(GtkSelectionData *selection_data)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
gchar *cf_name, *cf_name_freeme;
|
|
||||||
int in_files;
|
|
||||||
gpointer dialog;
|
|
||||||
GString *dialog_text;
|
|
||||||
int files_work;
|
|
||||||
char **in_filenames;
|
|
||||||
|
|
||||||
|
|
||||||
/* 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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
in_filenames = g_malloc(sizeof(char*) * in_files);
|
|
||||||
|
|
||||||
/* 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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(in_files) {
|
|
||||||
case(0):
|
|
||||||
/* shouldn't happen */
|
|
||||||
break;
|
|
||||||
case(1):
|
|
||||||
/* open and read the capture file (this will close an existing file) */
|
|
||||||
if (cf_open(&cfile, in_filenames[0], FALSE, &err) == CF_OK) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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_SAVE):
|
|
||||||
/* save file first */
|
|
||||||
file_save_as_cmd(after_save_open_dnd_file, data);
|
|
||||||
break;
|
|
||||||
case(ESD_BTN_DONT_SAVE):
|
|
||||||
cf_close(&cfile);
|
|
||||||
dnd_open_file_cmd(data);
|
|
||||||
break;
|
|
||||||
case(ESD_BTN_CANCEL):
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
|
|
||||||
ESD_BTNS_SAVE_DONTSAVE_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_save_file_answered_cb, selection_data);
|
|
||||||
} else {
|
|
||||||
/* unchanged file */
|
|
||||||
dnd_open_file_cmd(selection_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init the drag and drop functionality */
|
|
||||||
static void
|
|
||||||
dnd_init(GtkWidget *w)
|
|
||||||
{
|
|
||||||
/* we are only interested in the URI list containing filenames */
|
|
||||||
static GtkTargetEntry target_entry[] = {
|
|
||||||
/*{"STRING", 0, DND_TARGET_STRING},*/
|
|
||||||
/*{"text/plain", 0, DND_TARGET_STRING},*/
|
|
||||||
{"text/uri-list", 0, DND_TARGET_URL}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* set this window as a dnd destination */
|
|
||||||
gtk_drag_dest_set(
|
|
||||||
w, GTK_DEST_DEFAULT_ALL, target_entry,
|
|
||||||
sizeof(target_entry) / sizeof(GtkTargetEntry),
|
|
||||||
(GdkDragAction)(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
|
|
||||||
|
|
||||||
/* get notified, if some dnd coming in */
|
|
||||||
gtk_signal_connect(GTK_OBJECT(w), "drag_data_received",
|
|
||||||
GTK_SIGNAL_FUNC(dnd_data_received), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* And now our feature presentation... [ fade to music ] */
|
/* And now our feature presentation... [ fade to music ] */
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
|
|
|
@ -262,6 +262,10 @@ extern void main_widgets_show_or_hide(void);
|
||||||
extern gboolean main_filter_packets(capture_file *cf, const gchar *dftext,
|
extern gboolean main_filter_packets(capture_file *cf, const gchar *dftext,
|
||||||
gboolean force);
|
gboolean force);
|
||||||
|
|
||||||
|
/** Init the drag-n-drop functionality.
|
||||||
|
*/
|
||||||
|
extern void dnd_init(void);
|
||||||
|
|
||||||
/** Open a new file coming from drag and drop.
|
/** Open a new file coming from drag and drop.
|
||||||
* @param selection_data the selection data reported from GTK
|
* @param selection_data the selection data reported from GTK
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue