diff --git a/client/build.gradle.kts b/client/build.gradle.kts
index 058b9f2..c4e737f 100644
--- a/client/build.gradle.kts
+++ b/client/build.gradle.kts
@@ -9,7 +9,9 @@ ktfmt { kotlinLangStyle() }
dependencies {
implementation("com.jgoodies:jgoodies-forms:1.6.0")
implementation("com.miglayout:miglayout-swing:5.2")
+ implementation("com.konghq:unirest-java:3.14.2")
implementation(project(":core"))
+ testImplementation(testFixtures(project(":core")))
}
application {
diff --git a/client/src/main/java/bean/HyperlinkAdaptor.java b/client/src/main/java/bean/HyperlinkAdaptor.java
deleted file mode 100644
index f46d59a..0000000
--- a/client/src/main/java/bean/HyperlinkAdaptor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package bean;
-
-import java.awt.Component;
-import java.awt.Cursor;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-import util.Debug;
-
-public class HyperlinkAdaptor extends MouseAdapter
-{
- private HyperlinkListener listener = null;
- private Component listenerWindow = null;
-
- public HyperlinkAdaptor(HyperlinkListener listener)
- {
- if (!(listener instanceof Component))
- {
- Debug.stackTrace("Creating HyperlinkAdaptor with non-component: " + listener);
- }
-
- this.listener = listener;
- this.listenerWindow = (Component)listener;
- }
-
- @Override
- public void mouseClicked(MouseEvent arg0)
- {
- listener.linkClicked(arg0);
- }
-
- @Override
- public void mouseMoved(MouseEvent arg0)
- {
- if (listener.isOverHyperlink(arg0))
- {
- listenerWindow.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
- }
- else
- {
- listenerWindow.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- }
- }
-
- @Override
- public void mouseExited(MouseEvent arg0)
- {
- listenerWindow.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- }
-}
diff --git a/client/src/main/java/bean/HyperlinkListener.java b/client/src/main/java/bean/HyperlinkListener.java
deleted file mode 100644
index 747565e..0000000
--- a/client/src/main/java/bean/HyperlinkListener.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package bean;
-
-import java.awt.event.MouseEvent;
-
-public interface HyperlinkListener
-{
- public void linkClicked(MouseEvent arg0);
- public boolean isOverHyperlink(MouseEvent arg0);
-}
diff --git a/client/src/main/java/online/util/DesktopEntropyClient.java b/client/src/main/java/online/util/DesktopEntropyClient.java
index 6a7d147..f5f0e35 100644
--- a/client/src/main/java/online/util/DesktopEntropyClient.java
+++ b/client/src/main/java/online/util/DesktopEntropyClient.java
@@ -75,13 +75,6 @@ public void sendAsyncInSingleThread(MessageSenderParams message)
senderThread.start();
}
- /*public void sendAsync(MessageSenderParams message)
- {
- MessageSender senderRunnable = new MessageSender(this, message);
- Thread senderThread = new Thread(senderRunnable, "MessageSender");
- senderThread.start();
- }*/
-
@Override
public String sendSyncOnDevice(MessageSender runnable)
{
@@ -91,6 +84,6 @@ public String sendSyncOnDevice(MessageSender runnable)
@Override
public void checkForUpdates()
{
- UpdateChecker.checkForUpdates(FILE_NAME_ENTROPY_JAR, SERVER_PORT_NUMBER_DOWNLOAD);
+ UpdateManager.INSTANCE.checkForUpdates(OnlineConstants.ENTROPY_VERSION_NUMBER);
}
}
diff --git a/client/src/main/java/online/util/ResponseHandler.java b/client/src/main/java/online/util/ResponseHandler.java
index 36ef191..e6e606d 100644
--- a/client/src/main/java/online/util/ResponseHandler.java
+++ b/client/src/main/java/online/util/ResponseHandler.java
@@ -265,7 +265,7 @@ private static void handleConnectFailure(Element root)
if (failureReason.contains("out of date"))
{
- promptForUpdate(root);
+ promptForUpdate();
}
else
{
@@ -273,20 +273,15 @@ private static void handleConnectFailure(Element root)
}
}
- private static void promptForUpdate(final Element rootElement)
+ private static void promptForUpdate()
{
- SwingUtilities.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- int answer = DialogUtil.showQuestion("Entropy needs to update in order to connect. \n\nUpdate now?", false);
- if (answer == JOptionPane.YES_OPTION)
- {
- UpdateChecker.startUpdate(rootElement, OnlineConstants.FILE_NAME_ENTROPY_JAR, OnlineConstants.SERVER_PORT_NUMBER_DOWNLOAD);
- }
- }
- });
+ SwingUtilities.invokeLater(() -> {
+ int answer = DialogUtil.showQuestion("Entropy needs to update in order to connect. \n\nUpdate now?", false);
+ if (answer == JOptionPane.YES_OPTION)
+ {
+ UpdateManager.INSTANCE.checkForUpdates(OnlineConstants.ENTROPY_VERSION_NUMBER);
+ }
+ });
}
private static void handleKickOff(Element root)
diff --git a/client/src/main/java/screen/AbstractAboutDialog.java b/client/src/main/java/screen/AbstractAboutDialog.java
index 9ee95f3..f33094a 100644
--- a/client/src/main/java/screen/AbstractAboutDialog.java
+++ b/client/src/main/java/screen/AbstractAboutDialog.java
@@ -14,10 +14,10 @@
import javax.swing.SwingConstants;
import bean.HyperlinkAdaptor;
-import bean.HyperlinkListener;
+import bean.IHyperlinkListener;
public abstract class AbstractAboutDialog extends JDialog
- implements HyperlinkListener,
+ implements IHyperlinkListener,
ActionListener
{
public AbstractAboutDialog()
diff --git a/client/src/main/java/util/DialogUtil.java b/client/src/main/java/util/DialogUtil.java
index 9639ebe..51220a8 100644
--- a/client/src/main/java/util/DialogUtil.java
+++ b/client/src/main/java/util/DialogUtil.java
@@ -5,6 +5,8 @@
import screen.LoadingDialog;
+import java.awt.*;
+
import static utils.InjectedThings.logger;
public class DialogUtil
@@ -114,4 +116,13 @@ public static void dismissLoadingDialog()
{
loadingDialog.dismissDialog();
}
+
+ public static void showCustomMessage(Object message) {
+ JOptionPane.showMessageDialog(
+ null,
+ message,
+ "Information",
+ JOptionPane.INFORMATION_MESSAGE
+ );
+ }
}
diff --git a/client/src/main/java/util/UpdateChecker.java b/client/src/main/java/util/UpdateChecker.java
deleted file mode 100644
index 291b49b..0000000
--- a/client/src/main/java/util/UpdateChecker.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package util;
-
-import java.io.IOException;
-
-import javax.swing.JOptionPane;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-/**
- * Class to check for updates and launch the EntropyUpdater via a batch file if they are available
- */
-public class UpdateChecker implements XmlConstants
-{
- public static void checkForUpdates(String filename, int portForDownload)
- {
- try
- {
- checkForUpdatesAndDoDownloadIfRequired(filename, portForDownload);
- }
- finally
- {
- DialogUtil.dismissLoadingDialog();
- }
- }
-
- private static void checkForUpdatesAndDoDownloadIfRequired(String filename, int portForDownload)
- {
- //Show this here, checking the CRC can take time
- DialogUtil.showLoadingDialog("Checking for updates...");
- String crc = FileUtil.getMd5Crc(filename);
- if (crc == null)
- {
- DialogUtil.showError("Failed to check for updates (couldn't find " + filename + ").");
- return;
- }
-
- Debug.append("Checking for updates - fileCrc is " + crc);
-
- //We have a CRC, so go to the Server and check against it's copy.
- Document crcCheck = factoryCrcCheck(crc, filename);
- String responseStr = AbstractClient.getInstance().sendSync(crcCheck, false);
- if (responseStr == null)
- {
- DialogUtil.showError("Failed to check for updates (unable to connect).");
- return;
- }
-
- DialogUtil.dismissLoadingDialog();
-
- Document xmlResponse = XmlUtil.getDocumentFromXmlString(responseStr);
- Element rootElement = xmlResponse.getDocumentElement();
- String responseName = rootElement.getNodeName();
- if (responseName.equals(RESPONSE_TAG_NO_UPDATES))
- {
- //No need to show a message, should be pretty obvious
- Debug.append("I am up to date");
- return;
- }
-
- //An update is available
- int answer = DialogUtil.showQuestion("An update is available. Would you like to download it now?", false);
- if (answer == JOptionPane.NO_OPTION)
- {
- return;
- }
-
- startUpdate(rootElement, filename, portForDownload);
- }
-
- private static Document factoryCrcCheck(String fileCrc, String fileName)
- {
- Document document = XmlUtil.factoryNewDocument();
- Element rootElement = document.createElement(ROOT_TAG_CRC_CHECK);
- rootElement.setAttribute("FileCrc", fileCrc);
- rootElement.setAttribute("FileName", fileName);
-
- document.appendChild(rootElement);
- return document;
- }
-
- public static void startUpdate(Element rootElement, String filename, int portForUpdate)
- {
- int fileSize = XmlUtil.getAttributeInt(rootElement, "FileSize");
- String version = rootElement.getAttribute("VersionNumber");
- String args = fileSize + " " + version + " " + filename + " " + portForUpdate;
-
- try
- {
- if (AbstractClient.isAppleOs())
- {
- Runtime.getRuntime().exec("update.command " + args);
- }
- else
- {
- Runtime.getRuntime().exec("cmd /c start update.bat " + args);
- }
- }
- catch (IOException ioe)
- {
- Debug.stackTrace(ioe);
- String manualCommand = "update.bat " + args;
-
- String msg = "Failed to launch update.bat - call the following manually to perform the update: \n\n" + manualCommand;
- DialogUtil.showError(msg);
- }
-
- System.exit(0);
- }
-}
diff --git a/client/src/main/java/util/UpdateManager.kt b/client/src/main/java/util/UpdateManager.kt
new file mode 100644
index 0000000..2acd364
--- /dev/null
+++ b/client/src/main/java/util/UpdateManager.kt
@@ -0,0 +1,152 @@
+package util
+
+import bean.LinkLabel
+import java.awt.BorderLayout
+import java.io.File
+import javax.swing.JLabel
+import javax.swing.JOptionPane
+import javax.swing.JPanel
+import kong.unirest.Unirest
+import kong.unirest.json.JSONObject
+import utils.InjectedThings.logger
+import kotlin.system.exitProcess
+
+/**
+ * Automatically check for and download updates using the Github API
+ *
+ * https://developer.github.com/v3/repos/releases/#get-the-latest-release
+ */
+object UpdateManager {
+ fun checkForUpdates(currentVersion: String) {
+ // Show this here, checking the CRC can take time
+ logger.info("updateCheck", "Checking for updates - my version is $currentVersion")
+
+ val jsonResponse = queryLatestReleaseJson(OnlineConstants.ENTROPY_REPOSITORY_URL)
+ jsonResponse ?: return
+
+ val metadata = parseUpdateMetadata(jsonResponse)
+ if (metadata == null || !shouldUpdate(currentVersion, metadata)) {
+ return
+ }
+
+ startUpdate(metadata.getArgs(), Runtime.getRuntime())
+ }
+
+ fun queryLatestReleaseJson(repositoryUrl: String): JSONObject? {
+ try {
+ DialogUtil.showLoadingDialog("Checking for updates...")
+
+ val response = Unirest.get("$repositoryUrl/releases/latest").asJson()
+ if (response.status != 200) {
+ logger.error(
+ "updateError",
+ "Received non-success HTTP status: ${response.status} - ${response.statusText}",
+ "responseBody" to response.body,
+ )
+ DialogUtil.showError("Failed to check for updates (unable to connect).")
+ return null
+ }
+
+ return response.body.`object`
+ } catch (t: Throwable) {
+ logger.error("updateError", "Caught $t checking for updates", t)
+ DialogUtil.showError("Failed to check for updates (unable to connect).")
+ return null
+ } finally {
+ DialogUtil.dismissLoadingDialog()
+ }
+ }
+
+ fun shouldUpdate(currentVersion: String, metadata: UpdateMetadata): Boolean {
+ val newVersion = metadata.version
+ if (newVersion == currentVersion) {
+ logger.info("updateResult", "Up to date")
+ return false
+ }
+
+ // An update is available
+ logger.info("updateAvailable", "Newer release available - $newVersion")
+
+ if (!AbstractClient.isWindowsOs()) {
+ showManualDownloadMessage(newVersion)
+ return false
+ }
+
+ val answer =
+ DialogUtil.showQuestion(
+ "An update is available (${metadata.version}). Would you like to download it now?",
+ false
+ )
+ return answer == JOptionPane.YES_OPTION
+ }
+
+ private fun showManualDownloadMessage(newVersion: String) {
+ val fullUrl = "${OnlineConstants.ENTROPY_MANUAL_DOWNLOAD_URL}/tag/$newVersion"
+ val panel = JPanel()
+ panel.layout = BorderLayout(0, 0)
+ val lblOne =
+ JLabel("An update is available ($newVersion). You can download it manually from:")
+ val linkLabel = LinkLabel(fullUrl) { launchUrl(fullUrl) }
+
+ panel.add(lblOne, BorderLayout.NORTH)
+ panel.add(linkLabel, BorderLayout.SOUTH)
+
+ DialogUtil.showCustomMessage(panel)
+ }
+
+ fun parseUpdateMetadata(responseJson: JSONObject): UpdateMetadata? {
+ return try {
+ val remoteVersion = responseJson.getString("tag_name")
+ val assets = responseJson.getJSONArray("assets")
+ val asset = assets.getJSONObject(0)
+
+ val assetId = asset.getLong("id")
+ val fileName = asset.getString("name")
+ val size = asset.getLong("size")
+ UpdateMetadata(remoteVersion, assetId, fileName, size)
+ } catch (t: Throwable) {
+ logger.error(
+ "parseError",
+ "Error parsing update response",
+ t,
+ "responseBody" to responseJson
+ )
+ null
+ }
+ }
+
+ fun startUpdate(args: String, runtime: Runtime) {
+ prepareBatchFile()
+
+ try {
+ runtime.exec("cmd /c start update.bat $args")
+ } catch (t: Throwable) {
+ logger.error("batchError", "Error running update.bat", t)
+ val manualCommand = "update.bat $args"
+
+ val msg =
+ "Failed to launch update.bat - call the following manually to perform the update: \n\n$manualCommand"
+ DialogUtil.showError(msg)
+ return
+ }
+
+ exitProcess(0)
+ }
+
+ fun prepareBatchFile() {
+ val updateFile = File("update.bat")
+
+ updateFile.delete()
+ val updateScript = javaClass.getResource("/update/update.bat").readText()
+ updateFile.writeText(updateScript)
+ }
+}
+
+data class UpdateMetadata(
+ val version: String,
+ val assetId: Long,
+ val fileName: String,
+ val size: Long
+) {
+ fun getArgs() = "$size $version $fileName $assetId"
+}
diff --git a/client/src/main/java/util/UrlUtil.kt b/client/src/main/java/util/UrlUtil.kt
new file mode 100644
index 0000000..e8c0a2f
--- /dev/null
+++ b/client/src/main/java/util/UrlUtil.kt
@@ -0,0 +1,12 @@
+package util
+
+import utils.InjectedThings.logger
+
+/** N.B. will likely only work on linux */
+fun launchUrl(url: String, runtime: Runtime = Runtime.getRuntime()) {
+ try {
+ runtime.exec("xdg-open $url")
+ } catch (e: Exception) {
+ logger.error("urlError", "Failed to launch $url", e)
+ }
+}
diff --git a/client/src/main/kotlin/bean/HyperlinkAdaptor.kt b/client/src/main/kotlin/bean/HyperlinkAdaptor.kt
new file mode 100644
index 0000000..7510cd0
--- /dev/null
+++ b/client/src/main/kotlin/bean/HyperlinkAdaptor.kt
@@ -0,0 +1,36 @@
+package bean
+
+import java.awt.Component
+import java.awt.Cursor
+import java.awt.event.MouseAdapter
+import java.awt.event.MouseEvent
+
+class HyperlinkAdaptor(private val listener: IHyperlinkListener) : MouseAdapter() {
+ private val listenerWindow = listener as Component
+
+ override fun mouseClicked(arg0: MouseEvent) = listener.linkClicked(arg0)
+
+ override fun mouseMoved(arg0: MouseEvent) {
+ if (listener.isOverHyperlink(arg0)) {
+ listenerWindow.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
+ } else {
+ listenerWindow.cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)
+ }
+ }
+
+ override fun mouseEntered(e: MouseEvent) {
+ if (listener.isOverHyperlink(e)) {
+ listenerWindow.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
+ }
+ }
+
+ override fun mouseDragged(e: MouseEvent?) {
+ if (listenerWindow.cursor.type == Cursor.HAND_CURSOR) {
+ listenerWindow.cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)
+ }
+ }
+
+ override fun mouseExited(arg0: MouseEvent?) {
+ listenerWindow.cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)
+ }
+}
diff --git a/client/src/main/kotlin/bean/IHyperlinkListener.kt b/client/src/main/kotlin/bean/IHyperlinkListener.kt
new file mode 100644
index 0000000..58075c7
--- /dev/null
+++ b/client/src/main/kotlin/bean/IHyperlinkListener.kt
@@ -0,0 +1,9 @@
+package bean
+
+import java.awt.event.MouseEvent
+
+interface IHyperlinkListener {
+ fun linkClicked(arg0: MouseEvent)
+
+ fun isOverHyperlink(arg0: MouseEvent): Boolean
+}
diff --git a/client/src/main/kotlin/bean/LinkLabel.kt b/client/src/main/kotlin/bean/LinkLabel.kt
new file mode 100644
index 0000000..e20a46f
--- /dev/null
+++ b/client/src/main/kotlin/bean/LinkLabel.kt
@@ -0,0 +1,20 @@
+package bean
+
+import java.awt.Color
+import java.awt.event.MouseEvent
+import javax.swing.JLabel
+
+class LinkLabel(text: String, private val linkClicked: () -> Unit) :
+ JLabel("$text"), IHyperlinkListener {
+ init {
+ foreground = Color.BLUE
+
+ val adaptor = HyperlinkAdaptor(this)
+ addMouseListener(adaptor)
+ addMouseMotionListener(adaptor)
+ }
+
+ override fun linkClicked(arg0: MouseEvent) = linkClicked()
+
+ override fun isOverHyperlink(arg0: MouseEvent) = true
+}
diff --git a/client/src/test/kotlin/bean/LinkLabelTest.kt b/client/src/test/kotlin/bean/LinkLabelTest.kt
new file mode 100644
index 0000000..cace779
--- /dev/null
+++ b/client/src/test/kotlin/bean/LinkLabelTest.kt
@@ -0,0 +1,37 @@
+package bean
+
+import com.github.alyssaburlton.swingtest.doClick
+import com.github.alyssaburlton.swingtest.doHover
+import com.github.alyssaburlton.swingtest.doHoverAway
+import io.kotest.matchers.shouldBe
+import io.mockk.mockk
+import io.mockk.verify
+import java.awt.Color
+import java.awt.Cursor
+import org.junit.jupiter.api.Test
+import helper.AbstractTest
+
+class LinkLabelTest : AbstractTest() {
+ @Test
+ fun `Should style text as URL`() {
+ val label = LinkLabel("https://foo.bar") {}
+
+ label.text shouldBe "https://foo.bar"
+ label.foreground shouldBe Color.BLUE
+ }
+
+ @Test
+ fun `Should update cursor on hover, and execute callback on click`() {
+ val callback = mockk<() -> Unit>(relaxed = true)
+ val label = LinkLabel("test", callback)
+
+ label.doHover()
+ label.cursor shouldBe Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
+
+ label.doHoverAway()
+ label.cursor shouldBe Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)
+
+ label.doClick()
+ verify { callback() }
+ }
+}
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index a766fbf..b73ff3b 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -2,6 +2,7 @@ plugins {
id("Entropy.kotlin-common-conventions")
id("com.ncorti.ktfmt.gradle") version "0.15.1"
`java-library`
+ `java-test-fixtures`
}
ktfmt { kotlinLangStyle() }
diff --git a/core/src/main/java/util/AbstractClient.java b/core/src/main/java/util/AbstractClient.java
index 548e9a9..36b9417 100644
--- a/core/src/main/java/util/AbstractClient.java
+++ b/core/src/main/java/util/AbstractClient.java
@@ -76,6 +76,10 @@ public static boolean isAppleOs()
{
return operatingSystem.contains("mac") || operatingSystem.contains("darwin");
}
+ public static boolean isWindowsOs()
+ {
+ return operatingSystem.contains("windows");
+ }
public void checkForUpdatesIfRequired()
{
diff --git a/core/src/main/java/util/Debug.java b/core/src/main/java/util/Debug.java
index 5297dc1..7bb4083 100644
--- a/core/src/main/java/util/Debug.java
+++ b/core/src/main/java/util/Debug.java
@@ -4,29 +4,16 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
-import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class Debug implements CoreRegistry
{
- private static final long ERROR_MESSAGE_DELAY_MILLIS = 10000; //10s
-
- private static long lastErrorMillis = -1;
-
private static DebugOutput output = null;
- private static DebugExtension debugExtension = null;
private static boolean logToSystemOut = false;
- private static ThreadFactory loggerFactory = new ThreadFactory()
- {
- @Override
- public Thread newThread(Runnable r)
- {
- return new Thread(r, "Logger");
- }
- };
+ private static ThreadFactory loggerFactory = r -> new Thread(r, "Logger");
private static ExecutorService logService = Executors.newFixedThreadPool(1, loggerFactory);
@@ -117,27 +104,12 @@ public static void stackTrace(Throwable t)
{
stackTrace(t, "");
}
- public static void stackTrace(Throwable t, String message)
- {
- stackTrace(t, message, false);
- }
public static void stackTraceNoError(Throwable t)
{
- stackTrace(t, "", true);
+ stackTrace(t, "");
}
- public static void stackTrace(Throwable t, String message, boolean suppressError)
+ public static void stackTrace(Throwable t, String message)
{
- if (debugExtension != null
- && !suppressError)
- {
- boolean showError = System.currentTimeMillis() - lastErrorMillis > ERROR_MESSAGE_DELAY_MILLIS;
- debugExtension.exceptionCaught(showError);
- if (showError)
- {
- lastErrorMillis = System.currentTimeMillis();
- }
- }
-
String datetime = getCurrentTimeForLogging();
String trace = "";
@@ -178,11 +150,7 @@ public static void initialise(DebugOutput output)
{
Debug.output = output;
}
-
- public static void setDebugExtension(DebugExtension debugExtension)
- {
- Debug.debugExtension = debugExtension;
- }
+
public static void setLogToSystemOut(boolean logToSystemOut)
{
Debug.logToSystemOut = logToSystemOut;
diff --git a/core/src/main/java/util/DebugExtension.java b/core/src/main/java/util/DebugExtension.java
deleted file mode 100644
index a193629..0000000
--- a/core/src/main/java/util/DebugExtension.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package util;
-
-public interface DebugExtension
-{
- public void exceptionCaught(boolean showError);
- public void unableToEmailLogs();
- public void sendEmail(String title, String message) throws Exception;
-}
diff --git a/core/src/main/java/util/FileUtil.java b/core/src/main/java/util/FileUtil.java
index c66c49b..0f1bb79 100644
--- a/core/src/main/java/util/FileUtil.java
+++ b/core/src/main/java/util/FileUtil.java
@@ -24,42 +24,6 @@
public class FileUtil
{
- public static File createNewFile(String filePath, String contents)
- {
- File file = new File(filePath);
- boolean success = false;
-
- try
- {
- success = file.createNewFile();
- }
- catch (IOException ioe)
- {
- Debug.append("Caught " + ioe + " creating file " + filePath);
- }
-
- if (!success)
- {
- return null;
- }
-
- //We have created the empty file, now fill it
- try (FileOutputStream fos = new FileOutputStream(filePath))
- {
- byte[] bytes = contents.getBytes("UTF-8");
- fos.write(bytes);
- }
- catch (IOException ioe)
- {
- Debug.append("Caught " + ioe + " trying to insert bytes into file " + filePath);
- deleteFileIfExists(filePath);
- return null;
- }
-
- Debug.append("Successfully created file " + file);
- return file;
- }
-
public static String getMd5Crc(String filePath)
{
String crc = null;
@@ -97,61 +61,6 @@ public static long getFileSize(String filePath)
return fileSize;
}
- public static boolean deleteFileIfExists(String filePath)
- {
- boolean success = false;
-
- try
- {
- Path path = Paths.get(filePath);
- success = Files.deleteIfExists(path);
- }
- catch (Throwable t)
- {
- Debug.stackTrace(t, "Failed to delete file");
- }
-
- return success;
- }
-
- public static String swapInFile(String oldFilePath, String newFilePath)
- {
- boolean success = true;
-
- File oldFile = new File(oldFilePath);
- String oldFileName = oldFile.getName();
- File newFile = new File(newFilePath);
-
- File zzOldFile = new File(oldFile.getParent(), "zz" + oldFileName);
- if (oldFile.exists()
- && !oldFile.renameTo(zzOldFile))
- {
- return "Failed to rename old out of the way.";
- }
-
- success &= newFile.renameTo(new File(oldFile.getParent(), oldFileName));
- if (!success)
- {
- return "Failed to rename new file to " + oldFileName;
- }
-
- if (zzOldFile.isFile())
- {
- success &= deleteFileIfExists(zzOldFile.getPath());
- }
- else
- {
- success &= deleteDirectoryIfExists(zzOldFile);
- }
-
- if (!success)
- {
- return "Failed to delete zz'd old file: " + oldFile.getPath();
- }
-
- return null;
- }
-
public static void saveTextToFile(String text, Path destinationPath)
{
Charset charset = Charset.forName("US-ASCII");
@@ -170,24 +79,6 @@ public static void saveTextToFile(String text, Path destinationPath)
}
}
- public static String getFileContentsAsString(File file)
- {
- String ret = null;
-
- try
- {
- Path path = file.toPath();
- byte[] bytes = Files.readAllBytes(path);
- ret = new String(bytes, "UTF-8");
- }
- catch (Throwable t)
- {
- Debug.stackTrace(t);
- }
-
- return ret;
- }
-
public static String getBase64DecodedFileContentsAsString(File file)
{
try
@@ -211,196 +102,9 @@ public static void encodeAndSaveToFile(Path destinationPath, String stringToWrit
saveTextToFile(encodedStringToWrite, destinationPath);
}
- public static Dimension getImageDim(String path)
- {
- Dimension result = null;
- String suffix = getFileSuffix(path);
- Iterator iter = ImageIO.getImageReadersBySuffix(suffix);
- if (iter.hasNext())
- {
- ImageReader reader = iter.next();
- try (ImageInputStream stream = new FileImageInputStream(new File(path));)
- {
- reader.setInput(stream);
- int width = reader.getWidth(reader.getMinIndex());
- int height = reader.getHeight(reader.getMinIndex());
- result = new Dimension(width, height);
- }
- catch (IOException e)
- {
- Debug.stackTrace(e);
- }
- finally
- {
- reader.dispose();
- }
- }
- else
- {
- Debug.stackTrace("No reader found for file extension: " + suffix + " (full path: " + path + ")");
- }
-
- return result;
- }
-
- private static String getFileSuffix(String path)
- {
- if (path == null
- || path.lastIndexOf('.') == -1)
- {
- return "";
- }
-
- int dotIndex = path.lastIndexOf('.');
- return path.substring(dotIndex + 1);
- }
-
- /**
- * Helper to create a file object for a URL, e.g. from a classpath resource.
- * No longer used
- */
- /*public static File getForURL(URL url)
- {
- try
- {
- URI uri = url.toURI();
- return new File(uri);
- }
- catch (Throwable t)
- {
- Debug.append("Failed to construct file for URL: " + url);
- Debug.stackTrace(t);
- return null;
- }
- }*/
-
public static String stripFileExtension(String filename)
{
int ix = filename.indexOf('.');
return filename.substring(0, ix);
}
-
- public static byte[] getByteArrayForResource(String resourcePath)
- {
- try (InputStream is = FileUtil.class.getResourceAsStream(resourcePath);
- ByteArrayOutputStream baos = new ByteArrayOutputStream())
- {
- byte[] b = new byte[4096];
- int n = 0;
- while ((n = is.read(b)) != -1)
- {
- baos.write(b, 0, n);
- }
-
- return baos.toByteArray();
- }
- catch (IOException ioe)
- {
- Debug.stackTrace(ioe, "Failed to read classpath resource: " + resourcePath);
- return null;
- }
- }
-
- /**
- * Delete a whole directory, recursively clearing out the files/subfolders too.
- */
- public static boolean deleteDirectoryIfExists(File dir)
- {
- if (!dir.exists()
- || !dir.isDirectory())
- {
- //Just don't do anything
- return true;
- }
-
- boolean success = true;
- File[] files = dir.listFiles();
- for (int i=0; i 0)
- {
- outStream.write(buffer, 0, count);
- }
- }
- catch (SocketException se)
- {
- Debug.append("Caught " + se + " for JAR download.");
- }
- catch (Throwable t)
- {
- Debug.stackTrace(t);
- }
- finally
- {
- server.incrementFunctionsHandled();
- server.incrementFunctionsHandledForMessage("DownloadRequest");
-
- if (socket != null)
- {
- try {socket.close();} catch (Throwable t) {}
- }
- }
- }
-}
diff --git a/server/src/main/java/server/DownloadListener.java b/server/src/main/java/server/DownloadListener.java
deleted file mode 100644
index 6c3919b..0000000
--- a/server/src/main/java/server/DownloadListener.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package server;
-
-import java.net.Socket;
-
-public class DownloadListener extends ListenerRunnable
-{
- String filename = "";
-
- public DownloadListener(EntropyServer server, int port, String filename)
- {
- super(server, port);
-
- this.filename = filename;
- }
-
- @Override
- public void handleInboundMessage(EntropyServer server, Socket clientSocket)
- {
- DownloadHandler.handleDownload(server, clientSocket, filename);
- }
-}
diff --git a/server/src/main/java/server/EntropyServer.java b/server/src/main/java/server/EntropyServer.java
index d7127ff..00f2682 100644
--- a/server/src/main/java/server/EntropyServer.java
+++ b/server/src/main/java/server/EntropyServer.java
@@ -103,7 +103,6 @@ public final class EntropyServer extends JFrame
//Other
private String lastCommand = "";
- private SuperHashMap hmClientJarToVersion = new SuperHashMap<>();
private PrivateKey privateKey = null;
@@ -179,7 +178,6 @@ public static void main(String args[])
//Initialise interfaces etc
EncryptionUtil.setBase64Interface(new Base64Desktop());
- Debug.setDebugExtension(new ServerDebugExtension());
Debug.initialise(console);
//Set other variables on Debug
@@ -223,7 +221,6 @@ private void onStart()
readInPrivateKey();
readUsedKeysFromFile();
- readClientVersion();
registerDefaultRooms();
Debug.append("Starting permanent threads");
@@ -367,14 +364,6 @@ private void startListenerThreads()
Debug.stackTrace(t, "Unable to start listener thread on port " + i);
}
}
-
- startDownloadListener(FILE_NAME_ENTROPY_JAR, SERVER_PORT_NUMBER_DOWNLOAD);
- }
- private void startDownloadListener(String filename, int port)
- {
- DownloadListener listener = new DownloadListener(this, port, filename);
- ServerThread downloadListener = new ServerThread(listener, "DownloadListener-" + port);
- downloadListener.start();
}
private void startFunctionThread()
@@ -857,10 +846,6 @@ public Room getRoomForName(String name)
{
return hmRoomByName.get(name);
}
- public String getClientVersion(String jar)
- {
- return hmClientJarToVersion.get(jar);
- }
public void toggleOnline()
{
online = !online;
@@ -1061,45 +1046,6 @@ private void readUsedKeysFromFile()
}
}
- private void readClientVersion()
- {
- try
- {
- Charset charset = Charset.forName("US-ASCII");
- List jarsAndVersions = Files.readAllLines(FILE_PATH_CLIENT_VERSION, charset);
-
- for (int i=0; i jarAndVersion = StringUtil.getListFromDelims(jarAndVersionStr, ";");
-
- String jar = jarAndVersion.get(0);
- String version = jarAndVersion.get(1);
-
- hmClientJarToVersion.put(jar, version);
- }
-
- logClientVersions();
- }
- catch (Throwable t)
- {
- Debug.append("Caught " + t + " trying to read in client version");
- }
- }
- private void logClientVersions()
- {
- Iterator> it = hmClientJarToVersion.entrySet().iterator();
- for (; it.hasNext(); )
- {
- Map.Entry jarAndVersion = it.next();
-
- String jar = jarAndVersion.getKey();
- String version = jarAndVersion.getValue();
-
- Debug.append(FileUtil.stripFileExtension(jar) + " Version: " + version);
- }
- }
-
public ConcurrentHashMap getBlacklist()
{
return blacklist;
@@ -1415,11 +1361,6 @@ else if (command.startsWith(COMMAND_NOTIFY_USER))
else if (command.equals(COMMAND_SERVER_VERSION))
{
Debug.append("Server version: " + OnlineConstants.SERVER_VERSION);
- logClientVersions();
- }
- else if (command.equals(COMMAND_SERVER_RESET_CLIENT_VERSION))
- {
- readClientVersion();
}
else
{
@@ -1480,7 +1421,6 @@ private void printCommands()
Debug.appendWithoutDate(COMMAND_NOTIFICATION_LOGGING);
Debug.appendWithoutDate(COMMAND_NOTIFY_USER + "");
Debug.appendWithoutDate(COMMAND_SERVER_VERSION);
- Debug.appendWithoutDate(COMMAND_SERVER_RESET_CLIENT_VERSION);
}
private void dumpMessageStats()
diff --git a/server/src/main/java/server/MessageHandlerRunnable.java b/server/src/main/java/server/MessageHandlerRunnable.java
index 76659a2..397f6db 100644
--- a/server/src/main/java/server/MessageHandlerRunnable.java
+++ b/server/src/main/java/server/MessageHandlerRunnable.java
@@ -101,8 +101,7 @@ public void run()
Debug.appendWithoutDate("Response: " + responseStr);
}
- if (symmetricKey != null
- && !DownloadHandler.isDownloadMessage(name))
+ if (symmetricKey != null)
{
responseStr = EncryptionUtil.encrypt(responseStr, symmetricKey);
}
@@ -225,15 +224,6 @@ private Document handleUnencryptedMessage(Document message)
Element root = message.getDocumentElement();
String name = root.getNodeName();
- if (DownloadHandler.isDownloadMessage(name))
- {
- return DownloadHandler.processMessage(message, server);
- }
-
- if (name.equals(ROOT_TAG_CLIENT_MAIL))
- {
- return EntropyEmailUtil.handleClientMail(server, root);
- }
if (!name.equals(ROOT_TAG_NEW_SYMMETRIC_KEY))
{
diff --git a/server/src/main/java/server/ServerCommands.java b/server/src/main/java/server/ServerCommands.java
index a427ddd..90601f6 100644
--- a/server/src/main/java/server/ServerCommands.java
+++ b/server/src/main/java/server/ServerCommands.java
@@ -34,5 +34,4 @@ public interface ServerCommands
public static final String COMMAND_NOTIFICATION_LOGGING = "notification logging";
public static final String COMMAND_NOTIFY_USER = "notify ";
public static final String COMMAND_SERVER_VERSION = "version";
- public static final String COMMAND_SERVER_RESET_CLIENT_VERSION = "reset version";
}
diff --git a/server/src/main/java/util/EntropyEmailUtil.java b/server/src/main/java/util/EntropyEmailUtil.java
index 33cf234..813cd38 100644
--- a/server/src/main/java/util/EntropyEmailUtil.java
+++ b/server/src/main/java/util/EntropyEmailUtil.java
@@ -1,38 +1,12 @@
package util;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.util.ArrayList;
-
-import javax.crypto.SecretKey;
import javax.mail.MessagingException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-import server.EntropyServer;
-
public class EntropyEmailUtil
{
- public static final String EMAIL_ADDRESS_ENTROPY = "entropyDebug@gmail.com";
-
- private static final String ENTROPY_USERNAME = "entropyDebug";
private static final String NO_REPLY_USERNAME = "entropynoreply";
- private static final String ENTROPY_PASSWORD = "****";
private static final String NO_REPLY_PASSWORD = "****";
-
- /**
- * Send an email via the usual EntropyDebug account
- */
- public static void sendEmail(String title, String message) throws MessagingException
- {
- sendEmail(title, message, null);
- }
- public static void sendEmail(String title, String message, ArrayList attachments) throws MessagingException
- {
- EmailUtil.sendEmail(title, message, EMAIL_ADDRESS_ENTROPY, ENTROPY_USERNAME, ENTROPY_PASSWORD, attachments);
- }
+
/**
* Send an email from EntropyNoReply, e.g. a password reset
@@ -41,99 +15,4 @@ public static void sendEmailNoReply(String title, String message, String targetE
{
EmailUtil.sendEmail(title, message, targetEmail, NO_REPLY_USERNAME, NO_REPLY_PASSWORD, null);
}
-
- /**
- * Handle a client mail message
- */
- public static Document handleClientMail(EntropyServer server, Element rootElement)
- {
- String encryptedSymetricKeyStr = rootElement.getAttribute("EncryptedKey");
- String symmetricKeyStr = EncryptionUtil.decrypt(encryptedSymetricKeyStr, server.getPrivateKey(), true);
- SecretKey symmetricKey = EncryptionUtil.reconstructKeyFromString(symmetricKeyStr);
-
- if (symmetricKey == null)
- {
- //Want to know about this. I've seen a client passing up a blank tag for EncryptedKey, and I don't
- //know how that's possible.
- Debug.stackTrace("Failed to reconstruct symmetricKey for EncryptedKey attribute");
- Debug.append("EncryptedKeyStr: " + encryptedSymetricKeyStr);
- Debug.append("SymmetricKeyStr: " + symmetricKeyStr);
- }
-
- String subject = EncryptionUtil.decryptIfPossible(rootElement.getAttribute("Subject"), symmetricKey);
- String body = EncryptionUtil.decryptIfPossible(rootElement.getAttribute("Body"), symmetricKey);
-
- ArrayList attachments = new ArrayList<>();
- NodeList attachmentElements = rootElement.getElementsByTagName("Attachment");
- for (int i=0; i