From cf920c57c6cf4033c4d759727463e5bb4747f120 Mon Sep 17 00:00:00 2001 From: Adrian Malacoda Date: Sun, 13 Dec 2020 06:26:04 -0600 Subject: [PATCH] lib: add FtpServer type --- README.md | 2 +- .../monarchpass/piecannon/impl/FtpServer.java | 45 +++++++++++++++++++ .../piecannon/util/ServerFactory.java | 25 ++++++++++- servers.example.json | 1 + 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 lib/src/main/java/net/monarchpass/piecannon/impl/FtpServer.java diff --git a/README.md b/README.md index be754ff..db521fb 100644 --- a/README.md +++ b/README.md @@ -28,4 +28,4 @@ TODO ## How to use Place a `servers.json` in the Pie Cannon data directory. For GNU/Linux this is `XDG_DATA_HOME` (by default this would be `~/.local/share/piecannon`) (create this directory if it does not exist. For Android this would be the app's "externalFilesDir" (probably something like `Android/data/net.monarchpass.piecannon/files` - the app will tell you when you launch it). See `servers.example.json` for an example of such a file. Whenever you initiate a file upload, Pie Cannon will select one of your defined servers at random and upload the file. -For SFTP servers (the only supported type as of now), the `path` is relative to your home directory and should be where `url` points to. i.e. a file uploaded to `path` should be downloadable at `url`. In the future Pie Cannon should be able to get SSH credentials from your agent so you won't need to put a password in this file. +For FTP/SFTP servers (the only supported types as of now), the `path` is relative to your home directory and should be where `url` points to. i.e. a file uploaded to `path` should be downloadable at `url`. In the future Pie Cannon should be able to get SSH credentials from your agent so you won't need to put a password in this file. diff --git a/lib/src/main/java/net/monarchpass/piecannon/impl/FtpServer.java b/lib/src/main/java/net/monarchpass/piecannon/impl/FtpServer.java new file mode 100644 index 0000000..4340edf --- /dev/null +++ b/lib/src/main/java/net/monarchpass/piecannon/impl/FtpServer.java @@ -0,0 +1,45 @@ +package net.monarchpass.piecannon.impl; + +import net.monarchpass.piecannon.Server; +import com.google.common.io.ByteSource; +import com.google.common.io.ByteStreams; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; + +import lombok.Data; + +@Data +public class FtpServer implements Server { + private final String label; + private final String host; + private final int port; + private final String username; + private final String password; + private final String path; + private final URI uri; + + public URI upload (String name, ByteSource source) { + name = name.replace(" ", "%20"); + + try { + final URI target = URI.create(uri.toString() + "/" + name); + final URL ftpUrl = new URL(String.format("ftp://%s:%s@%s:%d/%s/%s;type=i", username, password, host, port, path, name)); + final URLConnection connection = ftpUrl.openConnection(); + + try (InputStream in = source.openStream()) { + try (OutputStream out = connection.getOutputStream()) { + ByteStreams.copy(in, out); + } + } + + return target; + } catch (final IOException exception) { + throw new RuntimeException(exception); + } + } +} diff --git a/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java b/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java index aa67bf0..a028a30 100644 --- a/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java +++ b/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java @@ -6,11 +6,19 @@ import java.util.function.Function; import com.google.gson.JsonObject; import net.monarchpass.piecannon.Server; +import net.monarchpass.piecannon.impl.FtpServer; import net.monarchpass.piecannon.impl.SftpServer; public class ServerFactory implements Function { public Server apply (final JsonObject object) { - return makeSftpServer(object); + final String type = object.getAsJsonPrimitive("type").getAsString(); + if (type.equalsIgnoreCase("ftp")) { + return makeFtpServer(object); + } else if (type.equalsIgnoreCase("sftp")) { + return makeSftpServer(object); + } + + throw new IllegalArgumentException("Invalid server type: " + type); } private Server makeSftpServer (final JsonObject object) { @@ -27,4 +35,19 @@ public class ServerFactory implements Function { path, URI.create(url) ); } + + private Server makeFtpServer (final JsonObject object) { + final String host = object.getAsJsonPrimitive("host").getAsString(); + final String label = object.has("label") ? object.getAsJsonPrimitive("label").getAsString() : host; + final int port = object.has("port") ? object.getAsJsonPrimitive("port").getAsInt() : 21; + final String username = object.getAsJsonPrimitive("username").getAsString(); + final String password = object.getAsJsonPrimitive("password").getAsString(); + final String path = object.getAsJsonPrimitive("path").getAsString(); + final String url = object.getAsJsonPrimitive("url").getAsString(); + + return new FtpServer( + label, host, port, username, password, + path, URI.create(url) + ); + } } diff --git a/servers.example.json b/servers.example.json index 2579c1b..c4d4a1b 100644 --- a/servers.example.json +++ b/servers.example.json @@ -1,4 +1,5 @@ [{ + "type": "ftp", "host": "example.com", "username": "username", "password": "password",