2010-08-13 21:03:29 +00:00
|
|
|
/* drag_and_drop.c
|
2005-02-05 15:35:25 +00:00
|
|
|
* Drag and Drop
|
|
|
|
*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2005-02-05 15:35:25 +00:00
|
|
|
* 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
|
2012-06-28 22:56:06 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2005-02-05 15:35:25 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-20 01:48:30 +00:00
|
|
|
#include "config.h"
|
2005-02-05 15:35:25 +00:00
|
|
|
|
2008-04-13 01:54:20 +00:00
|
|
|
#include <string.h>
|
2007-08-30 00:24:40 +00:00
|
|
|
|
2005-02-05 15:35:25 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
|
2016-02-18 12:06:13 +00:00
|
|
|
#include "../../file.h"
|
2005-05-12 03:29:26 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2014-06-30 05:38:29 +00:00
|
|
|
#include "ui/capture.h"
|
2005-05-12 03:29:26 +00:00
|
|
|
#endif
|
2005-02-05 15:35:25 +00:00
|
|
|
|
2012-08-03 23:30:47 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
#include "ui/capture_globals.h"
|
|
|
|
#endif
|
2012-01-18 19:38:34 +00:00
|
|
|
#include "ui/recent_utils.h"
|
2012-01-16 01:07:52 +00:00
|
|
|
#include "ui/simple_dialog.h"
|
|
|
|
|
2012-01-15 21:59:11 +00:00
|
|
|
#include "ui/gtk/gtkglobals.h"
|
|
|
|
#include "ui/gtk/capture_file_dlg.h"
|
|
|
|
#include "ui/gtk/drag_and_drop.h"
|
|
|
|
#include "ui/gtk/main.h"
|
2005-02-05 15:35:25 +00:00
|
|
|
|
2012-01-15 21:59:11 +00:00
|
|
|
#include "ui/gtk/old-gtk-compat.h"
|
2011-07-21 17:44:02 +00:00
|
|
|
|
2005-02-05 15:35:25 +00:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
|
|
|
|
2005-04-06 21:24:00 +00:00
|
|
|
/* Remove URI header.
|
|
|
|
* we have to remove the prefix to get a valid filename. */
|
|
|
|
#ifdef _WIN32
|
2005-02-05 15:35:25 +00:00
|
|
|
/*
|
2005-04-06 21:24:00 +00:00
|
|
|
* On win32 (at least WinXP), this prefix looks like (UNC):
|
2005-02-05 15:35:25 +00:00
|
|
|
* file:////servername/sharename/dir1/dir2/capture-file.cap
|
2005-04-06 21:24:00 +00:00
|
|
|
* or (local filename):
|
2005-02-05 15:35:25 +00:00
|
|
|
* file:///d:/dir1/dir2/capture-file.cap
|
2005-04-06 21:24:00 +00:00
|
|
|
*/
|
2005-02-05 15:35:25 +00:00
|
|
|
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;
|
2005-04-06 21:24:00 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* On UNIX (at least KDE 3.0 Konqueror), this prefix looks like:
|
|
|
|
* file:/dir1/dir2/capture-file.cap
|
|
|
|
*
|
|
|
|
* On UNIX (at least GNOME Nautilus 2.8.2), this prefix looks like:
|
|
|
|
* file:///dir1/dir2/capture-file.cap
|
2007-08-30 00:24:40 +00:00
|
|
|
*/
|
2005-04-06 21:24:00 +00:00
|
|
|
if (strncmp("file:", cf_name, 5) == 0) {
|
|
|
|
/* now becoming: /dir1/dir2/capture-file.cap or ///dir1/dir2/capture-file.cap */
|
2005-02-05 15:35:25 +00:00
|
|
|
cf_name += 5;
|
2005-04-06 21:24:00 +00:00
|
|
|
/* shorten //////thing to /thing */
|
|
|
|
for(; cf_name[1] == '/'; ++cf_name);
|
2005-02-05 15:35:25 +00:00
|
|
|
}
|
2005-04-06 21:24:00 +00:00
|
|
|
#endif
|
2005-02-05 15:35:25 +00:00
|
|
|
|
2007-08-30 00:24:40 +00:00
|
|
|
/*
|
2005-02-05 15:35:25 +00:00
|
|
|
* unescape the escaped URI characters (spaces, ...)
|
|
|
|
*
|
2007-08-30 00:24:40 +00:00
|
|
|
* we have to replace escaped chars to their equivalents,
|
2005-02-05 15:35:25 +00:00
|
|
|
* e.g. %20 (always a two digit hexstring) -> ' '
|
|
|
|
* the percent character '%' is escaped be a double one "%%"
|
|
|
|
*
|
2007-08-30 00:24:40 +00:00
|
|
|
* we do this conversation "in place" as the result is always
|
2005-02-05 15:35:25 +00:00
|
|
|
* 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++;
|
|
|
|
}
|
|
|
|
}
|
2012-01-20 21:20:53 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
} else if (*src == '/') {
|
|
|
|
*dest = '\\';
|
|
|
|
src++;
|
|
|
|
dest++;
|
|
|
|
#endif
|
2005-02-05 15:35:25 +00:00
|
|
|
} else {
|
|
|
|
*dest = *src;
|
|
|
|
src++;
|
|
|
|
dest++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*dest = '\0';
|
|
|
|
|
|
|
|
return cf_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open/merge the dnd file */
|
|
|
|
void
|
2005-07-25 18:02:32 +00:00
|
|
|
dnd_open_file_cmd(gchar *cf_names_freeme)
|
2005-02-05 15:35:25 +00:00
|
|
|
{
|
|
|
|
int err;
|
2005-07-25 18:02:32 +00:00
|
|
|
gchar *cf_name;
|
2013-05-14 18:16:58 +00:00
|
|
|
int in_file_count;
|
2005-02-05 15:35:25 +00:00
|
|
|
int files_work;
|
|
|
|
char **in_filenames;
|
2013-05-14 18:16:58 +00:00
|
|
|
char *tmpname;
|
2005-02-05 15:35:25 +00:00
|
|
|
|
2012-11-02 09:58:43 +00:00
|
|
|
if (cf_names_freeme == NULL) return;
|
2007-08-30 00:24:40 +00:00
|
|
|
|
2012-09-22 23:47:23 +00:00
|
|
|
/* DND_TARGET_URL:
|
2005-07-25 18:02:32 +00:00
|
|
|
* The cf_name_freeme is a single string, containing one or more URI's,
|
2012-09-22 23:47:23 +00:00
|
|
|
* terminated by CR/NL chars. The length of the whole field can be found
|
2005-02-05 15:35:25 +00:00
|
|
|
* 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. */
|
|
|
|
|
|
|
|
/* count the number of input files */
|
2005-07-25 18:02:32 +00:00
|
|
|
cf_name = cf_names_freeme;
|
2013-05-14 18:16:58 +00:00
|
|
|
for(in_file_count = 0; (cf_name = strstr(cf_name, "\r\n")) != NULL; ) {
|
2005-02-05 15:35:25 +00:00
|
|
|
cf_name += 2;
|
2013-05-14 18:16:58 +00:00
|
|
|
in_file_count++;
|
2005-02-05 15:35:25 +00:00
|
|
|
}
|
2013-05-14 18:16:58 +00:00
|
|
|
if (in_file_count == 0) {
|
2012-11-02 09:58:43 +00:00
|
|
|
g_free(cf_names_freeme);
|
|
|
|
return;
|
|
|
|
}
|
2005-02-05 15:35:25 +00:00
|
|
|
|
2013-05-14 18:16:58 +00:00
|
|
|
in_filenames = (char **)g_malloc(sizeof(char*) * in_file_count);
|
2005-02-05 15:35:25 +00:00
|
|
|
|
|
|
|
/* store the starts of the file entries in a gchar array */
|
2005-07-25 18:02:32 +00:00
|
|
|
cf_name = cf_names_freeme;
|
2005-02-05 15:35:25 +00:00
|
|
|
in_filenames[0] = cf_name;
|
2013-05-14 18:16:58 +00:00
|
|
|
for(files_work = 1; (cf_name = strstr(cf_name, "\r\n")) != NULL && files_work < in_file_count; ) {
|
2005-02-05 15:35:25 +00:00
|
|
|
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 */
|
2005-07-25 18:02:32 +00:00
|
|
|
cf_name = cf_names_freeme;
|
2005-02-05 15:35:25 +00:00
|
|
|
g_strdelimit(cf_name, "\r\n", '\0');
|
|
|
|
|
|
|
|
/* convert all filenames from URI to local filename (in place) */
|
2013-05-14 18:16:58 +00:00
|
|
|
for(files_work = 0; files_work < in_file_count; files_work++) {
|
2005-02-05 15:35:25 +00:00
|
|
|
in_filenames[files_work] = dnd_uri2filename(in_filenames[files_work]);
|
|
|
|
}
|
|
|
|
|
2013-05-14 18:16:58 +00:00
|
|
|
if (in_file_count == 1) {
|
2005-02-05 15:35:25 +00:00
|
|
|
/* open and read the capture file (this will close an existing file) */
|
2014-01-18 14:20:02 +00:00
|
|
|
if (cf_open(&cfile, in_filenames[0], WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
|
2013-01-14 19:00:44 +00:00
|
|
|
/* XXX - add this to the menu if the read fails? */
|
|
|
|
cf_read(&cfile, FALSE);
|
|
|
|
add_menu_recent_capture_file(in_filenames[0]);
|
|
|
|
} else {
|
|
|
|
/* the capture file couldn't be read (doesn't exist, file format unknown, ...) */
|
|
|
|
}
|
|
|
|
} else {
|
2013-05-14 18:16:58 +00:00
|
|
|
/* merge the files in chronological order */
|
2017-01-21 00:05:56 +00:00
|
|
|
if (cf_merge_files_to_tempfile(top_level, &tmpname, in_file_count, in_filenames,
|
2016-12-04 01:57:34 +00:00
|
|
|
WTAP_FILE_TYPE_SUBTYPE_PCAPNG, FALSE) == CF_OK) {
|
2013-05-14 18:16:58 +00:00
|
|
|
/* Merge succeeded; close the currently-open file and try
|
|
|
|
to open the merged capture file. */
|
|
|
|
cf_close(&cfile);
|
2014-01-18 14:20:02 +00:00
|
|
|
if (cf_open(&cfile, tmpname, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) == CF_OK) {
|
2013-05-14 18:16:58 +00:00
|
|
|
g_free(tmpname);
|
|
|
|
cf_read(&cfile, FALSE);
|
|
|
|
} else {
|
|
|
|
/* The merged file couldn't be read. */
|
|
|
|
g_free(tmpname);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* merge failed */
|
|
|
|
g_free(tmpname);
|
2005-02-05 15:35:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(in_filenames);
|
2005-07-25 18:02:32 +00:00
|
|
|
g_free(cf_names_freeme);
|
2005-02-05 15:35:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* we have received some drag and drop data */
|
|
|
|
/* (as we only registered to "text/uri-list", we will only get a file list here) */
|
2007-08-30 00:24:40 +00:00
|
|
|
static void
|
|
|
|
dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_,
|
2011-01-08 18:44:21 +00:00
|
|
|
GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_)
|
2005-02-05 15:35:25 +00:00
|
|
|
{
|
2008-06-24 03:38:15 +00:00
|
|
|
gchar *cf_names_freeme;
|
2011-02-07 18:41:38 +00:00
|
|
|
const guchar *sel_data_data;
|
|
|
|
gint sel_data_len;
|
2005-02-05 15:35:25 +00:00
|
|
|
|
|
|
|
if (info == DND_TARGET_URL) {
|
2007-08-30 00:24:40 +00:00
|
|
|
/* Usually we block incoming events by disabling the corresponding menu/toolbar items.
|
|
|
|
* This is the only place where an incoming event won't be blocked in such a way,
|
|
|
|
* so we have to take care of NOT loading a new file while a different process
|
2005-04-27 19:56:31 +00:00
|
|
|
* (e.g. capture/load/...) is still in progress. */
|
|
|
|
|
2005-05-12 03:29:26 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2005-04-27 19:56:31 +00:00
|
|
|
/* if a capture is running, do nothing but warn the user */
|
2013-05-22 07:44:28 +00:00
|
|
|
if((global_capture_session.state != CAPTURE_STOPPED)) {
|
2009-11-10 12:05:25 +00:00
|
|
|
simple_dialog(ESD_TYPE_CONFIRMATION,
|
2005-04-27 19:56:31 +00:00
|
|
|
ESD_BTN_OK,
|
2017-01-22 20:14:33 +00:00
|
|
|
"%sDrag and Drop currently not possible.%s\n\n"
|
2008-04-12 01:41:53 +00:00
|
|
|
"Dropping a file isn't possible while a capture is in progress.",
|
|
|
|
simple_dialog_primary_start(), simple_dialog_primary_end());
|
2005-04-27 19:56:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-05-12 03:29:26 +00:00
|
|
|
#endif
|
2005-04-27 19:56:31 +00:00
|
|
|
|
|
|
|
/* if another file read is still in progress, do nothing but warn the user */
|
2011-04-25 21:07:01 +00:00
|
|
|
if(cfile.state == FILE_READ_IN_PROGRESS) {
|
2009-11-10 12:05:25 +00:00
|
|
|
simple_dialog(ESD_TYPE_CONFIRMATION,
|
2005-04-27 19:56:31 +00:00
|
|
|
ESD_BTN_OK,
|
2017-01-22 20:14:33 +00:00
|
|
|
"%sDrag and Drop currently not possible.%s\n\n"
|
2008-04-12 01:41:53 +00:00
|
|
|
"Dropping a file isn't possible while loading another capture file.",
|
|
|
|
simple_dialog_primary_start(), simple_dialog_primary_end());
|
2005-04-27 19:56:31 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-22 23:47:23 +00:00
|
|
|
/* the selection_data will soon be gone, make a copy first */
|
|
|
|
/* the data string is not zero terminated -> make a zero terminated "copy" of it */
|
|
|
|
sel_data_len = gtk_selection_data_get_length(selection_data);
|
|
|
|
sel_data_data = gtk_selection_data_get_data(selection_data);
|
2013-03-09 10:09:58 +00:00
|
|
|
cf_names_freeme = (gchar *)g_malloc(sel_data_len + 1);
|
2012-09-22 23:47:23 +00:00
|
|
|
memcpy(cf_names_freeme, sel_data_data, sel_data_len);
|
|
|
|
cf_names_freeme[sel_data_len] = '\0';
|
2012-11-02 09:58:43 +00:00
|
|
|
|
2012-05-25 21:25:55 +00:00
|
|
|
/* If there's unsaved data, let the user save it first.
|
|
|
|
If they cancel out of it, don't open the file. */
|
|
|
|
if (do_file_close(&cfile, FALSE, " before opening a new capture file"))
|
2012-09-22 23:47:23 +00:00
|
|
|
dnd_open_file_cmd(cf_names_freeme);
|
2005-02-05 15:35:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* init the drag and drop functionality */
|
2007-08-30 00:24:40 +00:00
|
|
|
void
|
2005-02-05 15:35:25 +00:00
|
|
|
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},*/
|
2015-11-21 23:48:27 +00:00
|
|
|
{"text/uri-list", 0, DND_TARGET_URL}
|
2005-02-05 15:35:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* 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 */
|
2008-06-29 15:51:43 +00:00
|
|
|
g_signal_connect(w, "drag_data_received", G_CALLBACK(dnd_data_received), NULL);
|
2005-02-05 15:35:25 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 18:58:39 +00:00
|
|
|
/*
|
|
|
|
* Editor modelines - http://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:
|
|
|
|
*/
|