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 autentications = new ArrayList(); 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; } // 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(); } } // // 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); } } // // 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(); } } } } // }