diff --git a/util/pom.xml b/util/pom.xml
new file mode 100644
index 0000000..1c6672c
--- /dev/null
+++ b/util/pom.xml
@@ -0,0 +1,32 @@
+
+ 4.0.0
+ de.hsadmin.core
+ hsadmin-util
+ 4.0.4-SNAPSHOT
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+ junit
+ junit
+ 4.13.1
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+
+
+
diff --git a/util/src/main/java/de/hsadmin/core/util/Config.java b/util/src/main/java/de/hsadmin/core/util/Config.java
new file mode 100644
index 0000000..2d713a4
--- /dev/null
+++ b/util/src/main/java/de/hsadmin/core/util/Config.java
@@ -0,0 +1,58 @@
+package de.hsadmin.core.util;
+
+import java.io.File;
+import java.io.FileReader;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class Config {
+
+ private static Config instance;
+
+ private static Logger LOG = Logger.getLogger(Config.class.getName());
+
+ private Properties props;
+
+ private Config() {
+ props = new Properties();
+ File file = new File(System.getProperty("user.dir") + "/hsadmin.properties");
+ if (!file.canRead()) {
+ file = new File(System.getProperty("user.dir") + "/conf/hsadmin.properties");
+ }
+ if (!file.canRead()) {
+ file = new File(System.getProperty("user.home") + "/.hsadmin.properties");
+ }
+ if (!file.canRead()) {
+ file = new File("/etc/hsadmin.properties");
+ }
+ if (!file.canRead()) {
+ file = new File("/etc/hsadmin/hsadmin.properties");
+ }
+ if (file.canRead()) {
+ try {
+ LOG.info("Constructor - Properties-File: " + file.getAbsolutePath());
+ props.load(new FileReader(file));
+ } catch (Exception e) {
+ // should not happen
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static Config getInstance() {
+ if (instance == null) {
+ instance = new Config();
+ }
+ return instance;
+ }
+
+ public String getProperty(String propertyName) {
+ String property = props.getProperty(propertyName);
+ return property;
+ }
+
+ public String getProperty(String propertyName, String defaultValue) {
+ return props.getProperty(propertyName, defaultValue).trim();
+ }
+
+}
diff --git a/util/src/main/java/de/hsadmin/core/util/HSAdminException.java b/util/src/main/java/de/hsadmin/core/util/HSAdminException.java
new file mode 100644
index 0000000..351523c
--- /dev/null
+++ b/util/src/main/java/de/hsadmin/core/util/HSAdminException.java
@@ -0,0 +1,19 @@
+package de.hsadmin.core.util;
+
+public class HSAdminException extends Exception {
+
+ private static final long serialVersionUID = -5082179267383474532L;
+
+ public HSAdminException(String message) {
+ super(message);
+ }
+
+ public HSAdminException(Exception e) {
+ super(e);
+ }
+
+ public HSAdminException(String message, Exception aExc) {
+ super(message, aExc);
+ }
+
+}
diff --git a/util/src/main/java/de/hsadmin/core/util/IPv6Trick.java b/util/src/main/java/de/hsadmin/core/util/IPv6Trick.java
new file mode 100644
index 0000000..bab3fff
--- /dev/null
+++ b/util/src/main/java/de/hsadmin/core/util/IPv6Trick.java
@@ -0,0 +1,86 @@
+package de.hsadmin.core.util;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+
+public class IPv6Trick {
+
+ private static final String IPv4_LOCALHOST = "127.0.0";
+ private static final String IPv6_LOCALHOST = "::1";
+ private static final String IPv6_LOCALHOST_ALT = "0:0:0:0:0:0:0:1";
+
+ private static final String IPv4_83_223_79 = "83.223.79"; // Alboin-Kontor Berlin
+ private static final String IPv4_83_223_91 = "83.223.91"; // Alboin-Kontor Berlin
+ private static final String IPv4_83_223_95 = "83.223.95"; // Alboin-Kontor Berlin
+ private static final String IPv6_PREFIX_AK = "2a01:37:1000::1";
+
+ private static final String IPv4_83_223_78 = "83.223.78"; // e-Shelter Berlin
+ private static final String IPv4_83_223_94 = "83.223.94"; // e-Shelter Berlin
+ private static final String IPv6_PREFIX_ES = "2a01:37:3000::1";
+
+ private static final String IPv6_PREFIX_HS = "2a01:37:";
+ private static final String IPv6_PREFIX_HS_ALT = "2a01:0037:";
+
+ public static String convertIPv4ToIPv6(final String ipv4address) throws HSAdminException {
+ if (ipv4address == null || ipv4address.length() == 0) {
+ throw new HSAdminException("no IPv4 address given");
+ }
+ try {
+ InetAddress inetV4Address = InetAddress.getByName(ipv4address);
+ String inetV4AddressString = inetV4Address.getHostAddress();
+ if (inetV4AddressString.startsWith(IPv4_83_223_79) // Alboin-Kontor Berlin
+ || inetV4AddressString.startsWith(IPv4_83_223_91)
+ || inetV4AddressString.startsWith(IPv4_83_223_95) ) {
+ return embedIPv4Address(inetV4Address, InetAddress.getByName(IPv6_PREFIX_AK));
+ }
+ if (inetV4AddressString.startsWith(IPv4_83_223_78) // e-Shelter Berlin
+ || inetV4AddressString.startsWith(IPv4_83_223_94) ) {
+ return embedIPv4Address(inetV4Address, InetAddress.getByName(IPv6_PREFIX_ES));
+ }
+ } catch (UnknownHostException e) {
+ throw new HSAdminException(e);
+ }
+ throw new HSAdminException("unknown IPv4 address given");
+ }
+
+ public static boolean isKnownRemote(final String remoteAddress) {
+ boolean isKnown = false;
+ if (remoteAddress.startsWith(IPv4_LOCALHOST) || remoteAddress.startsWith(IPv6_LOCALHOST) || remoteAddress.startsWith(IPv6_LOCALHOST_ALT)) {
+ // localhost
+ isKnown = true;
+ }
+ if (remoteAddress.startsWith(IPv6_PREFIX_HS) || remoteAddress.startsWith(IPv6_PREFIX_HS_ALT)) {
+ // Hostsharing IPv6
+ isKnown = true;
+ }
+ if (remoteAddress.startsWith(IPv4_83_223_78) || remoteAddress.startsWith(IPv4_83_223_94)) {
+ // e-Shelter
+ isKnown = true;
+ }
+ if (remoteAddress.startsWith(IPv4_83_223_79) || remoteAddress.startsWith(IPv4_83_223_91) || remoteAddress.startsWith(IPv4_83_223_95)) {
+ // Speedbone Alboin Kontor
+ isKnown = true;
+ }
+ return isKnown;
+ }
+
+ private static String embedIPv4Address(final InetAddress ipv4address, final InetAddress ipv6Mask) throws UnknownHostException {
+ final byte[] ipv4Bytes = ipv4address.getAddress();
+ final byte[] ipv6Bytes = ipv6Mask.getAddress();
+ ipv6Bytes[10] = ipv4Bytes[0];
+ ipv6Bytes[11] = ipv4Bytes[1];
+ ipv6Bytes[12] = ipv4Bytes[2];
+ ipv6Bytes[13] = ipv4Bytes[3];
+ ipv6Bytes[14] = 0;
+ ipv6Bytes[15] = 0;
+ final InetAddress ipv6Address = InetAddress.getByAddress(ipv6Bytes);
+ final String ipv6String = ipv6Address.getHostAddress();
+ if (ipv6String.startsWith("/")) {
+ return ipv6String.substring(1);
+ } else {
+ return ipv6String;
+ }
+ }
+
+}
diff --git a/util/src/main/java/de/hsadmin/core/util/PasswordGenerator.java b/util/src/main/java/de/hsadmin/core/util/PasswordGenerator.java
new file mode 100644
index 0000000..8258cd2
--- /dev/null
+++ b/util/src/main/java/de/hsadmin/core/util/PasswordGenerator.java
@@ -0,0 +1,147 @@
+package de.hsadmin.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public final class PasswordGenerator {
+
+ private static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
+ private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String DIGITS = "0123456789";
+ private static final String PUNCTUATION = "!@#$%&*()_+-=[]|,./?><";
+ private boolean useLower;
+ private boolean useUpper;
+ private boolean useDigits;
+ private boolean usePunctuation;
+
+ private PasswordGenerator() {
+ throw new UnsupportedOperationException("Empty constructor is not supported.");
+ }
+
+ private PasswordGenerator(PasswordGeneratorBuilder builder) {
+ this.useLower = builder.useLower;
+ this.useUpper = builder.useUpper;
+ this.useDigits = builder.useDigits;
+ this.usePunctuation = builder.usePunctuation;
+ }
+
+ public static class PasswordGeneratorBuilder {
+
+ private boolean useLower;
+ private boolean useUpper;
+ private boolean useDigits;
+ private boolean usePunctuation;
+
+ public PasswordGeneratorBuilder() {
+ this.useLower = false;
+ this.useUpper = false;
+ this.useDigits = false;
+ this.usePunctuation = false;
+ }
+
+ /**
+ * Set true in case you would like to include lower characters (abc...xyz).
+ * Default false.
+ *
+ * @param useLower true in case you would like to include lower characters
+ * (abc...xyz). Default false.
+ * @return the builder for chaining.
+ */
+ public PasswordGeneratorBuilder useLower(boolean useLower) {
+ this.useLower = useLower;
+ return this;
+ }
+
+ /**
+ * Set true in case you would like to include upper characters (ABC...XYZ).
+ * Default false.
+ *
+ * @param useUpper true in case you would like to include upper characters
+ * (ABC...XYZ). Default false.
+ * @return the builder for chaining.
+ */
+ public PasswordGeneratorBuilder useUpper(boolean useUpper) {
+ this.useUpper = useUpper;
+ return this;
+ }
+
+ /**
+ * Set true in case you would like to include digit characters (123..). Default
+ * false.
+ *
+ * @param useDigits true in case you would like to include digit characters
+ * (123..). Default false.
+ * @return the builder for chaining.
+ */
+ public PasswordGeneratorBuilder useDigits(boolean useDigits) {
+ this.useDigits = useDigits;
+ return this;
+ }
+
+ /**
+ * Set true in case you would like to include punctuation characters (!@#..).
+ * Default false.
+ *
+ * @param usePunctuation true in case you would like to include punctuation
+ * characters (!@#..). Default false.
+ * @return the builder for chaining.
+ */
+ public PasswordGeneratorBuilder usePunctuation(boolean usePunctuation) {
+ this.usePunctuation = usePunctuation;
+ return this;
+ }
+
+ /**
+ * Get an object to use.
+ *
+ * @return the {@link gr.idrymavmela.business.lib.PasswordGenerator} object.
+ */
+ public PasswordGenerator build() {
+ return new PasswordGenerator(this);
+ }
+ }
+
+ /**
+ * This method will generate a password depending the use* properties you
+ * define. It will use the categories with a probability. It is not sure that
+ * all of the defined categories will be used.
+ *
+ * @param length the length of the password you would like to generate.
+ * @return a password that uses the categories you define when constructing the
+ * object with a probability.
+ */
+ public String generate(int length) {
+ // Argument Validation.
+ if (length <= 0) {
+ return "";
+ }
+
+ // Variables.
+ StringBuilder password = new StringBuilder(length);
+ Random random = new Random(System.nanoTime());
+
+ // Collect the categories to use.
+ List charCategories = new ArrayList<>(4);
+ if (useLower) {
+ charCategories.add(LOWER);
+ }
+ if (useUpper) {
+ charCategories.add(UPPER);
+ }
+ if (useDigits) {
+ charCategories.add(DIGITS);
+ }
+ if (usePunctuation) {
+ charCategories.add(PUNCTUATION);
+ }
+
+ // Build the password.
+ for (int i = 0; i < length; i++) {
+ String charCategory = charCategories.get(random.nextInt(charCategories.size()));
+ int position = random.nextInt(charCategory.length());
+ password.append(charCategory.charAt(position));
+ }
+ return new String(password);
+ }
+}
\ No newline at end of file
diff --git a/util/src/main/java/de/hsadmin/core/util/PasswordTool.java b/util/src/main/java/de/hsadmin/core/util/PasswordTool.java
new file mode 100644
index 0000000..9f87743
--- /dev/null
+++ b/util/src/main/java/de/hsadmin/core/util/PasswordTool.java
@@ -0,0 +1,44 @@
+package de.hsadmin.core.util;
+
+public final class PasswordTool {
+
+ public static final int MIN_COMPLEXITY = 3;
+ public static final int MIN_PASSWORD_LENGTH = 6;
+
+ private static final PasswordGenerator passwordGenerator = new PasswordGenerator.PasswordGeneratorBuilder()
+ .useDigits(true)
+ .useLower(true)
+ .useUpper(true)
+ .build();
+
+ public static String generatePassword() {
+ return passwordGenerator.generate(14);
+ }
+
+ public static void checkPasswordComplexity(final String password) throws HSAdminException {
+ int containsLowercaseCharacter = 0;
+ int containsUppercaseCharacter = 0;
+ int containsSpecialCharacter = 0;
+ int containsDigit = 0;
+ for (int idx = 0; idx < password.length(); idx++) {
+ char chr = password.charAt(idx);
+ if (chr >= 'a' && chr <= 'z') {
+ containsLowercaseCharacter = 1;
+ } else
+ if (chr >= 'A' && chr <= 'Z') {
+ containsUppercaseCharacter = 1;
+ } else
+ if (chr >= '0' && chr <= '1') {
+ containsDigit = 1;
+ } else {
+ containsSpecialCharacter = 1;
+ }
+ }
+ int complexity = containsLowercaseCharacter + containsUppercaseCharacter
+ + containsSpecialCharacter + containsDigit;
+ if (complexity < MIN_COMPLEXITY || password.length() < MIN_PASSWORD_LENGTH) {
+ throw new HSAdminException("simple password");
+ }
+ }
+
+}
diff --git a/util/src/main/java/de/hsadmin/core/util/TextUtil.java b/util/src/main/java/de/hsadmin/core/util/TextUtil.java
new file mode 100644
index 0000000..1c80168
--- /dev/null
+++ b/util/src/main/java/de/hsadmin/core/util/TextUtil.java
@@ -0,0 +1,87 @@
+package de.hsadmin.core.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class TextUtil {
+
+ private static final DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
+
+ public static synchronized String replaceUmlautCharacters(String umlautString) {
+ StringBuffer buffer = new StringBuffer();
+ for (char c : umlautString.toCharArray()) {
+ if ( (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ (c == ' ') ) {
+ buffer.append(c);
+ } else {
+ switch (c) {
+ case 'ä':
+ buffer.append("ae");
+ break;
+ case 'ö':
+ buffer.append("oe");
+ break;
+ case 'ü':
+ buffer.append("ue");
+ break;
+ case 'Ä':
+ buffer.append("Ae");
+ break;
+ case 'Ö':
+ buffer.append("Oe");
+ break;
+ case 'Ü':
+ buffer.append("Ue");
+ break;
+ case 'ß':
+ buffer.append("ss");
+ break;
+ default:
+ buffer.append('-');
+ break;
+ }
+ }
+ }
+ return buffer.toString();
+ }
+
+ public static synchronized String format(Date date) {
+ return df.format(date);
+ }
+
+ public static synchronized Date parseDate(String dateString) {
+ try {
+ return df.parse(dateString);
+ } catch (ParseException e) {
+ try {
+ return df.parse("01.01.1970");
+ } catch (ParseException e1) {
+ // don't care
+ return null;
+ }
+ }
+ }
+
+ public static synchronized String format(boolean free) {
+ return free ? "true" : "false";
+ }
+
+ public static synchronized boolean parseBool(String boolString) {
+ boolean parsedValue = "T".equals(boolString.toUpperCase()) || "TRUE".equals(boolString.toUpperCase());
+ return parsedValue;
+ }
+
+ public static synchronized String hidePassword(String passwd) {
+ final StringBuffer val = new StringBuffer(passwd.substring(0, 2));
+ for (int i = 2; i < 6; i++) {
+ val.append('*');
+ }
+ return val.toString();
+ }
+
+}
diff --git a/util/src/test/java/de/hsadmin/core/util/IPv6TrickTest.java b/util/src/test/java/de/hsadmin/core/util/IPv6TrickTest.java
new file mode 100644
index 0000000..7d17a8f
--- /dev/null
+++ b/util/src/test/java/de/hsadmin/core/util/IPv6TrickTest.java
@@ -0,0 +1,39 @@
+package de.hsadmin.core.util;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.After;
+import org.junit.Test;
+
+public class IPv6TrickTest {
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testConvertIPv4ToIPv6() {
+ try {
+ assertTrue(IPv6Trick.convertIPv4ToIPv6("83.223.78.2").startsWith("2a01:37:"));
+ assertTrue(IPv6Trick.convertIPv4ToIPv6("83.223.79.22").startsWith("2a01:37:"));
+ assertTrue(IPv6Trick.convertIPv4ToIPv6("83.223.91.222").startsWith("2a01:37:"));
+ assertTrue(IPv6Trick.convertIPv4ToIPv6("83.223.94.2").startsWith("2a01:37:"));
+ assertTrue(IPv6Trick.convertIPv4ToIPv6("83.223.95.2").startsWith("2a01:37:"));
+ } catch (HSAdminException e) {
+ fail(e.getMessage());
+ }
+ try {
+ IPv6Trick.convertIPv4ToIPv6("4.4.4.4");
+ fail("unknown adress");
+ } catch (HSAdminException e) {
+ // Ok
+ }
+ }
+
+ @Test
+ public void testIsKnownRemote() {
+ assertTrue(IPv6Trick.isKnownRemote("83.223.78.2"));
+ }
+
+}
diff --git a/util/src/test/java/de/hsadmin/core/util/PasswordToolTest.java b/util/src/test/java/de/hsadmin/core/util/PasswordToolTest.java
new file mode 100644
index 0000000..1e586f5
--- /dev/null
+++ b/util/src/test/java/de/hsadmin/core/util/PasswordToolTest.java
@@ -0,0 +1,62 @@
+package de.hsadmin.core.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PasswordToolTest {
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testCheckPasswordComplexity() {
+ String pw1 = "TTtt1";
+ String pw2 = "TTtt11";
+ String pw3 = "TTT12_";
+ String pw4 = "Testt1";
+ String pw5 = "Tthdsuhdalkdj";
+ String pw6 = "zaehler42";
+ try {
+ PasswordTool.checkPasswordComplexity(pw1);
+ fail("should fail");
+ } catch (HSAdminException e) {
+ assertTrue("simple password".equals(e.getMessage()));
+ }
+ try {
+ PasswordTool.checkPasswordComplexity(pw2);
+ } catch (HSAdminException e) {
+ fail(e.getMessage());
+ }
+ try {
+ PasswordTool.checkPasswordComplexity(pw3);
+ } catch (HSAdminException e) {
+ fail(e.getMessage());
+ }
+ try {
+ PasswordTool.checkPasswordComplexity(pw4);
+ } catch (HSAdminException e) {
+ fail(e.getMessage());
+ }
+ try {
+ PasswordTool.checkPasswordComplexity(pw5);
+ fail("should fail");
+ } catch (HSAdminException e) {
+ assertTrue("simple password".equals(e.getMessage()));
+ }
+ try {
+ PasswordTool.checkPasswordComplexity(pw6);
+ fail("should fail");
+ } catch (HSAdminException e) {
+ assertTrue("simple password".equals(e.getMessage()));
+ }
+ }
+
+}