Improved support for File DnD on Linux if File URIs are not escaped correctly (i.e. contain literal [ or ] in the File URI which is not allowed as per URI spec).

See https://www.filebot.net/forums/viewtopic.php?f=11&t=9651
This commit is contained in:
Reinhard Pointner 2019-01-23 15:36:53 +07:00
parent c1fe2c1f37
commit 8aee1e9e85
5 changed files with 33 additions and 17 deletions

View File

@ -1,13 +1,12 @@
package net.filebot.platform.gnome;
import java.io.File;
import java.net.URI;
import net.filebot.util.SystemProperty;
public interface GVFS {
File getPathForURI(URI uri);
File getPathForURI(String resource);
public static GVFS getDefaultVFS() {
GVFS gvfs = SystemProperty.of("net.filebot.gio.GVFS", path -> new PlatformGVFS(new File(path))).get();

View File

@ -2,7 +2,6 @@
package net.filebot.platform.gnome;
import java.io.File;
import java.net.URI;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
@ -12,8 +11,8 @@ public class NativeGVFS implements GVFS {
private static final LibGIO lib_gio = (LibGIO) Native.loadLibrary("gio-2.0", LibGIO.class);
private static final Pointer gvfs = lib_gio.g_vfs_get_default();
public File getPathForURI(URI uri) {
Pointer gfile = lib_gio.g_vfs_get_file_for_uri(gvfs, uri.toString());
public File getPathForURI(String resource) {
Pointer gfile = lib_gio.g_vfs_get_file_for_uri(gvfs, resource);
Pointer chars = lib_gio.g_file_get_path(gfile);
try {
@ -21,7 +20,7 @@ public class NativeGVFS implements GVFS {
return new File(chars.getString(0));
}
throw new IllegalArgumentException("Failed to locate local path: " + uri);
throw new IllegalArgumentException("Failed to locate local path: " + resource);
} finally {
lib_gio.g_object_unref(gfile);
lib_gio.g_free(chars);

View File

@ -6,6 +6,7 @@ import static java.util.stream.Collectors.*;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
public class PlatformGVFS implements GVFS {
@ -16,8 +17,23 @@ public class PlatformGVFS implements GVFS {
this.gvfs = gvfs;
}
public File getPathForURI(URI uri) {
return Protocol.forName(uri.getScheme()).getFile(gvfs, uri);
public File getPathForURI(String resource) {
return getPathForURI(parseURI(resource));
}
public File getPathForURI(URI resource) {
return Protocol.forName(resource.getScheme()).getFile(gvfs, resource);
}
public URI parseURI(String resource) {
try {
// DIRTY WORK AROUND: Square Brackets [] are reserved as per RFC2732 but some file managers (e.g. KDE Dolphin) don't URI encode them correctly
resource = resource.replace("[", "%5B").replace("]", "%5D");
return new URI(resource);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@Override

View File

@ -11,7 +11,6 @@ import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@ -112,7 +111,7 @@ public class FileTransferable implements Transferable {
}
try {
File file = GVFS.getDefaultVFS().getPathForURI(new URI(line));
File file = GVFS.getDefaultVFS().getPathForURI(line);
if (file == null || !file.exists()) {
throw new FileNotFoundException(file.getPath());

View File

@ -3,31 +3,34 @@ package net.filebot.gio;
import static org.junit.Assert.*;
import java.io.File;
import java.net.URI;
import org.junit.Test;
import net.filebot.platform.gnome.GVFS;
import net.filebot.platform.gnome.PlatformGVFS;
public class PlatformGVFSTest {
GVFS gvfs = new PlatformGVFS(new File("gvfs"));
PlatformGVFS gvfs = new PlatformGVFS(new File("gvfs"));
@Test
public void smb() throws Exception {
assertEquals("gvfs/smb-share:server=10.0.1.5,share=data/Movies/Avatar.mp4", gvfs.getPathForURI(new URI("smb://10.0.1.5/data/Movies/Avatar.mp4")).getPath());
assertEquals("gvfs/smb-share:server=192.168.0.1,share=test/a file with spaces.txt", gvfs.getPathForURI(new URI("smb://192.168.0.1/test/a%20file%20with%20spaces.txt")).getPath());
assertEquals("gvfs/smb-share:server=10.0.1.5,share=data/Movies/Avatar.mp4", gvfs.getPathForURI("smb://10.0.1.5/data/Movies/Avatar.mp4").getPath());
assertEquals("gvfs/smb-share:server=192.168.0.1,share=test/a file with spaces.txt", gvfs.getPathForURI("smb://192.168.0.1/test/a%20file%20with%20spaces.txt").getPath());
}
@Test
public void afp() throws Exception {
assertEquals("gvfs/afp-volume:host=10.0.1.5,user=reinhard,volume=data/Movies/Avatar.mp4", gvfs.getPathForURI(new URI("afp://reinhard@10.0.1.5/data/Movies/Avatar.mp4")).getPath());
assertEquals("gvfs/afp-volume:host=10.0.1.5,user=reinhard,volume=data/Movies/Avatar.mp4", gvfs.getPathForURI("afp://reinhard@10.0.1.5/data/Movies/Avatar.mp4").getPath());
}
@Test
public void sftp() throws Exception {
assertEquals("gvfs/sftp:host=myserver.org,user=nico/home/Movies/Avatar.mp4", gvfs.getPathForURI(new URI("sftp://nico@myserver.org/home/Movies/Avatar.mp4")).getPath());
assertEquals("gvfs/sftp:host=myserver.org,user=nico/home/Movies/Avatar.mp4", gvfs.getPathForURI("sftp://nico@myserver.org/home/Movies/Avatar.mp4").getPath());
}
@Test
public void fileWithSquareBrackets() throws Exception {
assertEquals("/home/media/Alias - 1x01 - [test].mp4", gvfs.parseURI("file:///home/media/Alias%20-%201x01%20-%20[test].mp4").getPath());
}
}