diff --git a/EOCV-Sim/build.gradle b/EOCV-Sim/build.gradle
index dfa77ef..b014a1e 100644
--- a/EOCV-Sim/build.gradle
+++ b/EOCV-Sim/build.gradle
@@ -75,9 +75,6 @@ dependencies {
implementation "org.apache.logging.log4j:log4j-slf4j2-impl:$log4j_version"
implementation "com.github.deltacv:steve:1.1.1"
- api("com.github.deltacv:AprilTagDesktop:$apriltag_plugin_version") {
- exclude group: 'com.github.deltacv.EOCVSim', module: 'Common'
- }
implementation 'info.picocli:picocli:4.6.1'
implementation 'com.google.code.gson:gson:2.8.9'
diff --git a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/gui/dialog/SuperAccessRequest.kt b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/gui/dialog/SuperAccessRequest.kt
index 6b8d807..58d98dc 100644
--- a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/gui/dialog/SuperAccessRequest.kt
+++ b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/gui/dialog/SuperAccessRequest.kt
@@ -1,165 +1,169 @@
-/*
- * Copyright (c) 2024 Sebastian Erives
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-package io.github.deltacv.eocvsim.gui.dialog
-
-import com.formdev.flatlaf.FlatLightLaf
-import com.formdev.flatlaf.intellijthemes.FlatArcDarkIJTheme
-import com.formdev.flatlaf.intellijthemes.FlatArcOrangeIJTheme
-import com.formdev.flatlaf.intellijthemes.FlatCobalt2IJTheme
-import com.github.serivesmejia.eocvsim.gui.EOCVSimIconLibrary
-import com.github.serivesmejia.eocvsim.gui.Icons
-import com.github.serivesmejia.eocvsim.gui.Icons.getImage
-import java.awt.BorderLayout
-import java.awt.Dimension
-import java.awt.Font
-import java.awt.event.WindowEvent
-import java.awt.event.WindowListener
-import javax.swing.*
-import kotlin.system.exitProcess
-
-class SuperAccessRequest(sourceName: String, reason: String) {
-
- init {
- FlatArcDarkIJTheme.setup()
-
- val panel = JPanel(BorderLayout())
- val frame = JDialog()
-
- frame.title = "EOCV-Sim SuperAccess Request"
-
- // Create UI components
- val titleLabel = JLabel("SuperAccess request from $sourceName", JLabel.CENTER)
-
- // Set the font of the JLabel to bold
- titleLabel.font = titleLabel.font.deriveFont(Font.BOLD, 21f)
-
- // Text Area for Reason Input
- val reasonTextArea = JTextPane().apply {
- isEditable = false
- contentType = "text/html"
-
- font = font.deriveFont(18f)
-
- var formattedReason = ""
-
- for(line in reason.split("
")) {
- formattedReason += wrapText(line, 80) + "
"
- }
-
- text = formattedReason
- }
- val scrollPane = JScrollPane(reasonTextArea)
-
- // Create a panel for buttons
- val buttonPanel = JPanel().apply {
- layout = BoxLayout(this, BoxLayout.X_AXIS)
- val acceptButton = JButton("Accept").apply {
- preferredSize = Dimension(100, 30)
- addActionListener {
- exitProcess(171)
- }
- }
-
- val rejectButton = JButton("Reject").apply {
- preferredSize = Dimension(100, 30)
- addActionListener {
- exitProcess(-172)
- }
- }
-
- add(Box.createHorizontalGlue()) // Push buttons to the center
- add(acceptButton)
- add(Box.createRigidArea(Dimension(10, 0))) // Space between buttons
- add(rejectButton)
- add(Box.createHorizontalGlue()) // Push buttons to the center
- }
-
- // Add components to the panel
- panel.add(titleLabel, BorderLayout.NORTH)
- panel.add(scrollPane, BorderLayout.CENTER)
- panel.add(buttonPanel, BorderLayout.SOUTH)
-
- // Setup the frame
- frame.contentPane = panel
- frame.isAlwaysOnTop = true
- frame.defaultCloseOperation = JDialog.HIDE_ON_CLOSE
- frame.isResizable = false
-
- frame.addWindowListener(object: WindowListener {
- override fun windowOpened(e: WindowEvent?) {}
- override fun windowClosing(e: WindowEvent?) {}
- override fun windowIconified(e: WindowEvent?) {}
- override fun windowDeiconified(e: WindowEvent?) {}
- override fun windowActivated(e: WindowEvent?) {}
- override fun windowDeactivated(e: WindowEvent?) {}
-
- override fun windowClosed(e: WindowEvent?) {
- exitProcess(-129)
- }
- })
-
- frame.setIconImage(EOCVSimIconLibrary.icoEOCVSim.image)
-
- frame.pack()
-
- frame.setLocationRelativeTo(null) // Center the window on the screen
- frame.isVisible = true
- }
-
-}
-
-private fun wrapText(text: String, maxLineLength: Int): String {
- val words = text.split(" ")
- val wrappedLines = mutableListOf()
- var currentLine = StringBuilder()
- val breakTag = "
" // HTML break tag
-
- for (word in words) {
- // Calculate the length of the line with a break tag
- val lineWithWord = if (currentLine.isEmpty()) {
- word
- } else {
- "$currentLine $word"
- }
- val lineLengthWithBreak = lineWithWord.length + (if (currentLine.isEmpty()) 0 else breakTag.length)
-
- // Check if adding the next word exceeds the maxLineLength
- if (lineLengthWithBreak > maxLineLength) {
- // If it does, add the current line to the list and start a new line
- wrappedLines.add(currentLine.toString())
- currentLine = StringBuilder(word)
- } else {
- // Append the word to the current line
- currentLine.append(" ").append(word)
- }
- }
-
- // Add the last line if it's not empty
- if (currentLine.isNotEmpty()) {
- wrappedLines.add(currentLine.toString())
- }
-
- // Join all lines with
for HTML
- return wrappedLines.joinToString(breakTag)
+/*
+ * Copyright (c) 2024 Sebastian Erives
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package io.github.deltacv.eocvsim.gui.dialog
+
+import com.formdev.flatlaf.FlatLightLaf
+import com.formdev.flatlaf.intellijthemes.FlatArcDarkIJTheme
+import com.formdev.flatlaf.intellijthemes.FlatArcOrangeIJTheme
+import com.formdev.flatlaf.intellijthemes.FlatCobalt2IJTheme
+import com.github.serivesmejia.eocvsim.gui.EOCVSimIconLibrary
+import com.github.serivesmejia.eocvsim.gui.Icons
+import com.github.serivesmejia.eocvsim.gui.Icons.getImage
+import java.awt.BorderLayout
+import java.awt.Dimension
+import java.awt.Font
+import java.awt.event.WindowEvent
+import java.awt.event.WindowListener
+import javax.swing.*
+
+class SuperAccessRequest(sourceName: String, reason: String, val callback: (Boolean) -> Unit) {
+
+ init {
+ FlatArcDarkIJTheme.setup()
+
+ val panel = JPanel(BorderLayout())
+ val frame = JDialog()
+
+ frame.title = "EOCV-Sim SuperAccess Request"
+
+ // Create UI components
+ val titleLabel = JLabel("SuperAccess request from $sourceName", JLabel.CENTER)
+
+ // Set the font of the JLabel to bold
+ titleLabel.font = titleLabel.font.deriveFont(Font.BOLD, 21f)
+
+ // Text Area for Reason Input
+ val reasonTextArea = JTextPane().apply {
+ isEditable = false
+ contentType = "text/html"
+
+ font = font.deriveFont(18f)
+
+ var formattedReason = ""
+
+ for(line in reason.split("
")) {
+ formattedReason += wrapText(line, 80) + "
"
+ }
+
+ text = formattedReason
+ }
+ val scrollPane = JScrollPane(reasonTextArea)
+
+ // Create a panel for buttons
+ val buttonPanel = JPanel().apply {
+ layout = BoxLayout(this, BoxLayout.X_AXIS)
+ val acceptButton = JButton("Accept").apply {
+ preferredSize = Dimension(100, 30)
+ addActionListener {
+ callback(true)
+
+ frame.isVisible = false
+ frame.dispose()
+ }
+ }
+
+ val rejectButton = JButton("Reject").apply {
+ preferredSize = Dimension(100, 30)
+ addActionListener {
+ callback(false)
+
+ frame.isVisible = false
+ frame.dispose()
+ }
+ }
+
+ add(Box.createHorizontalGlue()) // Push buttons to the center
+ add(acceptButton)
+ add(Box.createRigidArea(Dimension(10, 0))) // Space between buttons
+ add(rejectButton)
+ add(Box.createHorizontalGlue()) // Push buttons to the center
+ }
+
+ // Add components to the panel
+ panel.add(titleLabel, BorderLayout.NORTH)
+ panel.add(scrollPane, BorderLayout.CENTER)
+ panel.add(buttonPanel, BorderLayout.SOUTH)
+
+ // Setup the frame
+ frame.contentPane = panel
+ frame.isAlwaysOnTop = true
+ frame.defaultCloseOperation = JDialog.HIDE_ON_CLOSE
+ frame.isResizable = false
+
+ frame.addWindowListener(object: WindowListener {
+ override fun windowOpened(e: WindowEvent?) {}
+ override fun windowClosing(e: WindowEvent?) {}
+ override fun windowIconified(e: WindowEvent?) {}
+ override fun windowDeiconified(e: WindowEvent?) {}
+ override fun windowActivated(e: WindowEvent?) {}
+ override fun windowDeactivated(e: WindowEvent?) {}
+
+ override fun windowClosed(e: WindowEvent?) {
+ }
+ })
+
+ frame.setIconImage(EOCVSimIconLibrary.icoEOCVSim.image)
+
+ frame.pack()
+
+ frame.setLocationRelativeTo(null) // Center the window on the screen
+ frame.isVisible = true
+ }
+
+}
+
+private fun wrapText(text: String, maxLineLength: Int): String {
+ val words = text.split(" ")
+ val wrappedLines = mutableListOf()
+ var currentLine = StringBuilder()
+ val breakTag = "
" // HTML break tag
+
+ for (word in words) {
+ // Calculate the length of the line with a break tag
+ val lineWithWord = if (currentLine.isEmpty()) {
+ word
+ } else {
+ "$currentLine $word"
+ }
+ val lineLengthWithBreak = lineWithWord.length + (if (currentLine.isEmpty()) 0 else breakTag.length)
+
+ // Check if adding the next word exceeds the maxLineLength
+ if (lineLengthWithBreak > maxLineLength) {
+ // If it does, add the current line to the list and start a new line
+ wrappedLines.add(currentLine.toString())
+ currentLine = StringBuilder(word)
+ } else {
+ // Append the word to the current line
+ currentLine.append(" ").append(word)
+ }
+ }
+
+ // Add the last line if it's not empty
+ if (currentLine.isNotEmpty()) {
+ wrappedLines.add(currentLine.toString())
+ }
+
+ // Join all lines with
for HTML
+ return wrappedLines.joinToString(breakTag)
}
\ No newline at end of file
diff --git a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/gui/dialog/SuperAccessRequestMain.java b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/gui/dialog/SuperAccessRequestMain.java
deleted file mode 100644
index 27d76e4..0000000
--- a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/gui/dialog/SuperAccessRequestMain.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2024 Sebastian Erives
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-package io.github.deltacv.eocvsim.gui.dialog;
-
-import javax.swing.*;
-
-public class SuperAccessRequestMain {
- public static void main(String[] args) {
- SwingUtilities.invokeLater(() -> new SuperAccessRequest(args[0].replace("-", " "), args[1].replace("-", " ")));
- }
-}
diff --git a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSignatureVerifier.kt b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSignatureVerifier.kt
index c1e84a5..4b2960c 100644
--- a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSignatureVerifier.kt
+++ b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSignatureVerifier.kt
@@ -26,6 +26,7 @@ package io.github.deltacv.eocvsim.plugin.security
import com.github.serivesmejia.eocvsim.util.extension.hashString
import com.github.serivesmejia.eocvsim.util.loggerForThis
import com.moandjiezana.toml.Toml
+import io.github.deltacv.eocvsim.plugin.loader.InvalidPluginException
import java.io.File
import java.security.PublicKey
import java.security.Signature
@@ -124,8 +125,8 @@ object PluginSignatureVerifier {
val signatureStatus = mutableMapOf()
- for(signature in signatures) {
- signatureStatus[signature.key] = false
+ for(sign in signatures) {
+ signatureStatus[sign.key] = false
}
for (classEntry in classEntries) {
@@ -139,8 +140,7 @@ object PluginSignatureVerifier {
// Verify the signature of the class
if (!verifySignature(classData, signatures[classHash]!!, publicKey)) {
- logger.warn("Signature verification failed for class $className")
- return emptyResult
+ throw InvalidPluginException("Signature verification failed for class $className. Please try to re-download the plugin or discard it immediately.")
} else {
signatureStatus[classHash] = true
}
diff --git a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSigningTool.kt b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSigningTool.kt
index ce8cbb7..b6a4ee7 100644
--- a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSigningTool.kt
+++ b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/PluginSigningTool.kt
@@ -198,19 +198,22 @@ class PluginSigningTool : Runnable {
}
}
-// Use System.in
-fun main() {
- val scanner = Scanner(System.`in`)
+fun main(args: Array) {
+ if(args.isEmpty()) {
+ val scanner = Scanner(System.`in`)
- val tool = PluginSigningTool()
- println("Enter the plugin JAR file path:")
- tool.pluginFile = scanner.next()
+ val tool = PluginSigningTool()
+ println("Enter the plugin JAR file path:")
+ tool.pluginFile = scanner.next()
- println("Enter the authority to sign the plugin with:")
- tool.authority = scanner.next()
+ println("Enter the authority to sign the plugin with:")
+ tool.authority = scanner.next()
- println("Enter the private key file path:")
- tool.privateKeyFile = scanner.next()
+ println("Enter the private key file path:")
+ tool.privateKeyFile = scanner.next()
- tool.run()
+ tool.run()
+ } else {
+ CommandLine(PluginSigningTool()).execute(*args)
+ }
}
\ No newline at end of file
diff --git a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemon.kt b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemon.kt
index 3b7441c..4a23d9c 100644
--- a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemon.kt
+++ b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemon.kt
@@ -24,25 +24,30 @@
package io.github.deltacv.eocvsim.plugin.security.superaccess
import com.github.serivesmejia.eocvsim.util.JavaProcess
+import com.github.serivesmejia.eocvsim.util.SysUtil
import com.github.serivesmejia.eocvsim.util.io.EOCVSimFolder
import com.github.serivesmejia.eocvsim.util.loggerForThis
import com.github.serivesmejia.eocvsim.util.extension.plus
import com.github.serivesmejia.eocvsim.util.serialization.PolymorphicAdapter
import com.google.gson.GsonBuilder
import com.moandjiezana.toml.Toml
-import io.github.deltacv.eocvsim.gui.dialog.SuperAccessRequestMain
+import io.github.deltacv.eocvsim.gui.dialog.SuperAccessRequest
+import javax.swing.SwingUtilities
import io.github.deltacv.eocvsim.plugin.loader.PluginManager.Companion.GENERIC_LAWYER_YEET
import io.github.deltacv.eocvsim.plugin.loader.PluginManager.Companion.GENERIC_SUPERACCESS_WARN
import io.github.deltacv.eocvsim.plugin.loader.PluginParser
import io.github.deltacv.eocvsim.plugin.security.Authority
import io.github.deltacv.eocvsim.plugin.security.AuthorityFetcher
import io.github.deltacv.eocvsim.plugin.security.MutablePluginSignature
+import kotlinx.coroutines.newFixedThreadPoolContext
import org.java_websocket.client.WebSocketClient
import java.net.URI
import org.java_websocket.handshake.ServerHandshake
import java.util.zip.ZipFile
import java.io.File
import java.lang.Exception
+import java.security.MessageDigest
+import java.util.concurrent.Executors
import kotlin.system.exitProcess
object SuperAccessDaemon {
@@ -88,6 +93,8 @@ object SuperAccessDaemon {
class WsClient(port: Int) : WebSocketClient(URI("ws://localhost:$port")) {
+ private val executor = Executors.newFixedThreadPool(6)
+
override fun onOpen(p0: ServerHandshake?) {
logger.info("SuperAccessDaemon connection opened")
}
@@ -95,21 +102,37 @@ object SuperAccessDaemon {
override fun onMessage(msg: String) {
val message = gson.fromJson(msg, SuperAccessMessage::class.java)
- when(message) {
- is SuperAccessMessage.Request -> {
- handleRequest(message)
- }
+ executor.submit {
+ when (message) {
+ is SuperAccessMessage.Request -> {
+ handleRequest(message)
+ }
- is SuperAccessMessage.Check -> {
- handleCheck(message)
+ is SuperAccessMessage.Check -> {
+ handleCheck(message)
+ }
}
}
}
private fun handleRequest(message: SuperAccessMessage.Request) {
+ val pluginFile = File(message.pluginPath)
+
+ val parser = parsePlugin(pluginFile) ?: run {
+ logger.error("Failed to parse plugin at ${message.pluginPath}")
+ (gson.toJson(SuperAccessResponse.Failure(message.id)))
+ return@handleRequest
+ }
+
+ if(SUPERACCESS_FILE.exists() && SUPERACCESS_FILE.readLines().contains(pluginFile.fileHash())) {
+ accessGranted(message.id, message.pluginPath)
+ return
+ }
+
logger.info("Requesting SuperAccess for ${message.pluginPath}")
var validAuthority: Authority? = null
+ var untrusted = false
if(message.signature.authority != null) {
val declaredAuthority = message.signature.authority!!
@@ -125,19 +148,17 @@ object SuperAccessDaemon {
validAuthority = Authority(authorityName, fetchedAuthorityKey)
} else {
logger.warn("Authority key does not match the fetched key for $authorityName")
+ untrusted = true
}
}
- }
-
- val parser = parsePlugin(File(message.pluginPath)) ?: run {
- logger.error("Failed to parse plugin at ${message.pluginPath}")
- (gson.toJson(SuperAccessResponse.Failure(message.id)))
- return@handleRequest
+ } else {
+ val fetch = AuthorityFetcher.fetchAuthority(parser.pluginAuthor)
+ untrusted = fetch != null // the plugin is claiming to be made by the authority but it's not signed by them
}
val reason = message.reason
- val name = "${parser.pluginName} v${parser.pluginVersion} by ${parser.pluginAuthor}".replace(" ", "-")
+ val name = "${parser.pluginName} v${parser.pluginVersion} by ${parser.pluginAuthor}"
var warning = "$GENERIC_SUPERACCESS_WARN"
if(reason.trim().isNotBlank()) {
@@ -145,22 +166,24 @@ object SuperAccessDaemon {
}
warning += if(validAuthority != null) {
- "
This plugin is signed by the trusted authority ${validAuthority.name}."
+ "
This plugin has been digitally signed by ${validAuthority.name}, ensuring its integrity and authenticity.
${validAuthority.name} is a trusted authority in the EOCV-Sim ecosystem."
+ } else if(untrusted) {
+ "
This plugin claims to be made by trusted authority ${parser.pluginAuthor}, but it has not been digitally signed by them.
Beware of potential security risks.
"
} else {
GENERIC_LAWYER_YEET
}
warning += ""
- if(JavaProcess.exec(SuperAccessRequestMain::class.java, null, listOf(name, warning)) == 171) {
- logger.info("SuperAccess granted to ${message.pluginPath}")
- send(gson.toJson(SuperAccessResponse.Success(message.id)))
-
- SUPERACCESS_FILE.appendText("${parser.hash()}\n")
- access[message.pluginPath] = true
- } else {
- logger.info("SuperAccess denied to ${message.pluginPath}")
- send(gson.toJson(SuperAccessResponse.Failure(message.id)))
+ SwingUtilities.invokeLater {
+ SuperAccessRequest(name, warning) { granted ->
+ if(granted) {
+ SUPERACCESS_FILE.appendText(pluginFile.fileHash() + "\n")
+ accessGranted(message.id, message.pluginPath)
+ } else {
+ accessDenied(message.id, message.pluginPath)
+ }
+ }
}
}
@@ -175,19 +198,27 @@ object SuperAccessDaemon {
}
}
- val parser = parsePlugin(File(message.pluginPath)) ?: run {
+ val pluginFile = File(message.pluginPath)
+
+ val parser = parsePlugin(pluginFile) ?: run {
logger.error("Failed to parse plugin at ${message.pluginPath}")
send(gson.toJson(SuperAccessResponse.Failure(message.id)))
return
}
- if(SUPERACCESS_FILE.readLines().contains(parser.hash())) {
+ if(SUPERACCESS_FILE.exists() && SUPERACCESS_FILE.readLines().contains(pluginFile.fileHash())) {
accessGranted(message.id, message.pluginPath)
} else {
accessDenied(message.id, message.pluginPath)
}
}
+ private fun File.fileHash(): String {
+ val messageDigest = MessageDigest.getInstance("SHA-256")
+ messageDigest.update(readBytes())
+ return SysUtil.byteArray2Hex(messageDigest.digest())
+ }
+
private fun accessGranted(id: Int, pluginPath: String) {
access[pluginPath] = true
send(gson.toJson(SuperAccessResponse.Success(id)))
diff --git a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemonClient.kt b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemonClient.kt
index 538d282..dac20ea 100644
--- a/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemonClient.kt
+++ b/EOCV-Sim/src/main/java/io/github/deltacv/eocvsim/plugin/security/superaccess/SuperAccessDaemonClient.kt
@@ -24,20 +24,16 @@
package io.github.deltacv.eocvsim.plugin.security.superaccess
import com.github.serivesmejia.eocvsim.util.JavaProcess
-import com.github.serivesmejia.eocvsim.util.event.EventHandler
-import com.github.serivesmejia.eocvsim.util.event.EventListenerRemover
import com.github.serivesmejia.eocvsim.util.loggerForThis
-import org.firstinspires.ftc.robotcore.internal.collections.EvictingBlockingQueue
-import java.util.concurrent.ArrayBlockingQueue
import org.java_websocket.WebSocket
import org.java_websocket.handshake.ClientHandshake
import org.java_websocket.server.WebSocketServer
-import java.lang.Exception
import java.io.File
+import java.lang.Exception
import java.net.InetSocketAddress
import java.util.concurrent.Executors
-import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.Condition
+import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
typealias ResponseReceiver = (SuperAccessDaemon.SuperAccessResponse) -> Unit
diff --git a/Vision/build.gradle b/Vision/build.gradle
index d62ff8c..ad38e4b 100644
--- a/Vision/build.gradle
+++ b/Vision/build.gradle
@@ -28,7 +28,7 @@ configurations.all {
dependencies {
implementation project(':Common')
- implementation("com.github.deltacv:AprilTagDesktop:$apriltag_plugin_version") {
+ api("com.github.deltacv:AprilTagDesktop:$apriltag_plugin_version") {
exclude group: 'com.github.deltacv.EOCVSim', module: 'Common'
}