diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..38156aa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+keys
\ No newline at end of file
diff --git a/README.md b/README.md
index 75caea7..be074f7 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,30 @@
# Remote-Linux-Unlocker
-Remote Linux Unlocker is an android application paired with a linux daemon that allows users to unlock and lock the Ubuntu Unity lock screen.
-### How to install the android application
-Install the android application from the [Google Play Store](https://play.google.com/store/apps/details?id=com.maxchehab.remotelinuxunlocker) or download the source from this repository.
+Remote Linux Unlocker is an android application paired with a linux daemon that allows users to unlock and lock the Ubuntu Unity lock screen.
-### How to install the linux daemon
+## How to install the android application
-```sh
-$ wget https://github.com/maxchehab/remote-linux-unlocker/raw/master/linux-daemon/linux-daemon.zip
+Install the android application from the zip file (download command below) or download the source from this repository.
-$ unzip linux-daemon.zip
+> [!NOTE]
+> Until this PR is merged, replace the wget command below with
+> ```diff
+> - wget https://github.com/maxchehab/remote-linux-unlocker/raw/master/linux-daemon/linux-daemon.zip
+> + wget https://github.com/DitherDude/remote-linux-unlocker/raw/master/linux-daemon/linux-daemon.zip
+> ```
-$ cd linux-daemon
+## How to install the linux daemon
+```console
+user@machine:~/Downloads$ wget https://github.com/maxchehab/remote-linux-unlocker/raw/master/linux-daemon/linux-daemon.zip
+user@machine:~/Downloads$ unzip linux-daemon.zip
+user@machine:~/Downloads$ cd linux-daemon
#edit `unlocker-daemon.service` so that the absolute path to unlocker-daemon.py is correct
+#run the below commands as sudo!
+root@machine:.../linux-daemon# cp unlocker-daemon.service /etc/systemd/system/unlocker-daemon.service
+root@machine:~# systemctl daemon-reload
+root@machine:~# systemctl enable unlocker-daemon
+root@machine:~# systemctl start unlocker-daemon
-$ mv unlocker-daemon.service /etc/systemd/system/unlocker-daemon
-
-$ sudo systemctl daemon-reload
-
-$ sudo systemctl enable unlocker-daemon
-
-$ sudo systemctl start unlocker-daemon
-
-$ ./remote-linux-pair
+user@machine:.../linux-daemon$ ./remote-linux-pair
```
-
diff --git a/android-application/RemoteLinuxUnlocker/.idea/.gitignore b/android-application/RemoteLinuxUnlocker/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/android-application/RemoteLinuxUnlocker/.idea/AndroidProjectSystem.xml b/android-application/RemoteLinuxUnlocker/.idea/AndroidProjectSystem.xml
new file mode 100644
index 0000000..4a53bee
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/AndroidProjectSystem.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/caches/deviceStreaming.xml b/android-application/RemoteLinuxUnlocker/.idea/caches/deviceStreaming.xml
new file mode 100644
index 0000000..97cf2b8
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/caches/deviceStreaming.xml
@@ -0,0 +1,1138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/compiler.xml b/android-application/RemoteLinuxUnlocker/.idea/compiler.xml
index 96cc43e..b86273d 100644
--- a/android-application/RemoteLinuxUnlocker/.idea/compiler.xml
+++ b/android-application/RemoteLinuxUnlocker/.idea/compiler.xml
@@ -1,22 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/deploymentTargetSelector.xml b/android-application/RemoteLinuxUnlocker/.idea/deploymentTargetSelector.xml
new file mode 100644
index 0000000..461095e
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/deviceManager.xml b/android-application/RemoteLinuxUnlocker/.idea/deviceManager.xml
new file mode 100644
index 0000000..91f9558
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/deviceManager.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/dictionaries/project.xml b/android-application/RemoteLinuxUnlocker/.idea/dictionaries/project.xml
new file mode 100644
index 0000000..4b8f2fb
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/dictionaries/project.xml
@@ -0,0 +1,8 @@
+
+
+
+ maxchehab
+ remotelinuxunlocker
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/gradle.xml b/android-application/RemoteLinuxUnlocker/.idea/gradle.xml
index 7ac24c7..88e9c3c 100644
--- a/android-application/RemoteLinuxUnlocker/.idea/gradle.xml
+++ b/android-application/RemoteLinuxUnlocker/.idea/gradle.xml
@@ -1,17 +1,18 @@
+
-
+
+
-
-
+
+
-
diff --git a/android-application/RemoteLinuxUnlocker/.idea/inspectionProfiles/Project_Default.xml b/android-application/RemoteLinuxUnlocker/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..da6ad68
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/migrations.xml b/android-application/RemoteLinuxUnlocker/.idea/migrations.xml
new file mode 100644
index 0000000..f8051a6
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/misc.xml b/android-application/RemoteLinuxUnlocker/.idea/misc.xml
index f1c4621..da3439f 100644
--- a/android-application/RemoteLinuxUnlocker/.idea/misc.xml
+++ b/android-application/RemoteLinuxUnlocker/.idea/misc.xml
@@ -1,8 +1,8 @@
-
+
@@ -27,17 +27,7 @@
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/android-application/RemoteLinuxUnlocker/.idea/modules.xml b/android-application/RemoteLinuxUnlocker/.idea/modules.xml
deleted file mode 100644
index 0d01919..0000000
--- a/android-application/RemoteLinuxUnlocker/.idea/modules.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/.idea/runConfigurations.xml b/android-application/RemoteLinuxUnlocker/.idea/runConfigurations.xml
index 7f68460..72f00ed 100644
--- a/android-application/RemoteLinuxUnlocker/.idea/runConfigurations.xml
+++ b/android-application/RemoteLinuxUnlocker/.idea/runConfigurations.xml
@@ -3,6 +3,14 @@
+
+
+
+
+
+
+
+
diff --git a/android-application/RemoteLinuxUnlocker/app/app-release.apk b/android-application/RemoteLinuxUnlocker/app/app-release_old.apk
similarity index 100%
rename from android-application/RemoteLinuxUnlocker/app/app-release.apk
rename to android-application/RemoteLinuxUnlocker/app/app-release_old.apk
diff --git a/android-application/RemoteLinuxUnlocker/app/build.gradle b/android-application/RemoteLinuxUnlocker/app/build.gradle
index a2b793e..2832fff 100644
--- a/android-application/RemoteLinuxUnlocker/app/build.gradle
+++ b/android-application/RemoteLinuxUnlocker/app/build.gradle
@@ -1,35 +1,40 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.3"
+ compileSdkVersion 36
+ // buildToolsVersion "25.0.3"
defaultConfig {
applicationId "com.maxchehab.remotelinuxunlocker"
- minSdkVersion 15
- targetSdkVersion 25
+ minSdkVersion 26
+ targetSdkVersion 36
vectorDrawables.useSupportLibrary = true
versionCode 1
- versionName "1.0"
+ versionName "2.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_21
+ targetCompatibility JavaVersion.VERSION_21
+ }
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ namespace = "com.maxchehab.remotelinuxunlocker"
}
dependencies {
- compile fileTree(include: ['*.jar'], dir: 'libs')
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
- compile 'com.android.support:appcompat-v7:25.3.1'
- compile 'com.google.code.gson:gson:2.8.1'
- compile 'com.android.support.constraint:constraint-layout:1.0.2'
- compile 'com.android.support:cardview-v7:25.3.1'
- compile 'com.android.support:design:25.3.1'
- compile 'de.hdodenhof:circleimageview:2.1.0'
- testCompile 'junit:junit:4.12'
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.google.code.gson:gson:2.13.2'
+ implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ implementation 'com.android.support:cardview-v7:28.0.0'
+ implementation 'com.android.support:design:28.0.0'
+ implementation 'de.hdodenhof:circleimageview:3.1.0'
+ testImplementation 'junit:junit:4.13.2'
}
diff --git a/android-application/RemoteLinuxUnlocker/app/release/app-release.apk b/android-application/RemoteLinuxUnlocker/app/release/app-release.apk
new file mode 100644
index 0000000..cab2c28
Binary files /dev/null and b/android-application/RemoteLinuxUnlocker/app/release/app-release.apk differ
diff --git a/android-application/RemoteLinuxUnlocker/app/release/output-metadata.json b/android-application/RemoteLinuxUnlocker/app/release/output-metadata.json
new file mode 100644
index 0000000..37bc402
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/release/output-metadata.json
@@ -0,0 +1,21 @@
+{
+ "version": 3,
+ "artifactType": {
+ "type": "APK",
+ "kind": "Directory"
+ },
+ "applicationId": "com.maxchehab.remotelinuxunlocker",
+ "variantName": "release",
+ "elements": [
+ {
+ "type": "SINGLE",
+ "filters": [],
+ "attributes": [],
+ "versionCode": 1,
+ "versionName": "2.0",
+ "outputFile": "app-release.apk"
+ }
+ ],
+ "elementType": "File",
+ "minSdkVersionForDexing": 26
+}
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/AndroidManifest.xml b/android-application/RemoteLinuxUnlocker/app/src/main/AndroidManifest.xml
index a27b742..992dae2 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/AndroidManifest.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/AndroidManifest.xml
@@ -1,10 +1,10 @@
-
-
+
-
+
+ android:label="Remote Linux Unlocker"
+ android:exported="true">
-
+
-
+
@@ -31,13 +32,23 @@
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/Client.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/Client.java
index bb11c87..ac3e965 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/Client.java
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/Client.java
@@ -1,24 +1,21 @@
package com.maxchehab.remotelinuxunlocker;
-import android.os.AsyncTask;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
-import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
-import java.net.UnknownHostException;
+import java.util.concurrent.Callable;
-public class Client extends AsyncTask {
-
- String host;
- int port;
- String message;
+public class Client implements Callable {
+ final String host;
+ final int port;
+ final String message;
Client(String host, int port,String message) {
this.host = host;
@@ -27,7 +24,7 @@ public class Client extends AsyncTask {
}
@Override
- protected String doInBackground(Void... arg0) {
+ public String call() {
Socket socket = null;
try {
InetAddress address = InetAddress.getByName(host);
@@ -44,7 +41,7 @@ protected String doInBackground(Void... arg0) {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String response = in.readLine();
- Log.d("async-client","recieved message: " + response);
+ Log.d("async-client","received message: " + response);
return response;
} catch (IOException exception) {
Log.d("async-client", "the server is offline?");
@@ -54,16 +51,11 @@ protected String doInBackground(Void... arg0) {
try {
socket.close();
} catch (IOException e) {
+ //noinspection CallToPrintStackTrace
e.printStackTrace();
}
}
}
return null;
}
-
- @Override
- protected void onPostExecute(String result) {
- super.onPostExecute(result);
- }
-
}
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ClientBuilder.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ClientBuilder.java
new file mode 100644
index 0000000..207369f
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ClientBuilder.java
@@ -0,0 +1,27 @@
+package com.maxchehab.remotelinuxunlocker;
+
+public class ClientBuilder {
+
+ private String host;
+ private int port;
+ private String message;
+
+ public ClientBuilder setHost(String host) {
+ this.host = host;
+ return this;
+ }
+
+ public ClientBuilder setPort(int port) {
+ this.port = port;
+ return this;
+ }
+
+ public ClientBuilder setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+ public Client createClient() {
+ return new Client(host, port, message);
+ }
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerLayout.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerLayout.java
index bc2a49a..8ef63fb 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerLayout.java
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerLayout.java
@@ -1,19 +1,24 @@
package com.maxchehab.remotelinuxunlocker;
import android.content.Context;
+import android.content.res.ColorStateList;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.util.Log;
-import android.view.View;
import android.widget.Button;
import android.widget.TextView;
-import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Created by Max on 5/10/2017.
@@ -21,14 +26,19 @@
public class ComputerLayout extends CardView{
- public ComputerLayout(Context context, String ip, String key) {
+
+ public ComputerLayout(Context context) {
+ super(context);
+ }
+
+ public ComputerLayout(Context context, KeyPair key) {
super(context);
- init(ip,key,null);
+ init(context, key,null);
}
- public ComputerLayout(Context context, String ip, String key, String command) {
+ public ComputerLayout(Context context, KeyPair key, String command) {
super(context);
- init(ip,key, command);
+ init(context, key, command);
}
private TextView hostname;
@@ -36,82 +46,101 @@ public ComputerLayout(Context context, String ip, String key, String command) {
private boolean locked = false;
- private void init(final String ip, final String key, String command) {
-
+ private void init(Context context, KeyPair key, String command) {
inflate(getContext(), R.layout.computer_layout, this);
- hostname = (TextView) findViewById(R.id.hostname);
- lockButton = (Button) findViewById(R.id.lockButton);
-
- status(ip, key);
-
- lockButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- lockButton.setEnabled(false);
- lockButton.setClickable(false);
- if(locked){
- lock(ip,key,"unlock");
- }else{
- lock(ip, key,"lock");
- }
+ hostname = findViewById(R.id.hostname);
+ hostname.setText(String.format("%s@%s", key.user, key.ip));
+ lockButton = findViewById(R.id.lockButton);
+ ExecutorService executor2 = Executors.newSingleThreadExecutor();
+ Handler handler = new Handler(Looper.getMainLooper());
+ AtomicBoolean failed = new AtomicBoolean(false);
+ executor2.execute(() -> {
+ StatusResult result = status(key);
+ if (result != null) {
+ handler.post(() -> applyResult(context, result, key));
+ } else {
+ failed.set(true);
+ }
+ });
+ if (failed.get()) {
+ command = null;
+ }
+
+ lockButton.setOnClickListener(view -> {
+ lockButton.setEnabled(false);
+ lockButton.setClickable(false);
+ int color = ContextCompat.getColor(context, R.color.warningColorAccent);
+ lockButton.setBackgroundTintList(ColorStateList.valueOf(color));
+ lockButton.setText(R.string.loading_placeholder);
+ invalidate();
+ if(locked){
+ lock(context, key,"unlock");
+ }else{
+ lock(context, key,"lock");
}
});
if(command != null){
- lock(ip,key,command);
+ lock(context, key, command);
}
}
-
- private void lock(String ip, String key, String action){
+ private static final ExecutorService executor = Executors.newSingleThreadExecutor();
+ /** @noinspection CallToPrintStackTrace*/
+ private void lock(Context context, KeyPair key, String action){
try {
- new Client(ip,61599,"{\"command\":\"" + action + "\",\"key\":\"" + key + "\"}").execute().get(2, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- } catch (TimeoutException e) {
+ executor.submit(new ClientBuilder().setHost(key.ip).setPort(61599).setMessage("{\"command\":\"" + action + "\",\"key\":\"" + key.key + "\"}").createClient()).get(2, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
- boolean tempLocked = locked;
- while(tempLocked == locked){
- status(ip,key);
+ ExecutorService executor2 = Executors.newSingleThreadExecutor();
+ Handler handler = new Handler(Looper.getMainLooper());
+ executor2.execute(() -> {
+ boolean tempLocked = locked;
+ while(tempLocked == locked){
+ StatusResult result = status(key);
+ if (result != null && result.locked != locked) {
+ handler.post(() -> applyResult(context, result, key));
+ }
+ }
+ });
+ }
+
+ private record StatusResult(String hostname, boolean locked){}
+
+ private void applyResult(Context context, StatusResult result, KeyPair key) {
+ locked = result.locked;
+ hostname.setText(String.format("%s@%s", key.user, result.hostname));
+ if(locked){
+ int color = ContextCompat.getColor(context, R.color.dangerColorAccent);
+ lockButton.setBackgroundTintList(ColorStateList.valueOf(color));
+ lockButton.setText(R.string.unlock);
+ } else {
+ int color = ContextCompat.getColor(context, R.color.successColorAccent);
+ lockButton.setBackgroundTintList(ColorStateList.valueOf(color));
+ lockButton.setText(R.string.lock);
}
lockButton.setClickable(true);
lockButton.setEnabled(true);
}
- private void status(String ip, String key){
+ /** @noinspection CallToPrintStackTrace*/
+ private StatusResult status(KeyPair key){
String echoResponse = null;
try {
- echoResponse = new Client(ip,61599,"{\"command\":\"status\",\"key\":\"" + key + "\"}").execute().get(2, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- } catch (TimeoutException e) {
+ echoResponse = executor.submit(new ClientBuilder().setHost(key.ip).setPort(61599).setMessage("{\"command\":\"status\",\"key\":\"" + key.key + "\"}").createClient()).get(2, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
Log.d("status-response","Response: " + echoResponse);
- if(echoResponse == null){
- this.setVisibility(View.GONE);
- }else{
- this.setVisibility(View.VISIBLE);
- JsonParser jp = new JsonParser();
- JsonElement root = jp.parse(echoResponse);
- JsonObject rootobj = root.getAsJsonObject();
- Log.d("hostname",rootobj.get("hostname").getAsString());
- hostname.setText(rootobj.get("hostname").getAsString());
- locked = rootobj.get("isLocked").getAsBoolean();
-
- if(locked){
- lockButton.setText("Unlock");
- }else{
- lockButton.setText("Lock");
- }
+ if(echoResponse != null) {
+ JsonObject rootObj = JsonParser.parseString(echoResponse).getAsJsonObject();
+ Log.d("hostname",rootObj.get("hostname").getAsString());
+ return new StatusResult(rootObj.get("hostname").getAsString(), rootObj.get("isLocked").getAsBoolean());
}
+ return null;
}
}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerListActivity.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerListActivity.java
index 0588e09..e0283b7 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerListActivity.java
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ComputerListActivity.java
@@ -1,71 +1,65 @@
package com.maxchehab.remotelinuxunlocker;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.graphics.Color;
import android.os.Bundle;
-import android.support.design.widget.FloatingActionButton;
-import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
+import android.widget.Button;
import android.widget.LinearLayout;
+import android.widget.TextView;
-import java.math.BigInteger;
-import java.security.SecureRandom;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
import java.util.Random;
public class ComputerListActivity extends AppCompatActivity {
- private static Random rnd = new Random();
+ private static final Random rnd = new Random();
private SwipeRefreshLayout swipeContainer;
boolean commanded = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_computer_list);
-
-
- SharedPreferences sharedPref = getSharedPreferences("data", MODE_PRIVATE);
- if(!sharedPref.contains("key")){
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putString("key", new BigInteger(getRandomNumber(64)).toString());
- editor.commit();
- }
- if(!sharedPref.contains("ips")){
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putString("ips", "");
- editor.commit();
+ Settings settings = new Settings(this);
+// if (settings.unlockHook) {
+ {
+ Intent intent = new Intent(this, PersistenceService.class);
+ intent.putExtra("create", settings.unlockHook);
+ startForegroundService(intent);
}
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_computer_list);
+ Button buttonPair = findViewById(R.id.buttonPair);
+ buttonPair.setOnClickListener(view -> {
+ Intent intent = new Intent(this, PairingActivity.class);
+ startActivity(intent);
+ });
+ Button buttonSettings = findViewById(R.id.buttonSettings);
+ buttonSettings.setOnClickListener(view -> {
+ Intent intent = new Intent(this, SettingsActivity.class);
+ startActivity(intent);
+ });
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(view.getContext(), PairingActivity.class);
- startActivity(intent);
+ Button buttonManage = findViewById(R.id.buttonCommit);
+ buttonManage.setOnClickListener(view -> {
+ if (buttonManage.getText().toString().equals("Back")) {
+ buttonManage.setText(R.string.manage_devices);
+ refreshComputerList();
+ } else {
+ buttonManage.setText(R.string.back);
+ deleteComputerList();
}
});
- swipeContainer = (SwipeRefreshLayout) findViewById(R.id.refresh);
+ swipeContainer = findViewById(R.id.refresh);
// Setup refresh listener which triggers new data loading
- swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
- @Override
- public void onRefresh() {
- refreshComputerList();
- }
- });
+ swipeContainer.setOnRefreshListener(this::refreshComputerList);
// Configure the refreshing colors
- swipeContainer.setColorSchemeResources(R.color.colorAccent);
+ swipeContainer.setColorSchemeResources(R.color.defaultColorAccent);
refreshComputerList();
}
@@ -73,7 +67,7 @@ public void onRefresh() {
@Override
protected void onResume() {
if (getIntent().getAction() != null) {
- Log.e("INTENT-ACTION:",getIntent().getAction().toString());
+ Log.e("INTENT-ACTION:", getIntent().getAction());
}
refreshComputerList();
@@ -81,33 +75,50 @@ protected void onResume() {
}
public void refreshComputerList(){
- SharedPreferences sharedPref = getSharedPreferences("data", MODE_PRIVATE);
- String key = sharedPref.getString("key",null);
- Log.d("ips",sharedPref.getString("ips",null));
- String ipString = sharedPref.getString("ips",null);
- List ips = new ArrayList();
- if(ipString.length() > 0){
- ips = Arrays.asList(sharedPref.getString("ips",null).split(","));
- ips = new ArrayList(ips);
+ TextView infoBar = findViewById(R.id.infoBar);
+ ArrayList computerList = new ArrayList<>();
+ KeyPairList keys = new KeyPairList(this);
+ if (keys.isEmpty()) {
+ infoBar.setVisibility(View.VISIBLE);
+ } else {
+ infoBar.setVisibility(View.GONE);
+ }
+ for (KeyPair k: keys) {
+ if (!commanded && getIntent().hasExtra("command")) {
+ computerList.add(new ComputerLayout(this, k, getIntent().getStringExtra("command")));
+ commanded = true;
+ } else {
+ computerList.add(new ComputerLayout(this, k));
+ }
}
- ArrayList computerList = new ArrayList();
- for(int i = 0 ; i < ips.size(); i++){
- if(ips.get(i).length() > 0){
- Log.d("creating-ip",ips.get(i));
+ LinearLayout feedLayout = findViewById(R.id.CardHolder);
+ feedLayout.removeAllViews();
- if(!commanded && getIntent().hasExtra("command")){
- computerList.add(new ComputerLayout(this,ips.get(i),key,getIntent().getStringExtra("command")));
- commanded = true;
- }else{
- computerList.add(new ComputerLayout(this,ips.get(i),key));
- }
+ for(int i = 0; i < computerList.size(); i++){
+ feedLayout.addView(computerList.get(i));
+ }
+ swipeContainer.setRefreshing(false);
+ }
+ public void deleteComputerList() {
+ TextView infoBar = findViewById(R.id.infoBar);
+ ArrayList computerList = new ArrayList<>();
+ KeyPairList keys = new KeyPairList(this);
+ if (keys.isEmpty()) {
+ infoBar.setVisibility(View.VISIBLE);
+ } else {
+ infoBar.setVisibility(View.GONE);
+ }
+ for (KeyPair k: keys) {
+ computerList.add(new ManageLayout(this, k));
+ if (!commanded && getIntent().hasExtra("command")) {
+ commanded = true;
}
}
- LinearLayout feedLayout = (LinearLayout) findViewById(R.id.list);
+ LinearLayout feedLayout = findViewById(R.id.CardHolder);
feedLayout.removeAllViews();
@@ -123,5 +134,5 @@ public static String getRandomNumber(int digCount) {
sb.append((char)('0' + rnd.nextInt(10)));
return sb.toString();
}
-
}
+
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/InfoRowView.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/InfoRowView.java
new file mode 100644
index 0000000..c815712
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/InfoRowView.java
@@ -0,0 +1,40 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+
+public class InfoRowView extends LinearLayout {
+
+ private final TextView helpText;
+
+ public InfoRowView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOrientation(VERTICAL);
+ LayoutInflater.from(context).inflate(R.layout.view_info_row, this, true);
+ FrameLayout container = findViewById(R.id.contentContainer);
+ ImageView infoBtn = findViewById(R.id.infoBtn);
+ helpText = findViewById(R.id.helpText);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.InfoRowView);
+ String info = a.getString(R.styleable.InfoRowView_infoText);
+ int contentLayout = a.getResourceId(R.styleable.InfoRowView_contentLayout, 0);
+ a.recycle();
+ if (info != null) {
+ helpText.setText(info);
+ } else {
+ infoBtn.setVisibility(GONE);
+ }
+ if (contentLayout != 0) {
+ LayoutInflater.from(context).inflate(contentLayout, container, true);
+ }
+ infoBtn.setOnClickListener(v -> {
+ helpText.setVisibility(helpText.getVisibility() == VISIBLE ? GONE : VISIBLE);
+ });
+ }
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/KeyPair.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/KeyPair.java
new file mode 100644
index 0000000..841af7b
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/KeyPair.java
@@ -0,0 +1,29 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import static com.maxchehab.remotelinuxunlocker.ComputerListActivity.getRandomNumber;
+
+import java.math.BigInteger;
+import java.util.Objects;
+
+public class KeyPair {
+ final String ip;
+ final String key;
+ String user;
+
+ boolean unlock;
+
+ KeyPair(String ip) {
+ this.ip = ip;
+ this.key = new BigInteger(getRandomNumber(64)).toString();
+ this.user = "";
+ this.unlock = false;
+ }
+
+ public boolean containsIp(String ip) {
+ return Objects.equals(this.ip, ip);
+ }
+ public boolean containsUser(String user) {
+ return Objects.equals(this.user, user);
+ }
+}
+
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/KeyPairList.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/KeyPairList.java
new file mode 100644
index 0000000..95476e7
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/KeyPairList.java
@@ -0,0 +1,66 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import static android.content.Context.MODE_PRIVATE;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.google.gson.Gson;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+public class KeyPairList extends ArrayList {
+ public boolean containsKey(KeyPair key) {
+ for (KeyPair k: this) {
+ if (k.containsIp(key.ip) && k.containsUser(key.user)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ public void addKey(KeyPair key) {
+ this.add(key);
+ }
+ /** @noinspection BooleanMethodIsAlwaysInverted*/
+ public boolean removeKey(KeyPair key) {
+ for (KeyPair k : this) {
+ if (Objects.equals(k.ip, key.ip) && Objects.equals(k.user, key.user)) {
+ this.remove(k);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void commitKeys(Context context) {
+ String serialized = new Gson().toJson(this);
+ SharedPreferences sharedPref = context.getSharedPreferences("data", MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putString("keysets", serialized);
+ editor.apply();
+ }
+ /** @noinspection CallToPrintStackTrace*/
+ public KeyPairList(Context context) {
+ SharedPreferences sharedPref = context.getSharedPreferences("data", MODE_PRIVATE);
+ if(!sharedPref.contains("keysets")){
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putString("keysets", "");
+ editor.apply();
+ }
+ String data = sharedPref.getString("keysets",null);
+ try {
+ KeyPairList list = new Gson().fromJson(data, KeyPairList.class);
+ if (list == null || list.isEmpty()) {
+ return;
+ }
+ this.addAll(list);
+ } catch (Exception e) {
+ e.printStackTrace();
+ KeyPairList empty = new KeyPairList();
+ empty.commitKeys(context);
+ }
+ }
+
+ public KeyPairList(){}
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ManageLayout.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ManageLayout.java
new file mode 100644
index 0000000..bef390a
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/ManageLayout.java
@@ -0,0 +1,107 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.CardView;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class ManageLayout extends CardView {
+
+ public ManageLayout(Context context) {
+ super(context);
+ }
+
+ public ManageLayout(Context context, KeyPair key) {
+ super(context);
+ init(context, key);
+ }
+ private static final ExecutorService executor = Executors.newSingleThreadExecutor();
+ private static final Handler handler = new Handler(Looper.getMainLooper());
+ private TextView deetsBar;
+
+ private void init(Context context, KeyPair key) {
+ ExecutorService executor2 = Executors.newSingleThreadExecutor();
+ inflate(getContext(), R.layout.manage_layout, this);
+ deetsBar = findViewById(R.id.deetsBar);
+ Button deleteComputer = findViewById(R.id.deleteComputer);
+ deleteComputer.setOnClickListener(view -> {
+ deleteIp(context, key);
+ setVisibility(View.GONE);
+ });
+ Button unlockComputer = findViewById(R.id.unlockComputer);
+ if (key.unlock) {
+ int color = ContextCompat.getColor(context, R.color.successColorAccent);
+ unlockComputer.setBackgroundTintList(ColorStateList.valueOf(color));
+ unlockComputer.setText(R.string.lock);
+ }
+ unlockComputer.setOnClickListener(view -> {
+ KeyPairList keys = new KeyPairList(context);
+ if (!keys.removeKey(key)) {
+ System.out.println("Key not found.");
+ }
+ key.unlock = !key.unlock;
+ keys.add(key);
+ keys.commitKeys(context);
+ if (key.unlock) {
+ int color = ContextCompat.getColor(context, R.color.successColorAccent);
+ unlockComputer.setBackgroundTintList(ColorStateList.valueOf(color));
+ unlockComputer.setText(R.string.lock);
+ } else {
+ int color = ContextCompat.getColor(context, R.color.dangerColorAccent);
+ unlockComputer.setBackgroundTintList(ColorStateList.valueOf(color));
+ unlockComputer.setText(R.string.unlock);
+ }
+ });
+ deetsBar.setText(String.format("%s@%s", key.user, key.ip));
+ executor2.execute(() -> {
+ String hostname = status(key);
+ handler.post(() -> {
+ if (hostname != null) {
+ deetsBar.setText(String.format("%s@%s (%s)", key.user, key.ip, hostname));
+ }
+ });
+ });
+ }
+
+ void deleteIp(Context context, KeyPair key) {
+ KeyPairList keys = new KeyPairList(context);
+ if (!keys.removeKey(key)) {
+ System.out.println("Key not found.");
+ }
+ keys.commitKeys(context);
+ }
+ /** @noinspection CallToPrintStackTrace*/
+ private String status(KeyPair key) {
+ String echoResponse = null;
+ try {
+ echoResponse = executor.submit(new ClientBuilder().setHost(key.ip).setPort(61599).setMessage("{\"command\":\"status\",\"key\":\"" + key.key + "\"}").createClient()).get(2, TimeUnit.SECONDS);
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ e.printStackTrace();
+ }
+
+ Log.d("status-response","Response: " + echoResponse);
+
+ if(echoResponse != null) {
+ JsonObject rootObj = JsonParser.parseString(echoResponse).getAsJsonObject();
+ Log.d("hostname", rootObj.get("hostname").getAsString());
+ return rootObj.get("hostname").getAsString();
+ }
+ return null;
+ }
+
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PairingActivity.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PairingActivity.java
index f7e6e25..949bdb3 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PairingActivity.java
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PairingActivity.java
@@ -1,100 +1,83 @@
package com.maxchehab.remotelinuxunlocker;
-import android.content.Intent;
-import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.InputFilter;
-import android.text.Spanned;
import android.util.Log;
-import android.view.View;
import android.widget.Button;
import android.widget.EditText;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class PairingActivity extends AppCompatActivity {
private EditText ipInput;
- private Button pairButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pairing);
- ipInput = (EditText)findViewById(R.id.ipInput);
- pairButton = (Button)findViewById(R.id.pairButton);
+ ipInput = findViewById(R.id.ipInput);
+ Button pairButton = findViewById(R.id.pairButton);
InputFilter[] filters = new InputFilter[1];
- filters[0] = new InputFilter() {
- @Override
- public CharSequence filter(CharSequence source, int start,
- int end, Spanned dest, int dstart, int dend) {
- if (end > start) {
- String destTxt = dest.toString();
- String resultingTxt = destTxt.substring(0, dstart) +
- source.subSequence(start, end) +
- destTxt.substring(dend);
- if (!resultingTxt.matches ("^\\d{1,3}(\\." +
- "(\\d{1,3}(\\.(\\d{1,3}(\\.(\\d{1,3})?)?)?)?)?)?")) {
- return "";
- } else {
- String[] splits = resultingTxt.split("\\.");
- for (int i=0; i 255) {
- return "";
- }
+ filters[0] = (source, start, end, dest, dstart, dend) -> {
+ if (end > start) {
+ String destTxt = dest.toString();
+ String resultingTxt = destTxt.substring(0, dstart) +
+ source.subSequence(start, end) +
+ destTxt.substring(dend);
+ if (!resultingTxt.matches ("^\\d{1,3}(\\." +
+ "(\\d{1,3}(\\.(\\d{1,3}(\\.(\\d{1,3})?)?)?)?)?)?")) {
+ return "";
+ } else {
+ String[] splits = resultingTxt.split("\\.");
+ for (String split : splits) {
+ if (Integer.parseInt(split) > 255) {
+ return "";
}
}
}
- return null;
}
+ return null;
};
ipInput.setFilters(filters);
- pairButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- pair();
- }
- });
+ pairButton.setOnClickListener(view -> pair());
+ Button buttonBack = findViewById(R.id.buttonBack);
+ buttonBack.setOnClickListener(view -> finish());
}
-
+ private static final ExecutorService executor = Executors.newSingleThreadExecutor();
+ /** @noinspection CallToPrintStackTrace*/
void pair(){
- SharedPreferences sharedPref = getSharedPreferences("data", MODE_PRIVATE);
- String key = sharedPref.getString("key",null);
- String ipString = sharedPref.getString("ips",null);
- List ips = new ArrayList();
- if(ipString.length() > 0){
- ips = Arrays.asList(sharedPref.getString("ips",null).split(","));
- ips = new ArrayList(ips);
- }
- if(ips.contains(ipInput.getText().toString())){
- ipInput.setError("IP address is already paired.");
- return;
- }
+ KeyPair key = new KeyPair(ipInput.getText().toString());
+ KeyPairList keys = new KeyPairList(this);
try {
- String response = new Client(ipInput.getText().toString(), 61598, "{\"command\":\"pair\",\"key\":\"" + key + "\"}").execute().get(1, TimeUnit.SECONDS);
+ String response = executor.submit(new ClientBuilder().setHost(key.ip).setPort(61598).setMessage("{\"command\":\"pair\",\"key\":\"" + key.key + "\"}").createClient()).get(1, TimeUnit.SECONDS);
Log.d("UI RESPONSE", "response: " + response);
if(response == null){
pairFailed();
}else{
+ JsonObject responseObject = JsonParser.parseString(response).getAsJsonObject();
+ key.user = responseObject.get("user").getAsString();
+ if (keys.containsKey(key)) {
+ ipInput.setError("IP address is already paired with this user.");
+ return;
+ }
+ keys.addKey(key);
+ keys.commitKeys(this);
pairSuccess();
}
- } catch (InterruptedException e) {
- pairFailed();
- e.printStackTrace();
- } catch (ExecutionException e) {
- pairFailed();
- e.printStackTrace();
- }catch (TimeoutException e) {
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
pairFailed();
e.printStackTrace();
}
@@ -106,15 +89,6 @@ void pairFailed(){
void pairSuccess(){
ipInput.setError(null);
-
- SharedPreferences sharedPref = getSharedPreferences("data", MODE_PRIVATE);
- List ips = Arrays.asList(sharedPref.getString("ips",null).split(","));
- ips = new ArrayList(ips);
-
- ips.add(ipInput.getText().toString());
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putString("ips", android.text.TextUtils.join(",", ips));
- editor.commit();
finish();
}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PersistenceReceiver.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PersistenceReceiver.java
new file mode 100644
index 0000000..386c10b
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PersistenceReceiver.java
@@ -0,0 +1,29 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class PersistenceReceiver extends BroadcastReceiver
+{
+ private static final ExecutorService executor = Executors.newSingleThreadExecutor();
+ @Override
+ public void onReceive(Context context, Intent intent){
+ if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+ KeyPairList keys = new KeyPairList(context);
+ for (KeyPair k: keys) {
+ if (k.unlock) {
+ try {
+ executor.submit(new ClientBuilder().setHost(k.ip).setPort(61599).setMessage("{\"command\":\"unlock\",\"key\":\"" + k.key + "\"}").createClient()).get(2, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PersistenceService.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PersistenceService.java
new file mode 100644
index 0000000..913b2d0
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/PersistenceService.java
@@ -0,0 +1,73 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import static android.support.v4.app.ActivityCompat.requestPermissions;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.support.v4.app.NotificationCompat;
+
+public class PersistenceService extends Service {
+
+ private UnlockReceiver unlockReceiver;
+ private final String CHANNEL_ID = "PERSISTENCE_SERVICE";
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ boolean createMode = intent.getBooleanExtra("create", true);
+ if (!createMode) {
+ NotificationManager manager = getSystemService(NotificationManager.class);
+ if (manager != null) {
+ manager.deleteNotificationChannel(CHANNEL_ID);
+ return START_NOT_STICKY;
+ }
+ }
+ createNotificationChannel();
+ Notification notification = buildNotification();
+ try {
+ startForeground(1, notification);
+ } catch (Exception e) {
+ //Oh dear!
+ e.printStackTrace();
+ }
+ unlockReceiver = new UnlockReceiver();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
+ registerReceiver(unlockReceiver, filter);
+ return START_NOT_STICKY;
+ }
+ @Override
+ public void onDestroy() {
+ unregisterReceiver(unlockReceiver);
+ super.onDestroy();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private void createNotificationChannel() {
+ NotificationChannel serviceChannel = new NotificationChannel(CHANNEL_ID, "Disable me!", NotificationManager.IMPORTANCE_HIGH);
+ serviceChannel.setDescription("thing");
+ NotificationManager manager = getSystemService(NotificationManager.class);
+ if (manager != null) {
+ manager.createNotificationChannel(serviceChannel);
+ }
+ }
+
+ private Notification buildNotification() {
+ return new NotificationCompat.Builder(this, CHANNEL_ID)
+ .setContentTitle("Unlock with phone enabled!")
+ .setContentText("To hide this notification, please disable it in Notification Settings.")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .build();
+ }
+
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/Settings.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/Settings.java
new file mode 100644
index 0000000..c16dce7
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/Settings.java
@@ -0,0 +1,44 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import static android.content.Context.MODE_PRIVATE;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.google.gson.Gson;
+
+public class Settings {
+ boolean unlockHook = false;
+ public Settings() {}
+
+ /** @noinspection CallToPrintStackTrace*/
+ public Settings(Context context) {
+ SharedPreferences sharedPref = context.getSharedPreferences("data", MODE_PRIVATE);
+ if (!sharedPref.contains("settings")) {
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putString("settings", "");
+ editor.apply();
+ }
+ String data = sharedPref.getString("settings", null);
+ try {
+ Settings settings = new Gson().fromJson(data, Settings.class);
+ if (settings == null) {
+ return;
+ }
+ this.unlockHook = settings.unlockHook;
+ } catch (Exception e) {
+ e.printStackTrace();
+ Settings settings = new Settings();
+ settings.commitSettings(context);
+ }
+ }
+ @SuppressLint("ApplySharedPref")
+ public void commitSettings(Context context) {
+ String serialized = new Gson().toJson(this);
+ SharedPreferences sharedPref = context.getSharedPreferences("data", MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putString("settings", serialized);
+ editor.commit();
+ }
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/SettingsActivity.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/SettingsActivity.java
new file mode 100644
index 0000000..41c0642
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/SettingsActivity.java
@@ -0,0 +1,38 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.Button;
+import android.widget.Switch;
+
+public class SettingsActivity extends AppCompatActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_settings);
+ Settings settings = new Settings(this);
+ Switch switchUnlockHook = findViewById(R.id.switchUnlockHook);
+ if (settings.unlockHook) {
+ switchUnlockHook.setChecked(true);
+ }
+
+ Button buttonCommit = findViewById(R.id.buttonCommit);
+ buttonCommit.setOnClickListener(view -> {
+ setVisible(false);
+ settings.unlockHook = switchUnlockHook.isChecked();
+ settings.commitSettings(this);
+ Intent mainActivity = new Intent(this, ComputerListActivity.class);
+ int pendingId = 0;
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, pendingId, mainActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ AlarmManager manager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
+ manager.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
+ android.os.Process.killProcess(android.os.Process.myPid());
+ });
+ Button buttonBack = findViewById(R.id.buttonBack);
+ buttonBack.setOnClickListener(view -> finish());
+ }
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/UnlockReceiver.java b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/UnlockReceiver.java
new file mode 100644
index 0000000..7f37ce5
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/java/com/maxchehab/remotelinuxunlocker/UnlockReceiver.java
@@ -0,0 +1,31 @@
+package com.maxchehab.remotelinuxunlocker;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class UnlockReceiver extends BroadcastReceiver {
+
+ private static final ExecutorService executor = Executors.newSingleThreadExecutor();
+ @Override
+ public final void onReceive(Context context, Intent intent){
+ if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+ KeyPairList keys = new KeyPairList(context);
+ for (KeyPair k: keys) {
+ if (k.unlock) {
+ try {
+ executor.submit(new ClientBuilder().setHost(k.ip).setPort(61599).setMessage("{\"command\":\"unlock\",\"key\":\"" + k.key + "\"}").createClient()).get(2, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/drawable/ic_new.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/drawable/ic_new.xml
deleted file mode 100644
index 81cf155..0000000
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/drawable/ic_new.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_computer_list.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_computer_list.xml
index 3c10c01..ebcd189 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_computer_list.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_computer_list.xml
@@ -1,35 +1,71 @@
+
+ android:layout_height="match_parent"
-
+ android:orientation="vertical">
-
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_lock_computer.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_lock_computer.xml
index b97736e..b2b4b75 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_lock_computer.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_lock_computer.xml
@@ -1,9 +1,6 @@
-
-
+ tools:context="com.maxchehab.remotelinuxunlocker.LockComputer"/>
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_pairing.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_pairing.xml
index 5d020d4..f33e0b7 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_pairing.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_pairing.xml
@@ -1,20 +1,24 @@
+
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:orientation="vertical">
@@ -22,7 +26,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
- android:text="If you have not already installed Remote Linux Unlocker on your computer please do so. Instructions are at https://github.com/maxchehab/remote-linux-unlocker.\n\nOnce you have installed Remote Linux Unlocker on your computer run the command 'remote-linux-pair' in a terminal. Simply follow the instructions. "
+ android:text="@string/pair_instructions"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="14sp" />
@@ -31,14 +35,35 @@
android:id="@+id/ipInput"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:hint="127.0.0.1"/>
+ android:hint="@string/pair_sample_ip"
+ android:inputType="phone"
+ tools:ignore="Autofill" />
+ android:text="@string/pair"
+ style="@style/Widget.AppCompat.Button.Colored"/>
+
+
+
+
+
+
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_settings.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_settings.xml
new file mode 100644
index 0000000..2de9829
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_settings.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_unlock_computer.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_unlock_computer.xml
index addcda0..4e40906 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_unlock_computer.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/activity_unlock_computer.xml
@@ -1,6 +1,5 @@
@@ -17,11 +18,10 @@
android:orientation="vertical">
@@ -29,7 +29,7 @@
+ android:textSize="24sp" />
-
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/manage_layout.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/manage_layout.xml
new file mode 100644
index 0000000..be839be
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/manage_layout.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/view_info_row.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/view_info_row.xml
new file mode 100644
index 0000000..bc626ba
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/layout/view_info_row.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/attrs.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..2f49124
--- /dev/null
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/attrs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/colors.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/colors.xml
index 3ab3e9c..0e6fed2 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/colors.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/colors.xml
@@ -1,6 +1,9 @@
- #3F51B5
- #303F9F
- #FF4081
+ #3F51B5
+ #303F9F
+ #FF4081
+ #FF1744
+ #00C853
+ #FF9800
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/dimens.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/dimens.xml
deleted file mode 100644
index 59a0b0c..0000000
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/dimens.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
- 16dp
-
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/strings.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/strings.xml
index f5ddae0..e73333c 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/strings.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/strings.xml
@@ -1,5 +1,23 @@
Remote Linux Unlocker
- ComputerListActivity
- Lock Computer
+ Delete
+ Tux the Penguin inside a Computer display.
+ Computers will appear here
+ Manage Devices
+ Settings
+ Add device
+ Instructions to pair device:
+ If you have not already installed Remote Linux Unlocker on your computer please do so. Instructions are at https://github.com/maxchehab/remote-linux-unlocker.\n\nOnce you have installed Remote Linux Unlocker on your computer run the command \'remote-linux-pair\' in a terminal. Simply follow the instructions.
+ Application settings:
+ To change this application\'s settings, please use the options below.Note that pressing `APPLY` will immediately write the changes to the configuration, and re-launch this program.\nTap the ⓘ icon above any setting for more information.
+ 127.0.0.1
+ Pair
+ Unlock
+ Lock
+ Back
+ Apply and Relaunch
+ Loading…
+ Offline
+ Enable unlock hook
+ Info
diff --git a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/styles.xml b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/styles.xml
index 95579de..6d4bf2c 100644
--- a/android-application/RemoteLinuxUnlocker/app/src/main/res/values/styles.xml
+++ b/android-application/RemoteLinuxUnlocker/app/src/main/res/values/styles.xml
@@ -3,23 +3,22 @@
-
-
-
-
-
-
-
+
diff --git a/android-application/RemoteLinuxUnlocker/build.gradle b/android-application/RemoteLinuxUnlocker/build.gradle
index d0aa704..6e64062 100644
--- a/android-application/RemoteLinuxUnlocker/build.gradle
+++ b/android-application/RemoteLinuxUnlocker/build.gradle
@@ -2,10 +2,11 @@
buildscript {
repositories {
- jcenter()
+ google()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.2'
+ classpath 'com.android.tools.build:gradle:8.13.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -14,10 +15,11 @@ buildscript {
allprojects {
repositories {
- jcenter()
+ google()
+ mavenCentral()
}
}
-task clean(type: Delete) {
- delete rootProject.buildDir
+tasks.register('clean', Delete) {
+ delete layout.buildDirectory
}
diff --git a/android-application/RemoteLinuxUnlocker/gradle/wrapper/gradle-wrapper.properties b/android-application/RemoteLinuxUnlocker/gradle/wrapper/gradle-wrapper.properties
index ad11cb9..5b715b2 100644
--- a/android-application/RemoteLinuxUnlocker/gradle/wrapper/gradle-wrapper.properties
+++ b/android-application/RemoteLinuxUnlocker/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-all.zip
\ No newline at end of file
diff --git a/linux-daemon/keys.db b/linux-daemon/keys.db
deleted file mode 100644
index 1240cab..0000000
--- a/linux-daemon/keys.db
+++ /dev/null
@@ -1,2 +0,0 @@
-5743704979839069563839512692265820549527076999492449313315050835
-6912957806010502767906158581762725597848101883591337724546592587
diff --git a/linux-daemon/linux-daemon.zip b/linux-daemon/linux-daemon.zip
index 9db92ff..d9ac355 100644
Binary files a/linux-daemon/linux-daemon.zip and b/linux-daemon/linux-daemon.zip differ
diff --git a/linux-daemon/remote-linux-pair b/linux-daemon/remote-linux-pair
index ca80187..118e502 100755
--- a/linux-daemon/remote-linux-pair
+++ b/linux-daemon/remote-linux-pair
@@ -1,12 +1,13 @@
#!/usr/bin/env python
-import socket, sys, json, struct, os
+import socket, sys, json, struct, os, getpass, pwd
-from pprint import pprint
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
def is_json(myjson):
try:
json_object = json.loads(myjson)
- except ValueError, e:
+ except ValueError:
return False
return True
@@ -20,6 +21,14 @@ def get_default_gateway_linux():
return socket.inet_ntoa(struct.pack(">sys.stderr, "You are about to pair a new device to this computer.\nIf you have not done so already, please open the Remote Linux Unlocker app. You can download it here: https://play.google.com/store/apps/details?id=com.maxchehab.remotelinuxunlocker\nWhen you are ready, please type the following IP address into the required field on your device.\n\nIP Address: " + IP
+eprint("You are about to pair a new device to this computer.\nIf you have not done so already, please open the Remote Linux Unlocker app. You can download it here: https://play.google.com/store/apps/details?id=com.maxchehab.remotelinuxunlocker\nWhen you are ready, please type the following IP address into the required field on your device.\n\nIP Address: " + IP)
sock.bind(server_address)
# Listen for incoming connections
@@ -40,31 +49,32 @@ sock.listen(1)
while True:
# Wait for a connection
- print >>sys.stderr, '\nAwaiting your response...'
+ eprint('\nAwaiting your response...')
connection, client_address = sock.accept()
try:
- print >>sys.stderr, 'Connection received...'
+ eprint('Connection received...')
# Receive the data in small chunks and retransmit it
while True:
data = connection.recv(256).strip()
- print >>sys.stderr, 'Processing request...'
+ eprint('Processing request...')
if is_json(data):
data = json.loads(data)
if data["command"] == "pair" and len(data["key"]) == 64:
- if os.path.exists(os.path.dirname(os.path.realpath(__file__)) + '/keys.db'):
+ user = get_username()
+ if os.path.exists(os.path.dirname(os.path.realpath(__file__)) + '/keys'):
append_write = 'a' # append if already exists
else:
append_write = 'w' # make a new file if not
- with open(os.path.dirname(os.path.realpath(__file__)) + '/keys.db', append_write) as file:
- file.write(data["key"] + "\n")
- connection.sendall('{"status":"success"}')
- print >> sys.stderr, 'Pairing was successful!'
+ with open(os.path.dirname(os.path.realpath(__file__)) + '/keys', append_write) as file:
+ file.write(user + " " + data["key"] + "\n")
+ connection.sendall(b'{"status":"success","user":"' + user.encode() + b'"}')
+ eprint('Pairing was successful!')
sys.exit()
else:
- print >>sys.stderr, 'Invalid request!'
+ eprint('Invalid request!')
sys.exit()
break
diff --git a/linux-daemon/unlocker-daemon.py b/linux-daemon/unlocker-daemon.py
old mode 100644
new mode 100755
index 28f6e4a..cd0173a
--- a/linux-daemon/unlocker-daemon.py
+++ b/linux-daemon/unlocker-daemon.py
@@ -1,44 +1,60 @@
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket, sys, json, subprocess, os
-from pprint import pprint
+
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
def is_json(myjson):
try:
json_object = json.loads(myjson)
- except ValueError, e:
+ except ValueError:
return False
return True
+def get_user_from_key(key):
+ with open(os.path.dirname(os.path.realpath(__file__)) + '/keys') as file:
+ for line in file:
+ line = line.strip().split(' ')
+ if line[1] == key:
+ return line[0]
+ break
+ return ""
-def is_locked():
- users = [i.split(':') for i in open('/etc/shadow').readlines()]
- user = [i[0] for i in users if i[1] not in ('!', '*')][0]
+def authenticate_key(key):
+ # with open(os.path.dirname(os.path.realpath(__file__)) + '/keys') as file:
+ # for line in file:
+ # if line.strip().split(' ')[1] == key:
+ # return True
+ # break
+ # return False
+ return get_user_from_key(key) != ""
- commands = 'su ' + user + ' -c -- "gdbus call -e -d com.canonical.Unity -o /com/canonical/Unity/Session -m com.canonical.Unity.Session.IsLocked"'
+def is_locked(key):
+ # users = [i.split(':') for i in open('/etc/shadow').readlines()]
+ # user = [i[0] for i in users if i[1] not in ('!', '*')][0]
+ user = get_user_from_key(key)
+ if user == "":
+ return False
+ #commands = 'su ' + user + ' -c -- "gdbus call -e -d com.canonical.Unity -o /com/canonical/Unity/Session -m com.canonical.Unity.Session.IsLocked"'
+ commands = 'su ' + user + ' -c -- "dbus-send --session --dest=org.freedesktop.ScreenSaver --type=method_call --print-reply /org/freedesktop/ScreenSaver org.freedesktop.ScreenSaver.GetActive"'
p = subprocess.Popen(commands,stdout=subprocess.PIPE, shell=True)
- if "true" in str(p.communicate()):
+ res = str(p.communicate())
+ if "true" in res:
return True
else:
+ # print(users)
+ print(user + "> " + res)
return False
return False
-def authenticate_key(key):
- with open(os.path.dirname(os.path.realpath(__file__)) + '/keys.db') as file:
- for line in file:
- if line.strip() == key:
- return True
- break
-
- return False
-
-
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind the socket to the port
server_address = ('', 61599)
-print >>sys.stderr, 'starting up on %s port %s' % server_address
+eprint('starting up on %s port %s' % server_address)
sock.bind(server_address)
# Listen for incoming connections
@@ -46,37 +62,37 @@ def authenticate_key(key):
while True:
# Wait for a connection
- print >>sys.stderr, 'waiting for a connection'
+ eprint('waiting for a connection')
connection, client_address = sock.accept()
try:
- print >>sys.stderr, 'connection from', client_address
+ eprint('connection from', client_address)
# Receive the data in small chunks and retransmit it
while True:
data = connection.recv(256).strip()
- print >>sys.stderr, 'received "%s"' % data
+ eprint('received "%s"' % data)
if is_json(data):
data = json.loads(data)
if data["command"] == "lock" and data["key"] and authenticate_key(data["key"]):
- print >>sys.stderr, 'client requesting lock'
+ eprint('client requesting lock')
subprocess.call(["loginctl", "lock-sessions"])
- connection.sendall('{"status":"success"')
+ connection.sendall(b'{"status":"success"')
break
elif data["command"] == "unlock" and data["key"] and authenticate_key(data["key"]):
- print >>sys.stderr, 'client requesting unlock'
+ eprint('client requesting unlock')
subprocess.call(["loginctl", "unlock-sessions"])
- connection.sendall('{"status":"success"')
+ connection.sendall(b'{"status":"success"')
break
elif data["command"] == "status" and data["key"] and authenticate_key(data["key"]):
- print >>sys.stderr, 'client requesting echo'
- response = '{"status":"success","hostname":"' + socket.gethostname() + '","isLocked":"' + str(is_locked()) + '"}';
- print >> sys.stderr, response
- connection.sendall(response)
+ eprint('client requesting echo')
+ response = '{"status":"success","hostname":"' + socket.gethostname() + '","isLocked":"' + str(is_locked(data["key"])) + '"}'
+ eprint( response)
+ connection.sendall(response.encode("utf-8"))
break
else:
- print >>sys.stderr, 'no more data from', client_address
+ eprint('no more data from', client_address)
break
finally:
diff --git a/linux-daemon/unlocker-deamon.service b/linux-daemon/unlocker-daemon.service
similarity index 100%
rename from linux-daemon/unlocker-deamon.service
rename to linux-daemon/unlocker-daemon.service