Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.mhs.hboxmaintenanceserver.utils; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.UserInfo; import com.mhs.hboxmaintenanceserver.HBoxMaintenanceServer; import com.mhs.hboxmaintenanceserver.bean.Form; import com.mhs.hboxmaintenanceserver.config.DefaultConfig; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; /** * * @author Zulhaizat */ public class Utils { private static String COOKIE = null; public static String IPADDRESS_PATTERN = "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])"; public static String MACADDRESS_PATTERN = "(([0-9A-Fa-f]{2}[-:]){5}[0-9A-Fa-f]{2})|(([0-9A-Fa-f]{4}\\.){2}[0-9A-Fa-f]{4})"; /** * Set SSH's session * * @param host * @param username * @param password * @param jSch * @return * @throws JSchException */ public static Session setSSH(String host, String username, String password, JSch jSch) throws JSchException { Session _session = jSch.getSession(username, host); _session.setPassword(password); _session.setConfig("StrictHostKeyChecking", "no"); _session.setUserInfo(new UserInfo() { @Override public String getPassphrase() { throw null; } @Override public String getPassword() { return password; } @Override public boolean promptPassword(String string) { return false; } @Override public boolean promptPassphrase(String string) { return false; } @Override public boolean promptYesNo(String string) { return true; } @Override public void showMessage(String string) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }); _session.connect(); return _session; } private static void createFolder(String folder_name) { File folder = new File(folder_name); if (!folder.exists()) { folder.mkdir(); } } /** * Check folders' availability * */ public static void checkFoldersAvailability() { createFolder(DefaultConfig.ROOT_FOLDER); createFolder(DefaultConfig.LOG_FOLDER); createFolder(DefaultConfig.PROP_FOLDER); createFolder(DefaultConfig.HBOX_FOLDER); createFolder(DefaultConfig.TEMP_FOLDER); createFolder(DefaultConfig.INSTALLER_FOLDER); createFolder(DefaultConfig.DRIVERS_FOLDER); createFile("/drivers/drivers.zip", DefaultConfig.DRIVERS_ZIP); try { File zipFile = new File(DefaultConfig.DRIVERS_ZIP); unzip(zipFile.getAbsolutePath(), DefaultConfig.DRIVERS_FOLDER); zipFile.delete(); } catch (IOException ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } createFile("/HBox_config/isirona.properties.cfg", DefaultConfig.HBOX_CONFIG); createFile("/HBox_config/wpa_supplicant.conf", DefaultConfig.HBOX_WIFI); createFile("/HBox_config/ca.pem", DefaultConfig.HBOX_WIFI_CA_CERT); createFile("/HBox_config/ca.pkey", DefaultConfig.HBOX_WIFI_PRIVATE_KEY); createFile("/HBox_config/crontab", DefaultConfig.HBOX_CRONTAB); createFile("/installer/" + Utils.getHBoxPropValues("installer_zip"), DefaultConfig.INSTALLER_FOLDER + File.separator + Utils.getHBoxPropValues("installer_zip")); createFile("/installer/installer.sh", DefaultConfig.INSTALLER_SCRIPT); } /** * Unzip it * * @param zipFile input zip file * @param outputFolder * @throws java.io.FileNotFoundException */ public static void unzip(String zipFile, String outputFolder) throws FileNotFoundException, IOException { byte[] buffer = new byte[1024]; try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { ZipEntry ze = zis.getNextEntry(); while (ze != null) { String fileName = ze.getName(); File newFile = new File(outputFolder + File.separator + fileName); if (ze.isDirectory()) { newFile.mkdirs(); } else { try (FileOutputStream fos = new FileOutputStream(newFile)) { int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } fos.close(); } } ze = zis.getNextEntry(); } zis.closeEntry(); zis.close(); } } /** * Create file from resource * * @param resource_path * @param output_path */ public static void createFile(String resource_path, String output_path) { File file = new File(output_path); if (!file.exists()) { try { byte[] b = Utils.getBytesFromResource(resource_path); file.createNewFile(); if (b != null) { try (FileOutputStream fos = new FileOutputStream(file, true)) { IOUtils.write(b, fos); fos.close(); } } } catch (IOException ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } } } /** * Create properties file * * @param filename * @param props * @return */ private static File createPropFile(String filename, String[] props) { File file = new File(filename); if (!file.exists()) { FileWriter pw = null; try { pw = new FileWriter(file); for (String s : props) { pw.write(new String(s.getBytes(), "UTF-8")); } pw.close(); } catch (IOException ex) { Logger.getLogger(Utils.class.getName()).log(Level.SEVERE, null, ex); } finally { try { if (pw != null) { pw.close(); } } catch (IOException ex) { Logger.getLogger(Utils.class.getName()).log(Level.SEVERE, null, ex); } } } return file; } /** * Check if default prop file is exist * * @return */ public static boolean isDefaultPropFileExist() { return isPropFileExist(DefaultConfig.DEFAULT_PROP); } /** * Create default prop file * * @return */ public static File createDefaultPropFile() { return createPropFile(DefaultConfig.DEFAULT_PROP, DefaultConfig.PROPERTIES); } /** * Create hbox prop file * * @return */ public static File createHBoxPropFile() { return createPropFile(DefaultConfig.HBOX_PROP, DefaultConfig.HBOX_PROPERTIES); } public static File createWIFI_PROP_file() { return createPropFile(DefaultConfig.WIFI_PROP, DefaultConfig.WIFI_PROPERTIES); } /** * Check for properties file exist * * @param filename * @return */ private static boolean isPropFileExist(String filename) { File file = new File(filename); return file.exists(); } public static class Host { /** * @return the active */ public boolean isActive() { return active; } /** * @param active the active to set */ public void setActive(boolean active) { this.active = active; } /** * @return the fromDCX_server */ public boolean isFromDCX_server() { return fromDCX_server; } /** * @param fromDCX_server the fromDCX_server to set */ public void setFromDCX_server(boolean fromDCX_server) { this.fromDCX_server = fromDCX_server; } /** * @return the ip_address */ public String getIp_address() { return ip_address; } /** * @param ip_address the ip_address to set */ public void setIp_address(String ip_address) { this.ip_address = ip_address; } /** * @return the mac_address */ public String getMac_address() { return mac_address; } /** * @param mac_address the mac_address to set */ public void setMac_address(String mac_address) { this.mac_address = mac_address; } private String ip_address; private String mac_address; private boolean fromDCX_server = false; private boolean active = true; public Host(String ip_address, String mac_address, String host_name) { this.ip_address = ip_address; this.mac_address = mac_address; this.host_name = host_name; } public Host(String ip_address, String host_name) { this.ip_address = ip_address; this.host_name = host_name; } public Host(String ip_address, String host_name, boolean fromDCX_server, boolean active) { this.ip_address = ip_address; this.host_name = host_name; this.fromDCX_server = fromDCX_server; this.active = active; } public Host() { } /** * @return the host_name */ public String getHost_name() { return host_name; } /** * @param host_name the host_name to set */ public void setHost_name(String host_name) { this.host_name = host_name; } private String host_name; } /** * Install window service * * @param serviceName * @param displayName * @param desc * @param classPath * @param startClass * @param stopClass * @param JVM_options * @return * @throws URISyntaxException * @throws IOException * @throws InterruptedException */ public static boolean installWindowService(String serviceName, String displayName, String desc, String classPath, String startClass, String stopClass, String JVM_options) throws URISyntaxException, IOException, InterruptedException { Process process = Runtime.getRuntime() .exec("cmd /c " + DefaultConfig.DAEMON_FOLDER + File.separator + "prunsrv.exe //IS//" + serviceName + " " + "--Install=\"" + DefaultConfig.DAEMON_FOLDER + File.separator + "prunsrv.exe\" " + "--Description=\"" + desc + "\" " + "--Classpath=\"" + classPath + "\" " + "--DisplayName=\"" + displayName + "\" " + "--Jvm=auto " + "--StartMode=jvm " + "--StopMode=jvm " + "--StartClass=" + startClass + " " + "--StartParams=start;" + HBoxMaintenanceServer.DEFAULT_P + " " + "--StopClass=" + stopClass + " " + "--StopParams=stop " + JVM_options); return process.waitFor() == 0; } public static String getDefaultPropValues(String key) { return getPropValues(key, createDefaultPropFile()); } public static String getHBoxPropValues(String key) { return getPropValues(key, createHBoxPropFile()); } public static String getWIFI_PropValues(String key) { return getPropValues(key, createWIFI_PROP_file()); } /** * Get properties from configuration file * * @param key * @param propFile * @return */ private static String getPropValues(String key, File propFile) { try { Properties p = new Properties(); String prop; try (FileInputStream fis = new FileInputStream(propFile)) { p.load(fis); prop = p.getProperty(key); fis.close(); } if (prop.matches("ENC\\(.*\\)")) { return Utils.decrypt(prop); } return prop; } catch (FileNotFoundException ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } catch (IOException ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } catch (Exception ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } return null; } /** * Get bytes from resource * * @param uri * @return * @throws IOException */ public static byte[] getBytesFromResource(String uri) throws IOException { byte[] b; try (InputStream is = Utils.class.getResourceAsStream(uri)) { if (is == null) { return null; } b = IOUtils.toByteArray(is); is.close(); } return b; } public static String getExt(String filename) { return filename.substring(filename.lastIndexOf('.') + 1); } /** * Get LIST of HBOX in DHCP * * @param ip_range * @param manufacturer * @return * @throws IOException */ public static Host[] getListOfHBox_IN_DHCP(String ip_range, String manufacturer) throws IOException { ProcessBuilder pb = new ProcessBuilder("nmap", "-sP", ip_range); Process process = pb.start(); ArrayList<Host> hosts; try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) { String line, hostname; Host host = null; Pattern pattern; Matcher matcher; hosts = new ArrayList<>(); while ((line = br.readLine()) != null) { if (host == null && line.contains("Nmap scan report for")) { pattern = Pattern.compile(IPADDRESS_PATTERN, Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(line); host = new Host(); String ip_address = ""; while (matcher.find()) { ip_address += matcher.group(); } host.setIp_address(ip_address); } else if (host != null && line.matches("MAC Address: (.*) \\(" + manufacturer + "\\)")) { pattern = Pattern.compile(MACADDRESS_PATTERN, Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(line); String mac_address = ""; while (matcher.find()) { mac_address += matcher.group(); } host.setMac_address(mac_address.replaceAll("\\:", "")); hostname = host.getMac_address(); hostname = hostname.substring(hostname.length() - 6, hostname.length()); host.setHost_name("HBOX-" + hostname.toLowerCase()); hosts.add(host); host = null; } } } if (!hosts.isEmpty()) { return hosts.toArray(new Host[hosts.size()]); } return null; } public static class ReplaceString_File { private final String _old; private final String _new; public ReplaceString_File(String _old, String _new) { this._old = _old; this._new = _new; } /** * @return the _old */ public String getOld() { return _old; } /** * @return the _new */ public String getNew() { return _new; } } /** * Replace string in file * * @param rsfs * @param origFilename * @param prefix * @return * @throws IOException */ public static File replaceStringInFile(ReplaceString_File[] rsfs, String origFilename, String prefix) throws IOException { File tempFile = File.createTempFile(prefix + "-", ".TMP", new File(DefaultConfig.TEMP_FOLDER)); String content = FileUtils.readFileToString(new File(origFilename), "UTF-8"); for (ReplaceString_File rsf : rsfs) { content = content.replaceAll(rsf.getOld(), rsf.getNew()); } FileUtils.writeStringToFile(tempFile, content, "UTF-8"); return tempFile; } /** * Send form post * * @param form * @return * @throws MalformedURLException * @throws IOException */ public static Form sendPostForm(Form form) throws IOException { return sendPostForm(form, null); } /** * Send form post * * @param form * @param forms * @return * @throws MalformedURLException * @throws IOException */ public static Form sendPostForm(Form form, Form[] forms) throws MalformedURLException, IOException { URL obj = new URL(form.getUrl().trim()); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setDoInput(true); if (forms != null) { con.setDoOutput(true); // optional default is GET con.setRequestMethod("POST"); } //add request header con.setRequestProperty("User-Agent", DefaultConfig.USER_AGENT); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); con.setRequestProperty("Referer", form.getReferer()); con.setRequestProperty("Origin", form.getOrigin()); con.setRequestProperty("Host", form.getHost()); if (COOKIE != null) { try { con.setRequestProperty("Cookie", COOKIE); } catch (Exception ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } } String urlParameters = ""; if (forms != null) { for (Form fb : forms) { urlParameters += "&" + fb.getKey() + "=" + fb.getValue(); } urlParameters = urlParameters.substring(1); try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) { wr.writeBytes(urlParameters); wr.close(); } } if (con.getHeaderField("Set-Cookie") != null) { COOKIE = con.getHeaderField("Set-Cookie"); } Form form1 = new Form(); form1.setResponseCode(con.getResponseCode()); StringBuilder response = new StringBuilder(); if (form1.getResponseCode() == 200) { try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) { String inputLine; while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); } form1.setResult(response.toString()); } return form1; } /** * List directory contents for a resource folder. Not recursive. This is * basically a brute-force implementation. Works for regular files and also * JARs. * * @author Greg Briggs * @param path Should end with "/", but not start with one. * @return Just the name of each member item, not the full paths. * @throws URISyntaxException * @throws IOException */ public static String[] getResourceListing(String path) throws URISyntaxException, IOException { URL dirURL = Utils.class.getResource(path); if (dirURL != null && dirURL.getProtocol().equals("file")) { /* A file path: easy enough */ return new File(dirURL.toURI()).list(); } if (dirURL == null) { /* * In case of a jar file, we can't actually find a directory. * Have to assume the same jar as clazz. */ String me = Utils.class.getName().replace(".", "/") + ".class"; dirURL = Utils.class.getClassLoader().getResource(me); } if (dirURL.getProtocol().equals("file")) { /* A file path: easy enough */ String parent = (new File(dirURL.toURI()).getParent()); return new File(parent + "/../../../../../../resources/" + path).list(); } if (dirURL.getProtocol().equals("jar")) { /* A JAR path */ String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar Set<String> result = new HashSet<>(); //avoid duplicates in case it is a subdirectory while (entries.hasMoreElements()) { String name = entries.nextElement().getName(); if (name.startsWith(path)) { //filter according to the path String entry = name.substring(path.length()); int checkSubdir = entry.indexOf("/"); if (checkSubdir >= 0) { // if it is a subdirectory, we just return the directory name entry = entry.substring(0, checkSubdir); } result.add(entry); } } return result.toArray(new String[result.size()]); } throw new UnsupportedOperationException("Cannot list files for URL " + dirURL); } /** * Blowfish encryption * * @param value * @return * @throws java.lang.Exception */ public static String encrypt(String value) throws Exception { // create a key generator based upon the Blowfish cipher KeyGenerator keygenerator = KeyGenerator.getInstance("Blowfish"); File file = new File(DefaultConfig.SECRET_KEY); SecretKey secretkey; if (file.exists()) { // Load key from file secretkey = new SecretKeySpec(FileUtils.readFileToByteArray(file), "Blowfish"); } else { // create a key secretkey = keygenerator.generateKey(); FileUtils.writeByteArrayToFile(file, secretkey.getEncoded()); } // create a cipher based upon Blowfish Cipher cipher = Cipher.getInstance("Blowfish"); // initialise cipher to with secret key cipher.init(Cipher.ENCRYPT_MODE, secretkey); // encrypt message return bytesToHex(cipher.doFinal(value.getBytes())); } /** * Blowfish decryption * * @param value * @return * @throws java.lang.Exception */ public static String decrypt(String value) throws Exception { File file = new File(DefaultConfig.SECRET_KEY); SecretKey secretkey; if (file.exists()) { // Load key from file secretkey = new SecretKeySpec(FileUtils.readFileToByteArray(file), "Blowfish"); // create a cipher based upon Blowfish Cipher cipher = Cipher.getInstance("Blowfish"); cipher.init(Cipher.DECRYPT_MODE, secretkey); return new String(cipher.doFinal(hexToBytes(value.replace("ENC(", "").replace(")", "")))); } else { return value; } } public static byte[] hexToBytes(String str) { if (str == null) { return null; } else if (str.length() < 2) { return null; } else { int len = str.length() / 2; byte[] buffer = new byte[len]; for (int i = 0; i < len; i++) { buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16); } return buffer; } } public static String bytesToHex(byte[] data) { if (data == null) { return null; } else { int len = data.length; String str = ""; for (int i = 0; i < len; i++) { if ((data[i] & 0xFF) < 16) { str = str + "0" + java.lang.Integer.toHexString(data[i] & 0xFF); } else { str = str + java.lang.Integer.toHexString(data[i] & 0xFF); } } return str.toUpperCase(); } } /** * Encrypt some value in properties file * * @param propFilename * @param key * @param value * @throws Exception */ private static void encryptProperty(String propFilename, String key, String value) throws Exception { File file = new File(propFilename); if (file.exists()) { String properties = FileUtils.readFileToString(file); List<String> lines = FileUtils.readLines(file); for (String line : lines) { String[] _line = line.split("="); if (_line[0].trim().equals(key.trim())) { properties = properties.replace(line, _line[0].trim() + "=ENC(" + encrypt(value.replace("encode(", "").replace(")", "")) + ")"); break; } } FileUtils.writeStringToFile(file, properties); } } /** * Encode all prop values that need to be encoded * * @param propFile * @throws Exception */ public static void encodeAllPropValues(File propFile) throws Exception { try { Properties p = new Properties(); Set<Object> propKeySet; String propKey; try (FileInputStream fis = new FileInputStream(propFile)) { p.load(fis); propKeySet = p.keySet(); for (Object _propKey : propKeySet) { propKey = String.valueOf(_propKey); String val = p.getProperty(propKey); if (val.matches("encode\\(.*\\)")) { encryptProperty(propFile.getAbsolutePath(), propKey, val); } } fis.close(); } } catch (FileNotFoundException ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } catch (IOException ex) { DCXLogger.error(Utils.class, Level.SEVERE, ex); } } }