You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

498 lines
15 KiB
Java

/*
* Copyright (C) 2009-2017 Alistair Neil <info@dazzleships.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package lib;
import java.awt.Desktop;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.Random;
import java.util.regex.Pattern;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileFilter;
/**
*
* @author Alistair Neil <info@dazzleships.net>
*/
public final class Utilities {
/**
* Constructor
*/
public Utilities() {
}
/**
* Covert list to csv
*
* @param al
* @return String of comma separated values
*/
public static String getListAsCSV(ArrayList<String> al) {
return al.toString().replace("[", "").replace("]", "").replace(" ", "");
}
/**
* Preloads filechooser in background so it will open instantly when
* requested
*/
public static void preloadFileChooser() {
Thread t = new Thread(new java.lang.Runnable() {
@Override
public void run() {
JFileChooser fileChooser = new JFileChooser();
}
});
t.start();
}
/**
* Opens java file chooser dialog, convenience method. Returns filepath if
* successful and null if not
*
* @param parent
* @param folder
* @param filter Extension filter
* @param mode Fileselection mode
* @return String Filepath
*/
public static String openFileChooser(Frame parent, String folder, FileFilter filter, int mode) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(mode);
fileChooser.setCurrentDirectory(new File(folder));
if (filter != null) {
fileChooser.addChoosableFileFilter(filter);
}
int intReturn = fileChooser.showOpenDialog(parent);
if (intReturn == JFileChooser.APPROVE_OPTION) {
return fileChooser.getSelectedFile().getAbsolutePath();
} else {
return null;
}
}
/**
* Check for newer appversion
*
* @param localversion
* @param remoteversion
* @return True if newer
*/
public static boolean isNewerVersion(String localversion, String remoteversion) {
return convertBuildnumToFloat(remoteversion) > convertBuildnumToFloat(localversion);
}
/**
* Convert an debian build number into a floating point number
*
* @param version
* @return Float version
*/
private static float convertBuildnumToFloat(String version) {
float result;
Pattern p;
String[] parts;
try {
if (version.contains("-")) {
// Handling for old non-debian compatible version
p = Pattern.compile("-");
parts = p.split(version);
} else {
// Handling for new debian compatible version
p = Pattern.compile("\\.");
parts = p.split(version);
parts[0] = parts[0] + "." + parts[1];
parts[1] = parts[2];
parts[2] = "";
}
result = Float.parseFloat(parts[0]);
result += (Float.parseFloat(parts[1]) / 100000);
} catch (Exception ex) {
version = version.replaceAll("[^0-9.]", "");
result = convertVersionToFloat(version);
}
return result;
}
/**
* Convert a windows version number into a floating point number
*
* @param version
* @return Float version
*/
private static float convertVersionToFloat(String version) {
int c;
float f;
version = version.toLowerCase();
if (version.startsWith("v")) {
version = version.substring(1);
}
try {
c = version.charAt(version.length() - 1);
if (c > 96) {
version = version.substring(0, version.length() - 1);
Float fraction = (float) (c - 96) / 10000;
f = Float.parseFloat(version) + fraction;
} else {
f = Float.parseFloat(version);
}
} catch (Exception ex) {
f = 0;
}
return f;
}
/**
* Open the desktop default file editor
*
* @param path Path to file
*/
public static void editFile(String path) {
if (OSFunction.isLinux()) {
OSFunction.launchProcess("xdg-open", path);
return;
}
if (OSFunction.isWindows()) {
OSFunction.launchProcess("notepad", path);
}
}
/**
* Launch the desktops default file handling program
*
* @param strUrl
* @return Returns true if successful
*/
public static boolean openFileExternally(final String strUrl) {
String url = strUrl.replace("\\", "/");
try {
if (OSFunction.isLinux()) {
OSFunction.launchProcess("xdg-open", url);
} else {
if (Desktop.isDesktopSupported()) {
Desktop deskSupport = Desktop.getDesktop();
if (url.startsWith("http") || url.startsWith("ftp")) {
deskSupport.browse(new URI(url));
} else {
deskSupport.open(new File(url));
}
}
}
return true;
} catch (URISyntaxException | IOException ex) {
}
return false;
}
/**
* Initialises the UI Look and Feel
*
* @param theme
*/
public static void loadUIStyle(String theme) {
try {
if (theme == null) {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
return;
}
if (theme.contentEquals("Metal")) {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
return;
}
if (theme.contentEquals("Nimbus")) {
// Switch to Nimbus theme
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
return;
}
if (theme.contentEquals("System")) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
return;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
return;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
// If everything else fails use default cross platform metal
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
}
/**
* Adjust specified column width based on the width of a test string
*
* @param table
* @param test
*/
public static void adjustTableColumnWidth(JTable table, String... test) {
FontMetrics ourFontMetrics = table.getFontMetrics(table.getFont());
int col = 0;
for (String s : test) {
table.getColumn(table.getColumnName(col++)).setPreferredWidth(ourFontMetrics.stringWidth(s));
}
}
/**
* Generate secret key.
*
* @param length
* @return String key
*/
public static String generateSecretKey(int length) {
StringBuilder buffer = new StringBuilder();
Random random = new Random();
String chars = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int x;
try {
for (int i = 0; i < length; i++) {
x = random.nextInt(chars.length() - 1);
buffer.append(chars.substring(x, x + 1));
}
} catch (Exception ex) {
}
return buffer.toString();
}
public static String getTorHashPassword(String secret) {
byte[] key = S2KRFC2440(secret);
return "16:" + byteToHex(key);
}
/**
* Secret to key, Algorithm info taken from
* http://sunsite.icm.edu.pl/gnupg/rfc2440-3.html
*
* @param secret
* @return hashed key for the given secret
*/
public static byte[] S2KRFC2440(String secret) {
// Create our message digest for SHA-1
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (Exception ex) {
return null;
}
// Create our random S2K salt, the 9th byte is loaded with the code count which
// determines the amount of octet hashing used.
// This salt is eventually combined with the secret to prevent dictionary attacks
int codecount = 32;
byte[] s2ksalt = new byte[9];
SecureRandom sr = new SecureRandom();
sr.nextBytes(s2ksalt);
s2ksalt[8] = (byte) codecount;
// The octet hashing count is defined by the following formula where EXPBIAS is 6
int octethashcount = (16 + (codecount & 15)) << ((codecount >> 4) + 6);
// Merge our S2K salt and partialsecret arrays together into one array to
// create the full secret key.
byte[] partialsecret;
try {
partialsecret = secret.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
return null;
}
byte[] fullsecret = new byte[8 + partialsecret.length];
System.arraycopy(s2ksalt, 0, fullsecret, 0, 8);
System.arraycopy(partialsecret, 0, fullsecret, 8, partialsecret.length);
// Do the hashing based on the hashcount
while (true) {
if (octethashcount < fullsecret.length) {
md.update(fullsecret, 0, octethashcount);
break;
} else {
md.update(fullsecret);
}
octethashcount -= fullsecret.length;
}
// Create our final key by merging s2kspecifier and digest result
byte[] ourkey = new byte[20 + 9];
System.arraycopy(md.digest(), 0, ourkey, 9, 20);
System.arraycopy(s2ksalt, 0, ourkey, 0, 9);
return ourkey;
}
/**
* Get SHAHash using given password string
*
* @param password
* @return SHAhash string
*/
public static String getSHAHash(String password) {
String sha1 = "";
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(password.getBytes("UTF-8"));
sha1 = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
}
return sha1;
}
/**
* Convert byte to a hex string
*
* @param hash
* @return byte as a hex string
*/
private static String byteToHex(final byte[] hash) {
String result;
try (Formatter formatter = new Formatter()) {
for (byte b : hash) {
formatter.format("%02x", b);
}
result = formatter.toString();
}
return result;
}
/**
* Retrieve text from a resource text file
*
* @param resourcepath
* @return String text
*/
public static String getTextFromResource(String resourcepath) {
SimpleFile sf = new SimpleFile(resourcepath);
sf.openBufferedResource();
String text = sf.readEntireFile();
sf.closeFile();
return text;
}
/**
* Retrieve text from a text file
*
* @param filepath
* @return String text
*/
public static String getTextFromFile(String filepath) {
SimpleFile sf = new SimpleFile(filepath);
String text = "";
if (sf.exists()) {
sf.openBufferedRead();
text = sf.readEntireFile();
sf.closeFile();
}
return text;
}
/**
* Calculate the sha1 checksum of a given file
*
* @param filepath
* @return Checksum as a hex string
*/
public static String getSha1Sum(String filepath) {
StringBuilder sb = new StringBuilder("");
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
FileInputStream fis = new FileInputStream(filepath);
byte[] dataBytes = new byte[1024];
int nread;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
byte[] mdbytes = md.digest();
//convert the byte to hex format
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
} catch (NoSuchAlgorithmException | IOException ex) {
}
return sb.toString();
}
/**
* Creates a hidden dummy window for registration to various docks/launchers
* Fixes the neverending launching indicator
*/
public static void registerWindow() {
final JFrame jf = new JFrame();
jf.addWindowListener(new java.awt.event.WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
jf.dispose();
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
jf.setUndecorated(true);
jf.setBounds(0, 0, 0, 0);
jf.setVisible(true);
}
}