Initial commit

This commit is contained in:
2022-04-28 19:41:28 +02:00
commit 691021ca70
274 changed files with 8929 additions and 0 deletions

View File

@ -0,0 +1,58 @@
package org.blueshard.olymp;
import org.apache.log4j.Logger;
import org.blueshard.olymp.exception.FatalIOException;
import org.blueshard.olymp.logging.EmptyLogger;
import org.blueshard.olymp.logging.ServerLogger;
import org.blueshard.olymp.register_code.RegisterCode;
import org.blueshard.olymp.server.MainServer;
import org.blueshard.olymp.sql.SQL;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
public class Main {
private static Connection connection = new SQL().getConnection();
public Logger root = new EmptyLogger().getLogger();
public static void main(String[] args) throws IOException, SQLException {
if (args.length == 1) {
String command = args[0].strip().toLowerCase();
if (command.equals("sql")) {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
Connection connection = getConnection();
String SQLQuery;
while (true) {
System.out.print("SQL Query: ");
SQLQuery = input.readLine().strip().toUpperCase();
if (SQLQuery.equals("EXIT")) {
break;
} else {
connection.createStatement().executeQuery(SQLQuery);
}
}
} else if (command.equals("add registercode")) {
try {
RegisterCode.generateNewRegisterCode();
} catch (FatalIOException e) {
e.printStackTrace();
}
}
} else {
MainServer server = new MainServer(8269, new ServerLogger().main());
server.start();
connection.close();
}
}
public static Connection getConnection() {
return connection;
}
}

View File

@ -0,0 +1,20 @@
package org.blueshard.olymp.cli;
import org.blueshard.olymp.exception.FatalIOException;
import org.blueshard.olymp.register_code.RegisterCode;
import java.io.IOException;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) throws IOException, FatalIOException, SQLException {
switch (args[0].strip()) {
case "start":
org.blueshard.olymp.Main.main(new String[0]);
case "add register code":
RegisterCode.generateNewRegisterCode();
}
}
}

View File

@ -0,0 +1,15 @@
package org.blueshard.olymp.cli;
import javax.net.SocketFactory;
import java.io.IOException;
import java.net.Socket;
public class SQLCli {
public static void main(String[] args) throws IOException {
Socket server = SocketFactory.getDefault().createSocket("localhost", 8269);
}
}

View File

@ -0,0 +1,166 @@
package org.blueshard.olymp.data;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class Data {
private String dataAsString;
private Map<String, String> data = new HashMap<>();
public Data(String data) {
this.dataAsString = data;
String key = "";
String dataString = dataAsString;
String separator = getSeparator();
try {
if (separator.length() == 1) {
dataString = dataString.substring(dataString.indexOf(",")).strip();
} else {
dataString = dataString.substring(dataString.indexOf(",") + 1).strip();
}
} catch (StringIndexOutOfBoundsException e) {
dataString = "";
}
for (String string: dataString.split(separator)) {
string = string.strip();
if (string.equals(":") || string.equals(",") || string.equals("{") || string.equals("}")) {
continue;
} else if (key.isEmpty()) {
key = string;
} else {
this.data.put(key, string);
key = "";
}
}
}
public int getCode() {
int lenBeforeCode = 1 + getSeparator().length() + 1;
return Integer.parseInt(dataAsString.substring(lenBeforeCode, lenBeforeCode + DataCodes.DATACODESLENGHT));
}
public Map<String, String> getData() {
return data;
}
public String getDataAsString() {
return dataAsString;
}
public String getFromData(String key) {
return data.get(key);
}
private String getSeparator() {
return dataAsString.substring(1).split(":")[0];
}
public static class Builder {
private Map<String, String> data = new HashMap<>();
private int code;
public Builder(int code) {
this.code = code;
}
public String createData() {
String separator = createSeparator();
StringBuilder dataAsString = new StringBuilder("{" + separator + ":" + code);
data.forEach((key, value) -> dataAsString.append(",")
.append(separator)
.append(key)
.append(separator)
.append(":")
.append(separator)
.append(value)
.append(separator));
dataAsString.append("}");
return dataAsString.toString();
}
public String createSeparator() {
char choice;
StringBuilder stringBuilder = new StringBuilder();
String indicator = "'";
char[] choices = {'\'', '"', '^'};
data.forEach((key, value) -> stringBuilder.append(key).append(value));
String string = stringBuilder.toString();
while (true) {
if (string.contains(indicator)) {
switch (indicator) {
case "'":
indicator = "\"";
break;
case "\"":
indicator = "^";
break;
default:
{
choice = choices[new Random().nextInt(choices.length) - 1];
if (indicator.contains("|")) {
String[] splitted_indicator = indicator.split("\\|");
indicator = splitted_indicator[0] + choice + '|' + choice + splitted_indicator[1];
} else {
indicator = indicator + choice + '|' + choice + indicator;
}
}
}
} else {
return indicator;
}
}
}
public void addData(String key, String value) {
this.data.put(key, value);
}
public void addAllData(Map<String, String> allData) {
this.data.putAll(allData);
}
public int getCode() {
return code;
}
public Data getData() {
return new Data(getDataAsString());
}
public Map<String, String> getDataMap() {
return data;
}
public String getDataAsString() {
return createData();
}
}
public static boolean isDataString(String string) {
try {
string = string.strip();
if (string.startsWith("{") && string.endsWith("}") && string.contains(":")) {
String separator = string.substring(1).split(":")[0];
int lenBeforeCode = 1 + separator.length() + 1;
Integer.parseInt(string.substring(lenBeforeCode, lenBeforeCode + DataCodes.DATACODESLENGHT));
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
}

View File

@ -0,0 +1,156 @@
package org.blueshard.olymp.data;
public class DataCodes {
public static final int DATACODESLENGHT = 5;
public static class Client {
public static final int UNEXPECTEDERROR = 56400;
public static final int UNEXPECTEDEXIT = 95078;
public static final int CLOSE = 69826;
public static final int FIRSTCONNECT = 19938;
public static final int PUBLICKEY = 19294;
public static final int UPDATEYES = 80515;
public static final int UPDATENO = 38510;
public static final int LOGIN = 39208;
public static final int REGISTERCODE = 18981;
public static final int REGISTER = 84219;
public static final int GETFILESDATA = 28926;
public static final int GETFILE = 95868;
public static final int SENDFILE = 53639;
}
public static class Server {
public static final int UNEXPECTEDERROR = 29875;
public static final int UNEXPECTEDEXIT = 85048;
public static final int NOTLOGGEDIN = 77015;
public static final int CLOSE = 42812;
public static final int READY = 86670;
public static final int FIRSTCONNECT = 76896;
public static final int PUBLICKEY = 19294;
public static final int OPTIONALUPDATE = 12925;
public static final int REQUIREDUPDATE = 97103;
public static final int LOGINFAIL = 11868;
public static final int LOGINSUCCESS = 54151;
public static final int REGISTERCODE_EXIST = 31166;
public static final int REGISTERCODE_NOT_EXIST = 47648;
public static final int REGISTERFAIL = 52300;
public static final int REGISTERFAIL_USER_EXIST= 77444;
public static final int REGISTERSUCCESS = 34367;
public static final int RECEIVEFILEFAIL = 45747;
public static final int RECEIVEFILESUCCESS = 75368;
public static final int SENDFILESDATA = 78946;
public static final int SENDFILEFAIL = 90173;
public static final int SENDFILESSUCCESS = 37272;
}
public static class Params {
public static class CheckSum {
public static final String MD5 = "md5";
}
public static class ClientAgent {
public static final String CLIENTAGENT = "clientAgent";
public static final String VALIDAGENT = "validAgent";
public static final String THEOSUI = "theosUI";
}
public static class File {
public static final String STARTDIRECOTRY = "startDirectory";
public static final String FILEPATH = "filepath";
}
public static class Key {
public static final String PUBLICKEY = "key";
}
public static class LogLevel {
public static final String LOGLEVEL = "logLevel";
public static final String ALL = "0";
public static final String WARNING = "1";
public static final String NOTHING = "2";
}
public static class LogReg {
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
public static final String SALT = "salt";
public static final String EMAIL = "email";
}
public static class RegisterCode {
public static final String REGISTERCODE = "registerCode";
}
public static class Update {
public static final String UPDATE = "update";
public static final String NEWVERSION = "newVersion";
public static final String CHANGES = "changes";
}
public static class UserLevel {
public static final String USERLEVEL = "userLevel";
public static final String PUBLIC = "0";
public static final String PROTECTED = "1";
public static final String PRIVATE = "2";
}
public static class State {
public static final String STATE = "state";
public static final String ACTIVE = "active";
public static final String DISABLED = "disabled";
}
public static class Version {
public static final String VERSION = "version";
}
}
}

View File

@ -0,0 +1,48 @@
package org.blueshard.olymp.e2ee;
import org.blueshard.olymp.exception.UnexpectedException;
import org.blueshard.olymp.utils.ExceptionUtils;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class AESCipher {
private static final int keySize = 256;
public static byte[] generateKey() throws UnexpectedException {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(keySize);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
} catch (NoSuchAlgorithmException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
public static byte[] encrypt(byte[] input, byte[] key) throws UnexpectedException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
try {
SecretKey secretKey = new SecretKeySpec(key, 0, key.length, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(input);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new UnexpectedException(e);
}
}
public static byte[] decrypt(byte[] input, byte[] key) throws UnexpectedException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
try {
SecretKey secretKey = new SecretKeySpec(key, 0, key.length, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(input);
} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
throw new UnexpectedException(e);
}
}
}

View File

@ -0,0 +1,36 @@
package org.blueshard.olymp.e2ee;
import org.blueshard.olymp.exception.UnexpectedException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
public class E2EEConverter {
private final static String separator = "@";
public static String decrypt(String input, byte[] privateKey) throws UnexpectedException, BadPaddingException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException {
String[] inputAsArray = input.split(separator);
String key = inputAsArray[0];
String realInput = inputAsArray[1];
byte[] AESKey = RSACipher.decrypt(Base64.getDecoder().decode(key), privateKey);
return new String(AESCipher.decrypt(Base64.getDecoder().decode(realInput), AESKey));
}
public static String encrypt(String input, byte[] publicKey) throws UnexpectedException, BadPaddingException, InvalidKeyException, IllegalBlockSizeException, InvalidKeySpecException {
byte[] AESKey = AESCipher.generateKey();
String encryptedKey = Base64.getEncoder().encodeToString(RSACipher.encrypt(AESKey, publicKey));
String encryptedInput = Base64.getEncoder().encodeToString(AESCipher.encrypt(input.getBytes(StandardCharsets.UTF_8), AESKey));
return encryptedKey + separator + encryptedInput;
}
}

View File

@ -0,0 +1,57 @@
package org.blueshard.olymp.e2ee;
import org.blueshard.olymp.exception.UnexpectedException;
import org.blueshard.olymp.utils.ExceptionUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSACipher {
private static final int keySize = 2048;
public static KeyPair generateKeyPair() throws UnexpectedException {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
public static byte[] encrypt(byte[] key, byte[] publicKey) throws UnexpectedException, InvalidKeyException, InvalidKeySpecException, BadPaddingException {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
RSAPublicKey publicRSAKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicRSAKey);
return cipher.doFinal(key);
} catch (NoSuchAlgorithmException | IllegalBlockSizeException | NoSuchPaddingException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
public static byte[] decrypt(byte[] key, byte[] privateKey) throws UnexpectedException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, BadPaddingException {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privatePKCS8Key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privatePKCS8Key);
return cipher.doFinal(key);
} catch (NoSuchAlgorithmException | IllegalBlockSizeException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
}

View File

@ -0,0 +1,24 @@
package org.blueshard.olymp.exception;
import java.util.HashSet;
import java.util.Set;
public class ErrorCodes {
public final static int couldnt_create_userfiles_folder = 293;
public final static int couldnt_delete_userfiles_folder = 219;
public final static int couldnt_delete_custom_user_directory = 383;
public final static int couldnt_delete_custom_user_file = 942;
public static final int couldnt_read_versions_conf = 317;
public final static int couldnt_create_user_information = 249;
public final static int couldnt_get_user_information = 890;
public final static int couldnt_delete_user_information = 345;
public final static int couldnt_create_register_code = 457;
public final static int couldnt_get_register_code = 350;
public final static int couldnt_delete_register_code = 569;
}

View File

@ -0,0 +1,30 @@
package org.blueshard.olymp.exception;
public class FatalIOException extends Exception {
private final int errno;
private final Throwable throwable;
public FatalIOException(int errno, String message) {
super("Errno: " + errno + " - " + message);
this.errno = errno;
this.throwable = null;
}
public FatalIOException(int errno, String message, Throwable t) {
super("Errno: " + errno + " - " + message);
this.errno = errno;
this.throwable = t;
}
public int getErrno() {
return errno;
}
public Throwable getCauseThrowable() {
return throwable;
}
}

View File

@ -0,0 +1,15 @@
package org.blueshard.olymp.exception;
public class IllegalCodeException extends Exception {
private final int givenCode;
private final int requiredCode;
public IllegalCodeException(int givenCode, int requiredCode){
super("Wrong data code is given '" + givenCode + "', expected '" + requiredCode + "'");
this.givenCode = givenCode;
this.requiredCode = requiredCode;
}
}

View File

@ -0,0 +1,9 @@
package org.blueshard.olymp.exception;
public class IllegalPasswordException extends Exception {
public IllegalPasswordException(String errorMessage){
super(errorMessage);
}
}

View File

@ -0,0 +1,9 @@
package org.blueshard.olymp.exception;
public class RegisterCodeNotExistException extends Exception {
public RegisterCodeNotExistException(String registerCode) {
super("The register code '" + registerCode + "' do not exist");
}
}

View File

@ -0,0 +1,23 @@
package org.blueshard.olymp.exception;
public class UnexpectedException extends Exception {
public UnexpectedException() {
super("An unexpected error occurred");
}
public UnexpectedException(Throwable t) {
super("An unexpected error occurred (" + t.getMessage() + ")");
this.setStackTrace(t.getStackTrace());
}
public UnexpectedException(String message) {
super(message);
}
public UnexpectedException(String message, Throwable t) {
super(message);
this.setStackTrace(t.getStackTrace());
}
}

View File

@ -0,0 +1,9 @@
package org.blueshard.olymp.exception;
public class UserAlreadyExistException extends UserException {
public UserAlreadyExistException(String username, String message) {
super(username, message);
}
}

View File

@ -0,0 +1,13 @@
package org.blueshard.olymp.exception;
public class UserException extends Exception {
final String UUID;
public UserException(String UUID, String message) {
super(message);
this.UUID = UUID;
}
}

View File

@ -0,0 +1,9 @@
package org.blueshard.olymp.exception;
public class UserNotExistException extends UserException {
public UserNotExistException(String username, String message){
super(username, message);
}
}

View File

@ -0,0 +1,8 @@
package org.blueshard.olymp.exception;
public class UserNotLoggedInException extends UserException {
public UserNotLoggedInException(String username, String message) {
super(username, message);
}
}

View File

@ -0,0 +1,209 @@
package org.blueshard.olymp.files;
import java.io.*;
import java.util.Map;
import java.util.TreeMap;
public class ConfReader {
public static class SingleConfReader {
private File confFile;
private TreeMap<String, String> entries = new TreeMap<>();
public SingleConfReader(File confFile) throws IOException {
initialize(confFile);
}
public SingleConfReader(String confFile) throws IOException {
initialize(new File(confFile));
}
private void initialize(File confFile) throws IOException {
this.confFile = confFile;
BufferedReader bufferedReader = new BufferedReader(new FileReader(confFile));
String line;
while ((line = bufferedReader.readLine()) != null) {
line = line.strip();
if (line.isBlank() || line.isEmpty()) {
entries.put("#", null);
} else if (line.contains("#")) {
entries.put("#", line.substring(1));
} else {
String[] keyValue = line.split("=", 1);
entries.put(keyValue[0].strip(), keyValue[1].strip());
}
}
bufferedReader.close();
}
public boolean containsKey(String sectionName, String key) {
return entries.containsKey(key);
}
public boolean containsValue(String sectionName, String value) {
return entries.containsKey(value);
}
public TreeMap<String, String> getAll() {
return entries;
}
public TreeMap<String, String> getAll(boolean onlyText) {
if (onlyText) {
TreeMap<String, String> returnEntries = entries;
returnEntries.entrySet().removeIf(stringStringEntry -> stringStringEntry.getKey().equals("#"));
return returnEntries;
} else {
return entries;
}
}
public String getKey(String value) {
for (Map.Entry<String, String> entry: entries.entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return null;
}
public String getValue(String key) {
return entries.get(key);
}
public void remove(String key) {
entries.remove(key);
}
public void replace(String key, String newValue) {
entries.replace(key, newValue);
}
}
public static class MultipleConfReader {
private File confFile;
private TreeMap<String, TreeMap<String, String>> entries = new TreeMap<>();
public MultipleConfReader(File confFile) throws IOException {
initialize(confFile);
}
public MultipleConfReader(String confFile) throws IOException {
initialize(new File(confFile));
}
private void initialize(File confFile) throws IOException {
this.confFile = confFile;
BufferedReader bufferedReader = new BufferedReader(new FileReader(confFile));
String currentSection = null;
TreeMap<String, String> currentEntries = new TreeMap<>();
String line;
while ((line = bufferedReader.readLine()) != null) {
line = line.strip();
if (line.isBlank() || line.isEmpty()) {
currentEntries.put("#", null);
} else if (line.contains("#")) {
currentEntries.put("#", line.substring(1));
} else if (line.startsWith("[") && line.endsWith("]")) {
if (currentSection != null) {
entries.put(currentSection, currentEntries);
}
currentSection = line.substring(1, line.length() - 1);
} else {
String[] keyValue = line.split("=", 1);
if (keyValue.length == 1) {
currentEntries.put(keyValue[0].strip(), "");
} else {
currentEntries.put(keyValue[0].strip(), keyValue[1].strip());
}
}
}
bufferedReader.close();
}
public boolean containsKey(String sectionName, String key) {
return entries.get(sectionName).containsKey(key);
}
public boolean containsValue(String sectionName, String value) {
return entries.get(sectionName).containsKey(value);
}
public boolean containsSection(String sectionName) {
return entries.containsKey(sectionName);
}
public TreeMap<String, TreeMap<String, String>> getAll() {
return entries;
}
public TreeMap<String, TreeMap<String, String>> getAll(boolean onlyText) {
if (onlyText) {
TreeMap<String, TreeMap<String, String>> returnEntries = entries;
for (Map.Entry<String, TreeMap<String, String>> entry : entries.entrySet()) {
entry.getValue().entrySet().removeIf(stringStringEntry -> stringStringEntry.getKey().equals("#"));
}
return returnEntries;
} else {
return entries;
}
}
public TreeMap<String, String> getAll(String sectionName) {
TreeMap<String, String> returnEntries = entries.get(sectionName);
returnEntries.entrySet().removeIf(stringStringEntry -> stringStringEntry.getKey().equals("#"));
return returnEntries;
}
public TreeMap<String, String> getAll(String sectionName, boolean onlyText) {
if (onlyText) {
TreeMap<String, String> returnEntries = entries.get(sectionName);
returnEntries.entrySet().removeIf(stringStringEntry -> stringStringEntry.getKey().equals("#"));
return returnEntries;
} else {
return entries.get(sectionName);
}
}
public String getKey(String sectionName, String value) {
for (Map.Entry<String, String> entry: entries.get(sectionName).entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return null;
}
public String getValue(String sectionName, String key) {
return entries.get(sectionName).get(key);
}
public void remove(String sectionName, String key) {
entries.remove(sectionName).remove(key);
}
public void removeSection(String sectionName) {
entries.remove(sectionName);
}
public void replace(String sectionName, String key, String newValue) {
entries.get(sectionName).replace(key, newValue);
}
}
}

View File

@ -0,0 +1,267 @@
package org.blueshard.olymp.files;
import java.io.*;
import java.util.*;
public class ConfWriter {
public static class SingleConfWriter {
private TreeMap<String, String> entries = new TreeMap<>();
public void write(String filename) throws IOException {
write(new File(filename));
}
public void write(File file) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));
String key;
String value;
for (Map.Entry<String, String> entry: entries.entrySet()) {
key = entry.getKey();
value = entry.getValue();
if (key.equals("#")) {
if (value == null) {
bufferedWriter.newLine();
} else {
bufferedWriter.write(key + value);
}
} else {
bufferedWriter.write(key + " = " + value);
}
bufferedWriter.newLine();
}
bufferedWriter.flush();
bufferedWriter.close();
}
public void add(String key, String value) {
if (key == null) {
return;
} else if (key.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + key);
} else if (value.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + value);
} else {
entries.put(key, value);
}
}
public void addAll(TreeMap<String, String> newEntries) {
TreeMap<String, String> tempEntries = new TreeMap<>();
newEntries.forEach((key, value) -> {
if (key == null) {
return;
} else if (key.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + key);
} else if (value.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + value);
} else {
tempEntries.put(key, value);
}
});
entries.putAll(tempEntries);
}
public void addBlankLine() {
TreeMap<String, String> newEntries = entries;
newEntries.put("#", null);
entries = newEntries;
}
public void addComment(String comment) {
TreeMap<String, String> newEntries = entries;
newEntries.put("#", comment);
entries = newEntries;
}
public TreeMap<String, String> getAll() {
return entries;
}
public void getAndAdd(String string) throws IOException {
getAndAdd(new File(string));
}
public void getAndAdd(File file) throws IOException {
entries.putAll(new ConfReader.SingleConfReader(file).getAll());
}
public String getKey(String value) {
for (Map.Entry<String, String> entry: entries.entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return null;
}
public String getValue(String key) {
return entries.get(key);
}
public void remove(String key) {
entries.remove(key);
}
public void replace(String key, String newValue) {
entries.replace(key, newValue);
}
}
public static class MultipleConfWriter {
private TreeMap<String, TreeMap<String, String>> entries = new TreeMap<>();
public void createNewSection(String sectionName) {
entries.put(sectionName, new TreeMap<>());
}
public void write(String filename) throws IOException {
write(new File(filename));
}
public void write(File file) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));
String sectionKey;
String sectionValue;
for (Map.Entry<String, TreeMap<String, String>> entry: entries.entrySet()) {
String sectionName = entry.getKey();
bufferedWriter.write("[" + sectionName + "]");
bufferedWriter.newLine();
bufferedWriter.newLine();
for (Map.Entry<String, String> sectionEntry: entries.get(sectionName).entrySet()) {
sectionKey = sectionEntry.getKey();
sectionValue = sectionEntry.getValue();
if (sectionKey.equals("#")) {
if (sectionValue == null) {
bufferedWriter.newLine();
} else {
bufferedWriter.write(sectionKey + sectionValue);
}
} else {
bufferedWriter.write(sectionKey + " = " + sectionValue);
}
bufferedWriter.newLine();
}
}
bufferedWriter.flush();
bufferedWriter.close();
}
public void add(String sectionName, String key, String value) {
if (sectionName == null || key == null || !entries.containsKey(sectionName)) {
return;
} else if (key.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + key);
} else if (value.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + value);
} else {
TreeMap<String, String> newEntries = entries.get(sectionName);
newEntries.put(key, value);
entries.replace(sectionName, new TreeMap<>(newEntries));
}
}
public void addAll(String sectionName, TreeMap<String, String> newEntries) {
TreeMap<String, String> tempEntries = new TreeMap<>();
if (sectionName == null || !newEntries.containsKey(sectionName)) {
return;
} else {
newEntries.forEach((key, value) -> {
if (key == null) {
return;
} else if (key.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + key);
} else if (value.contains("#")) {
throw new IllegalArgumentException("Found '#' in " + value);
} else {
tempEntries.put(key, value);
}
});
}
TreeMap<String, String> newSectionEntries = entries.get(sectionName);
newSectionEntries.putAll(tempEntries);
entries.replace(sectionName, new TreeMap<>(newSectionEntries));
}
public void addBlankLine(String sectionName) {
TreeMap<String, String> newEntries = entries.get(sectionName);
newEntries.put("#", null);
entries.put(sectionName, newEntries);
}
public void addComment(String sectionName, String comment) {
TreeMap<String, String> newEntries = entries.get(sectionName);
newEntries.put("#", comment);
entries.put(sectionName, newEntries);
}
public void addSingleConfWriter(String sectionName, ConfWriter.SingleConfWriter singleConfWriter) {
entries.put(sectionName, singleConfWriter.entries);
}
public TreeMap<String, TreeMap<String, String>> getAll() {
return entries;
}
public void getAndAdd(String string) throws IOException {
getAndAdd(new File(string));
}
public void getAndAdd(File file) throws IOException {
entries.putAll(new ConfReader.MultipleConfReader(file).getAll());
}
public String getKey(String sectionName, String value) {
for (Map.Entry<String, String> entry: entries.get(sectionName).entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return null;
}
public String getValue(String sectionName, String key) {
return entries.get(sectionName).get(key);
}
public void remove(String sectionName, String key) {
entries.remove(sectionName).remove(key);
}
public void removeSection(String sectionName) {
entries.remove(sectionName);
}
public void replace(String sectionName, String key, String newValue) {
entries.get(sectionName).replace(key, newValue);
}
}
}

View File

@ -0,0 +1,39 @@
package org.blueshard.olymp.files;
public class ServerFiles {
public static class etc {
public static final String dir = "/srv/etc/";
public static final String register_codes = dir + "register_codes";
public static final String versions = dir + "versions.conf";
public static class update {
public static final String dir = "/srv/etc/update/";
public static final String TheosUI_jar = dir + "update.jar";
}
}
public static class logs {
public static final String dir = "/srv/logs/";
public static final String main_log = dir + "main.log";
}
public static class user_files {
public static final String dir = "/srv/user_files/";
public final String user_files_dir;
public user_files(String UUID) {
user_files_dir = dir + UUID + "/";
}
}
}

View File

@ -0,0 +1,76 @@
package org.blueshard.olymp.fileserver;
import org.apache.log4j.Logger;
import org.blueshard.olymp.e2ee.E2EEConverter;
import org.blueshard.olymp.exception.UnexpectedException;
import org.blueshard.olymp.server.ClientFactory;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
public class FileReceiver {
ClientFactory.Client client;
File destFile;
byte[] privateKey;
Logger logger;
public FileReceiver(ClientFactory.Client client, File destFile, byte[] privateKey, Logger logger) {
this.client = client;
this.destFile = destFile;
this.privateKey = privateKey;
this.logger = logger;
}
public String main() throws IOException, UnexpectedException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException, BadPaddingException, NoSuchPaddingException {
try {
SSLServerSocket FTPSocket = (SSLServerSocket) SSLServerSocketFactory.getDefault().createServerSocket(20);
logger.info("Start File Receiver for client " + client.getId());
logger.info("Receiver infos: " + FTPSocket.toString());
SSLSocket sslSocket = (SSLSocket) FTPSocket.accept();
logger.info("Client connected");
InputStream inputStream = sslSocket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(destFile);
StringBuilder hexString = new StringBuilder();
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
fileOutputStream.write(Base64.getDecoder().decode(E2EEConverter.decrypt(Base64.getEncoder().encodeToString(buffer), privateKey)), 0, length);
md5.update(buffer, 0, length);
}
logger.info("Received file from client and saved it");
byte[] digest = md5.digest();
for (byte b : digest) {
if ((0xff & b) < 0x10) {
hexString.append("0").append(Integer.toHexString((0xFF & b)));
} else {
hexString.append(Integer.toHexString(0xFF & b));
}
}
sslSocket.close();
logger.info("Closed File Receiver");
logger.info("File MD5 check sum is " + hexString.toString());
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new UnexpectedException(e);
}
}
}

View File

@ -0,0 +1,74 @@
package org.blueshard.olymp.fileserver;
import org.apache.log4j.Logger;
import org.blueshard.olymp.e2ee.E2EEConverter;
import org.blueshard.olymp.exception.UnexpectedException;
import org.blueshard.olymp.server.ClientFactory;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
public class FileSender {
ClientFactory.Client client;
File sourceFile;
byte[] publicKey;
Logger logger;
public FileSender(ClientFactory.Client client, File sourceFile, byte[] publicKey, Logger logger) {
this.client = client;
this.sourceFile = sourceFile;
this.publicKey = publicKey;
this.logger = logger;
}
public String main() throws IOException, UnexpectedException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException, InvalidKeyException {
try {
SSLServerSocket FTPSocket = (SSLServerSocket) SSLServerSocketFactory.getDefault().createServerSocket(20);
logger.info("Started file sender");
logger.info("Sender infos: " + FTPSocket.toString());
SSLSocket sslSocket = (SSLSocket) FTPSocket.accept();
logger.info("Client connected");
FileInputStream fileInputStream = new FileInputStream(sourceFile);
OutputStream outputStream = sslSocket.getOutputStream();
StringBuilder hexString = new StringBuilder();
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[1024];
int length;
while ((length = fileInputStream.read(buffer)) > 0) {
outputStream.write(Base64.getDecoder().decode(E2EEConverter.encrypt(Base64.getEncoder().encodeToString(buffer), publicKey)), 0, length);
md5.update(buffer, 0, length);
}
logger.info("Send file to client and saved it");
byte[] digest = md5.digest();
for (byte b : digest) {
if ((0xff & b) < 0x10) {
hexString.append("0").append(Integer.toHexString((0xFF & b)));
} else {
hexString.append(Integer.toHexString(0xFF & b));
}
}
sslSocket.close();
logger.info("Closed File Sender");
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new UnexpectedException(e);
}
}
}

View File

@ -0,0 +1,102 @@
package org.blueshard.olymp.logging;
import org.apache.log4j.*;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.blueshard.olymp.files.ServerFiles;
import org.blueshard.olymp.server.ClientFactory;
import org.blueshard.olymp.utils.ConsoleColors;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Locale;
public class ClientLogger {
private final Logger logger;
public ClientLogger(ClientFactory.Client client, Level logLevel) throws IOException {
logger = Logger.getLogger(String.valueOf(client.getId()));
logger.setLevel(logLevel);
ConsoleAppender consoleAppender = new ConsoleAppender(new Layout() {
@Override
public String format(LoggingEvent loggingEvent) {
DateFormat date = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", Locale.GERMANY);
Level level = loggingEvent.getLevel();
StringBuilder extraData = new StringBuilder();
String color;
String id = String.valueOf(client.getId());
ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation();
switch (loggingEvent.getLevel().toInt()) {
case Level.WARN_INT:
color = ConsoleColors.RED_BRIGHT;
break;
case Level.ERROR_INT:
color = ConsoleColors.RED_BOLD + ConsoleColors.RED_UNDERLINED;
break;
case Level.FATAL_INT:
color = ConsoleColors.BLACK;
break;
default:
color = "";
break;
}
if (throwableInformation != null) {
extraData.append(ConsoleColors.RED);
Arrays.asList(throwableInformation.getThrowable().getStackTrace()).forEach(stackTraceElement -> extraData.append(stackTraceElement).append("\n"));
}
return color + "[" + date.format(loggingEvent.getTimeStamp()) + " - ID: " + id + "] " + level + ": " + loggingEvent.getMessage() + "\n" + extraData.toString() + ConsoleColors.RESET;
}
@Override
public boolean ignoresThrowable() {
return false;
}
@Override
public void activateOptions() {
}
});
RollingFileAppender rollingFileAppender = new RollingFileAppender(new Layout() {
@Override
public String format(LoggingEvent loggingEvent) {
DateFormat date = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", Locale.GERMANY);
Level level = loggingEvent.getLevel();
StringBuilder extraData = new StringBuilder();
String id = String.valueOf(client.getId());
ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation();
if (throwableInformation != null) {
Arrays.asList(throwableInformation.getThrowable().getStackTrace()).forEach(stackTraceElement -> extraData.append(stackTraceElement).append("\n"));
}
return "[" + date.format(loggingEvent.getTimeStamp()) + " - ID: " + id + "] " + level + ": " + loggingEvent.getMessage() + "\n" + extraData.toString();
}
@Override
public boolean ignoresThrowable() {
return false;
}
@Override
public void activateOptions() {
}
}, ServerFiles.logs.main_log, true);
rollingFileAppender.setMaxBackupIndex(10);
rollingFileAppender.setMaxFileSize("10MB");
logger.addAppender(consoleAppender);
logger.addAppender(rollingFileAppender);
}
public Logger getLogger() {
return logger;
}
}

View File

@ -0,0 +1,14 @@
package org.blueshard.olymp.logging;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
public class EmptyLogger {
public Logger getLogger() {
Logger logger = Logger.getLogger(EmptyLogger.class.getName());
logger.setLevel(Level.OFF);
return logger;
}
}

View File

@ -0,0 +1,15 @@
package org.blueshard.olymp.logging;
import org.blueshard.olymp.user.User;
public class LogDeleter {
private final User user;
private final String logLifeTime;
public LogDeleter(User user, String logLifeTime) {
this.user = user;
this.logLifeTime = logLifeTime;
}
}

View File

@ -0,0 +1,92 @@
package org.blueshard.olymp.logging;
import org.apache.log4j.*;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.blueshard.olymp.files.ServerFiles;
import org.blueshard.olymp.utils.ConsoleColors;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
public class ServerLogger {
private final Logger logger = LogManager.getLogger(ServerLogger.class);
public Logger main() throws IOException {
logger.setLevel(Level.ALL);
RollingFileAppender rollingFileAppender = new RollingFileAppender(new Layout() {
@Override
public String format(LoggingEvent loggingEvent) {
SimpleDateFormat date = new SimpleDateFormat("HH:mm:ss");
StringBuilder extraData = new StringBuilder();
ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation();
if (throwableInformation != null) {
Arrays.asList(throwableInformation.getThrowable().getStackTrace()).forEach(stackTraceElement -> extraData.append(stackTraceElement).append("\n"));
}
return "[" + date.format(loggingEvent.getTimeStamp()) + " - Server] " + loggingEvent.getLevel() + ": " + loggingEvent.getMessage() + "\n" + extraData.toString();
}
@Override
public boolean ignoresThrowable() {
return false;
}
@Override
public void activateOptions() {
}
}, ServerFiles.logs.main_log, true);
rollingFileAppender.setMaxBackupIndex(10);
rollingFileAppender.setMaxFileSize("10MB");
ConsoleAppender consoleAppender = new ConsoleAppender(new Layout() {
@Override
public String format(LoggingEvent loggingEvent) {
SimpleDateFormat date = new SimpleDateFormat("HH:mm:ss");
StringBuilder extraData = new StringBuilder();
String color;
ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation();
switch (loggingEvent.getLevel().toInt()) {
case Level.WARN_INT:
color = ConsoleColors.RED_BRIGHT;
break;
case Level.ERROR_INT:
color = ConsoleColors.RED_BOLD + ConsoleColors.RED_UNDERLINED;
break;
case Level.FATAL_INT:
color = ConsoleColors.BLACK;
break;
default:
color = "";
break;
}
if (throwableInformation != null) {
extraData.append(ConsoleColors.RED);
Arrays.asList(throwableInformation.getThrowable().getStackTrace()).forEach(stackTraceElement -> extraData.append(stackTraceElement).append("\n"));
}
return color + "[" + date.format(loggingEvent.getTimeStamp()) + " - Server] " + loggingEvent.getLevel() + ": " + loggingEvent.getMessage() + "\n" + extraData.toString() + ConsoleColors.RESET;
}
@Override
public boolean ignoresThrowable() {
return false;
}
@Override
public void activateOptions() {
}
});
logger.addAppender(rollingFileAppender);
logger.addAppender(consoleAppender);
return logger;
}
}

View File

@ -0,0 +1,95 @@
package org.blueshard.olymp.register_code;
import org.blueshard.olymp.Main;
import org.blueshard.olymp.exception.ErrorCodes;
import org.blueshard.olymp.exception.FatalIOException;
import org.blueshard.olymp.sql.SQL;
import java.sql.*;
import java.util.HashSet;
import java.util.concurrent.ThreadLocalRandom;
public class RegisterCode {
public static String generateNewRegisterCode() throws FatalIOException {
String[] letters = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 18; i++) {
stringBuilder.append(letters[ThreadLocalRandom.current().nextInt(0, letters.length)]);
}
try {
Connection connection = Main.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO REGISTER_CODES VALUES(?)");
preparedStatement.setString(1, stringBuilder.toString());
preparedStatement.executeUpdate();
SQL.checkpoint();
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_create_register_code, "Couldn't add new register code", e);
}
return stringBuilder.toString();
}
public static HashSet<String> getAllRegisterCodes() throws FatalIOException {
HashSet<String> registerCodes = new HashSet<>();
try {
Statement statement = Main.getConnection().createStatement();
ResultSet resultSet = statement.executeQuery("SELECT CODE FROM REGISTER_CODE");
int columnCount;
while (resultSet.next()) {
registerCodes.add(resultSet.getString(1));
}
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_get_register_code, "Failed to read register codes", e);
}
return registerCodes;
}
public static boolean isRegisterCode(String registerCode) throws FatalIOException {
try {
Statement statement = Main.getConnection().createStatement();
ResultSet resultSet = statement.executeQuery("SELECT CODE FROM REGISTER_CODE");
while (resultSet.next()) {
if (resultSet.getString(1).equals(registerCode)) {
resultSet.close();
return true;
}
}
resultSet.close();
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_get_register_code, "Failed to read register codes", e);
}
return false;
}
public static void removeRegisterCode(String registerCode) throws FatalIOException {
try {
PreparedStatement preparedStatement = Main.getConnection().prepareStatement("DELETE FROM REGISTER_CODES WHERE CODE = ?");
preparedStatement.setString(1, registerCode);
preparedStatement.executeUpdate();
SQL.checkpoint();
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_delete_register_code, "Failed to delete register code " + registerCode, e);
}
}
}

View File

@ -0,0 +1,67 @@
package org.blueshard.olymp.security;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
public class Password {
public static PasswordInfos createPassword(String password, byte[] salt) throws InvalidKeySpecException {
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(salt);
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKeyFactory factory = null;
try {
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException ignore) {
}
byte[] hashedPassword;
try {
hashedPassword = factory.generateSecret(keySpec).getEncoded();
} catch (InvalidKeySpecException ignore) {
}
hashedPassword = factory.generateSecret(keySpec).getEncoded();
return new PasswordInfos(hashedPassword, salt);
}
public static class PasswordInfos {
private final byte[] password;
private final byte[] salt;
public PasswordInfos(byte[] password, byte[] salt) {
this.password = password;
this.salt = salt;
}
public byte[] getPasswordAsBytes() {
return password;
}
public String getPasswordAsString() {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(password);
}
public byte[] getSaltAsBytes() {
return salt;
}
public String getSaltAsString() {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(salt);
}
}
}

View File

@ -0,0 +1,133 @@
package org.blueshard.olymp.server;
import org.apache.log4j.Logger;
import org.blueshard.olymp.Main;
import org.blueshard.olymp.data.DataCodes;
import org.blueshard.olymp.data.Data;
import org.blueshard.olymp.e2ee.RSACipher;
import org.blueshard.olymp.exception.*;
import org.blueshard.olymp.files.ServerFiles;
import org.blueshard.olymp.register_code.RegisterCode;
import org.blueshard.olymp.sql.SQL;
import org.blueshard.olymp.sql.SQLPosition;
import org.blueshard.olymp.user.User;
import org.blueshard.olymp.version.TheosUIVersion;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
public class Action {
private Data data;
private final ClientSender clientSender;
public Action(Data data, ClientSender clientSender) {
this.data = data;
this.clientSender = clientSender;
}
public void refreshData(Data data) {
this.data = data;
}
public void close() {
clientSender.close();
}
public void firstConnectionResult(boolean validAgent, boolean update) {
clientSender.firstConnectResult(validAgent, update);
}
public void isRegisterCode() throws FatalIOException {
if (RegisterCode.isRegisterCode(data.getFromData(DataCodes.Params.RegisterCode.REGISTERCODE))) {
clientSender.registerCodeExist();
} else {
clientSender.registerCodeNotExist();
}
}
public static PrivateKey publicKey(OutputStream outputStream, Logger logger) throws UnexpectedException {
KeyPair keyPair = RSACipher.generateKeyPair();
ClientSender.publicKey(keyPair.getPublic(), new DataOutputStream(outputStream), logger);
return keyPair.getPrivate();
}
public static void ready(OutputStream outputStream, Logger logger) {
ClientSender.ready(new DataOutputStream(outputStream), logger);
}
public User login() throws UserNotExistException, IllegalCodeException, IllegalPasswordException, FatalIOException {
try {
PreparedStatement preparedStatement = Main.getConnection().prepareStatement("SELECT UUID FROM USERS WHERE USERNAME = ?");
preparedStatement.setString(1, data.getFromData(DataCodes.Params.LogReg.USERNAME));
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
User user = new User(resultSet.getString(1));
if (data.getCode() != DataCodes.Client.LOGIN) {
throw new IllegalCodeException(data.getCode(), DataCodes.Client.LOGIN);
} else if (!data.getFromData(DataCodes.Params.LogReg.PASSWORD).equals(user.getPasswordInfos().getPasswordAsString())) {
throw new IllegalPasswordException("Wrong password is given");
}
clientSender.loginSuccess();
resultSet.close();
return user;
} else {
resultSet.close();
throw new UserNotExistException(data.getFromData(DataCodes.Params.LogReg.USERNAME), "The user doesn't exist");
}
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_get_user_information, "Couldn't get UUID for user with name " + data.getFromData(DataCodes.Params.LogReg.USERNAME), e);
}
}
public User register() throws FatalIOException, UserAlreadyExistException, RegisterCodeNotExistException {
User user = User.createNewUser(data.getFromData(DataCodes.Params.RegisterCode.REGISTERCODE),
data.getFromData(DataCodes.Params.LogReg.USERNAME), data.getFromData(DataCodes.Params.LogReg.PASSWORD),
data.getFromData(DataCodes.Params.LogReg.SALT), data.getFromData(DataCodes.Params.LogReg.EMAIL));
clientSender.registerSuccess();
return user;
}
public void receiveFile(User user, byte[] privateKey) {
clientSender.receiveFile(new ServerFiles.user_files(user.getUUID()) + data.getFromData(DataCodes.Params.File.FILEPATH), privateKey);
}
public void requestArtificeUIOptionalUpdate(TheosUIVersion version) {
clientSender.requestArtificeUIOptionalUpdate(version, version.getChanges());
}
public void requestArtificeUIRequiredUpdate(TheosUIVersion version) {
clientSender.requestArtificeUIRequiredUpdate(version, version.getChanges());
}
public void sendFile(String file, byte[] publicKey) {
clientSender.sendFile(new File(file), publicKey);
}
public void sendUpdateFile(byte[] publicKey) {
clientSender.sendFile(new File(ServerFiles.etc.update.TheosUI_jar), publicKey);
}
public void sendUserFilesData(String UUID, String startDirectory) {
clientSender.filesData(UUID, new File(new ServerFiles.user_files(UUID).user_files_dir + startDirectory));
}
}

View File

@ -0,0 +1,86 @@
package org.blueshard.olymp.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Arrays;
import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom;
public class ClientFactory {
private TreeMap<Integer, Client> ids = new TreeMap<>();
public Client createNewClient(Socket socket, String clientAgent) {
int id;
do {
id = ThreadLocalRandom.current().nextInt(1, 999);
} while (ids.containsKey(id));
return new Client(id, socket, clientAgent);
}
public class Client {
private final int id;
private final Socket socket;
private String clientAgent;
public Client(int id, Socket socket, String clientAgent) {
ClientFactory.this.ids.clear();
this.id = id;
this.socket = socket;
this.clientAgent = clientAgent;
}
public void close() throws IOException {
try {
socket.close();
ids.remove(id);
} catch (IOException e) {
e.printStackTrace();
throw new IOException("Couldn't close connection");
}
}
public int getId() {
return id;
}
public String getClientAgent() {
return clientAgent;
}
public InetAddress getInetAddress() {
return socket.getInetAddress();
}
public InputStream getInputStream() throws IOException {
return socket.getInputStream();
}
public String getIPAddress() {
return getInetAddress().getHostAddress();
}
public OutputStream getOutputStream() throws IOException {
return socket.getOutputStream();
}
public int getPort() {
return socket.getPort();
}
public void setClientAgent(String clientAgent) throws IllegalAccessException {
if (this.clientAgent != null) {
throw new IllegalAccessException("Client agent is already set");
} else {
this.clientAgent = clientAgent;
}
}
}
}

View File

@ -0,0 +1,86 @@
package org.blueshard.olymp.server;
import org.apache.log4j.Logger;
import org.blueshard.olymp.data.DataCodes;
import org.blueshard.olymp.data.Data;
import org.blueshard.olymp.e2ee.E2EEConverter;
import org.blueshard.olymp.exception.UnexpectedException;
import org.blueshard.olymp.user.User;
import java.io.*;
import java.security.GeneralSecurityException;
public class ClientReceiver {
private final User user;
private final ClientFactory.Client client;
private final byte[] clientPublicKey;
private final byte[] privateKey;
private final Logger logger;
private final DataInputStream clientInput;
private final ClientSender clientSender;
ClientReceiver(User user, ClientFactory.Client client, ClientSender clientSender, byte[] clientPublicKey, byte[] privateKey, Logger logger) throws IOException {
this.user = user;
this.client = client;
this.clientPublicKey = clientPublicKey;
this.privateKey = privateKey;
this.logger = logger;
try {
this.clientInput = new DataInputStream(this.client.getInputStream());
this.clientSender = clientSender;
} catch (IOException e) {
throw new IOException(ResultCodes.UNEXPECTEDEXIT + ";" + e.getMessage());
}
}
public int main() {
Data inputData;
Action action = new Action(null, clientSender);
while (true) {
try {
inputData = new Data(E2EEConverter.decrypt(clientInput.readUTF(), privateKey));
} catch (IOException | GeneralSecurityException e) {
return ResultCodes.UNEXPECTEDEXIT;
} catch (UnexpectedException e) {
clientSender.unexpectedError();
return ResultCodes.UNEXPECTEDEXIT;
}
action.refreshData(inputData);
switch (inputData.getCode()) {
case DataCodes.Client.UNEXPECTEDEXIT:
return ResultCodes.UNEXPECTEDEXIT;
case DataCodes.Client.CLOSE:
return ResultCodes.EXIT;
case DataCodes.Client.GETFILESDATA:
String startDirectory = inputData.getFromData(DataCodes.Params.File.STARTDIRECOTRY);
if (startDirectory == null) {
startDirectory = "/";
}
action.sendUserFilesData(user.getUUID(), startDirectory);
break;
case DataCodes.Client.GETFILE:
action.sendFile(user.getUserfileDirectory() + inputData.getFromData(DataCodes.Params.File.FILEPATH), privateKey);
break;
case DataCodes.Client.SENDFILE:
action.receiveFile(user, clientPublicKey);
break;
}
}
}
public static class ResultCodes {
public static final int EXIT = 25;
public static final int UNEXPECTEDEXIT = 84;
}
}

View File

@ -0,0 +1,350 @@
package org.blueshard.olymp.server;
import org.apache.log4j.Logger;
import org.blueshard.olymp.data.Data;
import org.blueshard.olymp.data.DataCodes;
import org.blueshard.olymp.e2ee.E2EEConverter;
import org.blueshard.olymp.exception.UnexpectedException;
import org.blueshard.olymp.fileserver.FileReceiver;
import org.blueshard.olymp.fileserver.FileSender;
import org.blueshard.olymp.files.ServerFiles;
import org.blueshard.olymp.utils.SizeUnit;
import org.blueshard.olymp.version.TheosUIVersion;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import java.util.concurrent.Executors;
public class ClientSender {
private final ClientFactory.Client client;
private final byte[] clientPublicKey;
private final Logger logger;
private final DataOutputStream dataOutputStream;
public ClientSender(ClientFactory.Client client, byte[] clientPublicKey, Logger logger) throws IOException, IllegalBlockSizeException, UnexpectedException, InvalidKeySpecException, InvalidKeyException, BadPaddingException {
this.client = client;
this.clientPublicKey = clientPublicKey;
this.logger = logger;
this.dataOutputStream = new DataOutputStream(this.client.getOutputStream());
if (clientPublicKey.length != 0) {
E2EEConverter.encrypt("Test", clientPublicKey); // just test if the client key works
}
}
public void send(Data data) throws IOException {
if (clientPublicKey.length == 0) {
dataOutputStream.writeUTF(data.getDataAsString() + "\n");
} else {
try {
dataOutputStream.writeUTF(E2EEConverter.encrypt(data.getDataAsString() + "\n", clientPublicKey));
} catch (UnexpectedException e) {
logger.error("An unexpected error occurred", e);
unexpectedError();
} catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException ignore) {
}
}
dataOutputStream.flush();
}
public void send(Data.Builder data) throws IOException {
send(data.getData());
}
private String loggerInfo(String data) {
return "Send " + data + " data";
}
private String loggerWarning(String data) {
return "Failed to send " + data + " data";
}
public void close() {
try {
send(new Data.Builder(DataCodes.Server.CLOSE));
logger.info(loggerInfo("close"));
} catch (IOException e) {
logger.warn(loggerWarning("close"), e);
}
}
public void unexpectedError() {
try {
send(new Data.Builder(DataCodes.Server.UNEXPECTEDERROR));
logger.info(loggerInfo("unexpected error"));
} catch (IOException e) {
logger.warn(loggerWarning("unexpected error"));
}
}
public void unexpectedExit() {
try {
send(new Data.Builder(DataCodes.Server.UNEXPECTEDEXIT));
logger.info(loggerInfo("unexpected exit"));
} catch (IOException e) {
logger.warn(loggerWarning("unexpected exit"));
}
}
public static void publicKey(PublicKey publicKey, DataOutputStream dataOutputStream, Logger logger) {
try {
Data.Builder data = new Data.Builder(DataCodes.Server.PUBLICKEY);
data.addData(DataCodes.Params.Key.PUBLICKEY, Base64.getEncoder().encodeToString(publicKey.getEncoded()));
dataOutputStream.writeUTF(data.getDataAsString() + "\n");
dataOutputStream.flush();
logger.info("Send public key data");
} catch (IOException e) {
logger.warn("Failed to send public key data");
}
}
public static void ready(DataOutputStream dataOutputStream, Logger logger) {
try {
dataOutputStream.writeUTF(new Data.Builder(DataCodes.Server.READY).getDataAsString() + "\n");
dataOutputStream.flush();
logger.info("Send ready data");
} catch (IOException e) {
logger.warn("Failed to send ready data", e);
}
}
public void userNotLoggedIn() {
try {
send(new Data.Builder(DataCodes.Server.NOTLOGGEDIN));
logger.info(loggerInfo("user not logged in"));
} catch (IOException e) {
logger.warn(loggerWarning("user not logged in"));
}
}
//----- update -----//
public void firstConnectResult(boolean validAgent, boolean update) {
Data.Builder data = new Data.Builder(DataCodes.Server.FIRSTCONNECT);
data.addData(DataCodes.Params.ClientAgent.VALIDAGENT, String.valueOf(validAgent));
data.addData(DataCodes.Params.Update.UPDATE, String.valueOf(update));
try {
send(data);
logger.info(loggerInfo("first connect result"));
} catch (IOException e) {
logger.warn(loggerWarning("first connect result"), e);
}
}
public void requestArtificeUIOptionalUpdate(TheosUIVersion version, String changes) {
Data.Builder data = new Data.Builder(DataCodes.Server.OPTIONALUPDATE);
data.addData(DataCodes.Params.Update.NEWVERSION, version.toString());
data.addData(DataCodes.Params.Update.CHANGES, changes);
try {
send(data);
logger.info(loggerInfo("request ArtificeUI optional update"));
} catch (IOException e) {
logger.warn(loggerWarning("request ArtificeUI optional update"));
}
}
public void requestArtificeUIRequiredUpdate(TheosUIVersion version, String changes) {
Data.Builder data = new Data.Builder(DataCodes.Server.REQUIREDUPDATE);
data.addData(DataCodes.Params.Update.NEWVERSION, version.toString());
data.addData(DataCodes.Params.Update.CHANGES, changes);
try {
send(data);
logger.info(loggerInfo("request ArtificeUI required update"));
} catch (IOException e) {
logger.warn(loggerWarning("request ArtificeUI required update"));
}
}
//----- login / register -----//
public void loginFailed() {
try {
send(new Data.Builder(DataCodes.Server.LOGINFAIL));
logger.info(loggerInfo("login fail"));
} catch (IOException e) {
logger.warn(loggerWarning("login fail"));
}
}
public void loginSuccess() {
try {
send(new Data.Builder(DataCodes.Server.LOGINSUCCESS));
logger.info(loggerInfo("login success"));
} catch (IOException e) {
logger.warn(loggerWarning("login success"));
}
}
public void registerCodeExist() {
try {
send(new Data.Builder(DataCodes.Server.REGISTERCODE_EXIST));
logger.info(loggerInfo("register code exist"));
} catch (IOException e) {
logger.warn(loggerWarning("register code exist"));
}
}
public void registerCodeNotExist() {
try {
send(new Data.Builder(DataCodes.Server.REGISTERCODE_NOT_EXIST));
logger.info(loggerInfo("register code not exist"));
} catch (IOException e) {
logger.warn(loggerWarning("register code not exist"));
}
}
public void registerFailed() {
try {
send(new Data.Builder(DataCodes.Server.REGISTERFAIL));
logger.info(loggerInfo("register fail"));
} catch (IOException e) {
logger.warn(loggerWarning("register fail"));
}
}
public void registerFailed_UserExist() {
try {
send(new Data.Builder(DataCodes.Server.REGISTERFAIL_USER_EXIST));
logger.info(loggerInfo("register fail, user exist"));
} catch (IOException e) {
logger.warn(loggerWarning("register fail, user exist"));
}
}
public void registerSuccess() {
try {
send(new Data.Builder(DataCodes.Server.REGISTERSUCCESS));
System.out.println(new Data.Builder(DataCodes.Server.REGISTERSUCCESS).getDataAsString());
logger.info(loggerInfo("register success"));
} catch (IOException e) {
logger.warn(loggerWarning("register success"));
}
}
//----- filesData ----//
public void filesData(String UUID, File startDirectory) {
Data.Builder data = new Data.Builder(DataCodes.Server.SENDFILESDATA);
String file;
File[] files = startDirectory.listFiles();
int userDirectoryLength = new ServerFiles.user_files(UUID).user_files_dir.length();
for (int i = 0; i < files.length; i++) {
file = startDirectory.getAbsolutePath() + "/" + files[i].getName();
if (files[i].isDirectory()) {
data.addData("d" + i, file.substring(userDirectoryLength));
} else {
data.addData("f" + SizeUnit.BYTES(files[i].length()).toMegabyte() + "MB", file.substring(userDirectoryLength));
}
}
try {
send(data);
logger.info("Send files data");
} catch (IOException e) {
logger.warn("Failed to send user files data");
}
}
public void receiveFile(String file, byte[] privateKey) {
FileReceiver fileReceiver = new FileReceiver(client, new File(file), privateKey, logger);
Executors.newSingleThreadExecutor().execute(() -> {
try {
try {
String md5CheckSum = fileReceiver.main();
} catch (UnexpectedException e) {
logger.warn("An unexpected io exception occurred", e);
} catch (IllegalBlockSizeException | InvalidKeyException | InvalidKeySpecException | BadPaddingException | NoSuchPaddingException e) {
logger.warn("An unexpected exception occurred");
}
logger.info("Received file " + file);
receiveFileSuccess();
} catch (IOException e) {
logger.warn("Failed to receive file " + file);
e.printStackTrace();
}
});
}
public void receiveFileFailed() {
try {
send(new Data.Builder(DataCodes.Server.RECEIVEFILEFAIL));
logger.info(loggerInfo("receive file fail"));
} catch (IOException e) {
logger.warn(loggerWarning("receive file fail"));
}
}
public void receiveFileSuccess() {
try {
send(new Data.Builder(DataCodes.Server.RECEIVEFILESUCCESS));
logger.info(loggerInfo("receive file success"));
} catch (IOException e) {
logger.warn(loggerWarning("receive file success"));
}
}
public void sendFile(File file, byte[] publicKey) {
FileSender fileSender = new FileSender(client, file, publicKey, logger);
Executors.newSingleThreadExecutor().execute(() -> {
try {
String md5CheckSum = null;
try {
md5CheckSum = fileSender.main();
} catch (UnexpectedException e) {
logger.warn("An unexpected io exception occurred", e);
} catch (BadPaddingException | IllegalBlockSizeException | InvalidKeySpecException | InvalidKeyException e) {
logger.warn("An unexpected exception occurred");
}
logger.info("Send file " + file);
sendFileSuccess(md5CheckSum);
} catch (IOException e) {
logger.warn("Failed to send file " + file.getAbsolutePath());
e.printStackTrace();
sendFileFailed();
}
});
}
public void sendFileFailed() {
try {
send(new Data.Builder(DataCodes.Server.SENDFILEFAIL));
logger.info(loggerInfo("send file data"));
} catch (IOException e) {
logger.warn(loggerWarning("send file fail"));
}
}
public void sendFileSuccess(String checkSum) {
try {
Data.Builder data = new Data.Builder(DataCodes.Server.SENDFILESSUCCESS);
data.addData(DataCodes.Params.CheckSum.MD5, checkSum);
send(data);
logger.info(loggerInfo("send file success"));
} catch (IOException e) {
logger.warn(loggerWarning("send file success"));
}
}
}

View File

@ -0,0 +1,345 @@
package org.blueshard.olymp.server;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.blueshard.olymp.Main;
import org.blueshard.olymp.data.Data;
import org.blueshard.olymp.data.DataCodes;
import org.blueshard.olymp.e2ee.E2EEConverter;
import org.blueshard.olymp.exception.*;
import org.blueshard.olymp.logging.ClientLogger;
import org.blueshard.olymp.register_code.RegisterCode;
import org.blueshard.olymp.user.User;
import org.blueshard.olymp.utils.ExceptionUtils;
import org.blueshard.olymp.version.TheosUIVersion;
import javax.net.ServerSocketFactory;
import java.io.*;
import java.lang.reflect.Field;
import java.net.ServerSocket;
import java.net.SocketException;
import java.security.GeneralSecurityException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashSet;
import java.util.concurrent.Executors;
public class MainServer {
private final int port;
private final Logger logger;
private ServerSocket serverSocket = null;
private ClientFactory clientFactory = new ClientFactory();
public MainServer(int port, Logger logger) {
this.port = port;
this.logger = logger;
}
public void start() {
try {
serverSocket = ServerSocketFactory.getDefault().createServerSocket(port);
} catch (IOException e) {
logger.fatal("Couldn't create server");
e.printStackTrace();
return;
}
logger.info("Start server");
logger.info("Server infos: " + serverSocket.toString());
while (true){
ClientFactory.Client client;
try {
client = clientFactory.createNewClient(serverSocket.accept(), null);
} catch (IOException e) {
logger.error("Couldn't connect to new client");
e.printStackTrace();
return;
}
logger.info("New Client connected - ID: " + client.getId());
try {
Executors.newSingleThreadExecutor().execute(() -> {
try {
boolean notLoggedIn = true;
Data inputData;
Logger clientLogger = null;
User user = null;
byte[] clientPublicKey;
if (client.getInetAddress().getHostAddress().equals("127.0.0.1")) {
logger.info("Localhost connected");
DataInputStream dataInputStream = new DataInputStream(client.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(client.getOutputStream());
String connectionType = dataInputStream.readUTF().strip().toLowerCase();
switch (connectionType) {
case "sql":
logger.info("Localhost acts in SQL mode");
Connection connection = Main.getConnection();
StringBuilder resultData = new StringBuilder();
ResultSetMetaData resultSetMetaData;
String input;
while (true) {
try {
input = dataInputStream.readUTF().replaceAll("\\s{2,}", " ").strip();
if (input.toLowerCase().equals("exit")) {
logger.info("Localhost exit sql mode");
break;
} else if (input.toLowerCase().startsWith("add register code")) {
String times = input.toLowerCase().substring("add register code".length() - 1);
if (times.isBlank()) {
String registerCode = RegisterCode.generateNewRegisterCode();
logger.info("Localhost generated a new register code ('" + registerCode + "')");
dataOutputStream.writeUTF(registerCode);
} else {
StringBuilder stringBuilder = new StringBuilder();
int intTimes;
try {
intTimes = Integer.parseInt(times);
} catch (NumberFormatException e) {
logger.warn("'" + times + "' is not a valid number", e);
dataOutputStream.writeUTF(ExceptionUtils.extractExceptionMessage(e));
continue;
}
for (int i = 1; i < intTimes + 1; i++) {
stringBuilder.append(RegisterCode.generateNewRegisterCode()).append("\n");
}
logger.info("Localhost generated a new register codes ('" + stringBuilder.toString() + "')");
dataOutputStream.writeUTF(stringBuilder.toString());
}
} else if (input.toLowerCase().startsWith("all register codes")) {
HashSet<String> allRegisterCodes = RegisterCode.getAllRegisterCodes();
logger.info("Localhost got all register codes");
dataOutputStream.writeUTF(Arrays.toString(allRegisterCodes.toArray(new String[allRegisterCodes.size()])));
} else if (input.toLowerCase().startsWith("is register code")) {
String registerCode = input.toLowerCase().substring("is register code".length() - 1);
boolean isRegisterCode = RegisterCode.isRegisterCode(registerCode);
logger.info("Localhost checked register code '" + registerCode + "' for it's validity (" + isRegisterCode + ")");
dataOutputStream.writeUTF(String.valueOf(isRegisterCode));
} else if (input.toLowerCase().startsWith("remove register code")) {
String registerCode = input.toLowerCase().substring("remove register code".length() - 1);
RegisterCode.removeRegisterCode(registerCode);
logger.info("Localhost removed register code '" + registerCode + "'");
} else {
logger.info("Localhost send following SQL query: '" + input + "'");
try {
ResultSet resultSet = connection.createStatement().executeQuery(input);
logger.info("SQL query from localhost executed successfully");
while (resultSet.next()) {
resultSetMetaData = resultSet.getMetaData();
for (int i = 1; i < resultSetMetaData.getColumnCount() + 1; i++) {
resultData.append(resultSetMetaData.getColumnName(i)).append(resultSet.getString(i)).append("\n");
}
}
dataOutputStream.writeUTF(resultData.toString());
logger.info("Sent SQL query result set");
} catch (SQLException e) {
logger.warn("SQL query from localhost caused an error", e);
dataOutputStream.writeUTF(e.getSQLState());
}
resultData.delete(0, resultData.length());
}
} catch (FatalIOException e) {
logger.fatal("Fatal IO Exception occurred (" + ExceptionUtils.errorNumberToString(e.getErrno()) + ")", e);
dataOutputStream.writeUTF("Fatal IO Exception occurred (" + ExceptionUtils.errorNumberToString(e.getErrno()) + ")\n" + ExceptionUtils.extractExceptionMessage(e));
}
}
break;
}
client.close();
logger.info("Localhost disconnected");
return;
}
while (true) {
String clientData = new DataInputStream(client.getInputStream()).readUTF();
if (Data.isDataString(clientData)) {
if (new Data(clientData).getCode() == DataCodes.Client.PUBLICKEY) {
clientPublicKey = Base64.getDecoder().decode(new Data(clientData).getFromData(DataCodes.Params.Key.PUBLICKEY));
logger.info("Received client public key");
break;
} else {
logger.info("Client send invalid data");
}
} else {
logger.info("Client send invalid data");
}
}
byte[] privateKey = Action.publicKey(client.getOutputStream(), logger).getEncoded();
ClientSender clientSender;
try {
clientSender = new ClientSender(client, clientPublicKey, logger);
} catch (GeneralSecurityException ignore) {
return;
}
Action action = new Action(null, clientSender);
String agent = null;
String update = null;
TheosUIVersion version = null;
try {
Data data = new Data(E2EEConverter.decrypt(new DataInputStream(client.getInputStream()).readUTF(), privateKey));
String clientAgent = data.getFromData(DataCodes.Params.ClientAgent.CLIENTAGENT);
if (clientAgent.equals(DataCodes.Params.ClientAgent.THEOSUI)) {
client.setClientAgent(clientAgent);
agent = DataCodes.Params.ClientAgent.THEOSUI;
version = new TheosUIVersion(data.getFromData(DataCodes.Params.Version.VERSION));
if (version.hasRequiredUpdate()) {
logger.info("Client has a deprecated TheosUI version");
update = "r";
} else if (version.hasOptionalUpdate()) {
logger.info("Client has a deprecated TheosUI version");
update = "o";
}
} else {
logger.error("Client use an invalid client agent, connection get closed");
}
} catch (GeneralSecurityException | IllegalAccessException ignore) {
}
action.firstConnectionResult(agent != null, update != null);
if (agent == null) {
clientSender.close();
client.close();
return;
}
if (update != null && agent.equals(DataCodes.Params.ClientAgent.THEOSUI)) {
if (update.equals("r")) {
action.requestArtificeUIRequiredUpdate(version);
} else if (update.equals("o")) {
action.requestArtificeUIOptionalUpdate(version);
}
}
while (notLoggedIn) {
try {
inputData = new Data(E2EEConverter.decrypt(new DataInputStream(client.getInputStream()).readUTF(), privateKey));
} catch (IOException | GeneralSecurityException e) {
clientSender.unexpectedError();
return;
}
action.refreshData(inputData);
switch (inputData.getCode()) {
case DataCodes.Client.CLOSE:
case DataCodes.Client.UNEXPECTEDEXIT:
return;
case DataCodes.Client.REGISTERCODE:
action.isRegisterCode();
break;
case DataCodes.Client.LOGIN:
try {
user = action.login();
if (String.valueOf(user.getLogLevel()).equals(DataCodes.Params.LogLevel.ALL)) {
clientLogger = new ClientLogger(client, Level.ALL).getLogger();
} else if (String.valueOf(user.getLogLevel()).equals(DataCodes.Params.LogLevel.WARNING)) {
clientLogger = new ClientLogger(client, Level.WARN).getLogger();
} else {
clientLogger = new ClientLogger(client, Level.OFF).getLogger();
}
logger.info("New Client details - IP: " + client.getIPAddress() + "\n" +
"Port: " + client.getPort());
logger.info("Logged in successfully");
notLoggedIn = false;
} catch (IOException | UserNotExistException | IllegalPasswordException e) {
clientSender.loginFailed();
logger.warn("Login failed", e);
} catch (IllegalCodeException e) {
clientSender.unexpectedError();
logger.warn("An unexpected error occurred", e);
}
break;
case DataCodes.Client.REGISTER:
try {
user = action.register();
clientLogger = new ClientLogger(client, Level.OFF).getLogger();
logger.info("Registered in successfully");
notLoggedIn = false;
} catch (IOException e) {
clientSender.registerFailed();
logger.warn("Register failed", e);
} catch (UserAlreadyExistException e) {
clientSender.registerFailed_UserExist();
logger.warn("Couldn't register, user already exist", e);
} catch (RegisterCodeNotExistException e) {
clientSender.registerCodeNotExist();
logger.warn("Couldn't register, given register code do not exist");
}
break;
default:
clientSender.userNotLoggedIn();
logger.warn("User isn't logged in");
break;
}
}
int resultCode = new ClientReceiver(user, client, clientSender, clientPublicKey, privateKey, clientLogger).main();
if (resultCode == ClientReceiver.ResultCodes.EXIT) {
client.close();
logger.info("Closed connection to client");
} else if (resultCode == ClientReceiver.ResultCodes.UNEXPECTEDEXIT) {
client.close();
logger.warn("Unexpected closed the connection to client");
}
} catch (SocketException e) {
logger.error("Socket Exception for client " + client.getId() + " occurred", e);
} catch (IOException e) {
logger.error("IO Exception for client " + client.getId() +" occurred", e);
} catch (FatalIOException e) {
String name;
int errno;
ErrorCodes errorCodes = new ErrorCodes();
Field[] fields = ErrorCodes.class.getFields();
for (Field field : fields) {
try {
name = field.getName();
errno = (int) field.get(errorCodes);
if (errno == e.getErrno()) {
logger.fatal("Fatal IOException occurred while login or register - Errno: " + e.getErrno() + " (" + name + ")", e);
return;
}
} catch (IllegalAccessException illegalAccessException) {
illegalAccessException.printStackTrace();
}
}
logger.error("Fatal IOException occurred while login or register - Errno: " + e.getErrno(), e);
} catch (UnexpectedException e) {
e.printStackTrace();
}
});
} catch (Exception e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
logger.error("An unexpected error occurred: " + stringWriter, e);
}
}
}
public void close() throws IOException {
serverSocket.close();
logger.info("Closed server");
}
}

View File

@ -0,0 +1,39 @@
package org.blueshard.olymp.sql;
import org.blueshard.olymp.Main;
import java.sql.*;
public class SQL {
private Connection connection = null;
public SQL () {
try {
Class.forName("org.hsqldb.jdbcDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
return;
}
try {
connection = DriverManager.getConnection("jdbc:hsqldb:file:/srv/hsqldb/olympdb/olympdb", "OLYMP", "&C=@zFR7kLQvGy%e");
} catch (SQLException e) {
e.printStackTrace();
return;
}
}
public void close() throws SQLException {
connection.close();
}
public Connection getConnection() {
return connection;
}
public static void checkpoint() throws SQLException {
Main.getConnection().createStatement().execute("CHECKPOINT");
}
}

View File

@ -0,0 +1,22 @@
package org.blueshard.olymp.sql;
public class SQLPosition {
public static class USERS {
public static final int UUID = 1;
public static final int USERNAME = 2;
public static final int PASSWORD = 3;
public static final int SALT = 4;
public static final int MAIL = 5;
public static final int ACTIVE = 6;
public static final int USERLEVEL = 7;
public static final int LOGLEVEL = 8;
public static final int MAX_FILES = 9;
public static final int FILES = 10;
public static final int MAX_FILES_SIZE = 11;
public static final int FILES_SIZE = 12;
}
}

View File

@ -0,0 +1,146 @@
package org.blueshard.olymp.user;
import org.blueshard.olymp.Main;
import org.blueshard.olymp.exception.*;
import org.blueshard.olymp.files.ServerFiles;
import org.blueshard.olymp.register_code.RegisterCode;
import org.blueshard.olymp.security.Password;
import org.blueshard.olymp.sql.SQL;
import org.blueshard.olymp.sql.SQLPosition;
import org.blueshard.olymp.utils.*;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.sql.*;
import java.util.*;
public class User extends UserInfos {
private Password.PasswordInfos passwordInfos;
public User(String UUID) throws UserNotExistException, FatalIOException {
super(UUID);
if (!isUser(UUID)){
throw new UserNotExistException(UUID, "The user " + UUID + " doesn't exists");
}
try {
PreparedStatement preparedStatement = Main.getConnection().prepareStatement("SELECT PASSWORD, SALT FROM USERS WHERE (UUID = ?)");
preparedStatement.setString(1, UUID);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
passwordInfos = new Password.PasswordInfos(Base64.getDecoder().decode(resultSet.getString(1)), Base64.getDecoder().decode(resultSet.getString(2)));
}
} catch (SQLException e) {
e.printStackTrace();
throw new FatalIOException(ErrorCodes.couldnt_get_user_information, "Couldn't get user information for user " + UUID, e);
}
}
public boolean equalsPassword(String clearPassword) throws InvalidKeySpecException {
return Password.createPassword(clearPassword, passwordInfos.getSaltAsBytes()).getPasswordAsString().equals(passwordInfos.getPasswordAsString());
}
public static User createNewUser(String registerCode, String username, String password, String salt, String mailAddress) throws FatalIOException, UserAlreadyExistException, RegisterCodeNotExistException {
if (isUser(username)) {
throw new UserAlreadyExistException(username, "The user " + username + " already exists");
}
if (!RegisterCode.isRegisterCode(registerCode)) {
throw new RegisterCodeNotExistException(registerCode);
}
String uuid = UUID.randomUUID().toString();
File userDirectory = new File(new ServerFiles.user_files(uuid).user_files_dir);
if (!userDirectory.mkdir()) {
throw new FatalIOException(ErrorCodes.couldnt_create_userfiles_folder, "Couldn't create " + new ServerFiles.user_files(uuid).user_files_dir);
}
//--------------------------------------------------------------------------------------//
try {
PreparedStatement preparedStatement = Main.getConnection().prepareStatement("INSERT INTO USERS (UUID, USERNAME, PASSWORD, SALT, EMAIL) VALUES (?, ?, ?, ?, ?)");
preparedStatement.setString(1, uuid);
preparedStatement.setString(2, username);
preparedStatement.setString(3, password);
preparedStatement.setString(4, salt);
preparedStatement.setString(5, mailAddress);
preparedStatement.executeUpdate();
SQL.checkpoint();
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_create_user_information, "Failed to add new user", e);
}
RegisterCode.removeRegisterCode(registerCode);
try {
return new User(username);
} catch (UserNotExistException e) {
//shouldn't get thrown
return null;
}
}
public static void deleteUser(String UUID) throws FatalIOException, IOException {
try {
PreparedStatement preparedStatement = Main.getConnection().prepareStatement("DELETE FROM USERS WHERE UUID = ?");
preparedStatement.setString(1, UUID);
preparedStatement.executeUpdate();
SQL.checkpoint();
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_delete_user_information, "Couldn't delete user information for user " + UUID, e);
}
File file;
ArrayList<File> customUserFiles = FileUtils.getAllFilesInDirectory(new ServerFiles.user_files(UUID).user_files_dir);
ListIterator<File> customUserFileListIterator = customUserFiles.listIterator(customUserFiles.size());
while(customUserFileListIterator.hasPrevious()) {
file = customUserFileListIterator.previous();
if (!file.delete()) {
if (file.isDirectory()) {
throw new FatalIOException(ErrorCodes.couldnt_delete_custom_user_directory, "Couldn't delete custom user folder " + file.getAbsolutePath());
} else {
throw new FatalIOException(ErrorCodes.couldnt_delete_custom_user_file, "Couldn't delete custom user file " + file.getAbsolutePath());
}
}
}
}
public static boolean isUser(String UUID) throws FatalIOException {
try {
Statement statement = Main.getConnection().createStatement();
ResultSet resultSet = statement.executeQuery("SELECT UUID FROM USERS");
while (resultSet.next()) {
if (resultSet.getString(1).equals(UUID)) {
return true;
}
}
resultSet.close();
return false;
} catch (SQLException e) {
throw new FatalIOException(ErrorCodes.couldnt_get_user_information, "Couldn't get all usernames", e);
}
}
}

View File

@ -0,0 +1,112 @@
package org.blueshard.olymp.user;
import org.blueshard.olymp.Main;
import org.blueshard.olymp.exception.ErrorCodes;
import org.blueshard.olymp.exception.FatalIOException;
import org.blueshard.olymp.files.ConfReader;
import org.blueshard.olymp.files.ConfWriter;
import org.blueshard.olymp.files.ServerFiles;
import org.blueshard.olymp.security.Password;
import org.blueshard.olymp.sql.SQL;
import org.blueshard.olymp.sql.SQLPosition;
import java.io.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Base64;
import java.util.TreeMap;
public class UserInfos {
private final String UUID;
private String username;
private Password.PasswordInfos passwordInfos;
private String mail;
private boolean active;
private int userLevel;
private int logLevel;
private long maxFiles;
private long files;
private double maxFilesSize;
private double filesSize;
public UserInfos(String UUID) throws FatalIOException {
try {
PreparedStatement preparedStatement = Main.getConnection().prepareStatement("SELECT * FROM USERS WHERE (UUID = ?)");
preparedStatement.setString(1, UUID);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
this.UUID = UUID;
this.username = resultSet.getString(SQLPosition.USERS.USERNAME);
this.passwordInfos = new Password.PasswordInfos(Base64.getDecoder().decode(resultSet.getString(SQLPosition.USERS.PASSWORD)),
Base64.getDecoder().decode(resultSet.getString(SQLPosition.USERS.SALT)));
this.mail = resultSet.getString(SQLPosition.USERS.MAIL);
this.active = resultSet.getBoolean(SQLPosition.USERS.ACTIVE);
this.userLevel = resultSet.getInt(SQLPosition.USERS.USERLEVEL);
this.logLevel = resultSet.getInt(SQLPosition.USERS.LOGLEVEL);
this.maxFiles = resultSet.getLong(SQLPosition.USERS.MAX_FILES);
this.files = resultSet.getLong(SQLPosition.USERS.FILES);
this.maxFilesSize = resultSet.getDouble(SQLPosition.USERS.MAX_FILES_SIZE);
this.filesSize = resultSet.getDouble(SQLPosition.USERS.FILES_SIZE);
} else {
throw new FatalIOException(ErrorCodes.couldnt_get_user_information, "Couldn't get user information for user " + UUID);
}
} catch (SQLException e) {
e.printStackTrace();
throw new FatalIOException(ErrorCodes.couldnt_get_user_information, "Couldn't get user information for user " + UUID, e);
}
}
public String getUUID() {
return UUID;
}
public String getUsername() {
return username;
}
public Password.PasswordInfos getPasswordInfos() {
return passwordInfos;
}
public String getMail() {
return mail;
}
public boolean getActive() {
return active;
}
public int getUserLevel() {
return userLevel;
}
public int getLogLevel() {
return logLevel;
}
public long getMaxFiles() {
return maxFiles;
}
public long getFiles() {
return files;
}
public double getMaxFilesSize() {
return maxFilesSize;
}
public double getFilesSize() {
return filesSize;
}
public String getUserfileDirectory() {
return new ServerFiles.user_files(getUUID()).user_files_dir;
}
}

View File

@ -0,0 +1 @@
#empty

View File

@ -0,0 +1,76 @@
package org.blueshard.olymp.utils;
public class ConsoleColors {
// Reset
public static final String RESET = "\033[0m"; // Text Reset
// Regular Colors
public static final String BLACK = "\033[0;30m"; // BLACK
public static final String RED = "\033[0;31m"; // RED
public static final String GREEN = "\033[0;32m"; // GREEN
public static final String YELLOW = "\033[0;33m"; // YELLOW
public static final String BLUE = "\033[0;34m"; // BLUE
public static final String PURPLE = "\033[0;35m"; // PURPLE
public static final String CYAN = "\033[0;36m"; // CYAN
public static final String WHITE = "\033[0;37m"; // WHITE
// Bold
public static final String BLACK_BOLD = "\033[1;30m"; // BLACK
public static final String RED_BOLD = "\033[1;31m"; // RED
public static final String GREEN_BOLD = "\033[1;32m"; // GREEN
public static final String YELLOW_BOLD = "\033[1;33m"; // YELLOW
public static final String BLUE_BOLD = "\033[1;34m"; // BLUE
public static final String PURPLE_BOLD = "\033[1;35m"; // PURPLE
public static final String CYAN_BOLD = "\033[1;36m"; // CYAN
public static final String WHITE_BOLD = "\033[1;37m"; // WHITE
// Underline
public static final String BLACK_UNDERLINED = "\033[4;30m"; // BLACK
public static final String RED_UNDERLINED = "\033[4;31m"; // RED
public static final String GREEN_UNDERLINED = "\033[4;32m"; // GREEN
public static final String YELLOW_UNDERLINED = "\033[4;33m"; // YELLOW
public static final String BLUE_UNDERLINED = "\033[4;34m"; // BLUE
public static final String PURPLE_UNDERLINED = "\033[4;35m"; // PURPLE
public static final String CYAN_UNDERLINED = "\033[4;36m"; // CYAN
public static final String WHITE_UNDERLINED = "\033[4;37m"; // WHITE
// Background
public static final String BLACK_BACKGROUND = "\033[40m"; // BLACK
public static final String RED_BACKGROUND = "\033[41m"; // RED
public static final String GREEN_BACKGROUND = "\033[42m"; // GREEN
public static final String YELLOW_BACKGROUND = "\033[43m"; // YELLOW
public static final String BLUE_BACKGROUND = "\033[44m"; // BLUE
public static final String PURPLE_BACKGROUND = "\033[45m"; // PURPLE
public static final String CYAN_BACKGROUND = "\033[46m"; // CYAN
public static final String WHITE_BACKGROUND = "\033[47m"; // WHITE
// High Intensity
public static final String BLACK_BRIGHT = "\033[0;90m"; // BLACK
public static final String RED_BRIGHT = "\033[0;91m"; // RED
public static final String GREEN_BRIGHT = "\033[0;92m"; // GREEN
public static final String YELLOW_BRIGHT = "\033[0;93m"; // YELLOW
public static final String BLUE_BRIGHT = "\033[0;94m"; // BLUE
public static final String PURPLE_BRIGHT = "\033[0;95m"; // PURPLE
public static final String CYAN_BRIGHT = "\033[0;96m"; // CYAN
public static final String WHITE_BRIGHT = "\033[0;97m"; // WHITE
// Bold High Intensity
public static final String BLACK_BOLD_BRIGHT = "\033[1;90m"; // BLACK
public static final String RED_BOLD_BRIGHT = "\033[1;91m"; // RED
public static final String GREEN_BOLD_BRIGHT = "\033[1;92m"; // GREEN
public static final String YELLOW_BOLD_BRIGHT = "\033[1;93m";// YELLOW
public static final String BLUE_BOLD_BRIGHT = "\033[1;94m"; // BLUE
public static final String PURPLE_BOLD_BRIGHT = "\033[1;95m";// PURPLE
public static final String CYAN_BOLD_BRIGHT = "\033[1;96m"; // CYAN
public static final String WHITE_BOLD_BRIGHT = "\033[1;97m"; // WHITE
// High Intensity backgrounds
public static final String BLACK_BACKGROUND_BRIGHT = "\033[0;100m";// BLACK
public static final String RED_BACKGROUND_BRIGHT = "\033[0;101m";// RED
public static final String GREEN_BACKGROUND_BRIGHT = "\033[0;102m";// GREEN
public static final String YELLOW_BACKGROUND_BRIGHT = "\033[0;103m";// YELLOW
public static final String BLUE_BACKGROUND_BRIGHT = "\033[0;104m";// BLUE
public static final String PURPLE_BACKGROUND_BRIGHT = "\033[0;105m"; // PURPLE
public static final String CYAN_BACKGROUND_BRIGHT = "\033[0;106m"; // CYAN
public static final String WHITE_BACKGROUND_BRIGHT = "\033[0;107m"; // WHITE
}

View File

@ -0,0 +1,38 @@
package org.blueshard.olymp.utils;
import org.blueshard.olymp.exception.ErrorCodes;
import java.lang.reflect.Field;
import java.util.Arrays;
public class ExceptionUtils {
public static String errorNumberToString(int errorNumber) {
String name;
int errno;
ErrorCodes errorCodes = new ErrorCodes();
Field[] fields = ErrorCodes.class.getFields();
for (Field field : fields) {
try {
name = field.getName();
errno = (int) field.get(errorCodes);
if (errno == errorNumber) {
return name;
}
} catch (IllegalAccessException illegalAccessException) {
illegalAccessException.printStackTrace();
}
}
return null;
}
public static String extractExceptionMessage(Throwable throwable) {
StringBuilder stringBuilder = new StringBuilder();
Arrays.asList(throwable.getStackTrace()).forEach(stackTraceElement -> stringBuilder.append(stackTraceElement).append("\n"));
return stringBuilder.toString();
}
}

View File

@ -0,0 +1,70 @@
package org.blueshard.olymp.utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
public class FileUtils {
public static ArrayList<File> getAllFilesInDirectory(String path) throws IOException {
ArrayList<File> files = new ArrayList<>();
Files.walk(Paths.get(path)).map(Path::toFile).forEach(files::add);
return files;
}
public static File[] sortFilesInDirectory(File path) {
File[] files = path.listFiles();
Arrays.sort(files, (object1, object2) -> object1.getName().compareToIgnoreCase(object2.getName()));
return files;
}
public class CreateHashSum {
String file;
CreateHashSum(String file) {
this.file = file;
}
public String MD5() throws IOException {
try {
StringBuilder hexString = new StringBuilder();
MessageDigest md5 = MessageDigest.getInstance("MD5");
InputStream inputStream = Files.newInputStream(Paths.get(file));
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
md5.update(buffer, 0 , length);
}
byte[] digest = md5.digest();
for (byte b : digest) {
if ((0xff & b) < 0x10) {
hexString.append("0").append(Integer.toHexString((0xFF & b)));
} else {
hexString.append(Integer.toHexString(0xFF & b));
}
}
return hexString.toString();
} catch (NoSuchAlgorithmException ignore) {
return null;
}
}
}
}

View File

@ -0,0 +1,196 @@
package org.blueshard.olymp.utils;
public class SizeUnit {
private int unit;
private double size;
private final static int BYTE = 1;
private final static int KILOBYTE = 3;
private final static int MEGABYTE = 5;
private final static int GIGABYTE = 7;
private final static int TERRABYTE = 9;
private final static int PETABYTE = 11;
private final static int EXABYTE = 13;
SizeUnit(int unit, double size){
this.unit = unit;
this.size = size;
}
public static SizeUnit BYTES(double bytes){
return new SizeUnit(BYTE, bytes);
}
public static SizeUnit KILOBYTE(double kilobytes) {
return new SizeUnit(KILOBYTE, kilobytes);
}
public static SizeUnit MEGABYTE(double megabytes) {
return new SizeUnit(MEGABYTE, megabytes);
}
public static SizeUnit GIGABYTE(double gigabytes) {
return new SizeUnit(GIGABYTE, gigabytes);
}
public static SizeUnit TERRABYTE(double terrabytes) {
return new SizeUnit(TERRABYTE, terrabytes);
}
public static SizeUnit PETABYTE(double petabytes) {
return new SizeUnit(PETABYTE, petabytes);
}
public static SizeUnit EXABYTE(double exabytes) {
return new SizeUnit(EXABYTE, exabytes);
}
public Double toByte(){
switch (unit) {
case BYTE:
return size;
case KILOBYTE:
return size * 1000;
case MEGABYTE:
return size * 1000000;
case GIGABYTE:
return size * 1000000000;
case TERRABYTE:
return size * 1000000000000L;
case PETABYTE:
return size * 1000000000000000L;
case EXABYTE:
return size * 1000000000000000000L;
default:
return 0D;
}
}
public Double toKilobyte(){
switch (unit) {
case BYTE:
return size / 1000;
case KILOBYTE:
return size;
case MEGABYTE:
return size * 1000;
case GIGABYTE:
return size * 1000000;
case TERRABYTE:
return size * 1000000000;
case PETABYTE:
return size * 1000000000000L;
case EXABYTE:
return size * 1000000000000000L;
default:
return 0D;
}
}
public Double toMegabyte(){
switch (unit) {
case BYTE:
return size / 1000000;
case KILOBYTE:
return size / 1000;
case MEGABYTE:
return size;
case GIGABYTE:
return size * 1000;
case TERRABYTE:
return size * 1000000;
case PETABYTE:
return size * 1000000000;
case EXABYTE:
return size * 1000000000000L;
default:
return 0D;
}
}
public Double toGigabyte(){
switch (unit) {
case BYTE:
return size / 1000000000L;
case KILOBYTE:
return size / 1000000;
case MEGABYTE:
return size / 1000;
case GIGABYTE:
return size;
case TERRABYTE:
return size * 1000;
case PETABYTE:
return size * 1000000;
case EXABYTE:
return size * 1000000000;
default:
return 0D;
}
}
public Double toTerrabyte(){
switch (unit) {
case BYTE:
return size / 1000000000000L;
case KILOBYTE:
return size / 1000000000;
case MEGABYTE:
return size / 1000000;
case GIGABYTE:
return size / 1000;
case TERRABYTE:
return size;
case PETABYTE:
return size * 1000;
case EXABYTE:
return size * 1000000;
default:
return 0D;
}
}
public Double toPetabyte(){
switch (unit) {
case BYTE:
return size / 1000000000000000L;
case KILOBYTE:
return size / 1000000000000L;
case MEGABYTE:
return size / 1000000000;
case GIGABYTE:
return size / 1000000;
case TERRABYTE:
return size / 1000;
case PETABYTE:
return size;
case EXABYTE:
return size * 1000;
default:
return 0D;
}
}
public Double toExabyte(){
switch (unit) {
case BYTE:
return size / 1000000000000000000L;
case KILOBYTE:
return size / 1000000000000000L;
case MEGABYTE:
return size / 1000000000000L;
case GIGABYTE:
return size / 1000000000;
case TERRABYTE:
return size / 1000000;
case PETABYTE:
return size / 1000;
case EXABYTE:
return size;
default:
return 0D;
}
}
}

View File

@ -0,0 +1,17 @@
package org.blueshard.olymp.utils;
import java.util.Map;
public class StringUtils {
public static String format(String string, Map<String, String> formatMap){
for(Map.Entry<String, String> entry: formatMap.entrySet()) {
string = string.replace("{" + entry.getKey() + "}", entry.getValue());
}
return string;
}
}

View File

@ -0,0 +1,40 @@
package org.blueshard.olymp.version;
public class ServerVersion extends Version {
public ServerVersion(String version) {
super(version);
}
@Override
public int toInt() {
switch (toString()) {
case "0.1.0":
return 1;
default:
return 0;
}
}
public boolean higherThan(String version) {
return higherThan(new ServerVersion(version));
}
@Override
public boolean higherThan(Version version) {
return toInt() > version.toInt();
}
public boolean lowerThan(String version) {
return lowerThan(new ServerVersion(version));
}
@Override
public boolean lowerThan(Version version) {
return toInt() < version.toInt();
}
public static ServerVersion currentVersion() {
return new ServerVersion("0.1.0");
}
}

View File

@ -0,0 +1,133 @@
package org.blueshard.olymp.version;
import org.blueshard.olymp.exception.ErrorCodes;
import org.blueshard.olymp.exception.FatalIOException;
import org.blueshard.olymp.files.ConfReader;
import org.blueshard.olymp.files.ServerFiles;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TheosUIVersion extends Version {
TreeMap<String, String> versions;
Set<String> versionsKeySet;
public TheosUIVersion(String version) throws FatalIOException {
super(version);
try {
versions = new ConfReader.MultipleConfReader(ServerFiles.etc.versions).getAll("TheosUI", true);
} catch (IOException e) {
throw new FatalIOException(ErrorCodes.couldnt_read_versions_conf, "Failed to read versions.conf", e);
}
versionsKeySet = versions.keySet();
}
@Override
public int toInt() {
String[] allVersions = versionsKeySet.toArray(new String[versionsKeySet.size()]);
for (int i = 0; i < allVersions.length; i++) {
if (allVersions[i].equals(toString())) {
return i + 1;
}
}
return 0;
}
private int toInt(String version) {
String[] allVersions = versionsKeySet.toArray(new String[versionsKeySet.size()]);
for (int i = 0; i < allVersions.length; i++) {
if (allVersions[i].equals(version)) {
return i + 1;
}
}
return 0;
}
public boolean higherThan(String version) {
return toInt() > toInt(version);
}
@Override
public boolean higherThan(Version version) {
return toInt() > toInt(version.toString());
}
public boolean lowerThan(String version) {
return toInt() < toInt(version);
}
@Override
public boolean lowerThan(Version version) {
return toInt() < toInt(version.toString());
}
public String getChanges() {
return versions.get(toString()).split(":")[1];
}
public boolean hasOptionalUpdate() throws FatalIOException {
if (toInt() != currentVersion().toInt()) {
Map<String, String> reverseVersions = versions.descendingMap();
for (Map.Entry<String, String> stringStringEntry : reverseVersions.entrySet()) {
String key = stringStringEntry.getKey();
String value = stringStringEntry.getValue().split(":")[0];
if (!key.equals(toString())) {
if (value.equals("optional")) {
return true;
}
} else {
return false;
}
}
}
return false;
}
public boolean hasRequiredUpdate() throws FatalIOException {
if (toInt() != currentVersion().toInt()) {
Map<String, String> reverseVersions = versions.descendingMap();
for (Map.Entry<String, String> stringStringEntry : reverseVersions.entrySet()) {
String key = stringStringEntry.getKey();
String value = stringStringEntry.getValue().split(":")[0];
if (!key.equals(toString())) {
if (value.equals("required")) {
return true;
}
} else {
return false;
}
}
}
return false;
}
public static TheosUIVersion currentVersion() throws FatalIOException {
try {
return new TheosUIVersion(new ConfReader.MultipleConfReader(ServerFiles.etc.versions).getAll("TheosUI", true).lastKey());
} catch (IOException e) {
throw new FatalIOException(ErrorCodes.couldnt_read_versions_conf, "Failed to read versions.conf", e);
}
}
public static TheosUIVersion toArtificeUIVersion(int versionAsInt) throws IOException, FatalIOException {
Set<String> versionsKeySet = new ConfReader.MultipleConfReader(ServerFiles.etc.versions).getAll("TheosUI", true).keySet();
String[] allVersions = versionsKeySet.toArray(new String[versionsKeySet.size()]);
for (int i = allVersions.length; i > 0; i--) {
if (i == versionAsInt) {
return new TheosUIVersion(allVersions[i]);
}
}
return null;
}
}

View File

@ -0,0 +1,21 @@
package org.blueshard.olymp.version;
public abstract class Version {
private final String version;
public Version(String version) {
this.version = version;
}
@Override
public String toString() {
return version;
}
public abstract int toInt();
public abstract boolean higherThan(Version version);
public abstract boolean lowerThan(Version version);
}

View File

@ -0,0 +1,16 @@
package org.blueshard.sekaijuclt;
import org.apache.log4j.Level;
import org.blueshard.sekaijuclt.client.MainClient;
import org.blueshard.sekaijuclt.logging.MainLogger;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
MainClient client = new MainClient(8269, "192.168.2.104", new MainLogger(Level.ALL).getLogger());
client.start("/srv/ssl/sslTrustStore.jks", "@VR&_*p%9!L+kC3FZ4QX");
}
}

View File

@ -0,0 +1 @@
#empty

View File

@ -0,0 +1,52 @@
package org.blueshard.sekaijuclt.client;
import org.blueshard.sekaijuclt.data.Data;
import org.blueshard.sekaijuclt.data.DataCodes;
import org.blueshard.sekaijuclt.exception.IllegalCodeException;
import org.blueshard.sekaijuclt.security.Password;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class Action {
private final DataInputStream dataInputStream;
private final ServerSender serverSender;
public Action(InputStream inputStream, ServerSender serverSender) {
this.dataInputStream = new DataInputStream(inputStream);
this.serverSender = serverSender;
}
public int login(String username, String clearPassword) throws IOException {
Password.PasswordInfos passwordInfos = Password.createPassword(clearPassword, new byte[64]);
serverSender.login(username, passwordInfos);
return new Data(dataInputStream.readUTF()).getCode();
}
public int register(String username, String clearPassword, String email) throws IOException {
Password.PasswordInfos passwordInfos = Password.createPassword(clearPassword, new byte[64]);
serverSender.register(username, passwordInfos, email);
return new Data(dataInputStream.readUTF()).getCode();
}
public String[][] getFilesData(String directory) throws IOException, IllegalCodeException {
serverSender.getFilesData();
Data data = new Data(dataInputStream.readUTF());
String[][] files = new String[2][data.getData().hashCode()];
if (data.getCode() != DataCodes.Server.SENDFILESDATA) {
throw new IllegalCodeException(data.getCode(), DataCodes.Server.SENDFILESDATA);
}
data.getData().forEach((index, file) -> {
if (index.startsWith("d")) {
files[0][Integer.parseInt(index.substring(1))] = file;
} else {
files[1][Integer.parseInt(index.substring(1))] = file;
}
});
return files;
}
}

View File

@ -0,0 +1,110 @@
package org.blueshard.sekaijuclt.client;
import org.apache.log4j.Logger;
import org.blueshard.sekaijuclt.data.DataCodes;
import org.blueshard.sekaijuclt.exception.IllegalCodeException;
import org.blueshard.sekaijuserv.data.Data;
import org.blueshard.sekaijuserv.exception.UnexpectedException;
import org.blueshard.sekaijuserv.server.ClientSender;
import org.blueshard.sekaijuserv.user.UserParams;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.security.GeneralSecurityException;
import java.util.Base64;
public class MainClient {
private final int serverPort;
private final String serverIP;
private final Logger logger;
public MainClient(int serverPort, String serverIP, Logger logger) {
this.serverPort = serverPort;
this.serverIP = serverIP;
this.logger = logger;
}
public void start(String trustStoreFile, String trustStorePassword) throws IOException {
System.setProperty("javax.net.ssl.trustStore", trustStoreFile);
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
SSLSocket server = (SSLSocket) SSLSocketFactory.getDefault().createSocket("192.168", 8269);
byte[] privateKey;
try {
privateKey = new org.blueshard.sekaijuserv.server.Action(null, new ClientSender(server, new byte[0], logger)).publicKey().getEncoded();
} catch (GeneralSecurityException | UnexpectedException ignore) {
return;
}
byte[] serverPublicKey = Base64.getDecoder().decode(new Data(new DataInputStream(server.getInputStream()).readUTF()).getFromData(UserParams.Key.PUBLICKEY));
ServerSender serverSender;
try {
serverSender = new ServerSender(server.getOutputStream(), serverPublicKey, logger);
} catch (GeneralSecurityException | UnexpectedException ignore) {
return;
}
Action action = new Action(null, serverSender);
logger.info("Started client");
Console console = System.console();
while (true) {
String logReg = console.readLine("To connect type 'login' to login, or 'register' to register: ").strip().toLowerCase();
if (logReg.equals("login")) {
String username = console.readLine("Username: ").strip();
String password = String.valueOf(console.readPassword("Password: ")).strip();
int resultCode = action.login(username, password);
if (resultCode == DataCodes.Server.LOGINFAIL) {
logger.warn("Login failed");
} else if (resultCode == DataCodes.Server.LOGINSUCCESS) {
logger.info("Logged in successfully");
break;
} else if (resultCode == DataCodes.Server.UNEXPECTEDERROR) {
logger.warn("An unexpected error occurred");
} else if (resultCode == DataCodes.Server.UNEXPECTEDEXIT) {
logger.fatal("Server exited unexpected");
return;
}
} else if (logReg.equals("register")) {
String password;
String passwordAgain;
String username = console.readLine("Username: ");
do {
password = String.valueOf(console.readPassword("Password: "));
passwordAgain = String.valueOf(console.readPassword("Re-type your Password: "));
} while (!password.equals(passwordAgain));
String email = console.readLine("Email: ");
int resultCode = action.register(username, password, email);
if (resultCode == DataCodes.Server.REGISTERFAIL) {
logger.warn("Register failed");
} else if (resultCode == DataCodes.Server.REGISTERFAIL_USER_EXIST) {
logger.warn("The user already exists");
} else if (resultCode == DataCodes.Server.REGISTERSUCCESS) {
logger.info("Registered successfully");
break;
} else if (resultCode == DataCodes.Server.UNEXPECTEDERROR) {
logger.warn("An unexpected error occurred");
} else if (resultCode == DataCodes.Server.UNEXPECTEDEXIT) {
logger.fatal("Server exited unexpected");
return;
}
}
}
ServerSendRecv sendRecv = new ServerSendRecv(server, logger);
try {
sendRecv.main();
} catch (IllegalCodeException e) {
serverSender.unexpectedExit();
}
}
}

View File

@ -0,0 +1,143 @@
package org.blueshard.sekaijuclt.client;
import org.apache.log4j.Logger;
import org.blueshard.sekaijuclt.exception.IllegalCodeException;
import javax.net.ssl.SSLSocket;
import java.io.Console;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
public class ServerSendRecv {
private final Logger logger;
private final Action action;
private final DataInputStream serverInput;
private final ServerSender serverSender;
public ServerSendRecv(SSLSocket socket, ServerSender serverSender, byte[] privateKey, Logger logger) throws IOException {
this.logger = logger;
try {
this.serverInput = new DataInputStream(socket.getInputStream());
this.serverSender = serverSender;
} catch (IOException e) {
throw new IOException(ResultCode.UNEXPECTEDEXIT + ";" + e.getMessage());
}
this.action = new Action(socket.getInputStream(), this.serverSender);
}
public int main() throws IOException, IllegalCodeException {
Console console = System.console();
String input;
System.out.println("Type ... to ...: " +
" exit Close connection to server" +
" file-mode Enter file mode");
while (true) {
input = console.readLine("Action: ").strip().toLowerCase();
if (input.equals("exit")) {
serverSender.exit();
return ResultCode.EXIT;
} else if (input.equals("file-mode")) {
while (true) {
SendRecvFiles files = new SendRecvFiles(action);
input = console.readLine(files.getCurrentDirectory() + ": ").strip().toLowerCase();
if (input.startsWith("cd")) {
files.cdDirectory(input.substring(2).strip());
} else if (input.equals("ls")) {
StringBuilder stringBuilder = new StringBuilder();
files.listFilesAsList().forEach(s -> stringBuilder.append(s).append(" "));
System.out.println(stringBuilder.toString());
} else if (input.equals("exit")) {
return ResultCode.EXIT;
}
}
}
}
}
public static class SendRecvFiles {
private final Action action;
private ArrayList<String> currentDirectory = new ArrayList<>();
private HashMap<String, Object> files = new HashMap<>();
public SendRecvFiles(Action action) throws IOException, IllegalCodeException {
this.action = action;
addToFiles(action.getFilesData(""));
}
private void addToFiles(String[][] data) {
for (int i = 0; i < data[0].length; i++) {
files.put(data[0][i], new HashMap<>());
}
for (int i = 0; i < data[1].length; i++) {
files.put(data[1][i], null);
}
}
private ArrayList<String> toSortedArrayList(String[] files) {
Arrays.sort(files, String::compareToIgnoreCase);
return new ArrayList<>(Arrays.asList(files));
}
public void cdDirectory(String directory) throws IOException, IllegalCodeException {
directory = directory.strip();
if (directory.equals("..")) {
if (currentDirectory.isEmpty()) {
return;
} else {
currentDirectory.remove(currentDirectory.size() - 1);
}
} else {
if (listFiles().get(directory) != null) {
HashMap<String, Object> files = (HashMap<String, Object>) listFiles().get(directory);
if (files.isEmpty()) {
addToFiles(action.getFilesData(getCurrentDirectory() + "/"));
}
currentDirectory.add(directory);
}
}
}
public ArrayList<String> listFilesAsList() {
HashMap<String, Object> currentFiles = new HashMap<>();
for (String s: currentDirectory) {
currentFiles = (HashMap<String, Object>) files.get(s);
}
return toSortedArrayList((String[]) currentFiles.keySet().toArray());
}
public HashMap<String, Object> listFiles() {
HashMap<String, Object> currentFiles = new HashMap<>();
for (String s: currentDirectory) {
currentFiles = (HashMap<String, Object>) files.get(s);
}
return currentFiles;
}
public String getCurrentDirectory() {
StringBuilder stringBuilder = new StringBuilder();
currentDirectory.forEach(stringBuilder::append);
return stringBuilder.toString();
}
}
public static class ResultCode {
public static final int EXIT = 25;
public static final int UNEXPECTEDEXIT = 84;
}
}

View File

@ -0,0 +1,145 @@
package org.blueshard.sekaijuclt.client;
import org.apache.log4j.Logger;
import org.blueshard.sekaijuclt.data.Data;
import org.blueshard.sekaijuclt.data.DataCodes;
import org.blueshard.sekaijuclt.security.Password;
import org.blueshard.sekaijuclt.user.UserParams;
import org.blueshard.sekaijuserv.e2ee.E2EEConverter;
import org.blueshard.sekaijuserv.exception.UnexpectedException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
public class ServerSender {
private final DataOutputStream dataOutputStream;
private final byte[] serverPublicKey;
private final Logger logger;
public ServerSender(OutputStream outputStream, byte[] serverPublicKey, Logger logger) throws IllegalBlockSizeException, UnexpectedException, InvalidKeySpecException, InvalidKeyException, BadPaddingException {
this.dataOutputStream = new DataOutputStream(outputStream);
this.serverPublicKey = serverPublicKey;
this.logger = logger;
if (serverPublicKey.length != 0) {
E2EEConverter.encrypt("Test", serverPublicKey); // just test if the server key works
}
}
private void send(Data data) throws IOException {
if (serverPublicKey.length == 0) {
dataOutputStream.writeUTF(data.getDataAsString() + "\n");
} else {
try {
dataOutputStream.writeUTF(E2EEConverter.encrypt(data.getDataAsString() + "\n", serverPublicKey));
} catch (UnexpectedException e) {
logger.error("An unexpected error occurred", e);
unexpectedError();
} catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException ignore) {
}
}
dataOutputStream.flush();
}
private void send(Data.Builder data) throws IOException {
send(data.getData());
}
private String loggerInfo(String data) {
return "Send " + data + " data";
}
private String loggerWarning(String data) {
return "Failed to send " + data + " data";
}
public void exit() {
try {
send(new Data.Builder(DataCodes.Client.EXIT));
logger.info(loggerInfo("exit"));
} catch (IOException e) {
logger.warn(loggerWarning("exit"));
}
}
public void unexpectedError() {
try {
send(new Data.Builder(DataCodes.Client.UNEXPECTEDERROR));
logger.info(loggerInfo("unexpected error"));
} catch (IOException e) {
logger.warn(loggerWarning("unexpected error"), e);
}
}
public void unexpectedExit() {
try {
send(new Data.Builder(DataCodes.Client.UNEXPECTEDEXIT));
logger.info(loggerInfo("unexpected exit"));
} catch (IOException e) {
logger.warn(loggerWarning("unexpected exit"), e);
}
}
public void publicKey(String publicKey) {
try {
Data.Builder data = new Data.Builder(DataCodes.Client.PUBLICKEY);
data.addData(org.blueshard.sekaijuserv.user.UserParams.Key.PUBLICKEY, publicKey);
send(data);
logger.info(loggerInfo("public key"));
} catch (IOException e) {
logger.warn(loggerWarning("public key"));
}
}
//----- login / register -----//
public void login(String username, Password.PasswordInfos passwordInfos) {
Data.Builder data = new Data.Builder(DataCodes.Client.LOGIN);
data.addData(UserParams.USERNAME, username);
data.addData(UserParams.PASSWORD, passwordInfos.getPasswordAsString());
data.addData(UserParams.SALT, passwordInfos.getSaltAsString());
try {
send(data);
logger.info(loggerInfo("login"));
} catch (IOException e) {
logger.warn(loggerWarning("login"), e);
}
}
public void register(String username, Password.PasswordInfos passwordInfos, String email) {
Data.Builder data = new Data.Builder(DataCodes.Client.REGISTER);
data.addData(UserParams.USERNAME, username);
data.addData(UserParams.PASSWORD, passwordInfos.getPasswordAsString());
data.addData(UserParams.SALT, passwordInfos.getSaltAsString());
data.addData(UserParams.EMAIL, email);
try {
send(data);
logger.info(loggerInfo("register"));
} catch (IOException e) {
logger.warn(loggerWarning("register"), e);
}
}
//----- files -----//
public void getFilesData() {
Data.Builder data = new Data.Builder(DataCodes.Client.GETFILESDATA);
try {
send(data);
logger.info(loggerInfo("get files data"));
} catch (IOException e) {
logger.warn(loggerWarning("get files data"), e);
}
}
}

View File

@ -0,0 +1,161 @@
package org.blueshard.sekaijuclt.data;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class Data {
private String dataAsString;
private Map<String, String> data = new HashMap<>();
public Data(String data) {
this.dataAsString = data;
String key = "";
String dataString = dataAsString;
String separator = getSeparator();
try {
if (separator.length() == 1) {
dataString = dataString.substring(dataString.indexOf(",")).strip();
} else {
dataString = dataString.substring(dataString.indexOf(",") + 1).strip();
}
} catch (StringIndexOutOfBoundsException e) {
dataString = "";
}
for (String string: dataString.split(separator)) {
string = string.strip();
if (string.equals(":") || string.equals(",") || string.equals("{") || string.equals("}")) {
continue;
} else if (key.isEmpty()) {
key = string;
} else {
this.data.put(key, string);
key = "";
}
}
}
public int getCode() {
int lenBeforeCode = 1 + getSeparator().length() + 1;
return Integer.parseInt(dataAsString.substring(lenBeforeCode, lenBeforeCode + DataCodes.DATACODESLENGHT));
}
public Map<String, String> getData() {
return data;
}
public String getDataAsString() {
return dataAsString;
}
public String getFromData(String key) {
return data.get(key);
}
private String getSeparator() {
return dataAsString.substring(1).split(":")[0];
}
public static class Builder {
private Map<String, String> data = new HashMap<>();
private int code;
public Builder(int code) {
this.code = code;
}
public String createData() {
String separator = createSeparator();
StringBuilder dataAsString = new StringBuilder("{" + separator + ":" + code);
data.forEach((key, value) -> dataAsString.append(",")
.append(separator)
.append(key)
.append(separator)
.append(":")
.append(separator)
.append(value)
.append(separator));
dataAsString.append("}");
return dataAsString.toString();
}
public String createSeparator() {
char choice;
StringBuilder stringBuilder = new StringBuilder();
String indicator = "'";
char[] choices = {'\'', '"', '^'};
data.forEach((key, value) -> stringBuilder.append(key).append(value));
String string = stringBuilder.toString();
while (true) {
if (string.contains(indicator)) {
switch (indicator) {
case "'" -> indicator = "\"";
case "\"" -> indicator = "^";
default -> {
choice = choices[new Random().nextInt(choices.length) - 1];
if (indicator.contains("|")) {
String[] splitted_indicator = indicator.split("\\|");
indicator = splitted_indicator[0] + choice + '|' + choice + splitted_indicator[1];
} else {
indicator = indicator + choice + '|' + choice + indicator;
}
}
}
} else {
return indicator;
}
}
}
public void addData(String key, String value) {
this.data.put(key, value);
}
public void addAllData(Map<String, String> allData) {
this.data.putAll(allData);
}
public int getCode() {
return code;
}
public Data getData() {
return new Data(getDataAsString());
}
public Map<String, String> getDataMap() {
return data;
}
public String getDataAsString() {
return createData();
}
}
public static boolean isDataString(String string) {
try {
string = string.strip();
if (string.startsWith("{") && string.endsWith("}") && string.contains(":")) {
String separator = string.substring(1).split(":")[0];
int lenBeforeCode = 1 + separator.length() + 1;
Integer.parseInt(string.substring(lenBeforeCode, lenBeforeCode + DataCodes.DATACODESLENGHT));
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
}

View File

@ -0,0 +1,50 @@
package org.blueshard.sekaijuclt.data;
public class DataCodes {
public static final int DATACODESLENGHT = 5;
public static class Client {
public static final int UNEXPECTEDERROR = 56400;
public static final int UNEXPECTEDEXIT = 95078;
public static final int EXIT = 69826;
public static final int PUBLICKEY = 19294;
public static final int LOGIN = 39208;
public static final int REGISTER = 84219;
public static final int GETFILESDATA = 28926;
public static final int GETFILE = 95868;
public static final int SENDFILE = 53639;
}
public static class Server {
public static final int UNEXPECTEDERROR = 29875;
public static final int UNEXPECTEDEXIT = 85048;
public static final int NOTLOGGEDIN = 77015;
public static final int EXIT = 42812;
public static final int PUBLICKEY = 19294;
public static final int LOGINFAIL = 11868;
public static final int LOGINSUCCESS = 54151;
public static final int REGISTERFAIL = 52300;
public static final int REGISTERFAIL_USER_EXIST= 77444;
public static final int REGISTERSUCCESS = 34367;
public static final int RECEIVEFILEFAIL = 45747;
public static final int RECEIVEFILESUCCESS = 75368;
public static final int SENDFILESDATA = 78946;
public static final int SENDFILEFAIL = 90173;
public static final int SENDFILESSUCCESS = 37272;
}
}

View File

@ -0,0 +1,48 @@
package org.blueshard.sekaijuclt.e2ee;
import org.blueshard.sekaijuserv.exception.UnexpectedException;
import org.blueshard.sekaijuserv.utils.ExceptionUtils;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class AESCipher {
private static final int keySize = 256;
public static byte[] generateKey() throws UnexpectedException {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(keySize);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
} catch (NoSuchAlgorithmException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
public static byte[] encrypt(byte[] input, byte[] key) throws UnexpectedException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
try {
SecretKey secretKey = new SecretKeySpec(key, 0, key.length, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(input);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new UnexpectedException(e);
}
}
public static byte[] decrypt(byte[] input, byte[] key) throws UnexpectedException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
try {
SecretKey secretKey = new SecretKeySpec(key, 0, key.length, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(input);
} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
throw new UnexpectedException(e);
}
}
}

View File

@ -0,0 +1,36 @@
package org.blueshard.sekaijuclt.e2ee;
import org.blueshard.sekaijuserv.exception.UnexpectedException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
public class E2EEConverter {
private final static String separator = "@";
public static String decrypt(String input, byte[] privateKey) throws UnexpectedException, BadPaddingException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException {
String[] inputAsArray = input.split(separator);
String key = inputAsArray[0];
String realInput = inputAsArray[1];
byte[] AESKey = RSACipher.decrypt(Base64.getDecoder().decode(key), privateKey);
return new String(AESCipher.decrypt(Base64.getDecoder().decode(realInput), AESKey));
}
public static String encrypt(String input, byte[] publicKey) throws UnexpectedException, BadPaddingException, InvalidKeyException, IllegalBlockSizeException, InvalidKeySpecException {
byte[] AESKey = AESCipher.generateKey();
String encryptedKey = Base64.getEncoder().encodeToString(RSACipher.encrypt(AESKey, publicKey));
String encryptedInput = Base64.getEncoder().encodeToString(AESCipher.encrypt(input.getBytes(StandardCharsets.UTF_8), AESKey));
return encryptedKey + separator + encryptedInput;
}
}

View File

@ -0,0 +1,57 @@
package org.blueshard.sekaijuclt.e2ee;
import org.blueshard.sekaijuserv.exception.UnexpectedException;
import org.blueshard.sekaijuserv.utils.ExceptionUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSACipher {
private static final int keySize = 2048;
public static KeyPair generateKeyPair() throws UnexpectedException {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
public static byte[] encrypt(byte[] key, byte[] publicKey) throws UnexpectedException, InvalidKeyException, InvalidKeySpecException, BadPaddingException {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
RSAPublicKey publicRSAKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicRSAKey);
return cipher.doFinal(key);
} catch (NoSuchAlgorithmException | IllegalBlockSizeException | NoSuchPaddingException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
public static byte[] decrypt(byte[] key, byte[] privateKey) throws UnexpectedException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, BadPaddingException {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privatePKCS8Key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privatePKCS8Key);
return cipher.doFinal(key);
} catch (NoSuchAlgorithmException | IllegalBlockSizeException e) {
throw new UnexpectedException(ExceptionUtils.extractExceptionMessage(e));
}
}
}

View File

@ -0,0 +1,37 @@
package org.blueshard.sekaijuclt.exception;
import java.util.HashSet;
import java.util.Set;
public class ErrorCodes {
public final static int couldnt_read_users_conf = 545;
public final static int couldnt_write_users_conf = 376;
public final static int couldnt_create_user_folder = 639;
public final static int couldnt_delete_user_folder = 152;
public final static int couldnt_create_user_userfiles_folder = 293;
public final static int couldnt_delete_user_userfiles_folder = 219;
public final static int couldnt_create_user_user_conf = 934;
public final static int couldnt_read_user_user_conf = 177;
public final static int couldnt_write_user_user_conf = 990;
public final static int couldnt_delete_user_user_conf = 680;
public final static int couldnt_create_user_user_files_conf = 353;
public final static int couldnt_read_user_user_files_conf = 155;
public final static int couldnt_write_user_user_files_conf = 476;
public final static int couldnt_delete_user_user_files_conf = 559;
public final static int couldnt_delete_custom_user_directory = 383;
public final static int couldnt_delete_custom_user_file = 942;
public final static HashSet<Integer> allFatalUserLoginRegisterErrors = new HashSet<>(Set.of(couldnt_read_users_conf, couldnt_write_users_conf,
couldnt_create_user_folder, couldnt_delete_user_folder,
couldnt_create_user_userfiles_folder, couldnt_delete_user_userfiles_folder,
couldnt_create_user_user_conf, couldnt_read_user_user_conf, couldnt_write_user_user_conf, couldnt_delete_user_user_conf,
couldnt_create_user_user_files_conf, couldnt_read_user_user_files_conf, couldnt_write_user_user_files_conf, couldnt_delete_user_user_files_conf,
couldnt_delete_custom_user_directory, couldnt_delete_custom_user_file));
}

View File

@ -0,0 +1,17 @@
package org.blueshard.sekaijuclt.exception;
public class FatalIOException extends Exception {
private final int errno;
public FatalIOException(int errno, String message) {
super("Errno: " + errno + " - " + message);
this.errno = errno;
}
public int getErrno() {
return errno;
}
}

View File

@ -0,0 +1,15 @@
package org.blueshard.sekaijuclt.exception;
public class IllegalCodeException extends Exception {
private final int givenCode;
private final int requiredCode;
public IllegalCodeException(int givenCode, int requiredCode){
super("Wrong data code is given '" + givenCode + "', expected '" + requiredCode + "'");
this.givenCode = givenCode;
this.requiredCode = requiredCode;
}
}

View File

@ -0,0 +1,9 @@
package org.blueshard.sekaijuclt.exception;
public class IllegalPasswordException extends Exception {
public IllegalPasswordException(String errorMessage){
super(errorMessage);
}
}

View File

@ -0,0 +1,23 @@
package org.blueshard.sekaijuclt.exception;
public class UnexpectedException extends Exception {
public UnexpectedException() {
super("An unexpected error occurred");
}
public UnexpectedException(Throwable t) {
super("An unexpected error occurred (" + t.getMessage() + ")");
this.setStackTrace(t.getStackTrace());
}
public UnexpectedException(String message) {
super(message);
}
public UnexpectedException(String message, Throwable t) {
super(message);
this.setStackTrace(t.getStackTrace());
}
}

View File

@ -0,0 +1,9 @@
package org.blueshard.sekaijuclt.exception;
public class UserAlreadyExistException extends UserException {
public UserAlreadyExistException(String username, String message) {
super(username, message);
}
}

View File

@ -0,0 +1,13 @@
package org.blueshard.sekaijuclt.exception;
public class UserException extends Exception {
final String username;
public UserException(String username, String message) {
super(message);
this.username = username;
}
}

View File

@ -0,0 +1,9 @@
package org.blueshard.sekaijuclt.exception;
public class UserNotExistException extends UserException {
public UserNotExistException(String username, String message){
super(username, message);
}
}

View File

@ -0,0 +1,8 @@
package org.blueshard.sekaijuclt.exception;
public class UserNotLoggedInException extends UserException {
public UserNotLoggedInException(String username, String message) {
super(username, message);
}
}

View File

@ -0,0 +1 @@
#empty

View File

@ -0,0 +1,65 @@
package org.blueshard.sekaijuclt.security;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
public class Password {
public static PasswordInfos createPassword(String password, byte[] salt) {
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(salt);
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKeyFactory factory = null;
try {
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException ignore) {
}
byte[] hashedPassword = new byte[0];
try {
hashedPassword = factory.generateSecret(keySpec).getEncoded();
} catch (InvalidKeySpecException ignore) {
}
return new PasswordInfos(hashedPassword, salt);
}
public static class PasswordInfos {
private final byte[] password;
private final byte[] salt;
public PasswordInfos(byte[] password, byte[] salt) {
this.password = password;
this.salt = salt;
}
public byte[] getPasswordAsBytes() {
return password;
}
public String getPasswordAsString() {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(password);
}
public byte[] getSaltAsBytes() {
return salt;
}
public String getSaltAsString() {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(salt);
}
}
}

View File

@ -0,0 +1,58 @@
package org.blueshard.sekaijuclt.user;
public class UserParams {
public final static String USERNAME = "username";
public final static String PASSWORD = "password";
public final static String SALT = "salt";
public final static String EMAIL = "email";
public static class File {
public final static String STARTDIRECOTRY = "startDirectory";
public final static String FILEPATH = "filepath";
}
public static class CheckSum {
public final static String MD5 = "md5";
}
public static class Key {
public final static String PUBLICKEY = "key";
}
public static class LogLevel {
public final static String LOGLEVEL = "logLevel";
public final static String ALL = "0";
public final static String WARNING = "1";
public final static String NOTHING = "2";
}
public static class UserLevel {
public final static String USERLEVEL = "userLevel";
public final static String PUBLIC = "0";
public final static String PROTECTED = "1";
public final static String PRIVATE = "2";
}
public static class State {
public final static String STATE = "state";
public final static String ACTIVE = "active";
public final static String DISABLED = "disabled";
}
}

View File

@ -0,0 +1,76 @@
package org.blueshard.sekaijuclt.utils;
public class ConsoleColors {
// Reset
public static final String RESET = "\033[0m"; // Text Reset
// Regular Colors
public static final String BLACK = "\033[0;30m"; // BLACK
public static final String RED = "\033[0;31m"; // RED
public static final String GREEN = "\033[0;32m"; // GREEN
public static final String YELLOW = "\033[0;33m"; // YELLOW
public static final String BLUE = "\033[0;34m"; // BLUE
public static final String PURPLE = "\033[0;35m"; // PURPLE
public static final String CYAN = "\033[0;36m"; // CYAN
public static final String WHITE = "\033[0;37m"; // WHITE
// Bold
public static final String BLACK_BOLD = "\033[1;30m"; // BLACK
public static final String RED_BOLD = "\033[1;31m"; // RED
public static final String GREEN_BOLD = "\033[1;32m"; // GREEN
public static final String YELLOW_BOLD = "\033[1;33m"; // YELLOW
public static final String BLUE_BOLD = "\033[1;34m"; // BLUE
public static final String PURPLE_BOLD = "\033[1;35m"; // PURPLE
public static final String CYAN_BOLD = "\033[1;36m"; // CYAN
public static final String WHITE_BOLD = "\033[1;37m"; // WHITE
// Underline
public static final String BLACK_UNDERLINED = "\033[4;30m"; // BLACK
public static final String RED_UNDERLINED = "\033[4;31m"; // RED
public static final String GREEN_UNDERLINED = "\033[4;32m"; // GREEN
public static final String YELLOW_UNDERLINED = "\033[4;33m"; // YELLOW
public static final String BLUE_UNDERLINED = "\033[4;34m"; // BLUE
public static final String PURPLE_UNDERLINED = "\033[4;35m"; // PURPLE
public static final String CYAN_UNDERLINED = "\033[4;36m"; // CYAN
public static final String WHITE_UNDERLINED = "\033[4;37m"; // WHITE
// Background
public static final String BLACK_BACKGROUND = "\033[40m"; // BLACK
public static final String RED_BACKGROUND = "\033[41m"; // RED
public static final String GREEN_BACKGROUND = "\033[42m"; // GREEN
public static final String YELLOW_BACKGROUND = "\033[43m"; // YELLOW
public static final String BLUE_BACKGROUND = "\033[44m"; // BLUE
public static final String PURPLE_BACKGROUND = "\033[45m"; // PURPLE
public static final String CYAN_BACKGROUND = "\033[46m"; // CYAN
public static final String WHITE_BACKGROUND = "\033[47m"; // WHITE
// High Intensity
public static final String BLACK_BRIGHT = "\033[0;90m"; // BLACK
public static final String RED_BRIGHT = "\033[0;91m"; // RED
public static final String GREEN_BRIGHT = "\033[0;92m"; // GREEN
public static final String YELLOW_BRIGHT = "\033[0;93m"; // YELLOW
public static final String BLUE_BRIGHT = "\033[0;94m"; // BLUE
public static final String PURPLE_BRIGHT = "\033[0;95m"; // PURPLE
public static final String CYAN_BRIGHT = "\033[0;96m"; // CYAN
public static final String WHITE_BRIGHT = "\033[0;97m"; // WHITE
// Bold High Intensity
public static final String BLACK_BOLD_BRIGHT = "\033[1;90m"; // BLACK
public static final String RED_BOLD_BRIGHT = "\033[1;91m"; // RED
public static final String GREEN_BOLD_BRIGHT = "\033[1;92m"; // GREEN
public static final String YELLOW_BOLD_BRIGHT = "\033[1;93m";// YELLOW
public static final String BLUE_BOLD_BRIGHT = "\033[1;94m"; // BLUE
public static final String PURPLE_BOLD_BRIGHT = "\033[1;95m";// PURPLE
public static final String CYAN_BOLD_BRIGHT = "\033[1;96m"; // CYAN
public static final String WHITE_BOLD_BRIGHT = "\033[1;97m"; // WHITE
// High Intensity backgrounds
public static final String BLACK_BACKGROUND_BRIGHT = "\033[0;100m";// BLACK
public static final String RED_BACKGROUND_BRIGHT = "\033[0;101m";// RED
public static final String GREEN_BACKGROUND_BRIGHT = "\033[0;102m";// GREEN
public static final String YELLOW_BACKGROUND_BRIGHT = "\033[0;103m";// YELLOW
public static final String BLUE_BACKGROUND_BRIGHT = "\033[0;104m";// BLUE
public static final String PURPLE_BACKGROUND_BRIGHT = "\033[0;105m"; // PURPLE
public static final String CYAN_BACKGROUND_BRIGHT = "\033[0;106m"; // CYAN
public static final String WHITE_BACKGROUND_BRIGHT = "\033[0;107m"; // WHITE
}

View File

@ -0,0 +1,71 @@
package org.blueshard.sekaijuclt.utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
public class FileUtils {
public static ArrayList<File> getAllFilesInDirectory(String path) throws IOException {
ArrayList<File> files = new ArrayList<>();
Files.walk(Paths.get(path)).map(Path::toFile).forEach(files::add);
return files;
}
public static File[] sortFilesInDirectory(File path) {
File[] files = path.listFiles();
Arrays.sort(files, (object1, object2) -> object1.getName().compareToIgnoreCase(object2.getName()));
return files;
}
public class CreateHashSum {
String file;
CreateHashSum(String file) {
this.file = file;
}
public String MD5() throws IOException {
try {
StringBuilder hexString = new StringBuilder();
MessageDigest md5 = MessageDigest.getInstance("MD5");
InputStream inputStream = Files.newInputStream(Paths.get(file));
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
md5.update(buffer, 0 , length);
}
byte[] digest = md5.digest();
for (byte b : digest) {
if ((0xff & b) < 0x10) {
hexString.append("0").append(Integer.toHexString((0xFF & b)));
} else {
hexString.append(Integer.toHexString(0xFF & b));
}
}
return hexString.toString();
} catch (NoSuchAlgorithmException ignore) {
return null;
}
}
}
}

View File

@ -0,0 +1,140 @@
package org.blueshard.sekaijuclt.utils;
public class SizeUnit {
private int unit;
private double size;
private final static int BYTE = 1;
private final static int KILOBYTE = 3;
private final static int MEGABYTE = 5;
private final static int GIGABYTE = 7;
private final static int TERRABYTE = 9;
private final static int PETABYTE = 11;
private final static int EXABYTE = 13;
SizeUnit(int unit, double size){
this.unit = unit;
this.size = size;
}
public static SizeUnit BYTES(double bytes){
return new SizeUnit(BYTE, bytes);
}
public static SizeUnit KILOBYTE(double kilobytes) {
return new SizeUnit(KILOBYTE, kilobytes);
}
public static SizeUnit MEGABYTE(double megabytes) {
return new SizeUnit(MEGABYTE, megabytes);
}
public static SizeUnit GIGABYTE(double gigabytes) {
return new SizeUnit(GIGABYTE, gigabytes);
}
public static SizeUnit TERRABYTE(double terrabytes) {
return new SizeUnit(TERRABYTE, terrabytes);
}
public static SizeUnit PETABYTE(double petabytes) {
return new SizeUnit(PETABYTE, petabytes);
}
public static SizeUnit EXABYTE(double exabytes) {
return new SizeUnit(EXABYTE, exabytes);
}
public Double toByte(){
return switch (unit) {
case BYTE -> size;
case KILOBYTE -> size * 1000;
case MEGABYTE -> size * 1000000;
case GIGABYTE -> size * 1000000000;
case TERRABYTE -> size * 1000000000000L;
case PETABYTE -> size * 1000000000000000L;
case EXABYTE -> size * 1000000000000000000L;
default -> 0D;
};
}
public Double toKilobyte(){
return switch (unit) {
case BYTE -> size / 1000;
case KILOBYTE -> size;
case MEGABYTE -> size * 1000;
case GIGABYTE -> size * 1000000;
case TERRABYTE -> size * 1000000000;
case PETABYTE -> size * 1000000000000L;
case EXABYTE -> size * 1000000000000000L;
default -> 0D;
};
}
public Double toMegabyte(){
return switch (unit) {
case BYTE -> size / 1000000;
case KILOBYTE -> size / 1000;
case MEGABYTE -> size;
case GIGABYTE -> size * 1000;
case TERRABYTE -> size * 1000000;
case PETABYTE -> size * 1000000000;
case EXABYTE -> size * 1000000000000L;
default -> 0D;
};
}
public Double toGigabyte(){
return switch (unit) {
case BYTE -> size / 1000000000L;
case KILOBYTE -> size / 1000000;
case MEGABYTE -> size / 1000;
case GIGABYTE -> size;
case TERRABYTE -> size * 1000;
case PETABYTE -> size * 1000000;
case EXABYTE -> size * 1000000000;
default -> 0D;
};
}
public Double toTerrabyte(){
return switch (unit) {
case BYTE -> size / 1000000000000L;
case KILOBYTE -> size / 1000000000;
case MEGABYTE -> size / 1000000;
case GIGABYTE -> size / 1000;
case TERRABYTE -> size;
case PETABYTE -> size * 1000;
case EXABYTE -> size * 1000000;
default -> 0D;
};
}
public Double toPetabyte(){
return switch (unit) {
case BYTE -> size / 1000000000000000L;
case KILOBYTE -> size / 1000000000000L;
case MEGABYTE -> size / 1000000000;
case GIGABYTE -> size / 1000000;
case TERRABYTE -> size / 1000;
case PETABYTE -> size;
case EXABYTE -> size * 1000;
default -> 0D;
};
}
public Double toExabyte(){
return switch (unit) {
case BYTE -> size / 1000000000000000000L;
case KILOBYTE -> size / 1000000000000000L;
case MEGABYTE -> size / 1000000000000L;
case GIGABYTE -> size / 1000000000;
case TERRABYTE -> size / 1000000;
case PETABYTE -> size / 1000;
case EXABYTE -> size;
default -> 0D;
};
}
}

View File

@ -0,0 +1,17 @@
package org.blueshard.sekaijuclt.utils;
import java.util.Map;
public class StringUtils {
public static String format(String string, Map<String, String> formatMap){
for(Map.Entry<String, String> entry: formatMap.entrySet()) {
string = string.replace("{" + entry.getKey() + "}", entry.getValue());
}
return string;
}
}