package art.servers.controller;
|
|
|
import art.library.interop.InteropParameter;
|
import art.library.interop.InteropParameters;
|
import art.library.interop.InteropResponse;
|
import art.library.interop.serialization.Serialization;
|
import art.library.interop.serialization.SerializationException;
|
import art.library.utils.licence.Licence;
|
import art.servers.Shared;
|
import art.servers.configuration.Configuration;
|
import art.servers.configuration.ConfigurationListenerHttp;
|
import art.servers.configuration.ConfigurationSecurity;
|
import art.servers.types.HttpAuthentication;
|
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpHandler;
|
import com.sun.net.httpserver.HttpServer;
|
import java.io.ByteArrayOutputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.io.PrintWriter;
|
import java.io.StringWriter;
|
import java.lang.reflect.Method;
|
import java.net.InetSocketAddress;
|
import java.net.URLDecoder;
|
import java.nio.charset.StandardCharsets;
|
import java.rmi.ServerException;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.concurrent.Executors;
|
|
|
|
public class ControllerListenerHttpWeb extends Thread
|
{
|
protected String name = null;
|
protected ConfigurationListenerHttp configuration = null;
|
protected HttpServer server = null;
|
protected ListenerImplementation listenerImplementation = null;
|
protected ConfigurationSecurity security = null;
|
|
public List<HttpAuthentication> autentications = new ArrayList<HttpAuthentication>();
|
|
|
public ControllerListenerHttpWeb(ConfigurationListenerHttp configuration, ConfigurationSecurity security)
|
{
|
this.name = Shared.getMessage("Listener HTTPS");
|
this.configuration = configuration;
|
this.security = security;
|
this.listenerImplementation = new ListenerImplementation();
|
this.setName(name);
|
}
|
|
|
|
public void run()
|
{
|
Shared.traceInformation(name, "Starting");
|
|
while (isInterrupted() == false)
|
{
|
try
|
{
|
if (server == null)
|
{
|
connect();
|
}
|
|
sleep(1000);
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
Shared.traceInformation(name, "Finishing");
|
}
|
|
|
|
|
|
|
protected void connect()
|
{
|
try
|
{
|
server = HttpServer.create(new InetSocketAddress(configuration.port), 0);
|
contexts();
|
server.setExecutor(Executors.newCachedThreadPool());
|
server.start();
|
return;
|
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
protected void contexts()
|
{
|
server.createContext("/login", new login());
|
server.createContext("/art", new art());
|
}
|
|
|
|
|
|
|
|
|
protected class login implements HttpHandler
|
{
|
public void handle(HttpExchange httpExchange) throws IOException
|
{
|
String language = null;
|
|
try
|
{
|
InteropParameters parameters = new InteropParameters(httpExchange.getRequestURI().getRawQuery());
|
language = (parameters.hasParameter("language") == true) ? (String)parameters.getParameterValue("language") : "";
|
String type = (parameters.hasParameter("type") == true) ? (String)parameters.getParameterValue("type") : "text";
|
parameters.addParameter(new InteropParameter("body-content", getRequestBody(httpExchange)));
|
InteropResponse response = login(parameters, type, httpExchange.getRemoteAddress().getHostName());
|
result(httpExchange, response);
|
}
|
catch (Exception e)
|
{
|
result(httpExchange, 400, language, e);
|
}
|
}
|
|
|
|
|
private InteropResponse login(InteropParameters parameters, String type, String address) throws SerializationException
|
{
|
String language = (String)parameters.getParameterValue("language");
|
|
try
|
{
|
String username = (String)parameters.getParameterValue("username");
|
String password = (String)parameters.getParameterValue("password");
|
HttpAuthentication authentication = login(username, password, address);
|
|
if (type.equalsIgnoreCase("json"))
|
{
|
InteropResponse response = new InteropResponse(authentication.getHttpToken());
|
Object[] objects = response.getValue();
|
return response;
|
}
|
else
|
{
|
InteropResponse response = new InteropResponse(authentication.getHttpToken().token);
|
response.mime = "text/plain";
|
return response;
|
}
|
}
|
catch (Exception e)
|
{
|
StringWriter sw = new StringWriter();
|
e.printStackTrace(new PrintWriter(sw));
|
throw new SerializationException(Shared.getMessage(language, "Authentication error"));
|
}
|
}
|
|
|
|
|
private HttpAuthentication login(String username, String password, String address) throws Exception
|
{
|
// Check user autentication
|
|
Configuration configuration = (Configuration)Shared.configuration;
|
|
HttpAuthentication authentication = new HttpAuthentication(username, password, address);
|
|
if ((username.equals("read")) && (password.equals(Licence.decrypt(security.readPassword))))
|
{
|
authentication.profileWebServer = HttpAuthentication.PROFILE_READ;
|
}
|
else if ((username.equals("write")) && (password.equals(Licence.decrypt(security.writePassword))))
|
{
|
authentication.profileWebServer = HttpAuthentication.PROFILE_WRITE;
|
}
|
else if ((username.equals("admin")) && (password.equals(Licence.decrypt(security.adminPassword))))
|
{
|
authentication.profileWebServer = HttpAuthentication.PROFILE_ADMIN;
|
}
|
else
|
{
|
throw new Exception("Autentication error");
|
}
|
|
return authentication;
|
}
|
}
|
|
|
|
|
|
protected class art implements HttpHandler
|
{
|
public void handle(HttpExchange httpExchange) throws IOException
|
{
|
String language = null;
|
|
try
|
{
|
InteropParameters parameters = new InteropParameters(httpExchange.getRequestURI().getRawQuery());
|
language = (parameters.hasParameter("language") == true) ? (String)parameters.getParameterValue("language") : "";
|
|
int tokenStatus = checkToken(httpExchange, parameters);
|
|
|
if (tokenStatus != 200)
|
{
|
result(httpExchange, tokenStatus, Shared.getMessage(language, "Invalid token"));
|
}
|
else
|
{
|
parameters.addParameter(new InteropParameter("body-content", getRequestBody(httpExchange)));
|
String operation = (String)parameters.getParameterValue("operation");
|
Method method = listenerImplementation.getClass().getMethod(operation, parameters.getClass());
|
InteropResponse response = (InteropResponse)method.invoke(listenerImplementation, parameters);
|
result(httpExchange, response);
|
}
|
}
|
catch (Exception exception)
|
{
|
result(httpExchange, 400, language, exception);
|
}
|
}
|
}
|
|
|
|
|
|
|
protected int checkToken(HttpExchange httpExchange, InteropParameters parameters)
|
{
|
Configuration configuration = (Configuration)Shared.configuration;
|
|
try
|
{
|
HttpAuthentication authentication = Serialization.deserialize(HttpAuthentication.class, Licence.decrypt((String)parameters.getParameterValue("token")));
|
authentication.updateExpirationTimestamp();
|
|
if (authentication.isTokenValid(httpExchange.getRemoteAddress().getHostName()) == false)
|
{
|
return 401; // Page expired
|
}
|
|
authentication.lastRequestTimestamp = System.currentTimeMillis();
|
return 200;
|
}
|
catch (Exception e)
|
{
|
}
|
|
try
|
{
|
String[] login = ((String)parameters.getParameterValue("token")).split(",");
|
String username = login[0];
|
String password = login[1];
|
|
if ((username.equals("read")) && (password.equals(Licence.decrypt(security.readPassword))))
|
{
|
HttpAuthentication authentication = new HttpAuthentication(username, password, httpExchange.getRemoteAddress().getHostName(), HttpAuthentication.PROFILE_READ);
|
authentication.updateExpirationTimestamp();
|
String token = URLDecoder.decode(authentication.getHttpToken().token, StandardCharsets.UTF_8.toString());
|
parameters.setParameter("token", token);
|
authentication.lastRequestTimestamp = System.currentTimeMillis();
|
return 200;
|
}
|
|
if ((username.equals("write")) && (password.equals(Licence.decrypt(security.writePassword))))
|
{
|
HttpAuthentication authentication = new HttpAuthentication(username, password, httpExchange.getRemoteAddress().getHostName(), HttpAuthentication.PROFILE_WRITE);
|
authentication.updateExpirationTimestamp();
|
String token = URLDecoder.decode(authentication.getHttpToken().token, StandardCharsets.UTF_8.toString());
|
parameters.setParameter("token", token);
|
authentication.lastRequestTimestamp = System.currentTimeMillis();
|
return 200;
|
}
|
|
if ((username.equals("admin")) && (password.equals(Licence.decrypt(security.adminPassword))))
|
{
|
HttpAuthentication authentication = new HttpAuthentication(username, password, httpExchange.getRemoteAddress().getHostName(), HttpAuthentication.PROFILE_ADMIN);
|
authentication.updateExpirationTimestamp();
|
String token = URLDecoder.decode(authentication.getHttpToken().token, StandardCharsets.UTF_8.toString());
|
parameters.setParameter("token", token);
|
authentication.lastRequestTimestamp = System.currentTimeMillis();
|
return 200;
|
}
|
|
}
|
catch (Exception e)
|
{
|
}
|
|
try
|
{
|
HttpAuthentication authentication = getAuthentication(httpExchange);
|
authentication.updateExpirationTimestamp();
|
String token = URLDecoder.decode(authentication.getHttpToken().token, StandardCharsets.UTF_8.toString());
|
parameters.addParameter("token", token);
|
authentication.lastRequestTimestamp = System.currentTimeMillis();
|
return 200;
|
}
|
catch (Exception e)
|
{
|
}
|
|
|
return 401; // Invalid token, unauthorized
|
}
|
|
|
|
|
public HttpAuthentication getAuthentication(HttpExchange httpExchange)
|
{
|
String address = httpExchange.getRemoteAddress().getHostName();
|
String userAgent = httpExchange.getRequestHeaders().getFirst("User-Agent");
|
|
|
for (HttpAuthentication current : autentications)
|
{
|
if ((current.userAgent.equals(userAgent)) && (current.address.equals(address)))
|
{
|
return current;
|
}
|
}
|
|
return null;
|
}
|
|
|
|
|
// <editor-fold defaultstate="collapsed" desc="Request body">
|
|
|
|
protected byte[] getRequestBody(HttpExchange httpExchange) throws Exception
|
{
|
ByteArrayOutputStream bos = null;
|
|
try
|
{
|
InputStream input = httpExchange.getRequestBody();
|
bos = new ByteArrayOutputStream();
|
byte[] buffer = new byte[8196];
|
int length;
|
|
while ((length = input.read(buffer)) != -1)
|
{
|
bos.write(buffer, 0, length);
|
}
|
return bos.toByteArray();
|
}
|
catch (Exception exception)
|
{
|
throw exception;
|
}
|
finally
|
{
|
try { bos.close(); } catch (Exception ex) {};
|
httpExchange.getRequestBody().close();
|
}
|
}
|
|
|
|
|
// </editor-fold>
|
|
|
// <editor-fold defaultstate="collapsed" desc="Response">
|
|
|
protected void result(HttpExchange httpExchange, int httpErrorCode, byte[] data) throws Exception
|
{
|
try
|
{
|
httpExchange.sendResponseHeaders(httpErrorCode, data.length);
|
httpExchange.getResponseBody().write(data);
|
}
|
finally
|
{
|
try { httpExchange.getResponseBody().close(); } catch (Exception e) {}
|
try { httpExchange.close(); } catch (Exception e) {}
|
}
|
}
|
|
|
|
|
protected void result(HttpExchange httpExchange, InteropResponse response)
|
{
|
// https://www.sitepoint.com/mime-types-complete-list/
|
// httpExchange.getResponseHeaders().set("Content-Type", "text/html; charset=" + StandardCharsets.UTF_8);
|
// httpExchange.getResponseHeaders().set("Content-Type", "application/pdf"; charset=" + StandardCharsets.UTF_8);
|
// httpExchange.getResponseHeaders().set("Content-Type", "application/vnd.ms-excel"; charset=" + StandardCharsets.UTF_8);
|
|
httpExchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
|
|
if (httpExchange.getRequestMethod().equalsIgnoreCase("OPTIONS"))
|
{
|
httpExchange.getResponseHeaders().add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
httpExchange.getResponseHeaders().add("Access-Control-Allow-Headers", "Content-Type,Authorization");
|
|
try
|
{
|
httpExchange.sendResponseHeaders(204, -1);
|
}
|
catch (Exception e)
|
{
|
}
|
|
httpExchange.close();
|
return;
|
}
|
|
if (response.mime == null)
|
{
|
httpExchange.getResponseHeaders().set("Content-Type", "application/json; charset=" + StandardCharsets.UTF_8);
|
}
|
else
|
{
|
httpExchange.getResponseHeaders().set("Content-Type", response.mime + "; charset=" + StandardCharsets.UTF_8);
|
}
|
|
|
// Check if response is a file
|
|
if (response.name != null)
|
{
|
try
|
{
|
// For filenames with polish characters
|
|
byte[] filenameBytes = response.name.getBytes("UTF-8");
|
String filename = "";
|
for (byte character : filenameBytes) filename += (char)(character & 0xFF);
|
httpExchange.getResponseHeaders().set("Content-Disposition", "attachment; filename=\"" + filename + "\"");
|
}
|
catch (Exception e)
|
{
|
httpExchange.getResponseHeaders().set("Content-Disposition", "attachment; filename=\"" + response.name + "\"");
|
}
|
}
|
|
|
// Check mime text/plain
|
|
if (response.mime != null)
|
{
|
if (response.mime.equalsIgnoreCase("text/plain"))
|
{
|
try
|
{
|
byte[] data = ((String)response.getValue()[0]).getBytes();
|
result(httpExchange, 200, data);
|
httpExchange.close();
|
return;
|
}
|
catch (Exception exception)
|
{
|
manageException(httpExchange, exception);
|
}
|
|
return;
|
}
|
else if (response.mime.equalsIgnoreCase("application/json"))
|
{
|
try
|
{
|
if (response.array == true)
|
{
|
String message = Serialization.toString(response.getValue());
|
result(httpExchange, 200, message.getBytes());
|
}
|
else
|
{
|
String message = Serialization.toString(response.getValue()[0]);
|
result(httpExchange, 200, message.getBytes());
|
}
|
}
|
catch (Exception e)
|
{
|
manageException(httpExchange, e);
|
}
|
|
return;
|
}
|
}
|
|
|
// Try send raw bytes
|
|
try
|
{
|
byte[] data = (byte[])response.getValue()[0];
|
result(httpExchange, 200, data);
|
httpExchange.close();
|
return;
|
}
|
catch (Exception exception)
|
{
|
manageException(httpExchange, exception);
|
}
|
|
|
|
|
|
// Default JSON
|
|
try
|
{
|
if (response.array == false)
|
{
|
String message = Serialization.toString(response.getValue()[0]);
|
result(httpExchange, 200, message.getBytes());
|
httpExchange.close();
|
return;
|
}
|
else
|
{
|
if (response.getValue().length == 0)
|
{
|
String message = Serialization.toString(response.getValue());
|
result(httpExchange, 200, message.getBytes());
|
httpExchange.close();
|
return;
|
}
|
else
|
{
|
String message = Serialization.toString(response.getValue());
|
result(httpExchange, 200, message.getBytes());
|
httpExchange.close();
|
return;
|
}
|
}
|
}
|
catch (Exception exception)
|
{
|
manageException(httpExchange, exception);
|
}
|
|
}
|
|
|
|
|
|
protected void result (HttpExchange httpExchange, int httpErrorCode, String language, Exception exception)
|
{
|
Throwable throwable = exception.getCause();
|
|
if (throwable != null)
|
{
|
if ((throwable instanceof SerializationException) || (throwable instanceof ServerException))
|
{
|
result(httpExchange, httpErrorCode, Shared.getMessage(language, throwable.getMessage()));
|
}
|
}
|
|
if ((exception instanceof SerializationException) || (exception instanceof ServerException))
|
{
|
result(httpExchange, httpErrorCode, Shared.getMessage(language, exception.getMessage()));
|
}
|
|
StringWriter sw = new StringWriter();
|
exception.printStackTrace(new PrintWriter(sw));
|
String message = sw.toString();
|
result(httpExchange, httpErrorCode, message);
|
}
|
|
|
|
|
protected void result (HttpExchange httpExchange, int httpErrorCode, String message)
|
{
|
try
|
{
|
result(httpExchange, httpErrorCode, message.getBytes());
|
}
|
catch (Exception e)
|
{
|
manageException(httpExchange, e);
|
}
|
}
|
|
|
// </editor-fold>
|
|
|
// <editor-fold defaultstate="collapsed" desc="Exception">
|
|
|
protected void manageException (HttpExchange httpExchange, Exception exception)
|
{
|
try
|
{
|
httpExchange.close();
|
}
|
catch (Exception e)
|
{
|
}
|
|
if (exception instanceof IOException)
|
{
|
String message = exception.toString().toLowerCase();
|
|
if (message.contains("an established connection was aborted by the software in your host machine") == true)
|
{
|
if (server != null)
|
{
|
try{server.stop(10);} catch (Exception ex){};
|
server = null;
|
connect();
|
}
|
}
|
}
|
}
|
|
|
// </editor-fold>
|
|
}
|