commit initial version of PieCannon library and desktop app.
Documentation is sparse right now, I'm working on getting the desktop and android apps working first.
This commit is contained in:
parent
8790054c64
commit
569e174b78
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
target
|
@ -0,0 +1,9 @@
|
||||
# Project Pie Cannon
|
||||
Pie Cannon is an easy way to upload files to the internet and get a shareable link. File goes in, link comes out.
|
||||
|
||||
It doesn't come with a backend because you're expected to bring your own. A plain old FTP/SFTP+HTTP server will work fine, but support for more backends is on the way.
|
||||
|
||||
This project is separated into a library and a desktop application (targeting mainly GNU/Linux), with an Android application in the works.
|
||||
|
||||
## How to use
|
||||
TODO
|
3
desktop/piecannon
Executable file
3
desktop/piecannon
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
RESULT=$(mvn -B exec:java -Dexec.mainClass=net.monarchpass.piecannon.App -Dexec.arguments=$1 -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN | tail -n 1)
|
||||
xdg-open $RESULT
|
67
desktop/pom.xml
Normal file
67
desktop/pom.xml
Normal file
@ -0,0 +1,67 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.monarchpass</groupId>
|
||||
<artifactId>piecannon-desktop-app</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.monarchpass</groupId>
|
||||
<artifactId>libpiecannon</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>30.0-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kothar</groupId>
|
||||
<artifactId>xdg-java</artifactId>
|
||||
<version>0.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.16</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.7.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.truth</groupId>
|
||||
<artifactId>truth</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
84
desktop/src/main/java/net/monarchpass/piecannon/App.java
Normal file
84
desktop/src/main/java/net/monarchpass/piecannon/App.java
Normal file
@ -0,0 +1,84 @@
|
||||
package net.monarchpass.piecannon;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.freedesktop.BaseDirectory;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import lombok.extern.java.Log;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@Log
|
||||
public class App {
|
||||
public static void main (final String... args) throws Exception {
|
||||
final File serversJson = getServersJson();
|
||||
final List<Server> servers = loadServersFrom(serversJson);
|
||||
log.log(Level.INFO, "{0} servers loaded from {1}", new Object[] {
|
||||
servers.size(), serversJson
|
||||
});
|
||||
|
||||
if (servers.isEmpty()) {
|
||||
log.log(Level.SEVERE, "No servers defined, please define at least one in {0}", serversJson);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
final Server server = servers.get(new Random().nextInt(servers.size()));
|
||||
log.log(Level.INFO, "Randomly selected server: {0}", server.getLabel());
|
||||
|
||||
if (args.length == 0) {
|
||||
log.log(Level.SEVERE, "No filename provided");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
final File source = new File(args[0]);
|
||||
if (!source.exists()) {
|
||||
log.log(Level.SEVERE, "No such file: {0}", source);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
final URI result = server.upload(source);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
public static List<Server> loadServersFrom (final File serversJson) throws IOException {
|
||||
if (!serversJson.exists()) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
final ServerFactory factory = new ServerFactory();
|
||||
try (final InputStream in = new FileInputStream(serversJson)) {
|
||||
final JsonParser parser = new JsonParser();
|
||||
return Streams.stream(parser.parse(new InputStreamReader(in)).getAsJsonArray())
|
||||
.filter(JsonElement::isJsonObject)
|
||||
.map(JsonObject.class::cast)
|
||||
.map(factory)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
public static File getServersJson () {
|
||||
return new File(getDataDirectory(), "servers.json");
|
||||
}
|
||||
|
||||
public static File getDataDirectory () {
|
||||
return new File(BaseDirectory.get(BaseDirectory.XDG_DATA_HOME), "piecannon");
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package net.monarchpass.piecannon;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.monarchpass.piecannon.impl.SftpServer;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
public class ServerFactory implements Function<JsonObject, Server> {
|
||||
public Server apply (final JsonObject object) {
|
||||
return makeSftpServer(object);
|
||||
}
|
||||
|
||||
private Server makeSftpServer (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() : 22;
|
||||
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 SftpServer(
|
||||
label, host, port, username, password,
|
||||
path, URI.create(url)
|
||||
);
|
||||
}
|
||||
}
|
10
desktop/src/test/java/net/monarchpass/piecannon/AppTest.java
Normal file
10
desktop/src/test/java/net/monarchpass/piecannon/AppTest.java
Normal file
@ -0,0 +1,10 @@
|
||||
package net.monarchpass.piecannon;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
public class AppTest {
|
||||
@Test
|
||||
public void test () throws Exception {}
|
||||
}
|
57
lib/pom.xml
Normal file
57
lib/pom.xml
Normal file
@ -0,0 +1,57 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.monarchpass</groupId>
|
||||
<artifactId>libpiecannon</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.mwiede</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.60</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>30.0-android</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.16</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.7.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.truth</groupId>
|
||||
<artifactId>truth</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
39
lib/src/main/java/net/monarchpass/piecannon/PieCannon.java
Normal file
39
lib/src/main/java/net/monarchpass/piecannon/PieCannon.java
Normal file
@ -0,0 +1,39 @@
|
||||
package net.monarchpass.piecannon;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.CharSource;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
public class PieCannon {
|
||||
private final List<Server> servers = new ArrayList<>();
|
||||
|
||||
public void addServer (final Server server) {
|
||||
servers.add(server);
|
||||
}
|
||||
|
||||
public List<Server> getServers () {
|
||||
return Collections.unmodifiableList(servers);
|
||||
}
|
||||
|
||||
public static boolean testServer (final Server server) {
|
||||
final String testString = "piecannon-test-" + System.currentTimeMillis();
|
||||
final URI result = server.upload("piecannon.test", CharSource.wrap(testString).asByteSource(Charsets.UTF_8));
|
||||
|
||||
try (final InputStream in = result.toURL().openStream()) {
|
||||
return new String(ByteStreams.toByteArray(in), Charsets.UTF_8).equals(testString);
|
||||
} catch (final IOException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
12
lib/src/main/java/net/monarchpass/piecannon/Server.java
Normal file
12
lib/src/main/java/net/monarchpass/piecannon/Server.java
Normal file
@ -0,0 +1,12 @@
|
||||
package net.monarchpass.piecannon;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.io.ByteSource;
|
||||
|
||||
public interface Server {
|
||||
public String getLabel ();
|
||||
public URI upload (String name, ByteSource source);
|
||||
public default URI upload (File file) {return upload(file.getName(), Files.asByteSource(file));}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package net.monarchpass.piecannon.impl;
|
||||
|
||||
import net.monarchpass.piecannon.Server;
|
||||
import com.google.common.io.ByteSource;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.jcraft.jsch.Channel;
|
||||
import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.SftpException;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SftpServer 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) {
|
||||
try {
|
||||
final JSch jsch = new JSch();
|
||||
final Session session = jsch.getSession(username, host, port);
|
||||
session.setPassword(password);
|
||||
session.setConfig("StrictHostKeyChecking", "no");
|
||||
session.connect();
|
||||
|
||||
final Channel channel = session.openChannel("sftp");
|
||||
channel.connect();
|
||||
|
||||
final ChannelSftp sftp = (ChannelSftp) channel;
|
||||
sftp.cd(path);
|
||||
|
||||
try (InputStream in = source.openStream()) {
|
||||
sftp.put(in, name);
|
||||
}
|
||||
|
||||
session.disconnect();
|
||||
return URI.create(uri.toString() + "/" + name);
|
||||
} catch (final JSchException | IOException | SftpException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
30
lib/src/test/java/net/monarchpass/piecannon/SftpTest.java
Normal file
30
lib/src/test/java/net/monarchpass/piecannon/SftpTest.java
Normal file
@ -0,0 +1,30 @@
|
||||
package net.monarchpass.piecannon;
|
||||
|
||||
import java.net.URI;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import net.monarchpass.piecannon.impl.SftpServer;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
public class SftpTest {
|
||||
@Test
|
||||
public void test () throws Exception {
|
||||
final String testServerHost = System.getProperty("piecannon.test.host");
|
||||
if (testServerHost == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String testServerUser = System.getProperty("piecannon.test.user");
|
||||
final String testServerPassword = System.getProperty("piecannon.test.password");
|
||||
final String testServerPath = System.getProperty("piecannon.test.path");
|
||||
final String testServerURL = System.getProperty("piecannon.test.url");
|
||||
|
||||
final Server server = new SftpServer(
|
||||
"Test Server Instance", testServerHost, 22,
|
||||
testServerUser, testServerPassword, testServerPath,
|
||||
URI.create(testServerURL)
|
||||
);
|
||||
|
||||
assertThat(PieCannon.testServer(server)).isTrue();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user