diff --git a/.gitignore b/.gitignore
index 2353a94..61baa9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,8 +63,12 @@ genTwitterTokens/classes/generatetwittertokens
.idea
out/
*.iml
+target/
# Netbeans Project files
nbproject
# Eclipse Project files
+
+
+*access*
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d030dd2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+## NGINX Reverse Config
+ server {
+ listen 80;
+ listen [::]:80;
+ server_name paste.mc8051.de;
+
+ root /var/www/html/;
+ index index.html index.php index.htm;
+
+ client_max_body_size 25m;
+
+ ## Definition Reverse Proxy ##
+ location / {
+ proxy_pass http://127.0.0.1:8080/;
+ proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
+ proxy_redirect off;
+ proxy_buffering off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+ }
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..06c2bdf
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,90 @@
+
+
+ 4.0.0
+
+ de.gurkengewuerz
+ termbin
+ 1.0-SNAPSHOT
+
+
+
+ MIT License
+ https://opensource.org/licenses/MIT
+ repo
+
+
+
+
+
+ Gurkengewuerz
+ admin@gurkengewuerz.de
+ https://gurkengewuerz.de
+ Europe/Berlin
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-server
+ 9.4.3.v20170317
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.16.1
+
+
+ org.json
+ json
+ 20160810
+
+
+ org.apache.commons
+ commons-lang3
+ 3.5
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.5.1
+
+
+ 1.8
+
+
+
+ maven-assembly-plugin
+ 2.6
+
+ false
+ ${project.artifactId}
+
+
+ jar-with-dependencies
+
+
+
+
+ ${project.groupId}.${project.artifactId}.Termbin
+
+
+
+
+
+ assamble
+
+ single
+
+ package
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/de/gurkengewuerz/termbin/Config.java b/src/main/java/de/gurkengewuerz/termbin/Config.java
similarity index 83%
rename from src/de/gurkengewuerz/termbin/Config.java
rename to src/main/java/de/gurkengewuerz/termbin/Config.java
index 5bf1c85..87291fe 100644
--- a/src/de/gurkengewuerz/termbin/Config.java
+++ b/src/main/java/de/gurkengewuerz/termbin/Config.java
@@ -20,8 +20,12 @@ import java.util.logging.Logger;
*/
public class Config extends JSONObject {
private File file;
- private static List ban = new ArrayList<>();
- private static List whitelist = new ArrayList<>();
+ private List ban = new ArrayList<>();
+ private List whitelist = new ArrayList<>();
+
+ private JSONObject uploadServerConf;
+ private JSONObject dataServerConf;
+ private JSONObject apiServerConf;
public Config(File file) throws IOException {
this.file = file;
@@ -38,9 +42,11 @@ public class Config extends JSONObject {
throw new AccessDeniedException(file.getAbsolutePath() + " is not accessable");
}
- this.put("log", "termvin.log");
+ this.put("accesslog", "access");
this.put("database", "db.sqlite3");
this.put("domain", "http://localhost/");
+ this.put("uploadlifetime", 24 * 7); // 1 week hours
+ this.put("maxkb", 1024 * 2); // 2 mb
JSONObject uploadserver = new JSONObject();
uploadserver.put("port", 8888);
@@ -48,7 +54,7 @@ public class Config extends JSONObject {
this.put("uploadserver", uploadserver);
JSONObject dataserver = new JSONObject();
- dataserver.put("port", 8080);
+ dataserver.put("port", 7070);
this.put("dataserver", dataserver);
JSONObject apiserver = new JSONObject();
@@ -116,7 +122,7 @@ public class Config extends JSONObject {
jt.back();
break;
case '}':
- loadRestData();
+ save();
return;
default:
throw jt.syntaxError("Expected a ',' or '}'");
@@ -140,9 +146,29 @@ public class Config extends JSONObject {
if (whitelist.contains(json_ban.getString(i))) continue;
ban.add(json_ban.getString(i));
}
+
+ uploadServerConf = getJSONObject("uploadserver");
+ dataServerConf = getJSONObject("dataserver");
+ apiServerConf = getJSONObject("apiserver");
}
public boolean isBanned(String ipv4) {
return ban.contains(ipv4);
}
+
+ public List getBans() {
+ return ban;
+ }
+
+ public JSONObject getUploadServerConfig() {
+ return uploadServerConf;
+ }
+
+ public JSONObject getDataServerConfig() {
+ return dataServerConf;
+ }
+
+ public JSONObject getApiServerConfig() {
+ return apiServerConf;
+ }
}
diff --git a/src/de/gurkengewuerz/termbin/Database.java b/src/main/java/de/gurkengewuerz/termbin/Database.java
similarity index 100%
rename from src/de/gurkengewuerz/termbin/Database.java
rename to src/main/java/de/gurkengewuerz/termbin/Database.java
diff --git a/src/de/gurkengewuerz/termbin/Server/APIHandler.java b/src/main/java/de/gurkengewuerz/termbin/Server/APIHandler.java
similarity index 92%
rename from src/de/gurkengewuerz/termbin/Server/APIHandler.java
rename to src/main/java/de/gurkengewuerz/termbin/Server/APIHandler.java
index 7c6d5f5..0e37804 100644
--- a/src/de/gurkengewuerz/termbin/Server/APIHandler.java
+++ b/src/main/java/de/gurkengewuerz/termbin/Server/APIHandler.java
@@ -24,9 +24,10 @@ public class APIHandler extends AbstractHandler {
@Override
public void handle(String s, Request request, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
- Logger.getLogger(getClass().getName()).log(Level.INFO, "API Request by " + request.getRemoteAddr() + "@" + s);
+ Logger.getLogger(getClass().getName()).log(Level.INFO, "API Request by " + request.getHeader("User-Agent") + " " + request.getRemoteAddr() + "@" + s);
+ Termbin.getAccesslog().log(Level.INFO, request.getRemoteAddr() + " - - " + request.getHeader("User-Agent") + " - " + s);
- if(Termbin.getConfig().isBanned(request.getRemoteAddr())) {
+ if (Termbin.getConfig().isBanned(request.getRemoteAddr())) {
request.setHandled(true);
Logger.getLogger(getClass().getName()).log(Level.INFO, "API Request by " + request.getRemoteAddr() + "@" + s + " closed BANNED");
return;
@@ -53,7 +54,7 @@ public class APIHandler extends AbstractHandler {
int n = httpServletRequest.getInputStream().read(buff);
if (n < 0) break;
baos.write(buff, 0, n);
- if (baos.size() > 1024 * 1024 * 2) {// 2 MB
+ if (baos.size() > 1024 * Termbin.getConfig().getInt("maxkb")) {
breaked = true;
returnObject.put("error", "File too big");
Logger.getLogger(getClass().getName()).log(Level.INFO, "API Request by " + request.getRemoteAddr() + "@" + s + " closed FILE TOO BIG");
diff --git a/src/de/gurkengewuerz/termbin/Server/DataHandler.java b/src/main/java/de/gurkengewuerz/termbin/Server/DataHandler.java
similarity index 84%
rename from src/de/gurkengewuerz/termbin/Server/DataHandler.java
rename to src/main/java/de/gurkengewuerz/termbin/Server/DataHandler.java
index c9057e5..f35f4e5 100644
--- a/src/de/gurkengewuerz/termbin/Server/DataHandler.java
+++ b/src/main/java/de/gurkengewuerz/termbin/Server/DataHandler.java
@@ -21,7 +21,8 @@ public class DataHandler extends AbstractHandler {
@Override
public void handle(String s, Request request, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
- Logger.getLogger(getClass().getName()).log(Level.INFO, "Request by " + request.getRemoteAddr() + "@" + s);
+ Logger.getLogger(getClass().getName()).log(Level.INFO, "API Request by " + request.getHeader("User-Agent") + " " + request.getRemoteAddr() + "@" + s);
+ Termbin.getAccesslog().log(Level.INFO, request.getRemoteAddr() + " - - " + request.getHeader("User-Agent") + " - " + s);
if (Termbin.getConfig().isBanned(request.getRemoteAddr())) {
request.setHandled(true);
@@ -37,6 +38,8 @@ public class DataHandler extends AbstractHandler {
boolean found = false;
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
while (rs.next()) {
+ if ((((System.currentTimeMillis() / 1000) - rs.getFloat("timestamp")) / 60 / 60) > Termbin.getConfig().getInt("uploadlifetime"))
+ break;
found = true;
httpServletResponse.setContentType(rs.getString("filetype"));
if (rs.getString("filetype").equals("text/plain")) {
@@ -49,12 +52,14 @@ public class DataHandler extends AbstractHandler {
if (!found) {
httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ httpServletResponse.setContentType("text/html");
httpServletResponse.getOutputStream().write("".getBytes("UTF-8"));
}
} catch (SQLException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ httpServletResponse.setContentType("text/html");
httpServletResponse.getOutputStream().write("".getBytes("UTF-8"));
}
diff --git a/src/de/gurkengewuerz/termbin/Server/UploadServer.java b/src/main/java/de/gurkengewuerz/termbin/Server/UploadServer.java
similarity index 93%
rename from src/de/gurkengewuerz/termbin/Server/UploadServer.java
rename to src/main/java/de/gurkengewuerz/termbin/Server/UploadServer.java
index 1b3b183..7402804 100644
--- a/src/de/gurkengewuerz/termbin/Server/UploadServer.java
+++ b/src/main/java/de/gurkengewuerz/termbin/Server/UploadServer.java
@@ -17,16 +17,21 @@ import java.util.logging.Logger;
*/
public class UploadServer {
+ private ServerSocket listener;
+ private int clientNumber = 1;
+
public UploadServer(String ipv4, int port) throws IOException {
Logger.getLogger("Main").log(Level.INFO, "Starting...");
- int clientNumber = 1;
- ServerSocket listener = new ServerSocket(port);
+
+ listener = new ServerSocket(port);
if (!ipv4.isEmpty() && !ipv4.equals("0.0.0.0")) {
listener.bind(new InetSocketAddress(ipv4, port));
}
Logger.getLogger(getClass().getName()).log(Level.INFO, "Started. Waiting for Clients.");
+ }
+ public void start() throws IOException {
try {
while (true) {
Socket socketOfServer = listener.accept();
@@ -53,7 +58,7 @@ public class UploadServer {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
}
Logger.getLogger(getClass().getName()).log(Level.INFO, "opened " + client + " at " + socketOfServer.getLocalAddress() + ":" + socketOfServer.getLocalPort());
-
+ Termbin.getAccesslog().log(Level.INFO, clientIP + " - - socket " + socketOfServer.getLocalPort());
if (Termbin.getConfig().isBanned(clientIP)) {
Logger.getLogger(getClass().getName()).log(Level.INFO, "closed " + client + " with error banned");
try {
@@ -77,7 +82,7 @@ public class UploadServer {
int n = socketOfServer.getInputStream().read(buff);
if (n < 0) break;
baos.write(buff, 0, n);
- if (baos.size() > 1024 * 1024 * 2) {// 2 MB
+ if (baos.size() > 1024 * Termbin.getConfig().getInt("maxkb")) {// 2 MB
Logger.getLogger(getClass().getName()).log(Level.INFO, "closed " + client + " with file to big");
os.write("File to big!");
os.newLine();
diff --git a/src/de/gurkengewuerz/termbin/Termbin.java b/src/main/java/de/gurkengewuerz/termbin/Termbin.java
similarity index 52%
rename from src/de/gurkengewuerz/termbin/Termbin.java
rename to src/main/java/de/gurkengewuerz/termbin/Termbin.java
index 3e3aaf9..a7eb108 100644
--- a/src/de/gurkengewuerz/termbin/Termbin.java
+++ b/src/main/java/de/gurkengewuerz/termbin/Termbin.java
@@ -5,14 +5,14 @@ import de.gurkengewuerz.termbin.Server.DataHandler;
import de.gurkengewuerz.termbin.Server.UploadServer;
import de.gurkengewuerz.termbin.Utils.HashUtils;
import org.eclipse.jetty.server.Server;
-import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.SQLException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.*;
/**
* Created by gurkengewuerz.de on 02.07.2017.
@@ -21,74 +21,94 @@ public class Termbin {
private static Database db;
private static Config conf;
+ private static final Logger accesslog = Logger.getLogger("Accesslog");
- public static void main(String args[]) {
- File f = new File("." + File.separator + "settings.json");
-
- try {
- conf = new Config(f);
- } catch (IOException e) {
- Logger.getLogger(Termbin.class.getName()).log(Level.SEVERE, null, e);
- System.exit(1);
+ public static void main(String args[]) throws Exception {
+ String settingsFile = "." + File.separator + "settings.json";
+ if (args.length >= 1) {
+ settingsFile = args[0];
}
+ File f = new File(settingsFile);
+
+ conf = new Config(f);
conf.load();
- try {
- db = new Database(conf.getString("database"));
- createDatabase();
- } catch (Exception e) {
- Logger.getLogger(Termbin.class.getName()).log(Level.SEVERE, null, e);
- }
+ db = new Database(conf.getString("database"));
+ createDatabase();
- Runnable uploadServerTask = () -> {
+ FileHandler fh = new FileHandler(conf.getString("accesslog") + ".%u.log", 5242880, 5, true);
+// FileHandler fh = new FileHandler(conf.getString("accesslog") + ".log", true);
+ SimpleFormatter sf = new SimpleFormatter();
+ fh.setFormatter(sf);
+ accesslog.setUseParentHandlers(false);
+ accesslog.addHandler(fh);
+
+ CountDownLatch lock = new CountDownLatch(3);
+
+ Thread uploadServerThread = new Thread(() -> {
try {
- JSONObject uploadServerConf = conf.getJSONObject("uploadserver");
- new UploadServer(uploadServerConf.getString("bind"), uploadServerConf.getInt("port"));
+ UploadServer uploadServer = new UploadServer(conf.getUploadServerConfig().getString("bind"), conf.getUploadServerConfig().getInt("port"));
+ lock.countDown();
+ uploadServer.start();
} catch (IOException e) {
Logger.getLogger(Termbin.class.getName()).log(Level.SEVERE, null, e);
}
- };
- Thread uploadServerThread = new Thread(uploadServerTask);
+ });
uploadServerThread.start();
-
- Runnable dataServerTask = () -> {
+ Thread dataServerThread = new Thread(() -> {
try {
- JSONObject dataServerConf = conf.getJSONObject("dataserver");
- Server dataServer = new Server(dataServerConf.getInt("port"));
+ Server dataServer = new Server(conf.getDataServerConfig().getInt("port"));
dataServer.setHandler(new DataHandler());
dataServer.start();
- dataServer.join();
+ lock.countDown();
} catch (Exception e) {
Logger.getLogger(Termbin.class.getName()).log(Level.SEVERE, null, e);
}
- };
- Thread dataServerThread = new Thread(dataServerTask);
+ });
dataServerThread.start();
-
- Runnable apiServerTask = () -> {
+ Thread apiServerThread = new Thread(() -> {
try {
- JSONObject apiServerConf = conf.getJSONObject("apiserver");
- Server apiServer = new Server(apiServerConf.getInt("port"));
+ Server apiServer = new Server(conf.getApiServerConfig().getInt("port"));
apiServer.setHandler(new APIHandler());
apiServer.start();
- apiServer.join();
+ lock.countDown();
} catch (Exception e) {
Logger.getLogger(Termbin.class.getName()).log(Level.SEVERE, null, e);
}
- };
- Thread apiServerThread = new Thread(apiServerTask);
+ });
apiServerThread.start();
- // TODO: Check if all threads started successfully
- // TODO: log to file
- // TODO: Arguments (Settings file)
- // TODO: print start values (all ports etc.)
- // TODO: Config Max lifetime => Check insert time on request
- // TODO: Maven
+ boolean counts = lock.await(4, TimeUnit.SECONDS);
+ if (counts) {
+ String cr = System.getProperty("line.separator");
+ String stringInfo = cr +
+ "########################################" + cr +
+ " Configfile: " + f.getAbsolutePath() + cr +
+ " Domain: " + conf.getString("domain") + cr +
+ " Upload Lifetime: " + conf.getInt("uploadlifetime") + "h" + cr +
+ " Upload Size: " + conf.getInt("maxkb") + "kb" + cr +
+ " Bans listed: " + conf.getBans().size() + cr +
+ " Accesslog: " + conf.getString("accesslog") + cr +
+ " Upload Server: " + conf.getUploadServerConfig().getString("bind") + ":" + conf.getUploadServerConfig().getInt("port") + cr +
+ " API Server: 0.0.0.0:" + conf.getApiServerConfig().getInt("port") + cr +
+ " Data Server: 0.0.0.0:" + conf.getDataServerConfig().getInt("port") + cr +
+ "########################################" + cr;
+
+ Logger.getLogger(Termbin.class.getName()).log(Level.INFO, stringInfo);
+
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ for (Handler h : accesslog.getHandlers()) {
+ h.close();
+ }
+ }));
+ } else {
+ Logger.getLogger(Termbin.class.getName()).log(Level.SEVERE, "Servers couldn't started!");
+ System.exit(1);
+ }
}
public static Database getDatabase() {
@@ -100,8 +120,12 @@ public class Termbin {
return conf;
}
+ public static Logger getAccesslog() {
+ return accesslog;
+ }
+
public static String upload(String ip, String text, byte[] rawData, FileType fileType) throws SQLException {
- String answerID = HashUtils.getSha256(System.currentTimeMillis() + "").substring(0, 8);
+ String answerID = HashUtils.getSha256(System.currentTimeMillis() + ip).substring(0, 8);
PreparedStatement ps = getDatabase().getPreparedStatement("INSERT INTO data (uniqueid, timestamp, fromClient, filetype, text, rawData) VALUES (?, ?, ?, ?, ?, ?);");
ps.setString(1, answerID);
ps.setInt(2, (int) (System.currentTimeMillis() / 1000));
@@ -110,9 +134,12 @@ public class Termbin {
if (fileType.equals(FileType.TXT)) {
ps.setString(5, text);
ps.setBytes(6, null);
+ getAccesslog().log(Level.INFO, ip + " - - upload with text " + " id#" + answerID);
+
} else {
ps.setString(5, null);
ps.setBytes(6, rawData);
+ getAccesslog().log(Level.INFO, ip + "upload with " + rawData.length + " bytes " + " id#" + answerID);
}
ps.execute();
diff --git a/src/de/gurkengewuerz/termbin/Utils/HashUtils.java b/src/main/java/de/gurkengewuerz/termbin/Utils/HashUtils.java
similarity index 100%
rename from src/de/gurkengewuerz/termbin/Utils/HashUtils.java
rename to src/main/java/de/gurkengewuerz/termbin/Utils/HashUtils.java
diff --git a/src/de/gurkengewuerz/termbin/Utils/ImageUtils.java b/src/main/java/de/gurkengewuerz/termbin/Utils/ImageUtils.java
similarity index 100%
rename from src/de/gurkengewuerz/termbin/Utils/ImageUtils.java
rename to src/main/java/de/gurkengewuerz/termbin/Utils/ImageUtils.java
diff --git a/src/de/gurkengewuerz/termbin/Utils/SQLInjectionEscaper.java b/src/main/java/de/gurkengewuerz/termbin/Utils/SQLInjectionEscaper.java
similarity index 100%
rename from src/de/gurkengewuerz/termbin/Utils/SQLInjectionEscaper.java
rename to src/main/java/de/gurkengewuerz/termbin/Utils/SQLInjectionEscaper.java