From c0cb1b4f2efa09f99dcb9d0b7120373645a1f334 Mon Sep 17 00:00:00 2001 From: Adrian Malacoda Date: Sun, 13 Dec 2020 21:04:03 -0600 Subject: [PATCH 1/2] lib: add GoFile server type. Note this isn't as useful as a direct file upload because GoFile forces clients to visit a page before accessing the file, meaning e.g. the file won't embed in a chat service. Also included is "ByteSourceUploadable" which wraps a Guava ByteSource as a jodd-http Uploadable, so that we can implement multipart-upload services as appropriate. --- lib/.factorypath | 3 ++ lib/pom.xml | 5 ++ .../piecannon/impl/GoFileServer.java | 46 ++++++++++++++++ .../piecannon/util/ByteSourceUploadable.java | 54 +++++++++++++++++++ .../piecannon/util/ServerFactory.java | 9 +++- .../net/monarchpass/piecannon/GoFileTest.java | 27 ++++++++++ 6 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 lib/src/main/java/net/monarchpass/piecannon/impl/GoFileServer.java create mode 100644 lib/src/main/java/net/monarchpass/piecannon/util/ByteSourceUploadable.java create mode 100644 lib/src/test/java/net/monarchpass/piecannon/GoFileTest.java diff --git a/lib/.factorypath b/lib/.factorypath index 5f3fa78..f3afc51 100644 --- a/lib/.factorypath +++ b/lib/.factorypath @@ -7,5 +7,8 @@ + + + diff --git a/lib/pom.xml b/lib/pom.xml index 8ecedbf..2d644c1 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -27,6 +27,11 @@ gson 2.8.6 + + org.jodd + jodd-http + 6.0.3 + org.projectlombok lombok diff --git a/lib/src/main/java/net/monarchpass/piecannon/impl/GoFileServer.java b/lib/src/main/java/net/monarchpass/piecannon/impl/GoFileServer.java new file mode 100644 index 0000000..d940452 --- /dev/null +++ b/lib/src/main/java/net/monarchpass/piecannon/impl/GoFileServer.java @@ -0,0 +1,46 @@ +package net.monarchpass.piecannon.impl; + +import java.net.URI; +import java.util.Map; + +import com.google.common.io.ByteSource; +import com.google.gson.Gson; + +import jodd.http.HttpRequest; +import lombok.Data; +import net.monarchpass.piecannon.Server; +import net.monarchpass.piecannon.util.ByteSourceUploadable; + +@Data +public class GoFileServer implements Server { + public static final String DEFAULT_HOST = "gofile.io"; + public static final String DEFAULT_API_HOST = "apiv2." + DEFAULT_HOST; + + private final Gson gson = new Gson(); + private final String label; + private String host = DEFAULT_HOST; + private String apiHost = DEFAULT_API_HOST; + + @Override + public URI upload (String name, ByteSource source) { + Response response = request(HttpRequest.get(String.format("https://%s/getServer", apiHost))); + + final String serverId = (String)response.getData().get("server"); + response = request(HttpRequest.post(String.format("https://%s.%s/uploadFile", serverId, host)) + .form("file", new ByteSourceUploadable(name, source))); + + final String code = (String)response.getData().get("code"); + final URI uri = URI.create(String.format("https://%s/d/%s", host, code)); + return uri; + } + + private Response request (final HttpRequest request) { + return gson.fromJson(request.send().bodyText(), Response.class); + } + + @Data + public static class Response { + public final String status; + public final Map data; + } +} diff --git a/lib/src/main/java/net/monarchpass/piecannon/util/ByteSourceUploadable.java b/lib/src/main/java/net/monarchpass/piecannon/util/ByteSourceUploadable.java new file mode 100644 index 0000000..edeb660 --- /dev/null +++ b/lib/src/main/java/net/monarchpass/piecannon/util/ByteSourceUploadable.java @@ -0,0 +1,54 @@ +package net.monarchpass.piecannon.util; + +import java.io.IOException; +import java.io.InputStream; + +import com.google.common.io.ByteSource; + +import jodd.http.HttpException; +import jodd.http.upload.Uploadable; +import lombok.Data; + +@Data +public class ByteSourceUploadable implements Uploadable { + private final String fileName; + private final ByteSource source; + + @Override + public ByteSource getContent () { + return source; + } + + @Override + public byte[] getBytes () { + try { + return source.read(); + } catch (final IOException exception) { + throw new HttpException(exception); + } + } + + @Override + public String getFileName () { + return fileName; + } + + @Override + public String getMimeType () { + return null; + } + + @Override + public int getSize () { + try { + return (int) source.size(); + } catch (final IOException exception) { + throw new HttpException(exception); + } + } + + @Override + public InputStream openInputStream () throws IOException { + return source.openStream(); + } +} 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 a028a30..90adba5 100644 --- a/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java +++ b/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java @@ -1,18 +1,23 @@ package net.monarchpass.piecannon.util; import java.net.URI; - +import java.util.Optional; import java.util.function.Function; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + import net.monarchpass.piecannon.Server; import net.monarchpass.piecannon.impl.FtpServer; +import net.monarchpass.piecannon.impl.GoFileServer; import net.monarchpass.piecannon.impl.SftpServer; public class ServerFactory implements Function { public Server apply (final JsonObject object) { final String type = object.getAsJsonPrimitive("type").getAsString(); - if (type.equalsIgnoreCase("ftp")) { + if (type.equalsIgnoreCase("gofile")) { + return new GoFileServer(Optional.ofNullable(object.getAsJsonPrimitive("label")).map(JsonPrimitive::getAsString).orElse("GoFile")); + } else if (type.equalsIgnoreCase("ftp")) { return makeFtpServer(object); } else if (type.equalsIgnoreCase("sftp")) { return makeSftpServer(object); diff --git a/lib/src/test/java/net/monarchpass/piecannon/GoFileTest.java b/lib/src/test/java/net/monarchpass/piecannon/GoFileTest.java new file mode 100644 index 0000000..7894d67 --- /dev/null +++ b/lib/src/test/java/net/monarchpass/piecannon/GoFileTest.java @@ -0,0 +1,27 @@ +package net.monarchpass.piecannon; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.logging.Level; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import lombok.extern.java.Log; +import net.monarchpass.piecannon.impl.GoFileServer; + +@Log +public class GoFileTest { + @Test + @Disabled + public void test () throws Exception { + try { + System.setProperty("https.protocols", "TLSv1.2"); + final GoFileServer server = new GoFileServer("GoFileTest"); + assertThat(PieCannon.testServer(server)).isTrue(); + } catch (final Exception exception) { + log.log(Level.SEVERE, "", exception); + throw exception; + } + } +} From 6ed87b738fa87a1aff9554fef27693e173b7d2c9 Mon Sep 17 00:00:00 2001 From: Adrian Malacoda Date: Sun, 13 Dec 2020 22:03:18 -0600 Subject: [PATCH 2/2] lib: Add WebDav server type, make this the default server type (since it's relatively simple, standardized, and requires the least configuration). --- .../piecannon/util/ServerFactory.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) 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 90adba5..bee6931 100644 --- a/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java +++ b/lib/src/main/java/net/monarchpass/piecannon/util/ServerFactory.java @@ -11,11 +11,17 @@ import net.monarchpass.piecannon.Server; import net.monarchpass.piecannon.impl.FtpServer; import net.monarchpass.piecannon.impl.GoFileServer; import net.monarchpass.piecannon.impl.SftpServer; +import net.monarchpass.piecannon.impl.WebDavServer; public class ServerFactory implements Function { public Server apply (final JsonObject object) { - final String type = object.getAsJsonPrimitive("type").getAsString(); - if (type.equalsIgnoreCase("gofile")) { + final String type = Optional.ofNullable(object.getAsJsonPrimitive("type")) + .map(JsonPrimitive::getAsString) + .orElse("webdav"); + + if (type.equals("webdav")) { + return makeWebDavServer(object); + } else if (type.equalsIgnoreCase("gofile")) { return new GoFileServer(Optional.ofNullable(object.getAsJsonPrimitive("label")).map(JsonPrimitive::getAsString).orElse("GoFile")); } else if (type.equalsIgnoreCase("ftp")) { return makeFtpServer(object); @@ -23,9 +29,26 @@ public class ServerFactory implements Function { return makeSftpServer(object); } - throw new IllegalArgumentException("Invalid server type: " + type); + throw new IllegalArgumentException("Invalid server type: " + type); } + private Server makeWebDavServer (final JsonObject object) { + final String label = Optional.ofNullable(object.getAsJsonPrimitive("label")) + .map(JsonPrimitive::getAsString) + .orElse("WebDav"); + final String username = Optional.ofNullable(object.getAsJsonPrimitive("username")) + .map(JsonPrimitive::getAsString) + .orElse(null); + final String password = Optional.ofNullable(object.getAsJsonPrimitive("password")) + .map(JsonPrimitive::getAsString) + .orElse(null); + final String url = object.getAsJsonPrimitive("url").getAsString(); + + return new WebDavServer( + label, URI.create(url), username, password + ); + } + private Server makeSftpServer (final JsonObject object) { final String host = object.getAsJsonPrimitive("host").getAsString(); final String label = object.has("label") ? object.getAsJsonPrimitive("label").getAsString() : host;