Rewrite the drag and drop code to handle multiple files (oops),
as well as being much more robust about misformatted file URIs.
This commit is contained in:
parent
78aa41ac5e
commit
e1671b50e6
106
gtk/main.c
106
gtk/main.c
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
|
@ -441,40 +442,89 @@ gotdrag(GtkWidget *widget SHUTUP, GdkDragContext *dc, gint x SHUTUP,
|
||||||
gint y SHUTUP, GtkSelectionData *sel, guint info SHUTUP, guint time,
|
gint y SHUTUP, GtkSelectionData *sel, guint info SHUTUP, guint time,
|
||||||
gpointer gdata) {
|
gpointer gdata) {
|
||||||
struct cbdata *data = gdata;
|
struct cbdata *data = gdata;
|
||||||
char prefix[] = "file://";
|
char prefix[] = "file:";
|
||||||
char *file, *sele, *targ, *type;
|
char *files, *decoded, *deslashed, *hostless;
|
||||||
int ii;
|
int ii, len;
|
||||||
|
GList *errs;
|
||||||
|
gboolean gotfile;
|
||||||
|
struct stat sb;
|
||||||
|
int prelen = strlen(prefix);
|
||||||
|
|
||||||
|
#ifdef DND_DEBUG
|
||||||
|
char *sele = gdk_atom_name(sel->selection);
|
||||||
|
char *targ = gdk_atom_name(sel->target);
|
||||||
|
char *type = gdk_atom_name(sel->type);
|
||||||
|
|
||||||
|
fprintf(stderr, "dropped file: sel=%s targ=%s type=%s fmt=%i len=%i\n",
|
||||||
|
sele, targ, type, sel->format, sel->length);
|
||||||
|
g_free(sele);
|
||||||
|
g_free(targ);
|
||||||
|
g_free(type);
|
||||||
|
if(8 == sel->format) {
|
||||||
|
for(ii = 0; ii < sel->length; ii++)
|
||||||
|
fprintf(stderr, "%02X ", sel->data[ii]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
errs = NULL;
|
||||||
|
gotfile = FALSE;
|
||||||
if(gdk_atom_intern("XdndSelection", FALSE) == sel->selection &&
|
if(gdk_atom_intern("XdndSelection", FALSE) == sel->selection &&
|
||||||
8 == sel->format && (int)sizeof(prefix) - 1 < sel->length &&
|
8 == sel->format) {
|
||||||
0 == strncmp(prefix, sel->data, sizeof(prefix) - 1)) {
|
/* split file list on carriage returns and linefeeds */
|
||||||
file = urldecode(sel->data + (sizeof(prefix) - 1),
|
files = g_new(char, sel->length + 1);
|
||||||
sel->length - (sizeof(prefix) - 1));
|
memcpy(files, sel->data, sel->length);
|
||||||
if(g_utf8_validate(file, -1, NULL) &&
|
files[sel->length] = '\0';
|
||||||
addtorrent(data->tr, data->wind, file, NULL, FALSE, NULL)) {
|
for(ii = 0; '\0' != files[ii]; ii++)
|
||||||
g_free(file);
|
if('\015' == files[ii] || '\012' == files[ii])
|
||||||
gtk_drag_finish(dc, TRUE, FALSE, time);
|
files[ii] = '\0';
|
||||||
addedtorrents(data);
|
|
||||||
return;
|
/* try to get a usable filename out of the URI supplied and add it */
|
||||||
|
for(ii = 0; ii < sel->length; ii += len + 1) {
|
||||||
|
if('\0' == files[ii])
|
||||||
|
len = 0;
|
||||||
|
else {
|
||||||
|
len = strlen(files + ii);
|
||||||
|
/* de-urlencode the URI */
|
||||||
|
decoded = urldecode(files + ii, len);
|
||||||
|
if(g_utf8_validate(decoded, -1, NULL)) {
|
||||||
|
/* remove the file: prefix */
|
||||||
|
if(prelen < len && 0 == strncmp(prefix, decoded, prelen)) {
|
||||||
|
deslashed = decoded + prelen;
|
||||||
|
/* trim excess / characters from the beginning */
|
||||||
|
while('/' == deslashed[0] && '/' == deslashed[1])
|
||||||
|
deslashed++;
|
||||||
|
/* if the file doesn't exist, the first part might be a hostname */
|
||||||
|
if(0 > g_stat(deslashed, &sb) &&
|
||||||
|
NULL != (hostless = strchr(deslashed + 1, '/')) &&
|
||||||
|
0 == g_stat(hostless, &sb))
|
||||||
|
deslashed = hostless;
|
||||||
|
/* finally, try to add it as a torrent */
|
||||||
|
if(addtorrent(data->tr, data->wind, deslashed, NULL, FALSE, &errs))
|
||||||
|
gotfile = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free(decoded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_free(file);
|
|
||||||
} else {
|
g_free(files);
|
||||||
sele = gdk_atom_name(sel->selection);
|
if(gotfile)
|
||||||
targ = gdk_atom_name(sel->target);
|
addedtorrents(data);
|
||||||
type = gdk_atom_name(sel->type);
|
|
||||||
fprintf(stderr, "unhandled drag: sel=%s targ=%s type=%s fmt=%i len=%i\n",
|
/* print any errors */
|
||||||
sele, targ, type, sel->format, sel->length);
|
if(NULL != errs) {
|
||||||
g_free(sele);
|
files = joinstrlist(errs, "\n");
|
||||||
g_free(targ);
|
errmsg(data->wind, ngettext("Failed to load the torrent file %s",
|
||||||
g_free(type);
|
"Failed to load the torrent files:\n%s",
|
||||||
if(8 == sel->format) {
|
g_list_length(errs)), files);
|
||||||
for(ii = 0; ii < sel->length; ii++)
|
g_list_foreach(errs, (GFunc)g_free, NULL);
|
||||||
fprintf(stderr, "%02X ", sel->data[ii]);
|
g_list_free(errs);
|
||||||
fprintf(stderr, "\n");
|
g_free(files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_drag_finish(dc, FALSE, FALSE, time);
|
gtk_drag_finish(dc, gotfile, FALSE, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue