diff --git a/.gitignore b/.gitignore
index a14101e6c..be193326d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,36 @@
-.gradle
-/local.properties
-/.idea/workspace.xml
-/.idea/libraries
+#built application files
+*.apk
+*.ap_
+
+# files for the dex VM
+*.dex
+
+# Java class files
+*.class
+
+# generated files
+bin/
+gen/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Windows thumbnail db
+Thumbs.db
+
+# OSX files
.DS_Store
-/build
+
+# Android Studio
*.iml
-/.idea/.name
-/.idea/gradle.xml
-/.idea/misc.xml
-/.idea/modules.xml
-/term/term-release.apk
-/term/Term-nh.apk
-release
+.idea
+#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
+.gradle
+build/
+.navigation
+captures/
+output.json
+
+#NDK
+obj/
+.externalNativeBuild
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 9a8b7e5c4..000000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
deleted file mode 100644
index e7bedf337..000000000
--- a/.idea/copyright/profiles_settings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index 97626ba45..000000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index e503882fa..000000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 3b312839b..000000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml
deleted file mode 100644
index 922003b84..000000000
--- a/.idea/scopes/scope_settings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/Android.mk b/Android.mk
index 633ef4ec7..6fb4ff640 100644
--- a/Android.mk
+++ b/Android.mk
@@ -25,4 +25,4 @@ LOCAL_SRC_FILES := $(nhterm_dir)/$(nhterm_apk)
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
-include $(BUILD_PREBUILT)
\ No newline at end of file
+include $(BUILD_PREBUILT)
diff --git a/README.md b/README.md
index 50f7a58f8..cc8857810 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,23 @@
-#NetHunter Terminal Emulator
+# NetHunter Terminal Emulator
-This is a new fork of the Android Terminal Emulator so we can adapt it to our neeeds for Kali Linux Nethunter.
+This is a new fork of the Android Terminal Emulator so we can adapt it to our neeeds for Kali NetHunter.
Dependencies running the terminal:
- Nedds a full instalation (included the chroot install) of Kali Nethunter
+ Needs a full installation of Kali NetHunter (including chroot)
-Buiding from sources:
+Building from sources:
(Todo) see: https://github.com/jmingov/NetHunter-Terminal-Emulator/blob/master/docs/Building.md
-Since the original proyect is "ended" we left here the credits an licenses:
+Since the original project has "ended" we'll include the credits and licenses below:
Original author: https://github.com/jackpal
-Original proyect: https://github.com/jackpal/Android-Terminal-Emulator
+Original project: https://github.com/jackpal/Android-Terminal-Emulator
-License: The same as the original proyect. (Thouse files are [included](https://github.com/jmingov/NetHunter-Terminal-Emulator/blob/master/NOTICE) in this proyect too.)
+License: The same as the original project. (Thouse files are [included](https://github.com/jmingov/NetHunter-Terminal-Emulator/blob/master/NOTICE) in this project too.)
diff --git a/build.gradle b/build.gradle
index 474fe2aa8..087f69faf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,9 +1,3 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-task wrapper (type:Wrapper) {
- gradleVersion = '4.1'
- distributionUrl = 'https://services.gradle.org/distributions/gradle-4.1-rc-1-all.zip'
-}
-
buildscript {
repositories {
jcenter()
@@ -13,12 +7,24 @@ buildscript {
}
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.0-beta3'
+ classpath 'com.android.tools.build:gradle:3.2.0'
}
}
+
allprojects {
repositories {
jcenter()
+ google()
}
-}
\ No newline at end of file
+}
+
+ext {
+ compileSdkVersion=28
+ minSdkVersion=14
+ targetSdkVersion=28
+ //version=YYYYMMVVRR (Either "VV" for stable version OR "RR" for pre-release candidate (e.g. 0001 for rc1)
+ versionCode=2019020002
+ versionName="2019.2-rc2"
+}
+
diff --git a/emulatorview/build.gradle b/emulatorview/build.gradle
index f3ba04aef..cad5df3c5 100644
--- a/emulatorview/build.gradle
+++ b/emulatorview/build.gradle
@@ -1,12 +1,18 @@
apply plugin: 'com.android.library'
+repositories {
+ jcenter()
+ google()
+}
+
android {
- compileSdkVersion 25
- buildToolsVersion "25"
+<<<<<<< HEAD
+ compileSdkVersion 28
+ buildToolsVersion "28.0.3"
defaultConfig {
- minSdkVersion 4
- targetSdkVersion 25
+ minSdkVersion 14
+ targetSdkVersion 27
}
buildTypes {
diff --git a/emulatorview/src/main/AndroidManifest.xml b/emulatorview/src/main/AndroidManifest.xml
index 61513aa83..601d55941 100644
--- a/emulatorview/src/main/AndroidManifest.xml
+++ b/emulatorview/src/main/AndroidManifest.xml
@@ -3,5 +3,4 @@
package="com.offsec.nhterm.emulatorview"
android:versionCode="43"
android:versionName="1.0.42">
-
diff --git a/emulatorview/src/main/java/com/offsec/nhterm/emulatorview/TermSession.java b/emulatorview/src/main/java/com/offsec/nhterm/emulatorview/TermSession.java
index f98e4f5b2..2cfe4688e 100644
--- a/emulatorview/src/main/java/com/offsec/nhterm/emulatorview/TermSession.java
+++ b/emulatorview/src/main/java/com/offsec/nhterm/emulatorview/TermSession.java
@@ -112,11 +112,12 @@ public interface FinishCallback {
private FinishCallback mFinishCallback;
private boolean mIsRunning = false;
- private final Handler mMsgHandler = new Handler() {
+
+ private final Handler mMsgHandler = new Handler(new Handler.Callback() {
@Override
- public void handleMessage(Message msg) {
+ public boolean handleMessage(Message msg) {
if (!mIsRunning) {
- return;
+ return false;
}
if (msg.what == NEW_INPUT) {
readFromProcess();
@@ -128,8 +129,9 @@ public void run() {
}
});
}
+ return true;
}
- };
+ });
private UpdateCallback mTitleChangedListener;
@@ -186,16 +188,17 @@ public void run() {
Looper.prepare();
Log.d("TermSession.java: ", "new Handler");
- mWriterHandler = new Handler() {
+ mWriterHandler = new Handler(new Handler.Callback() {
@Override
- public void handleMessage(Message msg) {
+ public boolean handleMessage(Message msg) {
if (msg.what == NEW_OUTPUT) {
writeToOutput();
} else if (msg.what == FINISH) {
Looper.myLooper().quit();
}
+ return true;
}
- };
+ });
// Drain anything in the queue from before we started
Log.d("TermSession.java: ", "writeToOutput()");
diff --git a/gradle.properties b/gradle.properties
index e0b6a5fed..004c59039 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -13,3 +13,4 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Fri Sep 16 18:00:52 CDT 2016
+
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0f83a6793..a0545d350 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu Aug 31 21:08:59 CDT 2017
+#Thu Feb 14 02:14:00 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/libtermexec/build.gradle b/libtermexec/build.gradle
index 34ed3dddb..e899b6c97 100644
--- a/libtermexec/build.gradle
+++ b/libtermexec/build.gradle
@@ -1,9 +1,10 @@
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
+ classpath 'com.android.tools.build:gradle:3.2.0'
}
}
apply plugin: 'com.android.library'
@@ -13,18 +14,18 @@ repositories {
}
android {
- compileSdkVersion 25
- buildToolsVersion "26.0.1"
+ compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
- minSdkVersion 14
- targetSdkVersion 25
- versionCode 2
- versionName "2.0"
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+ versionCode rootProject.ext.versionCode
+ versionName rootProject.ext.versionName
+
ndk {
moduleName 'libjackpal-termexec2'
- abiFilters 'armeabi', 'arm64-v8a', 'armeabi-v7a', 'x86'
+ abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86'
ldLibs 'log', 'c'
}
}
@@ -63,5 +64,5 @@ android.libraryVariants.all { variant ->
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation 'com.android.support:support-annotations:26+'
+ implementation 'com.android.support:support-annotations:28.0.0'
}
\ No newline at end of file
diff --git a/libtermexec/src/main/jni/Application.mk b/libtermexec/src/main/jni/Application.mk
index 35ab62887..c29f1d41f 100644
--- a/libtermexec/src/main/jni/Application.mk
+++ b/libtermexec/src/main/jni/Application.mk
@@ -1,2 +1,2 @@
# Build for ARMv5TE, mips and x86 architectures.
-APP_ABI := armeabi mips x86 arm64-v8a armeabi-v7a
+APP_ABI := mips x86 arm64-v8a armeabi-v7a
diff --git a/libtermexec/src/main/jni/process.cpp b/libtermexec/src/main/jni/process.cpp
index 65c505e7f..2e4a8bcd6 100644
--- a/libtermexec/src/main/jni/process.cpp
+++ b/libtermexec/src/main/jni/process.cpp
@@ -26,8 +26,9 @@
#include
#include
#include
+#include
-typedef unsigned short char16_t;
+typedef unsigned short uint_least16_t;
class String8 {
public:
@@ -41,7 +42,7 @@ class String8 {
}
}
- void set(const char16_t* o, size_t numChars) {
+ void set(const uint_least16_t* o, size_t numChars) {
if (mString) {
free(mString);
}
diff --git a/term/build.gradle b/term/build.gradle
index e4ef9de1d..ec2f2c9d9 100644
--- a/term/build.gradle
+++ b/term/build.gradle
@@ -1,16 +1,18 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 26
- buildToolsVersion '26.0.1'
+ compileSdkVersion rootProject.ext.compileSdkVersion
+
defaultConfig {
applicationId 'com.offsec.nhterm'
- minSdkVersion 14
- targetSdkVersion 26
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+ versionCode rootProject.ext.versionCode
+ versionName rootProject.ext.versionName
ndk {
moduleName "libjackpal-androidterm5nhj1"
- abiFilters 'armeabi', 'arm64-v8a', 'armeabi-v7a', 'x86'
+ abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86'
ldLibs 'log', 'c'
}
}
@@ -44,5 +46,5 @@ android {
dependencies {
implementation project(':emulatorview')
implementation project(':libtermexec')
- implementation "com.android.support:support-v4:+"
+ implementation 'com.android.support:support-v4:+'
}
diff --git a/term/src/main/AndroidManifest.xml b/term/src/main/AndroidManifest.xml
index f03738761..ae0acd229 100644
--- a/term/src/main/AndroidManifest.xml
+++ b/term/src/main/AndroidManifest.xml
@@ -10,6 +10,8 @@
+
+
-
+
diff --git a/term/src/main/java/com/offsec/nhterm/ShellTermSession.java b/term/src/main/java/com/offsec/nhterm/ShellTermSession.java
index d20fb7cd1..a0b4f7438 100644
--- a/term/src/main/java/com/offsec/nhterm/ShellTermSession.java
+++ b/term/src/main/java/com/offsec/nhterm/ShellTermSession.java
@@ -96,13 +96,29 @@ private void initializeSession(String mShell) throws IOException {
if (settings.verifyPath()) {
path = checkPath(path);
}
- String[] env = new String[3];
+ String[] env = new String[4];
env[0] = "TERM=" + settings.getTermType();
- env[1] = "PATH=" + path + ":/data/data/com.offsec.nethunter/files/scripts/";
+ env[1] = "PATH=" + path + ":/data/data/com.offsec.nethunter/files/scripts" + ":/sbin/.magisk/busybox";
env[2] = "HOME=" + settings.getHomePath();
+ // Seems the $HOSTNAME is not defined in the file /system/etc/mkshrc on android 9,
+ // so the workaround is to set the $HOSTNAME manually by running getprop net.hostname, but shoud getprop be fine to use here?
+ env[3] = "HOSTNAME=" + getSystemProperty("ro.product.name");
// Log.d("Initialize Sess", settings.getShell());
mProcId = createSubprocess(mShell, env);
}
+ // Copied from stack overflow..https://stackoverflow.com/questions/16944494/system-getpropertyparam-returns-wrong-value-android by @Muzikant
+ private String getSystemProperty(String propertyName) {
+ String propertyValue = "";// let's default empty
+ try {
+ Process getPropProcess = Runtime.getRuntime().exec("getprop " + propertyName);
+ BufferedReader osRes = new BufferedReader(new InputStreamReader(getPropProcess.getInputStream()));
+ propertyValue = osRes.readLine();
+ osRes.close();
+ } catch (Exception e) {
+ Log.d(": Get hostname: ", "Failed to get hostname by $(getprop net.hostname)");
+ }
+ return propertyValue;
+ }
private String checkPath(String path) {
String[] dirs = path.split(":");
diff --git a/term/src/main/java/com/offsec/nhterm/ShellType.java b/term/src/main/java/com/offsec/nhterm/ShellType.java
index 235e76686..51bcbf05b 100644
--- a/term/src/main/java/com/offsec/nhterm/ShellType.java
+++ b/term/src/main/java/com/offsec/nhterm/ShellType.java
@@ -11,9 +11,9 @@
class ShellType {
static final String ANDROID_SHELL = whichCMD("sh") + " -";
- static final String ANDROID_SU_SHELL = whichCMD("su");
- static final String KALI_SHELL = whichCMD("su") + " -c /data/data/com.offsec.nethunter/files/scripts/bootkali";
- static final String KALI_LOGIN_SHELL = whichCMD("su") +" -c /data/data/com.offsec.nethunter/files/scripts/bootkali_login";
+ static final String ANDROID_SU_SHELL = whichCMD("su") + " --mount-master";
+ static final String KALI_SHELL = whichCMD("su") + " --mount-master -c /data/data/com.offsec.nethunter/files/scripts/bootkali";
+ static final String KALI_LOGIN_SHELL = whichCMD("su") + " --mount-master -c /data/data/com.offsec.nethunter/files/scripts/bootkali_login";
private static String whichCMD(String theCmd){
String output = null;
diff --git a/term/src/main/java/com/offsec/nhterm/Term.java b/term/src/main/java/com/offsec/nhterm/Term.java
index fd47f8e8f..ec9589e10 100644
--- a/term/src/main/java/com/offsec/nhterm/Term.java
+++ b/term/src/main/java/com/offsec/nhterm/Term.java
@@ -15,7 +15,6 @@
*/
package com.offsec.nhterm;
-
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
@@ -35,6 +34,7 @@
import android.content.res.Resources;
import android.net.Uri;
import android.net.wifi.WifiManager;
+import android.nfc.Tag;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -58,6 +58,7 @@
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
+import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@@ -198,7 +199,7 @@ public View getView(int position, View convertView, ViewGroup parent) {
Log.d("mPendingPathBroadcasts","Tamano = " + mTermService.getSessions().size());
Log.d("mPendingPathBroadcasts","Tamano = " + oldLength);
TextView label = new TextView(Term.this);
- @SuppressLint("StringFormatInvalid") String title = getSessionTitle(position, getString(R.string.window_title, position + 1));
+ String title = getSessionTitle(position, getString(R.string.window_title, position + 1));
label.setText(title);
if (AndroidCompat.SDK >= 13) {
label.setTextAppearance(Term.this, TextAppearance_Holo_Widget_ActionBar_Title);
@@ -376,7 +377,7 @@ public void onCreate(Bundle icicle) {
Intent broadcast = new Intent(ACTION_PATH_BROADCAST);
if (AndroidCompat.SDK >= 12) {
- broadcast.addFlags(FLAG_INCLUDE_STOPPED_PACKAGES);
+ broadcast.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
}
mPendingPathBroadcasts++;
sendOrderedBroadcast(broadcast, PERMISSION_PATH_BROADCAST, mPathReceiver, null, RESULT_OK, null, null);
@@ -388,7 +389,6 @@ public void onCreate(Bundle icicle) {
TSIntent = new Intent(this, TermService.class);
startService(TSIntent);
-
if (AndroidCompat.SDK >= 11) {
int actionBarMode = mSettings.actionBarMode();
mActionBarMode = actionBarMode;
@@ -411,7 +411,7 @@ public void onCreate(Bundle icicle) {
setFunctionKeyListener();
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TermDebug.LOG_TAG);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "com.offsec.nhterm:TermDebug.LOG_TAG");
WifiManager wm = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
int wifiLockMode = WifiManager.WIFI_MODE_FULL;
if (AndroidCompat.SDK >= 12) {
@@ -777,6 +777,8 @@ public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_preferences) {
doPreferences();
+ } else if (id == R.id.menu_chroot_path) {
+ doConfigChrootPath();
} else if (id == R.id.menu_new_window) {
doCreateNewWindow();
} else if (id == R.id.menu_close_window) {
@@ -897,7 +899,7 @@ public void onClick(DialogInterface dialog, int id) {
if(CheckRoot.isDeviceRooted()){
Log.d("isDeviceRooted","Device is rooted!");
- String chroot_dir = "/data/local/nhsystem/kali-armhf"; // Not sure if I can wildcard this
+ String chroot_dir = mSettings.getChrootDir();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (!dir_exists(chroot_dir)){
@@ -992,13 +994,13 @@ public boolean dir_exists(String dir_path)
@TargetApi(Build.VERSION_CODES.KITKAT)
private void NotFound(String text){
- String msg = "";
+ String msg = "Please config a proper Chroot Container Path in Settings.";
- if (Objects.equals(text, "/data/data/com.offsec.nethunter/files/scripts/bootkali")){
- msg = "Please run Nethunter Application to generate!";
- } else if (Objects.equals(text, "/data/local/nhsystem/kali-armhf")){
- msg = "Missing chroot. You need to install from Chroot Manager";
- }
+ //if (Objects.equals(text, "/data/data/com.offsec.nethunter/files/scripts/bootkali")){
+ // msg = "Please run Nethunter Application to generate!";
+ //} else if (Objects.equals(text, "/data/local/nhsystem/kali-armhf")){
+ //msg = "Missing chroot. You need to install from Chroot Manager";
+ //}
/// Do something for not found text (alertDialog)
alertDialogBuilder = new AlertDialog.Builder(this);
//alertDialogBuilder.setView(promptsView);
@@ -1080,6 +1082,30 @@ private void sendKeyStrings(String str, boolean esc) {
}
}
+ private void doConfigChrootPath(){
+ final View promptView = getLayoutInflater().inflate(R.layout.menu_chroot_path, null);
+ final EditText chrootpathEditText = promptView.findViewById(R.id.menu_chroot_path_et);
+ chrootpathEditText.setText(mSettings.getChrootDir());
+ final AlertDialog.Builder adbConfigChrootPath = new AlertDialog.Builder(this);
+ adbConfigChrootPath.setView(promptView);
+ adbConfigChrootPath.setCancelable(false);
+ adbConfigChrootPath.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mSettings.setChrootDir(getApplicationContext(), chrootpathEditText.getText().toString());
+ }
+ });
+ adbConfigChrootPath.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
+ adbConfigChrootPath.create().show();
+
+
+
+ }
private void doCreateNewWindow() {
if (mTermSessions == null) {
Log.w(TermDebug.LOG_TAG, "Couldn't create new window because mTermSessions == null");
diff --git a/term/src/main/java/com/offsec/nhterm/TermService.java b/term/src/main/java/com/offsec/nhterm/TermService.java
index 42a968311..5129895d9 100644
--- a/term/src/main/java/com/offsec/nhterm/TermService.java
+++ b/term/src/main/java/com/offsec/nhterm/TermService.java
@@ -15,7 +15,7 @@
*/
package com.offsec.nhterm;
-
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
@@ -31,14 +31,11 @@
import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import android.util.Log;
-import android.app.Notification;
+
import android.support.v4.app.NotificationCompat;
import android.app.PendingIntent;
-
-import com.offsec.nhterm.R;
import com.offsec.nhterm.emulatorview.TermSession;
-
import com.offsec.nhterm.compat.ServiceForegroundCompat;
import com.offsec.nhterm.libtermexec.v1.*;
import com.offsec.nhterm.util.SessionList;
@@ -51,9 +48,9 @@ public class TermService extends Service implements TermSession.FinishCallback
/* Parallels the value of START_STICKY on API Level >= 5 */
private static final int COMPAT_START_STICKY = 1;
- private NotificationManager mNotificationManager;
- private final int notifyID = 1;
-
+ private NotificationManager notificationManager;
+ private static final int notifyID = 1;
+ private static final String NH_TERM_CHANNEL_ID = "NH_TERM_CHANNEL";
private static final int RUNNING_NOTIFICATION = 1;
private ServiceForegroundCompat compat;
@@ -102,14 +99,28 @@ public void onCreate() {
//compat = new ServiceForegroundCompat(this);
mTermSessions = new SessionList();
- mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ // Create the NotificationChannel
+ CharSequence name = getString(R.string.nh_term_notification_channel);
+ String description = getString(R.string.nh_term_notification_channel);
+ int importance = NotificationManager.IMPORTANCE_LOW;
+ NotificationChannel mChannel = new NotificationChannel(NH_TERM_CHANNEL_ID, name, importance);
+ mChannel.setDescription(description);
+ // Register the channel with the system; you can't change the importance
+ // or other notification behaviors after this
+ notificationManager = (NotificationManager) getSystemService(
+ NOTIFICATION_SERVICE);
+ if (notificationManager != null) {
+ notificationManager.createNotificationChannel(mChannel);
+ }
+ }
// Building the notification
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, NH_TERM_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_service_notification_icon) // notification icon
.setContentTitle(getText(R.string.application_terminal)) // main title of the notification
.setContentText(getText(R.string.service_notify_text)); // notification text
- //.setContentIntent(pendingIntent); // notification intent
+ //.setContentIntent(pendingIntent); // notification intent
Intent notifyIntent = new Intent(this, Term.class);
@@ -133,16 +144,19 @@ public void onCreate() {
mBuilder.setContentIntent(resultPendingIntent);
// mId allows you to update the notification later on.
- mNotificationManager.notify(notifyID, mBuilder.build());
+ //notificationManager.notify(notifyID, mBuilder.build());
+ startForeground(notifyID, mBuilder.build());
- //compat.startForeground(RUNNING_NOTIFICATION, notification);
Log.d(TermDebug.LOG_TAG, "TermService started");
}
@Override
public void onDestroy() {
+ // invoking notificationManager.cancel on Android < 8 causes a null pointer exception so we should check first
+ if (notificationManager == null)
+ notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Remove notification
- mNotificationManager.cancel(notifyID);
+ notificationManager.cancel(notifyID);
for (TermSession session : mTermSessions) {
/* Don't automatically remove from list of sessions -- we clear the
diff --git a/term/src/main/java/com/offsec/nhterm/compat/ServiceForegroundCompat.java b/term/src/main/java/com/offsec/nhterm/compat/ServiceForegroundCompat.java
index 28b4bd15f..af566a654 100644
--- a/term/src/main/java/com/offsec/nhterm/compat/ServiceForegroundCompat.java
+++ b/term/src/main/java/com/offsec/nhterm/compat/ServiceForegroundCompat.java
@@ -21,6 +21,7 @@
import java.lang.reflect.InvocationTargetException;
import android.app.Service;
import android.util.Log;
+
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
diff --git a/term/src/main/java/com/offsec/nhterm/util/TermSettings.java b/term/src/main/java/com/offsec/nhterm/util/TermSettings.java
index cbc7a1539..46173a2b0 100644
--- a/term/src/main/java/com/offsec/nhterm/util/TermSettings.java
+++ b/term/src/main/java/com/offsec/nhterm/util/TermSettings.java
@@ -18,8 +18,10 @@
import com.offsec.nhterm.R;
+import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.preference.PreferenceManager;
import android.view.KeyEvent;
/**
@@ -28,6 +30,7 @@
public class TermSettings {
private SharedPreferences mPrefs;
+ private String mChrootPath;
private int mStatusBar;
private boolean mFunctionBar;
private int mActionBarMode;
@@ -71,6 +74,7 @@ public class TermSettings {
private boolean mUseKeyboardShortcuts;
+ private static final String CHROOT_DIR = "chroot_dir";
private static final String STATUSBAR_KEY = "statusbar";
private static final String FUNCTIONBAR_KEY = "functionbar";
private static final String ACTIONBAR_KEY = "actionbar";
@@ -183,6 +187,8 @@ public TermSettings(Resources res, SharedPreferences prefs) {
}
private void readDefaultPrefs(Resources res) {
+
+ mChrootPath = res.getString(R.string.chroot_dir);
mStatusBar = Integer.parseInt(res.getString(R.string.pref_statusbar_default));
mFunctionBar = res.getBoolean(R.bool.pref_functionbar_default);
mActionBarMode = res.getInteger(R.integer.pref_actionbar_default);
@@ -223,6 +229,8 @@ private void readDefaultPrefs(Resources res) {
public void readPrefs(SharedPreferences prefs) {
mPrefs = prefs;
+
+ mChrootPath = readStringPref(CHROOT_DIR, mChrootPath);
mStatusBar = readIntPref(STATUSBAR_KEY, mStatusBar, 1);
mFunctionBar = readBooleanPref(FUNCTIONBAR_KEY, mFunctionBar);
mActionBarMode = readIntPref(ACTIONBAR_KEY, mActionBarMode, ACTION_BAR_MODE_MAX);
@@ -284,6 +292,13 @@ private boolean readBooleanPref(String key, boolean defaultValue) {
return mPrefs.getBoolean(key, defaultValue);
}
+ public String getChrootDir() { return mChrootPath; }
+
+ public void setChrootDir(Context context, String chrootDir) {
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+ mPrefs.edit().putString(CHROOT_DIR, chrootDir).apply();
+ mPrefs = null;
+ }
public boolean showStatusBar() {
return true;
}
diff --git a/term/src/main/jni/Application.mk b/term/src/main/jni/Application.mk
index 35ab62887..c29f1d41f 100644
--- a/term/src/main/jni/Application.mk
+++ b/term/src/main/jni/Application.mk
@@ -1,2 +1,2 @@
# Build for ARMv5TE, mips and x86 architectures.
-APP_ABI := armeabi mips x86 arm64-v8a armeabi-v7a
+APP_ABI := mips x86 arm64-v8a armeabi-v7a
diff --git a/term/src/main/res/layout/menu_chroot_path.xml b/term/src/main/res/layout/menu_chroot_path.xml
new file mode 100644
index 000000000..b99aa8dab
--- /dev/null
+++ b/term/src/main/res/layout/menu_chroot_path.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/term/src/main/res/menu/main.xml b/term/src/main/res/menu/main.xml
index 166245a9e..29dc8be1a 100644
--- a/term/src/main/res/menu/main.xml
+++ b/term/src/main/res/menu/main.xml
@@ -16,6 +16,8 @@
-->