diff --git a/.gitignore b/.gitignore index a5b5cd0..c96d30a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,250 +1,251 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# DNX -project.lock.json -artifacts/ - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ -orleans.codegen.cs - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.imlasd - - - - -target/classes/* +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.imlasd + + + + +target/classes/* +/target/ diff --git a/main/resources/META-INF/persistence.xml b/main/resources/META-INF/persistence.xml index d3530b5..23d3d04 100644 --- a/main/resources/META-INF/persistence.xml +++ b/main/resources/META-INF/persistence.xml @@ -1,12 +1,27 @@ - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8819e72..02ac466 100644 --- a/pom.xml +++ b/pom.xml @@ -1,78 +1,84 @@ - - 4.0.0 - ChatServer - ChatServer - 0.0.1-SNAPSHOT - - src - - - maven-compiler-plugin - 3.5.1 - - 1.8 - 1.8 - - - - - - - org.apache.derby - derby - 10.12.1.1 - - - org.apache.derby - derbyclient - 10.12.1.1 - - - - org.hibernate - hibernate-core - 5.2.1.Final - - - - commons-io - commons-io - 2.5 - - - org.reflections - reflections - 0.9.10 - runtime - - - - org.jsoup - jsoup - 1.9.2 - - - - org.apache.logging.log4j - log4j-core - 2.6.2 - - - - org.apache.logging.log4j - log4j-api - 2.6.2 - - - - org.json - json - 20160212 - - - - 1.8 - 1.8 - + + 4.0.0 + ChatServer + ChatServer + 0.0.1-SNAPSHOT + + src + + + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + + + org.apache.derby + derby + 10.12.1.1 + + + org.apache.derby + derbyclient + 10.12.1.1 + + + + org.hibernate + hibernate-core + 5.2.1.Final + + + + commons-io + commons-io + 2.5 + + + org.reflections + reflections + 0.9.10 + runtime + + + + org.jsoup + jsoup + 1.9.2 + + + + org.apache.logging.log4j + log4j-core + 2.6.2 + + + + org.apache.logging.log4j + log4j-api + 2.6.2 + + + + org.json + json + 20160212 + + + + org.hibernate + hibernate-c3p0 + 5.2.1.Final + + + + 1.8 + 1.8 + \ No newline at end of file diff --git a/src/io/github/norbipeti/chat/server/IOHelper.java b/src/io/github/norbipeti/chat/server/IOHelper.java index 55dac68..b5c4b69 100644 --- a/src/io/github/norbipeti/chat/server/IOHelper.java +++ b/src/io/github/norbipeti/chat/server/IOHelper.java @@ -1,178 +1,182 @@ -package io.github.norbipeti.chat.server; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.time.Period; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.HashMap; -import java.util.UUID; -import java.util.function.Function; - -import org.apache.commons.io.IOUtils; -import org.json.JSONObject; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; - -import com.sun.net.httpserver.HttpExchange; - -import io.github.norbipeti.chat.server.db.DataProvider; -import io.github.norbipeti.chat.server.db.domain.User; -import io.github.norbipeti.chat.server.page.Page; - -public class IOHelper { - public static void SendResponse(int code, String content, HttpExchange exchange) throws IOException { - exchange.sendResponseHeaders(code, content.length()); - IOUtils.write(content, exchange.getResponseBody(), StandardCharsets.UTF_8); - exchange.getResponseBody().close(); - } - - public static boolean SendPage(int code, Page page, HttpExchange exchange) throws IOException { - String content = GetPage(page, exchange); - SendResponse(code, content, exchange); - return true; - } - - public static String GetPage(Page page, HttpExchange exchange) throws IOException { - File file = new File(page.GetHTMLPath()); - if (!file.exists()) { - SendResponse(501, - "

501 Not Implemented

The page \"" + page.GetName() + "\" cannot be found on disk.", - exchange); - return null; - } - return ReadFile(file); - } - - public static String ReadFile(File file) throws FileNotFoundException, IOException { - FileInputStream inputStream = new FileInputStream(file); - String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - return content; - } - - @Deprecated - public static HashMap GetPOST(HttpExchange exchange) throws IOException { - if (exchange.getRequestBody().available() == 0) - return new HashMap<>(); - try { - String[] content = IOUtils.toString(exchange.getRequestBody(), StandardCharsets.ISO_8859_1).split("\\&"); - HashMap vars = new HashMap<>(); - for (String var : content) { - String[] spl = var.split("\\="); - if (spl.length == 1) - vars.put(spl[0], ""); - else - vars.put(spl[0], spl[1]); - } - return vars; - } catch (Exception e) { - e.printStackTrace(); - return new HashMap<>(); - } - } - - public static JSONObject GetPOSTJSON(HttpExchange exchange) throws IOException { - if (exchange.getRequestBody().available() == 0) - return null; - try { - String content = IOUtils.toString(exchange.getRequestBody(), StandardCharsets.ISO_8859_1); - JSONObject obj = new JSONObject(content); - return obj; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - public static boolean SendModifiedPage(int code, Page page, Function modifyfunc, - HttpExchange exchange) throws IOException { - String content = GetPage(page, exchange); - if (content == null) - return false; - Document doc = Jsoup.parse(content); - doc = modifyfunc.apply(doc); - SendResponse(200, doc.html(), exchange); - return true; - } - - public static void LoginUser(HttpExchange exchange, User user, DataProvider provider) { - provider.SetValues(() -> user.setSessionid(UUID.randomUUID())); - System.out.println("Logging in user: " + user); - ZonedDateTime expiretime = ZonedDateTime.now(ZoneId.of("GMT")).plus(Period.of(2, 0, 0)); - exchange.getResponseHeaders().add("Set-Cookie", - "user_id=" + user.getId() + "; expires=" + expiretime.format(DateTimeFormatter.RFC_1123_DATE_TIME)); - exchange.getResponseHeaders().add("Set-Cookie", - "session_id=" + user.getSessionid() + "; expires=" + expiretime); - } - - public static void LogoutUser(HttpExchange exchange, User user) { - user.setSessionid(new UUID(0, 0)); - SendLogoutHeaders(exchange); - } - - private static void SendLogoutHeaders(HttpExchange exchange) { - String expiretime = "Sat, 19 Mar 2016 23:33:00 GMT"; - exchange.getResponseHeaders().add("Set-Cookie", "user_id=del; expires=" + expiretime); - exchange.getResponseHeaders().add("Set-Cookie", "session_id=del; expires=" + expiretime); - } - - public static void Redirect(String url, HttpExchange exchange) throws IOException { - exchange.getResponseHeaders().add("Location", url); - IOHelper.SendResponse(303, "If you can see this, click here to continue", exchange); - } - - public static HashMap GetCookies(HttpExchange exchange) { - if (!exchange.getRequestHeaders().containsKey("Cookie")) - return new HashMap<>(); - HashMap map = new HashMap<>(); - for (String cheader : exchange.getRequestHeaders().get("Cookie")) { - String[] spl = cheader.split("\\;\\s*"); - for (String s : spl) { - String[] kv = s.split("\\="); - if (kv.length < 2) - continue; - map.put(kv[0], kv[1]); - } - } - return map; - } - - /** - * Get logged in user. It may also send logout headers if the cookies are - * invalid. - * - * @param exchange - * @return The logged in user or null if not logged in. - */ - public static User GetLoggedInUser(HttpExchange exchange) { - HashMap cookies = GetCookies(exchange); - System.out.println("Cookies: " + cookies); - if (!cookies.containsKey("user_id") || !cookies.containsKey("session_id")) - return null; - System.out.println("Cookies found"); - try (DataProvider provider = new DataProvider()) { - User user = provider.getUser(Long.parseLong(cookies.get("user_id"))); - System.out.println("User: " + user); - System.out.println("session_id: " + cookies.get("session_id")); - if (user != null) - System.out.println("Equals: " + UUID.fromString(cookies.get("session_id")).equals(user.getSessionid())); - if (user != null && cookies.get("session_id") != null - && UUID.fromString(cookies.get("session_id")).equals(user.getSessionid())) - return user; - else - SendLogoutHeaders(exchange); - } - return null; - } - - public static void SendResponse(int code, Function action, HttpExchange exchange) - throws IOException { - Document doc = new Document(""); - doc = action.apply(doc); - SendResponse(200, doc.html(), exchange); - } -} +package io.github.norbipeti.chat.server; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Period; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.UUID; +import java.util.function.Function; + +import org.apache.commons.io.IOUtils; +import org.json.JSONObject; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + +import com.sun.net.httpserver.HttpExchange; + +import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.db.domain.User; +import io.github.norbipeti.chat.server.page.Page; + +public class IOHelper { + public static void SendResponse(int code, String content, HttpExchange exchange) throws IOException { + exchange.sendResponseHeaders(code, content.length()); + IOUtils.write(content, exchange.getResponseBody(), StandardCharsets.UTF_8); + exchange.getResponseBody().close(); + } + + public static boolean SendPage(int code, Page page, HttpExchange exchange) throws IOException { + String content = GetPage(page, exchange); + SendResponse(code, content, exchange); + return true; + } + + public static String GetPage(Page page, HttpExchange exchange) throws IOException { + File file = new File(page.GetHTMLPath()); + if (!file.exists()) { + SendResponse(501, + "

501 Not Implemented

The page \"" + page.GetName() + "\" cannot be found on disk.", + exchange); + return null; + } + return ReadFile(file); + } + + public static String ReadFile(File file) throws FileNotFoundException, IOException { + FileInputStream inputStream = new FileInputStream(file); + String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + return content; + } + + @Deprecated + public static HashMap GetPOST(HttpExchange exchange) throws IOException { + if (exchange.getRequestBody().available() == 0) + return new HashMap<>(); + try { + String[] content = IOUtils.toString(exchange.getRequestBody(), StandardCharsets.ISO_8859_1).split("\\&"); + HashMap vars = new HashMap<>(); + for (String var : content) { + String[] spl = var.split("\\="); + if (spl.length == 1) + vars.put(spl[0], ""); + else + vars.put(spl[0], spl[1]); + } + return vars; + } catch (Exception e) { + e.printStackTrace(); + return new HashMap<>(); + } + } + + public static JSONObject GetPOSTJSON(HttpExchange exchange) throws IOException { + if (exchange.getRequestBody().available() == 0) + return null; + try { + String content = IOUtils.toString(exchange.getRequestBody(), StandardCharsets.ISO_8859_1); + JSONObject obj = new JSONObject(content); + return obj; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static boolean SendModifiedPage(int code, Page page, Function modifyfunc, + HttpExchange exchange) throws IOException { + String content = GetPage(page, exchange); + if (content == null) + return false; + Document doc = Jsoup.parse(content); + doc = modifyfunc.apply(doc); + SendResponse(200, doc.html(), exchange); + return true; + } + + public static void LoginUser(HttpExchange exchange, User user, DataProvider provider) { + System.out.println("Logging in user: " + user); + // provider.SetValues(() -> + // user.setSessionid(UUID.randomUUID().toString())); + user.setSessionid(UUID.randomUUID().toString()); + provider.saveUser(user); + System.out.println("Session ID set to " + user.getSessionid()); + ZonedDateTime expiretime = ZonedDateTime.now(ZoneId.of("GMT")).plus(Period.of(2, 0, 0)); + exchange.getResponseHeaders().add("Set-Cookie", + "user_id=" + user.getId() + "; expires=" + expiretime.format(DateTimeFormatter.RFC_1123_DATE_TIME)); + exchange.getResponseHeaders().add("Set-Cookie", + "session_id=" + user.getSessionid() + "; expires=" + expiretime); + } + + public static void LogoutUser(HttpExchange exchange, User user) { + user.setSessionid(new UUID(0, 0).toString()); + SendLogoutHeaders(exchange); + } + + private static void SendLogoutHeaders(HttpExchange exchange) { + String expiretime = "Sat, 19 Mar 2016 23:33:00 GMT"; + exchange.getResponseHeaders().add("Set-Cookie", "user_id=del; expires=" + expiretime); + exchange.getResponseHeaders().add("Set-Cookie", "session_id=del; expires=" + expiretime); + } + + public static void Redirect(String url, HttpExchange exchange) throws IOException { + exchange.getResponseHeaders().add("Location", url); + IOHelper.SendResponse(303, "If you can see this, click here to continue", exchange); + } + + public static HashMap GetCookies(HttpExchange exchange) { + if (!exchange.getRequestHeaders().containsKey("Cookie")) + return new HashMap<>(); + HashMap map = new HashMap<>(); + for (String cheader : exchange.getRequestHeaders().get("Cookie")) { + String[] spl = cheader.split("\\;\\s*"); + for (String s : spl) { + String[] kv = s.split("\\="); + if (kv.length < 2) + continue; + map.put(kv[0], kv[1]); + } + } + return map; + } + + /** + * Get logged in user. It may also send logout headers if the cookies are + * invalid. + * + * @param exchange + * @return The logged in user or null if not logged in. + */ + public static User GetLoggedInUser(HttpExchange exchange) { + HashMap cookies = GetCookies(exchange); + System.out.println("Cookies: " + cookies); + if (!cookies.containsKey("user_id") || !cookies.containsKey("session_id")) + return null; + System.out.println("Cookies found"); + try (DataProvider provider = new DataProvider()) { + User user = provider.getUser(Long.parseLong(cookies.get("user_id"))); + System.out.println("User: " + user); + System.out.println("session_id: " + cookies.get("session_id")); + if (user != null) + System.out.println("Equals: " + cookies.get("session_id").equals(user.getSessionid())); + if (user != null && cookies.get("session_id") != null + && cookies.get("session_id").equals(user.getSessionid())) + return user; + else + SendLogoutHeaders(exchange); + } + return null; + } + + public static void SendResponse(int code, Function action, HttpExchange exchange) + throws IOException { + Document doc = new Document(""); + doc = action.apply(doc); + SendResponse(200, doc.html(), exchange); + } +} diff --git a/src/io/github/norbipeti/chat/server/Main.java b/src/io/github/norbipeti/chat/server/Main.java index ea76852..e7f2cb5 100644 --- a/src/io/github/norbipeti/chat/server/Main.java +++ b/src/io/github/norbipeti/chat/server/Main.java @@ -1,109 +1,108 @@ -package io.github.norbipeti.chat.server; - -import java.lang.reflect.Modifier; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Set; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.LoggerConfig; -import org.reflections.Reflections; -import org.reflections.scanners.SubTypesScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; - -import com.sun.net.httpserver.HttpServer; -import io.github.norbipeti.chat.server.db.*; -import io.github.norbipeti.chat.server.db.domain.*; -import io.github.norbipeti.chat.server.page.*; - -public class Main { - // public static final HashMap Pages = new HashMap(); - - public static void main(String[] args) { // http://stackoverflow.com/questions/9266632/access-restriction-is-not-accessible-due-to-restriction-on-required-library/10642163#10642163 - try { // rt.jar Javadoc: - // https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/ - // https://docs.oracle.com/javase/8/docs/api/ - System.out.println(System.getProperty("java.class.path")); // TODO: - // log4j - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); - loggerConfig.setLevel(Level.WARN); - ctx.updateLoggers(); // This causes all Loggers to refetch - // information from their LoggerConfig. - System.out.println("Loading database..."); - try (DataProvider provider = new DataProvider()) { - User user = new User(); - user.setName("asd"); - user.setEmail("test@test.com"); - User user2 = new User(); - user2.setName("Teszt"); - user2.setEmail("test2@test.com"); - user2.getContacts().add(user); - provider.addUser(user); - List users = provider.getUsers(); - user = users.get(0); - user.getContacts().add(user2); - provider.addUser(user2); - users = provider.getUsers(); - user2 = users.get(1); - System.out.println(users); - System.out.println("1st's contact: " + user.getContacts().get(0)); - System.out.println("2nd's contact: " + user2.getContacts().get(0)); - Conversation convo = new Conversation(); - convo.getUsers().add(user); - convo.getUsers().add(user2); - Message msg = new Message(); - msg.setSender(user); - msg.setTime(new Date()); - msg.setMessage("Teszt 1"); - convo.getMesssages().add(msg); - Message msg2 = new Message(); - msg2.setSender(user2); - msg2.setTime(new Date()); - msg2.setMessage("Teszt 2"); - convo.getMesssages().add(msg2); - provider.addConversation(convo); - } - System.out.println("Starting webserver..."); - HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 8080), 10); - Reflections rf = new Reflections( - new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(Page.class.getClassLoader())) - .addClassLoader(Page.class.getClassLoader()).addScanners(new SubTypesScanner()) - .filterInputsBy((String pkg) -> pkg.contains("io.github.norbipeti.chat.server.page"))); - Set> pages = rf.getSubTypesOf(Page.class); - for (Class page : pages) { - try { - if (Modifier.isAbstract(page.getModifiers())) - continue; - Page p = page.newInstance(); - addPage(server, p); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - server.start(); - System.out.println("Ready... Press Enter to stop."); - System.in.read(); - System.out.println("Stopping..."); - server.stop(1); - } catch (Exception e) { - e.printStackTrace(); - } - System.out.println("Stopped"); - } - - private static void addPage(HttpServer server, Page page) { - server.createContext("/" + page.GetName(), page); - } +package io.github.norbipeti.chat.server; + +import java.lang.reflect.Modifier; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.LoggerConfig; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +import com.sun.net.httpserver.HttpServer; +import io.github.norbipeti.chat.server.db.*; +import io.github.norbipeti.chat.server.db.domain.*; +import io.github.norbipeti.chat.server.page.*; + +public class Main { + // public static final HashMap Pages = new HashMap(); + + public static void main(String[] args) { // http://stackoverflow.com/questions/9266632/access-restriction-is-not-accessible-due-to-restriction-on-required-library/10642163#10642163 + try { // rt.jar Javadoc: + // https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/ + // https://docs.oracle.com/javase/8/docs/api/ + System.out.println(System.getProperty("java.class.path")); // TODO: + // log4j + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); + loggerConfig.setLevel(Level.WARN); + ctx.updateLoggers(); // This causes all Loggers to refetch + // information from their LoggerConfig. + System.out.println("Loading database..."); + try (DataProvider provider = new DataProvider()) { + User user = new User(); + user.setName("asd"); + user.setEmail("test@test.com"); + User user2 = new User(); + user2.setName("Teszt"); + user2.setEmail("test2@test.com"); + user2.getContacts().add(user); + provider.saveUser(user); + List users = provider.getUsers(); + user = users.get(0); + user.getContacts().add(user2); + provider.saveUser(user2); + users = provider.getUsers(); + user2 = users.get(1); + System.out.println(users); + System.out.println("1st's contact: " + user.getContacts().get(0)); + System.out.println("2nd's contact: " + user2.getContacts().get(0)); + Conversation convo = new Conversation(); + convo.getUsers().add(user); + convo.getUsers().add(user2); + Message msg = new Message(); + msg.setSender(user); + msg.setTime(new Date()); + msg.setMessage("Teszt 1"); + convo.getMesssages().add(msg); + Message msg2 = new Message(); + msg2.setSender(user2); + msg2.setTime(new Date()); + msg2.setMessage("Teszt 2"); + convo.getMesssages().add(msg2); + provider.saveConversation(convo); + } + System.out.println("Starting webserver..."); + HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 8080), 10); + Reflections rf = new Reflections( + new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(Page.class.getClassLoader())) + .addClassLoader(Page.class.getClassLoader()).addScanners(new SubTypesScanner()) + .filterInputsBy((String pkg) -> pkg.contains("io.github.norbipeti.chat.server.page"))); + Set> pages = rf.getSubTypesOf(Page.class); + for (Class page : pages) { + try { + if (Modifier.isAbstract(page.getModifiers())) + continue; + Page p = page.newInstance(); + addPage(server, p); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + server.start(); + System.out.println("Ready... Press Enter to stop."); + System.in.read(); + System.out.println("Stopping..."); + server.stop(1); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("Stopped"); + } + + private static void addPage(HttpServer server, Page page) { + server.createContext("/" + page.GetName(), page); + } } \ No newline at end of file diff --git a/src/io/github/norbipeti/chat/server/db/DataProvider.java b/src/io/github/norbipeti/chat/server/db/DataProvider.java index f4a3ffb..2ac63b0 100644 --- a/src/io/github/norbipeti/chat/server/db/DataProvider.java +++ b/src/io/github/norbipeti/chat/server/db/DataProvider.java @@ -1,87 +1,100 @@ -package io.github.norbipeti.chat.server.db; - -import java.util.List; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.Persistence; -import javax.persistence.TypedQuery; - -import io.github.norbipeti.chat.server.db.domain.*; - -public class DataProvider implements AutoCloseable { - private EntityManagerFactory emf; - - public DataProvider() { - emf = Persistence.createEntityManagerFactory("ChatServerPU"); - } - - public void addUser(User user) { - save(user); - } - - public void addConversation(Conversation convo) { - save(convo); - } - - private void save(Object object) { - EntityManager em = emf.createEntityManager(); - em.getTransaction().begin(); - em.persist(object); - em.getTransaction().commit(); - em.close(); - } - - public List getUsers() { - return get(User.class); - } - - public List getMessages() { - return get(Message.class); - } - - public List getConversations() { - return get(Conversation.class); - } - - private List get(Class cl) { - EntityManager em = emf.createEntityManager(); - TypedQuery query = em.createQuery("SELECT x FROM " + cl.getSimpleName() + " x", cl); - List results = query.getResultList(); - em.close(); - return results; - } - - public void removeUser(User user) { - EntityManager em = emf.createEntityManager(); - em.getTransaction().begin(); - User managedUser = em.find(User.class, user.getId()); - em.remove(managedUser); - em.getTransaction().commit(); - em.close(); - } - - public User getUser(Long id) { - return get(User.class, id); - } - - private T get(Class cl, Long id) { - EntityManager em = emf.createEntityManager(); - T result = em.find(cl, id); - em.close(); - return result; - } - - public void SetValues(Runnable action) { - EntityManager em = emf.createEntityManager(); - em.getTransaction().begin(); - action.run(); - em.getTransaction().commit(); - em.close(); - } - - @Override - public void close() { - if (emf != null) - emf.close(); - } -} +package io.github.norbipeti.chat.server.db; + +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.TypedQuery; + +import org.hibernate.Session; + +import io.github.norbipeti.chat.server.db.domain.*; + +public class DataProvider implements AutoCloseable { + private EntityManagerFactory emf; + + public DataProvider() { + emf = Persistence.createEntityManagerFactory("ChatServerPU"); + } + + public void saveUser(User user) { + save(user); + } + + public void saveConversation(Conversation convo) { + save(convo); + } + + private void save(Object object) { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + Session s = em.unwrap(Session.class); + s.saveOrUpdate(object); + em.persist(object); + em.getTransaction().commit(); + em.close(); + } + + public List getUsers() { + return get(User.class); + } + + public List getMessages() { + return get(Message.class); + } + + public List getConversations() { + return get(Conversation.class); + } + + private List get(Class cl) { + EntityManager em = emf.createEntityManager(); + TypedQuery query = em.createQuery("SELECT x FROM " + cl.getSimpleName() + " x", cl); + List results = query.getResultList(); + em.close(); + return results; + } + + public void removeUser(User user) { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + User managedUser = em.find(User.class, user.getId()); + em.remove(managedUser); + em.getTransaction().commit(); + em.close(); + } + + public User getUser(Long id) { + return get(User.class, id); + } + + private T get(Class cl, Long id) { + EntityManager em = emf.createEntityManager(); + T result = em.find(cl, id); + em.close(); + return result; + } + + @Deprecated + public void SetValues(Runnable action) { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + action.run(); + em.flush(); + em.getTransaction().commit(); + em.close(); + } + + @Override + public void close() { + if (emf != null) + emf.close(); + } + + public boolean isEntityManaged(Object entity) { + EntityManager em = emf.createEntityManager(); + boolean ret = em.contains(entity); + em.close(); + return ret; + } +} diff --git a/src/io/github/norbipeti/chat/server/db/domain/User.java b/src/io/github/norbipeti/chat/server/db/domain/User.java index 821412e..f549c22 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/User.java +++ b/src/io/github/norbipeti/chat/server/db/domain/User.java @@ -1,115 +1,113 @@ -package io.github.norbipeti.chat.server.db.domain; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import javax.persistence.*; - -@Entity -@Table(name = "\"User\"") -public class User { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", unique = true, nullable = false) - private Long id; - private String name; - private String email; - private String password; - @ElementCollection(fetch = FetchType.EAGER) - private List contacts; - private String salt; - @Column(columnDefinition = "CHAR(16) FOR BIT DATA") - private UUID sessionid; - @Version - @GeneratedValue - private int Version; - @ElementCollection(fetch = FetchType.EAGER) - @ManyToMany(cascade = CascadeType.ALL) - public List conversations; - - public List getContacts() { - if (contacts == null) - contacts = new ArrayList<>(); - return contacts; - } - - public void setContacts(List contacts) { - this.contacts = contacts; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEmail() { - return email; - } - - @Override - public String toString() { - List c = null; - if (contacts != null) { - c = new ArrayList<>(); - for (User u : contacts) - c.add(u.name); - } - return "User [id=" + id + ", name=" + name + ", email=" + email + ", password=" + password + ", contacts=" + c - + ", sessionid=" + sessionid + "]"; // TODO: SessionID null - // after getting from db - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getSalt() { - return salt; - } - - public void setSalt(String salt) { - this.salt = salt; - } - - public UUID getSessionid() { - return sessionid; - } - - public void setSessionid(UUID sessionid) { - this.sessionid = sessionid; - } - - public List getConversations() { - if (conversations == null) - conversations = new ArrayList<>(); - return conversations; - } - - public void setConversations(List conversations) { - this.conversations = conversations; - } - - public User() { - - } -} +package io.github.norbipeti.chat.server.db.domain; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.*; + +@Entity +@Table(name = "\"User\"") +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false) + private Long id; + private String name; + private String email; + private String password; + @ElementCollection(fetch = FetchType.EAGER) + private List contacts; + private String salt; + //@Column(columnDefinition = "CHAR(16) FOR BIT DATA") + @Column(columnDefinition="VARCHAR(64)") + private String sessionid; + @Version + @GeneratedValue + private int Version; + @ElementCollection(fetch = FetchType.EAGER) + @ManyToMany(cascade = CascadeType.ALL) + public List conversations; + + public List getContacts() { + if (contacts == null) + contacts = new ArrayList<>(); + return contacts; + } + + public void setContacts(List contacts) { + this.contacts = contacts; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + @Override + public String toString() { + List c = null; + if (contacts != null) { + c = new ArrayList<>(); + for (User u : contacts) + c.add(u.name); + } + return "User [id=" + id + ", name=" + name + ", email=" + email + ", password=" + password + ", contacts=" + c + + ", sessionid=" + sessionid + "]"; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt; + } + + public String getSessionid() { + return sessionid; + } + + public void setSessionid(String sessionid) { + this.sessionid = sessionid; + } + + public List getConversations() { + if (conversations == null) + conversations = new ArrayList<>(); + return conversations; + } + + public void setConversations(List conversations) { + this.conversations = conversations; + } + + public User() { + + } +} diff --git a/src/io/github/norbipeti/chat/server/page/IndexPage.java b/src/io/github/norbipeti/chat/server/page/IndexPage.java index 90f5605..0f2abf7 100644 --- a/src/io/github/norbipeti/chat/server/page/IndexPage.java +++ b/src/io/github/norbipeti/chat/server/page/IndexPage.java @@ -1,60 +1,53 @@ -package io.github.norbipeti.chat.server.page; - -import java.io.IOException; - -import org.jsoup.nodes.Element; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.ssl.internal.ssl.Provider; - -import io.github.norbipeti.chat.server.IOHelper; -import io.github.norbipeti.chat.server.db.DataProvider; -import io.github.norbipeti.chat.server.db.domain.Conversation; -import io.github.norbipeti.chat.server.db.domain.Message; -import io.github.norbipeti.chat.server.db.domain.User; - -public class IndexPage extends Page { - - @Override - public void handlePage(HttpExchange exchange) throws IOException { - // final User user = IOHelper.GetLoggedInUser(exchange); - TODO - final User user = new User(); - user.setEmail("test@test.com"); - user.setName("Norbi"); - user.setId(3L); - if (user == null) - IOHelper.SendModifiedPage(200, this, (doc) -> { - doc.getElementById("userbox").remove(); - doc.getElementById("usercontent").remove(); - return doc; - }, exchange); - else - IOHelper.SendModifiedPage(200, this, (doc) -> { - doc.getElementById("loginbox").remove(); - doc.getElementById("registerbox").remove(); - Element userbox = doc.getElementById("userbox"); - userbox.html(userbox.html().replace("", user.getName())); - Element channelmessages = doc.getElementById("channelmessages"); - try (DataProvider provider = new DataProvider()) { - Conversation convo = provider.getConversations().get(0); //TODO - for (Message message : convo.getMesssages()) { - Element msgelement = channelmessages.appendElement("div"); - Element header = msgelement.appendElement("p"); - header.text(message.getSender().getName() + " - " + message.getTime()); - Element body = msgelement.appendElement("p"); - body.text(message.getMessage()); - } - } - return doc; - }, exchange); - } // TODO: - // Validation - // at - // registration - - @Override - public String GetName() { - return ""; - } - -} +package io.github.norbipeti.chat.server.page; + +import java.io.IOException; + +import org.jsoup.nodes.Element; + +import com.sun.net.httpserver.HttpExchange; +import io.github.norbipeti.chat.server.IOHelper; +import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.db.domain.User; + +public class IndexPage extends Page { + + @Override + public void handlePage(HttpExchange exchange) throws IOException { + final User user = IOHelper.GetLoggedInUser(exchange); + /*final User user = new User(); + user.setEmail("test@test.com"); + user.setName("Norbi"); + user.setId(3L);*/ + if (user == null) + IOHelper.SendModifiedPage(200, this, (doc) -> { + doc.getElementById("userbox").remove(); + doc.getElementById("usercontent").remove(); + return doc; + }, exchange); + else + IOHelper.SendModifiedPage(200, this, (doc) -> { + doc.getElementById("loginbox").remove(); + doc.getElementById("registerbox").remove(); + Element userbox = doc.getElementById("userbox"); + userbox.html(userbox.html().replace("", user.getName())); + Element channelmessages = doc.getElementById("channelmessages"); + try (DataProvider provider = new DataProvider()) { + /*Conversation convo = provider.getConversations().get(0); // TODO + for (Message message : convo.getMesssages()) { + Element msgelement = channelmessages.appendElement("div"); + Element header = msgelement.appendElement("p"); + header.text(message.getSender().getName() + " - " + message.getTime()); + Element body = msgelement.appendElement("p"); + body.text(message.getMessage()); + }*/ + } + return doc; + }, exchange); + } // TODO: Validation at registration (no special chars, etc.) + + @Override + public String GetName() { + return ""; + } + +} diff --git a/src/io/github/norbipeti/chat/server/page/RegisterPage.java b/src/io/github/norbipeti/chat/server/page/RegisterPage.java index 487ee8f..3e2a508 100644 --- a/src/io/github/norbipeti/chat/server/page/RegisterPage.java +++ b/src/io/github/norbipeti/chat/server/page/RegisterPage.java @@ -1,72 +1,72 @@ -package io.github.norbipeti.chat.server.page; - -import java.io.IOException; -import org.json.JSONObject; -import org.mindrot.jbcrypt.BCrypt; - -import com.sun.net.httpserver.HttpExchange; - -import io.github.norbipeti.chat.server.IOHelper; -import io.github.norbipeti.chat.server.db.DataProvider; -import io.github.norbipeti.chat.server.db.domain.User; - -public class RegisterPage extends Page { - @Override - public void handlePage(HttpExchange exchange) throws IOException { - JSONObject post = IOHelper.GetPOSTJSON(exchange); - if (post != null) { - String errormsg = CheckValues(post, "name", "email", "pass", "pass2"); - if (errormsg.length() > 0) { - final String msg = errormsg; - IOHelper.SendResponse(200, (doc) -> doc.html(msg).ownerDocument(), exchange); - return; // TODO: Use JavaScript too, for error checks - } - try (DataProvider provider = new DataProvider()) { - for (User user : provider.getUsers()) { - if (post.get("email").equals(user.getEmail())) { - errormsg += "

An user with this name already exists

"; - break; - } - } - if (!post.get("pass").equals(post.get("pass2"))) - errormsg += "

The passwords don't match

"; - if (errormsg.length() > 0) { - final String msg = errormsg; - IOHelper.SendResponse(200, (doc) -> doc.html(msg).ownerDocument(), exchange); - return; - } - User user = new User(); - user.setName(post.getString("name")); - user.setEmail(post.getString("email")); - user.setSalt(BCrypt.gensalt()); // http://www.mindrot.org/projects/jBCrypt/ - user.setPassword(BCrypt.hashpw(post.getString("pass"), user.getSalt())); - provider.addUser(user); - User managedUser = provider.getUser(user.getId()); - IOHelper.LoginUser(exchange, managedUser, provider); - IOHelper.SendResponse(200, "Success", exchange); - } catch (Exception e) { - throw e; - } - return; - } - IOHelper.Redirect("/", exchange); - } - - private String CheckValues(JSONObject post, String... values) { - String errormsg = ""; - for (String value : values) - if (!CheckValue(post.getString(value))) - errormsg += "

" + value + " can't be empty

"; - return errormsg; - } - - private boolean CheckValue(String val) { - return val != null && val.length() > 0; - } - - @Override - public String GetName() { - return "register"; - } - -} +package io.github.norbipeti.chat.server.page; + +import java.io.IOException; +import org.json.JSONObject; +import org.mindrot.jbcrypt.BCrypt; + +import com.sun.net.httpserver.HttpExchange; + +import io.github.norbipeti.chat.server.IOHelper; +import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.db.domain.User; + +public class RegisterPage extends Page { + @Override + public void handlePage(HttpExchange exchange) throws IOException { + JSONObject post = IOHelper.GetPOSTJSON(exchange); + if (post != null) { + String errormsg = CheckValues(post, "name", "email", "pass", "pass2"); + if (errormsg.length() > 0) { + final String msg = errormsg; + IOHelper.SendResponse(200, (doc) -> doc.html(msg).ownerDocument(), exchange); + return; // TODO: Use JavaScript too, for error checks + } + try (DataProvider provider = new DataProvider()) { + for (User user : provider.getUsers()) { + if (post.get("email").equals(user.getEmail())) { + errormsg += "

An user with this name already exists

"; + break; + } + } + if (!post.get("pass").equals(post.get("pass2"))) + errormsg += "

The passwords don't match

"; + if (errormsg.length() > 0) { + final String msg = errormsg; + IOHelper.SendResponse(200, (doc) -> doc.html(msg).ownerDocument(), exchange); + return; + } + User user = new User(); + user.setName(post.getString("name")); + user.setEmail(post.getString("email")); + user.setSalt(BCrypt.gensalt()); // http://www.mindrot.org/projects/jBCrypt/ + user.setPassword(BCrypt.hashpw(post.getString("pass"), user.getSalt())); + provider.saveUser(user); + User managedUser = provider.getUser(user.getId()); + IOHelper.LoginUser(exchange, managedUser, provider); + IOHelper.SendResponse(200, "Success", exchange); + } catch (Exception e) { + throw e; + } + return; + } + IOHelper.Redirect("/", exchange); + } + + private String CheckValues(JSONObject post, String... values) { + String errormsg = ""; + for (String value : values) + if (!CheckValue(post.getString(value))) + errormsg += "

" + value + " can't be empty

"; + return errormsg; + } + + private boolean CheckValue(String val) { + return val != null && val.length() > 0; + } + + @Override + public String GetName() { + return "register"; + } + +}