diff --git a/source/net/filebot/gio/GVFS.java b/source/net/filebot/gio/GVFS.java index 168c03ce..ca783ecd 100644 --- a/source/net/filebot/gio/GVFS.java +++ b/source/net/filebot/gio/GVFS.java @@ -10,7 +10,7 @@ public interface GVFS { File getPathForURI(URI uri); public static GVFS getDefaultVFS() { - return SystemProperty.of("net.filebot.gio.GVFS", PlatformGVFS::new, NativeGVFS::new).get(); + return SystemProperty.of("net.filebot.gio.GVFS", path -> new PlatformGVFS(new File(path)), NativeGVFS::new).get(); } } diff --git a/source/net/filebot/gio/NativeGVFS.java b/source/net/filebot/gio/NativeGVFS.java index 338e2294..35a76166 100644 --- a/source/net/filebot/gio/NativeGVFS.java +++ b/source/net/filebot/gio/NativeGVFS.java @@ -17,10 +17,11 @@ public class NativeGVFS implements GVFS { Pointer chars = lib_gio.g_file_get_path(gfile); try { - if (chars != null) + if (chars != null) { return new File(chars.getString(0)); - else - return null; + } + + throw new IllegalArgumentException("Failed to locate local path: " + uri); } finally { lib_gio.g_object_unref(gfile); lib_gio.g_free(chars); diff --git a/source/net/filebot/gio/PlatformGVFS.java b/source/net/filebot/gio/PlatformGVFS.java index cd4eb8e3..b19d3bb3 100644 --- a/source/net/filebot/gio/PlatformGVFS.java +++ b/source/net/filebot/gio/PlatformGVFS.java @@ -8,19 +8,43 @@ public class PlatformGVFS implements GVFS { private final File gvfs; - public PlatformGVFS(String gvfs) { - this.gvfs = new File(gvfs); + public PlatformGVFS(File gvfs) { + if (gvfs.list() == null) { + throw new IllegalArgumentException(gvfs.getPath() + " is not a valid directory"); + } + + this.gvfs = gvfs; } public File getPathForURI(URI uri) { - // e.g. smb://10.0.1.5/data/Movies/Avatar.mp4 -> /run/user/1000/gvfs/smb-share:server=10.0.1.5,share=data/Movies/Avatar.mp4 - - switch (uri.getScheme()) { - case "file": + if ("file".equals(uri.getScheme())) { return new File(uri); - default: - return new File(gvfs, uri.getScheme() + "-share:server=" + uri.getHost() + ",share=" + uri.getPath().substring(1)); } + + // e.g. smb://10.0.1.5/data/Movies/Avatar.mp4 -> /run/user/1000/gvfs/smb-share:server=10.0.1.5,share=data/Movies/Avatar.mp4 + // e.g. afp://reinhard@10.0.1.5/data/Movies/Avatar.mp4 -> /run/user/1000/gvfs/afp-volume:host=10.0.1.5,user=reinhard,volume=data/Movies/Avatar.mp4 + // e.g. sftp://reinhard@10.0.1.5/home/Movies/Avatar.mp4 -> /run/user/1000/gvfs/sftp:host=10.0.1.5,user=reinhard/home/Movies/Avatar.mp4 + + // guess GVFS folder based on keywords (see https://wiki.gnome.org/Projects/gvfs/doc) + for (String mount : gvfs.list()) { + if (mount.startsWith(uri.getScheme()) && mount.contains(uri.getHost())) { + if (uri.getUserInfo() != null && !mount.contains(uri.getUserInfo())) + continue; + if (uri.getPort() > 0 && !mount.contains(String.valueOf(uri.getPort()))) + continue; + + String path = uri.getPath().substring(1); + String share = path.substring(0, path.indexOf('/')); + + if (mount.endsWith(share)) { + path = path.substring(share.length()).substring(1); + } + + return new File(new File(gvfs, mount), path); + } + } + + throw new IllegalArgumentException("Failed to locate local path: " + uri); } } diff --git a/source/net/filebot/ui/transfer/FileTransferable.java b/source/net/filebot/ui/transfer/FileTransferable.java index 5f8e8f7e..d15e5b29 100644 --- a/source/net/filebot/ui/transfer/FileTransferable.java +++ b/source/net/filebot/ui/transfer/FileTransferable.java @@ -107,8 +107,7 @@ public class FileTransferable implements Transferable { } try { - URI uri = new URI(line); - File file = GVFS.getDefaultVFS().getPathForURI(uri); + File file = GVFS.getDefaultVFS().getPathForURI(new URI(line)); if (file == null || !file.exists()) { throw new FileNotFoundException(line); @@ -116,8 +115,7 @@ public class FileTransferable implements Transferable { files.add(file); } catch (Throwable e) { - // URISyntaxException, IllegalArgumentException, FileNotFoundException, LinkageError, etc - debug.warning("Invalid file URI: " + line); + debug.warning(e::toString); } } diff --git a/test/net/filebot/gio/PlatformGVFSTest.java b/test/net/filebot/gio/PlatformGVFSTest.java new file mode 100644 index 00000000..44bc08cc --- /dev/null +++ b/test/net/filebot/gio/PlatformGVFSTest.java @@ -0,0 +1,44 @@ +package net.filebot.gio; + +import static java.util.Arrays.*; +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URI; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class PlatformGVFSTest { + + static File gvfsRoot = new File("gvfs"); + static String[] shares = { "smb-share:server=10.0.1.5,share=data", "afp-volume:host=10.0.1.5,user=reinhard,volume=data", "sftp:host=myserver.org,user=nico" }; + + GVFS gvfs = new PlatformGVFS(gvfsRoot); + + @BeforeClass + public static void before() throws Exception { + stream(shares).forEach(f -> new File(gvfsRoot, f).mkdirs()); + } + + @AfterClass + public static void after() throws Exception { + } + + @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()); + } + + @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()); + } + + @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()); + } + +}